]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #68297 - Aaron1011:fix/new-const-prop-bounds, r=oli-obk
authorYuki Okushi <huyuumi.dev@gmail.com>
Mon, 20 Jan 2020 22:32:44 +0000 (07:32 +0900)
committerGitHub <noreply@github.com>
Mon, 20 Jan 2020 22:32:44 +0000 (07:32 +0900)
 Filter and test predicates using `normalize_and_test_predicates` for const-prop

Fixes #68264

Previously, I attempted to use
`substitute_normalize_and_test_predicates` to detect unsatisfiable
bounds. Unfortunately, since const-prop runs in a generic environment
(we don't have any of the function's generic parameters substituted),
this could lead to cycle errors when attempting to normalize predicates.

This check is replaced with a more precise check. We now only call
`normalize_and_test_predicates` on predicates that have the possibility
of being proved unsatisfiable - that is, predicates that don't depend
on anything local to the function (e.g. generic parameters). This
ensures that we don't hit cycle errors when we normalize said
predicates, while still ensuring that we detect unsatisfiable
predicates.

I haven't been able to come up with a minimization of the Diesel issue - however, I've verified that it compiles successfully.

542 files changed:
.gitmodules
Cargo.lock
LICENSE-APACHE
src/ci/docker/dist-various-1/Dockerfile
src/ci/docker/dist-various-1/build-riscv-toolchain.sh [new file with mode: 0755]
src/ci/docker/dist-various-1/crosstool-ng.sh [new file with mode: 0755]
src/ci/docker/dist-various-1/riscv64-unknown-linux-gnu.config [new file with mode: 0644]
src/doc/rustc-guide
src/doc/unstable-book/src/language-features/slice-patterns.md [deleted file]
src/liballoc/benches/string.rs
src/liballoc/tests/btree/map.rs
src/libarena/lib.rs
src/libcore/any.rs
src/libcore/cell.rs
src/libcore/fmt/builders.rs
src/libcore/fmt/mod.rs
src/libcore/fmt/rt/v1.rs
src/libcore/iter/sources.rs
src/libcore/lib.rs
src/libcore/ptr/mod.rs
src/libcore/str/lossy.rs
src/libcore/str/mod.rs
src/libcore/str/pattern.rs
src/libcore/sync/atomic.rs
src/libcore/tests/fmt/builders.rs
src/libcore/tests/lib.rs
src/librustc/Cargo.toml
src/librustc/arena.rs
src/librustc/benches/lib.rs
src/librustc/hir/check_attr.rs
src/librustc/hir/map/mod.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/error_reporting/need_type_info.rs
src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
src/librustc/infer/error_reporting/note.rs
src/librustc/infer/lexical_region_resolve/mod.rs
src/librustc/infer/opaque_types/mod.rs
src/librustc/lib.rs
src/librustc/middle/exported_symbols.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/weak_lang_items.rs
src/librustc/mir/interpret/error.rs
src/librustc/mir/interpret/mod.rs
src/librustc/query/mod.rs
src/librustc/traits/error_reporting.rs [deleted file]
src/librustc/traits/error_reporting/mod.rs [new file with mode: 0644]
src/librustc/traits/error_reporting/on_unimplemented.rs [new file with mode: 0644]
src/librustc/traits/error_reporting/suggestions.rs [new file with mode: 0644]
src/librustc/traits/mod.rs
src/librustc/traits/on_unimplemented.rs
src/librustc/traits/query/dropck_outlives.rs
src/librustc/traits/select.rs
src/librustc/traits/specialize/mod.rs
src/librustc/traits/specialize/specialization_graph.rs
src/librustc/traits/util.rs
src/librustc/traits/wf.rs
src/librustc/ty/context.rs
src/librustc/ty/error.rs
src/librustc/ty/mod.rs
src/librustc/ty/query/plumbing.rs
src/librustc_ast_lowering/Cargo.toml
src/librustc_ast_lowering/expr.rs
src/librustc_ast_lowering/item.rs
src/librustc_ast_lowering/lib.rs
src/librustc_ast_lowering/path.rs
src/librustc_ast_passes/Cargo.toml
src/librustc_ast_passes/ast_validation.rs
src/librustc_ast_passes/feature_gate.rs
src/librustc_ast_passes/lib.rs
src/librustc_builtin_macros/Cargo.toml
src/librustc_builtin_macros/asm.rs
src/librustc_builtin_macros/deriving/default.rs
src/librustc_builtin_macros/deriving/generic/mod.rs
src/librustc_builtin_macros/deriving/mod.rs
src/librustc_builtin_macros/format.rs
src/librustc_codegen_ssa/Cargo.toml
src/librustc_codegen_ssa/back/linker.rs
src/librustc_codegen_ssa/back/symbol_export.rs
src/librustc_codegen_ssa/back/write.rs
src/librustc_codegen_ssa/common.rs
src/librustc_codegen_ssa/lib.rs
src/librustc_codegen_ssa/mir/statement.rs
src/librustc_codegen_utils/symbol_names.rs
src/librustc_data_structures/profiling.rs
src/librustc_data_structures/sharded.rs
src/librustc_error_codes/error_codes.rs
src/librustc_error_codes/error_codes/E0195.md
src/librustc_error_codes/error_codes/E0197.md
src/librustc_error_codes/error_codes/E0198.md
src/librustc_error_codes/error_codes/E0199.md
src/librustc_error_codes/error_codes/E0200.md
src/librustc_error_codes/error_codes/E0201.md
src/librustc_error_codes/error_codes/E0204.md
src/librustc_error_codes/error_codes/E0527.md
src/librustc_error_codes/error_codes/E0528.md
src/librustc_error_codes/error_codes/E0730.md
src/librustc_error_codes/error_codes/E0746.md [new file with mode: 0644]
src/librustc_error_codes/lib.rs
src/librustc_errors/annotate_snippet_emitter_writer.rs
src/librustc_errors/diagnostic_builder.rs
src/librustc_errors/emitter.rs
src/librustc_errors/lib.rs
src/librustc_feature/accepted.rs
src/librustc_feature/active.rs
src/librustc_hir/hir.rs
src/librustc_hir/intravisit.rs
src/librustc_hir/print.rs
src/librustc_incremental/persist/dirty_clean.rs
src/librustc_incremental/persist/save.rs
src/librustc_interface/passes.rs
src/librustc_interface/queries.rs
src/librustc_lint/Cargo.toml
src/librustc_lint/builtin.rs
src/librustc_lint/context.rs
src/librustc_lint/internal.rs
src/librustc_lint/levels.rs
src/librustc_lint/nonstandard_style.rs
src/librustc_metadata/Cargo.toml
src/librustc_metadata/creader.rs
src/librustc_metadata/lib.rs
src/librustc_metadata/locator.rs
src/librustc_metadata/native_libs.rs
src/librustc_metadata/rmeta/decoder.rs
src/librustc_metadata/rmeta/encoder.rs
src/librustc_mir/Cargo.toml
src/librustc_mir/borrow_check/borrow_set.rs
src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
src/librustc_mir/borrow_check/diagnostics/mod.rs
src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs
src/librustc_mir/borrow_check/diagnostics/region_errors.rs
src/librustc_mir/borrow_check/diagnostics/region_name.rs
src/librustc_mir/borrow_check/diagnostics/var_name.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/region_infer/mod.rs
src/librustc_mir/borrow_check/region_infer/values.rs
src/librustc_mir/borrow_check/type_check/mod.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/validity.rs
src/librustc_mir/lib.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/transform/check_consts/ops.rs
src/librustc_mir/transform/check_consts/validation.rs
src/librustc_mir/transform/check_unsafety.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_mir/transform/qualify_min_const_fn.rs
src/librustc_mir/util/borrowck_errors.rs
src/librustc_mir_build/Cargo.toml
src/librustc_mir_build/build/mod.rs
src/librustc_mir_build/hair/cx/expr.rs
src/librustc_mir_build/hair/pattern/check_match.rs
src/librustc_mir_build/hair/pattern/mod.rs
src/librustc_mir_build/lib.rs
src/librustc_parse/Cargo.toml
src/librustc_parse/config.rs
src/librustc_parse/lib.rs
src/librustc_parse/parser/diagnostics.rs
src/librustc_parse/parser/item.rs
src/librustc_parse/parser/mod.rs
src/librustc_parse/parser/pat.rs
src/librustc_parse/parser/ty.rs
src/librustc_passes/Cargo.toml
src/librustc_passes/check_const.rs
src/librustc_passes/dead.rs
src/librustc_passes/entry.rs
src/librustc_passes/intrinsicck.rs
src/librustc_passes/lib.rs
src/librustc_passes/lib_features.rs
src/librustc_passes/loops.rs
src/librustc_passes/reachable.rs
src/librustc_passes/stability.rs
src/librustc_plugin_impl/Cargo.toml
src/librustc_plugin_impl/load.rs
src/librustc_privacy/Cargo.toml
src/librustc_privacy/lib.rs
src/librustc_resolve/Cargo.toml
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/def_collector.rs
src/librustc_resolve/diagnostics.rs
src/librustc_resolve/imports.rs
src/librustc_resolve/late.rs
src/librustc_resolve/late/diagnostics.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/lifetimes.rs
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/lib.rs
src/librustc_save_analysis/sig.rs
src/librustc_session/Cargo.toml
src/librustc_session/options.rs
src/librustc_session/parse.rs
src/librustc_span/source_map.rs
src/librustc_target/lib.rs
src/librustc_traits/chalk_context/mod.rs
src/librustc_traits/lowering/environment.rs
src/librustc_ty/lib.rs
src/librustc_ty/ty.rs
src/librustc_typeck/Cargo.toml
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/autoderef.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/expr.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/op.rs
src/librustc_typeck/check/pat.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/coherence/builtin.rs
src/librustc_typeck/coherence/inherent_impls.rs
src/librustc_typeck/coherence/inherent_impls_overlap.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/orphan.rs
src/librustc_typeck/coherence/unsafety.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/impl_wf_check.rs
src/librustc_typeck/lib.rs
src/librustc_typeck/outlives/test.rs
src/librustc_typeck/structured_errors.rs
src/librustc_typeck/variance/test.rs
src/librustdoc/clean/auto_trait.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/html/highlight.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/render.rs
src/librustdoc/html/render/cache.rs
src/librustdoc/lib.rs
src/librustdoc/passes/check_code_block_syntax.rs
src/librustdoc/test.rs
src/librustdoc/visit_ast.rs
src/libstd/lib.rs
src/libstd/time.rs
src/libsyntax/Cargo.toml
src/libsyntax/ast.rs
src/libsyntax/attr/builtin.rs
src/libsyntax/lib.rs
src/libsyntax/mut_visit.rs
src/libsyntax/print/pprust.rs
src/libsyntax/visit.rs
src/libtest/lib.rs
src/llvm-project
src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs
src/test/codegen-units/item-collection/generic-drop-glue.rs
src/test/codegen-units/item-collection/instantiation-through-vtable.rs
src/test/codegen-units/item-collection/non-generic-drop-glue.rs
src/test/codegen-units/item-collection/transitive-drop-glue.rs
src/test/codegen-units/item-collection/tuple-drop-glue.rs
src/test/codegen-units/item-collection/unsizing.rs
src/test/codegen-units/partitioning/extern-drop-glue.rs
src/test/codegen-units/partitioning/local-drop-glue.rs
src/test/codegen-units/partitioning/vtable-through-const.rs
src/test/codegen/drop.rs
src/test/mir-opt/const_prop/ref_deref_project.rs
src/test/mir-opt/retag.rs
src/test/mir-opt/slice-drop-shim.rs
src/test/mir-opt/uniform_array_move_out.rs
src/test/mir-opt/unusual-item-types.rs
src/test/run-make-fulldeps/issue64319/Makefile [new file with mode: 0644]
src/test/run-make-fulldeps/issue64319/bar.rs [new file with mode: 0644]
src/test/run-make-fulldeps/issue64319/foo.rs [new file with mode: 0644]
src/test/run-make-fulldeps/sanitizer-address/Makefile [deleted file]
src/test/run-make-fulldeps/sanitizer-address/overflow.rs [deleted file]
src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile [deleted file]
src/test/run-make-fulldeps/sanitizer-invalid-target/hello.rs [deleted file]
src/test/run-make-fulldeps/sanitizer-leak/Makefile [deleted file]
src/test/run-make-fulldeps/sanitizer-leak/leak.rs [deleted file]
src/test/run-make-fulldeps/sanitizer-memory/Makefile [deleted file]
src/test/run-make-fulldeps/sanitizer-memory/maybeuninit.rs [deleted file]
src/test/run-make-fulldeps/sanitizer-memory/uninit.rs [deleted file]
src/test/run-make-fulldeps/share-generics-dylib/Makefile [new file with mode: 0644]
src/test/run-make-fulldeps/share-generics-dylib/instance_provider_a.rs [new file with mode: 0644]
src/test/run-make-fulldeps/share-generics-dylib/instance_provider_b.rs [new file with mode: 0644]
src/test/run-make-fulldeps/share-generics-dylib/instance_user_a_rlib.rs [new file with mode: 0644]
src/test/run-make-fulldeps/share-generics-dylib/instance_user_b_rlib.rs [new file with mode: 0644]
src/test/run-make-fulldeps/share-generics-dylib/instance_user_dylib.rs [new file with mode: 0644]
src/test/run-make-fulldeps/share-generics-dylib/linked_leaf.rs [new file with mode: 0644]
src/test/rustdoc-ui/invalid-syntax.rs
src/test/rustdoc-ui/invalid-syntax.stderr
src/test/rustdoc-ui/test-compile-fail1.rs [new file with mode: 0644]
src/test/rustdoc-ui/test-compile-fail1.stderr [new file with mode: 0644]
src/test/rustdoc-ui/test-compile-fail2.rs [new file with mode: 0644]
src/test/rustdoc-ui/test-compile-fail2.stderr [new file with mode: 0644]
src/test/rustdoc-ui/test-compile-fail3.rs [new file with mode: 0644]
src/test/rustdoc-ui/test-compile-fail3.stderr [new file with mode: 0644]
src/test/rustdoc-ui/test-no_std.rs [new file with mode: 0644]
src/test/rustdoc-ui/test-no_std.stdout [new file with mode: 0644]
src/test/rustdoc/bad-codeblock-syntax.rs
src/test/rustdoc/deref-typedef.rs [new file with mode: 0644]
src/test/rustdoc/remove-url-from-headings.rs [new file with mode: 0644]
src/test/ui/array-slice-vec/slice-pat-type-mismatches.rs [new file with mode: 0644]
src/test/ui/array-slice-vec/slice-pat-type-mismatches.stderr [new file with mode: 0644]
src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.rs [new file with mode: 0644]
src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.stderr [new file with mode: 0644]
src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs
src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs
src/test/ui/array-slice-vec/subslice-patterns-pass.rs
src/test/ui/array-slice-vec/vec-matching-fixed.rs
src/test/ui/array-slice-vec/vec-matching-fold.rs
src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs
src/test/ui/array-slice-vec/vec-matching.rs
src/test/ui/array-slice-vec/vec-tail-matching.rs
src/test/ui/async-await/async-fn-nonsend.rs
src/test/ui/async-await/async-fn-nonsend.stderr
src/test/ui/async-await/issue-64130-4-async-move.stderr
src/test/ui/binding/empty-types-in-patterns.rs
src/test/ui/binding/irrefutable-slice-patterns.rs
src/test/ui/binding/match-byte-array-patterns.rs
src/test/ui/binding/match-vec-alternatives.rs
src/test/ui/binding/zero_sized_subslice_match.rs
src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs
src/test/ui/borrowck/borrowck-closures-slice-patterns.rs
src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr
src/test/ui/borrowck/borrowck-describe-lvalue.rs
src/test/ui/borrowck/borrowck-describe-lvalue.stderr
src/test/ui/borrowck/borrowck-move-out-from-array-match.rs
src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr
src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs
src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr
src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs
src/test/ui/borrowck/borrowck-move-out-from-array-use-match.rs
src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr
src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs
src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr
src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs
src/test/ui/borrowck/borrowck-move-out-from-array-use.rs
src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr
src/test/ui/borrowck/borrowck-move-out-from-array.rs
src/test/ui/borrowck/borrowck-move-out-from-array.stderr
src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs
src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr
src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs
src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs
src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr
src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs
src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs
src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs
src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr
src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs
src/test/ui/borrowck/borrowck-vec-pattern-element-loan.stderr
src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs
src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr
src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs
src/test/ui/borrowck/borrowck-vec-pattern-move-tail.stderr
src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs
src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr
src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs
src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr
src/test/ui/c-variadic/variadic-ffi-4.nll.stderr
src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr
src/test/ui/const-generics/array-impls/alloc-traits-no-impls-length-33.stderr
src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr
src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs [new file with mode: 0644]
src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.stderr [new file with mode: 0644]
src/test/ui/consts/array-literal-index-oob.rs
src/test/ui/consts/array-literal-index-oob.stderr
src/test/ui/consts/associated_const_generic.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/promoted_errors.rs
src/test/ui/consts/const-eval/promoted_errors.stderr
src/test/ui/consts/const-eval/promoted_errors2.rs
src/test/ui/consts/const-eval/promoted_errors2.stderr
src/test/ui/consts/const_prop_slice_pat_ice.rs
src/test/ui/consts/issue-67529.rs [new file with mode: 0644]
src/test/ui/consts/issue-67640.rs [new file with mode: 0644]
src/test/ui/consts/issue-67641.rs [new file with mode: 0644]
src/test/ui/consts/issue-67862.rs [new file with mode: 0644]
src/test/ui/consts/miri_unleashed/drop.stderr
src/test/ui/consts/miri_unleashed/mutable_const2.stderr
src/test/ui/destructure-trait-ref.rs
src/test/ui/destructure-trait-ref.stderr
src/test/ui/drop/dynamic-drop-async.rs
src/test/ui/drop/dynamic-drop.rs
src/test/ui/dst/dst-bad-assign-3.rs
src/test/ui/dst/dst-bad-assign-3.stderr
src/test/ui/dst/dst-bad-assign.rs
src/test/ui/dst/dst-bad-assign.stderr
src/test/ui/error-codes/E0528.rs
src/test/ui/error-codes/E0528.stderr
src/test/ui/error-codes/E0603.stderr
src/test/ui/error-codes/E0746.fixed [new file with mode: 0644]
src/test/ui/error-codes/E0746.rs [new file with mode: 0644]
src/test/ui/error-codes/E0746.stderr [new file with mode: 0644]
src/test/ui/error-festival.stderr
src/test/ui/export-import.stderr
src/test/ui/export-tag-variant.stderr
src/test/ui/export.stderr
src/test/ui/extern/extern-crate-visibility.rs
src/test/ui/extern/extern-crate-visibility.stderr
src/test/ui/feature-gates/feature-gate-slice-patterns.rs [deleted file]
src/test/ui/feature-gates/feature-gate-slice-patterns.stderr [deleted file]
src/test/ui/generic-associated-types/impl_bounds.stderr
src/test/ui/hygiene/privacy.stderr
src/test/ui/ignore-all-the-things.rs
src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs [new file with mode: 0644]
src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr [new file with mode: 0644]
src/test/ui/impl-trait/equality.stderr
src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs [new file with mode: 0644]
src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr [new file with mode: 0644]
src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs [new file with mode: 0644]
src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr [new file with mode: 0644]
src/test/ui/import.stderr
src/test/ui/imports/issue-55884-2.rs
src/test/ui/imports/issue-55884-2.stderr
src/test/ui/imports/reexports.stderr
src/test/ui/imports/unresolved-imports-used.stderr
src/test/ui/issues/issue-10545.stderr
src/test/ui/issues/issue-11593.stderr
src/test/ui/issues/issue-11680.stderr
src/test/ui/issues/issue-12369.rs
src/test/ui/issues/issue-12369.stderr
src/test/ui/issues/issue-12567.rs
src/test/ui/issues/issue-12567.stderr
src/test/ui/issues/issue-13407.stderr
src/test/ui/issues/issue-13641.stderr
src/test/ui/issues/issue-15080.rs
src/test/ui/issues/issue-15104.rs
src/test/ui/issues/issue-16725.stderr
src/test/ui/issues/issue-17718-const-privacy.stderr
src/test/ui/issues/issue-17877.rs
src/test/ui/issues/issue-23311.rs
src/test/ui/issues/issue-26548.rs [deleted file]
src/test/ui/issues/issue-26548.stderr [deleted file]
src/test/ui/issues/issue-26619.rs
src/test/ui/issues/issue-26619.stderr
src/test/ui/issues/issue-28388-2.stderr
src/test/ui/issues/issue-29161.stderr
src/test/ui/issues/issue-37598.rs
src/test/ui/issues/issue-38591.rs [deleted file]
src/test/ui/issues/issue-38857.rs
src/test/ui/issues/issue-38857.stderr
src/test/ui/issues/issue-3993.stderr
src/test/ui/issues/issue-58344.stderr
src/test/ui/issues/issue-5883.stderr
src/test/ui/issues/issue-7784.rs
src/test/ui/lifetimes/lifetime-elision-return-type-trait.stderr
src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs [new file with mode: 0644]
src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr [new file with mode: 0644]
src/test/ui/macros/macro-local-data-key-priv.stderr
src/test/ui/marker_trait_attr/issue-61651-type-mismatch.rs [new file with mode: 0644]
src/test/ui/match/match-vec-mismatch.rs [deleted file]
src/test/ui/match/match-vec-mismatch.stderr [deleted file]
src/test/ui/moves/move-out-of-array-ref.rs
src/test/ui/moves/move-out-of-array-ref.stderr
src/test/ui/never_type/feature-gate-never_type_fallback.stderr
src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs
src/test/ui/or-patterns/exhaustiveness-pass.rs
src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs
src/test/ui/parser/macro/pub-item-macro.stderr
src/test/ui/parser/match-vec-invalid.rs [deleted file]
src/test/ui/parser/match-vec-invalid.stderr [deleted file]
src/test/ui/parser/pat-lt-bracket-6.rs
src/test/ui/parser/pat-lt-bracket-6.stderr
src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs
src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr
src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs
src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs
src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
src/test/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs
src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs
src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs
src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs
src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
src/test/ui/pattern/issue-53820-slice-pattern-large-array.rs [deleted file]
src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs [deleted file]
src/test/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs [new file with mode: 0644]
src/test/ui/pattern/usefulness/match-byte-array-patterns.rs
src/test/ui/pattern/usefulness/match-byte-array-patterns.stderr
src/test/ui/pattern/usefulness/match-slice-patterns.rs
src/test/ui/pattern/usefulness/match-slice-patterns.stderr
src/test/ui/pattern/usefulness/match-vec-unreachable.rs
src/test/ui/pattern/usefulness/match-vec-unreachable.stderr
src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs
src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr
src/test/ui/pattern/usefulness/non-exhaustive-match.rs
src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs
src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr
src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs
src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr
src/test/ui/pattern/usefulness/slice-patterns-irrefutable.rs
src/test/ui/pattern/usefulness/slice-patterns-reachability.rs
src/test/ui/pattern/usefulness/slice-patterns-reachability.stderr
src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
src/test/ui/privacy/decl-macro.stderr
src/test/ui/privacy/privacy-in-paths.stderr
src/test/ui/privacy/privacy-ns2.stderr
src/test/ui/privacy/privacy-ufcs.stderr
src/test/ui/privacy/privacy1.stderr
src/test/ui/privacy/privacy2.stderr
src/test/ui/privacy/privacy4.stderr
src/test/ui/privacy/privacy5.stderr
src/test/ui/privacy/private-item-simple.stderr
src/test/ui/privacy/restricted/test.stderr
src/test/ui/proc-macro/disappearing-resolution.rs
src/test/ui/proc-macro/disappearing-resolution.stderr
src/test/ui/reachable/unreachable-variant.stderr
src/test/ui/recursion/issue-26548-recursion-via-normalize.rs [new file with mode: 0644]
src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr [new file with mode: 0644]
src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs [new file with mode: 0644]
src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr [new file with mode: 0644]
src/test/ui/repr/repr-packed-contains-align.rs
src/test/ui/repr/repr-packed-contains-align.stderr
src/test/ui/resolve/privacy-enum-ctor.stderr
src/test/ui/resolve/privacy-struct-ctor.stderr
src/test/ui/rfc-2005-default-binding-mode/slice.rs
src/test/ui/rfc-2005-default-binding-mode/slice.stderr
src/test/ui/rfc-2008-non-exhaustive/struct.stderr
src/test/ui/rfc-2008-non-exhaustive/variant.stderr
src/test/ui/rfcs/rfc-2005-default-binding-mode/slice.rs
src/test/ui/sanitizer-address.rs [new file with mode: 0644]
src/test/ui/sanitizer-leak.rs [new file with mode: 0644]
src/test/ui/sanitizer-memory.rs [new file with mode: 0644]
src/test/ui/sanitizer-unsupported-target.rs [new file with mode: 0644]
src/test/ui/sanitizer-unsupported-target.stderr [new file with mode: 0644]
src/test/ui/shadowed/shadowed-use-visibility.rs
src/test/ui/shadowed/shadowed-use-visibility.stderr
src/test/ui/stability-in-private-module.rs
src/test/ui/stability-in-private-module.stderr
src/test/ui/static/static-priv-by-default2.stderr
src/test/ui/structs/struct-variant-privacy-xc.stderr
src/test/ui/structs/struct-variant-privacy.stderr
src/test/ui/test-panic-abort.rs
src/test/ui/test-panic-abort.run.stdout
src/test/ui/threads-sendsync/sync-send-iterators-in-libcore.rs
src/test/ui/trailing-comma.rs
src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr
src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr
src/test/ui/uninhabited/uninhabited-patterns.rs
src/test/ui/use/use-from-trait-xc.stderr
src/test/ui/use/use-mod/use-mod-3.stderr
src/test/ui/xcrate/xcrate-private-by-default.stderr
src/tools/clippy

index 31db0772cfb6b3f789fde5073b823f3c74908998..62cbbdd9a3a0663c13f2df49375eb225ff8079c0 100644 (file)
@@ -40,7 +40,7 @@
 [submodule "src/llvm-project"]
        path = src/llvm-project
        url = https://github.com/rust-lang/llvm-project.git
-       branch = rustc/9.0-2019-09-19
+       branch = rustc/9.0-2019-12-19
 [submodule "src/doc/embedded-book"]
        path = src/doc/embedded-book
        url = https://github.com/rust-embedded/book.git
index f33d7ff12febff8ddad98478bc31215fb2e5f310..48bc269ebb65414f51c165ce1feb4aac1d6f5e75 100644 (file)
@@ -3092,7 +3092,6 @@ dependencies = [
  "rustc-rayon-core",
  "rustc_apfloat",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_feature",
  "rustc_hir",
@@ -3358,7 +3357,6 @@ dependencies = [
  "log",
  "rustc",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_hir",
  "rustc_index",
@@ -3375,7 +3373,6 @@ version = "0.0.0"
 dependencies = [
  "log",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_feature",
  "rustc_parse",
@@ -3391,7 +3388,6 @@ dependencies = [
  "fmt_macros",
  "log",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_expand",
  "rustc_feature",
@@ -3445,7 +3441,6 @@ dependencies = [
  "rustc_apfloat",
  "rustc_codegen_utils",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_fs_util",
  "rustc_hir",
@@ -3675,7 +3670,6 @@ dependencies = [
  "log",
  "rustc",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_feature",
  "rustc_hir",
@@ -3716,7 +3710,6 @@ dependencies = [
  "memmap",
  "rustc",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_expand",
  "rustc_hir",
@@ -3744,7 +3737,6 @@ dependencies = [
  "rustc",
  "rustc_apfloat",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_hir",
  "rustc_index",
@@ -3767,7 +3759,6 @@ dependencies = [
  "rustc",
  "rustc_apfloat",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_hir",
  "rustc_index",
@@ -3786,7 +3777,6 @@ dependencies = [
  "bitflags",
  "log",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_feature",
  "rustc_lexer",
@@ -3804,7 +3794,6 @@ dependencies = [
  "log",
  "rustc",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_feature",
  "rustc_hir",
@@ -3820,7 +3809,6 @@ name = "rustc_plugin_impl"
 version = "0.0.0"
 dependencies = [
  "rustc",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_hir",
  "rustc_lint",
@@ -3836,7 +3824,6 @@ dependencies = [
  "log",
  "rustc",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_hir",
  "rustc_span",
@@ -3854,7 +3841,6 @@ dependencies = [
  "rustc",
  "rustc_ast_lowering",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_expand",
  "rustc_feature",
@@ -3890,7 +3876,6 @@ dependencies = [
  "log",
  "num_cpus",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_feature",
  "rustc_fs_util",
@@ -3973,7 +3958,6 @@ dependencies = [
  "log",
  "rustc",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_hir",
  "rustc_index",
@@ -4493,7 +4477,6 @@ version = "0.0.0"
 dependencies = [
  "log",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_feature",
  "rustc_index",
index 16fe87b06e802f094b3fbb0894b137bca2b16ef1..1b5ec8b78e237b5c3b3d812a7c0a6589d0f7161d 100644 (file)
@@ -174,28 +174,3 @@ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
    of your accepting any such warranty or additional liability.
 
 END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
-   To apply the Apache License to your work, attach the following
-   boilerplate notice, with the fields enclosed by brackets "[]"
-   replaced with your own identifying information. (Don't include
-   the brackets!)  The text should be enclosed in the appropriate
-   comment syntax for the file format. We also recommend that a
-   file or class name and description of purpose be included on the
-   same "printed page" as the copyright notice for easier
-   identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
index 6bbf0928783117f58e96e3a7df472b80be27ccd0..546e73e33d7f38770475a5ac7a6294e84b70c402 100644 (file)
@@ -2,11 +2,24 @@ FROM ubuntu:16.04
 
 RUN apt-get update && apt-get install -y --no-install-recommends \
   g++ \
+  automake \
+  bison \
+  bzip2 \
+  flex \
+  help2man \
+  libtool-bin \
+  texinfo \
+  unzip \
+  wget \
+  xz-utils \
+  libncurses-dev \
+  gawk \
   make \
   file \
   curl \
   ca-certificates \
   python2.7 \
+  python3 \
   git \
   cmake \
   sudo \
@@ -35,6 +48,18 @@ RUN add-apt-repository ppa:team-gcc-arm-embedded/ppa && \
     apt-get update && \
     apt-get install -y --no-install-recommends gcc-arm-embedded
 
+COPY scripts/rustbuild-setup.sh dist-various-1/build-riscv-toolchain.sh dist-various-1/riscv64-unknown-linux-gnu.config dist-various-1/crosstool-ng.sh /build/
+RUN ./crosstool-ng.sh
+
+# Crosstool-ng will refuse to build as root
+RUN sh ./rustbuild-setup.sh
+USER rustbuild
+
+RUN ./build-riscv-toolchain.sh
+
+USER root
+ENV PATH=/x-tools/riscv64-unknown-linux-gnu/bin:$PATH
+
 COPY dist-various-1/build-rumprun.sh /build
 RUN ./build-rumprun.sh
 
@@ -129,6 +154,7 @@ ENV TARGETS=$TARGETS,riscv32imc-unknown-none-elf
 ENV TARGETS=$TARGETS,riscv32imac-unknown-none-elf
 ENV TARGETS=$TARGETS,riscv64imac-unknown-none-elf
 ENV TARGETS=$TARGETS,riscv64gc-unknown-none-elf
+ENV TARGETS=$TARGETS,riscv64gc-unknown-linux-gnu
 ENV TARGETS=$TARGETS,armebv7r-none-eabi
 ENV TARGETS=$TARGETS,armebv7r-none-eabihf
 ENV TARGETS=$TARGETS,armv7r-none-eabi
@@ -147,6 +173,9 @@ ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
     CC_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc \
     AR_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-ar \
     CXX_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-g++ \
+    CC_riscv64gc_unknown_linux_gnu=riscv64-unknown-linux-gnu-gcc \
+    AR_riscv64gc_unknown_linux_gnu=riscv64-unknown-linux-gnu-ar \
+    CXX_riscv64gc_unknown_linux_gnu=riscv64-unknown-linux-gnu-g++ \
     CC_riscv32i_unknown_none_elf=false \
     CC_riscv32imc_unknown_none_elf=false \
     CC_riscv32imac_unknown_none_elf=false \
diff --git a/src/ci/docker/dist-various-1/build-riscv-toolchain.sh b/src/ci/docker/dist-various-1/build-riscv-toolchain.sh
new file mode 100755 (executable)
index 0000000..9cb5700
--- /dev/null
@@ -0,0 +1,27 @@
+#!/usr/bin/env bash
+
+set -ex
+
+hide_output() {
+  set +x
+  on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/build.log
+exit 1
+"
+  trap "$on_err" ERR
+  bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+  PING_LOOP_PID=$!
+  $@ &> /tmp/build.log
+  rm /tmp/build.log
+  trap - ERR
+  kill $PING_LOOP_PID
+  set -x
+}
+
+mkdir -p /tmp/build-riscv
+cp riscv64-unknown-linux-gnu.config /tmp/build-riscv/.config
+cd /tmp/build-riscv
+hide_output ct-ng build
+cd ..
+rm -rf build-riscv
diff --git a/src/ci/docker/dist-various-1/crosstool-ng.sh b/src/ci/docker/dist-various-1/crosstool-ng.sh
new file mode 100755 (executable)
index 0000000..b01fdd0
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+set -ex
+
+# Mirrored from https://github.com/crosstool-ng/crosstool-ng/archive/crosstool-ng-1.24.0.tar.gz
+url="https://ci-mirrors.rust-lang.org/rustc/crosstool-ng-1.24.0.tar.gz"
+curl -Lf $url | tar xzf -
+cd crosstool-ng-crosstool-ng-1.24.0
+./bootstrap
+./configure --prefix=/usr/local
+make -j$(nproc)
+make install
+cd ..
+rm -rf crosstool-ng-crosstool-ng-1.24.0
diff --git a/src/ci/docker/dist-various-1/riscv64-unknown-linux-gnu.config b/src/ci/docker/dist-various-1/riscv64-unknown-linux-gnu.config
new file mode 100644 (file)
index 0000000..dd06065
--- /dev/null
@@ -0,0 +1,908 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# crosstool-NG  Configuration
+#
+CT_CONFIGURE_has_static_link=y
+CT_CONFIGURE_has_cxx11=y
+CT_CONFIGURE_has_wget=y
+CT_CONFIGURE_has_curl=y
+CT_CONFIGURE_has_make_3_81_or_newer=y
+CT_CONFIGURE_has_make_4_0_or_newer=y
+CT_CONFIGURE_has_libtool_2_4_or_newer=y
+CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
+CT_CONFIGURE_has_autoconf_2_65_or_newer=y
+CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
+CT_CONFIGURE_has_automake_1_15_or_newer=y
+CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
+CT_CONFIGURE_has_python_3_4_or_newer=y
+CT_CONFIGURE_has_bison_2_7_or_newer=y
+CT_CONFIGURE_has_python=y
+CT_CONFIGURE_has_dtc=y
+CT_CONFIGURE_has_svn=y
+CT_CONFIGURE_has_git=y
+CT_CONFIGURE_has_md5sum=y
+CT_CONFIGURE_has_sha1sum=y
+CT_CONFIGURE_has_sha256sum=y
+CT_CONFIGURE_has_sha512sum=y
+CT_CONFIGURE_has_install_with_strip_program=y
+CT_CONFIG_VERSION_CURRENT="3"
+CT_CONFIG_VERSION="3"
+CT_MODULES=y
+
+#
+# Paths and misc options
+#
+
+#
+# crosstool-NG behavior
+#
+# CT_OBSOLETE is not set
+CT_EXPERIMENTAL=y
+# CT_ALLOW_BUILD_AS_ROOT is not set
+# CT_DEBUG_CT is not set
+
+#
+# Paths
+#
+CT_LOCAL_TARBALLS_DIR="${HOME}/src"
+CT_SAVE_TARBALLS=y
+# CT_TARBALLS_BUILDROOT_LAYOUT is not set
+CT_WORK_DIR="${CT_TOP_DIR}/.build"
+CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_RM_RF_PREFIX_DIR=y
+CT_REMOVE_DOCS=y
+CT_INSTALL_LICENSES=y
+CT_PREFIX_DIR_RO=y
+CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
+# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
+
+#
+# Downloading
+#
+CT_DOWNLOAD_AGENT_WGET=y
+# CT_DOWNLOAD_AGENT_CURL is not set
+# CT_DOWNLOAD_AGENT_NONE is not set
+# CT_FORBID_DOWNLOAD is not set
+# CT_FORCE_DOWNLOAD is not set
+CT_CONNECT_TIMEOUT=10
+CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
+# CT_ONLY_DOWNLOAD is not set
+# CT_USE_MIRROR is not set
+CT_VERIFY_DOWNLOAD_DIGEST=y
+CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
+CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
+# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
+
+#
+# Extracting
+#
+# CT_FORCE_EXTRACT is not set
+CT_OVERRIDE_CONFIG_GUESS_SUB=y
+# CT_ONLY_EXTRACT is not set
+CT_PATCH_BUNDLED=y
+# CT_PATCH_LOCAL is not set
+# CT_PATCH_BUNDLED_LOCAL is not set
+# CT_PATCH_LOCAL_BUNDLED is not set
+# CT_PATCH_NONE is not set
+CT_PATCH_ORDER="bundled"
+
+#
+# Build behavior
+#
+CT_PARALLEL_JOBS=0
+CT_LOAD=""
+CT_USE_PIPES=y
+CT_EXTRA_CFLAGS_FOR_BUILD=""
+CT_EXTRA_LDFLAGS_FOR_BUILD=""
+CT_EXTRA_CFLAGS_FOR_HOST=""
+CT_EXTRA_LDFLAGS_FOR_HOST=""
+# CT_CONFIG_SHELL_SH is not set
+# CT_CONFIG_SHELL_ASH is not set
+CT_CONFIG_SHELL_BASH=y
+# CT_CONFIG_SHELL_CUSTOM is not set
+CT_CONFIG_SHELL="${bash}"
+
+#
+# Logging
+#
+# CT_LOG_ERROR is not set
+# CT_LOG_WARN is not set
+# CT_LOG_INFO is not set
+# CT_LOG_EXTRA is not set
+CT_LOG_ALL=y
+# CT_LOG_DEBUG is not set
+CT_LOG_LEVEL_MAX="ALL"
+# CT_LOG_SEE_TOOLS_WARN is not set
+CT_LOG_TO_FILE=y
+CT_LOG_FILE_COMPRESS=y
+
+#
+# Target options
+#
+# CT_ARCH_ALPHA is not set
+# CT_ARCH_ARC is not set
+# CT_ARCH_ARM is not set
+# CT_ARCH_AVR is not set
+# CT_ARCH_M68K is not set
+# CT_ARCH_MICROBLAZE is not set
+# CT_ARCH_MIPS is not set
+# CT_ARCH_MOXIE is not set
+# CT_ARCH_MSP430 is not set
+# CT_ARCH_NIOS2 is not set
+# CT_ARCH_POWERPC is not set
+CT_ARCH_RISCV=y
+# CT_ARCH_S390 is not set
+# CT_ARCH_SH is not set
+# CT_ARCH_SPARC is not set
+# CT_ARCH_X86 is not set
+# CT_ARCH_XTENSA is not set
+CT_ARCH="riscv"
+CT_ARCH_CHOICE_KSYM="RISCV"
+CT_ARCH_TUNE=""
+CT_ARCH_RISCV_SHOW=y
+
+#
+# Options for riscv
+#
+CT_ARCH_RISCV_PKG_KSYM=""
+CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
+CT_ARCH_SUFFIX=""
+# CT_OMIT_TARGET_VENDOR is not set
+
+#
+# Generic target options
+#
+# CT_MULTILIB is not set
+# CT_DEMULTILIB is not set
+CT_ARCH_SUPPORTS_BOTH_MMU=y
+CT_ARCH_USE_MMU=y
+CT_ARCH_SUPPORTS_32=y
+CT_ARCH_SUPPORTS_64=y
+CT_ARCH_DEFAULT_32=y
+CT_ARCH_BITNESS=64
+# CT_ARCH_32 is not set
+CT_ARCH_64=y
+
+#
+# Target optimisations
+#
+CT_ARCH_SUPPORTS_WITH_ARCH=y
+CT_ARCH_SUPPORTS_WITH_ABI=y
+CT_ARCH_SUPPORTS_WITH_TUNE=y
+CT_ARCH_ARCH="rv64gc"
+CT_ARCH_ABI=""
+CT_TARGET_CFLAGS=""
+CT_TARGET_LDFLAGS=""
+
+#
+# Toolchain options
+#
+
+#
+# General toolchain options
+#
+CT_FORCE_SYSROOT=y
+CT_USE_SYSROOT=y
+CT_SYSROOT_NAME="sysroot"
+CT_SYSROOT_DIR_PREFIX=""
+CT_WANTS_STATIC_LINK=y
+CT_WANTS_STATIC_LINK_CXX=y
+# CT_STATIC_TOOLCHAIN is not set
+CT_SHOW_CT_VERSION=y
+CT_TOOLCHAIN_PKGVERSION=""
+CT_TOOLCHAIN_BUGURL=""
+
+#
+# Tuple completion and aliasing
+#
+CT_TARGET_VENDOR="unknown"
+CT_TARGET_ALIAS_SED_EXPR=""
+CT_TARGET_ALIAS=""
+
+#
+# Toolchain type
+#
+# CT_NATIVE is not set
+CT_CROSS=y
+# CT_CROSS_NATIVE is not set
+# CT_CANADIAN is not set
+CT_TOOLCHAIN_TYPE="cross"
+
+#
+# Build system
+#
+CT_BUILD=""
+CT_BUILD_PREFIX=""
+CT_BUILD_SUFFIX=""
+
+#
+# Misc options
+#
+# CT_TOOLCHAIN_ENABLE_NLS is not set
+
+#
+# Operating System
+#
+CT_KERNEL_SUPPORTS_SHARED_LIBS=y
+# CT_KERNEL_BARE_METAL is not set
+CT_KERNEL_LINUX=y
+CT_KERNEL="linux"
+CT_KERNEL_CHOICE_KSYM="LINUX"
+CT_KERNEL_LINUX_SHOW=y
+
+#
+# Options for linux
+#
+CT_KERNEL_LINUX_PKG_KSYM="LINUX"
+CT_LINUX_DIR_NAME="linux"
+CT_LINUX_PKG_NAME="linux"
+CT_LINUX_SRC_RELEASE=y
+# CT_LINUX_SRC_DEVEL is not set
+# CT_LINUX_SRC_CUSTOM is not set
+CT_LINUX_PATCH_GLOBAL=y
+# CT_LINUX_PATCH_BUNDLED is not set
+# CT_LINUX_PATCH_LOCAL is not set
+# CT_LINUX_PATCH_BUNDLED_LOCAL is not set
+# CT_LINUX_PATCH_LOCAL_BUNDLED is not set
+# CT_LINUX_PATCH_NONE is not set
+CT_LINUX_PATCH_ORDER="global"
+CT_LINUX_V_4_20=y
+# CT_LINUX_V_4_19 is not set
+# CT_LINUX_V_4_18 is not set
+# CT_LINUX_V_4_17 is not set
+# CT_LINUX_V_4_16 is not set
+# CT_LINUX_V_4_15 is not set
+# CT_LINUX_V_4_14 is not set
+# CT_LINUX_V_4_13 is not set
+# CT_LINUX_V_4_12 is not set
+# CT_LINUX_V_4_11 is not set
+# CT_LINUX_V_4_10 is not set
+# CT_LINUX_V_4_9 is not set
+# CT_LINUX_V_4_4 is not set
+# CT_LINUX_V_4_1 is not set
+# CT_LINUX_V_3_16 is not set
+# CT_LINUX_V_3_13 is not set
+# CT_LINUX_V_3_12 is not set
+# CT_LINUX_V_3_10 is not set
+# CT_LINUX_V_3_4 is not set
+# CT_LINUX_V_3_2 is not set
+# CT_LINUX_NO_VERSIONS is not set
+CT_LINUX_VERSION="4.20.8"
+CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
+CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
+CT_LINUX_later_than_4_8=y
+CT_LINUX_4_8_or_later=y
+CT_LINUX_later_than_3_7=y
+CT_LINUX_3_7_or_later=y
+CT_LINUX_later_than_3_2=y
+CT_LINUX_3_2_or_later=y
+CT_LINUX_REQUIRE_3_2_or_later=y
+CT_KERNEL_LINUX_VERBOSITY_0=y
+# CT_KERNEL_LINUX_VERBOSITY_1 is not set
+# CT_KERNEL_LINUX_VERBOSITY_2 is not set
+CT_KERNEL_LINUX_VERBOSE_LEVEL=0
+CT_KERNEL_LINUX_INSTALL_CHECK=y
+CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
+
+#
+# Common kernel options
+#
+CT_SHARED_LIBS=y
+
+#
+# Binary utilities
+#
+CT_ARCH_BINFMT_ELF=y
+CT_BINUTILS_BINUTILS=y
+CT_BINUTILS="binutils"
+CT_BINUTILS_CHOICE_KSYM="BINUTILS"
+CT_BINUTILS_BINUTILS_SHOW=y
+
+#
+# Options for binutils
+#
+CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
+CT_BINUTILS_DIR_NAME="binutils"
+CT_BINUTILS_USE_GNU=y
+CT_BINUTILS_USE="BINUTILS"
+CT_BINUTILS_PKG_NAME="binutils"
+CT_BINUTILS_SRC_RELEASE=y
+# CT_BINUTILS_SRC_DEVEL is not set
+# CT_BINUTILS_SRC_CUSTOM is not set
+CT_BINUTILS_PATCH_GLOBAL=y
+# CT_BINUTILS_PATCH_BUNDLED is not set
+# CT_BINUTILS_PATCH_LOCAL is not set
+# CT_BINUTILS_PATCH_BUNDLED_LOCAL is not set
+# CT_BINUTILS_PATCH_LOCAL_BUNDLED is not set
+# CT_BINUTILS_PATCH_NONE is not set
+CT_BINUTILS_PATCH_ORDER="global"
+CT_BINUTILS_V_2_32=y
+# CT_BINUTILS_V_2_31 is not set
+# CT_BINUTILS_V_2_30 is not set
+# CT_BINUTILS_V_2_29 is not set
+# CT_BINUTILS_V_2_28 is not set
+# CT_BINUTILS_V_2_27 is not set
+# CT_BINUTILS_V_2_26 is not set
+# CT_BINUTILS_NO_VERSIONS is not set
+CT_BINUTILS_VERSION="2.32"
+CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
+CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
+CT_BINUTILS_later_than_2_30=y
+CT_BINUTILS_2_30_or_later=y
+CT_BINUTILS_later_than_2_27=y
+CT_BINUTILS_2_27_or_later=y
+CT_BINUTILS_later_than_2_25=y
+CT_BINUTILS_2_25_or_later=y
+CT_BINUTILS_REQUIRE_2_25_or_later=y
+CT_BINUTILS_later_than_2_23=y
+CT_BINUTILS_2_23_or_later=y
+
+#
+# GNU binutils
+#
+CT_BINUTILS_HAS_HASH_STYLE=y
+CT_BINUTILS_HAS_GOLD=y
+CT_BINUTILS_HAS_PLUGINS=y
+CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
+CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
+CT_BINUTILS_LINKER_LD=y
+CT_BINUTILS_LINKERS_LIST="ld"
+CT_BINUTILS_LINKER_DEFAULT="bfd"
+# CT_BINUTILS_PLUGINS is not set
+CT_BINUTILS_RELRO=m
+CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
+# CT_BINUTILS_FOR_TARGET is not set
+CT_ALL_BINUTILS_CHOICES="BINUTILS"
+
+#
+# C-library
+#
+CT_LIBC_GLIBC=y
+# CT_LIBC_MUSL is not set
+# CT_LIBC_UCLIBC is not set
+CT_LIBC="glibc"
+CT_LIBC_CHOICE_KSYM="GLIBC"
+CT_THREADS="nptl"
+CT_LIBC_GLIBC_SHOW=y
+
+#
+# Options for glibc
+#
+CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
+CT_GLIBC_DIR_NAME="glibc"
+CT_GLIBC_USE_GNU=y
+CT_GLIBC_USE="GLIBC"
+CT_GLIBC_PKG_NAME="glibc"
+CT_GLIBC_SRC_RELEASE=y
+# CT_GLIBC_SRC_DEVEL is not set
+# CT_GLIBC_SRC_CUSTOM is not set
+CT_GLIBC_PATCH_GLOBAL=y
+# CT_GLIBC_PATCH_BUNDLED is not set
+# CT_GLIBC_PATCH_LOCAL is not set
+# CT_GLIBC_PATCH_BUNDLED_LOCAL is not set
+# CT_GLIBC_PATCH_LOCAL_BUNDLED is not set
+# CT_GLIBC_PATCH_NONE is not set
+CT_GLIBC_PATCH_ORDER="global"
+CT_GLIBC_V_2_29=y
+# CT_GLIBC_NO_VERSIONS is not set
+CT_GLIBC_VERSION="2.29"
+CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
+CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
+CT_GLIBC_2_29_or_later=y
+CT_GLIBC_2_29_or_older=y
+CT_GLIBC_REQUIRE_2_29_or_later=y
+CT_GLIBC_later_than_2_27=y
+CT_GLIBC_2_27_or_later=y
+CT_GLIBC_later_than_2_26=y
+CT_GLIBC_2_26_or_later=y
+CT_GLIBC_later_than_2_25=y
+CT_GLIBC_2_25_or_later=y
+CT_GLIBC_later_than_2_24=y
+CT_GLIBC_2_24_or_later=y
+CT_GLIBC_later_than_2_23=y
+CT_GLIBC_2_23_or_later=y
+CT_GLIBC_later_than_2_20=y
+CT_GLIBC_2_20_or_later=y
+CT_GLIBC_later_than_2_17=y
+CT_GLIBC_2_17_or_later=y
+CT_GLIBC_later_than_2_14=y
+CT_GLIBC_2_14_or_later=y
+CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
+CT_GLIBC_DEP_BINUTILS=y
+CT_GLIBC_DEP_GCC=y
+CT_GLIBC_DEP_PYTHON=y
+CT_GLIBC_BUILD_SSP=y
+CT_GLIBC_HAS_LIBIDN_ADDON=y
+# CT_GLIBC_USE_LIBIDN_ADDON is not set
+CT_GLIBC_NO_SPARC_V8=y
+CT_GLIBC_HAS_OBSOLETE_RPC=y
+CT_GLIBC_EXTRA_CONFIG_ARRAY=""
+CT_GLIBC_CONFIGPARMS=""
+CT_GLIBC_EXTRA_CFLAGS=""
+CT_GLIBC_ENABLE_OBSOLETE_RPC=y
+# CT_GLIBC_ENABLE_FORTIFIED_BUILD is not set
+# CT_GLIBC_DISABLE_VERSIONING is not set
+CT_GLIBC_OLDEST_ABI=""
+CT_GLIBC_FORCE_UNWIND=y
+# CT_GLIBC_LOCALES is not set
+CT_GLIBC_KERNEL_VERSION_NONE=y
+# CT_GLIBC_KERNEL_VERSION_AS_HEADERS is not set
+# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
+CT_GLIBC_MIN_KERNEL=""
+CT_GLIBC_SSP_DEFAULT=y
+# CT_GLIBC_SSP_NO is not set
+# CT_GLIBC_SSP_YES is not set
+# CT_GLIBC_SSP_ALL is not set
+# CT_GLIBC_SSP_STRONG is not set
+# CT_GLIBC_ENABLE_WERROR is not set
+CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
+CT_LIBC_SUPPORT_THREADS_ANY=y
+CT_LIBC_SUPPORT_THREADS_NATIVE=y
+
+#
+# Common C library options
+#
+CT_THREADS_NATIVE=y
+# CT_CREATE_LDSO_CONF is not set
+CT_LIBC_XLDD=y
+
+#
+# C compiler
+#
+CT_CC_CORE_PASSES_NEEDED=y
+CT_CC_CORE_PASS_1_NEEDED=y
+CT_CC_CORE_PASS_2_NEEDED=y
+CT_CC_SUPPORT_CXX=y
+CT_CC_SUPPORT_FORTRAN=y
+CT_CC_SUPPORT_ADA=y
+CT_CC_SUPPORT_OBJC=y
+CT_CC_SUPPORT_OBJCXX=y
+CT_CC_SUPPORT_GOLANG=y
+CT_CC_GCC=y
+CT_CC="gcc"
+CT_CC_CHOICE_KSYM="GCC"
+CT_CC_GCC_SHOW=y
+
+#
+# Options for gcc
+#
+CT_CC_GCC_PKG_KSYM="GCC"
+CT_GCC_DIR_NAME="gcc"
+CT_GCC_USE_GNU=y
+# CT_GCC_USE_LINARO is not set
+CT_GCC_USE="GCC"
+CT_GCC_PKG_NAME="gcc"
+CT_GCC_SRC_RELEASE=y
+# CT_GCC_SRC_DEVEL is not set
+# CT_GCC_SRC_CUSTOM is not set
+CT_GCC_PATCH_GLOBAL=y
+# CT_GCC_PATCH_BUNDLED is not set
+# CT_GCC_PATCH_LOCAL is not set
+# CT_GCC_PATCH_BUNDLED_LOCAL is not set
+# CT_GCC_PATCH_LOCAL_BUNDLED is not set
+# CT_GCC_PATCH_NONE is not set
+CT_GCC_PATCH_ORDER="global"
+CT_GCC_V_8=y
+# CT_GCC_V_7 is not set
+# CT_GCC_NO_VERSIONS is not set
+CT_GCC_VERSION="8.3.0"
+CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
+CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_GCC_SIGNATURE_FORMAT=""
+CT_GCC_later_than_7=y
+CT_GCC_7_or_later=y
+CT_GCC_REQUIRE_7_or_later=y
+CT_GCC_later_than_6=y
+CT_GCC_6_or_later=y
+CT_GCC_later_than_5=y
+CT_GCC_5_or_later=y
+CT_GCC_REQUIRE_5_or_later=y
+CT_GCC_later_than_4_9=y
+CT_GCC_4_9_or_later=y
+CT_GCC_REQUIRE_4_9_or_later=y
+CT_GCC_later_than_4_8=y
+CT_GCC_4_8_or_later=y
+CT_CC_GCC_HAS_LIBMPX=y
+CT_CC_GCC_ENABLE_CXX_FLAGS=""
+CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
+CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
+CT_CC_GCC_STATIC_LIBSTDCXX=y
+# CT_CC_GCC_SYSTEM_ZLIB is not set
+CT_CC_GCC_CONFIG_TLS=m
+
+#
+# Optimisation features
+#
+CT_CC_GCC_USE_GRAPHITE=y
+CT_CC_GCC_USE_LTO=y
+
+#
+# Settings for libraries running on target
+#
+CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
+# CT_CC_GCC_LIBMUDFLAP is not set
+# CT_CC_GCC_LIBGOMP is not set
+# CT_CC_GCC_LIBSSP is not set
+# CT_CC_GCC_LIBQUADMATH is not set
+# CT_CC_GCC_LIBSANITIZER is not set
+
+#
+# Misc. obscure options.
+#
+CT_CC_CXA_ATEXIT=y
+# CT_CC_GCC_DISABLE_PCH is not set
+CT_CC_GCC_SJLJ_EXCEPTIONS=m
+CT_CC_GCC_LDBL_128=m
+# CT_CC_GCC_BUILD_ID is not set
+CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
+# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
+# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
+# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
+CT_CC_GCC_LNK_HASH_STYLE=""
+CT_CC_GCC_DEC_FLOAT_AUTO=y
+# CT_CC_GCC_DEC_FLOAT_BID is not set
+# CT_CC_GCC_DEC_FLOAT_DPD is not set
+# CT_CC_GCC_DEC_FLOATS_NO is not set
+CT_ALL_CC_CHOICES="GCC"
+
+#
+# Additional supported languages:
+#
+CT_CC_LANG_CXX=y
+# CT_CC_LANG_FORTRAN is not set
+# CT_CC_LANG_ADA is not set
+# CT_CC_LANG_OBJC is not set
+# CT_CC_LANG_OBJCXX is not set
+# CT_CC_LANG_GOLANG is not set
+CT_CC_LANG_OTHERS=""
+
+#
+# Debug facilities
+#
+# CT_DEBUG_DUMA is not set
+CT_DEBUG_GDB=y
+CT_DEBUG_GDB_PKG_KSYM="GDB"
+CT_GDB_DIR_NAME="gdb"
+CT_GDB_USE_GNU=y
+CT_GDB_USE="GDB"
+CT_GDB_PKG_NAME="gdb"
+CT_GDB_SRC_RELEASE=y
+# CT_GDB_SRC_DEVEL is not set
+# CT_GDB_SRC_CUSTOM is not set
+CT_GDB_PATCH_GLOBAL=y
+# CT_GDB_PATCH_BUNDLED is not set
+# CT_GDB_PATCH_LOCAL is not set
+# CT_GDB_PATCH_BUNDLED_LOCAL is not set
+# CT_GDB_PATCH_LOCAL_BUNDLED is not set
+# CT_GDB_PATCH_NONE is not set
+CT_GDB_PATCH_ORDER="global"
+CT_GDB_V_8_2=y
+# CT_GDB_V_8_1 is not set
+# CT_GDB_V_8_0 is not set
+# CT_GDB_NO_VERSIONS is not set
+CT_GDB_VERSION="8.2.1"
+CT_GDB_MIRRORS="$(CT_Mirrors GNU gdb) $(CT_Mirrors sourceware gdb/releases)"
+CT_GDB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GDB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GDB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_GDB_SIGNATURE_FORMAT=""
+CT_GDB_later_than_8_0=y
+CT_GDB_8_0_or_later=y
+CT_GDB_REQUIRE_8_0_or_later=y
+CT_GDB_later_than_7_12=y
+CT_GDB_7_12_or_later=y
+CT_GDB_later_than_7_2=y
+CT_GDB_7_2_or_later=y
+CT_GDB_later_than_7_0=y
+CT_GDB_7_0_or_later=y
+CT_GDB_CROSS=y
+# CT_GDB_CROSS_STATIC is not set
+# CT_GDB_CROSS_SIM is not set
+# CT_GDB_CROSS_PYTHON is not set
+CT_GDB_CROSS_EXTRA_CONFIG_ARRAY=""
+# CT_GDB_NATIVE is not set
+# CT_GDB_GDBSERVER is not set
+CT_GDB_HAS_PKGVERSION_BUGURL=y
+CT_GDB_HAS_PYTHON=y
+CT_GDB_INSTALL_GDBINIT=y
+CT_GDB_HAS_IPA_LIB=y
+# CT_DEBUG_LTRACE is not set
+# CT_DEBUG_STRACE is not set
+CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
+
+#
+# Companion libraries
+#
+# CT_COMPLIBS_CHECK is not set
+# CT_COMP_LIBS_CLOOG is not set
+CT_COMP_LIBS_EXPAT=y
+CT_COMP_LIBS_EXPAT_PKG_KSYM="EXPAT"
+CT_EXPAT_DIR_NAME="expat"
+CT_EXPAT_PKG_NAME="expat"
+CT_EXPAT_SRC_RELEASE=y
+# CT_EXPAT_SRC_DEVEL is not set
+# CT_EXPAT_SRC_CUSTOM is not set
+CT_EXPAT_PATCH_GLOBAL=y
+# CT_EXPAT_PATCH_BUNDLED is not set
+# CT_EXPAT_PATCH_LOCAL is not set
+# CT_EXPAT_PATCH_BUNDLED_LOCAL is not set
+# CT_EXPAT_PATCH_LOCAL_BUNDLED is not set
+# CT_EXPAT_PATCH_NONE is not set
+CT_EXPAT_PATCH_ORDER="global"
+CT_EXPAT_V_2_2=y
+# CT_EXPAT_NO_VERSIONS is not set
+CT_EXPAT_VERSION="2.2.6"
+CT_EXPAT_MIRRORS="http://downloads.sourceforge.net/project/expat/expat/${CT_EXPAT_VERSION}"
+CT_EXPAT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_EXPAT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_EXPAT_ARCHIVE_FORMATS=".tar.bz2"
+CT_EXPAT_SIGNATURE_FORMAT=""
+CT_COMP_LIBS_GETTEXT=y
+CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
+CT_GETTEXT_DIR_NAME="gettext"
+CT_GETTEXT_PKG_NAME="gettext"
+CT_GETTEXT_SRC_RELEASE=y
+# CT_GETTEXT_SRC_DEVEL is not set
+# CT_GETTEXT_SRC_CUSTOM is not set
+CT_GETTEXT_PATCH_GLOBAL=y
+# CT_GETTEXT_PATCH_BUNDLED is not set
+# CT_GETTEXT_PATCH_LOCAL is not set
+# CT_GETTEXT_PATCH_BUNDLED_LOCAL is not set
+# CT_GETTEXT_PATCH_LOCAL_BUNDLED is not set
+# CT_GETTEXT_PATCH_NONE is not set
+CT_GETTEXT_PATCH_ORDER="global"
+CT_GETTEXT_V_0_19_8_1=y
+# CT_GETTEXT_NO_VERSIONS is not set
+CT_GETTEXT_VERSION="0.19.8.1"
+CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
+CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
+CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_GMP=y
+CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
+CT_GMP_DIR_NAME="gmp"
+CT_GMP_PKG_NAME="gmp"
+CT_GMP_SRC_RELEASE=y
+# CT_GMP_SRC_DEVEL is not set
+# CT_GMP_SRC_CUSTOM is not set
+CT_GMP_PATCH_GLOBAL=y
+# CT_GMP_PATCH_BUNDLED is not set
+# CT_GMP_PATCH_LOCAL is not set
+# CT_GMP_PATCH_BUNDLED_LOCAL is not set
+# CT_GMP_PATCH_LOCAL_BUNDLED is not set
+# CT_GMP_PATCH_NONE is not set
+CT_GMP_PATCH_ORDER="global"
+CT_GMP_V_6_1=y
+# CT_GMP_NO_VERSIONS is not set
+CT_GMP_VERSION="6.1.2"
+CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
+CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
+CT_GMP_SIGNATURE_FORMAT="packed/.sig"
+CT_GMP_later_than_5_1_0=y
+CT_GMP_5_1_0_or_later=y
+CT_GMP_later_than_5_0_0=y
+CT_GMP_5_0_0_or_later=y
+CT_GMP_REQUIRE_5_0_0_or_later=y
+CT_COMP_LIBS_ISL=y
+CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
+CT_ISL_DIR_NAME="isl"
+CT_ISL_PKG_NAME="isl"
+CT_ISL_SRC_RELEASE=y
+# CT_ISL_SRC_DEVEL is not set
+# CT_ISL_SRC_CUSTOM is not set
+CT_ISL_PATCH_GLOBAL=y
+# CT_ISL_PATCH_BUNDLED is not set
+# CT_ISL_PATCH_LOCAL is not set
+# CT_ISL_PATCH_BUNDLED_LOCAL is not set
+# CT_ISL_PATCH_LOCAL_BUNDLED is not set
+# CT_ISL_PATCH_NONE is not set
+CT_ISL_PATCH_ORDER="global"
+CT_ISL_V_0_20=y
+# CT_ISL_V_0_19 is not set
+# CT_ISL_V_0_18 is not set
+# CT_ISL_V_0_17 is not set
+# CT_ISL_V_0_16 is not set
+# CT_ISL_V_0_15 is not set
+# CT_ISL_NO_VERSIONS is not set
+CT_ISL_VERSION="0.20"
+CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
+CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_ISL_SIGNATURE_FORMAT=""
+CT_ISL_later_than_0_18=y
+CT_ISL_0_18_or_later=y
+CT_ISL_later_than_0_15=y
+CT_ISL_0_15_or_later=y
+CT_ISL_REQUIRE_0_15_or_later=y
+CT_ISL_later_than_0_14=y
+CT_ISL_0_14_or_later=y
+CT_ISL_REQUIRE_0_14_or_later=y
+CT_ISL_later_than_0_13=y
+CT_ISL_0_13_or_later=y
+CT_ISL_later_than_0_12=y
+CT_ISL_0_12_or_later=y
+CT_ISL_REQUIRE_0_12_or_later=y
+# CT_COMP_LIBS_LIBELF is not set
+CT_COMP_LIBS_LIBICONV=y
+CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
+CT_LIBICONV_DIR_NAME="libiconv"
+CT_LIBICONV_PKG_NAME="libiconv"
+CT_LIBICONV_SRC_RELEASE=y
+# CT_LIBICONV_SRC_DEVEL is not set
+# CT_LIBICONV_SRC_CUSTOM is not set
+CT_LIBICONV_PATCH_GLOBAL=y
+# CT_LIBICONV_PATCH_BUNDLED is not set
+# CT_LIBICONV_PATCH_LOCAL is not set
+# CT_LIBICONV_PATCH_BUNDLED_LOCAL is not set
+# CT_LIBICONV_PATCH_LOCAL_BUNDLED is not set
+# CT_LIBICONV_PATCH_NONE is not set
+CT_LIBICONV_PATCH_ORDER="global"
+CT_LIBICONV_V_1_15=y
+# CT_LIBICONV_NO_VERSIONS is not set
+CT_LIBICONV_VERSION="1.15"
+CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
+CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
+CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_MPC=y
+CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
+CT_MPC_DIR_NAME="mpc"
+CT_MPC_PKG_NAME="mpc"
+CT_MPC_SRC_RELEASE=y
+# CT_MPC_SRC_DEVEL is not set
+# CT_MPC_SRC_CUSTOM is not set
+CT_MPC_PATCH_GLOBAL=y
+# CT_MPC_PATCH_BUNDLED is not set
+# CT_MPC_PATCH_LOCAL is not set
+# CT_MPC_PATCH_BUNDLED_LOCAL is not set
+# CT_MPC_PATCH_LOCAL_BUNDLED is not set
+# CT_MPC_PATCH_NONE is not set
+CT_MPC_PATCH_ORDER="global"
+CT_MPC_V_1_1=y
+# CT_MPC_V_1_0 is not set
+# CT_MPC_NO_VERSIONS is not set
+CT_MPC_VERSION="1.1.0"
+CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
+CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_FORMATS=".tar.gz"
+CT_MPC_SIGNATURE_FORMAT="packed/.sig"
+CT_MPC_1_1_0_or_later=y
+CT_MPC_1_1_0_or_older=y
+CT_COMP_LIBS_MPFR=y
+CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
+CT_MPFR_DIR_NAME="mpfr"
+CT_MPFR_PKG_NAME="mpfr"
+CT_MPFR_SRC_RELEASE=y
+# CT_MPFR_SRC_DEVEL is not set
+# CT_MPFR_SRC_CUSTOM is not set
+CT_MPFR_PATCH_GLOBAL=y
+# CT_MPFR_PATCH_BUNDLED is not set
+# CT_MPFR_PATCH_LOCAL is not set
+# CT_MPFR_PATCH_BUNDLED_LOCAL is not set
+# CT_MPFR_PATCH_LOCAL_BUNDLED is not set
+# CT_MPFR_PATCH_NONE is not set
+CT_MPFR_PATCH_ORDER="global"
+CT_MPFR_V_4_0=y
+# CT_MPFR_V_3_1 is not set
+# CT_MPFR_NO_VERSIONS is not set
+CT_MPFR_VERSION="4.0.2"
+CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
+CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
+CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
+CT_MPFR_later_than_4_0_0=y
+CT_MPFR_4_0_0_or_later=y
+CT_MPFR_later_than_3_0_0=y
+CT_MPFR_3_0_0_or_later=y
+CT_MPFR_REQUIRE_3_0_0_or_later=y
+CT_COMP_LIBS_NCURSES=y
+CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
+CT_NCURSES_DIR_NAME="ncurses"
+CT_NCURSES_PKG_NAME="ncurses"
+CT_NCURSES_SRC_RELEASE=y
+# CT_NCURSES_SRC_DEVEL is not set
+# CT_NCURSES_SRC_CUSTOM is not set
+CT_NCURSES_PATCH_GLOBAL=y
+# CT_NCURSES_PATCH_BUNDLED is not set
+# CT_NCURSES_PATCH_LOCAL is not set
+# CT_NCURSES_PATCH_BUNDLED_LOCAL is not set
+# CT_NCURSES_PATCH_LOCAL_BUNDLED is not set
+# CT_NCURSES_PATCH_NONE is not set
+CT_NCURSES_PATCH_ORDER="global"
+CT_NCURSES_V_6_1=y
+# CT_NCURSES_V_6_0 is not set
+# CT_NCURSES_NO_VERSIONS is not set
+CT_NCURSES_VERSION="6.1"
+CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
+CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
+CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
+# CT_NCURSES_NEW_ABI is not set
+CT_NCURSES_HOST_CONFIG_ARGS=""
+CT_NCURSES_HOST_DISABLE_DB=y
+CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
+CT_NCURSES_TARGET_CONFIG_ARGS=""
+# CT_NCURSES_TARGET_DISABLE_DB is not set
+CT_NCURSES_TARGET_FALLBACKS=""
+CT_COMP_LIBS_ZLIB=y
+CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
+CT_ZLIB_DIR_NAME="zlib"
+CT_ZLIB_PKG_NAME="zlib"
+CT_ZLIB_SRC_RELEASE=y
+# CT_ZLIB_SRC_DEVEL is not set
+# CT_ZLIB_SRC_CUSTOM is not set
+CT_ZLIB_PATCH_GLOBAL=y
+# CT_ZLIB_PATCH_BUNDLED is not set
+# CT_ZLIB_PATCH_LOCAL is not set
+# CT_ZLIB_PATCH_BUNDLED_LOCAL is not set
+# CT_ZLIB_PATCH_LOCAL_BUNDLED is not set
+# CT_ZLIB_PATCH_NONE is not set
+CT_ZLIB_PATCH_ORDER="global"
+CT_ZLIB_V_1_2_11=y
+# CT_ZLIB_NO_VERSIONS is not set
+CT_ZLIB_VERSION="1.2.11"
+CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
+CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
+CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
+CT_LIBICONV_NEEDED=y
+CT_GETTEXT_NEEDED=y
+CT_GMP_NEEDED=y
+CT_MPFR_NEEDED=y
+CT_ISL_NEEDED=y
+CT_MPC_NEEDED=y
+CT_EXPAT_NEEDED=y
+CT_NCURSES_NEEDED=y
+CT_ZLIB_NEEDED=y
+CT_LIBICONV=y
+CT_GETTEXT=y
+CT_GMP=y
+CT_MPFR=y
+CT_ISL=y
+CT_MPC=y
+CT_EXPAT=y
+CT_NCURSES=y
+CT_ZLIB=y
+
+#
+# Companion tools
+#
+# CT_COMP_TOOLS_FOR_HOST is not set
+# CT_COMP_TOOLS_AUTOCONF is not set
+# CT_COMP_TOOLS_AUTOMAKE is not set
+# CT_COMP_TOOLS_BISON is not set
+# CT_COMP_TOOLS_DTC is not set
+# CT_COMP_TOOLS_LIBTOOL is not set
+# CT_COMP_TOOLS_M4 is not set
+# CT_COMP_TOOLS_MAKE is not set
+CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
+
+#
+# Test suite
+#
+# CT_TEST_SUITE_GCC is not set
index b5c6babcdd4ce1fa90458b7827a5fde082e79e87..92baf7293dd2d418d2ac4b141b0faa822075d9f7 160000 (submodule)
@@ -1 +1 @@
-Subproject commit b5c6babcdd4ce1fa90458b7827a5fde082e79e87
+Subproject commit 92baf7293dd2d418d2ac4b141b0faa822075d9f7
diff --git a/src/doc/unstable-book/src/language-features/slice-patterns.md b/src/doc/unstable-book/src/language-features/slice-patterns.md
deleted file mode 100644 (file)
index cdb7449..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-# `slice_patterns`
-
-The tracking issue for this feature is: [#62254]
-
-[#62254]: https://github.com/rust-lang/rust/issues/62254
-
-------------------------
-
-The `slice_patterns` feature gate lets you use `..` to indicate any number of
-elements inside a pattern matching a slice. This wildcard can only be used once
-for a given array. If there's an pattern before the `..`, the subslice will be
-matched against that pattern. For example:
-
-```rust
-#![feature(slice_patterns)]
-
-fn is_symmetric(list: &[u32]) -> bool {
-    match list {
-        &[] | &[_] => true,
-        &[x, ref inside @ .., y] if x == y => is_symmetric(inside),
-        &[..] => false,
-    }
-}
-
-fn main() {
-    let sym = &[0, 1, 4, 2, 4, 1, 0];
-    assert!(is_symmetric(sym));
-
-    let not_sym = &[0, 1, 7, 2, 4, 1, 0];
-    assert!(!is_symmetric(not_sym));
-}
-```
index 599c8b1682851a7dc0a6dfbf66b4b969ca078d42..5c95160ba2d14dba82ea7a57b4fef7b64ef45f88 100644 (file)
@@ -1,5 +1,5 @@
 use std::iter::repeat;
-use test::Bencher;
+use test::{black_box, Bencher};
 
 #[bench]
 fn bench_with_capacity(b: &mut Bencher) {
index 35ce1354f52e09b3e9bda104963d186db8736db3..f5be72c39b20c68356cfab215c554ffe29a4bf1a 100644 (file)
@@ -4,6 +4,7 @@
 use std::fmt::Debug;
 use std::iter::FromIterator;
 use std::ops::Bound::{self, Excluded, Included, Unbounded};
+use std::ops::RangeBounds;
 use std::rc::Rc;
 
 use super::DeterministicRng;
@@ -68,6 +69,11 @@ fn test_basic_small() {
     assert_eq!(map.last_key_value(), None);
     assert_eq!(map.keys().count(), 0);
     assert_eq!(map.values().count(), 0);
+    assert_eq!(map.range(..).next(), None);
+    assert_eq!(map.range(..1).next(), None);
+    assert_eq!(map.range(1..).next(), None);
+    assert_eq!(map.range(1..=1).next(), None);
+    assert_eq!(map.range(1..2).next(), None);
     assert_eq!(map.insert(1, 1), None);
 
     // 1 key-value pair:
@@ -118,6 +124,11 @@ fn test_basic_small() {
     assert_eq!(map.last_key_value(), None);
     assert_eq!(map.keys().count(), 0);
     assert_eq!(map.values().count(), 0);
+    assert_eq!(map.range(..).next(), None);
+    assert_eq!(map.range(..1).next(), None);
+    assert_eq!(map.range(1..).next(), None);
+    assert_eq!(map.range(1..=1).next(), None);
+    assert_eq!(map.range(1..2).next(), None);
     assert_eq!(map.remove(&1), None);
 }
 
@@ -128,7 +139,6 @@ fn test_iter() {
     #[cfg(miri)]
     let size = 200;
 
-    // Forwards
     let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
 
     fn test<T>(size: usize, mut iter: T)
@@ -154,7 +164,6 @@ fn test_iter_rev() {
     #[cfg(miri)]
     let size = 200;
 
-    // Forwards
     let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
 
     fn test<T>(size: usize, mut iter: T)
@@ -275,7 +284,6 @@ fn test_iter_mixed() {
     #[cfg(miri)]
     let size = 200;
 
-    // Forwards
     let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
 
     fn test<T>(size: usize, mut iter: T)
@@ -299,27 +307,147 @@ fn test<T>(size: usize, mut iter: T)
     test(size, map.into_iter());
 }
 
-#[test]
-fn test_range_small() {
-    let size = 5;
-
-    // Forwards
-    let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
-
-    let mut j = 0;
-    for ((&k, &v), i) in map.range(2..).zip(2..size) {
-        assert_eq!(k, i);
-        assert_eq!(v, i);
-        j += 1;
-    }
-    assert_eq!(j, size - 2);
+fn range_keys(map: &BTreeMap<i32, i32>, range: impl RangeBounds<i32>) -> Vec<i32> {
+    map.range(range)
+        .map(|(&k, &v)| {
+            assert_eq!(k, v);
+            k
+        })
+        .collect()
 }
 
 #[test]
-fn test_range_inclusive() {
-    let size = 500;
+fn test_range_small() {
+    let size = 4;
+
+    let map: BTreeMap<_, _> = (1..=size).map(|i| (i, i)).collect();
+    let all: Vec<_> = (1..=size).collect();
+    let (first, last) = (vec![all[0]], vec![all[size as usize - 1]]);
+
+    assert_eq!(range_keys(&map, (Excluded(0), Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(size))), all);
+    assert_eq!(range_keys(&map, (Excluded(0), Unbounded)), all);
+    assert_eq!(range_keys(&map, (Included(0), Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(0), Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(0), Included(size))), all);
+    assert_eq!(range_keys(&map, (Included(0), Unbounded)), all);
+    assert_eq!(range_keys(&map, (Included(1), Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(1), Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(1), Included(size))), all);
+    assert_eq!(range_keys(&map, (Included(1), Unbounded)), all);
+    assert_eq!(range_keys(&map, (Unbounded, Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Unbounded, Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Unbounded, Included(size))), all);
+    assert_eq!(range_keys(&map, ..), all);
+
+    assert_eq!(range_keys(&map, (Excluded(0), Excluded(1))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(0))), vec![]);
+    assert_eq!(range_keys(&map, (Included(0), Included(0))), vec![]);
+    assert_eq!(range_keys(&map, (Included(0), Excluded(1))), vec![]);
+    assert_eq!(range_keys(&map, (Unbounded, Excluded(1))), vec![]);
+    assert_eq!(range_keys(&map, (Unbounded, Included(0))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(0), Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(1))), first);
+    assert_eq!(range_keys(&map, (Included(0), Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Included(0), Included(1))), first);
+    assert_eq!(range_keys(&map, (Included(1), Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Included(1), Included(1))), first);
+    assert_eq!(range_keys(&map, (Unbounded, Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Unbounded, Included(1))), first);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Excluded(size + 1))), last);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size + 1))), last);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size))), last);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Unbounded)), last);
+    assert_eq!(range_keys(&map, (Included(size), Excluded(size + 1))), last);
+    assert_eq!(range_keys(&map, (Included(size), Included(size + 1))), last);
+    assert_eq!(range_keys(&map, (Included(size), Included(size))), last);
+    assert_eq!(range_keys(&map, (Included(size), Unbounded)), last);
+    assert_eq!(range_keys(&map, (Excluded(size), Excluded(size + 1))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(size), Included(size))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(size), Unbounded)), vec![]);
+    assert_eq!(range_keys(&map, (Included(size + 1), Excluded(size + 1))), vec![]);
+    assert_eq!(range_keys(&map, (Included(size + 1), Included(size + 1))), vec![]);
+    assert_eq!(range_keys(&map, (Included(size + 1), Unbounded)), vec![]);
+
+    assert_eq!(range_keys(&map, ..3), vec![1, 2]);
+    assert_eq!(range_keys(&map, 3..), vec![3, 4]);
+    assert_eq!(range_keys(&map, 2..=3), vec![2, 3]);
+}
+
+#[test]
+fn test_range_depth_2() {
+    // Assuming that node.CAPACITY is 11, having 12 pairs implies a depth 2 tree
+    // with 2 leaves. Depending on details we don't want or need to rely upon,
+    // the single key at the root will be 6 or 7.
+
+    let map: BTreeMap<_, _> = (1..=12).map(|i| (i, i)).collect();
+    for &root in &[6, 7] {
+        assert_eq!(range_keys(&map, (Excluded(root), Excluded(root + 1))), vec![]);
+        assert_eq!(range_keys(&map, (Excluded(root), Included(root + 1))), vec![root + 1]);
+        assert_eq!(range_keys(&map, (Included(root), Excluded(root + 1))), vec![root]);
+        assert_eq!(range_keys(&map, (Included(root), Included(root + 1))), vec![root, root + 1]);
+
+        assert_eq!(range_keys(&map, (Excluded(root - 1), Excluded(root))), vec![]);
+        assert_eq!(range_keys(&map, (Included(root - 1), Excluded(root))), vec![root - 1]);
+        assert_eq!(range_keys(&map, (Excluded(root - 1), Included(root))), vec![root]);
+        assert_eq!(range_keys(&map, (Included(root - 1), Included(root))), vec![root - 1, root]);
+    }
+}
+
+#[test]
+fn test_range_large() {
+    let size = 200;
 
-    let map: BTreeMap<_, _> = (0..=size).map(|i| (i, i)).collect();
+    let map: BTreeMap<_, _> = (1..=size).map(|i| (i, i)).collect();
+    let all: Vec<_> = (1..=size).collect();
+    let (first, last) = (vec![all[0]], vec![all[size as usize - 1]]);
+
+    assert_eq!(range_keys(&map, (Excluded(0), Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(size))), all);
+    assert_eq!(range_keys(&map, (Excluded(0), Unbounded)), all);
+    assert_eq!(range_keys(&map, (Included(0), Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(0), Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(0), Included(size))), all);
+    assert_eq!(range_keys(&map, (Included(0), Unbounded)), all);
+    assert_eq!(range_keys(&map, (Included(1), Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(1), Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Included(1), Included(size))), all);
+    assert_eq!(range_keys(&map, (Included(1), Unbounded)), all);
+    assert_eq!(range_keys(&map, (Unbounded, Excluded(size + 1))), all);
+    assert_eq!(range_keys(&map, (Unbounded, Included(size + 1))), all);
+    assert_eq!(range_keys(&map, (Unbounded, Included(size))), all);
+    assert_eq!(range_keys(&map, ..), all);
+
+    assert_eq!(range_keys(&map, (Excluded(0), Excluded(1))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(0))), vec![]);
+    assert_eq!(range_keys(&map, (Included(0), Included(0))), vec![]);
+    assert_eq!(range_keys(&map, (Included(0), Excluded(1))), vec![]);
+    assert_eq!(range_keys(&map, (Unbounded, Excluded(1))), vec![]);
+    assert_eq!(range_keys(&map, (Unbounded, Included(0))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(0), Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Excluded(0), Included(1))), first);
+    assert_eq!(range_keys(&map, (Included(0), Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Included(0), Included(1))), first);
+    assert_eq!(range_keys(&map, (Included(1), Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Included(1), Included(1))), first);
+    assert_eq!(range_keys(&map, (Unbounded, Excluded(2))), first);
+    assert_eq!(range_keys(&map, (Unbounded, Included(1))), first);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Excluded(size + 1))), last);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size + 1))), last);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size))), last);
+    assert_eq!(range_keys(&map, (Excluded(size - 1), Unbounded)), last);
+    assert_eq!(range_keys(&map, (Included(size), Excluded(size + 1))), last);
+    assert_eq!(range_keys(&map, (Included(size), Included(size + 1))), last);
+    assert_eq!(range_keys(&map, (Included(size), Included(size))), last);
+    assert_eq!(range_keys(&map, (Included(size), Unbounded)), last);
+    assert_eq!(range_keys(&map, (Excluded(size), Excluded(size + 1))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(size), Included(size))), vec![]);
+    assert_eq!(range_keys(&map, (Excluded(size), Unbounded)), vec![]);
+    assert_eq!(range_keys(&map, (Included(size + 1), Excluded(size + 1))), vec![]);
+    assert_eq!(range_keys(&map, (Included(size + 1), Included(size + 1))), vec![]);
+    assert_eq!(range_keys(&map, (Included(size + 1), Unbounded)), vec![]);
 
     fn check<'a, L, R>(lhs: L, rhs: R)
     where
@@ -331,18 +459,9 @@ fn check<'a, L, R>(lhs: L, rhs: R)
         assert_eq!(lhs, rhs);
     }
 
-    check(map.range(size + 1..=size + 1), vec![]);
-    check(map.range(size..=size), vec![(&size, &size)]);
-    check(map.range(size..=size + 1), vec![(&size, &size)]);
-    check(map.range(0..=0), vec![(&0, &0)]);
-    check(map.range(0..=size - 1), map.range(..size));
-    check(map.range(-1..=-1), vec![]);
-    check(map.range(-1..=size), map.range(..));
-    check(map.range(..=size), map.range(..));
-    check(map.range(..=200), map.range(..201));
+    check(map.range(..=100), map.range(..101));
     check(map.range(5..=8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]);
-    check(map.range(-1..=0), vec![(&0, &0)]);
-    check(map.range(-1..=2), vec![(&0, &0), (&1, &1), (&2, &2)]);
+    check(map.range(-1..=2), vec![(&1, &1), (&2, &2)]);
 }
 
 #[test]
index beb0bac17d2ea0d3c6fcbe4042470c5a48206b6f..2a3d92edc4956dafc26936d82c8a506ff0e5029a 100644 (file)
@@ -21,7 +21,6 @@
 extern crate alloc;
 
 use rustc_data_structures::cold_path;
-use rustc_data_structures::sync::MTLock;
 use smallvec::SmallVec;
 
 use std::cell::{Cell, RefCell};
@@ -116,11 +115,6 @@ fn default() -> TypedArena<T> {
 }
 
 impl<T> TypedArena<T> {
-    pub fn in_arena(&self, ptr: *const T) -> bool {
-        let ptr = ptr as *const T as *mut T;
-
-        self.chunks.borrow().iter().any(|chunk| chunk.start() <= ptr && ptr < chunk.end())
-    }
     /// Allocates an object in the `TypedArena`, returning a reference to it.
     #[inline]
     pub fn alloc(&self, object: T) -> &mut T {
@@ -334,12 +328,6 @@ fn default() -> DroplessArena {
 }
 
 impl DroplessArena {
-    pub fn in_arena<T: ?Sized>(&self, ptr: *const T) -> bool {
-        let ptr = ptr as *const u8 as *mut u8;
-
-        self.chunks.borrow().iter().any(|chunk| chunk.start() <= ptr && ptr < chunk.end())
-    }
-
     #[inline]
     fn align(&self, align: usize) {
         let final_address = ((self.ptr.get() as usize) + align - 1) & !(align - 1);
@@ -500,66 +488,5 @@ pub fn alloc_from_iter<T, I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T]
     }
 }
 
-#[derive(Default)]
-// FIXME(@Zoxc): this type is entirely unused in rustc
-pub struct SyncTypedArena<T> {
-    lock: MTLock<TypedArena<T>>,
-}
-
-impl<T> SyncTypedArena<T> {
-    #[inline(always)]
-    pub fn alloc(&self, object: T) -> &mut T {
-        // Extend the lifetime of the result since it's limited to the lock guard
-        unsafe { &mut *(self.lock.lock().alloc(object) as *mut T) }
-    }
-
-    #[inline(always)]
-    pub fn alloc_slice(&self, slice: &[T]) -> &mut [T]
-    where
-        T: Copy,
-    {
-        // Extend the lifetime of the result since it's limited to the lock guard
-        unsafe { &mut *(self.lock.lock().alloc_slice(slice) as *mut [T]) }
-    }
-
-    #[inline(always)]
-    pub fn clear(&mut self) {
-        self.lock.get_mut().clear();
-    }
-}
-
-#[derive(Default)]
-pub struct SyncDroplessArena {
-    lock: MTLock<DroplessArena>,
-}
-
-impl SyncDroplessArena {
-    #[inline(always)]
-    pub fn in_arena<T: ?Sized>(&self, ptr: *const T) -> bool {
-        self.lock.lock().in_arena(ptr)
-    }
-
-    #[inline(always)]
-    pub fn alloc_raw(&self, bytes: usize, align: usize) -> &mut [u8] {
-        // Extend the lifetime of the result since it's limited to the lock guard
-        unsafe { &mut *(self.lock.lock().alloc_raw(bytes, align) as *mut [u8]) }
-    }
-
-    #[inline(always)]
-    pub fn alloc<T>(&self, object: T) -> &mut T {
-        // Extend the lifetime of the result since it's limited to the lock guard
-        unsafe { &mut *(self.lock.lock().alloc(object) as *mut T) }
-    }
-
-    #[inline(always)]
-    pub fn alloc_slice<T>(&self, slice: &[T]) -> &mut [T]
-    where
-        T: Copy,
-    {
-        // Extend the lifetime of the result since it's limited to the lock guard
-        unsafe { &mut *(self.lock.lock().alloc_slice(slice) as *mut [T]) }
-    }
-}
-
 #[cfg(test)]
 mod tests;
index 4afea12a362c89f04810544c1c4f46448f1a4d56..af02e84d3fa537f5c7fdb1469e4d45ba29364f33 100644 (file)
@@ -476,11 +476,15 @@ pub const fn type_name<T: ?Sized>() -> &'static str {
 ///
 /// This is intended for diagnostic use. The exact contents and format of the
 /// string are not specified, other than being a best-effort description of the
-/// type. For example, `type_name_of::<Option<String>>(None)` could return
+/// type. For example, `type_name_of_val::<Option<String>>(None)` could return
 /// `"Option<String>"` or `"std::option::Option<std::string::String>"`, but not
 /// `"foobar"`. In addition, the output may change between versions of the
 /// compiler.
 ///
+/// This function does not resolve trait objects,
+/// meaning that `type_name_of_val(&7u32 as &dyn Debug)`
+/// may return `"dyn Debug"`, but not `"u32"`.
+///
 /// The type name should not be considered a unique identifier of a type;
 /// multiple types may share the same type name.
 ///
index 4fcd0d9737d562252f7d82508e57e0beeba21e6e..e7eecf7540ad74121d4a0c840536afff154a98e5 100644 (file)
 //! ```
 //!
 
-// ignore-tidy-undocumented-unsafe
-
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::cmp::Ordering;
@@ -368,6 +366,10 @@ pub fn swap(&self, other: &Self) {
         if ptr::eq(self, other) {
             return;
         }
+        // SAFETY: This can be risky if called from separate threads, but `Cell`
+        // is `!Sync` so this won't happen. This also won't invalidate any
+        // pointers since `Cell` makes sure nothing else will be pointing into
+        // either of these `Cell`s.
         unsafe {
             ptr::swap(self.value.get(), other.value.get());
         }
@@ -387,6 +389,8 @@ pub fn swap(&self, other: &Self) {
     /// ```
     #[stable(feature = "move_cell", since = "1.17.0")]
     pub fn replace(&self, val: T) -> T {
+        // SAFETY: This can cause data races if called from a separate thread,
+        // but `Cell` is `!Sync` so this won't happen.
         mem::replace(unsafe { &mut *self.value.get() }, val)
     }
 
@@ -423,6 +427,8 @@ impl<T: Copy> Cell<T> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get(&self) -> T {
+        // SAFETY: This can cause data races if called from a separate thread,
+        // but `Cell` is `!Sync` so this won't happen.
         unsafe { *self.value.get() }
     }
 
@@ -491,6 +497,9 @@ pub const fn as_ptr(&self) -> *mut T {
     #[inline]
     #[stable(feature = "cell_get_mut", since = "1.11.0")]
     pub fn get_mut(&mut self) -> &mut T {
+        // SAFETY: This can cause data races if called from a separate thread,
+        // but `Cell` is `!Sync` so this won't happen, and `&mut` guarantees
+        // unique access.
         unsafe { &mut *self.value.get() }
     }
 
@@ -510,6 +519,7 @@ pub fn get_mut(&mut self) -> &mut T {
     #[inline]
     #[stable(feature = "as_cell", since = "1.37.0")]
     pub fn from_mut(t: &mut T) -> &Cell<T> {
+        // SAFETY: `&mut` ensures unique access.
         unsafe { &*(t as *mut T as *const Cell<T>) }
     }
 }
@@ -553,6 +563,7 @@ impl<T> Cell<[T]> {
     /// ```
     #[stable(feature = "as_cell", since = "1.37.0")]
     pub fn as_slice_of_cells(&self) -> &[Cell<T>] {
+        // SAFETY: `Cell<T>` has the same memory layout as `T`.
         unsafe { &*(self as *const Cell<[T]> as *const [Cell<T>]) }
     }
 }
@@ -816,6 +827,8 @@ pub fn borrow(&self) -> Ref<'_, T> {
     #[inline]
     pub fn try_borrow(&self) -> Result<Ref<'_, T>, BorrowError> {
         match BorrowRef::new(&self.borrow) {
+            // SAFETY: `BorrowRef` ensures that there is only immutable access
+            // to the value while borrowed.
             Some(b) => Ok(Ref { value: unsafe { &*self.value.get() }, borrow: b }),
             None => Err(BorrowError { _private: () }),
         }
@@ -891,6 +904,7 @@ pub fn borrow_mut(&self) -> RefMut<'_, T> {
     #[inline]
     pub fn try_borrow_mut(&self) -> Result<RefMut<'_, T>, BorrowMutError> {
         match BorrowRefMut::new(&self.borrow) {
+            // SAFETY: `BorrowRef` guarantees unique access.
             Some(b) => Ok(RefMut { value: unsafe { &mut *self.value.get() }, borrow: b }),
             None => Err(BorrowMutError { _private: () }),
         }
@@ -940,6 +954,7 @@ pub fn as_ptr(&self) -> *mut T {
     #[inline]
     #[stable(feature = "cell_get_mut", since = "1.11.0")]
     pub fn get_mut(&mut self) -> &mut T {
+        // SAFETY: `&mut` guarantees unique access.
         unsafe { &mut *self.value.get() }
     }
 
index 626eb1e862d992eb8f9cfbae986a0aee422de5a2..dd0f3ccb15841721ca16c28c1288b3e13baccf21 100644 (file)
@@ -159,6 +159,62 @@ pub fn field(&mut self, name: &str, value: &dyn fmt::Debug) -> &mut DebugStruct<
         self
     }
 
+    /// Marks the struct as non-exhaustive, indicating to the reader that there are some other
+    /// fields that are not shown in the debug representation.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(debug_non_exhaustive)]
+    /// use std::fmt;
+    ///
+    /// struct Bar {
+    ///     bar: i32,
+    ///     hidden: f32,
+    /// }
+    ///
+    /// impl fmt::Debug for Bar {
+    ///     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+    ///         fmt.debug_struct("Bar")
+    ///            .field("bar", &self.bar)
+    ///            .finish_non_exhaustive() // Show that some other field(s) exist.
+    ///     }
+    /// }
+    ///
+    /// assert_eq!(
+    ///     format!("{:?}", Bar { bar: 10, hidden: 1.0 }),
+    ///     "Bar { bar: 10, .. }",
+    /// );
+    /// ```
+    #[unstable(feature = "debug_non_exhaustive", issue = "67364")]
+    pub fn finish_non_exhaustive(&mut self) -> fmt::Result {
+        self.result = self.result.and_then(|_| {
+            // Draw non-exhaustive dots (`..`), and open brace if necessary (no fields).
+            if self.is_pretty() {
+                if !self.has_fields {
+                    self.fmt.write_str(" {\n")?;
+                }
+                let mut slot = None;
+                let mut state = Default::default();
+                let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut state);
+                writer.write_str("..\n")?;
+            } else {
+                if self.has_fields {
+                    self.fmt.write_str(", ..")?;
+                } else {
+                    self.fmt.write_str(" { ..")?;
+                }
+            }
+            if self.is_pretty() {
+                self.fmt.write_str("}")?
+            } else {
+                self.fmt.write_str(" }")?;
+            }
+            Ok(())
+        });
+        self.result
+    }
+
     /// Finishes output and returns any error encountered.
     ///
     /// # Examples
index e68f3c58a3e07769aedfe787b866d3d1b1733a03..900ef63f1dfcc3a3b2b263b463779307c26f3c3f 100644 (file)
@@ -10,7 +10,6 @@
 use crate::num::flt2dec;
 use crate::ops::Deref;
 use crate::result;
-use crate::slice;
 use crate::str;
 
 mod builders;
@@ -234,8 +233,6 @@ pub struct Formatter<'a> {
     precision: Option<usize>,
 
     buf: &'a mut (dyn Write + 'a),
-    curarg: slice::Iter<'a, ArgumentV1<'a>>,
-    args: &'a [ArgumentV1<'a>],
 }
 
 // NB. Argument is essentially an optimized partially applied formatting function,
@@ -1043,8 +1040,6 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
         buf: output,
         align: rt::v1::Alignment::Unknown,
         fill: ' ',
-        args: args.args,
-        curarg: args.args.iter(),
     };
 
     let mut idx = 0;
@@ -1063,7 +1058,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
             // a string piece.
             for (arg, piece) in fmt.iter().zip(args.pieces.iter()) {
                 formatter.buf.write_str(*piece)?;
-                formatter.run(arg)?;
+                run(&mut formatter, arg, &args.args)?;
                 idx += 1;
             }
         }
@@ -1077,6 +1072,39 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
     Ok(())
 }
 
+fn run(fmt: &mut Formatter<'_>, arg: &rt::v1::Argument, args: &[ArgumentV1<'_>]) -> Result {
+    fmt.fill = arg.format.fill;
+    fmt.align = arg.format.align;
+    fmt.flags = arg.format.flags;
+    fmt.width = getcount(args, &arg.format.width);
+    fmt.precision = getcount(args, &arg.format.precision);
+
+    // Extract the correct argument
+    let value = {
+        #[cfg(bootstrap)]
+        {
+            match arg.position {
+                rt::v1::Position::At(i) => args[i],
+            }
+        }
+        #[cfg(not(bootstrap))]
+        {
+            args[arg.position]
+        }
+    };
+
+    // Then actually do some printing
+    (value.formatter)(value.value, fmt)
+}
+
+fn getcount(args: &[ArgumentV1<'_>], cnt: &rt::v1::Count) -> Option<usize> {
+    match *cnt {
+        rt::v1::Count::Is(n) => Some(n),
+        rt::v1::Count::Implied => None,
+        rt::v1::Count::Param(i) => args[i].as_usize(),
+    }
+}
+
 /// Padding after the end of something. Returned by `Formatter::padding`.
 #[must_use = "don't forget to write the post padding"]
 struct PostPadding {
@@ -1114,41 +1142,6 @@ fn wrap_buf<'b, 'c, F>(&'b mut self, wrap: F) -> Formatter<'c>
             align: self.align,
             width: self.width,
             precision: self.precision,
-
-            // These only exist in the struct for the `run` method,
-            // which won’t be used together with this method.
-            curarg: self.curarg.clone(),
-            args: self.args,
-        }
-    }
-
-    // First up is the collection of functions used to execute a format string
-    // at runtime. This consumes all of the compile-time statics generated by
-    // the format! syntax extension.
-    fn run(&mut self, arg: &rt::v1::Argument) -> Result {
-        // Fill in the format parameters into the formatter
-        self.fill = arg.format.fill;
-        self.align = arg.format.align;
-        self.flags = arg.format.flags;
-        self.width = self.getcount(&arg.format.width);
-        self.precision = self.getcount(&arg.format.precision);
-
-        // Extract the correct argument
-        let value = match arg.position {
-            rt::v1::Position::Next => *self.curarg.next().unwrap(),
-            rt::v1::Position::At(i) => self.args[i],
-        };
-
-        // Then actually do some printing
-        (value.formatter)(value.value, self)
-    }
-
-    fn getcount(&mut self, cnt: &rt::v1::Count) -> Option<usize> {
-        match *cnt {
-            rt::v1::Count::Is(n) => Some(n),
-            rt::v1::Count::Implied => None,
-            rt::v1::Count::Param(i) => self.args[i].as_usize(),
-            rt::v1::Count::NextParam => self.curarg.next()?.as_usize(),
         }
     }
 
index 826ae36d2d100f7cbc1d0e2b6bc9b805f507986d..fd81f93242b89e5cc8a31c8d547012424ce48697 100644 (file)
@@ -7,7 +7,10 @@
 
 #[derive(Copy, Clone)]
 pub struct Argument {
+    #[cfg(bootstrap)]
     pub position: Position,
+    #[cfg(not(bootstrap))]
+    pub position: usize,
     pub format: FormatSpec,
 }
 
@@ -37,12 +40,11 @@ pub enum Alignment {
 pub enum Count {
     Is(usize),
     Param(usize),
-    NextParam,
     Implied,
 }
 
+#[cfg(bootstrap)]
 #[derive(Copy, Clone)]
 pub enum Position {
-    Next,
     At(usize),
 }
index a65d47cc2c1f00805baba5b8be57965425fc46aa..25dfc573e416abd38a0a9c3e23ae12812e2566b9 100644 (file)
@@ -208,6 +208,11 @@ pub fn repeat_with<A, F: FnMut() -> A>(repeater: F) -> RepeatWith<F> {
 #[stable(feature = "iter_empty", since = "1.2.0")]
 pub struct Empty<T>(marker::PhantomData<T>);
 
+#[stable(feature = "iter_empty_send_sync", since = "1.42.0")]
+unsafe impl<T> Send for Empty<T> {}
+#[stable(feature = "iter_empty_send_sync", since = "1.42.0")]
+unsafe impl<T> Sync for Empty<T> {}
+
 #[stable(feature = "core_impl_debug", since = "1.9.0")]
 impl<T> fmt::Debug for Empty<T> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
index 15720ddcfc677f19a5f358fb0d9f37576866be3f..f77b4d7461e74a164f6df4982150c2854f1f5742 100644 (file)
 #![feature(associated_type_bounds)]
 #![feature(const_type_id)]
 #![feature(const_caller_location)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 
 #[prelude_import]
 #[allow(unused)]
index d7b351f13458ac2c18095221d9d7650c50b28db0..c1976868bf7607698803b7b947adedba30fb60cc 100644 (file)
 /// i.e., you do not usually have to worry about such issues unless you call `drop_in_place`
 /// manually.
 #[stable(feature = "drop_in_place", since = "1.8.0")]
-#[inline(always)]
-pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
-    real_drop_in_place(&mut *to_drop)
-}
-
-// The real `drop_in_place` -- the one that gets called implicitly when variables go
-// out of scope -- should have a safe reference and not a raw pointer as argument
-// type.  When we drop a local variable, we access it with a pointer that behaves
-// like a safe reference; transmuting that to a raw pointer does not mean we can
-// actually access it with raw pointers.
 #[lang = "drop_in_place"]
 #[allow(unconditional_recursion)]
-unsafe fn real_drop_in_place<T: ?Sized>(to_drop: &mut T) {
+pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
     // Code here does not matter - this is replaced by the
     // real drop glue by the compiler.
-    real_drop_in_place(to_drop)
+    drop_in_place(to_drop)
 }
 
 /// Creates a null raw pointer.
index 8a1fb9de54667db0b7e1c96e9d9e1f7c8b6567f1..88b2bc551b7d1138e136ff4cf49d95ea63d3e804 100644 (file)
@@ -3,8 +3,6 @@
 use crate::mem;
 use crate::str as core_str;
 
-// ignore-tidy-undocumented-unsafe
-
 /// Lossy UTF-8 string.
 #[unstable(feature = "str_internals", issue = "none")]
 pub struct Utf8Lossy {
@@ -17,6 +15,7 @@ pub fn from_str(s: &str) -> &Utf8Lossy {
     }
 
     pub fn from_bytes(bytes: &[u8]) -> &Utf8Lossy {
+        // SAFETY: Both use the same memory layout, and UTF-8 correctness isn't required.
         unsafe { mem::transmute(bytes) }
     }
 
@@ -60,6 +59,8 @@ fn safe_get(xs: &[u8], i: usize) -> u8 {
         while i < self.source.len() {
             let i_ = i;
 
+            // SAFETY: `i` starts at `0`, is less than `self.source.len()`, and
+            // only increases, so `0 <= i < self.source.len()`.
             let byte = unsafe { *self.source.get_unchecked(i) };
             i += 1;
 
@@ -69,6 +70,7 @@ fn safe_get(xs: &[u8], i: usize) -> u8 {
 
                 macro_rules! error {
                     () => {{
+                        // SAFETY: We have checked up to `i` that source is valid UTF-8.
                         unsafe {
                             let r = Utf8LossyChunk {
                                 valid: core_str::from_utf8_unchecked(&self.source[0..i_]),
@@ -130,6 +132,7 @@ macro_rules! error {
         }
 
         let r = Utf8LossyChunk {
+            // SAFETY: We have checked that the entire source is valid UTF-8.
             valid: unsafe { core_str::from_utf8_unchecked(self.source) },
             broken: &[],
         };
index ab771b1164bada9cac464668ce8ab02b5755636d..5a7cddd4041d500200ec22071f1b176ab46bce30 100644 (file)
@@ -1,5 +1,4 @@
 // ignore-tidy-filelength
-// ignore-tidy-undocumented-unsafe
 
 //! String manipulation.
 //!
@@ -341,6 +340,7 @@ pub fn error_len(&self) -> Option<usize> {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
     run_utf8_validation(v)?;
+    // SAFETY: Just ran validation.
     Ok(unsafe { from_utf8_unchecked(v) })
 }
 
@@ -379,6 +379,7 @@ pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
 #[stable(feature = "str_mut_extras", since = "1.20.0")]
 pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
     run_utf8_validation(v)?;
+    // SAFETY: Just ran validation.
     Ok(unsafe { from_utf8_unchecked_mut(v) })
 }
 
@@ -581,7 +582,7 @@ impl<'a> Iterator for Chars<'a> {
     #[inline]
     fn next(&mut self) -> Option<char> {
         next_code_point(&mut self.iter).map(|ch| {
-            // str invariant says `ch` is a valid Unicode Scalar Value
+            // SAFETY: `str` invariant says `ch` is a valid Unicode Scalar Value.
             unsafe { char::from_u32_unchecked(ch) }
         })
     }
@@ -628,7 +629,7 @@ impl<'a> DoubleEndedIterator for Chars<'a> {
     #[inline]
     fn next_back(&mut self) -> Option<char> {
         next_code_point_reverse(&mut self.iter).map(|ch| {
-            // str invariant says `ch` is a valid Unicode Scalar Value
+            // SAFETY: `str` invariant says `ch` is a valid Unicode Scalar Value.
             unsafe { char::from_u32_unchecked(ch) }
         })
     }
@@ -658,6 +659,7 @@ impl<'a> Chars<'a> {
     #[stable(feature = "iter_to_slice", since = "1.4.0")]
     #[inline]
     pub fn as_str(&self) -> &'a str {
+        // SAFETY: `Chars` is only made from a str, which guarantees the iter is valid UTF-8.
         unsafe { from_utf8_unchecked(self.iter.as_slice()) }
     }
 }
@@ -1102,6 +1104,7 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> {
     fn get_end(&mut self) -> Option<&'a str> {
         if !self.finished && (self.allow_trailing_empty || self.end - self.start > 0) {
             self.finished = true;
+            // SAFETY: `self.start` and `self.end` always lie on unicode boundaries.
             unsafe {
                 let string = self.matcher.haystack().get_unchecked(self.start..self.end);
                 Some(string)
@@ -1119,6 +1122,7 @@ fn next(&mut self) -> Option<&'a str> {
 
         let haystack = self.matcher.haystack();
         match self.matcher.next_match() {
+            // SAFETY: `Searcher` guarantees that `a` and `b` lie on unicode boundaries.
             Some((a, b)) => unsafe {
                 let elt = haystack.get_unchecked(self.start..a);
                 self.start = b;
@@ -1151,11 +1155,13 @@ fn next_back(&mut self) -> Option<&'a str>
 
         let haystack = self.matcher.haystack();
         match self.matcher.next_match_back() {
+            // SAFETY: `Searcher` guarantees that `a` and `b` lie on unicode boundaries.
             Some((a, b)) => unsafe {
                 let elt = haystack.get_unchecked(b..self.end);
                 self.end = a;
                 Some(elt)
             },
+            // SAFETY: `self.start` and `self.end` always lie on unicode boundaries.
             None => unsafe {
                 self.finished = true;
                 Some(haystack.get_unchecked(self.start..self.end))
@@ -1297,6 +1303,7 @@ impl<'a, P: Pattern<'a>> MatchIndicesInternal<'a, P> {
     fn next(&mut self) -> Option<(usize, &'a str)> {
         self.0
             .next_match()
+            // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries.
             .map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) })
     }
 
@@ -1307,6 +1314,7 @@ fn next_back(&mut self) -> Option<(usize, &'a str)>
     {
         self.0
             .next_match_back()
+            // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries.
             .map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) })
     }
 }
@@ -1348,6 +1356,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 impl<'a, P: Pattern<'a>> MatchesInternal<'a, P> {
     #[inline]
     fn next(&mut self) -> Option<&'a str> {
+        // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries.
         self.0.next_match().map(|(a, b)| unsafe {
             // Indices are known to be on utf8 boundaries
             self.0.haystack().get_unchecked(a..b)
@@ -1359,6 +1368,7 @@ fn next_back(&mut self) -> Option<&'a str>
     where
         P::Searcher: ReverseSearcher<'a>,
     {
+        // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries.
         self.0.next_match_back().map(|(a, b)| unsafe {
             // Indices are known to be on utf8 boundaries
             self.0.haystack().get_unchecked(a..b)
@@ -1579,6 +1589,10 @@ macro_rules! next {
             if align != usize::max_value() && align.wrapping_sub(index) % usize_bytes == 0 {
                 let ptr = v.as_ptr();
                 while index < blocks_end {
+                    // SAFETY: since `align - index` and `ascii_block_size` are
+                    // multiples of `usize_bytes`, `block = ptr.add(index)` is
+                    // always aligned with a `usize` so it's safe to dereference
+                    // both `block` and `block.offset(1)`.
                     unsafe {
                         let block = ptr.add(index) as *const usize;
                         // break if there is a nonascii byte
@@ -1804,6 +1818,7 @@ fn get(self, slice: &str) -> Option<&Self::Output> {
                 && slice.is_char_boundary(self.start)
                 && slice.is_char_boundary(self.end)
             {
+                // SAFETY: just checked that `start` and `end` are on a char boundary.
                 Some(unsafe { self.get_unchecked(slice) })
             } else {
                 None
@@ -1815,6 +1830,7 @@ fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
                 && slice.is_char_boundary(self.start)
                 && slice.is_char_boundary(self.end)
             {
+                // SAFETY: just checked that `start` and `end` are on a char boundary.
                 Some(unsafe { self.get_unchecked_mut(slice) })
             } else {
                 None
@@ -1845,6 +1861,7 @@ fn index_mut(self, slice: &mut str) -> &mut Self::Output {
                 && slice.is_char_boundary(self.start)
                 && slice.is_char_boundary(self.end)
             {
+                // SAFETY: just checked that `start` and `end` are on a char boundary.
                 unsafe { self.get_unchecked_mut(slice) }
             } else {
                 super::slice_error_fail(slice, self.start, self.end)
@@ -1873,6 +1890,7 @@ impl SliceIndex<str> for ops::RangeTo<usize> {
         #[inline]
         fn get(self, slice: &str) -> Option<&Self::Output> {
             if slice.is_char_boundary(self.end) {
+                // SAFETY: just checked that `end` is on a char boundary.
                 Some(unsafe { self.get_unchecked(slice) })
             } else {
                 None
@@ -1881,6 +1899,7 @@ fn get(self, slice: &str) -> Option<&Self::Output> {
         #[inline]
         fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
             if slice.is_char_boundary(self.end) {
+                // SAFETY: just checked that `end` is on a char boundary.
                 Some(unsafe { self.get_unchecked_mut(slice) })
             } else {
                 None
@@ -1903,8 +1922,8 @@ fn index(self, slice: &str) -> &Self::Output {
         }
         #[inline]
         fn index_mut(self, slice: &mut str) -> &mut Self::Output {
-            // is_char_boundary checks that the index is in [0, .len()]
             if slice.is_char_boundary(self.end) {
+                // SAFETY: just checked that `end` is on a char boundary.
                 unsafe { self.get_unchecked_mut(slice) }
             } else {
                 super::slice_error_fail(slice, 0, self.end)
@@ -1934,6 +1953,7 @@ impl SliceIndex<str> for ops::RangeFrom<usize> {
         #[inline]
         fn get(self, slice: &str) -> Option<&Self::Output> {
             if slice.is_char_boundary(self.start) {
+                // SAFETY: just checked that `start` is on a char boundary.
                 Some(unsafe { self.get_unchecked(slice) })
             } else {
                 None
@@ -1942,6 +1962,7 @@ fn get(self, slice: &str) -> Option<&Self::Output> {
         #[inline]
         fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
             if slice.is_char_boundary(self.start) {
+                // SAFETY: just checked that `start` is on a char boundary.
                 Some(unsafe { self.get_unchecked_mut(slice) })
             } else {
                 None
@@ -1966,8 +1987,8 @@ fn index(self, slice: &str) -> &Self::Output {
         }
         #[inline]
         fn index_mut(self, slice: &mut str) -> &mut Self::Output {
-            // is_char_boundary checks that the index is in [0, .len()]
             if slice.is_char_boundary(self.start) {
+                // SAFETY: just checked that `start` is on a char boundary.
                 unsafe { self.get_unchecked_mut(slice) }
             } else {
                 super::slice_error_fail(slice, self.start, slice.len())
@@ -2238,7 +2259,6 @@ pub fn is_char_boundary(&self, index: usize) -> bool {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "str_as_bytes", since = "1.32.0")]
     #[inline(always)]
-    // SAFETY: const sound because we transmute two types with the same layout
     #[allow(unused_attributes)]
     #[allow_internal_unstable(const_fn_union)]
     pub const fn as_bytes(&self) -> &[u8] {
@@ -2247,6 +2267,7 @@ union Slices<'a> {
             str: &'a str,
             slice: &'a [u8],
         }
+        // SAFETY: const sound because we transmute two types with the same layout
         unsafe { Slices { str: self }.slice }
     }
 
@@ -2573,6 +2594,7 @@ pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut s
     pub fn split_at(&self, mid: usize) -> (&str, &str) {
         // is_char_boundary checks that the index is in [0, .len()]
         if self.is_char_boundary(mid) {
+            // SAFETY: just checked that `mid` is on a char boundary.
             unsafe { (self.get_unchecked(0..mid), self.get_unchecked(mid..self.len())) }
         } else {
             slice_error_fail(self, 0, mid)
@@ -2617,6 +2639,7 @@ pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
         if self.is_char_boundary(mid) {
             let len = self.len();
             let ptr = self.as_mut_ptr();
+            // SAFETY: just checked that `mid` is on a char boundary.
             unsafe {
                 (
                     from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, mid)),
@@ -3805,10 +3828,8 @@ pub fn trim_matches<'a, P>(&'a self, pat: P) -> &'a str
         if let Some((_, b)) = matcher.next_reject_back() {
             j = b;
         }
-        unsafe {
-            // Searcher is known to return valid indices
-            self.get_unchecked(i..j)
-        }
+        // SAFETY: `Searcher` is known to return valid indices.
+        unsafe { self.get_unchecked(i..j) }
     }
 
     /// Returns a string slice with all prefixes that match a pattern
@@ -3844,10 +3865,8 @@ pub fn trim_start_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
         if let Some((a, _)) = matcher.next_reject() {
             i = a;
         }
-        unsafe {
-            // Searcher is known to return valid indices
-            self.get_unchecked(i..self.len())
-        }
+        // SAFETY: `Searcher` is known to return valid indices.
+        unsafe { self.get_unchecked(i..self.len()) }
     }
 
     /// Returns a string slice with the prefix removed.
@@ -3878,10 +3897,8 @@ pub fn strip_prefix<'a, P: Pattern<'a>>(&'a self, prefix: P) -> Option<&'a str>
                 "The first search step from Searcher \
                 must include the first character"
             );
-            unsafe {
-                // Searcher is known to return valid indices.
-                Some(self.get_unchecked(len..))
-            }
+            // SAFETY: `Searcher` is known to return valid indices.
+            unsafe { Some(self.get_unchecked(len..)) }
         } else {
             None
         }
@@ -3919,10 +3936,8 @@ pub fn strip_suffix<'a, P>(&'a self, suffix: P) -> Option<&'a str>
                 "The first search step from ReverseSearcher \
                 must include the last character"
             );
-            unsafe {
-                // Searcher is known to return valid indices.
-                Some(self.get_unchecked(..start))
-            }
+            // SAFETY: `Searcher` is known to return valid indices.
+            unsafe { Some(self.get_unchecked(..start)) }
         } else {
             None
         }
@@ -3970,10 +3985,8 @@ pub fn trim_end_matches<'a, P>(&'a self, pat: P) -> &'a str
         if let Some((_, b)) = matcher.next_reject_back() {
             j = b;
         }
-        unsafe {
-            // Searcher is known to return valid indices
-            self.get_unchecked(0..j)
-        }
+        // SAFETY: `Searcher` is known to return valid indices.
+        unsafe { self.get_unchecked(0..j) }
     }
 
     /// Returns a string slice with all prefixes that match a pattern
@@ -4166,6 +4179,7 @@ pub fn eq_ignore_ascii_case(&self, other: &str) -> bool {
     /// ```
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
     pub fn make_ascii_uppercase(&mut self) {
+        // SAFETY: safe because we transmute two types with the same layout.
         let me = unsafe { self.as_bytes_mut() };
         me.make_ascii_uppercase()
     }
@@ -4191,6 +4205,7 @@ pub fn make_ascii_uppercase(&mut self) {
     /// ```
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
     pub fn make_ascii_lowercase(&mut self) {
+        // SAFETY: safe because we transmute two types with the same layout.
         let me = unsafe { self.as_bytes_mut() };
         me.make_ascii_lowercase()
     }
@@ -4357,6 +4372,7 @@ fn default() -> Self {
 impl Default for &mut str {
     /// Creates an empty mutable str
     fn default() -> Self {
+        // SAFETY: The empty string is valid UTF-8.
         unsafe { from_utf8_unchecked_mut(&mut []) }
     }
 }
@@ -4412,6 +4428,7 @@ struct BytesIsNotEmpty impl<'a, 'b> Fn = |s: &'a &'b [u8]| -> bool {
 
     #[derive(Clone)]
     struct UnsafeBytesToStr impl<'a> Fn = |bytes: &'a [u8]| -> &'a str {
+        // SAFETY: not safe
         unsafe { from_utf8_unchecked(bytes) }
     };
 }
index 46d9499394a381c33eb8450ecb16a57b5739247e..ef64d8b0fdf8880883ee168c22a5e0164c72fea7 100644 (file)
@@ -3,8 +3,6 @@
 //! For more details, see the traits [`Pattern`], [`Searcher`],
 //! [`ReverseSearcher`], and [`DoubleEndedSearcher`].
 
-// ignore-tidy-undocumented-unsafe
-
 #![unstable(
     feature = "pattern",
     reason = "API not fully fleshed out and ready to be stabilized",
@@ -271,6 +269,14 @@ fn haystack(&self) -> &'a str {
     #[inline]
     fn next(&mut self) -> SearchStep {
         let old_finger = self.finger;
+        // SAFETY: 1-4 guarantee safety of `get_unchecked`
+        // 1. `self.finger` and `self.finger_back` are kept on unicode boundaries
+        //    (this is invariant)
+        // 2. `self.finger >= 0` since it starts at 0 and only increases
+        // 3. `self.finger < self.finger_back` because otherwise the char `iter`
+        //    would return `SearchStep::Done`
+        // 4. `self.finger` comes before the end of the haystack because `self.finger_back`
+        //    starts at the end and only decreases
         let slice = unsafe { self.haystack.get_unchecked(old_finger..self.finger_back) };
         let mut iter = slice.chars();
         let old_len = iter.iter.len();
@@ -293,6 +299,7 @@ fn next_match(&mut self) -> Option<(usize, usize)> {
             // get the haystack after the last character found
             let bytes = self.haystack.as_bytes().get(self.finger..self.finger_back)?;
             // the last byte of the utf8 encoded needle
+            // SAFETY: we have an invariant that `utf8_size < 5`
             let last_byte = unsafe { *self.utf8_encoded.get_unchecked(self.utf8_size - 1) };
             if let Some(index) = memchr::memchr(last_byte, bytes) {
                 // The new finger is the index of the byte we found,
@@ -336,6 +343,7 @@ unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> {
     #[inline]
     fn next_back(&mut self) -> SearchStep {
         let old_finger = self.finger_back;
+        // SAFETY: see the comment for next() above
         let slice = unsafe { self.haystack.get_unchecked(self.finger..old_finger) };
         let mut iter = slice.chars();
         let old_len = iter.iter.len();
@@ -363,6 +371,7 @@ fn next_match_back(&mut self) -> Option<(usize, usize)> {
                 return None;
             };
             // the last byte of the utf8 encoded needle
+            // SAFETY: we have an invariant that `utf8_size < 5`
             let last_byte = unsafe { *self.utf8_encoded.get_unchecked(self.utf8_size - 1) };
             if let Some(index) = memchr::memrchr(last_byte, bytes) {
                 // we searched a slice that was offset by self.finger,
index fae95ca5cdb36ba4182343e308d7c53f05bf810d..9d449bb9915071e3453af165045684d205cbacc9 100644 (file)
 //! println!("live threads: {}", old_thread_count + 1);
 //! ```
 
-// ignore-tidy-undocumented-unsafe
-
 #![stable(feature = "rust1", since = "1.0.0")]
 #![cfg_attr(not(target_has_atomic_load_store = "8"), allow(dead_code))]
 #![cfg_attr(not(target_has_atomic_load_store = "8"), allow(unused_imports))]
@@ -350,6 +348,7 @@ pub const fn new(v: bool) -> AtomicBool {
     #[inline]
     #[stable(feature = "atomic_access", since = "1.15.0")]
     pub fn get_mut(&mut self) -> &mut bool {
+        // SAFETY: the mutable reference guarantees unique ownership.
         unsafe { &mut *(self.v.get() as *mut bool) }
     }
 
@@ -400,6 +399,8 @@ pub fn into_inner(self) -> bool {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn load(&self, order: Ordering) -> bool {
+        // SAFETY: any data races are prevented by atomic intrinsics and the raw
+        // pointer passed in is valid because we got it from a reference.
         unsafe { atomic_load(self.v.get(), order) != 0 }
     }
 
@@ -432,6 +433,8 @@ pub fn load(&self, order: Ordering) -> bool {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn store(&self, val: bool, order: Ordering) {
+        // SAFETY: any data races are prevented by atomic intrinsics and the raw
+        // pointer passed in is valid because we got it from a reference.
         unsafe {
             atomic_store(self.v.get(), val as u8, order);
         }
@@ -463,6 +466,7 @@ pub fn store(&self, val: bool, order: Ordering) {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[cfg(target_has_atomic = "8")]
     pub fn swap(&self, val: bool, order: Ordering) -> bool {
+        // SAFETY: data races are prevented by atomic intrinsics.
         unsafe { atomic_swap(self.v.get(), val as u8, order) != 0 }
     }
 
@@ -558,6 +562,7 @@ pub fn compare_exchange(
         success: Ordering,
         failure: Ordering,
     ) -> Result<bool, bool> {
+        // SAFETY: data races are prevented by atomic intrinsics.
         match unsafe {
             atomic_compare_exchange(self.v.get(), current as u8, new as u8, success, failure)
         } {
@@ -615,6 +620,7 @@ pub fn compare_exchange_weak(
         success: Ordering,
         failure: Ordering,
     ) -> Result<bool, bool> {
+        // SAFETY: data races are prevented by atomic intrinsics.
         match unsafe {
             atomic_compare_exchange_weak(self.v.get(), current as u8, new as u8, success, failure)
         } {
@@ -661,6 +667,7 @@ pub fn compare_exchange_weak(
     #[stable(feature = "rust1", since = "1.0.0")]
     #[cfg(target_has_atomic = "8")]
     pub fn fetch_and(&self, val: bool, order: Ordering) -> bool {
+        // SAFETY: data races are prevented by atomic intrinsics.
         unsafe { atomic_and(self.v.get(), val as u8, order) != 0 }
     }
 
@@ -756,6 +763,7 @@ pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[cfg(target_has_atomic = "8")]
     pub fn fetch_or(&self, val: bool, order: Ordering) -> bool {
+        // SAFETY: data races are prevented by atomic intrinsics.
         unsafe { atomic_or(self.v.get(), val as u8, order) != 0 }
     }
 
@@ -797,6 +805,7 @@ pub fn fetch_or(&self, val: bool, order: Ordering) -> bool {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[cfg(target_has_atomic = "8")]
     pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool {
+        // SAFETY: data races are prevented by atomic intrinsics.
         unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 }
     }
 
@@ -872,6 +881,7 @@ pub const fn new(p: *mut T) -> AtomicPtr<T> {
     #[inline]
     #[stable(feature = "atomic_access", since = "1.15.0")]
     pub fn get_mut(&mut self) -> &mut *mut T {
+        // SAFETY: the mutable reference guarantees unique ownership.
         unsafe { &mut *self.p.get() }
     }
 
@@ -923,6 +933,7 @@ pub fn into_inner(self) -> *mut T {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn load(&self, order: Ordering) -> *mut T {
+        // SAFETY: data races are prevented by atomic intrinsics.
         unsafe { atomic_load(self.p.get() as *mut usize, order) as *mut T }
     }
 
@@ -957,6 +968,7 @@ pub fn load(&self, order: Ordering) -> *mut T {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn store(&self, ptr: *mut T, order: Ordering) {
+        // SAFETY: data races are prevented by atomic intrinsics.
         unsafe {
             atomic_store(self.p.get() as *mut usize, ptr as usize, order);
         }
@@ -990,6 +1002,7 @@ pub fn store(&self, ptr: *mut T, order: Ordering) {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[cfg(target_has_atomic = "ptr")]
     pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
+        // SAFETY: data races are prevented by atomic intrinsics.
         unsafe { atomic_swap(self.p.get() as *mut usize, ptr as usize, order) as *mut T }
     }
 
@@ -1074,6 +1087,7 @@ pub fn compare_exchange(
         success: Ordering,
         failure: Ordering,
     ) -> Result<*mut T, *mut T> {
+        // SAFETY: data races are prevented by atomic intrinsics.
         unsafe {
             let res = atomic_compare_exchange(
                 self.p.get() as *mut usize,
@@ -1137,6 +1151,7 @@ pub fn compare_exchange_weak(
         success: Ordering,
         failure: Ordering,
     ) -> Result<*mut T, *mut T> {
+        // SAFETY: data races are prevented by atomic intrinsics.
         unsafe {
             let res = atomic_compare_exchange_weak(
                 self.p.get() as *mut usize,
@@ -1290,6 +1305,7 @@ pub const fn new(v: $int_type) -> Self {
                 #[inline]
                 #[$stable_access]
                 pub fn get_mut(&mut self) -> &mut $int_type {
+                    // SAFETY: the mutable reference guarantees unique ownership.
                     unsafe { &mut *self.v.get() }
                 }
             }
@@ -1344,6 +1360,7 @@ pub fn into_inner(self) -> $int_type {
                 #[inline]
                 #[$stable]
                 pub fn load(&self, order: Ordering) -> $int_type {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { atomic_load(self.v.get(), order) }
                 }
             }
@@ -1378,6 +1395,7 @@ pub fn load(&self, order: Ordering) -> $int_type {
                 #[inline]
                 #[$stable]
                 pub fn store(&self, val: $int_type, order: Ordering) {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { atomic_store(self.v.get(), val, order); }
                 }
             }
@@ -1408,6 +1426,7 @@ pub fn store(&self, val: $int_type, order: Ordering) {
                 #[$stable]
                 #[$cfg_cas]
                 pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { atomic_swap(self.v.get(), val, order) }
                 }
             }
@@ -1510,6 +1529,7 @@ pub fn compare_exchange(&self,
                                         new: $int_type,
                                         success: Ordering,
                                         failure: Ordering) -> Result<$int_type, $int_type> {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) }
                 }
             }
@@ -1562,6 +1582,7 @@ pub fn compare_exchange_weak(&self,
                                              new: $int_type,
                                              success: Ordering,
                                              failure: Ordering) -> Result<$int_type, $int_type> {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe {
                         atomic_compare_exchange_weak(self.v.get(), current, new, success, failure)
                     }
@@ -1596,6 +1617,7 @@ pub fn compare_exchange_weak(&self,
                 #[$stable]
                 #[$cfg_cas]
                 pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { atomic_add(self.v.get(), val, order) }
                 }
             }
@@ -1628,6 +1650,7 @@ pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type {
                 #[$stable]
                 #[$cfg_cas]
                 pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { atomic_sub(self.v.get(), val, order) }
                 }
             }
@@ -1663,6 +1686,7 @@ pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type {
                 #[$stable]
                 #[$cfg_cas]
                 pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { atomic_and(self.v.get(), val, order) }
                 }
             }
@@ -1699,6 +1723,7 @@ pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type {
                 #[$stable_nand]
                 #[$cfg_cas]
                 pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { atomic_nand(self.v.get(), val, order) }
                 }
             }
@@ -1734,6 +1759,7 @@ pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type {
                 #[$stable]
                 #[$cfg_cas]
                 pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { atomic_or(self.v.get(), val, order) }
                 }
             }
@@ -1769,6 +1795,7 @@ pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type {
                 #[$stable]
                 #[$cfg_cas]
                 pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { atomic_xor(self.v.get(), val, order) }
                 }
             }
@@ -1880,6 +1907,7 @@ pub fn fetch_update<F>(&self,
                        issue = "48655")]
                 #[$cfg_cas]
                 pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { $max_fn(self.v.get(), val, order) }
                 }
             }
@@ -1932,6 +1960,7 @@ pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type {
                        issue = "48655")]
                 #[$cfg_cas]
                 pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
+                    // SAFETY: data races are prevented by atomic intrinsics.
                     unsafe { $min_fn(self.v.get(), val, order) }
                 }
             }
@@ -1960,7 +1989,9 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
 }
 
 let mut atomic = ", stringify!($atomic_type), "::new(1);
-unsafe {
+",
+// SAFETY: Safe as long as `my_atomic_op` is atomic.
+"unsafe {
     my_atomic_op(atomic.as_mut_ptr());
 }
 # }
@@ -2526,6 +2557,7 @@ pub fn fence(order: Ordering) {
     // 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"))]
+    // SAFETY: using an atomic fence is safe.
     unsafe {
         match order {
             Acquire => intrinsics::atomic_fence_acq(),
@@ -2613,6 +2645,7 @@ pub fn fence(order: Ordering) {
 #[inline]
 #[stable(feature = "compiler_fences", since = "1.21.0")]
 pub fn compiler_fence(order: Ordering) {
+    // SAFETY: using an atomic fence is safe.
     unsafe {
         match order {
             Acquire => intrinsics::atomic_singlethreadfence_acq(),
index 90a9bccda15800022286157e17faa035a24893b4..129c121e8ceac0f5cd0974a9b15832a14445c5a2 100644 (file)
@@ -89,6 +89,91 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         baz: 10/20,
     },
     hello: \"world\",
+}",
+            format!("{:#?}", Bar)
+        );
+    }
+
+    #[test]
+    fn test_only_non_exhaustive() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_struct("Foo").finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!("Foo { .. }", format!("{:?}", Foo));
+        assert_eq!(
+            "Foo {
+    ..
+}",
+            format!("{:#?}", Foo)
+        );
+    }
+
+    #[test]
+    fn test_multiple_and_non_exhaustive() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_struct("Foo")
+                    .field("bar", &true)
+                    .field("baz", &format_args!("{}/{}", 10, 20))
+                    .finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!("Foo { bar: true, baz: 10/20, .. }", format!("{:?}", Foo));
+        assert_eq!(
+            "Foo {
+    bar: true,
+    baz: 10/20,
+    ..
+}",
+            format!("{:#?}", Foo)
+        );
+    }
+
+    #[test]
+    fn test_nested_non_exhaustive() {
+        struct Foo;
+
+        impl fmt::Debug for Foo {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_struct("Foo")
+                    .field("bar", &true)
+                    .field("baz", &format_args!("{}/{}", 10, 20))
+                    .finish_non_exhaustive()
+            }
+        }
+
+        struct Bar;
+
+        impl fmt::Debug for Bar {
+            fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+                fmt.debug_struct("Bar")
+                    .field("foo", &Foo)
+                    .field("hello", &"world")
+                    .finish_non_exhaustive()
+            }
+        }
+
+        assert_eq!(
+            "Bar { foo: Foo { bar: true, baz: 10/20, .. }, hello: \"world\", .. }",
+            format!("{:?}", Bar)
+        );
+        assert_eq!(
+            "Bar {
+    foo: Foo {
+        bar: true,
+        baz: 10/20,
+        ..
+    },
+    hello: \"world\",
+    ..
 }",
             format!("{:#?}", Bar)
         );
index 86cf6fc104c8390bc19e5a3baa4c6bfabd94763d..f0420247acfbd0337ce7f3000bdc7c2127240dce 100644 (file)
@@ -5,6 +5,7 @@
 #![feature(core_private_bignum)]
 #![feature(core_private_diy_float)]
 #![feature(debug_map_key_value)]
+#![feature(debug_non_exhaustive)]
 #![feature(dec2flt)]
 #![feature(exact_size_is_empty)]
 #![feature(fixed_size_array)]
@@ -18,7 +19,7 @@
 #![feature(range_is_empty)]
 #![feature(raw)]
 #![feature(saturating_neg)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(sort_internals)]
 #![feature(slice_partition_at_index)]
 #![feature(specialization)]
index 323ce3b6cbb6dc8a82a4f90379c60f02a2c61d79..b65635be54a3f1a3f6d54634a5ebd9518b145d12 100644 (file)
@@ -37,5 +37,4 @@ byteorder = { version = "1.3" }
 chalk-engine = { version = "0.9.0", default-features=false }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 measureme = "0.7.1"
-rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_session = { path = "../librustc_session" }
index cb3fdff53a3b0ed16a2a245d6e79e3e36b1157cb..15e92d8d8421930d60c32929051b805f72c4d7b2 100644 (file)
@@ -123,6 +123,9 @@ macro_rules! arena_types {
             [few] inferred_outlives_crate: rustc::ty::CratePredicatesMap<'tcx>,
             [] upvars: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>,
 
+            // Interned types
+            [] tys: rustc::ty::TyS<$tcx>,
+
             // HIR types
             [few] hir_forest: rustc::hir::map::Forest<$tcx>,
             [] arm: rustc_hir::Arm<$tcx>,
@@ -176,7 +179,7 @@ macro_rules! declare_arena {
     ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
         #[derive(Default)]
         pub struct Arena<$tcx> {
-            dropless: DroplessArena,
+            pub dropless: DroplessArena,
             drop: DropArena,
             $($name: arena_for_type!($a[$ty]),)*
         }
index ffb12f11c5136fb1169e53e764210888ffd32bad..de82b262e4956137c8dd50aa4e55a3562b3e2d9b 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(test)]
 
 extern crate test;
index 5a99e7965538b2ff243d6763fe42886715964e05..86eab3d92d366466c408fc5d8f2e00bbe3cf8998 100644 (file)
@@ -8,7 +8,6 @@
 use crate::ty::query::Providers;
 use crate::ty::TyCtxt;
 
-use rustc_error_codes::*;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -112,7 +111,7 @@ pub(crate) fn from_item(item: &Item<'_>) -> Target {
             ItemKind::Union(..) => Target::Union,
             ItemKind::Trait(..) => Target::Trait,
             ItemKind::TraitAlias(..) => Target::TraitAlias,
-            ItemKind::Impl(..) => Target::Impl,
+            ItemKind::Impl { .. } => Target::Impl,
         }
     }
 
@@ -144,7 +143,7 @@ fn from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem<'_>) -> Tar
                 let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id);
                 let containing_item = tcx.hir().expect_item(parent_hir_id);
                 let containing_impl_is_for_trait = match &containing_item.kind {
-                    hir::ItemKind::Impl(_, _, _, _, tr, _, _) => tr.is_some(),
+                    hir::ItemKind::Impl { ref of_trait, .. } => of_trait.is_some(),
                     _ => bug!("parent of an ImplItem must be an Impl"),
                 };
                 if containing_impl_is_for_trait {
index 46c5ee272d2352a97077189607f01f44b5710e7d..6d7f53133a66644717a88dff7490abe35d5b9fb8 100644 (file)
@@ -341,7 +341,7 @@ pub fn def_kind(&self, hir_id: HirId) -> Option<DefKind> {
                 | ItemKind::Use(..)
                 | ItemKind::ForeignMod(..)
                 | ItemKind::GlobalAsm(..)
-                | ItemKind::Impl(..) => return None,
+                | ItemKind::Impl { .. } => return None,
             },
             Node::ForeignItem(item) => match item.kind {
                 ForeignItemKind::Fn(..) => DefKind::Fn,
@@ -604,7 +604,7 @@ pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics<'hir>> {
                 | ItemKind::Union(_, ref generics)
                 | ItemKind::Trait(_, _, ref generics, ..)
                 | ItemKind::TraitAlias(ref generics, _)
-                | ItemKind::Impl(_, _, _, ref generics, ..) => Some(generics),
+                | ItemKind::Impl { ref generics, .. } => Some(generics),
                 _ => None,
             },
             _ => None,
@@ -821,7 +821,7 @@ pub fn get_enclosing_scope(&self, hir_id: HirId) -> Option<HirId> {
                     | ItemKind::Struct(..)
                     | ItemKind::Union(..)
                     | ItemKind::Trait(..)
-                    | ItemKind::Impl(..) => true,
+                    | ItemKind::Impl { .. } => true,
                     _ => false,
                 },
                 Node::ForeignItem(fi) => match fi.kind {
@@ -1332,7 +1332,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String {
                 ItemKind::Union(..) => "union",
                 ItemKind::Trait(..) => "trait",
                 ItemKind::TraitAlias(..) => "trait alias",
-                ItemKind::Impl(..) => "impl",
+                ItemKind::Impl { .. } => "impl",
             };
             format!("{} {}{}", item_str, path_str(), id_str)
         }
index c52d4335ea184fed6496b5e1d47dfa4be0bbb5c1..77182b97fd450231634011c9609971e7d6a38c53 100644 (file)
@@ -65,7 +65,6 @@
     Region, Ty, TyCtxt, TypeFoldable,
 };
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_error_codes::*;
 use rustc_errors::{pluralize, struct_span_err};
 use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
 use rustc_hir as hir;
@@ -254,7 +253,7 @@ fn emit_msg_span(
 
 fn item_scope_tag(item: &hir::Item<'_>) -> &'static str {
     match item.kind {
-        hir::ItemKind::Impl(..) => "impl",
+        hir::ItemKind::Impl { .. } => "impl",
         hir::ItemKind::Struct(..) => "struct",
         hir::ItemKind::Union(..) => "union",
         hir::ItemKind::Enum(..) => "enum",
@@ -2008,7 +2007,7 @@ fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode {
                 TypeError::IntrinsicCast => {
                     Error0308("cannot coerce intrinsics to function pointers")
                 }
-                TypeError::ObjectUnsafeCoercion(did) => Error0038(did.clone()),
+                TypeError::ObjectUnsafeCoercion(did) => Error0038(*did),
                 _ => Error0308("mismatched types"),
             },
         }
index 70f7987faf4ccf83d202b3092143cdec2a1ca443..9947dea2340964b2c8847a1530c96c5b4717e44d 100644 (file)
@@ -13,8 +13,6 @@
 use rustc_span::Span;
 use std::borrow::Cow;
 
-use rustc_error_codes::*;
-
 struct FindLocalByTypeVisitor<'a, 'tcx> {
     infcx: &'a InferCtxt<'a, 'tcx>,
     target_ty: Ty<'tcx>,
index d6e50209f72ddf73471091869bd6d72ea42a31d6..8f4c643992001d7ed01ba8747a065e4574fe35a6 100644 (file)
@@ -5,7 +5,6 @@
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::util::common::ErrorReported;
 
-use rustc_error_codes::*;
 use rustc_errors::struct_span_err;
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
index 2344d408a43a5d39e752f4a72c09b97aeabf985c..df37f53606b37ab8e60e03801773324e51590693 100644 (file)
@@ -5,8 +5,6 @@
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir::{FunctionRetTy, TyKind};
 
-use rustc_error_codes::*;
-
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// When given a `ConcreteFailure` for a function with parameters containing a named region and
     /// an anonymous region, emit an descriptive diagnostic error.
index 6303104e39dd317e5d28aa1acf9aba320346b85d..11dda71b8cb89c9de2bb757b7b5441c5dd972ff3 100644 (file)
@@ -5,8 +5,6 @@
 use crate::ty::{self, Region};
 use rustc_errors::{struct_span_err, DiagnosticBuilder};
 
-use rustc_error_codes::*;
-
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub(super) fn note_region_origin(
         &self,
index 0bc49a290150554055f9c38bd47d6084f4014f72..18c25ef0dd9e1365b555f3259d64bf04a0a8195b 100644 (file)
@@ -19,7 +19,6 @@
     Direction, Graph, NodeIndex, INCOMING, OUTGOING,
 };
 use rustc_hir::def_id::DefId;
-use rustc_index::bit_set::BitSet;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_span::Span;
 use std::fmt;
@@ -295,62 +294,59 @@ fn enforce_member_constraint(
     }
 
     fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) {
-        let mut process_constraint = |constraint: &Constraint<'tcx>| {
-            let (a_region, b_vid, b_data, retain) = match *constraint {
+        let mut constraints = IndexVec::from_elem_n(Vec::new(), var_values.values.len());
+        let mut changes = Vec::new();
+        for constraint in self.data.constraints.keys() {
+            let (a_vid, a_region, b_vid, b_data) = match *constraint {
                 Constraint::RegSubVar(a_region, b_vid) => {
                     let b_data = var_values.value_mut(b_vid);
-                    (a_region, b_vid, b_data, false)
+                    (None, a_region, b_vid, b_data)
                 }
                 Constraint::VarSubVar(a_vid, b_vid) => match *var_values.value(a_vid) {
-                    VarValue::ErrorValue => return (false, false),
+                    VarValue::ErrorValue => continue,
                     VarValue::Value(a_region) => {
                         let b_data = var_values.value_mut(b_vid);
-                        let retain = match *b_data {
-                            VarValue::Value(ReStatic) | VarValue::ErrorValue => false,
-                            _ => true,
-                        };
-                        (a_region, b_vid, b_data, retain)
+                        (Some(a_vid), a_region, b_vid, b_data)
                     }
                 },
                 Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => {
                     // These constraints are checked after expansion
                     // is done, in `collect_errors`.
-                    return (false, false);
+                    continue;
                 }
             };
-
-            let changed = self.expand_node(a_region, b_vid, b_data);
-            (changed, retain)
-        };
-
-        // Using bitsets to track the remaining elements is faster than using a
-        // `Vec` by itself (which requires removing elements, which requires
-        // element shuffling, which is slow).
-        let constraints: Vec<_> = self.data.constraints.keys().collect();
-        let mut live_indices: BitSet<usize> = BitSet::new_filled(constraints.len());
-        let mut killed_indices: BitSet<usize> = BitSet::new_empty(constraints.len());
-        let mut changed = true;
-        while changed {
-            changed = false;
-            for index in live_indices.iter() {
-                let constraint = constraints[index];
-                let (edge_changed, retain) = process_constraint(constraint);
-                changed |= edge_changed;
-                if !retain {
-                    let changed = killed_indices.insert(index);
-                    debug_assert!(changed);
+            if self.expand_node(a_region, b_vid, b_data) {
+                changes.push(b_vid);
+            }
+            if let Some(a_vid) = a_vid {
+                match *b_data {
+                    VarValue::Value(ReStatic) | VarValue::ErrorValue => (),
+                    _ => {
+                        constraints[a_vid].push((a_vid, b_vid));
+                        constraints[b_vid].push((a_vid, b_vid));
+                    }
                 }
             }
-            live_indices.subtract(&killed_indices);
+        }
 
-            // We could clear `killed_indices` here, but we don't need to and
-            // it's cheaper not to.
+        while let Some(vid) = changes.pop() {
+            constraints[vid].retain(|&(a_vid, b_vid)| {
+                let a_region = match *var_values.value(a_vid) {
+                    VarValue::ErrorValue => return false,
+                    VarValue::Value(a_region) => a_region,
+                };
+                let b_data = var_values.value_mut(b_vid);
+                if self.expand_node(a_region, b_vid, b_data) {
+                    changes.push(b_vid);
+                }
+                match *b_data {
+                    VarValue::Value(ReStatic) | VarValue::ErrorValue => false,
+                    _ => true,
+                }
+            });
         }
     }
 
-    // This function is very hot in some workloads. There's a single callsite
-    // so always inlining is ok even though it's large.
-    #[inline(always)]
     fn expand_node(
         &self,
         a_region: Region<'tcx>,
@@ -790,8 +786,8 @@ fn region_order_key(x: &RegionAndOrigin<'_>) -> u8 {
             self.var_infos[node_idx].origin.span(),
             &format!(
                 "collect_error_for_expanding_node() could not find \
-                      error for var {:?} in universe {:?}, lower_bounds={:#?}, \
-                      upper_bounds={:#?}",
+                 error for var {:?} in universe {:?}, lower_bounds={:#?}, \
+                 upper_bounds={:#?}",
                 node_idx, node_universe, lower_bounds, upper_bounds
             ),
         );
index ee214bea7b8fc39f45968fb28f4bfec728b3405f..fe3a5d149f676264616c8886017e2e3f0a45d6a6 100644 (file)
@@ -15,8 +15,6 @@
 use rustc_hir::Node;
 use rustc_span::Span;
 
-use rustc_error_codes::*;
-
 pub type OpaqueTypeMap<'tcx> = DefIdMap<OpaqueTypeDecl<'tcx>>;
 
 /// Information about the opaque types whose values we
index b894aabd9010073f222cb5f4b7b43bce29fa75e9..69ca40636948f72e92a5dc5cf65e1be7fc7dbc59 100644 (file)
@@ -42,7 +42,7 @@
 #![feature(optin_builtin_traits)]
 #![feature(option_expect_none)]
 #![feature(range_is_empty)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(specialization)]
 #![feature(unboxed_closures)]
 #![feature(thread_local)]
index e4af54f7771eaba259de388417e3670830592b40..a349b34eb1a0c18a45dd339565a99cf5f9eb02e8 100644 (file)
@@ -32,7 +32,9 @@ pub enum ExportedSymbol<'tcx> {
 }
 
 impl<'tcx> ExportedSymbol<'tcx> {
-    pub fn symbol_name(&self, tcx: TyCtxt<'tcx>) -> ty::SymbolName {
+    /// This is the symbol name of an instance if it is instantiated in the
+    /// local crate.
+    pub fn symbol_name_for_local_instance(&self, tcx: TyCtxt<'tcx>) -> ty::SymbolName {
         match *self {
             ExportedSymbol::NonGeneric(def_id) => tcx.symbol_name(ty::Instance::mono(tcx, def_id)),
             ExportedSymbol::Generic(def_id, substs) => {
@@ -50,9 +52,22 @@ pub fn compare_stable(&self, tcx: TyCtxt<'tcx>, other: &ExportedSymbol<'tcx>) ->
                 }
                 ExportedSymbol::Generic(..) | ExportedSymbol::NoDefId(_) => cmp::Ordering::Less,
             },
-            ExportedSymbol::Generic(..) => match *other {
+            ExportedSymbol::Generic(self_def_id, self_substs) => match *other {
                 ExportedSymbol::NonGeneric(_) => cmp::Ordering::Greater,
-                ExportedSymbol::Generic(..) => self.symbol_name(tcx).cmp(&other.symbol_name(tcx)),
+                ExportedSymbol::Generic(other_def_id, other_substs) => {
+                    // We compare the symbol names because they are cached as query
+                    // results which makes them relatively cheap to access repeatedly.
+                    //
+                    // It might be even faster to build a local cache of stable IDs
+                    // for sorting. Exported symbols are really only sorted once
+                    // in order to make the `exported_symbols` query result stable.
+                    let self_symbol_name =
+                        tcx.symbol_name(ty::Instance::new(self_def_id, self_substs));
+                    let other_symbol_name =
+                        tcx.symbol_name(ty::Instance::new(other_def_id, other_substs));
+
+                    self_symbol_name.cmp(&other_symbol_name)
+                }
                 ExportedSymbol::NoDefId(_) => cmp::Ordering::Less,
             },
             ExportedSymbol::NoDefId(self_symbol_name) => match *other {
index 643359f098b4d3c5424a615f457c5a126db0f564..27b769742a9fcf34e3ba48b993e469eca38bc7e2 100644 (file)
@@ -24,8 +24,6 @@
 use rustc_span::Span;
 use syntax::ast;
 
-use rustc_error_codes::*;
-
 // The actual lang items defined come at the end of this file in one handy table.
 // So you probably just want to nip down to the end.
 macro_rules! language_item_table {
index fdffd1251ce8f747f73ed6bc785b187741b29964..5571f8f2313d56f0d8e0dae37ed41527bfa52847 100644 (file)
@@ -15,8 +15,6 @@
 use rustc_target::spec::PanicStrategy;
 use syntax::ast;
 
-use rustc_error_codes::*;
-
 macro_rules! weak_lang_items {
     ($($name:ident, $item:ident, $sym:ident;)*) => (
 
index 8643bd63d8cba29e9ab99dbf4e14fcba938c2ed1..349dbd74ad1c9a271f3e0509e90470d56582ab63 100644 (file)
@@ -16,8 +16,6 @@
 use rustc_target::spec::abi::Abi;
 use std::{any::Any, env, fmt};
 
-use rustc_error_codes::*;
-
 #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)]
 pub enum ErrorHandled {
     /// Already reported a lint or an error for this evaluation.
@@ -33,7 +31,7 @@ pub fn assert_reported(self) {
             ErrorHandled::Reported => {}
             ErrorHandled::TooGeneric => bug!(
                 "MIR interpretation failed without reporting an error \
-                                              even though it was fully monomorphized"
+                 even though it was fully monomorphized"
             ),
         }
     }
index 47f067590b9d5e0803928734380999f45327a7a9..e554b280ef78cbc8723d559869c455a66a847fb4 100644 (file)
@@ -403,8 +403,8 @@ pub fn reserve(&mut self) -> AllocId {
         let next = self.next_id;
         self.next_id.0 = self.next_id.0.checked_add(1).expect(
             "You overflowed a u64 by incrementing by 1... \
-                     You've just earned yourself a free drink if we ever meet. \
-                     Seriously, how did you do that?!",
+             You've just earned yourself a free drink if we ever meet. \
+             Seriously, how did you do that?!",
         );
         next
     }
index f4c262fbac1d47d40b8d25b451f2c947761baab2..deb2d6ac630ac57534958e583400dcbd5e984ab8 100644 (file)
@@ -557,6 +557,9 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
             desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) }
         }
 
+        /// The `symbol_name` query provides the symbol name for calling a
+        /// given instance from the local crate. In particular, it will also
+        /// look up the correct symbol name of instances from upstream crates.
         query symbol_name(key: ty::Instance<'tcx>) -> ty::SymbolName {
             no_force
             desc { "computing the symbol for `{}`", key }
@@ -971,6 +974,11 @@ fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String {
     }
 
     Linking {
+        /// The list of symbols exported from the given crate.
+        ///
+        /// - All names contained in `exported_symbols(cnum)` are guaranteed to
+        ///   correspond to a publicly visible symbol in `cnum` machine code.
+        /// - The `exported_symbols` sets of different crates do not intersect.
         query exported_symbols(_: CrateNum)
             -> Arc<Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)>> {
             desc { "exported_symbols" }
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
deleted file mode 100644 (file)
index 7f151af..0000000
+++ /dev/null
@@ -1,2991 +0,0 @@
-use super::{
-    ConstEvalFailure, EvaluationResult, FulfillmentError, FulfillmentErrorCode,
-    MismatchedProjectionTypes, ObjectSafetyViolation, Obligation, ObligationCause,
-    ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote,
-    OutputTypeParameterMismatch, Overflow, PredicateObligation, SelectionContext, SelectionError,
-    TraitNotObjectSafe,
-};
-
-use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
-use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use crate::infer::{self, InferCtxt};
-use crate::mir::interpret::ErrorHandled;
-use crate::session::DiagnosticMessageId;
-use crate::traits::object_safety_violations;
-use crate::ty::error::ExpectedFound;
-use crate::ty::fast_reject;
-use crate::ty::fold::TypeFolder;
-use crate::ty::subst::Subst;
-use crate::ty::GenericParamDefKind;
-use crate::ty::SubtypePredicate;
-use crate::ty::TypeckTables;
-use crate::ty::{self, AdtKind, DefIdTree, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
-
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style};
-use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_hir::Node;
-use rustc_span::source_map::SourceMap;
-use rustc_span::symbol::{kw, sym};
-use rustc_span::{ExpnKind, MultiSpan, Span, DUMMY_SP};
-use std::fmt;
-use syntax::ast;
-
-use rustc_error_codes::*;
-
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    pub fn report_fulfillment_errors(
-        &self,
-        errors: &[FulfillmentError<'tcx>],
-        body_id: Option<hir::BodyId>,
-        fallback_has_occurred: bool,
-    ) {
-        #[derive(Debug)]
-        struct ErrorDescriptor<'tcx> {
-            predicate: ty::Predicate<'tcx>,
-            index: Option<usize>, // None if this is an old error
-        }
-
-        let mut error_map: FxHashMap<_, Vec<_>> = self
-            .reported_trait_errors
-            .borrow()
-            .iter()
-            .map(|(&span, predicates)| {
-                (
-                    span,
-                    predicates
-                        .iter()
-                        .map(|predicate| ErrorDescriptor {
-                            predicate: predicate.clone(),
-                            index: None,
-                        })
-                        .collect(),
-                )
-            })
-            .collect();
-
-        for (index, error) in errors.iter().enumerate() {
-            // 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;
-            let expn_data = span.ctxt().outer_expn_data();
-            if let ExpnKind::Desugaring(_) = expn_data.kind {
-                span = expn_data.call_site;
-            }
-
-            error_map.entry(span).or_default().push(ErrorDescriptor {
-                predicate: error.obligation.predicate.clone(),
-                index: Some(index),
-            });
-
-            self.reported_trait_errors
-                .borrow_mut()
-                .entry(span)
-                .or_default()
-                .push(error.obligation.predicate.clone());
-        }
-
-        // 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() {
-            // We want to suppress "duplicate" errors with the same span.
-            for error in error_set {
-                if let Some(index) = error.index {
-                    // Suppress errors that are either:
-                    // 1) strictly implied by another error.
-                    // 2) implied by an error with a smaller index.
-                    for error2 in error_set {
-                        if error2.index.map_or(false, |index2| is_suppressed[index2]) {
-                            // Avoid errors being suppressed by already-suppressed
-                            // errors, to prevent all errors from being suppressed
-                            // at once.
-                            continue;
-                        }
-
-                        if self.error_implies(&error2.predicate, &error.predicate)
-                            && !(error2.index >= error.index
-                                && self.error_implies(&error.predicate, &error2.predicate))
-                        {
-                            info!("skipping {:?} (implied by {:?})", error, error2);
-                            is_suppressed[index] = true;
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-
-        for (error, suppressed) in errors.iter().zip(is_suppressed) {
-            if !suppressed {
-                self.report_fulfillment_error(error, body_id, fallback_has_occurred);
-            }
-        }
-    }
-
-    // returns if `cond` not occurring implies that `error` does not occur - i.e., that
-    // `error` occurring implies that `cond` occurs.
-    fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool {
-        if cond == error {
-            return true;
-        }
-
-        let (cond, error) = match (cond, error) {
-            (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error)) => (cond, error),
-            _ => {
-                // FIXME: make this work in other cases too.
-                return false;
-            }
-        };
-
-        for implication in super::elaborate_predicates(self.tcx, vec![cond.clone()]) {
-            if let ty::Predicate::Trait(implication) = implication {
-                let error = error.to_poly_trait_ref();
-                let implication = implication.to_poly_trait_ref();
-                // FIXME: I'm just not taking associated types at all here.
-                // Eventually I'll need to implement param-env-aware
-                // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
-                let param_env = ty::ParamEnv::empty();
-                if self.can_sub(param_env, error, implication).is_ok() {
-                    debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
-                    return true;
-                }
-            }
-        }
-
-        false
-    }
-
-    fn report_fulfillment_error(
-        &self,
-        error: &FulfillmentError<'tcx>,
-        body_id: Option<hir::BodyId>,
-        fallback_has_occurred: bool,
-    ) {
-        debug!("report_fulfillment_error({:?})", error);
-        match error.code {
-            FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
-                self.report_selection_error(
-                    &error.obligation,
-                    selection_error,
-                    fallback_has_occurred,
-                    error.points_at_arg_span,
-                );
-            }
-            FulfillmentErrorCode::CodeProjectionError(ref e) => {
-                self.report_projection_error(&error.obligation, e);
-            }
-            FulfillmentErrorCode::CodeAmbiguity => {
-                self.maybe_report_ambiguity(&error.obligation, body_id);
-            }
-            FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
-                self.report_mismatched_types(
-                    &error.obligation.cause,
-                    expected_found.expected,
-                    expected_found.found,
-                    err.clone(),
-                )
-                .emit();
-            }
-        }
-    }
-
-    fn report_projection_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        error: &MismatchedProjectionTypes<'tcx>,
-    ) {
-        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-
-        if predicate.references_error() {
-            return;
-        }
-
-        self.probe(|_| {
-            let err_buf;
-            let mut err = &error.err;
-            let mut values = None;
-
-            // try to find the mismatched types to report the error with.
-            //
-            // this can fail if the problem was higher-ranked, in which
-            // cause I have no idea for a good error message.
-            if let ty::Predicate::Projection(ref data) = predicate {
-                let mut selcx = SelectionContext::new(self);
-                let (data, _) = self.replace_bound_vars_with_fresh_vars(
-                    obligation.cause.span,
-                    infer::LateBoundRegionConversionTime::HigherRankedType,
-                    data,
-                );
-                let mut obligations = vec![];
-                let normalized_ty = super::normalize_projection_type(
-                    &mut selcx,
-                    obligation.param_env,
-                    data.projection_ty,
-                    obligation.cause.clone(),
-                    0,
-                    &mut obligations,
-                );
-
-                debug!(
-                    "report_projection_error obligation.cause={:?} obligation.param_env={:?}",
-                    obligation.cause, obligation.param_env
-                );
-
-                debug!(
-                    "report_projection_error normalized_ty={:?} data.ty={:?}",
-                    normalized_ty, data.ty
-                );
-
-                let is_normalized_ty_expected = match &obligation.cause.code {
-                    ObligationCauseCode::ItemObligation(_)
-                    | ObligationCauseCode::BindingObligation(_, _)
-                    | ObligationCauseCode::ObjectCastObligation(_) => false,
-                    _ => true,
-                };
-
-                if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp(
-                    is_normalized_ty_expected,
-                    normalized_ty,
-                    data.ty,
-                ) {
-                    values = Some(infer::ValuePairs::Types(ExpectedFound::new(
-                        is_normalized_ty_expected,
-                        normalized_ty,
-                        data.ty,
-                    )));
-
-                    err_buf = error;
-                    err = &err_buf;
-                }
-            }
-
-            let msg = format!("type mismatch resolving `{}`", predicate);
-            let error_id = (DiagnosticMessageId::ErrorId(271), Some(obligation.cause.span), msg);
-            let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
-            if fresh {
-                let mut diag = struct_span_err!(
-                    self.tcx.sess,
-                    obligation.cause.span,
-                    E0271,
-                    "type mismatch resolving `{}`",
-                    predicate
-                );
-                self.note_type_err(&mut diag, &obligation.cause, None, values, err);
-                self.note_obligation_cause(&mut diag, obligation);
-                diag.emit();
-            }
-        });
-    }
-
-    fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
-        /// returns the fuzzy category of a given type, or None
-        /// if the type can be equated to any type.
-        fn type_category(t: Ty<'_>) -> Option<u32> {
-            match t.kind {
-                ty::Bool => Some(0),
-                ty::Char => Some(1),
-                ty::Str => Some(2),
-                ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3),
-                ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4),
-                ty::Ref(..) | ty::RawPtr(..) => Some(5),
-                ty::Array(..) | ty::Slice(..) => Some(6),
-                ty::FnDef(..) | ty::FnPtr(..) => Some(7),
-                ty::Dynamic(..) => Some(8),
-                ty::Closure(..) => Some(9),
-                ty::Tuple(..) => Some(10),
-                ty::Projection(..) => Some(11),
-                ty::Param(..) => Some(12),
-                ty::Opaque(..) => Some(13),
-                ty::Never => Some(14),
-                ty::Adt(adt, ..) => match adt.adt_kind() {
-                    AdtKind::Struct => Some(15),
-                    AdtKind::Union => Some(16),
-                    AdtKind::Enum => Some(17),
-                },
-                ty::Generator(..) => Some(18),
-                ty::Foreign(..) => Some(19),
-                ty::GeneratorWitness(..) => Some(20),
-                ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None,
-                ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
-            }
-        }
-
-        match (type_category(a), type_category(b)) {
-            (Some(cat_a), Some(cat_b)) => match (&a.kind, &b.kind) {
-                (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b,
-                _ => cat_a == cat_b,
-            },
-            // infer and error can be equated to all types
-            _ => true,
-        }
-    }
-
-    fn impl_similar_to(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> Option<DefId> {
-        let tcx = self.tcx;
-        let param_env = obligation.param_env;
-        let trait_ref = tcx.erase_late_bound_regions(&trait_ref);
-        let trait_self_ty = trait_ref.self_ty();
-
-        let mut self_match_impls = vec![];
-        let mut fuzzy_match_impls = vec![];
-
-        self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| {
-            let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id);
-            let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().subst(tcx, impl_substs);
-
-            let impl_self_ty = impl_trait_ref.self_ty();
-
-            if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) {
-                self_match_impls.push(def_id);
-
-                if trait_ref
-                    .substs
-                    .types()
-                    .skip(1)
-                    .zip(impl_trait_ref.substs.types().skip(1))
-                    .all(|(u, v)| self.fuzzy_match_tys(u, v))
-                {
-                    fuzzy_match_impls.push(def_id);
-                }
-            }
-        });
-
-        let impl_def_id = if self_match_impls.len() == 1 {
-            self_match_impls[0]
-        } else if fuzzy_match_impls.len() == 1 {
-            fuzzy_match_impls[0]
-        } else {
-            return None;
-        };
-
-        tcx.has_attr(impl_def_id, sym::rustc_on_unimplemented).then_some(impl_def_id)
-    }
-
-    fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
-        self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind {
-            hir::GeneratorKind::Gen => "a generator",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function",
-            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure",
-        })
-    }
-
-    /// Used to set on_unimplemented's `ItemContext`
-    /// to be the enclosing (async) block/function/closure
-    fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str> {
-        let hir = &self.tcx.hir();
-        let node = hir.find(hir_id)?;
-        if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) = &node {
-            self.describe_generator(*body_id).or_else(|| {
-                Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
-                    "an async function"
-                } else {
-                    "a function"
-                })
-            })
-        } else if let hir::Node::Expr(hir::Expr {
-            kind: hir::ExprKind::Closure(_is_move, _, body_id, _, gen_movability),
-            ..
-        }) = &node
-        {
-            self.describe_generator(*body_id).or_else(|| {
-                Some(if gen_movability.is_some() { "an async closure" } else { "a closure" })
-            })
-        } else if let hir::Node::Expr(hir::Expr { .. }) = &node {
-            let parent_hid = hir.get_parent_node(hir_id);
-            if parent_hid != hir_id {
-                return self.describe_enclosure(parent_hid);
-            } else {
-                None
-            }
-        } else {
-            None
-        }
-    }
-
-    fn on_unimplemented_note(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> OnUnimplementedNote {
-        let def_id =
-            self.impl_similar_to(trait_ref, obligation).unwrap_or_else(|| trait_ref.def_id());
-        let trait_ref = *trait_ref.skip_binder();
-
-        let mut flags = vec![];
-        flags.push((
-            sym::item_context,
-            self.describe_enclosure(obligation.cause.body_id).map(|s| s.to_owned()),
-        ));
-
-        match obligation.cause.code {
-            ObligationCauseCode::BuiltinDerivedObligation(..)
-            | ObligationCauseCode::ImplDerivedObligation(..) => {}
-            _ => {
-                // this is a "direct", user-specified, rather than derived,
-                // obligation.
-                flags.push((sym::direct, None));
-            }
-        }
-
-        if let ObligationCauseCode::ItemObligation(item) = obligation.cause.code {
-            // FIXME: maybe also have some way of handling methods
-            // from other traits? That would require name resolution,
-            // which we might want to be some sort of hygienic.
-            //
-            // Currently I'm leaving it for what I need for `try`.
-            if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
-                let method = self.tcx.item_name(item);
-                flags.push((sym::from_method, None));
-                flags.push((sym::from_method, Some(method.to_string())));
-            }
-        }
-        if let Some((t, _)) = self.get_parent_trait_ref(&obligation.cause.code) {
-            flags.push((sym::parent_trait, Some(t)));
-        }
-
-        if let Some(k) = obligation.cause.span.desugaring_kind() {
-            flags.push((sym::from_desugaring, None));
-            flags.push((sym::from_desugaring, Some(format!("{:?}", k))));
-        }
-        let generics = self.tcx.generics_of(def_id);
-        let self_ty = trait_ref.self_ty();
-        // This is also included through the generics list as `Self`,
-        // but the parser won't allow you to use it
-        flags.push((sym::_Self, Some(self_ty.to_string())));
-        if let Some(def) = self_ty.ty_adt_def() {
-            // We also want to be able to select self's original
-            // signature with no type arguments resolved
-            flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string())));
-        }
-
-        for param in generics.params.iter() {
-            let value = match param.kind {
-                GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
-                    trait_ref.substs[param.index as usize].to_string()
-                }
-                GenericParamDefKind::Lifetime => continue,
-            };
-            let name = param.name;
-            flags.push((name, Some(value)));
-        }
-
-        if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) {
-            flags.push((sym::crate_local, None));
-        }
-
-        // Allow targeting all integers using `{integral}`, even if the exact type was resolved
-        if self_ty.is_integral() {
-            flags.push((sym::_Self, Some("{integral}".to_owned())));
-        }
-
-        if let ty::Array(aty, len) = self_ty.kind {
-            flags.push((sym::_Self, Some("[]".to_owned())));
-            flags.push((sym::_Self, Some(format!("[{}]", aty))));
-            if let Some(def) = aty.ty_adt_def() {
-                // We also want to be able to select the array's type's original
-                // signature with no type arguments resolved
-                flags.push((
-                    sym::_Self,
-                    Some(format!("[{}]", self.tcx.type_of(def.did).to_string())),
-                ));
-                let tcx = self.tcx;
-                if let Some(len) = len.try_eval_usize(tcx, ty::ParamEnv::empty()) {
-                    flags.push((
-                        sym::_Self,
-                        Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)),
-                    ));
-                } else {
-                    flags.push((
-                        sym::_Self,
-                        Some(format!("[{}; _]", self.tcx.type_of(def.did).to_string())),
-                    ));
-                }
-            }
-        }
-
-        if let Ok(Some(command)) =
-            OnUnimplementedDirective::of_item(self.tcx, trait_ref.def_id, def_id)
-        {
-            command.evaluate(self.tcx, trait_ref, &flags[..])
-        } else {
-            OnUnimplementedNote::default()
-        }
-    }
-
-    fn find_similar_impl_candidates(
-        &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
-    ) -> Vec<ty::TraitRef<'tcx>> {
-        let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true);
-        let all_impls = self.tcx.all_impls(trait_ref.def_id());
-
-        match simp {
-            Some(simp) => all_impls
-                .iter()
-                .filter_map(|&def_id| {
-                    let imp = self.tcx.impl_trait_ref(def_id).unwrap();
-                    let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true);
-                    if let Some(imp_simp) = imp_simp {
-                        if simp != imp_simp {
-                            return None;
-                        }
-                    }
-
-                    Some(imp)
-                })
-                .collect(),
-            None => {
-                all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect()
-            }
-        }
-    }
-
-    fn report_similar_impl_candidates(
-        &self,
-        impl_candidates: Vec<ty::TraitRef<'tcx>>,
-        err: &mut DiagnosticBuilder<'_>,
-    ) {
-        if impl_candidates.is_empty() {
-            return;
-        }
-
-        let len = impl_candidates.len();
-        let end = if impl_candidates.len() <= 5 { impl_candidates.len() } else { 4 };
-
-        let normalize = |candidate| {
-            self.tcx.infer_ctxt().enter(|ref infcx| {
-                let normalized = infcx
-                    .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
-                    .normalize(candidate)
-                    .ok();
-                match normalized {
-                    Some(normalized) => format!("\n  {:?}", normalized.value),
-                    None => format!("\n  {:?}", candidate),
-                }
-            })
-        };
-
-        // Sort impl candidates so that ordering is consistent for UI tests.
-        let mut normalized_impl_candidates =
-            impl_candidates.iter().map(normalize).collect::<Vec<String>>();
-
-        // Sort before taking the `..end` range,
-        // because the ordering of `impl_candidates` may not be deterministic:
-        // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
-        normalized_impl_candidates.sort();
-
-        err.help(&format!(
-            "the following implementations were found:{}{}",
-            normalized_impl_candidates[..end].join(""),
-            if len > 5 { format!("\nand {} others", len - 4) } else { String::new() }
-        ));
-    }
-
-    /// Reports that an overflow has occurred and halts compilation. We
-    /// halt compilation unconditionally because it is important that
-    /// overflows never be masked -- they basically represent computations
-    /// whose result could not be truly determined and thus we can't say
-    /// if the program type checks or not -- and they are unusual
-    /// occurrences in any case.
-    pub fn report_overflow_error<T>(
-        &self,
-        obligation: &Obligation<'tcx, T>,
-        suggest_increasing_limit: bool,
-    ) -> !
-    where
-        T: fmt::Display + TypeFoldable<'tcx>,
-    {
-        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            obligation.cause.span,
-            E0275,
-            "overflow evaluating the requirement `{}`",
-            predicate
-        );
-
-        if suggest_increasing_limit {
-            self.suggest_new_overflow_limit(&mut err);
-        }
-
-        self.note_obligation_cause_code(
-            &mut err,
-            &obligation.predicate,
-            &obligation.cause.code,
-            &mut vec![],
-        );
-
-        err.emit();
-        self.tcx.sess.abort_if_errors();
-        bug!();
-    }
-
-    /// Reports that a cycle was detected which led to overflow and halts
-    /// compilation. This is equivalent to `report_overflow_error` except
-    /// that we can give a more helpful error message (and, in particular,
-    /// we do not suggest increasing the overflow limit, which is not
-    /// going to help).
-    pub fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
-        let cycle = self.resolve_vars_if_possible(&cycle.to_owned());
-        assert!(cycle.len() > 0);
-
-        debug!("report_overflow_error_cycle: cycle={:?}", cycle);
-
-        self.report_overflow_error(&cycle[0], false);
-    }
-
-    pub fn report_extra_impl_obligation(
-        &self,
-        error_span: Span,
-        item_name: ast::Name,
-        _impl_item_def_id: DefId,
-        trait_item_def_id: DefId,
-        requirement: &dyn fmt::Display,
-    ) -> DiagnosticBuilder<'tcx> {
-        let msg = "impl has stricter requirements than trait";
-        let sp = self.tcx.sess.source_map().def_span(error_span);
-
-        let mut err = struct_span_err!(self.tcx.sess, sp, E0276, "{}", msg);
-
-        if let Some(trait_item_span) = self.tcx.hir().span_if_local(trait_item_def_id) {
-            let span = self.tcx.sess.source_map().def_span(trait_item_span);
-            err.span_label(span, format!("definition of `{}` from trait", item_name));
-        }
-
-        err.span_label(sp, format!("impl has extra requirement {}", requirement));
-
-        err
-    }
-
-    /// Gets the parent trait chain start
-    fn get_parent_trait_ref(
-        &self,
-        code: &ObligationCauseCode<'tcx>,
-    ) -> Option<(String, Option<Span>)> {
-        match code {
-            &ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
-                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-                match self.get_parent_trait_ref(&data.parent_code) {
-                    Some(t) => Some(t),
-                    None => {
-                        let ty = parent_trait_ref.skip_binder().self_ty();
-                        let span =
-                            TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id));
-                        Some((ty.to_string(), span))
-                    }
-                }
-            }
-            _ => None,
-        }
-    }
-
-    pub fn report_selection_error(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        error: &SelectionError<'tcx>,
-        fallback_has_occurred: bool,
-        points_at_arg: bool,
-    ) {
-        let tcx = self.tcx;
-        let span = obligation.cause.span;
-
-        let mut err = match *error {
-            SelectionError::Unimplemented => {
-                if let ObligationCauseCode::CompareImplMethodObligation {
-                    item_name,
-                    impl_item_def_id,
-                    trait_item_def_id,
-                }
-                | ObligationCauseCode::CompareImplTypeObligation {
-                    item_name,
-                    impl_item_def_id,
-                    trait_item_def_id,
-                } = obligation.cause.code
-                {
-                    self.report_extra_impl_obligation(
-                        span,
-                        item_name,
-                        impl_item_def_id,
-                        trait_item_def_id,
-                        &format!("`{}`", obligation.predicate),
-                    )
-                    .emit();
-                    return;
-                }
-                match obligation.predicate {
-                    ty::Predicate::Trait(ref trait_predicate) => {
-                        let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
-
-                        if self.tcx.sess.has_errors() && trait_predicate.references_error() {
-                            return;
-                        }
-                        let trait_ref = trait_predicate.to_poly_trait_ref();
-                        let (post_message, pre_message, type_def) = self
-                            .get_parent_trait_ref(&obligation.cause.code)
-                            .map(|(t, s)| {
-                                (
-                                    format!(" in `{}`", t),
-                                    format!("within `{}`, ", t),
-                                    s.map(|s| (format!("within this `{}`", t), s)),
-                                )
-                            })
-                            .unwrap_or_default();
-
-                        let OnUnimplementedNote { message, label, note, enclosing_scope } =
-                            self.on_unimplemented_note(trait_ref, obligation);
-                        let have_alt_message = message.is_some() || label.is_some();
-                        let is_try = self
-                            .tcx
-                            .sess
-                            .source_map()
-                            .span_to_snippet(span)
-                            .map(|s| &s == "?")
-                            .unwrap_or(false);
-                        let is_from = format!("{}", trait_ref.print_only_trait_path())
-                            .starts_with("std::convert::From<");
-                        let (message, note) = if is_try && is_from {
-                            (
-                                Some(format!(
-                                    "`?` couldn't convert the error to `{}`",
-                                    trait_ref.self_ty(),
-                                )),
-                                Some(
-                                    "the question mark operation (`?`) implicitly performs a \
-                                 conversion on the error value using the `From` trait"
-                                        .to_owned(),
-                                ),
-                            )
-                        } else {
-                            (message, note)
-                        };
-
-                        let mut err = struct_span_err!(
-                            self.tcx.sess,
-                            span,
-                            E0277,
-                            "{}",
-                            message.unwrap_or_else(|| format!(
-                                "the trait bound `{}` is not satisfied{}",
-                                trait_ref.to_predicate(),
-                                post_message,
-                            ))
-                        );
-
-                        let explanation =
-                            if obligation.cause.code == ObligationCauseCode::MainFunctionType {
-                                "consider using `()`, or a `Result`".to_owned()
-                            } else {
-                                format!(
-                                    "{}the trait `{}` is not implemented for `{}`",
-                                    pre_message,
-                                    trait_ref.print_only_trait_path(),
-                                    trait_ref.self_ty(),
-                                )
-                            };
-
-                        if self.suggest_add_reference_to_arg(
-                            &obligation,
-                            &mut err,
-                            &trait_ref,
-                            points_at_arg,
-                            have_alt_message,
-                        ) {
-                            self.note_obligation_cause(&mut err, obligation);
-                            err.emit();
-                            return;
-                        }
-                        if let Some(ref s) = label {
-                            // If it has a custom `#[rustc_on_unimplemented]`
-                            // error message, let's display it as the label!
-                            err.span_label(span, s.as_str());
-                            err.help(&explanation);
-                        } else {
-                            err.span_label(span, explanation);
-                        }
-                        if let Some((msg, span)) = type_def {
-                            err.span_label(span, &msg);
-                        }
-                        if let Some(ref s) = note {
-                            // If it has a custom `#[rustc_on_unimplemented]` note, let's display it
-                            err.note(s.as_str());
-                        }
-                        if let Some(ref s) = enclosing_scope {
-                            let enclosing_scope_span = tcx.def_span(
-                                tcx.hir()
-                                    .opt_local_def_id(obligation.cause.body_id)
-                                    .unwrap_or_else(|| {
-                                        tcx.hir().body_owner_def_id(hir::BodyId {
-                                            hir_id: obligation.cause.body_id,
-                                        })
-                                    }),
-                            );
-
-                            err.span_label(enclosing_scope_span, s.as_str());
-                        }
-
-                        self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
-                        self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg);
-                        self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
-                        self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
-                        self.note_version_mismatch(&mut err, &trait_ref);
-
-                        // Try to report a help message
-                        if !trait_ref.has_infer_types()
-                            && self.predicate_can_apply(obligation.param_env, trait_ref)
-                        {
-                            // If a where-clause may be useful, remind the
-                            // user that they can add it.
-                            //
-                            // don't display an on-unimplemented note, as
-                            // these notes will often be of the form
-                            //     "the type `T` can't be frobnicated"
-                            // which is somewhat confusing.
-                            self.suggest_restricting_param_bound(
-                                &mut err,
-                                &trait_ref,
-                                obligation.cause.body_id,
-                            );
-                        } else {
-                            if !have_alt_message {
-                                // Can't show anything else useful, try to find similar impls.
-                                let impl_candidates = self.find_similar_impl_candidates(trait_ref);
-                                self.report_similar_impl_candidates(impl_candidates, &mut err);
-                            }
-                            self.suggest_change_mut(
-                                &obligation,
-                                &mut err,
-                                &trait_ref,
-                                points_at_arg,
-                            );
-                        }
-
-                        // If this error is due to `!: Trait` not implemented but `(): Trait` is
-                        // implemented, and fallback has occurred, then it could be due to a
-                        // variable that used to fallback to `()` now falling back to `!`. Issue a
-                        // note informing about the change in behaviour.
-                        if trait_predicate.skip_binder().self_ty().is_never()
-                            && fallback_has_occurred
-                        {
-                            let predicate = trait_predicate.map_bound(|mut trait_pred| {
-                                trait_pred.trait_ref.substs = self.tcx.mk_substs_trait(
-                                    self.tcx.mk_unit(),
-                                    &trait_pred.trait_ref.substs[1..],
-                                );
-                                trait_pred
-                            });
-                            let unit_obligation = Obligation {
-                                predicate: ty::Predicate::Trait(predicate),
-                                ..obligation.clone()
-                            };
-                            if self.predicate_may_hold(&unit_obligation) {
-                                err.note(
-                                    "the trait is implemented for `()`. \
-                                         Possibly this error has been caused by changes to \
-                                         Rust's type-inference algorithm \
-                                         (see: https://github.com/rust-lang/rust/issues/48950 \
-                                         for more info). Consider whether you meant to use the \
-                                         type `()` here instead.",
-                                );
-                            }
-                        }
-
-                        err
-                    }
-
-                    ty::Predicate::Subtype(ref predicate) => {
-                        // Errors for Subtype predicates show up as
-                        // `FulfillmentErrorCode::CodeSubtypeError`,
-                        // not selection error.
-                        span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
-                    }
-
-                    ty::Predicate::RegionOutlives(ref predicate) => {
-                        let predicate = self.resolve_vars_if_possible(predicate);
-                        let err = self
-                            .region_outlives_predicate(&obligation.cause, &predicate)
-                            .err()
-                            .unwrap();
-                        struct_span_err!(
-                            self.tcx.sess,
-                            span,
-                            E0279,
-                            "the requirement `{}` is not satisfied (`{}`)",
-                            predicate,
-                            err,
-                        )
-                    }
-
-                    ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
-                        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-                        struct_span_err!(
-                            self.tcx.sess,
-                            span,
-                            E0280,
-                            "the requirement `{}` is not satisfied",
-                            predicate
-                        )
-                    }
-
-                    ty::Predicate::ObjectSafe(trait_def_id) => {
-                        let violations = object_safety_violations(self.tcx, trait_def_id);
-                        report_object_safety_error(self.tcx, span, trait_def_id, violations)
-                    }
-
-                    ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
-                        let found_kind = self.closure_kind(closure_def_id, closure_substs).unwrap();
-                        let closure_span = self
-                            .tcx
-                            .sess
-                            .source_map()
-                            .def_span(self.tcx.hir().span_if_local(closure_def_id).unwrap());
-                        let hir_id = self.tcx.hir().as_local_hir_id(closure_def_id).unwrap();
-                        let mut err = struct_span_err!(
-                            self.tcx.sess,
-                            closure_span,
-                            E0525,
-                            "expected a closure that implements the `{}` trait, \
-                             but this closure only implements `{}`",
-                            kind,
-                            found_kind
-                        );
-
-                        err.span_label(
-                            closure_span,
-                            format!("this closure implements `{}`, not `{}`", found_kind, kind),
-                        );
-                        err.span_label(
-                            obligation.cause.span,
-                            format!("the requirement to implement `{}` derives from here", kind),
-                        );
-
-                        // Additional context information explaining why the closure only implements
-                        // a particular trait.
-                        if let Some(tables) = self.in_progress_tables {
-                            let tables = tables.borrow();
-                            match (found_kind, tables.closure_kind_origins().get(hir_id)) {
-                                (ty::ClosureKind::FnOnce, Some((span, name))) => {
-                                    err.span_label(
-                                        *span,
-                                        format!(
-                                            "closure is `FnOnce` because it moves the \
-                                         variable `{}` out of its environment",
-                                            name
-                                        ),
-                                    );
-                                }
-                                (ty::ClosureKind::FnMut, Some((span, name))) => {
-                                    err.span_label(
-                                        *span,
-                                        format!(
-                                            "closure is `FnMut` because it mutates the \
-                                         variable `{}` here",
-                                            name
-                                        ),
-                                    );
-                                }
-                                _ => {}
-                            }
-                        }
-
-                        err.emit();
-                        return;
-                    }
-
-                    ty::Predicate::WellFormed(ty) => {
-                        if !self.tcx.sess.opts.debugging_opts.chalk {
-                            // WF predicates cannot themselves make
-                            // errors. They can only block due to
-                            // ambiguity; otherwise, they always
-                            // degenerate into other obligations
-                            // (which may fail).
-                            span_bug!(span, "WF predicate not satisfied for {:?}", ty);
-                        } else {
-                            // FIXME: we'll need a better message which takes into account
-                            // which bounds actually failed to hold.
-                            self.tcx.sess.struct_span_err(
-                                span,
-                                &format!("the type `{}` is not well-formed (chalk)", ty),
-                            )
-                        }
-                    }
-
-                    ty::Predicate::ConstEvaluatable(..) => {
-                        // Errors for `ConstEvaluatable` predicates show up as
-                        // `SelectionError::ConstEvalFailure`,
-                        // not `Unimplemented`.
-                        span_bug!(
-                            span,
-                            "const-evaluatable requirement gave wrong error: `{:?}`",
-                            obligation
-                        )
-                    }
-                }
-            }
-
-            OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => {
-                let found_trait_ref = self.resolve_vars_if_possible(&*found_trait_ref);
-                let expected_trait_ref = self.resolve_vars_if_possible(&*expected_trait_ref);
-
-                if expected_trait_ref.self_ty().references_error() {
-                    return;
-                }
-
-                let found_trait_ty = found_trait_ref.self_ty();
-
-                let found_did = match found_trait_ty.kind {
-                    ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did),
-                    ty::Adt(def, _) => Some(def.did),
-                    _ => None,
-                };
-
-                let found_span = found_did
-                    .and_then(|did| self.tcx.hir().span_if_local(did))
-                    .map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def
-
-                if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
-                    // We check closures twice, with obligations flowing in different directions,
-                    // but we want to complain about them only once.
-                    return;
-                }
-
-                self.reported_closure_mismatch.borrow_mut().insert((span, found_span));
-
-                let found = match found_trait_ref.skip_binder().substs.type_at(1).kind {
-                    ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()],
-                    _ => vec![ArgKind::empty()],
-                };
-
-                let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1);
-                let expected = match expected_ty.kind {
-                    ty::Tuple(ref tys) => tys
-                        .iter()
-                        .map(|t| ArgKind::from_expected_ty(t.expect_ty(), Some(span)))
-                        .collect(),
-                    _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())],
-                };
-
-                if found.len() == expected.len() {
-                    self.report_closure_arg_mismatch(
-                        span,
-                        found_span,
-                        found_trait_ref,
-                        expected_trait_ref,
-                    )
-                } else {
-                    let (closure_span, found) = found_did
-                        .and_then(|did| self.tcx.hir().get_if_local(did))
-                        .map(|node| {
-                            let (found_span, found) = self.get_fn_like_arguments(node);
-                            (Some(found_span), found)
-                        })
-                        .unwrap_or((found_span, found));
-
-                    self.report_arg_count_mismatch(
-                        span,
-                        closure_span,
-                        expected,
-                        found,
-                        found_trait_ty.is_closure(),
-                    )
-                }
-            }
-
-            TraitNotObjectSafe(did) => {
-                let violations = object_safety_violations(self.tcx, did);
-                report_object_safety_error(self.tcx, span, did, violations)
-            }
-
-            // already reported in the query
-            ConstEvalFailure(err) => {
-                if let ErrorHandled::TooGeneric = err {
-                    // Silence this error, as it can be produced during intermediate steps
-                    // when a constant is not yet able to be evaluated (but will be later).
-                    return;
-                }
-                self.tcx.sess.delay_span_bug(
-                    span,
-                    &format!("constant in type had an ignored error: {:?}", err),
-                );
-                return;
-            }
-
-            Overflow => {
-                bug!("overflow should be handled before the `report_selection_error` path");
-            }
-        };
-
-        self.note_obligation_cause(&mut err, obligation);
-
-        err.emit();
-    }
-
-    /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
-    /// with the same path as `trait_ref`, a help message about
-    /// a probable version mismatch is added to `err`
-    fn note_version_mismatch(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        trait_ref: &ty::PolyTraitRef<'tcx>,
-    ) {
-        let get_trait_impl = |trait_def_id| {
-            let mut trait_impl = None;
-            self.tcx.for_each_relevant_impl(trait_def_id, trait_ref.self_ty(), |impl_def_id| {
-                if trait_impl.is_none() {
-                    trait_impl = Some(impl_def_id);
-                }
-            });
-            trait_impl
-        };
-        let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
-        let all_traits = self.tcx.all_traits(LOCAL_CRATE);
-        let traits_with_same_path: std::collections::BTreeSet<_> = all_traits
-            .iter()
-            .filter(|trait_def_id| **trait_def_id != trait_ref.def_id())
-            .filter(|trait_def_id| self.tcx.def_path_str(**trait_def_id) == required_trait_path)
-            .collect();
-        for trait_with_same_path in traits_with_same_path {
-            if let Some(impl_def_id) = get_trait_impl(*trait_with_same_path) {
-                let impl_span = self.tcx.def_span(impl_def_id);
-                err.span_help(impl_span, "trait impl with same name found");
-                let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
-                let crate_msg = format!(
-                    "perhaps two different versions of crate `{}` are being used?",
-                    trait_crate
-                );
-                err.note(&crate_msg);
-            }
-        }
-    }
-    fn suggest_restricting_param_bound(
-        &self,
-        mut err: &mut DiagnosticBuilder<'_>,
-        trait_ref: &ty::PolyTraitRef<'_>,
-        body_id: hir::HirId,
-    ) {
-        let self_ty = trait_ref.self_ty();
-        let (param_ty, projection) = match &self_ty.kind {
-            ty::Param(_) => (true, None),
-            ty::Projection(projection) => (false, Some(projection)),
-            _ => return,
-        };
-
-        let suggest_restriction =
-            |generics: &hir::Generics<'_>, msg, err: &mut DiagnosticBuilder<'_>| {
-                let span = generics.where_clause.span_for_predicates_or_empty_place();
-                if !span.from_expansion() && span.desugaring_kind().is_none() {
-                    err.span_suggestion(
-                        generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(),
-                        &format!("consider further restricting {}", msg),
-                        format!(
-                            "{} {} ",
-                            if !generics.where_clause.predicates.is_empty() {
-                                ","
-                            } else {
-                                " where"
-                            },
-                            trait_ref.to_predicate(),
-                        ),
-                        Applicability::MachineApplicable,
-                    );
-                }
-            };
-
-        // FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
-        //        don't suggest `T: Sized + ?Sized`.
-        let mut hir_id = body_id;
-        while let Some(node) = self.tcx.hir().find(hir_id) {
-            match node {
-                hir::Node::TraitItem(hir::TraitItem {
-                    generics,
-                    kind: hir::TraitItemKind::Method(..),
-                    ..
-                }) if param_ty && self_ty == self.tcx.types.self_param => {
-                    // Restricting `Self` for a single method.
-                    suggest_restriction(&generics, "`Self`", err);
-                    return;
-                }
-
-                hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
-                | hir::Node::TraitItem(hir::TraitItem {
-                    generics,
-                    kind: hir::TraitItemKind::Method(..),
-                    ..
-                })
-                | hir::Node::ImplItem(hir::ImplItem {
-                    generics,
-                    kind: hir::ImplItemKind::Method(..),
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Trait(_, _, generics, _, _),
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Impl(_, _, _, generics, ..),
-                    ..
-                }) if projection.is_some() => {
-                    // Missing associated type bound.
-                    suggest_restriction(&generics, "the associated type", err);
-                    return;
-                }
-
-                hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Struct(_, generics),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Enum(_, generics), span, ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Union(_, generics),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Trait(_, _, generics, ..),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Impl(_, _, _, generics, ..),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Fn(_, generics, _),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::TyAlias(_, generics),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::TraitAlias(generics, _),
-                    span,
-                    ..
-                })
-                | hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }),
-                    span,
-                    ..
-                })
-                | hir::Node::TraitItem(hir::TraitItem { generics, span, .. })
-                | hir::Node::ImplItem(hir::ImplItem { generics, span, .. })
-                    if param_ty =>
-                {
-                    // Missing generic type parameter bound.
-                    let param_name = self_ty.to_string();
-                    let constraint = trait_ref.print_only_trait_path().to_string();
-                    if suggest_constraining_type_param(
-                        generics,
-                        &mut err,
-                        &param_name,
-                        &constraint,
-                        self.tcx.sess.source_map(),
-                        *span,
-                    ) {
-                        return;
-                    }
-                }
-
-                hir::Node::Crate => return,
-
-                _ => {}
-            }
-
-            hir_id = self.tcx.hir().get_parent_item(hir_id);
-        }
-    }
-
-    /// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a
-    /// suggestion to borrow the initializer in order to use have a slice instead.
-    fn suggest_borrow_on_unsized_slice(
-        &self,
-        code: &ObligationCauseCode<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-    ) {
-        if let &ObligationCauseCode::VariableType(hir_id) = code {
-            let parent_node = self.tcx.hir().get_parent_node(hir_id);
-            if let Some(Node::Local(ref local)) = self.tcx.hir().find(parent_node) {
-                if let Some(ref expr) = local.init {
-                    if let hir::ExprKind::Index(_, _) = expr.kind {
-                        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
-                            err.span_suggestion(
-                                expr.span,
-                                "consider borrowing here",
-                                format!("&{}", snippet),
-                                Applicability::MachineApplicable,
-                            );
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    fn mk_obligation_for_def_id(
-        &self,
-        def_id: DefId,
-        output_ty: Ty<'tcx>,
-        cause: ObligationCause<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-    ) -> PredicateObligation<'tcx> {
-        let new_trait_ref =
-            ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
-        Obligation::new(cause, param_env, new_trait_ref.to_predicate())
-    }
-
-    /// Given a closure's `DefId`, return the given name of the closure.
-    ///
-    /// This doesn't account for reassignments, but it's only used for suggestions.
-    fn get_closure_name(
-        &self,
-        def_id: DefId,
-        err: &mut DiagnosticBuilder<'_>,
-        msg: &str,
-    ) -> Option<String> {
-        let get_name =
-            |err: &mut DiagnosticBuilder<'_>, kind: &hir::PatKind<'_>| -> Option<String> {
-                // Get the local name of this closure. This can be inaccurate because
-                // of the possibility of reassignment, but this should be good enough.
-                match &kind {
-                    hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => {
-                        Some(format!("{}", name))
-                    }
-                    _ => {
-                        err.note(&msg);
-                        None
-                    }
-                }
-            };
-
-        let hir = self.tcx.hir();
-        let hir_id = hir.as_local_hir_id(def_id)?;
-        let parent_node = hir.get_parent_node(hir_id);
-        match hir.find(parent_node) {
-            Some(hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. })) => {
-                get_name(err, &local.pat.kind)
-            }
-            // Different to previous arm because one is `&hir::Local` and the other
-            // is `P<hir::Local>`.
-            Some(hir::Node::Local(local)) => get_name(err, &local.pat.kind),
-            _ => return None,
-        }
-    }
-
-    /// We tried to apply the bound to an `fn` or closure. Check whether calling it would
-    /// evaluate to a type that *would* satisfy the trait binding. If it would, suggest calling
-    /// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`.
-    fn suggest_fn_call(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'_>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
-    ) {
-        let self_ty = trait_ref.self_ty();
-        let (def_id, output_ty, callable) = match self_ty.kind {
-            ty::Closure(def_id, substs) => {
-                (def_id, self.closure_sig(def_id, substs).output(), "closure")
-            }
-            ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"),
-            _ => return,
-        };
-        let msg = format!("use parentheses to call the {}", callable);
-
-        let obligation = self.mk_obligation_for_def_id(
-            trait_ref.def_id(),
-            output_ty.skip_binder(),
-            obligation.cause.clone(),
-            obligation.param_env,
-        );
-
-        match self.evaluate_obligation(&obligation) {
-            Ok(EvaluationResult::EvaluatedToOk)
-            | Ok(EvaluationResult::EvaluatedToOkModuloRegions)
-            | Ok(EvaluationResult::EvaluatedToAmbig) => {}
-            _ => return,
-        }
-        let hir = self.tcx.hir();
-        // Get the name of the callable and the arguments to be used in the suggestion.
-        let snippet = match hir.get_if_local(def_id) {
-            Some(hir::Node::Expr(hir::Expr {
-                kind: hir::ExprKind::Closure(_, decl, _, span, ..),
-                ..
-            })) => {
-                err.span_label(*span, "consider calling this closure");
-                let name = match self.get_closure_name(def_id, err, &msg) {
-                    Some(name) => name,
-                    None => return,
-                };
-                let args = decl.inputs.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
-                format!("{}({})", name, args)
-            }
-            Some(hir::Node::Item(hir::Item {
-                ident,
-                kind: hir::ItemKind::Fn(.., body_id),
-                ..
-            })) => {
-                err.span_label(ident.span, "consider calling this function");
-                let body = hir.body(*body_id);
-                let args = body
-                    .params
-                    .iter()
-                    .map(|arg| match &arg.pat.kind {
-                        hir::PatKind::Binding(_, _, ident, None)
-                        // FIXME: provide a better suggestion when encountering `SelfLower`, it
-                        // should suggest a method call.
-                        if ident.name != kw::SelfLower => ident.to_string(),
-                        _ => "_".to_string(),
-                    })
-                    .collect::<Vec<_>>()
-                    .join(", ");
-                format!("{}({})", ident, args)
-            }
-            _ => return,
-        };
-        if points_at_arg {
-            // When the obligation error has been ensured to have been caused by
-            // an argument, the `obligation.cause.span` points at the expression
-            // of the argument, so we can provide a suggestion. This is signaled
-            // by `points_at_arg`. Otherwise, we give a more general note.
-            err.span_suggestion(
-                obligation.cause.span,
-                &msg,
-                snippet,
-                Applicability::HasPlaceholders,
-            );
-        } else {
-            err.help(&format!("{}: `{}`", msg, snippet));
-        }
-    }
-
-    fn suggest_add_reference_to_arg(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
-        has_custom_message: bool,
-    ) -> bool {
-        if !points_at_arg {
-            return false;
-        }
-
-        let span = obligation.cause.span;
-        let param_env = obligation.param_env;
-        let trait_ref = trait_ref.skip_binder();
-
-        if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code {
-            // Try to apply the original trait binding obligation by borrowing.
-            let self_ty = trait_ref.self_ty();
-            let found = self_ty.to_string();
-            let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty);
-            let substs = self.tcx.mk_substs_trait(new_self_ty, &[]);
-            let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs);
-            let new_obligation =
-                Obligation::new(ObligationCause::dummy(), param_env, new_trait_ref.to_predicate());
-            if self.predicate_must_hold_modulo_regions(&new_obligation) {
-                if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-                    // We have a very specific type of error, where just borrowing this argument
-                    // might solve the problem. In cases like this, the important part is the
-                    // original type obligation, not the last one that failed, which is arbitrary.
-                    // Because of this, we modify the error to refer to the original obligation and
-                    // return early in the caller.
-                    let msg = format!(
-                        "the trait bound `{}: {}` is not satisfied",
-                        found,
-                        obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
-                    );
-                    if has_custom_message {
-                        err.note(&msg);
-                    } else {
-                        err.message = vec![(msg, Style::NoStyle)];
-                    }
-                    if snippet.starts_with('&') {
-                        // This is already a literal borrow and the obligation is failing
-                        // somewhere else in the obligation chain. Do not suggest non-sense.
-                        return false;
-                    }
-                    err.span_label(
-                        span,
-                        &format!(
-                            "expected an implementor of trait `{}`",
-                            obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
-                        ),
-                    );
-                    err.span_suggestion(
-                        span,
-                        "consider borrowing here",
-                        format!("&{}", snippet),
-                        Applicability::MaybeIncorrect,
-                    );
-                    return true;
-                }
-            }
-        }
-        false
-    }
-
-    /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
-    /// suggest removing these references until we reach a type that implements the trait.
-    fn suggest_remove_reference(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-    ) {
-        let trait_ref = trait_ref.skip_binder();
-        let span = obligation.cause.span;
-
-        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-            let refs_number =
-                snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
-            if let Some('\'') =
-                snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next()
-            {
-                // Do not suggest removal of borrow from type arguments.
-                return;
-            }
-
-            let mut trait_type = trait_ref.self_ty();
-
-            for refs_remaining in 0..refs_number {
-                if let ty::Ref(_, t_type, _) = trait_type.kind {
-                    trait_type = t_type;
-
-                    let new_obligation = self.mk_obligation_for_def_id(
-                        trait_ref.def_id,
-                        trait_type,
-                        ObligationCause::dummy(),
-                        obligation.param_env,
-                    );
-
-                    if self.predicate_may_hold(&new_obligation) {
-                        let sp = self
-                            .tcx
-                            .sess
-                            .source_map()
-                            .span_take_while(span, |c| c.is_whitespace() || *c == '&');
-
-                        let remove_refs = refs_remaining + 1;
-                        let format_str =
-                            format!("consider removing {} leading `&`-references", remove_refs);
-
-                        err.span_suggestion_short(
-                            sp,
-                            &format_str,
-                            String::new(),
-                            Applicability::MachineApplicable,
-                        );
-                        break;
-                    }
-                } else {
-                    break;
-                }
-            }
-        }
-    }
-
-    /// Check if the trait bound is implemented for a different mutability and note it in the
-    /// final error.
-    fn suggest_change_mut(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
-    ) {
-        let span = obligation.cause.span;
-        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-            let refs_number =
-                snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
-            if let Some('\'') =
-                snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next()
-            {
-                // Do not suggest removal of borrow from type arguments.
-                return;
-            }
-            let trait_ref = self.resolve_vars_if_possible(trait_ref);
-            if trait_ref.has_infer_types() {
-                // Do not ICE while trying to find if a reborrow would succeed on a trait with
-                // unresolved bindings.
-                return;
-            }
-
-            if let ty::Ref(region, t_type, mutability) = trait_ref.skip_binder().self_ty().kind {
-                let trait_type = match mutability {
-                    hir::Mutability::Mut => self.tcx.mk_imm_ref(region, t_type),
-                    hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type),
-                };
-
-                let new_obligation = self.mk_obligation_for_def_id(
-                    trait_ref.skip_binder().def_id,
-                    trait_type,
-                    ObligationCause::dummy(),
-                    obligation.param_env,
-                );
-
-                if self.evaluate_obligation_no_overflow(&new_obligation).must_apply_modulo_regions()
-                {
-                    let sp = self
-                        .tcx
-                        .sess
-                        .source_map()
-                        .span_take_while(span, |c| c.is_whitespace() || *c == '&');
-                    if points_at_arg && mutability == hir::Mutability::Not && refs_number > 0 {
-                        err.span_suggestion(
-                            sp,
-                            "consider changing this borrow's mutability",
-                            "&mut ".to_string(),
-                            Applicability::MachineApplicable,
-                        );
-                    } else {
-                        err.note(&format!(
-                            "`{}` is implemented for `{:?}`, but not for `{:?}`",
-                            trait_ref.print_only_trait_path(),
-                            trait_type,
-                            trait_ref.skip_binder().self_ty(),
-                        ));
-                    }
-                }
-            }
-        }
-    }
-
-    fn suggest_semicolon_removal(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        err: &mut DiagnosticBuilder<'tcx>,
-        span: Span,
-        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
-    ) {
-        let hir = self.tcx.hir();
-        let parent_node = hir.get_parent_node(obligation.cause.body_id);
-        let node = hir.find(parent_node);
-        if let Some(hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::Fn(sig, _, body_id), ..
-        })) = node
-        {
-            let body = hir.body(*body_id);
-            if let hir::ExprKind::Block(blk, _) = &body.value.kind {
-                if sig.decl.output.span().overlaps(span)
-                    && blk.expr.is_none()
-                    && "()" == &trait_ref.self_ty().to_string()
-                {
-                    // FIXME(estebank): When encountering a method with a trait
-                    // bound not satisfied in the return type with a body that has
-                    // no return, suggest removal of semicolon on last statement.
-                    // Once that is added, close #54771.
-                    if let Some(ref stmt) = blk.stmts.last() {
-                        let sp = self.tcx.sess.source_map().end_point(stmt.span);
-                        err.span_label(sp, "consider removing this semicolon");
-                    }
-                }
-            }
-        }
-    }
-
-    /// Given some node representing a fn-like thing in the HIR map,
-    /// returns a span and `ArgKind` information that describes the
-    /// arguments it expects. This can be supplied to
-    /// `report_arg_count_mismatch`.
-    pub fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>) {
-        match node {
-            Node::Expr(&hir::Expr {
-                kind: hir::ExprKind::Closure(_, ref _decl, id, span, _),
-                ..
-            }) => (
-                self.tcx.sess.source_map().def_span(span),
-                self.tcx
-                    .hir()
-                    .body(id)
-                    .params
-                    .iter()
-                    .map(|arg| {
-                        if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } =
-                            *arg.pat
-                        {
-                            ArgKind::Tuple(
-                                Some(span),
-                                args.iter()
-                                    .map(|pat| {
-                                        let snippet = self
-                                            .tcx
-                                            .sess
-                                            .source_map()
-                                            .span_to_snippet(pat.span)
-                                            .unwrap();
-                                        (snippet, "_".to_owned())
-                                    })
-                                    .collect::<Vec<_>>(),
-                            )
-                        } else {
-                            let name =
-                                self.tcx.sess.source_map().span_to_snippet(arg.pat.span).unwrap();
-                            ArgKind::Arg(name, "_".to_owned())
-                        }
-                    })
-                    .collect::<Vec<ArgKind>>(),
-            ),
-            Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. })
-            | Node::ImplItem(&hir::ImplItem {
-                span,
-                kind: hir::ImplItemKind::Method(ref sig, _),
-                ..
-            })
-            | Node::TraitItem(&hir::TraitItem {
-                span,
-                kind: hir::TraitItemKind::Method(ref sig, _),
-                ..
-            }) => (
-                self.tcx.sess.source_map().def_span(span),
-                sig.decl
-                    .inputs
-                    .iter()
-                    .map(|arg| match arg.clone().kind {
-                        hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
-                            Some(arg.span),
-                            vec![("_".to_owned(), "_".to_owned()); tys.len()],
-                        ),
-                        _ => ArgKind::empty(),
-                    })
-                    .collect::<Vec<ArgKind>>(),
-            ),
-            Node::Ctor(ref variant_data) => {
-                let span = variant_data
-                    .ctor_hir_id()
-                    .map(|hir_id| self.tcx.hir().span(hir_id))
-                    .unwrap_or(DUMMY_SP);
-                let span = self.tcx.sess.source_map().def_span(span);
-
-                (span, vec![ArgKind::empty(); variant_data.fields().len()])
-            }
-            _ => panic!("non-FnLike node found: {:?}", node),
-        }
-    }
-
-    /// Reports an error when the number of arguments needed by a
-    /// trait match doesn't match the number that the expression
-    /// provides.
-    pub fn report_arg_count_mismatch(
-        &self,
-        span: Span,
-        found_span: Option<Span>,
-        expected_args: Vec<ArgKind>,
-        found_args: Vec<ArgKind>,
-        is_closure: bool,
-    ) -> DiagnosticBuilder<'tcx> {
-        let kind = if is_closure { "closure" } else { "function" };
-
-        let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
-            let arg_length = arguments.len();
-            let distinct = match &other[..] {
-                &[ArgKind::Tuple(..)] => true,
-                _ => false,
-            };
-            match (arg_length, arguments.get(0)) {
-                (1, Some(&ArgKind::Tuple(_, ref fields))) => {
-                    format!("a single {}-tuple as argument", fields.len())
-                }
-                _ => format!(
-                    "{} {}argument{}",
-                    arg_length,
-                    if distinct && arg_length > 1 { "distinct " } else { "" },
-                    pluralize!(arg_length)
-                ),
-            }
-        };
-
-        let expected_str = args_str(&expected_args, &found_args);
-        let found_str = args_str(&found_args, &expected_args);
-
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            span,
-            E0593,
-            "{} is expected to take {}, but it takes {}",
-            kind,
-            expected_str,
-            found_str,
-        );
-
-        err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
-
-        if let Some(found_span) = found_span {
-            err.span_label(found_span, format!("takes {}", found_str));
-
-            // move |_| { ... }
-            // ^^^^^^^^-- def_span
-            //
-            // move |_| { ... }
-            // ^^^^^-- prefix
-            let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span);
-            // move |_| { ... }
-            //      ^^^-- pipe_span
-            let pipe_span =
-                if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span };
-
-            // Suggest to take and ignore the arguments with expected_args_length `_`s if
-            // found arguments is empty (assume the user just wants to ignore args in this case).
-            // For example, if `expected_args_length` is 2, suggest `|_, _|`.
-            if found_args.is_empty() && is_closure {
-                let underscores = vec!["_"; expected_args.len()].join(", ");
-                err.span_suggestion(
-                    pipe_span,
-                    &format!(
-                        "consider changing the closure to take and ignore the expected argument{}",
-                        if expected_args.len() < 2 { "" } else { "s" }
-                    ),
-                    format!("|{}|", underscores),
-                    Applicability::MachineApplicable,
-                );
-            }
-
-            if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
-                if fields.len() == expected_args.len() {
-                    let sugg = fields
-                        .iter()
-                        .map(|(name, _)| name.to_owned())
-                        .collect::<Vec<String>>()
-                        .join(", ");
-                    err.span_suggestion(
-                        found_span,
-                        "change the closure to take multiple arguments instead of a single tuple",
-                        format!("|{}|", sugg),
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-            if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
-                if fields.len() == found_args.len() && is_closure {
-                    let sugg = format!(
-                        "|({}){}|",
-                        found_args
-                            .iter()
-                            .map(|arg| match arg {
-                                ArgKind::Arg(name, _) => name.to_owned(),
-                                _ => "_".to_owned(),
-                            })
-                            .collect::<Vec<String>>()
-                            .join(", "),
-                        // add type annotations if available
-                        if found_args.iter().any(|arg| match arg {
-                            ArgKind::Arg(_, ty) => ty != "_",
-                            _ => false,
-                        }) {
-                            format!(
-                                ": ({})",
-                                fields
-                                    .iter()
-                                    .map(|(_, ty)| ty.to_owned())
-                                    .collect::<Vec<String>>()
-                                    .join(", ")
-                            )
-                        } else {
-                            String::new()
-                        },
-                    );
-                    err.span_suggestion(
-                        found_span,
-                        "change the closure to accept a tuple instead of individual arguments",
-                        sugg,
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-        }
-
-        err
-    }
-
-    fn report_closure_arg_mismatch(
-        &self,
-        span: Span,
-        found_span: Option<Span>,
-        expected_ref: ty::PolyTraitRef<'tcx>,
-        found: ty::PolyTraitRef<'tcx>,
-    ) -> DiagnosticBuilder<'tcx> {
-        fn build_fn_sig_string<'tcx>(tcx: TyCtxt<'tcx>, trait_ref: &ty::TraitRef<'tcx>) -> String {
-            let inputs = trait_ref.substs.type_at(1);
-            let sig = if let ty::Tuple(inputs) = inputs.kind {
-                tcx.mk_fn_sig(
-                    inputs.iter().map(|k| k.expect_ty()),
-                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
-                    false,
-                    hir::Unsafety::Normal,
-                    ::rustc_target::spec::abi::Abi::Rust,
-                )
-            } else {
-                tcx.mk_fn_sig(
-                    ::std::iter::once(inputs),
-                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
-                    false,
-                    hir::Unsafety::Normal,
-                    ::rustc_target::spec::abi::Abi::Rust,
-                )
-            };
-            ty::Binder::bind(sig).to_string()
-        }
-
-        let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
-        let mut err = struct_span_err!(
-            self.tcx.sess,
-            span,
-            E0631,
-            "type mismatch in {} arguments",
-            if argument_is_closure { "closure" } else { "function" }
-        );
-
-        let found_str = format!(
-            "expected signature of `{}`",
-            build_fn_sig_string(self.tcx, found.skip_binder())
-        );
-        err.span_label(span, found_str);
-
-        let found_span = found_span.unwrap_or(span);
-        let expected_str = format!(
-            "found signature of `{}`",
-            build_fn_sig_string(self.tcx, expected_ref.skip_binder())
-        );
-        err.span_label(found_span, expected_str);
-
-        err
-    }
-}
-
-pub fn recursive_type_with_infinite_size_error(
-    tcx: TyCtxt<'tcx>,
-    type_def_id: DefId,
-) -> DiagnosticBuilder<'tcx> {
-    assert!(type_def_id.is_local());
-    let span = tcx.hir().span_if_local(type_def_id).unwrap();
-    let span = tcx.sess.source_map().def_span(span);
-    let mut err = struct_span_err!(
-        tcx.sess,
-        span,
-        E0072,
-        "recursive type `{}` has infinite size",
-        tcx.def_path_str(type_def_id)
-    );
-    err.span_label(span, "recursive type has infinite size");
-    err.help(&format!(
-        "insert indirection (e.g., a `Box`, `Rc`, or `&`) \
-                           at some point to make `{}` representable",
-        tcx.def_path_str(type_def_id)
-    ));
-    err
-}
-
-pub fn report_object_safety_error(
-    tcx: TyCtxt<'tcx>,
-    span: Span,
-    trait_def_id: DefId,
-    violations: Vec<ObjectSafetyViolation>,
-) -> DiagnosticBuilder<'tcx> {
-    let trait_str = tcx.def_path_str(trait_def_id);
-    let span = tcx.sess.source_map().def_span(span);
-    let mut err = struct_span_err!(
-        tcx.sess,
-        span,
-        E0038,
-        "the trait `{}` cannot be made into an object",
-        trait_str
-    );
-    err.span_label(span, format!("the trait `{}` cannot be made into an object", trait_str));
-
-    let mut reported_violations = FxHashSet::default();
-    for violation in violations {
-        if reported_violations.insert(violation.clone()) {
-            match violation.span() {
-                Some(span) => err.span_label(span, violation.error_msg()),
-                None => err.note(&violation.error_msg()),
-            };
-        }
-    }
-
-    if tcx.sess.trait_methods_not_found.borrow().contains(&span) {
-        // Avoid emitting error caused by non-existing method (#58734)
-        err.cancel();
-    }
-
-    err
-}
-
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    fn maybe_report_ambiguity(
-        &self,
-        obligation: &PredicateObligation<'tcx>,
-        body_id: Option<hir::BodyId>,
-    ) {
-        // Unable to successfully determine, probably means
-        // insufficient type information, but could mean
-        // ambiguous impls. The latter *ought* to be a
-        // coherence violation, so we don't report it here.
-
-        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
-        let span = obligation.cause.span;
-
-        debug!(
-            "maybe_report_ambiguity(predicate={:?}, obligation={:?} body_id={:?}, code={:?})",
-            predicate, obligation, body_id, obligation.cause.code,
-        );
-
-        // Ambiguity errors are often caused as fallout from earlier
-        // errors. So just ignore them if this infcx is tainted.
-        if self.is_tainted_by_errors() {
-            return;
-        }
-
-        let mut err = match predicate {
-            ty::Predicate::Trait(ref data) => {
-                let trait_ref = data.to_poly_trait_ref();
-                let self_ty = trait_ref.self_ty();
-                debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref);
-
-                if predicate.references_error() {
-                    return;
-                }
-                // Typically, this ambiguity should only happen if
-                // there are unresolved type inference variables
-                // (otherwise it would suggest a coherence
-                // failure). But given #21974 that is not necessarily
-                // the case -- we can have multiple where clauses that
-                // are only distinguished by a region, which results
-                // in an ambiguity even when all types are fully
-                // known, since we don't dispatch based on region
-                // relationships.
-
-                // This is kind of a hack: it frequently happens that some earlier
-                // error prevents types from being fully inferred, and then we get
-                // a bunch of uninteresting errors saying something like "<generic
-                // #0> doesn't implement Sized".  It may even be true that we
-                // could just skip over all checks where the self-ty is an
-                // inference variable, but I was afraid that there might be an
-                // inference variable created, registered as an obligation, and
-                // then never forced by writeback, and hence by skipping here we'd
-                // be ignoring the fact that we don't KNOW the type works
-                // out. Though even that would probably be harmless, given that
-                // we're only talking about builtin traits, which are known to be
-                // inhabited. We used to check for `self.tcx.sess.has_errors()` to
-                // avoid inundating the user with unnecessary errors, but we now
-                // check upstream for type errors and dont add the obligations to
-                // begin with in those cases.
-                if self
-                    .tcx
-                    .lang_items()
-                    .sized_trait()
-                    .map_or(false, |sized_id| sized_id == trait_ref.def_id())
-                {
-                    self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit();
-                    return;
-                }
-                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283);
-                err.note(&format!("cannot resolve `{}`", predicate));
-                if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code {
-                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
-                } else if let (
-                    Ok(ref snippet),
-                    ObligationCauseCode::BindingObligation(ref def_id, _),
-                ) =
-                    (self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code)
-                {
-                    let generics = self.tcx.generics_of(*def_id);
-                    if !generics.params.is_empty() && !snippet.ends_with('>') {
-                        // FIXME: To avoid spurious suggestions in functions where type arguments
-                        // where already supplied, we check the snippet to make sure it doesn't
-                        // end with a turbofish. Ideally we would have access to a `PathSegment`
-                        // instead. Otherwise we would produce the following output:
-                        //
-                        // error[E0283]: type annotations needed
-                        //   --> $DIR/issue-54954.rs:3:24
-                        //    |
-                        // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
-                        //    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
-                        //    |                        |
-                        //    |                        cannot infer type
-                        //    |                        help: consider specifying the type argument
-                        //    |                        in the function call:
-                        //    |                        `Tt::const_val::<[i8; 123]>::<T>`
-                        // ...
-                        // LL |     const fn const_val<T: Sized>() -> usize {
-                        //    |              --------- - required by this bound in `Tt::const_val`
-                        //    |
-                        //    = note: cannot resolve `_: Tt`
-
-                        err.span_suggestion(
-                            span,
-                            &format!(
-                                "consider specifying the type argument{} in the function call",
-                                if generics.params.len() > 1 { "s" } else { "" },
-                            ),
-                            format!(
-                                "{}::<{}>",
-                                snippet,
-                                generics
-                                    .params
-                                    .iter()
-                                    .map(|p| p.name.to_string())
-                                    .collect::<Vec<String>>()
-                                    .join(", ")
-                            ),
-                            Applicability::HasPlaceholders,
-                        );
-                    }
-                }
-                err
-            }
-
-            ty::Predicate::WellFormed(ty) => {
-                // Same hacky approach as above to avoid deluging user
-                // with error messages.
-                if ty.references_error() || self.tcx.sess.has_errors() {
-                    return;
-                }
-                self.need_type_info_err(body_id, span, ty, ErrorCode::E0282)
-            }
-
-            ty::Predicate::Subtype(ref data) => {
-                if data.references_error() || self.tcx.sess.has_errors() {
-                    // no need to overload user in such cases
-                    return;
-                }
-                let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
-                // both must be type variables, or the other would've been instantiated
-                assert!(a.is_ty_var() && b.is_ty_var());
-                self.need_type_info_err(body_id, span, a, ErrorCode::E0282)
-            }
-            ty::Predicate::Projection(ref data) => {
-                let trait_ref = data.to_poly_trait_ref(self.tcx);
-                let self_ty = trait_ref.self_ty();
-                if predicate.references_error() {
-                    return;
-                }
-                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284);
-                err.note(&format!("cannot resolve `{}`", predicate));
-                err
-            }
-
-            _ => {
-                if self.tcx.sess.has_errors() {
-                    return;
-                }
-                let mut err = struct_span_err!(
-                    self.tcx.sess,
-                    span,
-                    E0284,
-                    "type annotations needed: cannot resolve `{}`",
-                    predicate,
-                );
-                err.span_label(span, &format!("cannot resolve `{}`", predicate));
-                err
-            }
-        };
-        self.note_obligation_cause(&mut err, obligation);
-        err.emit();
-    }
-
-    fn suggest_fully_qualified_path(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        def_id: DefId,
-        span: Span,
-        trait_ref: DefId,
-    ) {
-        if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) {
-            if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind {
-                err.note(&format!(
-                    "{}s cannot be accessed directly on a `trait`, they can only be \
-                        accessed through a specific `impl`",
-                    assoc_item.kind.suggestion_descr(),
-                ));
-                err.span_suggestion(
-                    span,
-                    "use the fully qualified path to an implementation",
-                    format!("<Type as {}>::{}", self.tcx.def_path_str(trait_ref), assoc_item.ident),
-                    Applicability::HasPlaceholders,
-                );
-            }
-        }
-    }
-
-    /// Returns `true` if the trait predicate may apply for *some* assignment
-    /// to the type parameters.
-    fn predicate_can_apply(
-        &self,
-        param_env: ty::ParamEnv<'tcx>,
-        pred: ty::PolyTraitRef<'tcx>,
-    ) -> bool {
-        struct ParamToVarFolder<'a, 'tcx> {
-            infcx: &'a InferCtxt<'a, 'tcx>,
-            var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>,
-        }
-
-        impl<'a, 'tcx> TypeFolder<'tcx> for ParamToVarFolder<'a, 'tcx> {
-            fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
-                self.infcx.tcx
-            }
-
-            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
-                if let ty::Param(ty::ParamTy { name, .. }) = ty.kind {
-                    let infcx = self.infcx;
-                    self.var_map.entry(ty).or_insert_with(|| {
-                        infcx.next_ty_var(TypeVariableOrigin {
-                            kind: TypeVariableOriginKind::TypeParameterDefinition(name, None),
-                            span: DUMMY_SP,
-                        })
-                    })
-                } else {
-                    ty.super_fold_with(self)
-                }
-            }
-        }
-
-        self.probe(|_| {
-            let mut selcx = SelectionContext::new(self);
-
-            let cleaned_pred =
-                pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() });
-
-            let cleaned_pred = super::project::normalize(
-                &mut selcx,
-                param_env,
-                ObligationCause::dummy(),
-                &cleaned_pred,
-            )
-            .value;
-
-            let obligation =
-                Obligation::new(ObligationCause::dummy(), param_env, cleaned_pred.to_predicate());
-
-            self.predicate_may_hold(&obligation)
-        })
-    }
-
-    fn note_obligation_cause(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        obligation: &PredicateObligation<'tcx>,
-    ) {
-        // First, attempt to add note to this error with an async-await-specific
-        // message, and fall back to regular note otherwise.
-        if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
-            self.note_obligation_cause_code(
-                err,
-                &obligation.predicate,
-                &obligation.cause.code,
-                &mut vec![],
-            );
-        }
-    }
-
-    /// Adds an async-await specific note to the diagnostic when the future does not implement
-    /// an auto trait because of a captured type.
-    ///
-    /// ```ignore (diagnostic)
-    /// note: future does not implement `Qux` as this value is used across an await
-    ///   --> $DIR/issue-64130-3-other.rs:17:5
-    ///    |
-    /// LL |     let x = Foo;
-    ///    |         - has type `Foo`
-    /// LL |     baz().await;
-    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
-    /// LL | }
-    ///    | - `x` is later dropped here
-    /// ```
-    ///
-    /// When the diagnostic does not implement `Send` or `Sync` specifically, then the diagnostic
-    /// is "replaced" with a different message and a more specific error.
-    ///
-    /// ```ignore (diagnostic)
-    /// error: future cannot be sent between threads safely
-    ///   --> $DIR/issue-64130-2-send.rs:21:5
-    ///    |
-    /// LL | fn is_send<T: Send>(t: T) { }
-    ///    |    -------    ---- required by this bound in `is_send`
-    /// ...
-    /// LL |     is_send(bar());
-    ///    |     ^^^^^^^ future returned by `bar` is not send
-    ///    |
-    ///    = help: within `impl std::future::Future`, the trait `std::marker::Send` is not
-    ///            implemented for `Foo`
-    /// note: future is not send as this value is used across an await
-    ///   --> $DIR/issue-64130-2-send.rs:15:5
-    ///    |
-    /// LL |     let x = Foo;
-    ///    |         - has type `Foo`
-    /// LL |     baz().await;
-    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
-    /// LL | }
-    ///    | - `x` is later dropped here
-    /// ```
-    ///
-    /// Returns `true` if an async-await specific note was added to the diagnostic.
-    fn maybe_note_obligation_cause_for_async_await(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        obligation: &PredicateObligation<'tcx>,
-    ) -> bool {
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: obligation.predicate={:?} \
-                obligation.cause.span={:?}",
-            obligation.predicate, obligation.cause.span
-        );
-        let source_map = self.tcx.sess.source_map();
-
-        // Attempt to detect an async-await error by looking at the obligation causes, looking
-        // for a generator to be present.
-        //
-        // When a future does not implement a trait because of a captured type in one of the
-        // generators somewhere in the call stack, then the result is a chain of obligations.
-        //
-        // Given a `async fn` A that calls a `async fn` B which captures a non-send type and that
-        // future is passed as an argument to a function C which requires a `Send` type, then the
-        // chain looks something like this:
-        //
-        // - `BuiltinDerivedObligation` with a generator witness (B)
-        // - `BuiltinDerivedObligation` with a generator (B)
-        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (B)
-        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
-        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
-        // - `BuiltinDerivedObligation` with a generator witness (A)
-        // - `BuiltinDerivedObligation` with a generator (A)
-        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (A)
-        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
-        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
-        // - `BindingObligation` with `impl_send (Send requirement)
-        //
-        // The first obligation in the chain is the most useful and has the generator that captured
-        // the type. The last generator has information about where the bound was introduced. At
-        // least one generator should be present for this diagnostic to be modified.
-        let (mut trait_ref, mut target_ty) = match obligation.predicate {
-            ty::Predicate::Trait(p) => {
-                (Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty()))
-            }
-            _ => (None, None),
-        };
-        let mut generator = None;
-        let mut last_generator = None;
-        let mut next_code = Some(&obligation.cause.code);
-        while let Some(code) = next_code {
-            debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code);
-            match code {
-                ObligationCauseCode::BuiltinDerivedObligation(derived_obligation)
-                | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => {
-                    let ty = derived_obligation.parent_trait_ref.self_ty();
-                    debug!(
-                        "maybe_note_obligation_cause_for_async_await: \
-                            parent_trait_ref={:?} self_ty.kind={:?}",
-                        derived_obligation.parent_trait_ref, ty.kind
-                    );
-
-                    match ty.kind {
-                        ty::Generator(did, ..) => {
-                            generator = generator.or(Some(did));
-                            last_generator = Some(did);
-                        }
-                        ty::GeneratorWitness(..) => {}
-                        _ if generator.is_none() => {
-                            trait_ref = Some(*derived_obligation.parent_trait_ref.skip_binder());
-                            target_ty = Some(ty);
-                        }
-                        _ => {}
-                    }
-
-                    next_code = Some(derived_obligation.parent_code.as_ref());
-                }
-                _ => break,
-            }
-        }
-
-        // Only continue if a generator was found.
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: generator={:?} trait_ref={:?} \
-                target_ty={:?}",
-            generator, trait_ref, target_ty
-        );
-        let (generator_did, trait_ref, target_ty) = match (generator, trait_ref, target_ty) {
-            (Some(generator_did), Some(trait_ref), Some(target_ty)) => {
-                (generator_did, trait_ref, target_ty)
-            }
-            _ => return false,
-        };
-
-        let span = self.tcx.def_span(generator_did);
-
-        // Do not ICE on closure typeck (#66868).
-        if self.tcx.hir().as_local_hir_id(generator_did).is_none() {
-            return false;
-        }
-
-        // Get the tables from the infcx if the generator is the function we are
-        // currently type-checking; otherwise, get them by performing a query.
-        // This is needed to avoid cycles.
-        let in_progress_tables = self.in_progress_tables.map(|t| t.borrow());
-        let generator_did_root = self.tcx.closure_base_def_id(generator_did);
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: generator_did={:?} \
-             generator_did_root={:?} in_progress_tables.local_id_root={:?} span={:?}",
-            generator_did,
-            generator_did_root,
-            in_progress_tables.as_ref().map(|t| t.local_id_root),
-            span
-        );
-        let query_tables;
-        let tables: &TypeckTables<'tcx> = match &in_progress_tables {
-            Some(t) if t.local_id_root == Some(generator_did_root) => t,
-            _ => {
-                query_tables = self.tcx.typeck_tables_of(generator_did);
-                &query_tables
-            }
-        };
-
-        // Look for a type inside the generator interior that matches the target type to get
-        // a span.
-        let target_ty_erased = self.tcx.erase_regions(&target_ty);
-        let target_span = tables
-            .generator_interior_types
-            .iter()
-            .find(|ty::GeneratorInteriorTypeCause { ty, .. }| {
-                // Careful: the regions for types that appear in the
-                // generator interior are not generally known, so we
-                // want to erase them when comparing (and anyway,
-                // `Send` and other bounds are generally unaffected by
-                // the choice of region).  When erasing regions, we
-                // also have to erase late-bound regions. This is
-                // because the types that appear in the generator
-                // interior generally contain "bound regions" to
-                // represent regions that are part of the suspended
-                // generator frame. Bound regions are preserved by
-                // `erase_regions` and so we must also call
-                // `erase_late_bound_regions`.
-                let ty_erased = self.tcx.erase_late_bound_regions(&ty::Binder::bind(*ty));
-                let ty_erased = self.tcx.erase_regions(&ty_erased);
-                let eq = ty::TyS::same_type(ty_erased, target_ty_erased);
-                debug!(
-                    "maybe_note_obligation_cause_for_async_await: ty_erased={:?} \
-                        target_ty_erased={:?} eq={:?}",
-                    ty_erased, target_ty_erased, eq
-                );
-                eq
-            })
-            .map(|ty::GeneratorInteriorTypeCause { span, scope_span, expr, .. }| {
-                (span, source_map.span_to_snippet(*span), scope_span, expr)
-            });
-
-        debug!(
-            "maybe_note_obligation_cause_for_async_await: target_ty={:?} \
-                generator_interior_types={:?} target_span={:?}",
-            target_ty, tables.generator_interior_types, target_span
-        );
-        if let Some((target_span, Ok(snippet), scope_span, expr)) = target_span {
-            self.note_obligation_cause_for_async_await(
-                err,
-                *target_span,
-                scope_span,
-                *expr,
-                snippet,
-                generator_did,
-                last_generator,
-                trait_ref,
-                target_ty,
-                tables,
-                obligation,
-                next_code,
-            );
-            true
-        } else {
-            false
-        }
-    }
-
-    /// Unconditionally adds the diagnostic note described in
-    /// `maybe_note_obligation_cause_for_async_await`'s documentation comment.
-    fn note_obligation_cause_for_async_await(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        target_span: Span,
-        scope_span: &Option<Span>,
-        expr: Option<hir::HirId>,
-        snippet: String,
-        first_generator: DefId,
-        last_generator: Option<DefId>,
-        trait_ref: ty::TraitRef<'_>,
-        target_ty: Ty<'tcx>,
-        tables: &ty::TypeckTables<'_>,
-        obligation: &PredicateObligation<'tcx>,
-        next_code: Option<&ObligationCauseCode<'tcx>>,
-    ) {
-        let source_map = self.tcx.sess.source_map();
-
-        let is_async_fn = self
-            .tcx
-            .parent(first_generator)
-            .map(|parent_did| self.tcx.asyncness(parent_did))
-            .map(|parent_asyncness| parent_asyncness == hir::IsAsync::Async)
-            .unwrap_or(false);
-        let is_async_move = self
-            .tcx
-            .hir()
-            .as_local_hir_id(first_generator)
-            .and_then(|hir_id| self.tcx.hir().maybe_body_owned_by(hir_id))
-            .map(|body_id| self.tcx.hir().body(body_id))
-            .and_then(|body| body.generator_kind())
-            .map(|generator_kind| match generator_kind {
-                hir::GeneratorKind::Async(..) => true,
-                _ => false,
-            })
-            .unwrap_or(false);
-        let await_or_yield = if is_async_fn || is_async_move { "await" } else { "yield" };
-
-        // Special case the primary error message when send or sync is the trait that was
-        // not implemented.
-        let is_send = self.tcx.is_diagnostic_item(sym::send_trait, trait_ref.def_id);
-        let is_sync = self.tcx.is_diagnostic_item(sym::sync_trait, trait_ref.def_id);
-        let hir = self.tcx.hir();
-        let trait_explanation = if is_send || is_sync {
-            let (trait_name, trait_verb) =
-                if is_send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
-
-            err.clear_code();
-            err.set_primary_message(format!(
-                "future cannot be {} between threads safely",
-                trait_verb
-            ));
-
-            let original_span = err.span.primary_span().unwrap();
-            let mut span = MultiSpan::from_span(original_span);
-
-            let message = if let Some(name) = last_generator
-                .and_then(|generator_did| self.tcx.parent(generator_did))
-                .and_then(|parent_did| hir.as_local_hir_id(parent_did))
-                .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
-            {
-                format!("future returned by `{}` is not {}", name, trait_name)
-            } else {
-                format!("future is not {}", trait_name)
-            };
-
-            span.push_span_label(original_span, message);
-            err.set_span(span);
-
-            format!("is not {}", trait_name)
-        } else {
-            format!("does not implement `{}`", trait_ref.print_only_trait_path())
-        };
-
-        // Look at the last interior type to get a span for the `.await`.
-        let await_span = tables.generator_interior_types.iter().map(|t| t.span).last().unwrap();
-        let mut span = MultiSpan::from_span(await_span);
-        span.push_span_label(
-            await_span,
-            format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet),
-        );
-
-        span.push_span_label(target_span, format!("has type `{}`", target_ty));
-
-        // If available, use the scope span to annotate the drop location.
-        if let Some(scope_span) = scope_span {
-            span.push_span_label(
-                source_map.end_point(*scope_span),
-                format!("`{}` is later dropped here", snippet),
-            );
-        }
-
-        err.span_note(
-            span,
-            &format!(
-                "future {} as this value is used across an {}",
-                trait_explanation, await_or_yield,
-            ),
-        );
-
-        if let Some(expr_id) = expr {
-            let expr = hir.expect_expr(expr_id);
-            let is_ref = tables.expr_adjustments(expr).iter().any(|adj| adj.is_region_borrow());
-            let parent = hir.get_parent_node(expr_id);
-            if let Some(hir::Node::Expr(e)) = hir.find(parent) {
-                let method_span = hir.span(parent);
-                if tables.is_method_call(e) && is_ref {
-                    err.span_help(
-                        method_span,
-                        "consider moving this method call into a `let` \
-                        binding to create a shorter lived borrow",
-                    );
-                }
-            }
-        }
-
-        // Add a note for the item obligation that remains - normally a note pointing to the
-        // bound that introduced the obligation (e.g. `T: Send`).
-        debug!("note_obligation_cause_for_async_await: next_code={:?}", next_code);
-        self.note_obligation_cause_code(
-            err,
-            &obligation.predicate,
-            next_code.unwrap(),
-            &mut Vec::new(),
-        );
-    }
-
-    fn note_obligation_cause_code<T>(
-        &self,
-        err: &mut DiagnosticBuilder<'_>,
-        predicate: &T,
-        cause_code: &ObligationCauseCode<'tcx>,
-        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
-    ) where
-        T: fmt::Display,
-    {
-        let tcx = self.tcx;
-        match *cause_code {
-            ObligationCauseCode::ExprAssignable
-            | ObligationCauseCode::MatchExpressionArm { .. }
-            | ObligationCauseCode::Pattern { .. }
-            | ObligationCauseCode::IfExpression { .. }
-            | ObligationCauseCode::IfExpressionWithNoElse
-            | ObligationCauseCode::MainFunctionType
-            | ObligationCauseCode::StartFunctionType
-            | ObligationCauseCode::IntrinsicType
-            | ObligationCauseCode::MethodReceiver
-            | ObligationCauseCode::ReturnNoExpression
-            | ObligationCauseCode::MiscObligation => {}
-            ObligationCauseCode::SliceOrArrayElem => {
-                err.note("slice and array elements must have `Sized` type");
-            }
-            ObligationCauseCode::TupleElem => {
-                err.note("only the last element of a tuple may have a dynamically sized type");
-            }
-            ObligationCauseCode::ProjectionWf(data) => {
-                err.note(&format!("required so that the projection `{}` is well-formed", data,));
-            }
-            ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
-                err.note(&format!(
-                    "required so that reference `{}` does not outlive its referent",
-                    ref_ty,
-                ));
-            }
-            ObligationCauseCode::ObjectTypeBound(object_ty, region) => {
-                err.note(&format!(
-                    "required so that the lifetime bound of `{}` for `{}` is satisfied",
-                    region, object_ty,
-                ));
-            }
-            ObligationCauseCode::ItemObligation(item_def_id) => {
-                let item_name = tcx.def_path_str(item_def_id);
-                let msg = format!("required by `{}`", item_name);
-
-                if let Some(sp) = tcx.hir().span_if_local(item_def_id) {
-                    let sp = tcx.sess.source_map().def_span(sp);
-                    err.span_label(sp, &msg);
-                } else {
-                    err.note(&msg);
-                }
-            }
-            ObligationCauseCode::BindingObligation(item_def_id, span) => {
-                let item_name = tcx.def_path_str(item_def_id);
-                let msg = format!("required by this bound in `{}`", item_name);
-                if let Some(ident) = tcx.opt_item_name(item_def_id) {
-                    err.span_label(ident.span, "");
-                }
-                if span != DUMMY_SP {
-                    err.span_label(span, &msg);
-                } else {
-                    err.note(&msg);
-                }
-            }
-            ObligationCauseCode::ObjectCastObligation(object_ty) => {
-                err.note(&format!(
-                    "required for the cast to the object type `{}`",
-                    self.ty_to_string(object_ty)
-                ));
-            }
-            ObligationCauseCode::Coercion { source: _, target } => {
-                err.note(&format!("required by cast to type `{}`", self.ty_to_string(target)));
-            }
-            ObligationCauseCode::RepeatVec(suggest_const_in_array_repeat_expressions) => {
-                err.note(
-                    "the `Copy` trait is required because the \
-                          repeated element will be copied",
-                );
-                if suggest_const_in_array_repeat_expressions {
-                    err.note(
-                        "this array initializer can be evaluated at compile-time, for more \
-                              information, see issue \
-                              https://github.com/rust-lang/rust/issues/49147",
-                    );
-                    if tcx.sess.opts.unstable_features.is_nightly_build() {
-                        err.help(
-                            "add `#![feature(const_in_array_repeat_expressions)]` to the \
-                                  crate attributes to enable",
-                        );
-                    }
-                }
-            }
-            ObligationCauseCode::VariableType(_) => {
-                err.note("all local variables must have a statically known size");
-                if !self.tcx.features().unsized_locals {
-                    err.help("unsized locals are gated as an unstable feature");
-                }
-            }
-            ObligationCauseCode::SizedArgumentType => {
-                err.note("all function arguments must have a statically known size");
-                if !self.tcx.features().unsized_locals {
-                    err.help("unsized locals are gated as an unstable feature");
-                }
-            }
-            ObligationCauseCode::SizedReturnType => {
-                err.note(
-                    "the return type of a function must have a \
-                          statically known size",
-                );
-            }
-            ObligationCauseCode::SizedYieldType => {
-                err.note(
-                    "the yield type of a generator must have a \
-                          statically known size",
-                );
-            }
-            ObligationCauseCode::AssignmentLhsSized => {
-                err.note("the left-hand-side of an assignment must have a statically known size");
-            }
-            ObligationCauseCode::TupleInitializerSized => {
-                err.note("tuples must have a statically known size to be initialized");
-            }
-            ObligationCauseCode::StructInitializerSized => {
-                err.note("structs must have a statically known size to be initialized");
-            }
-            ObligationCauseCode::FieldSized { adt_kind: ref item, last } => match *item {
-                AdtKind::Struct => {
-                    if last {
-                        err.note(
-                            "the last field of a packed struct may only have a \
-                                      dynamically sized type if it does not need drop to be run",
-                        );
-                    } else {
-                        err.note(
-                            "only the last field of a struct may have a dynamically \
-                                      sized type",
-                        );
-                    }
-                }
-                AdtKind::Union => {
-                    err.note("no field of a union may have a dynamically sized type");
-                }
-                AdtKind::Enum => {
-                    err.note("no field of an enum variant may have a dynamically sized type");
-                }
-            },
-            ObligationCauseCode::ConstSized => {
-                err.note("constant expressions must have a statically known size");
-            }
-            ObligationCauseCode::ConstPatternStructural => {
-                err.note("constants used for pattern-matching must derive `PartialEq` and `Eq`");
-            }
-            ObligationCauseCode::SharedStatic => {
-                err.note("shared static variables must have a type that implements `Sync`");
-            }
-            ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
-                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-                let ty = parent_trait_ref.skip_binder().self_ty();
-                err.note(&format!("required because it appears within the type `{}`", ty));
-                obligated_types.push(ty);
-
-                let parent_predicate = parent_trait_ref.to_predicate();
-                if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
-                    self.note_obligation_cause_code(
-                        err,
-                        &parent_predicate,
-                        &data.parent_code,
-                        obligated_types,
-                    );
-                }
-            }
-            ObligationCauseCode::ImplDerivedObligation(ref data) => {
-                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-                err.note(&format!(
-                    "required because of the requirements on the impl of `{}` for `{}`",
-                    parent_trait_ref.print_only_trait_path(),
-                    parent_trait_ref.skip_binder().self_ty()
-                ));
-                let parent_predicate = parent_trait_ref.to_predicate();
-                self.note_obligation_cause_code(
-                    err,
-                    &parent_predicate,
-                    &data.parent_code,
-                    obligated_types,
-                );
-            }
-            ObligationCauseCode::CompareImplMethodObligation { .. } => {
-                err.note(&format!(
-                    "the requirement `{}` appears on the impl method \
-                              but not on the corresponding trait method",
-                    predicate
-                ));
-            }
-            ObligationCauseCode::CompareImplTypeObligation { .. } => {
-                err.note(&format!(
-                    "the requirement `{}` appears on the associated impl type\
-                     but not on the corresponding associated trait type",
-                    predicate
-                ));
-            }
-            ObligationCauseCode::ReturnType
-            | ObligationCauseCode::ReturnValue(_)
-            | ObligationCauseCode::BlockTailExpression(_) => (),
-            ObligationCauseCode::TrivialBound => {
-                err.help("see issue #48214");
-                if tcx.sess.opts.unstable_features.is_nightly_build() {
-                    err.help(
-                        "add `#![feature(trivial_bounds)]` to the \
-                              crate attributes to enable",
-                    );
-                }
-            }
-            ObligationCauseCode::AssocTypeBound(ref data) => {
-                err.span_label(data.original, "associated type defined here");
-                if let Some(sp) = data.impl_span {
-                    err.span_label(sp, "in this `impl` item");
-                }
-                for sp in &data.bounds {
-                    err.span_label(*sp, "restricted in this bound");
-                }
-            }
-        }
-    }
-
-    fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) {
-        let current_limit = self.tcx.sess.recursion_limit.get();
-        let suggested_limit = current_limit * 2;
-        err.help(&format!(
-            "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
-            suggested_limit
-        ));
-    }
-
-    fn is_recursive_obligation(
-        &self,
-        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
-        cause_code: &ObligationCauseCode<'tcx>,
-    ) -> bool {
-        if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
-            let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
-
-            if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) {
-                return true;
-            }
-        }
-        false
-    }
-}
-
-/// Summarizes information
-#[derive(Clone)]
-pub enum ArgKind {
-    /// An argument of non-tuple type. Parameters are (name, ty)
-    Arg(String, String),
-
-    /// An argument of tuple type. For a "found" argument, the span is
-    /// the locationo in the source of the pattern. For a "expected"
-    /// argument, it will be None. The vector is a list of (name, ty)
-    /// strings for the components of the tuple.
-    Tuple(Option<Span>, Vec<(String, String)>),
-}
-
-impl ArgKind {
-    fn empty() -> ArgKind {
-        ArgKind::Arg("_".to_owned(), "_".to_owned())
-    }
-
-    /// Creates an `ArgKind` from the expected type of an
-    /// argument. It has no name (`_`) and an optional source span.
-    pub fn from_expected_ty(t: Ty<'_>, span: Option<Span>) -> ArgKind {
-        match t.kind {
-            ty::Tuple(ref tys) => ArgKind::Tuple(
-                span,
-                tys.iter().map(|ty| ("_".to_owned(), ty.to_string())).collect::<Vec<_>>(),
-            ),
-            _ => ArgKind::Arg("_".to_owned(), t.to_string()),
-        }
-    }
-}
-
-/// Suggest restricting a type param with a new bound.
-pub fn suggest_constraining_type_param(
-    generics: &hir::Generics<'_>,
-    err: &mut DiagnosticBuilder<'_>,
-    param_name: &str,
-    constraint: &str,
-    source_map: &SourceMap,
-    span: Span,
-) -> bool {
-    let restrict_msg = "consider further restricting this bound";
-    if let Some(param) =
-        generics.params.iter().filter(|p| p.name.ident().as_str() == param_name).next()
-    {
-        if param_name.starts_with("impl ") {
-            // `impl Trait` in argument:
-            // `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
-            err.span_suggestion(
-                param.span,
-                restrict_msg,
-                // `impl CurrentTrait + MissingTrait`
-                format!("{} + {}", param_name, constraint),
-                Applicability::MachineApplicable,
-            );
-        } else if generics.where_clause.predicates.is_empty() && param.bounds.is_empty() {
-            // If there are no bounds whatsoever, suggest adding a constraint
-            // to the type parameter:
-            // `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
-            err.span_suggestion(
-                param.span,
-                "consider restricting this bound",
-                format!("{}: {}", param_name, constraint),
-                Applicability::MachineApplicable,
-            );
-        } else if !generics.where_clause.predicates.is_empty() {
-            // There is a `where` clause, so suggest expanding it:
-            // `fn foo<T>(t: T) where T: Debug {}` →
-            // `fn foo<T>(t: T) where T: Debug, T: Trait {}`
-            err.span_suggestion(
-                generics.where_clause.span().unwrap().shrink_to_hi(),
-                &format!("consider further restricting type parameter `{}`", param_name),
-                format!(", {}: {}", param_name, constraint),
-                Applicability::MachineApplicable,
-            );
-        } else {
-            // If there is no `where` clause lean towards constraining to the
-            // type parameter:
-            // `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
-            // `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
-            let sp = param.span.with_hi(span.hi());
-            let span = source_map.span_through_char(sp, ':');
-            if sp != param.span && sp != span {
-                // Only suggest if we have high certainty that the span
-                // covers the colon in `foo<T: Trait>`.
-                err.span_suggestion(
-                    span,
-                    restrict_msg,
-                    format!("{}: {} + ", param_name, constraint),
-                    Applicability::MachineApplicable,
-                );
-            } else {
-                err.span_label(
-                    param.span,
-                    &format!("consider adding a `where {}: {}` bound", param_name, constraint),
-                );
-            }
-        }
-        return true;
-    }
-    false
-}
diff --git a/src/librustc/traits/error_reporting/mod.rs b/src/librustc/traits/error_reporting/mod.rs
new file mode 100644 (file)
index 0000000..646cb80
--- /dev/null
@@ -0,0 +1,1410 @@
+pub mod on_unimplemented;
+pub mod suggestions;
+
+use super::{
+    ConstEvalFailure, EvaluationResult, FulfillmentError, FulfillmentErrorCode,
+    MismatchedProjectionTypes, ObjectSafetyViolation, Obligation, ObligationCause,
+    ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote,
+    OutputTypeParameterMismatch, Overflow, PredicateObligation, SelectionContext, SelectionError,
+    TraitNotObjectSafe,
+};
+
+use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
+use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use crate::infer::{self, InferCtxt};
+use crate::mir::interpret::ErrorHandled;
+use crate::session::DiagnosticMessageId;
+use crate::traits::object_safety_violations;
+use crate::ty::error::ExpectedFound;
+use crate::ty::fast_reject;
+use crate::ty::fold::TypeFolder;
+use crate::ty::SubtypePredicate;
+use crate::ty::{self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
+
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_span::source_map::SourceMap;
+use rustc_span::{ExpnKind, Span, DUMMY_SP};
+use std::fmt;
+use syntax::ast;
+
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+    pub fn report_fulfillment_errors(
+        &self,
+        errors: &[FulfillmentError<'tcx>],
+        body_id: Option<hir::BodyId>,
+        fallback_has_occurred: bool,
+    ) {
+        #[derive(Debug)]
+        struct ErrorDescriptor<'tcx> {
+            predicate: ty::Predicate<'tcx>,
+            index: Option<usize>, // None if this is an old error
+        }
+
+        let mut error_map: FxHashMap<_, Vec<_>> = self
+            .reported_trait_errors
+            .borrow()
+            .iter()
+            .map(|(&span, predicates)| {
+                (
+                    span,
+                    predicates
+                        .iter()
+                        .map(|predicate| ErrorDescriptor {
+                            predicate: predicate.clone(),
+                            index: None,
+                        })
+                        .collect(),
+                )
+            })
+            .collect();
+
+        for (index, error) in errors.iter().enumerate() {
+            // 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;
+            let expn_data = span.ctxt().outer_expn_data();
+            if let ExpnKind::Desugaring(_) = expn_data.kind {
+                span = expn_data.call_site;
+            }
+
+            error_map.entry(span).or_default().push(ErrorDescriptor {
+                predicate: error.obligation.predicate.clone(),
+                index: Some(index),
+            });
+
+            self.reported_trait_errors
+                .borrow_mut()
+                .entry(span)
+                .or_default()
+                .push(error.obligation.predicate.clone());
+        }
+
+        // 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() {
+            // We want to suppress "duplicate" errors with the same span.
+            for error in error_set {
+                if let Some(index) = error.index {
+                    // Suppress errors that are either:
+                    // 1) strictly implied by another error.
+                    // 2) implied by an error with a smaller index.
+                    for error2 in error_set {
+                        if error2.index.map_or(false, |index2| is_suppressed[index2]) {
+                            // Avoid errors being suppressed by already-suppressed
+                            // errors, to prevent all errors from being suppressed
+                            // at once.
+                            continue;
+                        }
+
+                        if self.error_implies(&error2.predicate, &error.predicate)
+                            && !(error2.index >= error.index
+                                && self.error_implies(&error.predicate, &error2.predicate))
+                        {
+                            info!("skipping {:?} (implied by {:?})", error, error2);
+                            is_suppressed[index] = true;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        for (error, suppressed) in errors.iter().zip(is_suppressed) {
+            if !suppressed {
+                self.report_fulfillment_error(error, body_id, fallback_has_occurred);
+            }
+        }
+    }
+
+    // returns if `cond` not occurring implies that `error` does not occur - i.e., that
+    // `error` occurring implies that `cond` occurs.
+    fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool {
+        if cond == error {
+            return true;
+        }
+
+        let (cond, error) = match (cond, error) {
+            (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error)) => (cond, error),
+            _ => {
+                // FIXME: make this work in other cases too.
+                return false;
+            }
+        };
+
+        for implication in super::elaborate_predicates(self.tcx, vec![cond.clone()]) {
+            if let ty::Predicate::Trait(implication) = implication {
+                let error = error.to_poly_trait_ref();
+                let implication = implication.to_poly_trait_ref();
+                // FIXME: I'm just not taking associated types at all here.
+                // Eventually I'll need to implement param-env-aware
+                // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
+                let param_env = ty::ParamEnv::empty();
+                if self.can_sub(param_env, error, implication).is_ok() {
+                    debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
+                    return true;
+                }
+            }
+        }
+
+        false
+    }
+
+    fn report_fulfillment_error(
+        &self,
+        error: &FulfillmentError<'tcx>,
+        body_id: Option<hir::BodyId>,
+        fallback_has_occurred: bool,
+    ) {
+        debug!("report_fulfillment_error({:?})", error);
+        match error.code {
+            FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
+                self.report_selection_error(
+                    &error.obligation,
+                    selection_error,
+                    fallback_has_occurred,
+                    error.points_at_arg_span,
+                );
+            }
+            FulfillmentErrorCode::CodeProjectionError(ref e) => {
+                self.report_projection_error(&error.obligation, e);
+            }
+            FulfillmentErrorCode::CodeAmbiguity => {
+                self.maybe_report_ambiguity(&error.obligation, body_id);
+            }
+            FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
+                self.report_mismatched_types(
+                    &error.obligation.cause,
+                    expected_found.expected,
+                    expected_found.found,
+                    err.clone(),
+                )
+                .emit();
+            }
+        }
+    }
+
+    fn report_projection_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        error: &MismatchedProjectionTypes<'tcx>,
+    ) {
+        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
+
+        if predicate.references_error() {
+            return;
+        }
+
+        self.probe(|_| {
+            let err_buf;
+            let mut err = &error.err;
+            let mut values = None;
+
+            // try to find the mismatched types to report the error with.
+            //
+            // this can fail if the problem was higher-ranked, in which
+            // cause I have no idea for a good error message.
+            if let ty::Predicate::Projection(ref data) = predicate {
+                let mut selcx = SelectionContext::new(self);
+                let (data, _) = self.replace_bound_vars_with_fresh_vars(
+                    obligation.cause.span,
+                    infer::LateBoundRegionConversionTime::HigherRankedType,
+                    data,
+                );
+                let mut obligations = vec![];
+                let normalized_ty = super::normalize_projection_type(
+                    &mut selcx,
+                    obligation.param_env,
+                    data.projection_ty,
+                    obligation.cause.clone(),
+                    0,
+                    &mut obligations,
+                );
+
+                debug!(
+                    "report_projection_error obligation.cause={:?} obligation.param_env={:?}",
+                    obligation.cause, obligation.param_env
+                );
+
+                debug!(
+                    "report_projection_error normalized_ty={:?} data.ty={:?}",
+                    normalized_ty, data.ty
+                );
+
+                let is_normalized_ty_expected = match &obligation.cause.code {
+                    ObligationCauseCode::ItemObligation(_)
+                    | ObligationCauseCode::BindingObligation(_, _)
+                    | ObligationCauseCode::ObjectCastObligation(_) => false,
+                    _ => true,
+                };
+
+                if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp(
+                    is_normalized_ty_expected,
+                    normalized_ty,
+                    data.ty,
+                ) {
+                    values = Some(infer::ValuePairs::Types(ExpectedFound::new(
+                        is_normalized_ty_expected,
+                        normalized_ty,
+                        data.ty,
+                    )));
+
+                    err_buf = error;
+                    err = &err_buf;
+                }
+            }
+
+            let msg = format!("type mismatch resolving `{}`", predicate);
+            let error_id = (DiagnosticMessageId::ErrorId(271), Some(obligation.cause.span), msg);
+            let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
+            if fresh {
+                let mut diag = struct_span_err!(
+                    self.tcx.sess,
+                    obligation.cause.span,
+                    E0271,
+                    "type mismatch resolving `{}`",
+                    predicate
+                );
+                self.note_type_err(&mut diag, &obligation.cause, None, values, err);
+                self.note_obligation_cause(&mut diag, obligation);
+                diag.emit();
+            }
+        });
+    }
+
+    fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
+        /// returns the fuzzy category of a given type, or None
+        /// if the type can be equated to any type.
+        fn type_category(t: Ty<'_>) -> Option<u32> {
+            match t.kind {
+                ty::Bool => Some(0),
+                ty::Char => Some(1),
+                ty::Str => Some(2),
+                ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3),
+                ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4),
+                ty::Ref(..) | ty::RawPtr(..) => Some(5),
+                ty::Array(..) | ty::Slice(..) => Some(6),
+                ty::FnDef(..) | ty::FnPtr(..) => Some(7),
+                ty::Dynamic(..) => Some(8),
+                ty::Closure(..) => Some(9),
+                ty::Tuple(..) => Some(10),
+                ty::Projection(..) => Some(11),
+                ty::Param(..) => Some(12),
+                ty::Opaque(..) => Some(13),
+                ty::Never => Some(14),
+                ty::Adt(adt, ..) => match adt.adt_kind() {
+                    AdtKind::Struct => Some(15),
+                    AdtKind::Union => Some(16),
+                    AdtKind::Enum => Some(17),
+                },
+                ty::Generator(..) => Some(18),
+                ty::Foreign(..) => Some(19),
+                ty::GeneratorWitness(..) => Some(20),
+                ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None,
+                ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+            }
+        }
+
+        match (type_category(a), type_category(b)) {
+            (Some(cat_a), Some(cat_b)) => match (&a.kind, &b.kind) {
+                (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b,
+                _ => cat_a == cat_b,
+            },
+            // infer and error can be equated to all types
+            _ => true,
+        }
+    }
+
+    fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
+        self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind {
+            hir::GeneratorKind::Gen => "a generator",
+            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block",
+            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function",
+            hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure",
+        })
+    }
+
+    fn find_similar_impl_candidates(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Vec<ty::TraitRef<'tcx>> {
+        let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true);
+        let all_impls = self.tcx.all_impls(trait_ref.def_id());
+
+        match simp {
+            Some(simp) => all_impls
+                .iter()
+                .filter_map(|&def_id| {
+                    let imp = self.tcx.impl_trait_ref(def_id).unwrap();
+                    let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true);
+                    if let Some(imp_simp) = imp_simp {
+                        if simp != imp_simp {
+                            return None;
+                        }
+                    }
+
+                    Some(imp)
+                })
+                .collect(),
+            None => {
+                all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect()
+            }
+        }
+    }
+
+    fn report_similar_impl_candidates(
+        &self,
+        impl_candidates: Vec<ty::TraitRef<'tcx>>,
+        err: &mut DiagnosticBuilder<'_>,
+    ) {
+        if impl_candidates.is_empty() {
+            return;
+        }
+
+        let len = impl_candidates.len();
+        let end = if impl_candidates.len() <= 5 { impl_candidates.len() } else { 4 };
+
+        let normalize = |candidate| {
+            self.tcx.infer_ctxt().enter(|ref infcx| {
+                let normalized = infcx
+                    .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
+                    .normalize(candidate)
+                    .ok();
+                match normalized {
+                    Some(normalized) => format!("\n  {:?}", normalized.value),
+                    None => format!("\n  {:?}", candidate),
+                }
+            })
+        };
+
+        // Sort impl candidates so that ordering is consistent for UI tests.
+        let mut normalized_impl_candidates =
+            impl_candidates.iter().map(normalize).collect::<Vec<String>>();
+
+        // Sort before taking the `..end` range,
+        // because the ordering of `impl_candidates` may not be deterministic:
+        // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
+        normalized_impl_candidates.sort();
+
+        err.help(&format!(
+            "the following implementations were found:{}{}",
+            normalized_impl_candidates[..end].join(""),
+            if len > 5 { format!("\nand {} others", len - 4) } else { String::new() }
+        ));
+    }
+
+    /// Reports that an overflow has occurred and halts compilation. We
+    /// halt compilation unconditionally because it is important that
+    /// overflows never be masked -- they basically represent computations
+    /// whose result could not be truly determined and thus we can't say
+    /// if the program type checks or not -- and they are unusual
+    /// occurrences in any case.
+    pub fn report_overflow_error<T>(
+        &self,
+        obligation: &Obligation<'tcx, T>,
+        suggest_increasing_limit: bool,
+    ) -> !
+    where
+        T: fmt::Display + TypeFoldable<'tcx>,
+    {
+        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            obligation.cause.span,
+            E0275,
+            "overflow evaluating the requirement `{}`",
+            predicate
+        );
+
+        if suggest_increasing_limit {
+            self.suggest_new_overflow_limit(&mut err);
+        }
+
+        self.note_obligation_cause_code(
+            &mut err,
+            &obligation.predicate,
+            &obligation.cause.code,
+            &mut vec![],
+        );
+
+        err.emit();
+        self.tcx.sess.abort_if_errors();
+        bug!();
+    }
+
+    /// Reports that a cycle was detected which led to overflow and halts
+    /// compilation. This is equivalent to `report_overflow_error` except
+    /// that we can give a more helpful error message (and, in particular,
+    /// we do not suggest increasing the overflow limit, which is not
+    /// going to help).
+    pub fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
+        let cycle = self.resolve_vars_if_possible(&cycle.to_owned());
+        assert!(cycle.len() > 0);
+
+        debug!("report_overflow_error_cycle: cycle={:?}", cycle);
+
+        self.report_overflow_error(&cycle[0], false);
+    }
+
+    pub fn report_extra_impl_obligation(
+        &self,
+        error_span: Span,
+        item_name: ast::Name,
+        _impl_item_def_id: DefId,
+        trait_item_def_id: DefId,
+        requirement: &dyn fmt::Display,
+    ) -> DiagnosticBuilder<'tcx> {
+        let msg = "impl has stricter requirements than trait";
+        let sp = self.tcx.sess.source_map().def_span(error_span);
+
+        let mut err = struct_span_err!(self.tcx.sess, sp, E0276, "{}", msg);
+
+        if let Some(trait_item_span) = self.tcx.hir().span_if_local(trait_item_def_id) {
+            let span = self.tcx.sess.source_map().def_span(trait_item_span);
+            err.span_label(span, format!("definition of `{}` from trait", item_name));
+        }
+
+        err.span_label(sp, format!("impl has extra requirement {}", requirement));
+
+        err
+    }
+
+    /// Gets the parent trait chain start
+    fn get_parent_trait_ref(
+        &self,
+        code: &ObligationCauseCode<'tcx>,
+    ) -> Option<(String, Option<Span>)> {
+        match code {
+            &ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
+                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
+                match self.get_parent_trait_ref(&data.parent_code) {
+                    Some(t) => Some(t),
+                    None => {
+                        let ty = parent_trait_ref.skip_binder().self_ty();
+                        let span =
+                            TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id));
+                        Some((ty.to_string(), span))
+                    }
+                }
+            }
+            _ => None,
+        }
+    }
+
+    pub fn report_selection_error(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        error: &SelectionError<'tcx>,
+        fallback_has_occurred: bool,
+        points_at_arg: bool,
+    ) {
+        let tcx = self.tcx;
+        let span = obligation.cause.span;
+
+        let mut err = match *error {
+            SelectionError::Unimplemented => {
+                if let ObligationCauseCode::CompareImplMethodObligation {
+                    item_name,
+                    impl_item_def_id,
+                    trait_item_def_id,
+                }
+                | ObligationCauseCode::CompareImplTypeObligation {
+                    item_name,
+                    impl_item_def_id,
+                    trait_item_def_id,
+                } = obligation.cause.code
+                {
+                    self.report_extra_impl_obligation(
+                        span,
+                        item_name,
+                        impl_item_def_id,
+                        trait_item_def_id,
+                        &format!("`{}`", obligation.predicate),
+                    )
+                    .emit();
+                    return;
+                }
+                match obligation.predicate {
+                    ty::Predicate::Trait(ref trait_predicate) => {
+                        let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
+
+                        if self.tcx.sess.has_errors() && trait_predicate.references_error() {
+                            return;
+                        }
+                        let trait_ref = trait_predicate.to_poly_trait_ref();
+                        let (post_message, pre_message, type_def) = self
+                            .get_parent_trait_ref(&obligation.cause.code)
+                            .map(|(t, s)| {
+                                (
+                                    format!(" in `{}`", t),
+                                    format!("within `{}`, ", t),
+                                    s.map(|s| (format!("within this `{}`", t), s)),
+                                )
+                            })
+                            .unwrap_or_default();
+
+                        let OnUnimplementedNote { message, label, note, enclosing_scope } =
+                            self.on_unimplemented_note(trait_ref, obligation);
+                        let have_alt_message = message.is_some() || label.is_some();
+                        let is_try = self
+                            .tcx
+                            .sess
+                            .source_map()
+                            .span_to_snippet(span)
+                            .map(|s| &s == "?")
+                            .unwrap_or(false);
+                        let is_from = format!("{}", trait_ref.print_only_trait_path())
+                            .starts_with("std::convert::From<");
+                        let (message, note) = if is_try && is_from {
+                            (
+                                Some(format!(
+                                    "`?` couldn't convert the error to `{}`",
+                                    trait_ref.self_ty(),
+                                )),
+                                Some(
+                                    "the question mark operation (`?`) implicitly performs a \
+                                     conversion on the error value using the `From` trait"
+                                        .to_owned(),
+                                ),
+                            )
+                        } else {
+                            (message, note)
+                        };
+
+                        let mut err = struct_span_err!(
+                            self.tcx.sess,
+                            span,
+                            E0277,
+                            "{}",
+                            message.unwrap_or_else(|| format!(
+                                "the trait bound `{}` is not satisfied{}",
+                                trait_ref.to_predicate(),
+                                post_message,
+                            ))
+                        );
+
+                        let explanation =
+                            if obligation.cause.code == ObligationCauseCode::MainFunctionType {
+                                "consider using `()`, or a `Result`".to_owned()
+                            } else {
+                                format!(
+                                    "{}the trait `{}` is not implemented for `{}`",
+                                    pre_message,
+                                    trait_ref.print_only_trait_path(),
+                                    trait_ref.self_ty(),
+                                )
+                            };
+
+                        if self.suggest_add_reference_to_arg(
+                            &obligation,
+                            &mut err,
+                            &trait_ref,
+                            points_at_arg,
+                            have_alt_message,
+                        ) {
+                            self.note_obligation_cause(&mut err, obligation);
+                            err.emit();
+                            return;
+                        }
+                        if let Some(ref s) = label {
+                            // If it has a custom `#[rustc_on_unimplemented]`
+                            // error message, let's display it as the label!
+                            err.span_label(span, s.as_str());
+                            err.help(&explanation);
+                        } else {
+                            err.span_label(span, explanation);
+                        }
+                        if let Some((msg, span)) = type_def {
+                            err.span_label(span, &msg);
+                        }
+                        if let Some(ref s) = note {
+                            // If it has a custom `#[rustc_on_unimplemented]` note, let's display it
+                            err.note(s.as_str());
+                        }
+                        if let Some(ref s) = enclosing_scope {
+                            let enclosing_scope_span = tcx.def_span(
+                                tcx.hir()
+                                    .opt_local_def_id(obligation.cause.body_id)
+                                    .unwrap_or_else(|| {
+                                        tcx.hir().body_owner_def_id(hir::BodyId {
+                                            hir_id: obligation.cause.body_id,
+                                        })
+                                    }),
+                            );
+
+                            err.span_label(enclosing_scope_span, s.as_str());
+                        }
+
+                        self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
+                        self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg);
+                        self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
+                        self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
+                        self.note_version_mismatch(&mut err, &trait_ref);
+                        if self.suggest_impl_trait(&mut err, span, &obligation, &trait_ref) {
+                            err.emit();
+                            return;
+                        }
+
+                        // Try to report a help message
+                        if !trait_ref.has_infer_types()
+                            && self.predicate_can_apply(obligation.param_env, trait_ref)
+                        {
+                            // If a where-clause may be useful, remind the
+                            // user that they can add it.
+                            //
+                            // don't display an on-unimplemented note, as
+                            // these notes will often be of the form
+                            //     "the type `T` can't be frobnicated"
+                            // which is somewhat confusing.
+                            self.suggest_restricting_param_bound(
+                                &mut err,
+                                &trait_ref,
+                                obligation.cause.body_id,
+                            );
+                        } else {
+                            if !have_alt_message {
+                                // Can't show anything else useful, try to find similar impls.
+                                let impl_candidates = self.find_similar_impl_candidates(trait_ref);
+                                self.report_similar_impl_candidates(impl_candidates, &mut err);
+                            }
+                            self.suggest_change_mut(
+                                &obligation,
+                                &mut err,
+                                &trait_ref,
+                                points_at_arg,
+                            );
+                        }
+
+                        // If this error is due to `!: Trait` not implemented but `(): Trait` is
+                        // implemented, and fallback has occurred, then it could be due to a
+                        // variable that used to fallback to `()` now falling back to `!`. Issue a
+                        // note informing about the change in behaviour.
+                        if trait_predicate.skip_binder().self_ty().is_never()
+                            && fallback_has_occurred
+                        {
+                            let predicate = trait_predicate.map_bound(|mut trait_pred| {
+                                trait_pred.trait_ref.substs = self.tcx.mk_substs_trait(
+                                    self.tcx.mk_unit(),
+                                    &trait_pred.trait_ref.substs[1..],
+                                );
+                                trait_pred
+                            });
+                            let unit_obligation = Obligation {
+                                predicate: ty::Predicate::Trait(predicate),
+                                ..obligation.clone()
+                            };
+                            if self.predicate_may_hold(&unit_obligation) {
+                                err.note(
+                                    "the trait is implemented for `()`. \
+                                         Possibly this error has been caused by changes to \
+                                         Rust's type-inference algorithm \
+                                         (see: https://github.com/rust-lang/rust/issues/48950 \
+                                         for more info). Consider whether you meant to use the \
+                                         type `()` here instead.",
+                                );
+                            }
+                        }
+
+                        err
+                    }
+
+                    ty::Predicate::Subtype(ref predicate) => {
+                        // Errors for Subtype predicates show up as
+                        // `FulfillmentErrorCode::CodeSubtypeError`,
+                        // not selection error.
+                        span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
+                    }
+
+                    ty::Predicate::RegionOutlives(ref predicate) => {
+                        let predicate = self.resolve_vars_if_possible(predicate);
+                        let err = self
+                            .region_outlives_predicate(&obligation.cause, &predicate)
+                            .err()
+                            .unwrap();
+                        struct_span_err!(
+                            self.tcx.sess,
+                            span,
+                            E0279,
+                            "the requirement `{}` is not satisfied (`{}`)",
+                            predicate,
+                            err,
+                        )
+                    }
+
+                    ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
+                        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
+                        struct_span_err!(
+                            self.tcx.sess,
+                            span,
+                            E0280,
+                            "the requirement `{}` is not satisfied",
+                            predicate
+                        )
+                    }
+
+                    ty::Predicate::ObjectSafe(trait_def_id) => {
+                        let violations = object_safety_violations(self.tcx, trait_def_id);
+                        report_object_safety_error(self.tcx, span, trait_def_id, violations)
+                    }
+
+                    ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
+                        let found_kind = self.closure_kind(closure_def_id, closure_substs).unwrap();
+                        let closure_span = self
+                            .tcx
+                            .sess
+                            .source_map()
+                            .def_span(self.tcx.hir().span_if_local(closure_def_id).unwrap());
+                        let hir_id = self.tcx.hir().as_local_hir_id(closure_def_id).unwrap();
+                        let mut err = struct_span_err!(
+                            self.tcx.sess,
+                            closure_span,
+                            E0525,
+                            "expected a closure that implements the `{}` trait, \
+                             but this closure only implements `{}`",
+                            kind,
+                            found_kind
+                        );
+
+                        err.span_label(
+                            closure_span,
+                            format!("this closure implements `{}`, not `{}`", found_kind, kind),
+                        );
+                        err.span_label(
+                            obligation.cause.span,
+                            format!("the requirement to implement `{}` derives from here", kind),
+                        );
+
+                        // Additional context information explaining why the closure only implements
+                        // a particular trait.
+                        if let Some(tables) = self.in_progress_tables {
+                            let tables = tables.borrow();
+                            match (found_kind, tables.closure_kind_origins().get(hir_id)) {
+                                (ty::ClosureKind::FnOnce, Some((span, name))) => {
+                                    err.span_label(
+                                        *span,
+                                        format!(
+                                            "closure is `FnOnce` because it moves the \
+                                         variable `{}` out of its environment",
+                                            name
+                                        ),
+                                    );
+                                }
+                                (ty::ClosureKind::FnMut, Some((span, name))) => {
+                                    err.span_label(
+                                        *span,
+                                        format!(
+                                            "closure is `FnMut` because it mutates the \
+                                         variable `{}` here",
+                                            name
+                                        ),
+                                    );
+                                }
+                                _ => {}
+                            }
+                        }
+
+                        err.emit();
+                        return;
+                    }
+
+                    ty::Predicate::WellFormed(ty) => {
+                        if !self.tcx.sess.opts.debugging_opts.chalk {
+                            // WF predicates cannot themselves make
+                            // errors. They can only block due to
+                            // ambiguity; otherwise, they always
+                            // degenerate into other obligations
+                            // (which may fail).
+                            span_bug!(span, "WF predicate not satisfied for {:?}", ty);
+                        } else {
+                            // FIXME: we'll need a better message which takes into account
+                            // which bounds actually failed to hold.
+                            self.tcx.sess.struct_span_err(
+                                span,
+                                &format!("the type `{}` is not well-formed (chalk)", ty),
+                            )
+                        }
+                    }
+
+                    ty::Predicate::ConstEvaluatable(..) => {
+                        // Errors for `ConstEvaluatable` predicates show up as
+                        // `SelectionError::ConstEvalFailure`,
+                        // not `Unimplemented`.
+                        span_bug!(
+                            span,
+                            "const-evaluatable requirement gave wrong error: `{:?}`",
+                            obligation
+                        )
+                    }
+                }
+            }
+
+            OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => {
+                let found_trait_ref = self.resolve_vars_if_possible(&*found_trait_ref);
+                let expected_trait_ref = self.resolve_vars_if_possible(&*expected_trait_ref);
+
+                if expected_trait_ref.self_ty().references_error() {
+                    return;
+                }
+
+                let found_trait_ty = found_trait_ref.self_ty();
+
+                let found_did = match found_trait_ty.kind {
+                    ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did),
+                    ty::Adt(def, _) => Some(def.did),
+                    _ => None,
+                };
+
+                let found_span = found_did
+                    .and_then(|did| self.tcx.hir().span_if_local(did))
+                    .map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def
+
+                if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
+                    // We check closures twice, with obligations flowing in different directions,
+                    // but we want to complain about them only once.
+                    return;
+                }
+
+                self.reported_closure_mismatch.borrow_mut().insert((span, found_span));
+
+                let found = match found_trait_ref.skip_binder().substs.type_at(1).kind {
+                    ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()],
+                    _ => vec![ArgKind::empty()],
+                };
+
+                let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1);
+                let expected = match expected_ty.kind {
+                    ty::Tuple(ref tys) => tys
+                        .iter()
+                        .map(|t| ArgKind::from_expected_ty(t.expect_ty(), Some(span)))
+                        .collect(),
+                    _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())],
+                };
+
+                if found.len() == expected.len() {
+                    self.report_closure_arg_mismatch(
+                        span,
+                        found_span,
+                        found_trait_ref,
+                        expected_trait_ref,
+                    )
+                } else {
+                    let (closure_span, found) = found_did
+                        .and_then(|did| self.tcx.hir().get_if_local(did))
+                        .map(|node| {
+                            let (found_span, found) = self.get_fn_like_arguments(node);
+                            (Some(found_span), found)
+                        })
+                        .unwrap_or((found_span, found));
+
+                    self.report_arg_count_mismatch(
+                        span,
+                        closure_span,
+                        expected,
+                        found,
+                        found_trait_ty.is_closure(),
+                    )
+                }
+            }
+
+            TraitNotObjectSafe(did) => {
+                let violations = object_safety_violations(self.tcx, did);
+                report_object_safety_error(self.tcx, span, did, violations)
+            }
+
+            // already reported in the query
+            ConstEvalFailure(err) => {
+                if let ErrorHandled::TooGeneric = err {
+                    // Silence this error, as it can be produced during intermediate steps
+                    // when a constant is not yet able to be evaluated (but will be later).
+                    return;
+                }
+                self.tcx.sess.delay_span_bug(
+                    span,
+                    &format!("constant in type had an ignored error: {:?}", err),
+                );
+                return;
+            }
+
+            Overflow => {
+                bug!("overflow should be handled before the `report_selection_error` path");
+            }
+        };
+
+        self.note_obligation_cause(&mut err, obligation);
+        self.point_at_returns_when_relevant(&mut err, &obligation);
+
+        err.emit();
+    }
+
+    /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
+    /// with the same path as `trait_ref`, a help message about
+    /// a probable version mismatch is added to `err`
+    fn note_version_mismatch(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        trait_ref: &ty::PolyTraitRef<'tcx>,
+    ) {
+        let get_trait_impl = |trait_def_id| {
+            let mut trait_impl = None;
+            self.tcx.for_each_relevant_impl(trait_def_id, trait_ref.self_ty(), |impl_def_id| {
+                if trait_impl.is_none() {
+                    trait_impl = Some(impl_def_id);
+                }
+            });
+            trait_impl
+        };
+        let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
+        let all_traits = self.tcx.all_traits(LOCAL_CRATE);
+        let traits_with_same_path: std::collections::BTreeSet<_> = all_traits
+            .iter()
+            .filter(|trait_def_id| **trait_def_id != trait_ref.def_id())
+            .filter(|trait_def_id| self.tcx.def_path_str(**trait_def_id) == required_trait_path)
+            .collect();
+        for trait_with_same_path in traits_with_same_path {
+            if let Some(impl_def_id) = get_trait_impl(*trait_with_same_path) {
+                let impl_span = self.tcx.def_span(impl_def_id);
+                err.span_help(impl_span, "trait impl with same name found");
+                let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
+                let crate_msg = format!(
+                    "perhaps two different versions of crate `{}` are being used?",
+                    trait_crate
+                );
+                err.note(&crate_msg);
+            }
+        }
+    }
+
+    fn mk_obligation_for_def_id(
+        &self,
+        def_id: DefId,
+        output_ty: Ty<'tcx>,
+        cause: ObligationCause<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> PredicateObligation<'tcx> {
+        let new_trait_ref =
+            ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
+        Obligation::new(cause, param_env, new_trait_ref.to_predicate())
+    }
+}
+
+pub fn recursive_type_with_infinite_size_error(
+    tcx: TyCtxt<'tcx>,
+    type_def_id: DefId,
+) -> DiagnosticBuilder<'tcx> {
+    assert!(type_def_id.is_local());
+    let span = tcx.hir().span_if_local(type_def_id).unwrap();
+    let span = tcx.sess.source_map().def_span(span);
+    let mut err = struct_span_err!(
+        tcx.sess,
+        span,
+        E0072,
+        "recursive type `{}` has infinite size",
+        tcx.def_path_str(type_def_id)
+    );
+    err.span_label(span, "recursive type has infinite size");
+    err.help(&format!(
+        "insert indirection (e.g., a `Box`, `Rc`, or `&`) \
+                           at some point to make `{}` representable",
+        tcx.def_path_str(type_def_id)
+    ));
+    err
+}
+
+pub fn report_object_safety_error(
+    tcx: TyCtxt<'tcx>,
+    span: Span,
+    trait_def_id: DefId,
+    violations: Vec<ObjectSafetyViolation>,
+) -> DiagnosticBuilder<'tcx> {
+    let trait_str = tcx.def_path_str(trait_def_id);
+    let span = tcx.sess.source_map().def_span(span);
+    let mut err = struct_span_err!(
+        tcx.sess,
+        span,
+        E0038,
+        "the trait `{}` cannot be made into an object",
+        trait_str
+    );
+    err.span_label(span, format!("the trait `{}` cannot be made into an object", trait_str));
+
+    let mut reported_violations = FxHashSet::default();
+    for violation in violations {
+        if reported_violations.insert(violation.clone()) {
+            match violation.span() {
+                Some(span) => err.span_label(span, violation.error_msg()),
+                None => err.note(&violation.error_msg()),
+            };
+        }
+    }
+
+    if tcx.sess.trait_methods_not_found.borrow().contains(&span) {
+        // Avoid emitting error caused by non-existing method (#58734)
+        err.cancel();
+    }
+
+    err
+}
+
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+    fn maybe_report_ambiguity(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        body_id: Option<hir::BodyId>,
+    ) {
+        // Unable to successfully determine, probably means
+        // insufficient type information, but could mean
+        // ambiguous impls. The latter *ought* to be a
+        // coherence violation, so we don't report it here.
+
+        let predicate = self.resolve_vars_if_possible(&obligation.predicate);
+        let span = obligation.cause.span;
+
+        debug!(
+            "maybe_report_ambiguity(predicate={:?}, obligation={:?} body_id={:?}, code={:?})",
+            predicate, obligation, body_id, obligation.cause.code,
+        );
+
+        // Ambiguity errors are often caused as fallout from earlier
+        // errors. So just ignore them if this infcx is tainted.
+        if self.is_tainted_by_errors() {
+            return;
+        }
+
+        let mut err = match predicate {
+            ty::Predicate::Trait(ref data) => {
+                let trait_ref = data.to_poly_trait_ref();
+                let self_ty = trait_ref.self_ty();
+                debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref);
+
+                if predicate.references_error() {
+                    return;
+                }
+                // Typically, this ambiguity should only happen if
+                // there are unresolved type inference variables
+                // (otherwise it would suggest a coherence
+                // failure). But given #21974 that is not necessarily
+                // the case -- we can have multiple where clauses that
+                // are only distinguished by a region, which results
+                // in an ambiguity even when all types are fully
+                // known, since we don't dispatch based on region
+                // relationships.
+
+                // This is kind of a hack: it frequently happens that some earlier
+                // error prevents types from being fully inferred, and then we get
+                // a bunch of uninteresting errors saying something like "<generic
+                // #0> doesn't implement Sized".  It may even be true that we
+                // could just skip over all checks where the self-ty is an
+                // inference variable, but I was afraid that there might be an
+                // inference variable created, registered as an obligation, and
+                // then never forced by writeback, and hence by skipping here we'd
+                // be ignoring the fact that we don't KNOW the type works
+                // out. Though even that would probably be harmless, given that
+                // we're only talking about builtin traits, which are known to be
+                // inhabited. We used to check for `self.tcx.sess.has_errors()` to
+                // avoid inundating the user with unnecessary errors, but we now
+                // check upstream for type errors and dont add the obligations to
+                // begin with in those cases.
+                if self
+                    .tcx
+                    .lang_items()
+                    .sized_trait()
+                    .map_or(false, |sized_id| sized_id == trait_ref.def_id())
+                {
+                    self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit();
+                    return;
+                }
+                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283);
+                err.note(&format!("cannot resolve `{}`", predicate));
+                if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code {
+                    self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
+                } else if let (
+                    Ok(ref snippet),
+                    ObligationCauseCode::BindingObligation(ref def_id, _),
+                ) =
+                    (self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code)
+                {
+                    let generics = self.tcx.generics_of(*def_id);
+                    if !generics.params.is_empty() && !snippet.ends_with('>') {
+                        // FIXME: To avoid spurious suggestions in functions where type arguments
+                        // where already supplied, we check the snippet to make sure it doesn't
+                        // end with a turbofish. Ideally we would have access to a `PathSegment`
+                        // instead. Otherwise we would produce the following output:
+                        //
+                        // error[E0283]: type annotations needed
+                        //   --> $DIR/issue-54954.rs:3:24
+                        //    |
+                        // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
+                        //    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+                        //    |                        |
+                        //    |                        cannot infer type
+                        //    |                        help: consider specifying the type argument
+                        //    |                        in the function call:
+                        //    |                        `Tt::const_val::<[i8; 123]>::<T>`
+                        // ...
+                        // LL |     const fn const_val<T: Sized>() -> usize {
+                        //    |              --------- - required by this bound in `Tt::const_val`
+                        //    |
+                        //    = note: cannot resolve `_: Tt`
+
+                        err.span_suggestion(
+                            span,
+                            &format!(
+                                "consider specifying the type argument{} in the function call",
+                                if generics.params.len() > 1 { "s" } else { "" },
+                            ),
+                            format!(
+                                "{}::<{}>",
+                                snippet,
+                                generics
+                                    .params
+                                    .iter()
+                                    .map(|p| p.name.to_string())
+                                    .collect::<Vec<String>>()
+                                    .join(", ")
+                            ),
+                            Applicability::HasPlaceholders,
+                        );
+                    }
+                }
+                err
+            }
+
+            ty::Predicate::WellFormed(ty) => {
+                // Same hacky approach as above to avoid deluging user
+                // with error messages.
+                if ty.references_error() || self.tcx.sess.has_errors() {
+                    return;
+                }
+                self.need_type_info_err(body_id, span, ty, ErrorCode::E0282)
+            }
+
+            ty::Predicate::Subtype(ref data) => {
+                if data.references_error() || self.tcx.sess.has_errors() {
+                    // no need to overload user in such cases
+                    return;
+                }
+                let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
+                // both must be type variables, or the other would've been instantiated
+                assert!(a.is_ty_var() && b.is_ty_var());
+                self.need_type_info_err(body_id, span, a, ErrorCode::E0282)
+            }
+            ty::Predicate::Projection(ref data) => {
+                let trait_ref = data.to_poly_trait_ref(self.tcx);
+                let self_ty = trait_ref.self_ty();
+                if predicate.references_error() {
+                    return;
+                }
+                let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284);
+                err.note(&format!("cannot resolve `{}`", predicate));
+                err
+            }
+
+            _ => {
+                if self.tcx.sess.has_errors() {
+                    return;
+                }
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0284,
+                    "type annotations needed: cannot resolve `{}`",
+                    predicate,
+                );
+                err.span_label(span, &format!("cannot resolve `{}`", predicate));
+                err
+            }
+        };
+        self.note_obligation_cause(&mut err, obligation);
+        err.emit();
+    }
+
+    /// Returns `true` if the trait predicate may apply for *some* assignment
+    /// to the type parameters.
+    fn predicate_can_apply(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        pred: ty::PolyTraitRef<'tcx>,
+    ) -> bool {
+        struct ParamToVarFolder<'a, 'tcx> {
+            infcx: &'a InferCtxt<'a, 'tcx>,
+            var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>,
+        }
+
+        impl<'a, 'tcx> TypeFolder<'tcx> for ParamToVarFolder<'a, 'tcx> {
+            fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+                self.infcx.tcx
+            }
+
+            fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
+                if let ty::Param(ty::ParamTy { name, .. }) = ty.kind {
+                    let infcx = self.infcx;
+                    self.var_map.entry(ty).or_insert_with(|| {
+                        infcx.next_ty_var(TypeVariableOrigin {
+                            kind: TypeVariableOriginKind::TypeParameterDefinition(name, None),
+                            span: DUMMY_SP,
+                        })
+                    })
+                } else {
+                    ty.super_fold_with(self)
+                }
+            }
+        }
+
+        self.probe(|_| {
+            let mut selcx = SelectionContext::new(self);
+
+            let cleaned_pred =
+                pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() });
+
+            let cleaned_pred = super::project::normalize(
+                &mut selcx,
+                param_env,
+                ObligationCause::dummy(),
+                &cleaned_pred,
+            )
+            .value;
+
+            let obligation =
+                Obligation::new(ObligationCause::dummy(), param_env, cleaned_pred.to_predicate());
+
+            self.predicate_may_hold(&obligation)
+        })
+    }
+
+    fn note_obligation_cause(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        obligation: &PredicateObligation<'tcx>,
+    ) {
+        // First, attempt to add note to this error with an async-await-specific
+        // message, and fall back to regular note otherwise.
+        if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
+            self.note_obligation_cause_code(
+                err,
+                &obligation.predicate,
+                &obligation.cause.code,
+                &mut vec![],
+            );
+        }
+    }
+
+    fn is_recursive_obligation(
+        &self,
+        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
+        cause_code: &ObligationCauseCode<'tcx>,
+    ) -> bool {
+        if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
+            let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
+
+            if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) {
+                return true;
+            }
+        }
+        false
+    }
+}
+
+/// Summarizes information
+#[derive(Clone)]
+pub enum ArgKind {
+    /// An argument of non-tuple type. Parameters are (name, ty)
+    Arg(String, String),
+
+    /// An argument of tuple type. For a "found" argument, the span is
+    /// the locationo in the source of the pattern. For a "expected"
+    /// argument, it will be None. The vector is a list of (name, ty)
+    /// strings for the components of the tuple.
+    Tuple(Option<Span>, Vec<(String, String)>),
+}
+
+impl ArgKind {
+    fn empty() -> ArgKind {
+        ArgKind::Arg("_".to_owned(), "_".to_owned())
+    }
+
+    /// Creates an `ArgKind` from the expected type of an
+    /// argument. It has no name (`_`) and an optional source span.
+    pub fn from_expected_ty(t: Ty<'_>, span: Option<Span>) -> ArgKind {
+        match t.kind {
+            ty::Tuple(ref tys) => ArgKind::Tuple(
+                span,
+                tys.iter().map(|ty| ("_".to_owned(), ty.to_string())).collect::<Vec<_>>(),
+            ),
+            _ => ArgKind::Arg("_".to_owned(), t.to_string()),
+        }
+    }
+}
+
+/// Suggest restricting a type param with a new bound.
+pub fn suggest_constraining_type_param(
+    generics: &hir::Generics<'_>,
+    err: &mut DiagnosticBuilder<'_>,
+    param_name: &str,
+    constraint: &str,
+    source_map: &SourceMap,
+    span: Span,
+) -> bool {
+    let restrict_msg = "consider further restricting this bound";
+    if let Some(param) =
+        generics.params.iter().filter(|p| p.name.ident().as_str() == param_name).next()
+    {
+        if param_name.starts_with("impl ") {
+            // `impl Trait` in argument:
+            // `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
+            err.span_suggestion(
+                param.span,
+                restrict_msg,
+                // `impl CurrentTrait + MissingTrait`
+                format!("{} + {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        } else if generics.where_clause.predicates.is_empty() && param.bounds.is_empty() {
+            // If there are no bounds whatsoever, suggest adding a constraint
+            // to the type parameter:
+            // `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
+            err.span_suggestion(
+                param.span,
+                "consider restricting this bound",
+                format!("{}: {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        } else if !generics.where_clause.predicates.is_empty() {
+            // There is a `where` clause, so suggest expanding it:
+            // `fn foo<T>(t: T) where T: Debug {}` →
+            // `fn foo<T>(t: T) where T: Debug, T: Trait {}`
+            err.span_suggestion(
+                generics.where_clause.span().unwrap().shrink_to_hi(),
+                &format!("consider further restricting type parameter `{}`", param_name),
+                format!(", {}: {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        } else {
+            // If there is no `where` clause lean towards constraining to the
+            // type parameter:
+            // `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
+            // `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
+            let sp = param.span.with_hi(span.hi());
+            let span = source_map.span_through_char(sp, ':');
+            if sp != param.span && sp != span {
+                // Only suggest if we have high certainty that the span
+                // covers the colon in `foo<T: Trait>`.
+                err.span_suggestion(
+                    span,
+                    restrict_msg,
+                    format!("{}: {} + ", param_name, constraint),
+                    Applicability::MachineApplicable,
+                );
+            } else {
+                err.span_label(
+                    param.span,
+                    &format!("consider adding a `where {}: {}` bound", param_name, constraint),
+                );
+            }
+        }
+        return true;
+    }
+    false
+}
diff --git a/src/librustc/traits/error_reporting/on_unimplemented.rs b/src/librustc/traits/error_reporting/on_unimplemented.rs
new file mode 100644 (file)
index 0000000..9f3fc91
--- /dev/null
@@ -0,0 +1,199 @@
+use super::{
+    ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote, PredicateObligation,
+};
+use crate::infer::InferCtxt;
+use crate::ty::subst::Subst;
+use crate::ty::{self, GenericParamDefKind};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_span::symbol::sym;
+
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+    fn impl_similar_to(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> Option<DefId> {
+        let tcx = self.tcx;
+        let param_env = obligation.param_env;
+        let trait_ref = tcx.erase_late_bound_regions(&trait_ref);
+        let trait_self_ty = trait_ref.self_ty();
+
+        let mut self_match_impls = vec![];
+        let mut fuzzy_match_impls = vec![];
+
+        self.tcx.for_each_relevant_impl(trait_ref.def_id, trait_self_ty, |def_id| {
+            let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id);
+            let impl_trait_ref = tcx.impl_trait_ref(def_id).unwrap().subst(tcx, impl_substs);
+
+            let impl_self_ty = impl_trait_ref.self_ty();
+
+            if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) {
+                self_match_impls.push(def_id);
+
+                if trait_ref
+                    .substs
+                    .types()
+                    .skip(1)
+                    .zip(impl_trait_ref.substs.types().skip(1))
+                    .all(|(u, v)| self.fuzzy_match_tys(u, v))
+                {
+                    fuzzy_match_impls.push(def_id);
+                }
+            }
+        });
+
+        let impl_def_id = if self_match_impls.len() == 1 {
+            self_match_impls[0]
+        } else if fuzzy_match_impls.len() == 1 {
+            fuzzy_match_impls[0]
+        } else {
+            return None;
+        };
+
+        tcx.has_attr(impl_def_id, sym::rustc_on_unimplemented).then_some(impl_def_id)
+    }
+
+    /// Used to set on_unimplemented's `ItemContext`
+    /// to be the enclosing (async) block/function/closure
+    fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str> {
+        let hir = &self.tcx.hir();
+        let node = hir.find(hir_id)?;
+        if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. }) = &node {
+            self.describe_generator(*body_id).or_else(|| {
+                Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header {
+                    "an async function"
+                } else {
+                    "a function"
+                })
+            })
+        } else if let hir::Node::Expr(hir::Expr {
+            kind: hir::ExprKind::Closure(_is_move, _, body_id, _, gen_movability),
+            ..
+        }) = &node
+        {
+            self.describe_generator(*body_id).or_else(|| {
+                Some(if gen_movability.is_some() { "an async closure" } else { "a closure" })
+            })
+        } else if let hir::Node::Expr(hir::Expr { .. }) = &node {
+            let parent_hid = hir.get_parent_node(hir_id);
+            if parent_hid != hir_id {
+                return self.describe_enclosure(parent_hid);
+            } else {
+                None
+            }
+        } else {
+            None
+        }
+    }
+
+    crate fn on_unimplemented_note(
+        &self,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> OnUnimplementedNote {
+        let def_id =
+            self.impl_similar_to(trait_ref, obligation).unwrap_or_else(|| trait_ref.def_id());
+        let trait_ref = *trait_ref.skip_binder();
+
+        let mut flags = vec![];
+        flags.push((
+            sym::item_context,
+            self.describe_enclosure(obligation.cause.body_id).map(|s| s.to_owned()),
+        ));
+
+        match obligation.cause.code {
+            ObligationCauseCode::BuiltinDerivedObligation(..)
+            | ObligationCauseCode::ImplDerivedObligation(..) => {}
+            _ => {
+                // this is a "direct", user-specified, rather than derived,
+                // obligation.
+                flags.push((sym::direct, None));
+            }
+        }
+
+        if let ObligationCauseCode::ItemObligation(item) = obligation.cause.code {
+            // FIXME: maybe also have some way of handling methods
+            // from other traits? That would require name resolution,
+            // which we might want to be some sort of hygienic.
+            //
+            // Currently I'm leaving it for what I need for `try`.
+            if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
+                let method = self.tcx.item_name(item);
+                flags.push((sym::from_method, None));
+                flags.push((sym::from_method, Some(method.to_string())));
+            }
+        }
+        if let Some((t, _)) = self.get_parent_trait_ref(&obligation.cause.code) {
+            flags.push((sym::parent_trait, Some(t)));
+        }
+
+        if let Some(k) = obligation.cause.span.desugaring_kind() {
+            flags.push((sym::from_desugaring, None));
+            flags.push((sym::from_desugaring, Some(format!("{:?}", k))));
+        }
+        let generics = self.tcx.generics_of(def_id);
+        let self_ty = trait_ref.self_ty();
+        // This is also included through the generics list as `Self`,
+        // but the parser won't allow you to use it
+        flags.push((sym::_Self, Some(self_ty.to_string())));
+        if let Some(def) = self_ty.ty_adt_def() {
+            // We also want to be able to select self's original
+            // signature with no type arguments resolved
+            flags.push((sym::_Self, Some(self.tcx.type_of(def.did).to_string())));
+        }
+
+        for param in generics.params.iter() {
+            let value = match param.kind {
+                GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
+                    trait_ref.substs[param.index as usize].to_string()
+                }
+                GenericParamDefKind::Lifetime => continue,
+            };
+            let name = param.name;
+            flags.push((name, Some(value)));
+        }
+
+        if let Some(true) = self_ty.ty_adt_def().map(|def| def.did.is_local()) {
+            flags.push((sym::crate_local, None));
+        }
+
+        // Allow targeting all integers using `{integral}`, even if the exact type was resolved
+        if self_ty.is_integral() {
+            flags.push((sym::_Self, Some("{integral}".to_owned())));
+        }
+
+        if let ty::Array(aty, len) = self_ty.kind {
+            flags.push((sym::_Self, Some("[]".to_owned())));
+            flags.push((sym::_Self, Some(format!("[{}]", aty))));
+            if let Some(def) = aty.ty_adt_def() {
+                // We also want to be able to select the array's type's original
+                // signature with no type arguments resolved
+                flags.push((
+                    sym::_Self,
+                    Some(format!("[{}]", self.tcx.type_of(def.did).to_string())),
+                ));
+                let tcx = self.tcx;
+                if let Some(len) = len.try_eval_usize(tcx, ty::ParamEnv::empty()) {
+                    flags.push((
+                        sym::_Self,
+                        Some(format!("[{}; {}]", self.tcx.type_of(def.did).to_string(), len)),
+                    ));
+                } else {
+                    flags.push((
+                        sym::_Self,
+                        Some(format!("[{}; _]", self.tcx.type_of(def.did).to_string())),
+                    ));
+                }
+            }
+        }
+
+        if let Ok(Some(command)) =
+            OnUnimplementedDirective::of_item(self.tcx, trait_ref.def_id, def_id)
+        {
+            command.evaluate(self.tcx, trait_ref, &flags[..])
+        } else {
+            OnUnimplementedNote::default()
+        }
+    }
+}
diff --git a/src/librustc/traits/error_reporting/suggestions.rs b/src/librustc/traits/error_reporting/suggestions.rs
new file mode 100644 (file)
index 0000000..c18e175
--- /dev/null
@@ -0,0 +1,1715 @@
+use super::{
+    ArgKind, EvaluationResult, Obligation, ObligationCause, ObligationCauseCode,
+    PredicateObligation,
+};
+
+use crate::infer::InferCtxt;
+use crate::traits::object_safety::object_safety_violations;
+use crate::ty::TypeckTables;
+use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable};
+
+use rustc_errors::{
+    error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style,
+};
+use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::Visitor;
+use rustc_hir::Node;
+use rustc_span::source_map::SourceMap;
+use rustc_span::symbol::{kw, sym};
+use rustc_span::{MultiSpan, Span, DUMMY_SP};
+use std::fmt;
+
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+    crate fn suggest_restricting_param_bound(
+        &self,
+        mut err: &mut DiagnosticBuilder<'_>,
+        trait_ref: &ty::PolyTraitRef<'_>,
+        body_id: hir::HirId,
+    ) {
+        let self_ty = trait_ref.self_ty();
+        let (param_ty, projection) = match &self_ty.kind {
+            ty::Param(_) => (true, None),
+            ty::Projection(projection) => (false, Some(projection)),
+            _ => return,
+        };
+
+        let suggest_restriction =
+            |generics: &hir::Generics<'_>, msg, err: &mut DiagnosticBuilder<'_>| {
+                let span = generics.where_clause.span_for_predicates_or_empty_place();
+                if !span.from_expansion() && span.desugaring_kind().is_none() {
+                    err.span_suggestion(
+                        generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(),
+                        &format!("consider further restricting {}", msg),
+                        format!(
+                            "{} {} ",
+                            if !generics.where_clause.predicates.is_empty() {
+                                ","
+                            } else {
+                                " where"
+                            },
+                            trait_ref.to_predicate(),
+                        ),
+                        Applicability::MachineApplicable,
+                    );
+                }
+            };
+
+        // FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
+        //        don't suggest `T: Sized + ?Sized`.
+        let mut hir_id = body_id;
+        while let Some(node) = self.tcx.hir().find(hir_id) {
+            match node {
+                hir::Node::TraitItem(hir::TraitItem {
+                    generics,
+                    kind: hir::TraitItemKind::Method(..),
+                    ..
+                }) if param_ty && self_ty == self.tcx.types.self_param => {
+                    // Restricting `Self` for a single method.
+                    suggest_restriction(&generics, "`Self`", err);
+                    return;
+                }
+
+                hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
+                | hir::Node::TraitItem(hir::TraitItem {
+                    generics,
+                    kind: hir::TraitItemKind::Method(..),
+                    ..
+                })
+                | hir::Node::ImplItem(hir::ImplItem {
+                    generics,
+                    kind: hir::ImplItemKind::Method(..),
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Trait(_, _, generics, _, _),
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Impl { generics, .. }, ..
+                }) if projection.is_some() => {
+                    // Missing associated type bound.
+                    suggest_restriction(&generics, "the associated type", err);
+                    return;
+                }
+
+                hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Struct(_, generics),
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Enum(_, generics), span, ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Union(_, generics),
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Trait(_, _, generics, ..),
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Impl { generics, .. },
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Fn(_, generics, _),
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::TyAlias(_, generics),
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::TraitAlias(generics, _),
+                    span,
+                    ..
+                })
+                | hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }),
+                    span,
+                    ..
+                })
+                | hir::Node::TraitItem(hir::TraitItem { generics, span, .. })
+                | hir::Node::ImplItem(hir::ImplItem { generics, span, .. })
+                    if param_ty =>
+                {
+                    // Missing generic type parameter bound.
+                    let param_name = self_ty.to_string();
+                    let constraint = trait_ref.print_only_trait_path().to_string();
+                    if suggest_constraining_type_param(
+                        generics,
+                        &mut err,
+                        &param_name,
+                        &constraint,
+                        self.tcx.sess.source_map(),
+                        *span,
+                    ) {
+                        return;
+                    }
+                }
+
+                hir::Node::Crate => return,
+
+                _ => {}
+            }
+
+            hir_id = self.tcx.hir().get_parent_item(hir_id);
+        }
+    }
+
+    /// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a
+    /// suggestion to borrow the initializer in order to use have a slice instead.
+    crate fn suggest_borrow_on_unsized_slice(
+        &self,
+        code: &ObligationCauseCode<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+    ) {
+        if let &ObligationCauseCode::VariableType(hir_id) = code {
+            let parent_node = self.tcx.hir().get_parent_node(hir_id);
+            if let Some(Node::Local(ref local)) = self.tcx.hir().find(parent_node) {
+                if let Some(ref expr) = local.init {
+                    if let hir::ExprKind::Index(_, _) = expr.kind {
+                        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
+                            err.span_suggestion(
+                                expr.span,
+                                "consider borrowing here",
+                                format!("&{}", snippet),
+                                Applicability::MachineApplicable,
+                            );
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /// Given a closure's `DefId`, return the given name of the closure.
+    ///
+    /// This doesn't account for reassignments, but it's only used for suggestions.
+    crate fn get_closure_name(
+        &self,
+        def_id: DefId,
+        err: &mut DiagnosticBuilder<'_>,
+        msg: &str,
+    ) -> Option<String> {
+        let get_name =
+            |err: &mut DiagnosticBuilder<'_>, kind: &hir::PatKind<'_>| -> Option<String> {
+                // Get the local name of this closure. This can be inaccurate because
+                // of the possibility of reassignment, but this should be good enough.
+                match &kind {
+                    hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => {
+                        Some(format!("{}", name))
+                    }
+                    _ => {
+                        err.note(&msg);
+                        None
+                    }
+                }
+            };
+
+        let hir = self.tcx.hir();
+        let hir_id = hir.as_local_hir_id(def_id)?;
+        let parent_node = hir.get_parent_node(hir_id);
+        match hir.find(parent_node) {
+            Some(hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. })) => {
+                get_name(err, &local.pat.kind)
+            }
+            // Different to previous arm because one is `&hir::Local` and the other
+            // is `P<hir::Local>`.
+            Some(hir::Node::Local(local)) => get_name(err, &local.pat.kind),
+            _ => return None,
+        }
+    }
+
+    /// We tried to apply the bound to an `fn` or closure. Check whether calling it would
+    /// evaluate to a type that *would* satisfy the trait binding. If it would, suggest calling
+    /// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`.
+    crate fn suggest_fn_call(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'_>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+        points_at_arg: bool,
+    ) {
+        let self_ty = trait_ref.self_ty();
+        let (def_id, output_ty, callable) = match self_ty.kind {
+            ty::Closure(def_id, substs) => {
+                (def_id, self.closure_sig(def_id, substs).output(), "closure")
+            }
+            ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"),
+            _ => return,
+        };
+        let msg = format!("use parentheses to call the {}", callable);
+
+        let obligation = self.mk_obligation_for_def_id(
+            trait_ref.def_id(),
+            output_ty.skip_binder(),
+            obligation.cause.clone(),
+            obligation.param_env,
+        );
+
+        match self.evaluate_obligation(&obligation) {
+            Ok(EvaluationResult::EvaluatedToOk)
+            | Ok(EvaluationResult::EvaluatedToOkModuloRegions)
+            | Ok(EvaluationResult::EvaluatedToAmbig) => {}
+            _ => return,
+        }
+        let hir = self.tcx.hir();
+        // Get the name of the callable and the arguments to be used in the suggestion.
+        let snippet = match hir.get_if_local(def_id) {
+            Some(hir::Node::Expr(hir::Expr {
+                kind: hir::ExprKind::Closure(_, decl, _, span, ..),
+                ..
+            })) => {
+                err.span_label(*span, "consider calling this closure");
+                let name = match self.get_closure_name(def_id, err, &msg) {
+                    Some(name) => name,
+                    None => return,
+                };
+                let args = decl.inputs.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
+                format!("{}({})", name, args)
+            }
+            Some(hir::Node::Item(hir::Item {
+                ident,
+                kind: hir::ItemKind::Fn(.., body_id),
+                ..
+            })) => {
+                err.span_label(ident.span, "consider calling this function");
+                let body = hir.body(*body_id);
+                let args = body
+                    .params
+                    .iter()
+                    .map(|arg| match &arg.pat.kind {
+                        hir::PatKind::Binding(_, _, ident, None)
+                        // FIXME: provide a better suggestion when encountering `SelfLower`, it
+                        // should suggest a method call.
+                        if ident.name != kw::SelfLower => ident.to_string(),
+                        _ => "_".to_string(),
+                    })
+                    .collect::<Vec<_>>()
+                    .join(", ");
+                format!("{}({})", ident, args)
+            }
+            _ => return,
+        };
+        if points_at_arg {
+            // When the obligation error has been ensured to have been caused by
+            // an argument, the `obligation.cause.span` points at the expression
+            // of the argument, so we can provide a suggestion. This is signaled
+            // by `points_at_arg`. Otherwise, we give a more general note.
+            err.span_suggestion(
+                obligation.cause.span,
+                &msg,
+                snippet,
+                Applicability::HasPlaceholders,
+            );
+        } else {
+            err.help(&format!("{}: `{}`", msg, snippet));
+        }
+    }
+
+    crate fn suggest_add_reference_to_arg(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+        points_at_arg: bool,
+        has_custom_message: bool,
+    ) -> bool {
+        if !points_at_arg {
+            return false;
+        }
+
+        let span = obligation.cause.span;
+        let param_env = obligation.param_env;
+        let trait_ref = trait_ref.skip_binder();
+
+        if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code {
+            // Try to apply the original trait binding obligation by borrowing.
+            let self_ty = trait_ref.self_ty();
+            let found = self_ty.to_string();
+            let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty);
+            let substs = self.tcx.mk_substs_trait(new_self_ty, &[]);
+            let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs);
+            let new_obligation =
+                Obligation::new(ObligationCause::dummy(), param_env, new_trait_ref.to_predicate());
+            if self.predicate_must_hold_modulo_regions(&new_obligation) {
+                if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+                    // We have a very specific type of error, where just borrowing this argument
+                    // might solve the problem. In cases like this, the important part is the
+                    // original type obligation, not the last one that failed, which is arbitrary.
+                    // Because of this, we modify the error to refer to the original obligation and
+                    // return early in the caller.
+                    let msg = format!(
+                        "the trait bound `{}: {}` is not satisfied",
+                        found,
+                        obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
+                    );
+                    if has_custom_message {
+                        err.note(&msg);
+                    } else {
+                        err.message = vec![(msg, Style::NoStyle)];
+                    }
+                    if snippet.starts_with('&') {
+                        // This is already a literal borrow and the obligation is failing
+                        // somewhere else in the obligation chain. Do not suggest non-sense.
+                        return false;
+                    }
+                    err.span_label(
+                        span,
+                        &format!(
+                            "expected an implementor of trait `{}`",
+                            obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
+                        ),
+                    );
+                    err.span_suggestion(
+                        span,
+                        "consider borrowing here",
+                        format!("&{}", snippet),
+                        Applicability::MaybeIncorrect,
+                    );
+                    return true;
+                }
+            }
+        }
+        false
+    }
+
+    /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
+    /// suggest removing these references until we reach a type that implements the trait.
+    crate fn suggest_remove_reference(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+    ) {
+        let trait_ref = trait_ref.skip_binder();
+        let span = obligation.cause.span;
+
+        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+            let refs_number =
+                snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
+            if let Some('\'') =
+                snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next()
+            {
+                // Do not suggest removal of borrow from type arguments.
+                return;
+            }
+
+            let mut trait_type = trait_ref.self_ty();
+
+            for refs_remaining in 0..refs_number {
+                if let ty::Ref(_, t_type, _) = trait_type.kind {
+                    trait_type = t_type;
+
+                    let new_obligation = self.mk_obligation_for_def_id(
+                        trait_ref.def_id,
+                        trait_type,
+                        ObligationCause::dummy(),
+                        obligation.param_env,
+                    );
+
+                    if self.predicate_may_hold(&new_obligation) {
+                        let sp = self
+                            .tcx
+                            .sess
+                            .source_map()
+                            .span_take_while(span, |c| c.is_whitespace() || *c == '&');
+
+                        let remove_refs = refs_remaining + 1;
+                        let format_str =
+                            format!("consider removing {} leading `&`-references", remove_refs);
+
+                        err.span_suggestion_short(
+                            sp,
+                            &format_str,
+                            String::new(),
+                            Applicability::MachineApplicable,
+                        );
+                        break;
+                    }
+                } else {
+                    break;
+                }
+            }
+        }
+    }
+
+    /// Check if the trait bound is implemented for a different mutability and note it in the
+    /// final error.
+    crate fn suggest_change_mut(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+        points_at_arg: bool,
+    ) {
+        let span = obligation.cause.span;
+        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+            let refs_number =
+                snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
+            if let Some('\'') =
+                snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next()
+            {
+                // Do not suggest removal of borrow from type arguments.
+                return;
+            }
+            let trait_ref = self.resolve_vars_if_possible(trait_ref);
+            if trait_ref.has_infer_types() {
+                // Do not ICE while trying to find if a reborrow would succeed on a trait with
+                // unresolved bindings.
+                return;
+            }
+
+            if let ty::Ref(region, t_type, mutability) = trait_ref.skip_binder().self_ty().kind {
+                let trait_type = match mutability {
+                    hir::Mutability::Mut => self.tcx.mk_imm_ref(region, t_type),
+                    hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type),
+                };
+
+                let new_obligation = self.mk_obligation_for_def_id(
+                    trait_ref.skip_binder().def_id,
+                    trait_type,
+                    ObligationCause::dummy(),
+                    obligation.param_env,
+                );
+
+                if self.evaluate_obligation_no_overflow(&new_obligation).must_apply_modulo_regions()
+                {
+                    let sp = self
+                        .tcx
+                        .sess
+                        .source_map()
+                        .span_take_while(span, |c| c.is_whitespace() || *c == '&');
+                    if points_at_arg && mutability == hir::Mutability::Not && refs_number > 0 {
+                        err.span_suggestion(
+                            sp,
+                            "consider changing this borrow's mutability",
+                            "&mut ".to_string(),
+                            Applicability::MachineApplicable,
+                        );
+                    } else {
+                        err.note(&format!(
+                            "`{}` is implemented for `{:?}`, but not for `{:?}`",
+                            trait_ref.print_only_trait_path(),
+                            trait_type,
+                            trait_ref.skip_binder().self_ty(),
+                        ));
+                    }
+                }
+            }
+        }
+    }
+
+    crate fn suggest_semicolon_removal(
+        &self,
+        obligation: &PredicateObligation<'tcx>,
+        err: &mut DiagnosticBuilder<'tcx>,
+        span: Span,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+    ) {
+        let hir = self.tcx.hir();
+        let parent_node = hir.get_parent_node(obligation.cause.body_id);
+        let node = hir.find(parent_node);
+        if let Some(hir::Node::Item(hir::Item {
+            kind: hir::ItemKind::Fn(sig, _, body_id), ..
+        })) = node
+        {
+            let body = hir.body(*body_id);
+            if let hir::ExprKind::Block(blk, _) = &body.value.kind {
+                if sig.decl.output.span().overlaps(span)
+                    && blk.expr.is_none()
+                    && "()" == &trait_ref.self_ty().to_string()
+                {
+                    // FIXME(estebank): When encountering a method with a trait
+                    // bound not satisfied in the return type with a body that has
+                    // no return, suggest removal of semicolon on last statement.
+                    // Once that is added, close #54771.
+                    if let Some(ref stmt) = blk.stmts.last() {
+                        let sp = self.tcx.sess.source_map().end_point(stmt.span);
+                        err.span_label(sp, "consider removing this semicolon");
+                    }
+                }
+            }
+        }
+    }
+
+    /// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if
+    /// applicable and signal that the error has been expanded appropriately and needs to be
+    /// emitted.
+    crate fn suggest_impl_trait(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        span: Span,
+        obligation: &PredicateObligation<'tcx>,
+        trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
+    ) -> bool {
+        match obligation.cause.code.peel_derives() {
+            // Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`.
+            ObligationCauseCode::SizedReturnType => {}
+            _ => return false,
+        }
+
+        let hir = self.tcx.hir();
+        let parent_node = hir.get_parent_node(obligation.cause.body_id);
+        let node = hir.find(parent_node);
+        let (sig, body_id) = if let Some(hir::Node::Item(hir::Item {
+            kind: hir::ItemKind::Fn(sig, _, body_id),
+            ..
+        })) = node
+        {
+            (sig, body_id)
+        } else {
+            return false;
+        };
+        let body = hir.body(*body_id);
+        let trait_ref = self.resolve_vars_if_possible(trait_ref);
+        let ty = trait_ref.skip_binder().self_ty();
+        let is_object_safe = match ty.kind {
+            ty::Dynamic(predicates, _) => {
+                // If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`.
+                predicates
+                    .principal_def_id()
+                    .map_or(true, |def_id| object_safety_violations(self.tcx, def_id).is_empty())
+            }
+            // We only want to suggest `impl Trait` to `dyn Trait`s.
+            // For example, `fn foo() -> str` needs to be filtered out.
+            _ => return false,
+        };
+
+        let ret_ty = if let hir::FunctionRetTy::Return(ret_ty) = sig.decl.output {
+            ret_ty
+        } else {
+            return false;
+        };
+
+        // Use `TypeVisitor` instead of the output type directly to find the span of `ty` for
+        // cases like `fn foo() -> (dyn Trait, i32) {}`.
+        // Recursively look for `TraitObject` types and if there's only one, use that span to
+        // suggest `impl Trait`.
+
+        // Visit to make sure there's a single `return` type to suggest `impl Trait`,
+        // otherwise suggest using `Box<dyn Trait>` or an enum.
+        let mut visitor = ReturnsVisitor(vec![]);
+        visitor.visit_body(&body);
+
+        let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
+
+        let mut ret_types = visitor.0.iter().filter_map(|expr| tables.node_type_opt(expr.hir_id));
+        let (last_ty, all_returns_have_same_type) =
+            ret_types.clone().fold((None, true), |(last_ty, mut same), returned_ty| {
+                same &= last_ty.map_or(true, |ty| ty == returned_ty);
+                (Some(returned_ty), same)
+            });
+        let all_returns_conform_to_trait =
+            if let Some(ty_ret_ty) = tables.node_type_opt(ret_ty.hir_id) {
+                match ty_ret_ty.kind {
+                    ty::Dynamic(predicates, _) => {
+                        let cause = ObligationCause::misc(ret_ty.span, ret_ty.hir_id);
+                        let param_env = ty::ParamEnv::empty();
+                        ret_types.all(|returned_ty| {
+                            predicates.iter().all(|predicate| {
+                                let pred = predicate.with_self_ty(self.tcx, returned_ty);
+                                let obl = Obligation::new(cause.clone(), param_env, pred);
+                                self.predicate_may_hold(&obl)
+                            })
+                        })
+                    }
+                    _ => true,
+                }
+            } else {
+                true
+            };
+
+        let (snippet, last_ty) =
+            if let (true, hir::TyKind::TraitObject(..), Ok(snippet), true, Some(last_ty)) = (
+                // Verify that we're dealing with a return `dyn Trait`
+                ret_ty.span.overlaps(span),
+                &ret_ty.kind,
+                self.tcx.sess.source_map().span_to_snippet(ret_ty.span),
+                // If any of the return types does not conform to the trait, then we can't
+                // suggest `impl Trait` nor trait objects, it is a type mismatch error.
+                all_returns_conform_to_trait,
+                last_ty,
+            ) {
+                (snippet, last_ty)
+            } else {
+                return false;
+            };
+        err.code(error_code!(E0746));
+        err.set_primary_message("return type cannot have an unboxed trait object");
+        err.children.clear();
+        let impl_trait_msg = "for information on `impl Trait`, see \
+            <https://doc.rust-lang.org/book/ch10-02-traits.html\
+            #returning-types-that-implement-traits>";
+        let trait_obj_msg = "for information on trait objects, see \
+            <https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
+            #using-trait-objects-that-allow-for-values-of-different-types>";
+        let has_dyn = snippet.split_whitespace().next().map_or(false, |s| s == "dyn");
+        let trait_obj = if has_dyn { &snippet[4..] } else { &snippet[..] };
+        if all_returns_have_same_type {
+            // Suggest `-> impl Trait`.
+            err.span_suggestion(
+                ret_ty.span,
+                &format!(
+                    "return `impl {1}` instead, as all return paths are of type `{}`, \
+                        which implements `{1}`",
+                    last_ty, trait_obj,
+                ),
+                format!("impl {}", trait_obj),
+                Applicability::MachineApplicable,
+            );
+            err.note(impl_trait_msg);
+        } else {
+            if is_object_safe {
+                // Suggest `-> Box<dyn Trait>` and `Box::new(returned_value)`.
+                // Get all the return values and collect their span and suggestion.
+                let mut suggestions = visitor
+                    .0
+                    .iter()
+                    .map(|expr| {
+                        (
+                            expr.span,
+                            format!(
+                                "Box::new({})",
+                                self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap()
+                            ),
+                        )
+                    })
+                    .collect::<Vec<_>>();
+                // Add the suggestion for the return type.
+                suggestions.push((
+                    ret_ty.span,
+                    format!("Box<{}{}>", if has_dyn { "" } else { "dyn " }, snippet),
+                ));
+                err.multipart_suggestion(
+                    "return a boxed trait object instead",
+                    suggestions,
+                    Applicability::MaybeIncorrect,
+                );
+            } else {
+                // This is currently not possible to trigger because E0038 takes precedence, but
+                // leave it in for completeness in case anything changes in an earlier stage.
+                err.note(&format!(
+                    "if trait `{}` was object safe, you could return a trait object",
+                    trait_obj,
+                ));
+            }
+            err.note(trait_obj_msg);
+            err.note(&format!(
+                "if all the returned values were of the same type you could use \
+                    `impl {}` as the return type",
+                trait_obj,
+            ));
+            err.note(impl_trait_msg);
+            err.note("you can create a new `enum` with a variant for each returned type");
+        }
+        true
+    }
+
+    crate fn point_at_returns_when_relevant(
+        &self,
+        err: &mut DiagnosticBuilder<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    ) {
+        match obligation.cause.code.peel_derives() {
+            ObligationCauseCode::SizedReturnType => {}
+            _ => return,
+        }
+
+        let hir = self.tcx.hir();
+        let parent_node = hir.get_parent_node(obligation.cause.body_id);
+        let node = hir.find(parent_node);
+        if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) =
+            node
+        {
+            let body = hir.body(*body_id);
+            // Point at all the `return`s in the function as they have failed trait bounds.
+            let mut visitor = ReturnsVisitor(vec![]);
+            visitor.visit_body(&body);
+            let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
+            for expr in &visitor.0 {
+                if let Some(returned_ty) = tables.node_type_opt(expr.hir_id) {
+                    let ty = self.resolve_vars_if_possible(&returned_ty);
+                    err.span_label(expr.span, &format!("this returned value is of type `{}`", ty));
+                }
+            }
+        }
+    }
+
+    /// Given some node representing a fn-like thing in the HIR map,
+    /// returns a span and `ArgKind` information that describes the
+    /// arguments it expects. This can be supplied to
+    /// `report_arg_count_mismatch`.
+    pub fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>) {
+        match node {
+            Node::Expr(&hir::Expr {
+                kind: hir::ExprKind::Closure(_, ref _decl, id, span, _),
+                ..
+            }) => (
+                self.tcx.sess.source_map().def_span(span),
+                self.tcx
+                    .hir()
+                    .body(id)
+                    .params
+                    .iter()
+                    .map(|arg| {
+                        if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } =
+                            *arg.pat
+                        {
+                            ArgKind::Tuple(
+                                Some(span),
+                                args.iter()
+                                    .map(|pat| {
+                                        let snippet = self
+                                            .tcx
+                                            .sess
+                                            .source_map()
+                                            .span_to_snippet(pat.span)
+                                            .unwrap();
+                                        (snippet, "_".to_owned())
+                                    })
+                                    .collect::<Vec<_>>(),
+                            )
+                        } else {
+                            let name =
+                                self.tcx.sess.source_map().span_to_snippet(arg.pat.span).unwrap();
+                            ArgKind::Arg(name, "_".to_owned())
+                        }
+                    })
+                    .collect::<Vec<ArgKind>>(),
+            ),
+            Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. })
+            | Node::ImplItem(&hir::ImplItem {
+                span,
+                kind: hir::ImplItemKind::Method(ref sig, _),
+                ..
+            })
+            | Node::TraitItem(&hir::TraitItem {
+                span,
+                kind: hir::TraitItemKind::Method(ref sig, _),
+                ..
+            }) => (
+                self.tcx.sess.source_map().def_span(span),
+                sig.decl
+                    .inputs
+                    .iter()
+                    .map(|arg| match arg.clone().kind {
+                        hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
+                            Some(arg.span),
+                            vec![("_".to_owned(), "_".to_owned()); tys.len()],
+                        ),
+                        _ => ArgKind::empty(),
+                    })
+                    .collect::<Vec<ArgKind>>(),
+            ),
+            Node::Ctor(ref variant_data) => {
+                let span = variant_data
+                    .ctor_hir_id()
+                    .map(|hir_id| self.tcx.hir().span(hir_id))
+                    .unwrap_or(DUMMY_SP);
+                let span = self.tcx.sess.source_map().def_span(span);
+
+                (span, vec![ArgKind::empty(); variant_data.fields().len()])
+            }
+            _ => panic!("non-FnLike node found: {:?}", node),
+        }
+    }
+
+    /// Reports an error when the number of arguments needed by a
+    /// trait match doesn't match the number that the expression
+    /// provides.
+    pub fn report_arg_count_mismatch(
+        &self,
+        span: Span,
+        found_span: Option<Span>,
+        expected_args: Vec<ArgKind>,
+        found_args: Vec<ArgKind>,
+        is_closure: bool,
+    ) -> DiagnosticBuilder<'tcx> {
+        let kind = if is_closure { "closure" } else { "function" };
+
+        let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
+            let arg_length = arguments.len();
+            let distinct = match &other[..] {
+                &[ArgKind::Tuple(..)] => true,
+                _ => false,
+            };
+            match (arg_length, arguments.get(0)) {
+                (1, Some(&ArgKind::Tuple(_, ref fields))) => {
+                    format!("a single {}-tuple as argument", fields.len())
+                }
+                _ => format!(
+                    "{} {}argument{}",
+                    arg_length,
+                    if distinct && arg_length > 1 { "distinct " } else { "" },
+                    pluralize!(arg_length)
+                ),
+            }
+        };
+
+        let expected_str = args_str(&expected_args, &found_args);
+        let found_str = args_str(&found_args, &expected_args);
+
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            span,
+            E0593,
+            "{} is expected to take {}, but it takes {}",
+            kind,
+            expected_str,
+            found_str,
+        );
+
+        err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
+
+        if let Some(found_span) = found_span {
+            err.span_label(found_span, format!("takes {}", found_str));
+
+            // move |_| { ... }
+            // ^^^^^^^^-- def_span
+            //
+            // move |_| { ... }
+            // ^^^^^-- prefix
+            let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span);
+            // move |_| { ... }
+            //      ^^^-- pipe_span
+            let pipe_span =
+                if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span };
+
+            // Suggest to take and ignore the arguments with expected_args_length `_`s if
+            // found arguments is empty (assume the user just wants to ignore args in this case).
+            // For example, if `expected_args_length` is 2, suggest `|_, _|`.
+            if found_args.is_empty() && is_closure {
+                let underscores = vec!["_"; expected_args.len()].join(", ");
+                err.span_suggestion(
+                    pipe_span,
+                    &format!(
+                        "consider changing the closure to take and ignore the expected argument{}",
+                        if expected_args.len() < 2 { "" } else { "s" }
+                    ),
+                    format!("|{}|", underscores),
+                    Applicability::MachineApplicable,
+                );
+            }
+
+            if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
+                if fields.len() == expected_args.len() {
+                    let sugg = fields
+                        .iter()
+                        .map(|(name, _)| name.to_owned())
+                        .collect::<Vec<String>>()
+                        .join(", ");
+                    err.span_suggestion(
+                        found_span,
+                        "change the closure to take multiple arguments instead of a single tuple",
+                        format!("|{}|", sugg),
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+            if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
+                if fields.len() == found_args.len() && is_closure {
+                    let sugg = format!(
+                        "|({}){}|",
+                        found_args
+                            .iter()
+                            .map(|arg| match arg {
+                                ArgKind::Arg(name, _) => name.to_owned(),
+                                _ => "_".to_owned(),
+                            })
+                            .collect::<Vec<String>>()
+                            .join(", "),
+                        // add type annotations if available
+                        if found_args.iter().any(|arg| match arg {
+                            ArgKind::Arg(_, ty) => ty != "_",
+                            _ => false,
+                        }) {
+                            format!(
+                                ": ({})",
+                                fields
+                                    .iter()
+                                    .map(|(_, ty)| ty.to_owned())
+                                    .collect::<Vec<String>>()
+                                    .join(", ")
+                            )
+                        } else {
+                            String::new()
+                        },
+                    );
+                    err.span_suggestion(
+                        found_span,
+                        "change the closure to accept a tuple instead of individual arguments",
+                        sugg,
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+        }
+
+        err
+    }
+
+    crate fn report_closure_arg_mismatch(
+        &self,
+        span: Span,
+        found_span: Option<Span>,
+        expected_ref: ty::PolyTraitRef<'tcx>,
+        found: ty::PolyTraitRef<'tcx>,
+    ) -> DiagnosticBuilder<'tcx> {
+        crate fn build_fn_sig_string<'tcx>(
+            tcx: TyCtxt<'tcx>,
+            trait_ref: &ty::TraitRef<'tcx>,
+        ) -> String {
+            let inputs = trait_ref.substs.type_at(1);
+            let sig = if let ty::Tuple(inputs) = inputs.kind {
+                tcx.mk_fn_sig(
+                    inputs.iter().map(|k| k.expect_ty()),
+                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
+                    false,
+                    hir::Unsafety::Normal,
+                    ::rustc_target::spec::abi::Abi::Rust,
+                )
+            } else {
+                tcx.mk_fn_sig(
+                    ::std::iter::once(inputs),
+                    tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
+                    false,
+                    hir::Unsafety::Normal,
+                    ::rustc_target::spec::abi::Abi::Rust,
+                )
+            };
+            ty::Binder::bind(sig).to_string()
+        }
+
+        let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            span,
+            E0631,
+            "type mismatch in {} arguments",
+            if argument_is_closure { "closure" } else { "function" }
+        );
+
+        let found_str = format!(
+            "expected signature of `{}`",
+            build_fn_sig_string(self.tcx, found.skip_binder())
+        );
+        err.span_label(span, found_str);
+
+        let found_span = found_span.unwrap_or(span);
+        let expected_str = format!(
+            "found signature of `{}`",
+            build_fn_sig_string(self.tcx, expected_ref.skip_binder())
+        );
+        err.span_label(found_span, expected_str);
+
+        err
+    }
+}
+
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+    crate fn suggest_fully_qualified_path(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        def_id: DefId,
+        span: Span,
+        trait_ref: DefId,
+    ) {
+        if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) {
+            if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind {
+                err.note(&format!(
+                    "{}s cannot be accessed directly on a `trait`, they can only be \
+                        accessed through a specific `impl`",
+                    assoc_item.kind.suggestion_descr(),
+                ));
+                err.span_suggestion(
+                    span,
+                    "use the fully qualified path to an implementation",
+                    format!("<Type as {}>::{}", self.tcx.def_path_str(trait_ref), assoc_item.ident),
+                    Applicability::HasPlaceholders,
+                );
+            }
+        }
+    }
+
+    /// Adds an async-await specific note to the diagnostic when the future does not implement
+    /// an auto trait because of a captured type.
+    ///
+    /// ```ignore (diagnostic)
+    /// note: future does not implement `Qux` as this value is used across an await
+    ///   --> $DIR/issue-64130-3-other.rs:17:5
+    ///    |
+    /// LL |     let x = Foo;
+    ///    |         - has type `Foo`
+    /// LL |     baz().await;
+    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
+    /// LL | }
+    ///    | - `x` is later dropped here
+    /// ```
+    ///
+    /// When the diagnostic does not implement `Send` or `Sync` specifically, then the diagnostic
+    /// is "replaced" with a different message and a more specific error.
+    ///
+    /// ```ignore (diagnostic)
+    /// error: future cannot be sent between threads safely
+    ///   --> $DIR/issue-64130-2-send.rs:21:5
+    ///    |
+    /// LL | fn is_send<T: Send>(t: T) { }
+    ///    |    -------    ---- required by this bound in `is_send`
+    /// ...
+    /// LL |     is_send(bar());
+    ///    |     ^^^^^^^ future returned by `bar` is not send
+    ///    |
+    ///    = help: within `impl std::future::Future`, the trait `std::marker::Send` is not
+    ///            implemented for `Foo`
+    /// note: future is not send as this value is used across an await
+    ///   --> $DIR/issue-64130-2-send.rs:15:5
+    ///    |
+    /// LL |     let x = Foo;
+    ///    |         - has type `Foo`
+    /// LL |     baz().await;
+    ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
+    /// LL | }
+    ///    | - `x` is later dropped here
+    /// ```
+    ///
+    /// Returns `true` if an async-await specific note was added to the diagnostic.
+    crate fn maybe_note_obligation_cause_for_async_await(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> bool {
+        debug!(
+            "maybe_note_obligation_cause_for_async_await: obligation.predicate={:?} \
+                obligation.cause.span={:?}",
+            obligation.predicate, obligation.cause.span
+        );
+        let source_map = self.tcx.sess.source_map();
+
+        // Attempt to detect an async-await error by looking at the obligation causes, looking
+        // for a generator to be present.
+        //
+        // When a future does not implement a trait because of a captured type in one of the
+        // generators somewhere in the call stack, then the result is a chain of obligations.
+        //
+        // Given a `async fn` A that calls a `async fn` B which captures a non-send type and that
+        // future is passed as an argument to a function C which requires a `Send` type, then the
+        // chain looks something like this:
+        //
+        // - `BuiltinDerivedObligation` with a generator witness (B)
+        // - `BuiltinDerivedObligation` with a generator (B)
+        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (B)
+        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
+        // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
+        // - `BuiltinDerivedObligation` with a generator witness (A)
+        // - `BuiltinDerivedObligation` with a generator (A)
+        // - `BuiltinDerivedObligation` with `std::future::GenFuture` (A)
+        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
+        // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
+        // - `BindingObligation` with `impl_send (Send requirement)
+        //
+        // The first obligation in the chain is the most useful and has the generator that captured
+        // the type. The last generator has information about where the bound was introduced. At
+        // least one generator should be present for this diagnostic to be modified.
+        let (mut trait_ref, mut target_ty) = match obligation.predicate {
+            ty::Predicate::Trait(p) => {
+                (Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty()))
+            }
+            _ => (None, None),
+        };
+        let mut generator = None;
+        let mut last_generator = None;
+        let mut next_code = Some(&obligation.cause.code);
+        while let Some(code) = next_code {
+            debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code);
+            match code {
+                ObligationCauseCode::BuiltinDerivedObligation(derived_obligation)
+                | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => {
+                    let ty = derived_obligation.parent_trait_ref.self_ty();
+                    debug!(
+                        "maybe_note_obligation_cause_for_async_await: \
+                            parent_trait_ref={:?} self_ty.kind={:?}",
+                        derived_obligation.parent_trait_ref, ty.kind
+                    );
+
+                    match ty.kind {
+                        ty::Generator(did, ..) => {
+                            generator = generator.or(Some(did));
+                            last_generator = Some(did);
+                        }
+                        ty::GeneratorWitness(..) => {}
+                        _ if generator.is_none() => {
+                            trait_ref = Some(*derived_obligation.parent_trait_ref.skip_binder());
+                            target_ty = Some(ty);
+                        }
+                        _ => {}
+                    }
+
+                    next_code = Some(derived_obligation.parent_code.as_ref());
+                }
+                _ => break,
+            }
+        }
+
+        // Only continue if a generator was found.
+        debug!(
+            "maybe_note_obligation_cause_for_async_await: generator={:?} trait_ref={:?} \
+                target_ty={:?}",
+            generator, trait_ref, target_ty
+        );
+        let (generator_did, trait_ref, target_ty) = match (generator, trait_ref, target_ty) {
+            (Some(generator_did), Some(trait_ref), Some(target_ty)) => {
+                (generator_did, trait_ref, target_ty)
+            }
+            _ => return false,
+        };
+
+        let span = self.tcx.def_span(generator_did);
+
+        // Do not ICE on closure typeck (#66868).
+        if self.tcx.hir().as_local_hir_id(generator_did).is_none() {
+            return false;
+        }
+
+        // Get the tables from the infcx if the generator is the function we are
+        // currently type-checking; otherwise, get them by performing a query.
+        // This is needed to avoid cycles.
+        let in_progress_tables = self.in_progress_tables.map(|t| t.borrow());
+        let generator_did_root = self.tcx.closure_base_def_id(generator_did);
+        debug!(
+            "maybe_note_obligation_cause_for_async_await: generator_did={:?} \
+             generator_did_root={:?} in_progress_tables.local_id_root={:?} span={:?}",
+            generator_did,
+            generator_did_root,
+            in_progress_tables.as_ref().map(|t| t.local_id_root),
+            span
+        );
+        let query_tables;
+        let tables: &TypeckTables<'tcx> = match &in_progress_tables {
+            Some(t) if t.local_id_root == Some(generator_did_root) => t,
+            _ => {
+                query_tables = self.tcx.typeck_tables_of(generator_did);
+                &query_tables
+            }
+        };
+
+        // Look for a type inside the generator interior that matches the target type to get
+        // a span.
+        let target_ty_erased = self.tcx.erase_regions(&target_ty);
+        let target_span = tables
+            .generator_interior_types
+            .iter()
+            .find(|ty::GeneratorInteriorTypeCause { ty, .. }| {
+                // Careful: the regions for types that appear in the
+                // generator interior are not generally known, so we
+                // want to erase them when comparing (and anyway,
+                // `Send` and other bounds are generally unaffected by
+                // the choice of region).  When erasing regions, we
+                // also have to erase late-bound regions. This is
+                // because the types that appear in the generator
+                // interior generally contain "bound regions" to
+                // represent regions that are part of the suspended
+                // generator frame. Bound regions are preserved by
+                // `erase_regions` and so we must also call
+                // `erase_late_bound_regions`.
+                let ty_erased = self.tcx.erase_late_bound_regions(&ty::Binder::bind(*ty));
+                let ty_erased = self.tcx.erase_regions(&ty_erased);
+                let eq = ty::TyS::same_type(ty_erased, target_ty_erased);
+                debug!(
+                    "maybe_note_obligation_cause_for_async_await: ty_erased={:?} \
+                        target_ty_erased={:?} eq={:?}",
+                    ty_erased, target_ty_erased, eq
+                );
+                eq
+            })
+            .map(|ty::GeneratorInteriorTypeCause { span, scope_span, expr, .. }| {
+                (span, source_map.span_to_snippet(*span), scope_span, expr)
+            });
+
+        debug!(
+            "maybe_note_obligation_cause_for_async_await: target_ty={:?} \
+                generator_interior_types={:?} target_span={:?}",
+            target_ty, tables.generator_interior_types, target_span
+        );
+        if let Some((target_span, Ok(snippet), scope_span, expr)) = target_span {
+            self.note_obligation_cause_for_async_await(
+                err,
+                *target_span,
+                scope_span,
+                *expr,
+                snippet,
+                generator_did,
+                last_generator,
+                trait_ref,
+                target_ty,
+                tables,
+                obligation,
+                next_code,
+            );
+            true
+        } else {
+            false
+        }
+    }
+
+    /// Unconditionally adds the diagnostic note described in
+    /// `maybe_note_obligation_cause_for_async_await`'s documentation comment.
+    crate fn note_obligation_cause_for_async_await(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        target_span: Span,
+        scope_span: &Option<Span>,
+        expr: Option<hir::HirId>,
+        snippet: String,
+        first_generator: DefId,
+        last_generator: Option<DefId>,
+        trait_ref: ty::TraitRef<'_>,
+        target_ty: Ty<'tcx>,
+        tables: &ty::TypeckTables<'_>,
+        obligation: &PredicateObligation<'tcx>,
+        next_code: Option<&ObligationCauseCode<'tcx>>,
+    ) {
+        let source_map = self.tcx.sess.source_map();
+
+        let is_async_fn = self
+            .tcx
+            .parent(first_generator)
+            .map(|parent_did| self.tcx.asyncness(parent_did))
+            .map(|parent_asyncness| parent_asyncness == hir::IsAsync::Async)
+            .unwrap_or(false);
+        let is_async_move = self
+            .tcx
+            .hir()
+            .as_local_hir_id(first_generator)
+            .and_then(|hir_id| self.tcx.hir().maybe_body_owned_by(hir_id))
+            .map(|body_id| self.tcx.hir().body(body_id))
+            .and_then(|body| body.generator_kind())
+            .map(|generator_kind| match generator_kind {
+                hir::GeneratorKind::Async(..) => true,
+                _ => false,
+            })
+            .unwrap_or(false);
+        let await_or_yield = if is_async_fn || is_async_move { "await" } else { "yield" };
+
+        // Special case the primary error message when send or sync is the trait that was
+        // not implemented.
+        let is_send = self.tcx.is_diagnostic_item(sym::send_trait, trait_ref.def_id);
+        let is_sync = self.tcx.is_diagnostic_item(sym::sync_trait, trait_ref.def_id);
+        let hir = self.tcx.hir();
+        let trait_explanation = if is_send || is_sync {
+            let (trait_name, trait_verb) =
+                if is_send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
+
+            err.clear_code();
+            err.set_primary_message(format!(
+                "future cannot be {} between threads safely",
+                trait_verb
+            ));
+
+            let original_span = err.span.primary_span().unwrap();
+            let mut span = MultiSpan::from_span(original_span);
+
+            let message = if let Some(name) = last_generator
+                .and_then(|generator_did| self.tcx.parent(generator_did))
+                .and_then(|parent_did| hir.as_local_hir_id(parent_did))
+                .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
+            {
+                format!("future returned by `{}` is not {}", name, trait_name)
+            } else {
+                format!("future is not {}", trait_name)
+            };
+
+            span.push_span_label(original_span, message);
+            err.set_span(span);
+
+            format!("is not {}", trait_name)
+        } else {
+            format!("does not implement `{}`", trait_ref.print_only_trait_path())
+        };
+
+        // Look at the last interior type to get a span for the `.await`.
+        let await_span = tables.generator_interior_types.iter().map(|t| t.span).last().unwrap();
+        let mut span = MultiSpan::from_span(await_span);
+        span.push_span_label(
+            await_span,
+            format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet),
+        );
+
+        span.push_span_label(target_span, format!("has type `{}`", target_ty));
+
+        // If available, use the scope span to annotate the drop location.
+        if let Some(scope_span) = scope_span {
+            span.push_span_label(
+                source_map.end_point(*scope_span),
+                format!("`{}` is later dropped here", snippet),
+            );
+        }
+
+        err.span_note(
+            span,
+            &format!(
+                "future {} as this value is used across an {}",
+                trait_explanation, await_or_yield,
+            ),
+        );
+
+        if let Some(expr_id) = expr {
+            let expr = hir.expect_expr(expr_id);
+            let is_ref = tables.expr_adjustments(expr).iter().any(|adj| adj.is_region_borrow());
+            let parent = hir.get_parent_node(expr_id);
+            if let Some(hir::Node::Expr(e)) = hir.find(parent) {
+                let method_span = hir.span(parent);
+                if tables.is_method_call(e) && is_ref {
+                    err.span_help(
+                        method_span,
+                        "consider moving this method call into a `let` \
+                        binding to create a shorter lived borrow",
+                    );
+                }
+            }
+        }
+
+        // Add a note for the item obligation that remains - normally a note pointing to the
+        // bound that introduced the obligation (e.g. `T: Send`).
+        debug!("note_obligation_cause_for_async_await: next_code={:?}", next_code);
+        self.note_obligation_cause_code(
+            err,
+            &obligation.predicate,
+            next_code.unwrap(),
+            &mut Vec::new(),
+        );
+    }
+
+    crate fn note_obligation_cause_code<T>(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        predicate: &T,
+        cause_code: &ObligationCauseCode<'tcx>,
+        obligated_types: &mut Vec<&ty::TyS<'tcx>>,
+    ) where
+        T: fmt::Display,
+    {
+        let tcx = self.tcx;
+        match *cause_code {
+            ObligationCauseCode::ExprAssignable
+            | ObligationCauseCode::MatchExpressionArm { .. }
+            | ObligationCauseCode::Pattern { .. }
+            | ObligationCauseCode::IfExpression { .. }
+            | ObligationCauseCode::IfExpressionWithNoElse
+            | ObligationCauseCode::MainFunctionType
+            | ObligationCauseCode::StartFunctionType
+            | ObligationCauseCode::IntrinsicType
+            | ObligationCauseCode::MethodReceiver
+            | ObligationCauseCode::ReturnNoExpression
+            | ObligationCauseCode::MiscObligation => {}
+            ObligationCauseCode::SliceOrArrayElem => {
+                err.note("slice and array elements must have `Sized` type");
+            }
+            ObligationCauseCode::TupleElem => {
+                err.note("only the last element of a tuple may have a dynamically sized type");
+            }
+            ObligationCauseCode::ProjectionWf(data) => {
+                err.note(&format!("required so that the projection `{}` is well-formed", data,));
+            }
+            ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
+                err.note(&format!(
+                    "required so that reference `{}` does not outlive its referent",
+                    ref_ty,
+                ));
+            }
+            ObligationCauseCode::ObjectTypeBound(object_ty, region) => {
+                err.note(&format!(
+                    "required so that the lifetime bound of `{}` for `{}` is satisfied",
+                    region, object_ty,
+                ));
+            }
+            ObligationCauseCode::ItemObligation(item_def_id) => {
+                let item_name = tcx.def_path_str(item_def_id);
+                let msg = format!("required by `{}`", item_name);
+
+                if let Some(sp) = tcx.hir().span_if_local(item_def_id) {
+                    let sp = tcx.sess.source_map().def_span(sp);
+                    err.span_label(sp, &msg);
+                } else {
+                    err.note(&msg);
+                }
+            }
+            ObligationCauseCode::BindingObligation(item_def_id, span) => {
+                let item_name = tcx.def_path_str(item_def_id);
+                let msg = format!("required by this bound in `{}`", item_name);
+                if let Some(ident) = tcx.opt_item_name(item_def_id) {
+                    err.span_label(ident.span, "");
+                }
+                if span != DUMMY_SP {
+                    err.span_label(span, &msg);
+                } else {
+                    err.note(&msg);
+                }
+            }
+            ObligationCauseCode::ObjectCastObligation(object_ty) => {
+                err.note(&format!(
+                    "required for the cast to the object type `{}`",
+                    self.ty_to_string(object_ty)
+                ));
+            }
+            ObligationCauseCode::Coercion { source: _, target } => {
+                err.note(&format!("required by cast to type `{}`", self.ty_to_string(target)));
+            }
+            ObligationCauseCode::RepeatVec(suggest_const_in_array_repeat_expressions) => {
+                err.note(
+                    "the `Copy` trait is required because the repeated element will be copied",
+                );
+                if suggest_const_in_array_repeat_expressions {
+                    err.note(
+                        "this array initializer can be evaluated at compile-time, for more \
+                         information, see issue \
+                         https://github.com/rust-lang/rust/issues/49147",
+                    );
+                    if tcx.sess.opts.unstable_features.is_nightly_build() {
+                        err.help(
+                            "add `#![feature(const_in_array_repeat_expressions)]` to the \
+                             crate attributes to enable",
+                        );
+                    }
+                }
+            }
+            ObligationCauseCode::VariableType(_) => {
+                err.note("all local variables must have a statically known size");
+                if !self.tcx.features().unsized_locals {
+                    err.help("unsized locals are gated as an unstable feature");
+                }
+            }
+            ObligationCauseCode::SizedArgumentType => {
+                err.note("all function arguments must have a statically known size");
+                if !self.tcx.features().unsized_locals {
+                    err.help("unsized locals are gated as an unstable feature");
+                }
+            }
+            ObligationCauseCode::SizedReturnType => {
+                err.note("the return type of a function must have a statically known size");
+            }
+            ObligationCauseCode::SizedYieldType => {
+                err.note("the yield type of a generator must have a statically known size");
+            }
+            ObligationCauseCode::AssignmentLhsSized => {
+                err.note("the left-hand-side of an assignment must have a statically known size");
+            }
+            ObligationCauseCode::TupleInitializerSized => {
+                err.note("tuples must have a statically known size to be initialized");
+            }
+            ObligationCauseCode::StructInitializerSized => {
+                err.note("structs must have a statically known size to be initialized");
+            }
+            ObligationCauseCode::FieldSized { adt_kind: ref item, last } => match *item {
+                AdtKind::Struct => {
+                    if last {
+                        err.note(
+                            "the last field of a packed struct may only have a \
+                             dynamically sized type if it does not need drop to be run",
+                        );
+                    } else {
+                        err.note(
+                            "only the last field of a struct may have a dynamically sized type",
+                        );
+                    }
+                }
+                AdtKind::Union => {
+                    err.note("no field of a union may have a dynamically sized type");
+                }
+                AdtKind::Enum => {
+                    err.note("no field of an enum variant may have a dynamically sized type");
+                }
+            },
+            ObligationCauseCode::ConstSized => {
+                err.note("constant expressions must have a statically known size");
+            }
+            ObligationCauseCode::ConstPatternStructural => {
+                err.note("constants used for pattern-matching must derive `PartialEq` and `Eq`");
+            }
+            ObligationCauseCode::SharedStatic => {
+                err.note("shared static variables must have a type that implements `Sync`");
+            }
+            ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
+                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
+                let ty = parent_trait_ref.skip_binder().self_ty();
+                err.note(&format!("required because it appears within the type `{}`", ty));
+                obligated_types.push(ty);
+
+                let parent_predicate = parent_trait_ref.to_predicate();
+                if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
+                    self.note_obligation_cause_code(
+                        err,
+                        &parent_predicate,
+                        &data.parent_code,
+                        obligated_types,
+                    );
+                }
+            }
+            ObligationCauseCode::ImplDerivedObligation(ref data) => {
+                let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
+                err.note(&format!(
+                    "required because of the requirements on the impl of `{}` for `{}`",
+                    parent_trait_ref.print_only_trait_path(),
+                    parent_trait_ref.skip_binder().self_ty()
+                ));
+                let parent_predicate = parent_trait_ref.to_predicate();
+                self.note_obligation_cause_code(
+                    err,
+                    &parent_predicate,
+                    &data.parent_code,
+                    obligated_types,
+                );
+            }
+            ObligationCauseCode::CompareImplMethodObligation { .. } => {
+                err.note(&format!(
+                    "the requirement `{}` appears on the impl method \
+                     but not on the corresponding trait method",
+                    predicate
+                ));
+            }
+            ObligationCauseCode::CompareImplTypeObligation { .. } => {
+                err.note(&format!(
+                    "the requirement `{}` appears on the associated impl type \
+                     but not on the corresponding associated trait type",
+                    predicate
+                ));
+            }
+            ObligationCauseCode::ReturnType
+            | ObligationCauseCode::ReturnValue(_)
+            | ObligationCauseCode::BlockTailExpression(_) => (),
+            ObligationCauseCode::TrivialBound => {
+                err.help("see issue #48214");
+                if tcx.sess.opts.unstable_features.is_nightly_build() {
+                    err.help("add `#![feature(trivial_bounds)]` to the crate attributes to enable");
+                }
+            }
+            ObligationCauseCode::AssocTypeBound(ref data) => {
+                err.span_label(data.original, "associated type defined here");
+                if let Some(sp) = data.impl_span {
+                    err.span_label(sp, "in this `impl` item");
+                }
+                for sp in &data.bounds {
+                    err.span_label(*sp, "restricted in this bound");
+                }
+            }
+        }
+    }
+
+    crate fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) {
+        let current_limit = self.tcx.sess.recursion_limit.get();
+        let suggested_limit = current_limit * 2;
+        err.help(&format!(
+            "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
+            suggested_limit
+        ));
+    }
+}
+
+/// Suggest restricting a type param with a new bound.
+pub fn suggest_constraining_type_param(
+    generics: &hir::Generics<'_>,
+    err: &mut DiagnosticBuilder<'_>,
+    param_name: &str,
+    constraint: &str,
+    source_map: &SourceMap,
+    span: Span,
+) -> bool {
+    let restrict_msg = "consider further restricting this bound";
+    if let Some(param) =
+        generics.params.iter().filter(|p| p.name.ident().as_str() == param_name).next()
+    {
+        if param_name.starts_with("impl ") {
+            // `impl Trait` in argument:
+            // `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
+            err.span_suggestion(
+                param.span,
+                restrict_msg,
+                // `impl CurrentTrait + MissingTrait`
+                format!("{} + {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        } else if generics.where_clause.predicates.is_empty() && param.bounds.is_empty() {
+            // If there are no bounds whatsoever, suggest adding a constraint
+            // to the type parameter:
+            // `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
+            err.span_suggestion(
+                param.span,
+                "consider restricting this bound",
+                format!("{}: {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        } else if !generics.where_clause.predicates.is_empty() {
+            // There is a `where` clause, so suggest expanding it:
+            // `fn foo<T>(t: T) where T: Debug {}` →
+            // `fn foo<T>(t: T) where T: Debug, T: Trait {}`
+            err.span_suggestion(
+                generics.where_clause.span().unwrap().shrink_to_hi(),
+                &format!("consider further restricting type parameter `{}`", param_name),
+                format!(", {}: {}", param_name, constraint),
+                Applicability::MachineApplicable,
+            );
+        } else {
+            // If there is no `where` clause lean towards constraining to the
+            // type parameter:
+            // `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
+            // `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
+            let sp = param.span.with_hi(span.hi());
+            let span = source_map.span_through_char(sp, ':');
+            if sp != param.span && sp != span {
+                // Only suggest if we have high certainty that the span
+                // covers the colon in `foo<T: Trait>`.
+                err.span_suggestion(
+                    span,
+                    restrict_msg,
+                    format!("{}: {} + ", param_name, constraint),
+                    Applicability::MachineApplicable,
+                );
+            } else {
+                err.span_label(
+                    param.span,
+                    &format!("consider adding a `where {}: {}` bound", param_name, constraint),
+                );
+            }
+        }
+        return true;
+    }
+    false
+}
+
+/// Collect all the returned expressions within the input expression.
+/// Used to point at the return spans when we want to suggest some change to them.
+struct ReturnsVisitor<'v>(Vec<&'v hir::Expr<'v>>);
+
+impl<'v> Visitor<'v> for ReturnsVisitor<'v> {
+    type Map = rustc::hir::map::Map<'v>;
+
+    fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<'_, Self::Map> {
+        hir::intravisit::NestedVisitorMap::None
+    }
+
+    fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
+        if let hir::ExprKind::Ret(Some(ex)) = ex.kind {
+            self.0.push(ex);
+        }
+        hir::intravisit::walk_expr(self, ex);
+    }
+
+    fn visit_body(&mut self, body: &'v hir::Body<'v>) {
+        if body.generator_kind().is_none() {
+            if let hir::ExprKind::Block(block, None) = body.value.kind {
+                if let Some(expr) = block.expr {
+                    self.0.push(expr);
+                }
+            }
+        }
+        hir::intravisit::walk_body(self, body);
+    }
+}
index 7509c2251f083d4dc211f2a8a5a35fd1a0c2e0ae..e93529186ac86ebf8f6f0838e2f7ad8780e6763f 100644 (file)
@@ -155,8 +155,8 @@ pub struct ObligationCause<'tcx> {
     pub code: ObligationCauseCode<'tcx>,
 }
 
-impl<'tcx> ObligationCause<'tcx> {
-    pub fn span(&self, tcx: TyCtxt<'tcx>) -> Span {
+impl ObligationCause<'_> {
+    pub fn span(&self, tcx: TyCtxt<'_>) -> Span {
         match self.code {
             ObligationCauseCode::CompareImplMethodObligation { .. }
             | ObligationCauseCode::MainFunctionType
@@ -1167,6 +1167,17 @@ pub fn dummy() -> ObligationCause<'tcx> {
     }
 }
 
+impl ObligationCauseCode<'_> {
+    // Return the base obligation, ignoring derived obligations.
+    pub fn peel_derives(&self) -> &Self {
+        let mut base_cause = self;
+        while let BuiltinDerivedObligation(cause) | ImplDerivedObligation(cause) = base_cause {
+            base_cause = &cause.parent_code;
+        }
+        base_cause
+    }
+}
+
 impl<'tcx, N> Vtable<'tcx, N> {
     pub fn nested_obligations(self) -> Vec<N> {
         match self {
index 1afe153bb1361937a7f72c4be81b61df8812bee5..669ec5ccc9b98b43edcfdf3706acc49406b7bab2 100644 (file)
@@ -11,8 +11,6 @@
 use syntax::ast::{MetaItem, NestedMetaItem};
 use syntax::attr;
 
-use rustc_error_codes::*;
-
 #[derive(Clone, Debug)]
 pub struct OnUnimplementedFormatString(Symbol);
 
index 34866b684de01a9369ed73182edf3c7093732a3f..2e5ef5adcd30ed96b5329993e54b65728e3c67ed 100644 (file)
@@ -6,8 +6,6 @@
 use rustc_span::source_map::Span;
 use std::iter::FromIterator;
 
-use rustc_error_codes::*;
-
 impl<'cx, 'tcx> At<'cx, 'tcx> {
     /// Given a type `ty` of some value being dropped, computes a set
     /// of "kinds" (types, regions) that must be outlive the execution
index fb1c46834d3a04af79321b0e4b029df0bfe4e274..3bfe542baabbf82a8e4245f545620d6d15cfab26 100644 (file)
@@ -1417,6 +1417,8 @@ fn candidate_from_obligation_no_cache<'o>(
 
         debug!("winnowed to {} candidates for {:?}: {:?}", candidates.len(), stack, candidates);
 
+        let needs_infer = stack.obligation.predicate.needs_infer();
+
         // If there are STILL multiple candidates, we can further
         // reduce the list by dropping duplicates -- including
         // resolving specializations.
@@ -1424,7 +1426,11 @@ fn candidate_from_obligation_no_cache<'o>(
             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])
+                    self.candidate_should_be_dropped_in_favor_of(
+                        &candidates[i],
+                        &candidates[j],
+                        needs_infer,
+                    )
                 });
                 if is_dup {
                     debug!("Dropping candidate #{}/{}: {:?}", i, candidates.len(), candidates[i]);
@@ -2258,6 +2264,7 @@ fn candidate_should_be_dropped_in_favor_of(
         &mut self,
         victim: &EvaluatedCandidate<'tcx>,
         other: &EvaluatedCandidate<'tcx>,
+        needs_infer: bool,
     ) -> bool {
         if victim.candidate == other.candidate {
             return true;
@@ -2339,10 +2346,55 @@ fn candidate_should_be_dropped_in_favor_of(
                     match victim.candidate {
                         ImplCandidate(victim_def) => {
                             let tcx = self.tcx();
-                            return tcx.specializes((other_def, victim_def))
-                                || tcx
-                                    .impls_are_allowed_to_overlap(other_def, victim_def)
-                                    .is_some();
+                            if tcx.specializes((other_def, victim_def)) {
+                                return true;
+                            }
+                            return match tcx.impls_are_allowed_to_overlap(other_def, victim_def) {
+                                Some(ty::ImplOverlapKind::Permitted { marker: true }) => {
+                                    // Subtle: If the predicate we are evaluating has inference
+                                    // variables, do *not* allow discarding candidates due to
+                                    // marker trait impls.
+                                    //
+                                    // Without this restriction, we could end up accidentally
+                                    // constrainting inference variables based on an arbitrarily
+                                    // chosen trait impl.
+                                    //
+                                    // Imagine we have the following code:
+                                    //
+                                    // ```rust
+                                    // #[marker] trait MyTrait {}
+                                    // impl MyTrait for u8 {}
+                                    // impl MyTrait for bool {}
+                                    // ```
+                                    //
+                                    // And we are evaluating the predicate `<_#0t as MyTrait>`.
+                                    //
+                                    // During selection, we will end up with one candidate for each
+                                    // impl of `MyTrait`. If we were to discard one impl in favor
+                                    // of the other, we would be left with one candidate, causing
+                                    // us to "successfully" select the predicate, unifying
+                                    // _#0t with (for example) `u8`.
+                                    //
+                                    // However, we have no reason to believe that this unification
+                                    // is correct - we've essentially just picked an arbitrary
+                                    // *possibility* for _#0t, and required that this be the *only*
+                                    // possibility.
+                                    //
+                                    // Eventually, we will either:
+                                    // 1) Unify all inference variables in the predicate through
+                                    // some other means (e.g. type-checking of a function). We will
+                                    // then be in a position to drop marker trait candidates
+                                    // without constraining inference variables (since there are
+                                    // none left to constrin)
+                                    // 2) Be left with some unconstrained inference variables. We
+                                    // will then correctly report an inference error, since the
+                                    // existence of multiple marker trait impls tells us nothing
+                                    // about which one should actually apply.
+                                    !needs_infer
+                                }
+                                Some(_) => true,
+                                None => false,
+                            };
                         }
                         ParamCandidate(ref cand) => {
                             // Prefer the impl to a global where clause candidate.
index f5199dbdabb2f42534d164b92ef1b4820e33e084..e559ea391cde09e10bd083047b0e5b1a0d36eb57 100644 (file)
@@ -25,8 +25,6 @@
 use super::util::impl_trait_ref_and_oblig;
 use super::{FulfillmentContext, SelectionContext};
 
-use rustc_error_codes::*;
-
 /// Information pertinent to an overlapping impl error.
 #[derive(Debug)]
 pub struct OverlapError {
index c176f139bf86826cc41d7a28258d19414e236cf1..9509b6220eb0ed15d6d49db5445686b7225545fe 100644 (file)
@@ -163,7 +163,7 @@ fn insert(
                         tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling)
                     {
                         match overlap_kind {
-                            ty::ImplOverlapKind::Permitted => {}
+                            ty::ImplOverlapKind::Permitted { marker: _ } => {}
                             ty::ImplOverlapKind::Issue33140 => {
                                 last_lint = Some(FutureCompatOverlapError {
                                     error: overlap_error(overlap),
index 65fd809657bd08fec282c73130cc6d86e9a017b0..f058a4d2df24a60ed4626126e74092c8dc0a92ee 100644 (file)
@@ -651,7 +651,7 @@ pub fn impl_is_default(tcx: TyCtxt<'_>, node_item_def_id: DefId) -> bool {
     match tcx.hir().as_local_hir_id(node_item_def_id) {
         Some(hir_id) => {
             let item = tcx.hir().expect_item(hir_id);
-            if let hir::ItemKind::Impl(_, _, defaultness, ..) = item.kind {
+            if let hir::ItemKind::Impl { defaultness, .. } = item.kind {
                 defaultness.is_default()
             } else {
                 false
index 2301395f557f13d0d9b1ce2c123175c8039940db..869ba5315c1aee3c5fab435e6e723be9b05bdfad 100644 (file)
@@ -229,9 +229,9 @@ fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elabo
                         //      |
                         //      = note: expected type `u32`
                         //                 found type `()`
-                        if let Some(hir::ItemKind::Impl(.., impl_items)) = item.map(|i| &i.kind) {
+                        if let Some(hir::ItemKind::Impl { items, .. }) = item.map(|i| &i.kind) {
                             let trait_assoc_item = tcx.associated_item(proj.projection_def_id());
-                            if let Some(impl_item) = impl_items
+                            if let Some(impl_item) = items
                                 .iter()
                                 .filter(|item| item.ident == trait_assoc_item.ident)
                                 .next()
@@ -279,14 +279,14 @@ fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elabo
                         //      |     ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
                         if let (
                             ty::Projection(ty::ProjectionTy { item_def_id, .. }),
-                            Some(hir::ItemKind::Impl(.., impl_items)),
+                            Some(hir::ItemKind::Impl { items, .. }),
                         ) = (&proj.skip_binder().self_ty().kind, item.map(|i| &i.kind))
                         {
                             if let Some((impl_item, trait_assoc_item)) = trait_assoc_items
                                 .filter(|i| i.def_id == *item_def_id)
                                 .next()
                                 .and_then(|trait_assoc_item| {
-                                    impl_items
+                                    items
                                         .iter()
                                         .filter(|i| i.ident == trait_assoc_item.ident)
                                         .next()
index ef776c88a8f7cd85859c809c59c46a90cb56a37d..a51f0f7f24c368e6f8aebcc45fb6a023c745c0c0 100644 (file)
 use rustc_session::config::{BorrowckMode, OutputFilenames};
 use rustc_session::Session;
 
-use arena::SyncDroplessArena;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::profiling::SelfProfilerRef;
-use rustc_data_structures::sharded::ShardedHashMap;
+use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
 use rustc_data_structures::stable_hasher::{
     hash_stable_hashmap, HashStable, StableHasher, StableVec,
 };
 use syntax::attr;
 use syntax::expand::allocator::AllocatorKind;
 
-pub struct AllArenas {
-    pub interner: SyncDroplessArena,
-}
-
-impl AllArenas {
-    pub fn new() -> Self {
-        AllArenas { interner: SyncDroplessArena::default() }
-    }
-}
-
 type InternedSet<'tcx, T> = ShardedHashMap<Interned<'tcx, T>, ()>;
 
 pub struct CtxtInterners<'tcx> {
     /// The arena that types, regions, etc. are allocated from.
-    arena: &'tcx SyncDroplessArena,
+    arena: &'tcx WorkerLocal<Arena<'tcx>>,
 
     /// Specifically use a speedy hash algorithm for these hash sets, since
     /// they're accessed quite often.
@@ -117,7 +106,7 @@ pub struct CtxtInterners<'tcx> {
 }
 
 impl<'tcx> CtxtInterners<'tcx> {
-    fn new(arena: &'tcx SyncDroplessArena) -> CtxtInterners<'tcx> {
+    fn new(arena: &'tcx WorkerLocal<Arena<'tcx>>) -> CtxtInterners<'tcx> {
         CtxtInterners {
             arena,
             type_: Default::default(),
@@ -1125,7 +1114,6 @@ pub fn create_global_ctxt(
         lint_store: Lrc<dyn Any + sync::Send + sync::Sync>,
         local_providers: ty::query::Providers<'tcx>,
         extern_providers: ty::query::Providers<'tcx>,
-        arenas: &'tcx AllArenas,
         arena: &'tcx WorkerLocal<Arena<'tcx>>,
         resolutions: ty::ResolverOutputs,
         hir: hir_map::Map<'tcx>,
@@ -1136,7 +1124,7 @@ pub fn create_global_ctxt(
         let data_layout = TargetDataLayout::parse(&s.target.target).unwrap_or_else(|err| {
             s.fatal(&err);
         });
-        let interners = CtxtInterners::new(&arenas.interner);
+        let interners = CtxtInterners::new(arena);
         let common_types = CommonTypes::new(&interners);
         let common_lifetimes = CommonLifetimes::new(&interners);
         let common_consts = CommonConsts::new(&interners, &common_types);
@@ -1567,11 +1555,11 @@ pub trait Lift<'tcx>: fmt::Debug {
 }
 
 macro_rules! nop_lift {
-    ($ty:ty => $lifted:ty) => {
+    ($set:ident; $ty:ty => $lifted:ty) => {
         impl<'a, 'tcx> Lift<'tcx> for $ty {
             type Lifted = $lifted;
             fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
-                if tcx.interners.arena.in_arena(*self as *const _) {
+                if tcx.interners.$set.contains_pointer_to(&Interned(*self)) {
                     Some(unsafe { mem::transmute(*self) })
                 } else {
                     None
@@ -1582,14 +1570,14 @@ fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
 }
 
 macro_rules! nop_list_lift {
-    ($ty:ty => $lifted:ty) => {
+    ($set:ident; $ty:ty => $lifted:ty) => {
         impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> {
             type Lifted = &'tcx List<$lifted>;
             fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
                 if self.is_empty() {
                     return Some(List::empty());
                 }
-                if tcx.interners.arena.in_arena(*self as *const _) {
+                if tcx.interners.$set.contains_pointer_to(&Interned(*self)) {
                     Some(unsafe { mem::transmute(*self) })
                 } else {
                     None
@@ -1599,21 +1587,21 @@ fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
     };
 }
 
-nop_lift! {Ty<'a> => Ty<'tcx>}
-nop_lift! {Region<'a> => Region<'tcx>}
-nop_lift! {Goal<'a> => Goal<'tcx>}
-nop_lift! {&'a Const<'a> => &'tcx Const<'tcx>}
+nop_lift! {type_; Ty<'a> => Ty<'tcx>}
+nop_lift! {region; Region<'a> => Region<'tcx>}
+nop_lift! {goal; Goal<'a> => Goal<'tcx>}
+nop_lift! {const_; &'a Const<'a> => &'tcx Const<'tcx>}
 
-nop_list_lift! {Goal<'a> => Goal<'tcx>}
-nop_list_lift! {Clause<'a> => Clause<'tcx>}
-nop_list_lift! {Ty<'a> => Ty<'tcx>}
-nop_list_lift! {ExistentialPredicate<'a> => ExistentialPredicate<'tcx>}
-nop_list_lift! {Predicate<'a> => Predicate<'tcx>}
-nop_list_lift! {CanonicalVarInfo => CanonicalVarInfo}
-nop_list_lift! {ProjectionKind => ProjectionKind}
+nop_list_lift! {goal_list; Goal<'a> => Goal<'tcx>}
+nop_list_lift! {clauses; Clause<'a> => Clause<'tcx>}
+nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>}
+nop_list_lift! {existential_predicates; ExistentialPredicate<'a> => ExistentialPredicate<'tcx>}
+nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>}
+nop_list_lift! {canonical_var_infos; CanonicalVarInfo => CanonicalVarInfo}
+nop_list_lift! {projs; ProjectionKind => ProjectionKind}
 
 // This is the impl for `&'a InternalSubsts<'a>`.
-nop_list_lift! {GenericArg<'a> => GenericArg<'tcx>}
+nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>}
 
 pub mod tls {
     use super::{ptr_eq, GlobalCtxt, TyCtxt};
@@ -1937,6 +1925,11 @@ fn clone(&self) -> Self {
 }
 impl<'tcx, T: 'tcx + ?Sized> Copy for Interned<'tcx, T> {}
 
+impl<'tcx, T: 'tcx + ?Sized> IntoPointer for Interned<'tcx, T> {
+    fn into_pointer(&self) -> *const () {
+        self.0 as *const _ as *const ()
+    }
+}
 // N.B., an `Interned<Ty>` compares and hashes as a `TyKind`.
 impl<'tcx> PartialEq for Interned<'tcx, TyS<'tcx>> {
     fn eq(&self, other: &Interned<'tcx, TyS<'tcx>>) -> bool {
@@ -2089,7 +2082,7 @@ macro_rules! slice_interners {
         $(impl<'tcx> TyCtxt<'tcx> {
             pub fn $method(self, v: &[$ty]) -> &'tcx List<$ty> {
                 self.interners.$field.intern_ref(v, || {
-                    Interned(List::from_arena(&self.interners.arena, v))
+                    Interned(List::from_arena(&*self.arena, v))
                 }).0
             }
         })+
index f7612874e05b6b9b9ee5a455707eb27447cbf155..217ca0ca3f6f51d38e464b578ddadaaf16593370 100644 (file)
@@ -244,9 +244,9 @@ pub fn sort_string(&self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
             ty::FnPtr(_) => "fn pointer".into(),
             ty::Dynamic(ref inner, ..) => {
                 if let Some(principal) = inner.principal() {
-                    format!("trait `{}`", tcx.def_path_str(principal.def_id())).into()
+                    format!("trait object `dyn {}`", tcx.def_path_str(principal.def_id())).into()
                 } else {
-                    "trait".into()
+                    "trait object".into()
                 }
             }
             ty::Closure(..) => "closure".into(),
index e6acb6b74dc6340b449d074ef66d7875463c371e..3040ecf90ed53b95925f8ed254c0c204067b80e4 100644 (file)
@@ -6,6 +6,7 @@
 pub use self::IntVarValue::*;
 pub use self::Variance::*;
 
+use crate::arena::Arena;
 use crate::hir::exports::ExportMap;
 use crate::hir::map as hir_map;
 
@@ -25,7 +26,6 @@
 use crate::ty::subst::{InternalSubsts, Subst, SubstsRef};
 use crate::ty::util::{Discr, IntTypeExt};
 use crate::ty::walk::TypeWalker;
-use arena::SyncDroplessArena;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::fx::FxIndexMap;
@@ -74,7 +74,7 @@
 pub use self::binding::BindingMode;
 pub use self::binding::BindingMode::*;
 
-pub use self::context::{keep_local, tls, AllArenas, FreeRegionInfo, TyCtxt};
+pub use self::context::{keep_local, tls, FreeRegionInfo, TyCtxt};
 pub use self::context::{
     CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, ResolvedOpaqueTy,
     UserType, UserTypeAnnotationIndex,
@@ -604,7 +604,7 @@ unsafe impl<T: Sync> Sync for List<T> {}
 
 impl<T: Copy> List<T> {
     #[inline]
-    fn from_arena<'tcx>(arena: &'tcx SyncDroplessArena, slice: &[T]) -> &'tcx List<T> {
+    fn from_arena<'tcx>(arena: &'tcx Arena<'tcx>, slice: &[T]) -> &'tcx List<T> {
         assert!(!mem::needs_drop::<T>());
         assert!(mem::size_of::<T>() != 0);
         assert!(slice.len() != 0);
@@ -617,7 +617,9 @@ fn from_arena<'tcx>(arena: &'tcx SyncDroplessArena, slice: &[T]) -> &'tcx List<T
 
         let size = offset + slice.len() * mem::size_of::<T>();
 
-        let mem = arena.alloc_raw(size, cmp::max(mem::align_of::<T>(), mem::align_of::<usize>()));
+        let mem = arena
+            .dropless
+            .alloc_raw(size, cmp::max(mem::align_of::<T>(), mem::align_of::<usize>()));
         unsafe {
             let result = &mut *(mem.as_mut_ptr() as *mut List<T>);
             // Write the length
@@ -2589,7 +2591,12 @@ fn deref(&self) -> &[ast::Attribute] {
 #[derive(Debug, PartialEq, Eq)]
 pub enum ImplOverlapKind {
     /// These impls are always allowed to overlap.
-    Permitted,
+    Permitted {
+        /// Whether or not the impl is permitted due to the trait being
+        /// a marker trait (a trait with #[marker], or a trait with
+        /// no associated items and #![feature(overlapping_marker_traits)] enabled)
+        marker: bool,
+    },
     /// These impls are allowed to overlap, but that raises
     /// an issue #33140 future-compatibility warning.
     ///
@@ -2709,7 +2716,7 @@ pub fn impls_are_allowed_to_overlap(
         if self.impl_trait_ref(def_id1).map_or(false, |tr| tr.references_error())
             || self.impl_trait_ref(def_id2).map_or(false, |tr| tr.references_error())
         {
-            return Some(ImplOverlapKind::Permitted);
+            return Some(ImplOverlapKind::Permitted { marker: false });
         }
 
         match (self.impl_polarity(def_id1), self.impl_polarity(def_id2)) {
@@ -2719,7 +2726,7 @@ pub fn impls_are_allowed_to_overlap(
                     "impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) (reservations)",
                     def_id1, def_id2
                 );
-                return Some(ImplOverlapKind::Permitted);
+                return Some(ImplOverlapKind::Permitted { marker: false });
             }
             (ImplPolarity::Positive, ImplPolarity::Negative)
             | (ImplPolarity::Negative, ImplPolarity::Positive) => {
@@ -2755,7 +2762,7 @@ pub fn impls_are_allowed_to_overlap(
                 "impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) (marker overlap)",
                 def_id1, def_id2
             );
-            Some(ImplOverlapKind::Permitted)
+            Some(ImplOverlapKind::Permitted { marker: true })
         } else {
             if let Some(self_ty1) = self.issue33140_self_ty(def_id1) {
                 if let Some(self_ty2) = self.issue33140_self_ty(def_id2) {
index 84efbe21f10aa25bce31a01e0599f574e9e4e92f..117a38c655eaa51a7b66808c66955afcd9705bef 100644 (file)
@@ -25,8 +25,6 @@
 use std::mem;
 use std::ptr;
 
-use rustc_error_codes::*;
-
 pub struct QueryCache<'tcx, D: QueryConfig<'tcx> + ?Sized> {
     pub(super) results: FxHashMap<D::Key, QueryValue<D::Value>>,
     pub(super) active: FxHashMap<D::Key, QueryResult<'tcx>>,
index 408e9a75d93dd6a92aeec7d9183efa0dbe8f867f..4b786d6245fc4056d6ee77a77b54a24433024788 100644 (file)
@@ -17,7 +17,6 @@ rustc_target = { path = "../librustc_target" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_index = { path = "../librustc_index" }
 rustc_span = { path = "../librustc_span" }
-rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_session = { path = "../librustc_session" }
 syntax = { path = "../libsyntax" }
index 9a229e709a5e55dd911f1038b24db78f69687016..a24bb52150a7224aa8b03bf14ff677e891cb1e72 100644 (file)
@@ -2,7 +2,6 @@
 
 use rustc::bug;
 use rustc_data_structures::thin_vec::ThinVec;
-use rustc_error_codes::*;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
@@ -909,18 +908,18 @@ fn with_loop_condition_scope<T, F>(&mut self, f: F) -> T
 
     fn lower_expr_asm(&mut self, asm: &InlineAsm) -> hir::ExprKind<'hir> {
         let inner = hir::InlineAsmInner {
-            inputs: asm.inputs.iter().map(|&(ref c, _)| c.clone()).collect(),
+            inputs: asm.inputs.iter().map(|&(c, _)| c).collect(),
             outputs: asm
                 .outputs
                 .iter()
                 .map(|out| hir::InlineAsmOutput {
-                    constraint: out.constraint.clone(),
+                    constraint: out.constraint,
                     is_rw: out.is_rw,
                     is_indirect: out.is_indirect,
                     span: out.expr.span,
                 })
                 .collect(),
-            asm: asm.asm.clone(),
+            asm: asm.asm,
             asm_str_style: asm.asm_str_style,
             clobbers: asm.clobbers.clone().into(),
             volatile: asm.volatile,
index beb53a19ac4ffae7bdbcb5e1be8111656b919dfa..bcc40b0c9c9c93b54b9a7511a8bc59dbfbb6bd14 100644 (file)
@@ -3,7 +3,6 @@
 
 use rustc::arena::Arena;
 use rustc::bug;
-use rustc_error_codes::*;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
@@ -67,14 +66,15 @@ fn visit_item(&mut self, item: &'a Item) {
         if let Some(hir_id) = item_hir_id {
             self.lctx.with_parent_item_lifetime_defs(hir_id, |this| {
                 let this = &mut ItemLowerer { lctx: this };
-                if let ItemKind::Impl(.., ref opt_trait_ref, _, _) = item.kind {
-                    if opt_trait_ref.as_ref().map(|tr| tr.constness.is_some()).unwrap_or(false) {
+                if let ItemKind::Impl { ref of_trait, .. } = item.kind {
+                    if of_trait.as_ref().map(|tr| tr.constness.is_some()).unwrap_or(false) {
+                        this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item));
                         this.lctx
                             .diagnostic()
                             .span_err(item.span, "const trait impls are not yet implemented");
                     }
 
-                    this.with_trait_impl_ref(opt_trait_ref, |this| visit::walk_item(this, item));
+                    this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item));
                 } else {
                     visit::walk_item(this, item);
                 }
@@ -118,7 +118,7 @@ fn with_parent_item_lifetime_defs<T>(
         let old_len = self.in_scope_lifetimes.len();
 
         let parent_generics = match self.items.get(&parent_hir_id).unwrap().kind {
-            hir::ItemKind::Impl(_, _, _, ref generics, ..)
+            hir::ItemKind::Impl { ref generics, .. }
             | hir::ItemKind::Trait(_, _, ref generics, ..) => &generics.params[..],
             _ => &[],
         };
@@ -173,7 +173,7 @@ pub(super) fn lower_mod(&mut self, m: &Mod) -> hir::Mod<'hir> {
                 vec
             }
             ItemKind::MacroDef(..) => SmallVec::new(),
-            ItemKind::Fn(..) | ItemKind::Impl(.., None, _, _) => smallvec![i.id],
+            ItemKind::Fn(..) | ItemKind::Impl { of_trait: None, .. } => smallvec![i.id],
             ItemKind::Static(ref ty, ..) => {
                 let mut ids = smallvec![i.id];
                 if self.sess.features_untracked().impl_trait_in_bindings {
@@ -361,15 +361,15 @@ fn lower_item_kind(
                     self.lower_generics(generics, ImplTraitContext::disallowed()),
                 )
             }
-            ItemKind::Impl(
+            ItemKind::Impl {
                 unsafety,
                 polarity,
                 defaultness,
-                ref ast_generics,
-                ref trait_ref,
-                ref ty,
-                ref impl_items,
-            ) => {
+                generics: ref ast_generics,
+                of_trait: ref trait_ref,
+                self_ty: ref ty,
+                items: ref impl_items,
+            } => {
                 let def_id = self.resolver.definitions().local_def_id(id);
 
                 // Lower the "impl header" first. This ordering is important
@@ -417,15 +417,15 @@ fn lower_item_kind(
                         )
                     });
 
-                hir::ItemKind::Impl(
+                hir::ItemKind::Impl {
                     unsafety,
                     polarity,
-                    self.lower_defaultness(defaultness, true /* [1] */),
+                    defaultness: self.lower_defaultness(defaultness, true /* [1] */),
                     generics,
-                    trait_ref,
-                    lowered_ty,
-                    new_impl_items,
-                )
+                    of_trait: trait_ref,
+                    self_ty: lowered_ty,
+                    items: new_impl_items,
+                }
             }
             ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref items) => {
                 let bounds = self.lower_param_bounds(bounds, ImplTraitContext::disallowed());
index 76a0889c376a22b1367ebf67fcec7cb21dbf249a..2cd4a6eb7e21ba15edf5a03ddf5cda9a025ef93e 100644 (file)
@@ -41,7 +41,6 @@
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
-use rustc_error_codes::*;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res};
index 65347d379bd6a19e97d19a67c8a07d4e6c879b0c..e5f7df6dbf9e453e7f13fc045270e6b79d215717 100644 (file)
@@ -3,7 +3,6 @@
 
 use rustc::lint::builtin::ELIDED_LIFETIMES_IN_PATHS;
 use rustc::span_bug;
-use rustc_error_codes::*;
 use rustc_errors::{struct_span_err, Applicability};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, PartialRes, Res};
index 2d45e280444955e08b2784647840c985f5d044e3..25b1acebd2a08bf2b58f4e8b3215d692578bf1ef 100644 (file)
@@ -12,7 +12,6 @@ path = "lib.rs"
 log = "0.4"
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
-rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_parse = { path = "../librustc_parse" }
 rustc_session = { path = "../librustc_session" }
index c915b7ba21692873630451ea71d230e3aafa4d72..bc02406aa2158b131a3cf81c29157b5ba268403f 100644 (file)
@@ -23,8 +23,6 @@
 use syntax::visit::{self, Visitor};
 use syntax::walk_list;
 
-use rustc_error_codes::*;
-
 /// A syntactic context that disallows certain kinds of bounds (e.g., `?Trait` or `?const Trait`).
 #[derive(Clone, Copy)]
 enum BoundContext {
@@ -612,9 +610,17 @@ fn visit_item(&mut self, item: &'a Item) {
         }
 
         match item.kind {
-            ItemKind::Impl(unsafety, polarity, _, _, Some(..), ref ty, ref impl_items) => {
+            ItemKind::Impl {
+                unsafety,
+                polarity,
+                defaultness: _,
+                generics: _,
+                of_trait: Some(_),
+                ref self_ty,
+                ref items,
+            } => {
                 self.invalid_visibility(&item.vis, None);
-                if let TyKind::Err = ty.kind {
+                if let TyKind::Err = self_ty.kind {
                     self.err_handler()
                         .struct_span_err(item.span, "`impl Trait for .. {}` is an obsolete syntax")
                         .help("use `auto trait Trait {}` instead")
@@ -629,7 +635,7 @@ fn visit_item(&mut self, item: &'a Item) {
                     )
                     .emit();
                 }
-                for impl_item in impl_items {
+                for impl_item in items {
                     self.invalid_visibility(&impl_item.vis, None);
                     if let AssocItemKind::Fn(ref sig, _) = impl_item.kind {
                         self.check_trait_fn_not_const(sig.header.constness);
@@ -637,7 +643,15 @@ fn visit_item(&mut self, item: &'a Item) {
                     }
                 }
             }
-            ItemKind::Impl(unsafety, polarity, defaultness, _, None, _, _) => {
+            ItemKind::Impl {
+                unsafety,
+                polarity,
+                defaultness,
+                generics: _,
+                of_trait: None,
+                self_ty: _,
+                items: _,
+            } => {
                 self.invalid_visibility(
                     &item.vis,
                     Some("place qualifiers on individual impl items instead"),
index 1e4b1ae07776212a8261dc882d999c45b7f71baf..953127429d5aa7ff7cea891ce28ac438eda5dffb 100644 (file)
@@ -1,4 +1,3 @@
-use rustc_error_codes::*;
 use rustc_errors::{struct_span_err, Handler};
 use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP};
 use rustc_feature::{Features, GateIssue, UnstableFeatures};
@@ -339,7 +338,7 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                 }
             }
 
-            ast::ItemKind::Impl(_, polarity, defaultness, ..) => {
+            ast::ItemKind::Impl { polarity, defaultness, .. } => {
                 if polarity == ast::ImplPolarity::Negative {
                     gate_feature_post!(
                         &self,
@@ -470,29 +469,8 @@ fn visit_expr(&mut self, e: &'a ast::Expr) {
         visit::walk_expr(self, e)
     }
 
-    fn visit_arm(&mut self, arm: &'a ast::Arm) {
-        visit::walk_arm(self, arm)
-    }
-
     fn visit_pat(&mut self, pattern: &'a ast::Pat) {
         match &pattern.kind {
-            PatKind::Slice(pats) => {
-                for pat in &*pats {
-                    let span = pat.span;
-                    let inner_pat = match &pat.kind {
-                        PatKind::Ident(.., Some(pat)) => pat,
-                        _ => pat,
-                    };
-                    if inner_pat.is_rest() {
-                        gate_feature_post!(
-                            &self,
-                            slice_patterns,
-                            span,
-                            "subslice patterns are unstable"
-                        );
-                    }
-                }
-            }
             PatKind::Box(..) => {
                 gate_feature_post!(
                     &self,
index eadbc485296e8705f41c4522ed6b88f42a4604fe..5de45f4e1f36571e597f6e8cfddb58f2688c4c4c 100644 (file)
@@ -2,7 +2,7 @@
 //! parsed by `rustc_parse` and then lowered, after the passes in this crate,
 //! by `rustc_ast_lowering`.
 
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 
 pub mod ast_validation;
 pub mod feature_gate;
index f291eaf93580bf526ecf1bb8594518ab584df985..3ce7f5d770ed165ce8f6a70197594829125a5637 100644 (file)
@@ -22,4 +22,3 @@ smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 syntax = { path = "../libsyntax" }
 rustc_expand = { path = "../librustc_expand" }
 rustc_span = { path = "../librustc_span" }
-rustc_error_codes = { path = "../librustc_error_codes" }
index a6b45e0567c72c23516dd6f0f387318a36b909eb..4723544316faffaf883077635d5b54ac8b6deca2 100644 (file)
@@ -12,8 +12,6 @@
 use syntax::token::{self, Token};
 use syntax::tokenstream::{self, TokenStream};
 
-use rustc_error_codes::*;
-
 enum State {
     Asm,
     Outputs,
index 72c41ad9745c1ae505cd78f5cea9155b36135c9f..b4f059e94c15e434612e9316648a2f6f0a298370 100644 (file)
@@ -9,8 +9,6 @@
 use syntax::ast::{Expr, MetaItem};
 use syntax::ptr::P;
 
-use rustc_error_codes::*;
-
 pub fn expand_deriving_default(
     cx: &mut ExtCtxt<'_>,
     span: Span,
index 7092483843f70df40c8b7d517ac5649e7d392f56..d346dbc8b4ee71a91aa6908c83b7338b09c54bef 100644 (file)
@@ -705,15 +705,15 @@ fn create_derived_impl(
             self.span,
             Ident::invalid(),
             a,
-            ast::ItemKind::Impl(
+            ast::ItemKind::Impl {
                 unsafety,
-                ast::ImplPolarity::Positive,
-                ast::Defaultness::Final,
-                trait_generics,
-                opt_trait_ref,
-                self_type,
-                methods.into_iter().chain(associated_types).collect(),
-            ),
+                polarity: ast::ImplPolarity::Positive,
+                defaultness: ast::Defaultness::Final,
+                generics: trait_generics,
+                of_trait: opt_trait_ref,
+                self_ty: self_type,
+                items: methods.into_iter().chain(associated_types).collect(),
+            },
         )
     }
 
@@ -1608,7 +1608,7 @@ fn create_subpatterns(
                 } else {
                     ast::BindingMode::ByRef(mutbl)
                 };
-                cx.pat(path.span, PatKind::Ident(binding_mode, (*path).clone(), None))
+                cx.pat(path.span, PatKind::Ident(binding_mode, *path, None))
             })
             .collect()
     }
index 4d83a6635ab17ce4f71f104dddfac76e613345db..9aa7623dc9f77cd1e3f856869b7b5aeee471792f 100644 (file)
@@ -156,15 +156,15 @@ fn inject_impl_of_structural_trait(
         span,
         ast::Ident::invalid(),
         attrs,
-        ItemKind::Impl(
-            ast::Unsafety::Normal,
-            ast::ImplPolarity::Positive,
-            ast::Defaultness::Final,
+        ItemKind::Impl {
+            unsafety: ast::Unsafety::Normal,
+            polarity: ast::ImplPolarity::Positive,
+            defaultness: ast::Defaultness::Final,
             generics,
-            Some(trait_ref),
-            self_type,
-            Vec::new(),
-        ),
+            of_trait: Some(trait_ref),
+            self_ty: self_type,
+            items: Vec::new(),
+        },
     );
 
     push(Annotatable::Item(newitem));
index 6fca74e22394465646dd5fda813fd02dbdf633e7..3f4e24ca993db4a14c5c619ba9b215c655400875 100644 (file)
@@ -590,17 +590,6 @@ fn build_piece(
             parse::NextArgument(ref arg) => {
                 // Build the position
                 let pos = {
-                    let pos = |c, arg| {
-                        let mut path = Context::rtpath(self.ecx, "Position");
-                        path.push(self.ecx.ident_of(c, sp));
-                        match arg {
-                            Some(i) => {
-                                let arg = self.ecx.expr_usize(sp, i);
-                                self.ecx.expr_call_global(sp, path, vec![arg])
-                            }
-                            None => self.ecx.expr_path(self.ecx.path_global(sp, path)),
-                        }
-                    };
                     match arg.position {
                         parse::ArgumentIs(i) | parse::ArgumentImplicitlyIs(i) => {
                             // Map to index in final generated argument array
@@ -615,7 +604,7 @@ fn build_piece(
                                     arg_idx
                                 }
                             };
-                            pos("At", Some(arg_idx))
+                            self.ecx.expr_usize(sp, arg_idx)
                         }
 
                         // should never be the case, because names are already
index eb192b27405e9ad91945174d75b8e37d3c478f8d..9f8b4e72a9cbf1c8d64f1b453ad068ca50596f96 100644 (file)
@@ -32,5 +32,4 @@ rustc_hir = { path = "../librustc_hir" }
 rustc_incremental = { path = "../librustc_incremental" }
 rustc_index = { path = "../librustc_index" }
 rustc_target = { path = "../librustc_target" }
-rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_session = { path = "../librustc_session" }
index 11f5d3007e6b4a8bf247d23422701f6aa967a749..4679f6501336cfcda6e2fff8185a57a4327a0712 100644 (file)
@@ -1103,7 +1103,11 @@ fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
     let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
     for &(symbol, level) in tcx.exported_symbols(LOCAL_CRATE).iter() {
         if level.is_below_threshold(export_threshold) {
-            symbols.push(symbol.symbol_name(tcx).to_string());
+            symbols.push(symbol_export::symbol_name_for_instance_in_crate(
+                tcx,
+                symbol,
+                LOCAL_CRATE,
+            ));
         }
     }
 
@@ -1124,12 +1128,7 @@ fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
                     continue;
                 }
 
-                // FIXME rust-lang/rust#64319, rust-lang/rust#64872:
-                // We want to block export of generics from dylibs,
-                // but we must fix rust-lang/rust#65890 before we can
-                // do that robustly.
-
-                symbols.push(symbol.symbol_name(tcx).to_string());
+                symbols.push(symbol_export::symbol_name_for_instance_in_crate(tcx, symbol, cnum));
             }
         }
     }
index a406b5f103b9d2f85f73109b6bb4cb33e7625699..bd44b4a38fd58c0c3572a23462214fab35b14610 100644 (file)
@@ -8,6 +8,7 @@
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::Instance;
 use rustc::ty::{SymbolName, TyCtxt};
+use rustc_codegen_utils::symbol_names;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
@@ -358,3 +359,32 @@ fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel
         SymbolExportLevel::Rust
     }
 }
+
+/// This is the symbol name of the given instance instantiated in a specific crate.
+pub fn symbol_name_for_instance_in_crate<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    symbol: ExportedSymbol<'tcx>,
+    instantiating_crate: CrateNum,
+) -> String {
+    // If this is something instantiated in the local crate then we might
+    // already have cached the name as a query result.
+    if instantiating_crate == LOCAL_CRATE {
+        return symbol.symbol_name_for_local_instance(tcx).to_string();
+    }
+
+    // This is something instantiated in an upstream crate, so we have to use
+    // the slower (because uncached) version of computing the symbol name.
+    match symbol {
+        ExportedSymbol::NonGeneric(def_id) => symbol_names::symbol_name_for_instance_in_crate(
+            tcx,
+            Instance::mono(tcx, def_id),
+            instantiating_crate,
+        ),
+        ExportedSymbol::Generic(def_id, substs) => symbol_names::symbol_name_for_instance_in_crate(
+            tcx,
+            Instance::new(def_id, substs),
+            instantiating_crate,
+        ),
+        ExportedSymbol::NoDefId(symbol_name) => symbol_name.to_string(),
+    }
+}
index 801bfdea70d6cbe5d6fb4eb154ee38169c46597b..049faff7c49ee69609e4d191968c84fbcf90d8da 100644 (file)
@@ -2,7 +2,7 @@
 use super::link::{self, get_linker, remove};
 use super::linker::LinkerInfo;
 use super::lto::{self, SerializedModule};
-use super::symbol_export::ExportedSymbols;
+use super::symbol_export::{symbol_name_for_instance_in_crate, ExportedSymbols};
 use crate::{
     CachedModuleCodegen, CodegenResults, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind,
     RLIB_BYTECODE_EXTENSION,
@@ -956,7 +956,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
             let symbols = tcx
                 .exported_symbols(cnum)
                 .iter()
-                .map(|&(s, lvl)| (s.symbol_name(tcx).to_string(), lvl))
+                .map(|&(s, lvl)| (symbol_name_for_instance_in_crate(tcx, s, cnum), lvl))
                 .collect();
             Arc::new(symbols)
         };
index e4531a77656a3bfb4d28fd69bfbdeed4bcd75ef1..28b61e0b36d64d08c3a4c33aa0825cac16e99a36 100644 (file)
@@ -13,8 +13,6 @@
 use crate::traits::BuilderMethods;
 use rustc_hir as hir;
 
-use rustc_error_codes::*;
-
 pub enum IntPredicate {
     IntEQ,
     IntNE,
index ee527ecb509b27417013717381c78cfc2c9b70e4..aba77231268e7e0226098c1bf65fede240edeeec 100644 (file)
@@ -4,7 +4,7 @@
 #![feature(box_syntax)]
 #![feature(core_intrinsics)]
 #![feature(libc)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(stmt_expr_attributes)]
 #![feature(try_blocks)]
 #![feature(in_band_lifetimes)]
index 574c06d9ceb419d6b1b8d892fc1ac22474dae324..8422c625d634ea11b680dda796f53e2db52d670c 100644 (file)
@@ -7,8 +7,6 @@
 use crate::traits::BuilderMethods;
 use crate::traits::*;
 
-use rustc_error_codes::*;
-
 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     pub fn codegen_statement(&mut self, mut bx: Bx, statement: &mir::Statement<'tcx>) -> Bx {
         debug!("codegen_statement(statement={:?})", statement);
index 450dcd3b6041c67f175c41777c75240771c36231..96a74f96fcf6054ba64b5dbb3721e30d949d1251 100644 (file)
@@ -91,8 +91,9 @@
 use rustc::mir::mono::{InstantiationMode, MonoItem};
 use rustc::session::config::SymbolManglingVersion;
 use rustc::ty::query::Providers;
+use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Instance, TyCtxt};
-use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_hir::Node;
 
 use rustc_span::symbol::Symbol;
 mod legacy;
 mod v0;
 
+/// This function computes the symbol name for the given `instance` and the
+/// given instantiating crate. That is, if you know that instance X is
+/// instantiated in crate Y, this is the symbol name this instance would have.
+pub fn symbol_name_for_instance_in_crate(
+    tcx: TyCtxt<'tcx>,
+    instance: Instance<'tcx>,
+    instantiating_crate: CrateNum,
+) -> String {
+    compute_symbol_name(tcx, instance, || instantiating_crate)
+}
+
 pub fn provide(providers: &mut Providers<'_>) {
-    *providers = Providers {
-        symbol_name: |tcx, instance| ty::SymbolName { name: symbol_name(tcx, instance) },
+    *providers = Providers { symbol_name: symbol_name_provider, ..*providers };
+}
 
-        ..*providers
-    };
+// The `symbol_name` query provides the symbol name for calling a given
+// instance from the local crate. In particular, it will also look up the
+// correct symbol name of instances from upstream crates.
+fn symbol_name_provider(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> ty::SymbolName {
+    let symbol_name = compute_symbol_name(tcx, instance, || {
+        // This closure determines the instantiating crate for instances that
+        // need an instantiating-crate-suffix for their symbol name, in order
+        // to differentiate between local copies.
+        //
+        // For generics we might find re-usable upstream instances. For anything
+        // else we rely on their being a local copy available.
+
+        if is_generic(instance.substs) {
+            let def_id = instance.def_id();
+
+            if !def_id.is_local() && tcx.sess.opts.share_generics() {
+                // If we are re-using a monomorphization from another crate,
+                // we have to compute the symbol hash accordingly.
+                let upstream_monomorphizations = tcx.upstream_monomorphizations_for(def_id);
+
+                upstream_monomorphizations
+                    .and_then(|monos| monos.get(&instance.substs).cloned())
+                    // If there is no instance available upstream, there'll be
+                    // one in the current crate.
+                    .unwrap_or(LOCAL_CRATE)
+            } else {
+                // For generic functions defined in the current crate, there
+                // can be no upstream instances. Also, if we don't share
+                // generics, we'll instantiate a local copy too.
+                LOCAL_CRATE
+            }
+        } else {
+            // For non-generic things that need to avoid naming conflicts, we
+            // always instantiate a copy in the local crate.
+            LOCAL_CRATE
+        }
+    });
+
+    ty::SymbolName { name: Symbol::intern(&symbol_name) }
 }
 
-fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol {
+/// Computes the symbol name for the given instance. This function will call
+/// `compute_instantiating_crate` if it needs to factor the instantiating crate
+/// into the symbol name.
+fn compute_symbol_name(
+    tcx: TyCtxt<'tcx>,
+    instance: Instance<'tcx>,
+    compute_instantiating_crate: impl FnOnce() -> CrateNum,
+) -> String {
     let def_id = instance.def_id();
     let substs = instance.substs;
 
@@ -121,11 +177,11 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol {
     if def_id.is_local() {
         if tcx.plugin_registrar_fn(LOCAL_CRATE) == Some(def_id) {
             let disambiguator = tcx.sess.local_crate_disambiguator();
-            return Symbol::intern(&tcx.sess.generate_plugin_registrar_symbol(disambiguator));
+            return tcx.sess.generate_plugin_registrar_symbol(disambiguator);
         }
         if tcx.proc_macro_decls_static(LOCAL_CRATE) == Some(def_id) {
             let disambiguator = tcx.sess.local_crate_disambiguator();
-            return Symbol::intern(&tcx.sess.generate_proc_macro_decls_symbol(disambiguator));
+            return tcx.sess.generate_proc_macro_decls_symbol(disambiguator);
         }
     }
 
@@ -162,29 +218,28 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol {
             || !tcx.wasm_import_module_map(def_id.krate).contains_key(&def_id)
         {
             if let Some(name) = attrs.link_name {
-                return name;
+                return name.to_string();
             }
-            return tcx.item_name(def_id);
+            return tcx.item_name(def_id).to_string();
         }
     }
 
     if let Some(name) = attrs.export_name {
         // Use provided name
-        return name;
+        return name.to_string();
     }
 
     if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) {
         // Don't mangle
-        return tcx.item_name(def_id);
+        return tcx.item_name(def_id).to_string();
     }
 
-    let is_generic = substs.non_erasable_generics().next().is_some();
     let avoid_cross_crate_conflicts =
         // If this is an instance of a generic function, we also hash in
         // the ID of the instantiating crate. This avoids symbol conflicts
         // in case the same instances is emitted in two crates of the same
         // project.
-        is_generic ||
+        is_generic(substs) ||
 
         // If we're dealing with an instance of a function that's inlined from
         // another crate but we're marking it as globally shared to our
@@ -197,25 +252,8 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol {
             _ => false,
         };
 
-    let instantiating_crate = if avoid_cross_crate_conflicts {
-        Some(if is_generic {
-            if !def_id.is_local() && tcx.sess.opts.share_generics() {
-                // If we are re-using a monomorphization from another crate,
-                // we have to compute the symbol hash accordingly.
-                let upstream_monomorphizations = tcx.upstream_monomorphizations_for(def_id);
-
-                upstream_monomorphizations
-                    .and_then(|monos| monos.get(&substs).cloned())
-                    .unwrap_or(LOCAL_CRATE)
-            } else {
-                LOCAL_CRATE
-            }
-        } else {
-            LOCAL_CRATE
-        })
-    } else {
-        None
-    };
+    let instantiating_crate =
+        if avoid_cross_crate_conflicts { Some(compute_instantiating_crate()) } else { None };
 
     // Pick the crate responsible for the symbol mangling version, which has to:
     // 1. be stable for each instance, whether it's being defined or imported
@@ -232,10 +270,12 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol {
         tcx.symbol_mangling_version(mangling_version_crate)
     };
 
-    let mangled = match mangling_version {
+    match mangling_version {
         SymbolManglingVersion::Legacy => legacy::mangle(tcx, instance, instantiating_crate),
         SymbolManglingVersion::V0 => v0::mangle(tcx, instance, instantiating_crate),
-    };
+    }
+}
 
-    Symbol::intern(&mangled)
+fn is_generic(substs: SubstsRef<'_>) -> bool {
+    substs.non_erasable_generics().next().is_some()
 }
index 004db0a79a8808fbfc6e2681a828752cdd51acf9..44cef727f034be23d7884972cbda659bd5a8bcec 100644 (file)
@@ -136,9 +136,11 @@ struct EventFilter: u32 {
     }
 }
 
+// keep this in sync with the `-Z self-profile-events` help message in librustc_session/options.rs
 const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[
     ("none", EventFilter::NONE),
     ("all", EventFilter::ALL),
+    ("default", EventFilter::DEFAULT),
     ("generic-activity", EventFilter::GENERIC_ACTIVITIES),
     ("query-provider", EventFilter::QUERY_PROVIDERS),
     ("query-cache-hit", EventFilter::QUERY_CACHE_HITS),
index 8b85d97a1d4fe235390bbae7dcb88fab62ca9023..ee3f88ff1675fa6039077b6ad8c5e258a38ec10a 100644 (file)
@@ -137,6 +137,20 @@ pub fn intern<Q>(&self, value: Q, make: impl FnOnce(Q) -> K) -> K
     }
 }
 
+pub trait IntoPointer {
+    /// Returns a pointer which outlives `self`.
+    fn into_pointer(&self) -> *const ();
+}
+
+impl<K: Eq + Hash + Copy + IntoPointer> ShardedHashMap<K, ()> {
+    pub fn contains_pointer_to<T: Hash + IntoPointer>(&self, value: &T) -> bool {
+        let hash = make_hash(&value);
+        let shard = self.get_shard_by_hash(hash).lock();
+        let value = value.into_pointer();
+        shard.raw_entry().from_hash(hash, |entry| entry.into_pointer() == value).is_some()
+    }
+}
+
 #[inline]
 fn make_hash<K: Hash + ?Sized>(val: &K) -> u64 {
     let mut state = FxHasher::default();
index 272147e28a4196c7254574803822e591415f5244..180ccb15977dd5126b2b9617f75efbedb166fe1f 100644 (file)
 E0743: include_str!("./error_codes/E0743.md"),
 E0744: include_str!("./error_codes/E0744.md"),
 E0745: include_str!("./error_codes/E0745.md"),
+E0746: include_str!("./error_codes/E0746.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
index 3606521020a11f1f3e4c8b96aa30c2b2ca9adc55..b8c313d412eba9ee91b67eee02994082187ba006 100644 (file)
@@ -1,4 +1,5 @@
-Your method's lifetime parameters do not match the trait declaration.
+The lifetime parameters of the method do not match the trait declaration.
+
 Erroneous code example:
 
 ```compile_fail,E0195
@@ -16,7 +17,7 @@ impl Trait for Foo {
 }
 ```
 
-The lifetime constraint `'b` for bar() implementation does not match the
+The lifetime constraint `'b` for `bar()` implementation does not match the
 trait declaration. Ensure lifetime declarations match exactly in both trait
 declaration and implementation. Example:
 
index 0d91157e572ccf3d51499c63b2f73f45162982e7..c142b8f3664c5e83a46c396d7191681c1298f79f 100644 (file)
@@ -1,13 +1,20 @@
+An inherent implementation was marked unsafe.
+
+Erroneous code example:
+
+```compile_fail,E0197
+struct Foo;
+
+unsafe impl Foo { } // error!
+```
+
 Inherent implementations (one that do not implement a trait but provide
 methods associated with a type) are always safe because they are not
 implementing an unsafe trait. Removing the `unsafe` keyword from the inherent
 implementation will resolve this error.
 
-```compile_fail,E0197
+```
 struct Foo;
 
-// this will cause this error
-unsafe impl Foo { }
-// converting it to this will fix it
-impl Foo { }
+impl Foo { } // ok!
 ```
index 6504d60dbd1d53d1abcb95433e9913f0941410a1..687214a205096ff62c0c5454062938714c309ea7 100644 (file)
@@ -1,17 +1,18 @@
-A negative implementation is one that excludes a type from implementing a
-particular trait. Not being able to use a trait is always a safe operation,
-so negative implementations are always safe and never need to be marked as
-unsafe.
+A negative implementation was marked as unsafe.
 
-```compile_fail
-#![feature(optin_builtin_traits)]
+Erroneous code example:
 
+```compile_fail
 struct Foo;
 
-// unsafe is unnecessary
-unsafe impl !Clone for Foo { }
+unsafe impl !Clone for Foo { } // error!
 ```
 
+A negative implementation is one that excludes a type from implementing a
+particular trait. Not being able to use a trait is always a safe operation,
+so negative implementations are always safe and never need to be marked as
+unsafe.
+
 This will compile:
 
 ```ignore (ignore auto_trait future compatibility warning)
index d0c12dc6f17550e4cbbecf4302c27af57e2e2382..88130e8e5e596540c2c10b02bb8ff41baca5cf27 100644 (file)
@@ -1,14 +1,23 @@
+A trait implementation was marked as unsafe while the trait is safe.
+
+Erroneous code example:
+
+```compile_fail,E0199
+struct Foo;
+
+trait Bar { }
+
+unsafe impl Bar for Foo { } // error!
+```
+
 Safe traits should not have unsafe implementations, therefore marking an
 implementation for a safe trait unsafe will cause a compiler error. Removing
-the unsafe marker on the trait noted in the error will resolve this problem.
+the unsafe marker on the trait noted in the error will resolve this problem:
 
-```compile_fail,E0199
+```
 struct Foo;
 
 trait Bar { }
 
-// this won't compile because Bar is safe
-unsafe impl Bar for Foo { }
-// this will compile
-impl Bar for Foo { }
+impl Bar for Foo { } // ok!
 ```
index 865e91430ac44e7462ce9430df04c3c043ca9217..7245bb59ce5ffa5406f42f82e752ff0b89303643 100644 (file)
@@ -1,14 +1,23 @@
+An unsafe trait was implemented without an unsafe implementation.
+
+Erroneous code example:
+
+```compile_fail,E0200
+struct Foo;
+
+unsafe trait Bar { }
+
+impl Bar for Foo { } // error!
+```
+
 Unsafe traits must have unsafe implementations. This error occurs when an
 implementation for an unsafe trait isn't marked as unsafe. This may be resolved
 by marking the unsafe implementation as unsafe.
 
-```compile_fail,E0200
+```
 struct Foo;
 
 unsafe trait Bar { }
 
-// this won't compile because Bar is unsafe and impl isn't unsafe
-impl Bar for Foo { }
-// this will compile
-unsafe impl Bar for Foo { }
+unsafe impl Bar for Foo { } // ok!
 ```
index bdbf02f0033ab9dc111aaaf0d441a52265999908..0e1a7b7b7deb1b4c79dff64aefda924b5d3ff34e 100644 (file)
@@ -1,7 +1,7 @@
-It is an error to define two associated items (like methods, associated types,
-associated functions, etc.) with the same identifier.
+Two associated items (like methods, associated types, associated functions,
+etc.) were defined with the same identifier.
 
-For example:
+Erroneous code example:
 
 ```compile_fail,E0201
 struct Foo(u8);
index 315690111359fde1b9a6859cc3f88a55f6fefb3e..96e44758be4fd7d2812b6915ea61e9c167a7d8f2 100644 (file)
@@ -1,21 +1,24 @@
-An attempt to implement the `Copy` trait for a struct failed because one of the
-fields does not implement `Copy`. To fix this, you must implement `Copy` for the
-mentioned field. Note that this may not be possible, as in the example of
+The `Copy` trait was implemented on a type which contains a field that doesn't
+implement the `Copy` trait.
+
+Erroneous code example:
 
 ```compile_fail,E0204
 struct Foo {
-    foo : Vec<u32>,
+    foo: Vec<u32>,
 }
 
-impl Copy for Foo { }
+impl Copy for Foo { } // error!
 ```
 
-This fails because `Vec<T>` does not implement `Copy` for any `T`.
+The `Copy` trait is implemented by default only on primitive types. If your
+type only contains primitive types, you'll be able to implement `Copy` on it.
+Otherwise, it won't be possible.
 
 Here's another example that will fail:
 
 ```compile_fail,E0204
-#[derive(Copy)]
+#[derive(Copy)] // error!
 struct Foo<'a> {
     ty: &'a mut bool,
 }
index 4bff39dc770e0ec4c30ec45b7ff4d1703e2c3f18..97ea31269388142df9853a62c3aa8b756aa86e1c 100644 (file)
@@ -17,8 +17,6 @@ Ensure that the pattern is consistent with the size of the matched
 array. Additional elements can be matched with `..`:
 
 ```
-#![feature(slice_patterns)]
-
 let r = &[1, 2, 3, 4];
 match r {
     &[a, b, ..] => { // ok!
index 4b6ea2469919cd61b28b650e5e1e6c2782e66cb3..54c2c4d4e9d0f765eb1d1450e1f7cc381ed9a569 100644 (file)
@@ -4,8 +4,6 @@ matched array.
 Example of erroneous code:
 
 ```compile_fail,E0528
-#![feature(slice_patterns)]
-
 let r = &[1, 2];
 match r {
     &[a, b, c, rest @ ..] => { // error: pattern requires at least 3
@@ -19,8 +17,6 @@ Ensure that the matched array has at least as many elements as the pattern
 requires. You can match an arbitrary number of remaining elements with `..`:
 
 ```
-#![feature(slice_patterns)]
-
 let r = &[1, 2, 3, 4, 5];
 match r {
     &[a, b, c, rest @ ..] => { // ok!
index 803a25148651c6753c860be20694c4f5eb80a2a0..bf1f72be3258926bd7f107935517027cbda26f8a 100644 (file)
@@ -18,8 +18,6 @@ Ensure that the pattern is consistent with the size of the matched
 array. Additional elements can be matched with `..`:
 
 ```
-#![feature(slice_patterns)]
-
 let r = &[1, 2, 3, 4];
 match r {
     &[a, b, ..] => { // ok!
diff --git a/src/librustc_error_codes/error_codes/E0746.md b/src/librustc_error_codes/error_codes/E0746.md
new file mode 100644 (file)
index 0000000..16b2722
--- /dev/null
@@ -0,0 +1,138 @@
+Return types cannot be `dyn Trait`s as they must be `Sized`.
+
+Erroneous code example:
+
+```compile_fail,E0277
+# // FIXME: after E0746 is in beta, change the above
+trait T {
+    fn bar(&self);
+}
+struct S(usize);
+impl T for S {
+    fn bar(&self) {}
+}
+
+// Having the trait `T` as return type is invalid because
+// unboxed trait objects do not have a statically known size:
+fn foo() -> dyn T {
+    S(42)
+}
+```
+
+To avoid the error there are a couple of options.
+
+If there is a single type involved, you can use [`impl Trait`]:
+
+```
+# trait T {
+#     fn bar(&self);
+# }
+# struct S(usize);
+# impl T for S {
+#     fn bar(&self) {}
+# }
+// The compiler will select `S(usize)` as the materialized return type of this
+// function, but callers will only know that the return type implements `T`.
+fn foo() -> impl T {
+    S(42)
+}
+```
+
+If there are multiple types involved, the only way you care to interact with
+them is through the trait's interface, and having to rely on dynamic dispatch
+is acceptable, then you can use [trait objects] with `Box`, or other container
+types like `Rc` or `Arc`:
+
+```
+# trait T {
+#     fn bar(&self);
+# }
+# struct S(usize);
+# impl T for S {
+#     fn bar(&self) {}
+# }
+struct O(&'static str);
+impl T for O {
+    fn bar(&self) {}
+}
+
+// This now returns a "trait object" and callers are only be able to access
+// associated items from `T`.
+fn foo(x: bool) -> Box<dyn T> {
+    if x {
+        Box::new(S(42))
+    } else {
+        Box::new(O("val"))
+    }
+}
+```
+
+Finally, if you wish to still be able to access the original type, you can
+create a new `enum` with a variant for each type:
+
+```
+# trait T {
+#     fn bar(&self);
+# }
+# struct S(usize);
+# impl T for S {
+#     fn bar(&self) {}
+# }
+# struct O(&'static str);
+# impl T for O {
+#     fn bar(&self) {}
+# }
+enum E {
+    S(S),
+    O(O),
+}
+
+// The caller can access the original types directly, but it needs to match on
+// the returned `enum E`.
+fn foo(x: bool) -> E {
+    if x {
+        E::S(S(42))
+    } else {
+        E::O(O("val"))
+    }
+}
+```
+
+You can even implement the `trait` on the returned `enum` so the callers
+*don't* have to match on the returned value to invoke the associated items:
+
+```
+# trait T {
+#     fn bar(&self);
+# }
+# struct S(usize);
+# impl T for S {
+#     fn bar(&self) {}
+# }
+# struct O(&'static str);
+# impl T for O {
+#     fn bar(&self) {}
+# }
+# enum E {
+#     S(S),
+#     O(O),
+# }
+impl T for E {
+    fn bar(&self) {
+        match self {
+            E::S(s) => s.bar(),
+            E::O(o) => o.bar(),
+        }
+    }
+}
+```
+
+If you decide to use trait objects, be aware that these rely on
+[dynamic dispatch], which has performance implications, as the compiler needs
+to emit code that will figure out which method to call *at runtime* instead of
+during compilation. Using trait objects we are trading flexibility for
+performance.
+
+[`impl Trait`]: https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits
+[trait objects]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types
+[dynamic dispatch]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#trait-objects-perform-dynamic-dispatch
index 14210fd69ad51b81a7432cdd64118723fb4f9665..f051fdd11b807584ec8bb5742444c1c2e3c7432b 100644 (file)
@@ -6,16 +6,8 @@ macro_rules! register_diagnostics {
         pub static DIAGNOSTICS: &[(&str, &str)] = &[
             $( (stringify!($ecode), $message), )*
         ];
-
-        $(
-            pub const $ecode: () = ();
-        )*
-        $(
-            pub const $code: () = ();
-        )*
     )
 }
 
 mod error_codes;
-
-pub use error_codes::*;
+pub use error_codes::DIAGNOSTICS;
index 7413cef6d32d44d3608f7fd0678ba6be7d0f3e9b..009ab6ac5b12f90ea37822a2ac6d7e05a546799b 100644 (file)
@@ -196,7 +196,7 @@ fn emit_messages_default(
     ) {
         let converter = DiagnosticConverter {
             source_map: self.source_map.clone(),
-            level: level.clone(),
+            level: *level,
             message,
             code: code.clone(),
             msp: msp.clone(),
index 73f66d550374050c4be7cc0eef6a3eceacfa1549..3c217c1d64373556cdd9605e89605d22d836cede 100644 (file)
@@ -399,8 +399,5 @@ macro_rules! struct_span_err {
 
 #[macro_export]
 macro_rules! error_code {
-    ($code:ident) => {{
-        let _ = $code;
-        $crate::DiagnosticId::Error(stringify!($code).to_owned())
-    }};
+    ($code:ident) => {{ $crate::DiagnosticId::Error(stringify!($code).to_owned()) }};
 }
index 526b4e2971befdf1f4fa6caa2dd68f9542ff5a04..b0e0cb611afaffb60711b97e46c21e669ff2d4dc 100644 (file)
@@ -1476,6 +1476,15 @@ fn emit_suggestion_default(
             None => return Ok(()),
         };
 
+        // Render the replacements for each suggestion
+        let suggestions = suggestion.splice_lines(&**sm);
+
+        if suggestions.is_empty() {
+            // Suggestions coming from macros can have malformed spans. This is a heavy handed
+            // approach to avoid ICEs by ignoring the suggestion outright.
+            return Ok(());
+        }
+
         let mut buffer = StyledBuffer::new();
 
         // Render the suggestion message
@@ -1492,9 +1501,6 @@ fn emit_suggestion_default(
             Some(Style::HeaderMsg),
         );
 
-        // Render the replacements for each suggestion
-        let suggestions = suggestion.splice_lines(&**sm);
-
         let mut row_num = 2;
         let mut notice_capitalization = false;
         for (complete, parts, only_capitalization) in suggestions.iter().take(MAX_SUGGESTIONS) {
@@ -1505,7 +1511,9 @@ fn emit_suggestion_default(
             let show_underline = !(parts.len() == 1 && parts[0].snippet.trim() == complete.trim())
                 && complete.lines().count() == 1;
 
-            let lines = sm.span_to_lines(parts[0].span).unwrap();
+            let lines = sm
+                .span_to_lines(parts[0].span)
+                .expect("span_to_lines failed when emitting suggestion");
 
             assert!(!lines.lines.is_empty());
 
index e24e8719133a987574b2d9def7200801d42a9b93..827e9b831f32d711978c1b0c960fc90aabc4ab49 100644 (file)
@@ -10,6 +10,7 @@
 
 pub use emitter::ColorConfig;
 
+use log::debug;
 use Level::*;
 
 use emitter::{is_case_difference, Emitter, EmitterWriter};
@@ -174,6 +175,15 @@ fn push_trailing(
 
         self.substitutions
             .iter()
+            .filter(|subst| {
+                // Suggestions coming from macros can have malformed spans. This is a heavy
+                // handed approach to avoid ICEs by ignoring the suggestion outright.
+                let invalid = subst.parts.iter().any(|item| cm.is_valid_span(item.span).is_err());
+                if invalid {
+                    debug!("splice_lines: suggestion contains an invalid span: {:?}", subst);
+                }
+                !invalid
+            })
             .cloned()
             .map(|mut substitution| {
                 // Assumption: all spans are in the same file, and all spans
index d880fc84b3819c6a1c3732688bb474fb1db9ace6..007cee4c7642443c1e74220c0fb784479e825698 100644 (file)
@@ -257,6 +257,8 @@ macro_rules! declare_features {
     /// Allows relaxing the coherence rules such that
     /// `impl<T> ForeignTrait<LocalType> for ForeignType<T>` is permitted.
     (accepted, re_rebalance_coherence, "1.41.0", Some(55437), None),
+    /// Allows using subslice patterns, `[a, .., b]` and `[a, xs @ .., b]`.
+    (accepted, slice_patterns, "1.42.0", Some(62254), None),
 
     // -------------------------------------------------------------------------
     // feature-group-end: accepted features
index 4c8c47a5671134b3cf270988e91fc22bc1a81215..6af9b6c0872780160e71c63332982c9344a433ed 100644 (file)
@@ -262,9 +262,6 @@ pub fn set(&self, features: &mut Features, span: Span) {
     /// Allows using non lexical lifetimes (RFC 2094).
     (active, nll, "1.0.0", Some(43234), None),
 
-    /// Allows using slice patterns.
-    (active, slice_patterns, "1.0.0", Some(62254), None),
-
     /// Allows the definition of `const` functions with some advanced features.
     (active, const_fn, "1.2.0", Some(57563), None),
 
index 550e3654d0800965d890d96ea4850048272c3c9d..1fef871b5140e41ad2b24b94b3cec134c0ef493c 100644 (file)
@@ -377,6 +377,13 @@ pub enum GenericBound<'hir> {
 }
 
 impl GenericBound<'_> {
+    pub fn trait_def_id(&self) -> Option<DefId> {
+        match self {
+            GenericBound::Trait(data, _) => Some(data.trait_ref.trait_def_id()),
+            _ => None,
+        }
+    }
+
     pub fn span(&self) -> Span {
         match self {
             &GenericBound::Trait(ref t, ..) => t.span,
@@ -2429,15 +2436,18 @@ pub enum ItemKind<'hir> {
     TraitAlias(Generics<'hir>, GenericBounds<'hir>),
 
     /// An implementation, e.g., `impl<A> Trait for Foo { .. }`.
-    Impl(
-        Unsafety,
-        ImplPolarity,
-        Defaultness,
-        Generics<'hir>,
-        Option<TraitRef<'hir>>, // (optional) trait this impl implements
-        &'hir Ty<'hir>,         // self
-        &'hir [ImplItemRef<'hir>],
-    ),
+    Impl {
+        unsafety: Unsafety,
+        polarity: ImplPolarity,
+        defaultness: Defaultness,
+        generics: Generics<'hir>,
+
+        /// The trait being implemented, if any.
+        of_trait: Option<TraitRef<'hir>>,
+
+        self_ty: &'hir Ty<'hir>,
+        items: &'hir [ImplItemRef<'hir>],
+    },
 }
 
 impl ItemKind<'_> {
@@ -2458,7 +2468,7 @@ pub fn descriptive_variant(&self) -> &str {
             ItemKind::Union(..) => "union",
             ItemKind::Trait(..) => "trait",
             ItemKind::TraitAlias(..) => "trait alias",
-            ItemKind::Impl(..) => "impl",
+            ItemKind::Impl { .. } => "impl",
         }
     }
 
@@ -2471,7 +2481,7 @@ pub fn generics(&self) -> Option<&Generics<'_>> {
             | ItemKind::Struct(_, ref generics)
             | ItemKind::Union(_, ref generics)
             | ItemKind::Trait(_, _, ref generics, _, _)
-            | ItemKind::Impl(_, _, _, ref generics, _, _, _) => generics,
+            | ItemKind::Impl { ref generics, .. } => generics,
             _ => return None,
         })
     }
index 3dbc5253a9abf5ce3fc6b68fb05ce37fce256d50..1a73e41db9da54c71d92d2a72d22239ac9c562bb 100644 (file)
@@ -566,12 +566,20 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
             // `visit_enum_def()` takes care of visiting the `Item`'s `HirId`.
             visitor.visit_enum_def(enum_definition, generics, item.hir_id, item.span)
         }
-        ItemKind::Impl(.., ref generics, ref opt_trait_reference, ref typ, impl_item_refs) => {
+        ItemKind::Impl {
+            unsafety: _,
+            defaultness: _,
+            polarity: _,
+            ref generics,
+            ref of_trait,
+            ref self_ty,
+            items,
+        } => {
             visitor.visit_id(item.hir_id);
             visitor.visit_generics(generics);
-            walk_list!(visitor, visit_trait_ref, opt_trait_reference);
-            visitor.visit_ty(typ);
-            walk_list!(visitor, visit_impl_item_ref, impl_item_refs);
+            walk_list!(visitor, visit_trait_ref, of_trait);
+            visitor.visit_ty(self_ty);
+            walk_list!(visitor, visit_impl_item_ref, items);
         }
         ItemKind::Struct(ref struct_definition, ref generics)
         | ItemKind::Union(ref struct_definition, ref generics) => {
index 759f423070aa0b35019e0840b47403f8266f8327..6c7d419395317b950a713df4949ed62c17aa3d2f 100644 (file)
@@ -627,15 +627,15 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
                 self.head(visibility_qualified(&item.vis, "union"));
                 self.print_struct(struct_def, generics, item.ident.name, item.span, true);
             }
-            hir::ItemKind::Impl(
+            hir::ItemKind::Impl {
                 unsafety,
                 polarity,
                 defaultness,
                 ref generics,
-                ref opt_trait,
-                ref ty,
-                impl_items,
-            ) => {
+                ref of_trait,
+                ref self_ty,
+                items,
+            } => {
                 self.head("");
                 self.print_visibility(&item.vis);
                 self.print_defaultness(defaultness);
@@ -651,19 +651,19 @@ pub fn print_item(&mut self, item: &hir::Item<'_>) {
                     self.s.word("!");
                 }
 
-                if let Some(ref t) = opt_trait {
+                if let Some(ref t) = of_trait {
                     self.print_trait_ref(t);
                     self.s.space();
                     self.word_space("for");
                 }
 
-                self.print_type(&ty);
+                self.print_type(&self_ty);
                 self.print_where_clause(&generics.where_clause);
 
                 self.s.space();
                 self.bopen();
                 self.print_inner_attributes(&item.attrs);
-                for impl_item in impl_items {
+                for impl_item in items {
                     self.ann.nested(self, Nested::ImplItem(impl_item.id));
                 }
                 self.bclose(item.span);
index ddfed53fa33491895e08504ae7727129af63ad74..c5e74868bda4a705352197c4a08eb0da0674ca27 100644 (file)
@@ -315,7 +315,7 @@ fn auto_labels(&mut self, item_id: hir::HirId, attr: &Attribute) -> (&'static st
                     //HirItem::Trait(..) => ("ItemTrait", LABELS_TRAIT),
 
                     // An implementation, eg `impl<A> Trait for Foo { .. }`
-                    HirItem::Impl(..) => ("ItemKind::Impl", LABELS_IMPL),
+                    HirItem::Impl { .. } => ("ItemKind::Impl", LABELS_IMPL),
 
                     _ => self.tcx.sess.span_fatal(
                         attr.span,
index 588e639f28946f7ef3134318db1c55a0a51659c4..87f39dedd02734331310758d29aab7753f81d091 100644 (file)
@@ -236,7 +236,7 @@ fn encode_work_product_index(
     let serialized_products: Vec<_> = work_products
         .iter()
         .map(|(id, work_product)| SerializedWorkProduct {
-            id: id.clone(),
+            id: *id,
             work_product: work_product.clone(),
         })
         .collect();
index c4444fbaa2fc761390e2b1b99be5d6cf84fa33ec..d62c7539d5f2189ac7c0663c7dc4e4231219bc29 100644 (file)
@@ -15,7 +15,7 @@
 use rustc::session::Session;
 use rustc::traits;
 use rustc::ty::steal::Steal;
-use rustc::ty::{self, AllArenas, GlobalCtxt, ResolverOutputs, TyCtxt};
+use rustc::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt};
 use rustc::util::common::ErrorReported;
 use rustc_builtin_macros;
 use rustc_codegen_ssa::back::link::emit_metadata;
@@ -715,7 +715,6 @@ pub fn create_global_ctxt<'tcx>(
     outputs: OutputFilenames,
     crate_name: &str,
     global_ctxt: &'tcx Once<GlobalCtxt<'tcx>>,
-    all_arenas: &'tcx AllArenas,
     arena: &'tcx WorkerLocal<Arena<'tcx>>,
 ) -> QueryContext<'tcx> {
     let sess = &compiler.session();
@@ -746,7 +745,6 @@ pub fn create_global_ctxt<'tcx>(
                 lint_store,
                 local_providers,
                 extern_providers,
-                &all_arenas,
                 arena,
                 resolver_outputs,
                 hir_map,
index bd9717d3f3d0253bb6b158244821460b6cfd371b..0af9b17a2995b2f5026b2d1cefc2759ddb93d316 100644 (file)
@@ -7,7 +7,7 @@
 use rustc::session::config::{OutputFilenames, OutputType};
 use rustc::session::Session;
 use rustc::ty::steal::Steal;
-use rustc::ty::{AllArenas, GlobalCtxt, ResolverOutputs};
+use rustc::ty::{GlobalCtxt, ResolverOutputs};
 use rustc::util::common::ErrorReported;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_data_structures::sync::{Lrc, Once, WorkerLocal};
@@ -66,7 +66,6 @@ pub struct Queries<'tcx> {
     compiler: &'tcx Compiler,
     gcx: Once<GlobalCtxt<'tcx>>,
 
-    all_arenas: AllArenas,
     arena: WorkerLocal<Arena<'tcx>>,
 
     dep_graph_future: Query<Option<DepGraphFuture>>,
@@ -86,7 +85,6 @@ pub fn new(compiler: &'tcx Compiler) -> Queries<'tcx> {
         Queries {
             compiler,
             gcx: Once::new(),
-            all_arenas: AllArenas::new(),
             arena: WorkerLocal::new(|_| Arena::default()),
             dep_graph_future: Default::default(),
             parse: Default::default(),
@@ -265,7 +263,6 @@ pub fn global_ctxt(&'tcx self) -> Result<&Query<QueryContext<'tcx>>> {
                 outputs,
                 &crate_name,
                 &self.gcx,
-                &self.all_arenas,
                 &self.arena,
             ))
         })
index abf9f96e6475b26e464dddf33271f8696f9e448c..7e23e70577975cdb9e3e90ee0625fad8ac2387ed 100644 (file)
@@ -13,7 +13,6 @@ log = "0.4"
 unicode-security = "0.0.2"
 rustc = { path = "../librustc" }
 rustc_errors = { path = "../librustc_errors" }
-rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_target = { path = "../librustc_target" }
 syntax = { path = "../libsyntax" }
index 6314c2b99539aae399deeb54b6bcb05b9b009096..c8d3d5f9c83d8d18ac7f44fcbef9c9c29c57318e 100644 (file)
@@ -251,7 +251,7 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
                 self.report_unsafe(cx, it.span, "declaration of an `unsafe` trait")
             }
 
-            ast::ItemKind::Impl(ast::Unsafety::Unsafe, ..) => {
+            ast::ItemKind::Impl { unsafety: ast::Unsafety::Unsafe, .. } => {
                 self.report_unsafe(cx, it.span, "implementation of an `unsafe` trait")
             }
 
@@ -431,7 +431,7 @@ fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) {
                 "a trait"
             }
             hir::ItemKind::TyAlias(..) => "a type alias",
-            hir::ItemKind::Impl(.., Some(ref trait_ref), _, impl_item_refs) => {
+            hir::ItemKind::Impl { of_trait: Some(ref trait_ref), items, .. } => {
                 // If the trait is private, add the impl items to `private_traits` so they don't get
                 // reported for missing docs.
                 let real_trait = trait_ref.path.res.def_id();
@@ -439,7 +439,7 @@ fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item<'_>) {
                     match cx.tcx.hir().find(hir_id) {
                         Some(Node::Item(item)) => {
                             if let hir::VisibilityKind::Inherited = item.vis.node {
-                                for impl_item_ref in impl_item_refs {
+                                for impl_item_ref in items {
                                     self.private_traits.insert(impl_item_ref.id.hir_id);
                                 }
                             }
index 2b514c301f2a3890a6765c845e7f5950d104313a..3b8cce5635d0715f17809238daa522e0e0f3fddb 100644 (file)
@@ -26,7 +26,6 @@
 use rustc::ty::{self, print::Printer, subst::GenericArg, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync;
-use rustc_error_codes::*;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, DefId};
@@ -245,7 +244,7 @@ pub fn register_group(
 
     pub fn register_renamed(&mut self, old_name: &str, new_name: &str) {
         let target = match self.by_name.get(new_name) {
-            Some(&Id(lint_id)) => lint_id.clone(),
+            Some(&Id(lint_id)) => lint_id,
             _ => bug!("invalid lint renaming of {} to {}", old_name, new_name),
         };
         self.by_name.insert(old_name.to_string(), Renamed(new_name.to_string(), target));
index 5a5aedc2e9715b33bff96069e1868ab2b43fa0d7..91aeccbb5e334457e44b6ce9e0ed4cfabdc79e52 100644 (file)
@@ -221,7 +221,7 @@ fn gen_args(segment: &PathSegment<'_>) -> String {
 
 impl EarlyLintPass for LintPassImpl {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
-        if let ItemKind::Impl(_, _, _, _, Some(lint_pass), _, _) = &item.kind {
+        if let ItemKind::Impl { of_trait: Some(lint_pass), .. } = &item.kind {
             if let Some(last) = lint_pass.path.segments.last() {
                 if last.ident.name == sym::LintPass {
                     let expn_data = lint_pass.path.span.ctxt().outer_expn_data();
index bbc3e57f5dd01a38683395b1906e4b88a769c5ba..d5bbdc53160f6f43d4b6079e73a0a03b2d49208b 100644 (file)
@@ -6,7 +6,6 @@
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_error_codes::*;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
index a2b7884241ff7b9bbc4600aa68b64a47043b3be1..394da4a5bb0c151942a897913b39d92468a8c77d 100644 (file)
@@ -350,7 +350,20 @@ fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::TraitItem<'
     }
 
     fn check_pat(&mut self, cx: &LateContext<'_, '_>, p: &hir::Pat<'_>) {
-        if let &PatKind::Binding(_, _, ident, _) = &p.kind {
+        if let &PatKind::Binding(_, hid, ident, _) = &p.kind {
+            if let hir::Node::Pat(parent_pat) = cx.tcx.hir().get(cx.tcx.hir().get_parent_node(hid))
+            {
+                if let PatKind::Struct(_, field_pats, _) = &parent_pat.kind {
+                    for field in field_pats.iter() {
+                        if field.ident != ident {
+                            // Only check if a new name has been introduced, to avoid warning
+                            // on both the struct definition and this pattern.
+                            self.check_snake_case(cx, "variable", &ident);
+                        }
+                    }
+                    return;
+                }
+            }
             self.check_snake_case(cx, "variable", &ident);
         }
     }
index 0a0bcb190bea720b1b90c7746d371915ce3f4967..6da584733aea0345e8d44b71fc117a39f6e03be6 100644 (file)
@@ -26,7 +26,6 @@ syntax = { path = "../libsyntax" }
 rustc_expand = { path = "../librustc_expand" }
 rustc_parse = { path = "../librustc_parse" }
 rustc_span = { path = "../librustc_span" }
-rustc_error_codes = { path = "../librustc_error_codes" }
 
 [target.'cfg(windows)'.dependencies]
 winapi = { version = "0.3", features = ["errhandlingapi", "libloaderapi"] }
index 181f872154c5107e55776b767d5c7a358bf23713..351e72d4678f2bed27deb2fd0a9f138012e72a5a 100644 (file)
@@ -12,7 +12,6 @@
 use rustc::ty::TyCtxt;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::Lrc;
-use rustc_error_codes::*;
 use rustc_errors::struct_span_err;
 use rustc_expand::base::SyntaxExtension;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
index 0fec4bff1633d095752a0544a435971344c58b8b..cf925ab91875f0fcf0e572ecbd22599d742f24aa 100644 (file)
@@ -10,7 +10,7 @@
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_quote)]
 #![feature(rustc_private)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(specialization)]
 #![feature(stmt_expr_attributes)]
 #![recursion_limit = "256"]
index 4745ad02a3aa4adcb10b0db6f3a8d7362e815a93..578216454f9dc487c11430a541df228850926301 100644 (file)
 
 use log::{debug, info, warn};
 
-use rustc_error_codes::*;
-
 #[derive(Clone)]
 struct CrateMismatch {
     path: PathBuf,
index 9426d5e26f5e545bdce78adecafdf0d8e67156f8..bbf6973be51a7690f5a5784767fa91a85777a652 100644 (file)
@@ -3,7 +3,6 @@
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_error_codes::*;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
index eb3dcfa72278ec7bee30db726fb0b8826c38930b..6280121f655660fab155a744edb8a5b1a6144446 100644 (file)
@@ -840,7 +840,7 @@ fn get_type(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
 
     fn get_stability(&self, id: DefIndex) -> Option<attr::Stability> {
         match self.is_proc_macro(id) {
-            true => self.root.proc_macro_stability.clone(),
+            true => self.root.proc_macro_stability,
             false => self.root.per_def.stability.get(self, id).map(|stab| stab.decode(self)),
         }
     }
index 7f8791d0c34dc467811e0045782d139c0b3f1bdd..9d2bea28c8c2ebf88da381576bb93becd9c8ad9c 100644 (file)
@@ -504,7 +504,7 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
             },
             proc_macro_data,
             proc_macro_stability: if is_proc_macro {
-                tcx.lookup_stability(DefId::local(CRATE_DEF_INDEX)).map(|stab| stab.clone())
+                tcx.lookup_stability(DefId::local(CRATE_DEF_INDEX)).map(|stab| *stab)
             } else {
                 None
             },
@@ -1073,7 +1073,7 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
                     ctor: None,
                 }), adt_def.repr)
             }
-            hir::ItemKind::Impl(_, _, defaultness, ..) => {
+            hir::ItemKind::Impl { defaultness, .. } => {
                 let trait_ref = self.tcx.impl_trait_ref(def_id);
                 let polarity = self.tcx.impl_polarity(def_id);
                 let parent = if let Some(trait_ref) = trait_ref {
@@ -1149,7 +1149,7 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
                     })
                 )
             }
-            hir::ItemKind::Impl(..) | hir::ItemKind::Trait(..) => {
+            hir::ItemKind::Impl { .. } | hir::ItemKind::Trait(..) => {
                 let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id);
                 record!(self.per_def.children[def_id] <-
                     associated_item_def_ids.iter().map(|&def_id| {
@@ -1172,13 +1172,13 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
             | hir::ItemKind::Enum(..)
             | hir::ItemKind::Struct(..)
             | hir::ItemKind::Union(..)
-            | hir::ItemKind::Impl(..) => self.encode_item_type(def_id),
+            | hir::ItemKind::Impl { .. } => self.encode_item_type(def_id),
             _ => {}
         }
         if let hir::ItemKind::Fn(..) = item.kind {
             record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id));
         }
-        if let hir::ItemKind::Impl(..) = item.kind {
+        if let hir::ItemKind::Impl { .. } = item.kind {
             if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) {
                 record!(self.per_def.impl_trait_ref[def_id] <- trait_ref);
             }
@@ -1199,7 +1199,7 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
             | hir::ItemKind::Enum(..)
             | hir::ItemKind::Struct(..)
             | hir::ItemKind::Union(..)
-            | hir::ItemKind::Impl(..)
+            | hir::ItemKind::Impl { .. }
             | hir::ItemKind::OpaqueTy(..)
             | hir::ItemKind::Trait(..)
             | hir::ItemKind::TraitAlias(..) => {
@@ -1645,7 +1645,7 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item<'_>) {
             hir::ItemKind::Union(..) => {
                 self.encode_fields(def_id);
             }
-            hir::ItemKind::Impl(..) => {
+            hir::ItemKind::Impl { .. } => {
                 for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
                     self.encode_info_for_impl_item(trait_item_def_id);
                 }
@@ -1666,7 +1666,7 @@ struct ImplVisitor<'tcx> {
 
 impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> {
     fn visit_item(&mut self, item: &hir::Item<'_>) {
-        if let hir::ItemKind::Impl(..) = item.kind {
+        if let hir::ItemKind::Impl { .. } = item.kind {
             let impl_id = self.tcx.hir().local_def_id(item.hir_id);
             if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id) {
                 self.impls.entry(trait_ref.def_id).or_default().push(impl_id.index);
index f9b61b9e2c9d8dfd75f7f9ad0444e2b97adc2410..00881e3ea6f1943e996ac00f246cbf451ac13cb6 100644 (file)
@@ -29,4 +29,3 @@ syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
 rustc_apfloat = { path = "../librustc_apfloat" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
-rustc_error_codes = { path = "../librustc_error_codes" }
index f2a44986cc4d4edccd167c26899abfb557130883..9d5cf3ec4bec0e8c2f962d85123fc020f6654dd8 100644 (file)
@@ -200,8 +200,8 @@ fn visit_assign(
                 region,
                 reserve_location: location,
                 activation_location: TwoPhaseActivation::NotTwoPhase,
-                borrowed_place: borrowed_place.clone(),
-                assigned_place: assigned_place.clone(),
+                borrowed_place: *borrowed_place,
+                assigned_place: *assigned_place,
             };
             let idx = self.idx_vec.push(borrow);
             self.location_map.insert(location, idx);
index 9a0c99b07e6f1806fb5eb824e04b0548a99f83ec..01b7c5645fe8b2a1c0aaff5baed72ceede5ddb87 100644 (file)
@@ -2,12 +2,13 @@
 
 use std::collections::VecDeque;
 
+use rustc::infer::NLLRegionVariableOrigin;
 use rustc::mir::{
     Body, CastKind, ConstraintCategory, FakeReadCause, Local, Location, Operand, Place, Rvalue,
     Statement, StatementKind, TerminatorKind,
 };
 use rustc::ty::adjustment::PointerCast;
-use rustc::ty::{self, TyCtxt};
+use rustc::ty::{self, RegionVid, TyCtxt};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_index::vec::IndexVec;
@@ -254,6 +255,23 @@ pub(in crate::borrow_check) fn add_lifetime_bound_suggestion_to_diagnostic<'tcx>
 }
 
 impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
+    fn free_region_constraint_info(
+        &self,
+        borrow_region: RegionVid,
+        outlived_region: RegionVid,
+    ) -> (ConstraintCategory, bool, Span, Option<RegionName>) {
+        let (category, from_closure, span) = self.regioncx.best_blame_constraint(
+            &self.body,
+            borrow_region,
+            NLLRegionVariableOrigin::FreeRegion,
+            |r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region),
+        );
+
+        let outlived_fr_name = self.give_region_a_name(outlived_region);
+
+        (category, from_closure, span, outlived_fr_name)
+    }
+
     /// Returns structured explanation for *why* the borrow contains the
     /// point from `location`. This is key for the "3-point errors"
     /// [described in the NLL RFC][d].
@@ -278,14 +296,14 @@ pub(in crate::borrow_check) fn explain_why_borrow_contains_point(
             location, borrow, kind_place
         );
 
-        let regioncx = &self.nonlexical_regioncx;
+        let regioncx = &self.regioncx;
         let body: &Body<'_> = &self.body;
         let tcx = self.infcx.tcx;
 
         let borrow_region_vid = borrow.region;
         debug!("explain_why_borrow_contains_point: borrow_region_vid={:?}", borrow_region_vid);
 
-        let region_sub = regioncx.find_sub_region_live_at(borrow_region_vid, location);
+        let region_sub = self.regioncx.find_sub_region_live_at(borrow_region_vid, location);
         debug!("explain_why_borrow_contains_point: region_sub={:?}", region_sub);
 
         match find_use::find(body, regioncx, tcx, region_sub, location) {
@@ -329,10 +347,9 @@ pub(in crate::borrow_check) fn explain_why_borrow_contains_point(
             }
 
             None => {
-                if let Some(region) = regioncx.to_error_region_vid(borrow_region_vid) {
-                    let (category, from_closure, span, region_name) = self
-                        .nonlexical_regioncx
-                        .free_region_constraint_info(self, borrow_region_vid, region);
+                if let Some(region) = self.to_error_region_vid(borrow_region_vid) {
+                    let (category, from_closure, span, region_name) =
+                        self.free_region_constraint_info(borrow_region_vid, region);
                     if let Some(region_name) = region_name {
                         let opt_place_desc = self.describe_place(borrow.borrowed_place.as_ref());
                         BorrowExplanation::MustBeValidFor {
@@ -345,14 +362,14 @@ pub(in crate::borrow_check) fn explain_why_borrow_contains_point(
                     } else {
                         debug!(
                             "explain_why_borrow_contains_point: \
-                                Could not generate a region name"
+                             Could not generate a region name"
                         );
                         BorrowExplanation::Unexplained
                     }
                 } else {
                     debug!(
                         "explain_why_borrow_contains_point: \
-                            Could not generate an error region vid"
+                         Could not generate an error region vid"
                     );
                     BorrowExplanation::Unexplained
                 }
index 3f3bdb9d36c76352d429503a78f7677a41f3f92b..0fc73d33f90013475e059f7d9f8003343cdfe071 100644 (file)
@@ -32,7 +32,7 @@
 crate use mutability_errors::AccessKind;
 crate use outlives_suggestion::OutlivesSuggestionBuilder;
 crate use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors};
-crate use region_name::{RegionErrorNamingCtx, RegionName, RegionNameSource};
+crate use region_name::{RegionName, RegionNameSource};
 
 pub(super) struct IncludingDowncast(pub(super) bool);
 
index 1425c22e461cfe82fd09b5d731e4e37f56234c09..ee9489078bdb9ba61d73168d6a419363235f637b 100644 (file)
@@ -12,7 +12,7 @@
 
 use crate::borrow_check::MirBorrowckCtxt;
 
-use super::{ErrorConstraintInfo, RegionErrorNamingCtx, RegionName, RegionNameSource};
+use super::{ErrorConstraintInfo, RegionName, RegionNameSource};
 
 /// The different things we could suggest.
 enum SuggestedConstraint {
@@ -77,19 +77,15 @@ fn region_name_is_suggestable(name: &RegionName) -> bool {
     fn region_vid_to_name(
         &self,
         mbcx: &MirBorrowckCtxt<'_, '_>,
-        renctx: &mut RegionErrorNamingCtx,
         region: RegionVid,
     ) -> Option<RegionName> {
-        mbcx.nonlexical_regioncx
-            .give_region_a_name(mbcx, renctx, region)
-            .filter(Self::region_name_is_suggestable)
+        mbcx.give_region_a_name(region).filter(Self::region_name_is_suggestable)
     }
 
     /// Compiles a list of all suggestions to be printed in the final big suggestion.
     fn compile_all_suggestions(
         &self,
         mbcx: &MirBorrowckCtxt<'_, '_>,
-        renctx: &mut RegionErrorNamingCtx,
     ) -> SmallVec<[SuggestedConstraint; 2]> {
         let mut suggested = SmallVec::new();
 
@@ -98,7 +94,7 @@ fn compile_all_suggestions(
         let mut unified_already = FxHashSet::default();
 
         for (fr, outlived) in &self.constraints_to_add {
-            let fr_name = if let Some(fr_name) = self.region_vid_to_name(mbcx, renctx, *fr) {
+            let fr_name = if let Some(fr_name) = self.region_vid_to_name(mbcx, *fr) {
                 fr_name
             } else {
                 continue;
@@ -107,9 +103,7 @@ fn compile_all_suggestions(
             let outlived = outlived
                 .iter()
                 // if there is a `None`, we will just omit that constraint
-                .filter_map(|fr| {
-                    self.region_vid_to_name(mbcx, renctx, *fr).map(|rname| (fr, rname))
-                })
+                .filter_map(|fr| self.region_vid_to_name(mbcx, *fr).map(|rname| (fr, rname)))
                 .collect::<Vec<_>>();
 
             // No suggestable outlived lifetimes.
@@ -173,12 +167,11 @@ fn compile_all_suggestions(
         &mut self,
         mbcx: &MirBorrowckCtxt<'_, '_>,
         errci: &ErrorConstraintInfo,
-        renctx: &mut RegionErrorNamingCtx,
         diag: &mut DiagnosticBuilder<'_>,
     ) {
         // Emit an intermediate note.
-        let fr_name = self.region_vid_to_name(mbcx, renctx, errci.fr);
-        let outlived_fr_name = self.region_vid_to_name(mbcx, renctx, errci.outlived_fr);
+        let fr_name = self.region_vid_to_name(mbcx, errci.fr);
+        let outlived_fr_name = self.region_vid_to_name(mbcx, errci.outlived_fr);
 
         if let (Some(fr_name), Some(outlived_fr_name)) = (fr_name, outlived_fr_name) {
             if let RegionNameSource::Static = outlived_fr_name.source {
@@ -194,11 +187,7 @@ fn compile_all_suggestions(
 
     /// If there is a suggestion to emit, add a diagnostic to the buffer. This is the final
     /// suggestion including all collected constraints.
-    crate fn add_suggestion(
-        &self,
-        mbcx: &mut MirBorrowckCtxt<'_, '_>,
-        renctx: &mut RegionErrorNamingCtx,
-    ) {
+    crate fn add_suggestion(&self, mbcx: &mut MirBorrowckCtxt<'_, '_>) {
         // No constraints to add? Done.
         if self.constraints_to_add.is_empty() {
             debug!("No constraints to suggest.");
@@ -215,7 +204,7 @@ fn compile_all_suggestions(
         }
 
         // Get all suggestable constraints.
-        let suggested = self.compile_all_suggestions(mbcx, renctx);
+        let suggested = self.compile_all_suggestions(mbcx);
 
         // If there are no suggestable constraints...
         if suggested.is_empty() {
index dc63fa80275e1994d242d35b121bc562092f9074..b999dfa3031035f83157f12b37fd2e0a1ea4c2f3 100644 (file)
@@ -1,27 +1,25 @@
 //! Error reporting machinery for lifetime errors.
 
 use rustc::infer::{
-    error_reporting::nice_region_error::NiceRegionError, region_constraints::GenericKind,
-    InferCtxt, NLLRegionVariableOrigin,
+    error_reporting::nice_region_error::NiceRegionError, opaque_types, NLLRegionVariableOrigin,
 };
-use rustc::mir::{Body, ConstraintCategory, Location};
+use rustc::mir::ConstraintCategory;
 use rustc::ty::{self, RegionVid, Ty};
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir::def_id::DefId;
-use rustc_index::vec::IndexVec;
 use rustc_span::symbol::kw;
 use rustc_span::Span;
-use std::collections::VecDeque;
 
 use crate::util::borrowck_errors;
 
 use crate::borrow_check::{
-    constraints::OutlivesConstraint, nll::ConstraintDescription,
-    region_infer::RegionInferenceContext, type_check::Locations, universal_regions::DefiningTy,
+    nll::ConstraintDescription,
+    region_infer::{values::RegionElement, TypeTest},
+    universal_regions::DefiningTy,
     MirBorrowckCtxt,
 };
 
-use super::{OutlivesSuggestionBuilder, RegionErrorNamingCtx, RegionName, RegionNameSource};
+use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource};
 
 impl ConstraintDescription for ConstraintCategory {
     fn description(&self) -> &'static str {
@@ -46,13 +44,6 @@ fn description(&self) -> &'static str {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-enum Trace {
-    StartRegion,
-    FromOutlivesConstraint(OutlivesConstraint),
-    NotVisited,
-}
-
 /// A collection of errors encountered during region inference. This is needed to efficiently
 /// report errors after borrow checking.
 ///
@@ -62,23 +53,8 @@ enum Trace {
 
 #[derive(Clone, Debug)]
 crate enum RegionErrorKind<'tcx> {
-    /// An error for a type test: `T: 'a` does not live long enough.
-    TypeTestDoesNotLiveLongEnough {
-        /// The span of the type test.
-        span: Span,
-        /// The generic type of the type test.
-        generic: GenericKind<'tcx>,
-    },
-
-    /// A generic bound failure for a type test.
-    TypeTestGenericBoundError {
-        /// The span of the type test.
-        span: Span,
-        /// The generic type of the type test.
-        generic: GenericKind<'tcx>,
-        /// The lower bound region.
-        lower_bound_region: ty::Region<'tcx>,
-    },
+    /// A generic bound failure for a type test (`T: 'a`).
+    TypeTestError { type_test: TypeTest<'tcx> },
 
     /// An unexpected hidden region for an opaque type.
     UnexpectedHiddenRegion {
@@ -94,8 +70,8 @@ enum Trace {
     BoundUniversalRegionError {
         /// The placeholder free region.
         longer_fr: RegionVid,
-        /// The region that erroneously must be outlived by `longer_fr`.
-        error_region: RegionVid,
+        /// The region element that erroneously must be outlived by `longer_fr`.
+        error_element: RegionElement,
         /// The origin of the placeholder region.
         fr_origin: NLLRegionVariableOrigin,
     },
@@ -128,26 +104,26 @@ pub struct ErrorConstraintInfo {
     pub(super) span: Span,
 }
 
-impl<'tcx> RegionInferenceContext<'tcx> {
+impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     /// Converts a region inference variable into a `ty::Region` that
     /// we can use for error reporting. If `r` is universally bound,
     /// then we use the name that we have on record for it. If `r` is
     /// existentially bound, then we check its inferred value and try
     /// to find a good name from that. Returns `None` if we can't find
     /// one (e.g., this is just some random part of the CFG).
-    pub fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> {
-        self.to_error_region_vid(r).and_then(|r| self.definitions[r].external_name)
+    pub(super) fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> {
+        self.to_error_region_vid(r).and_then(|r| self.regioncx.region_definition(r).external_name)
     }
 
-    /// Returns the [RegionVid] corresponding to the region returned by
+    /// Returns the `RegionVid` corresponding to the region returned by
     /// `to_error_region`.
-    pub fn to_error_region_vid(&self, r: RegionVid) -> Option<RegionVid> {
-        if self.universal_regions.is_universal_region(r) {
+    pub(super) fn to_error_region_vid(&self, r: RegionVid) -> Option<RegionVid> {
+        if self.regioncx.universal_regions().is_universal_region(r) {
             Some(r)
         } else {
-            let r_scc = self.constraint_sccs.scc(r);
-            let upper_bound = self.universal_upper_bound(r);
-            if self.scc_values.contains(r_scc, upper_bound) {
+            let upper_bound = self.regioncx.universal_upper_bound(r);
+
+            if self.regioncx.upper_bound_in_region_scc(r, upper_bound) {
                 self.to_error_region_vid(upper_bound)
             } else {
                 None
@@ -155,270 +131,134 @@ pub fn to_error_region_vid(&self, r: RegionVid) -> Option<RegionVid> {
         }
     }
 
-    /// Tries to find the best constraint to blame for the fact that
-    /// `R: from_region`, where `R` is some region that meets
-    /// `target_test`. This works by following the constraint graph,
-    /// creating a constraint path that forces `R` to outlive
-    /// `from_region`, and then finding the best choices within that
-    /// path to blame.
-    fn best_blame_constraint(
-        &self,
-        body: &Body<'tcx>,
-        from_region: RegionVid,
-        from_region_origin: NLLRegionVariableOrigin,
-        target_test: impl Fn(RegionVid) -> bool,
-    ) -> (ConstraintCategory, bool, Span) {
-        debug!(
-            "best_blame_constraint(from_region={:?}, from_region_origin={:?})",
-            from_region, from_region_origin
-        );
-
-        // Find all paths
-        let (path, target_region) =
-            self.find_constraint_paths_between_regions(from_region, target_test).unwrap();
-        debug!(
-            "best_blame_constraint: path={:#?}",
-            path.iter()
-                .map(|&c| format!(
-                    "{:?} ({:?}: {:?})",
-                    c,
-                    self.constraint_sccs.scc(c.sup),
-                    self.constraint_sccs.scc(c.sub),
-                ))
-                .collect::<Vec<_>>()
-        );
-
-        // Classify each of the constraints along the path.
-        let mut categorized_path: Vec<(ConstraintCategory, bool, Span)> = path
-            .iter()
-            .map(|constraint| {
-                if constraint.category == ConstraintCategory::ClosureBounds {
-                    self.retrieve_closure_constraint_info(body, &constraint)
-                } else {
-                    (constraint.category, false, constraint.locations.span(body))
-                }
-            })
-            .collect();
-        debug!("best_blame_constraint: categorized_path={:#?}", categorized_path);
-
-        // To find the best span to cite, we first try to look for the
-        // final constraint that is interesting and where the `sup` is
-        // not unified with the ultimate target region. The reason
-        // for this is that we have a chain of constraints that lead
-        // from the source to the target region, something like:
-        //
-        //    '0: '1 ('0 is the source)
-        //    '1: '2
-        //    '2: '3
-        //    '3: '4
-        //    '4: '5
-        //    '5: '6 ('6 is the target)
-        //
-        // Some of those regions are unified with `'6` (in the same
-        // SCC).  We want to screen those out. After that point, the
-        // "closest" constraint we have to the end is going to be the
-        // most likely to be the point where the value escapes -- but
-        // we still want to screen for an "interesting" point to
-        // highlight (e.g., a call site or something).
-        let target_scc = self.constraint_sccs.scc(target_region);
-        let mut range = 0..path.len();
-
-        // As noted above, when reporting an error, there is typically a chain of constraints
-        // leading from some "source" region which must outlive some "target" region.
-        // In most cases, we prefer to "blame" the constraints closer to the target --
-        // but there is one exception. When constraints arise from higher-ranked subtyping,
-        // we generally prefer to blame the source value,
-        // as the "target" in this case tends to be some type annotation that the user gave.
-        // Therefore, if we find that the region origin is some instantiation
-        // of a higher-ranked region, we start our search from the "source" point
-        // rather than the "target", and we also tweak a few other things.
-        //
-        // An example might be this bit of Rust code:
-        //
-        // ```rust
-        // let x: fn(&'static ()) = |_| {};
-        // let y: for<'a> fn(&'a ()) = x;
-        // ```
-        //
-        // In MIR, this will be converted into a combination of assignments and type ascriptions.
-        // In particular, the 'static is imposed through a type ascription:
-        //
-        // ```rust
-        // x = ...;
-        // AscribeUserType(x, fn(&'static ())
-        // y = x;
-        // ```
-        //
-        // We wind up ultimately with constraints like
-        //
-        // ```rust
-        // !a: 'temp1 // from the `y = x` statement
-        // 'temp1: 'temp2
-        // 'temp2: 'static // from the AscribeUserType
-        // ```
-        //
-        // and here we prefer to blame the source (the y = x statement).
-        let blame_source = match from_region_origin {
-            NLLRegionVariableOrigin::FreeRegion
-            | NLLRegionVariableOrigin::Existential { from_forall: false } => true,
-            NLLRegionVariableOrigin::Placeholder(_)
-            | NLLRegionVariableOrigin::Existential { from_forall: true } => false,
-        };
-
-        let find_region = |i: &usize| {
-            let constraint = path[*i];
-
-            let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup);
-
-            if blame_source {
-                match categorized_path[*i].0 {
-                    ConstraintCategory::OpaqueType
-                    | ConstraintCategory::Boring
-                    | ConstraintCategory::BoringNoLocation
-                    | ConstraintCategory::Internal => false,
-                    ConstraintCategory::TypeAnnotation
-                    | ConstraintCategory::Return
-                    | ConstraintCategory::Yield => true,
-                    _ => constraint_sup_scc != target_scc,
-                }
-            } else {
-                match categorized_path[*i].0 {
-                    ConstraintCategory::OpaqueType
-                    | ConstraintCategory::Boring
-                    | ConstraintCategory::BoringNoLocation
-                    | ConstraintCategory::Internal => false,
-                    _ => true,
-                }
-            }
-        };
-
-        let best_choice =
-            if blame_source { range.rev().find(find_region) } else { range.find(find_region) };
-
-        debug!(
-            "best_blame_constraint: best_choice={:?} blame_source={}",
-            best_choice, blame_source
-        );
-
-        if let Some(i) = best_choice {
-            if let Some(next) = categorized_path.get(i + 1) {
-                if categorized_path[i].0 == ConstraintCategory::Return
-                    && next.0 == ConstraintCategory::OpaqueType
+    /// Returns `true` if a closure is inferred to be an `FnMut` closure.
+    fn is_closure_fn_mut(&self, fr: RegionVid) -> bool {
+        if let Some(ty::ReFree(free_region)) = self.to_error_region(fr) {
+            if let ty::BoundRegion::BrEnv = free_region.bound_region {
+                if let DefiningTy::Closure(def_id, substs) =
+                    self.regioncx.universal_regions().defining_ty
                 {
-                    // The return expression is being influenced by the return type being
-                    // impl Trait, point at the return type and not the return expr.
-                    return *next;
+                    return substs.as_closure().kind(def_id, self.infcx.tcx)
+                        == ty::ClosureKind::FnMut;
                 }
             }
-            return categorized_path[i];
         }
 
-        // If that search fails, that is.. unusual. Maybe everything
-        // is in the same SCC or something. In that case, find what
-        // appears to be the most interesting point to report to the
-        // user via an even more ad-hoc guess.
-        categorized_path.sort_by(|p0, p1| p0.0.cmp(&p1.0));
-        debug!("`: sorted_path={:#?}", categorized_path);
-
-        *categorized_path.first().unwrap()
+        false
     }
 
-    /// Walks the graph of constraints (where `'a: 'b` is considered
-    /// an edge `'a -> 'b`) to find all paths from `from_region` to
-    /// `to_region`. The paths are accumulated into the vector
-    /// `results`. The paths are stored as a series of
-    /// `ConstraintIndex` values -- in other words, a list of *edges*.
-    ///
-    /// Returns: a series of constraints as well as the region `R`
-    /// that passed the target test.
-    fn find_constraint_paths_between_regions(
-        &self,
-        from_region: RegionVid,
-        target_test: impl Fn(RegionVid) -> bool,
-    ) -> Option<(Vec<OutlivesConstraint>, RegionVid)> {
-        let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions);
-        context[from_region] = Trace::StartRegion;
-
-        // Use a deque so that we do a breadth-first search. We will
-        // stop at the first match, which ought to be the shortest
-        // path (fewest constraints).
-        let mut deque = VecDeque::new();
-        deque.push_back(from_region);
-
-        while let Some(r) = deque.pop_front() {
-            debug!(
-                "find_constraint_paths_between_regions: from_region={:?} r={:?} value={}",
-                from_region,
-                r,
-                self.region_value_str(r),
-            );
-
-            // Check if we reached the region we were looking for. If so,
-            // we can reconstruct the path that led to it and return it.
-            if target_test(r) {
-                let mut result = vec![];
-                let mut p = r;
-                loop {
-                    match context[p] {
-                        Trace::NotVisited => {
-                            bug!("found unvisited region {:?} on path to {:?}", p, r)
-                        }
-
-                        Trace::FromOutlivesConstraint(c) => {
-                            result.push(c);
-                            p = c.sup;
-                        }
-
-                        Trace::StartRegion => {
-                            result.reverse();
-                            return Some((result, r));
-                        }
+    /// Produces nice borrowck error diagnostics for all the errors collected in `nll_errors`.
+    pub(in crate::borrow_check) fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) {
+        // Iterate through all the errors, producing a diagnostic for each one. The diagnostics are
+        // buffered in the `MirBorrowckCtxt`.
+
+        let mut outlives_suggestion = OutlivesSuggestionBuilder::default();
+
+        for nll_error in nll_errors.into_iter() {
+            match nll_error {
+                RegionErrorKind::TypeTestError { type_test } => {
+                    // Try to convert the lower-bound region into something named we can print for the user.
+                    let lower_bound_region = self.to_error_region(type_test.lower_bound);
+
+                    let type_test_span = type_test.locations.span(&self.body);
+
+                    if let Some(lower_bound_region) = lower_bound_region {
+                        let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
+                        self.infcx
+                            .construct_generic_bound_failure(
+                                region_scope_tree,
+                                type_test_span,
+                                None,
+                                type_test.generic_kind,
+                                lower_bound_region,
+                            )
+                            .buffer(&mut self.errors_buffer);
+                    } else {
+                        // FIXME. We should handle this case better. It
+                        // indicates that we have e.g., some region variable
+                        // whose value is like `'a+'b` where `'a` and `'b` are
+                        // distinct unrelated univesal regions that are not
+                        // known to outlive one another. It'd be nice to have
+                        // some examples where this arises to decide how best
+                        // to report it; we could probably handle it by
+                        // iterating over the universal regions and reporting
+                        // an error that multiple bounds are required.
+                        self.infcx
+                            .tcx
+                            .sess
+                            .struct_span_err(
+                                type_test_span,
+                                &format!("`{}` does not live long enough", type_test.generic_kind),
+                            )
+                            .buffer(&mut self.errors_buffer);
                     }
                 }
-            }
 
-            // Otherwise, walk over the outgoing constraints and
-            // enqueue any regions we find, keeping track of how we
-            // reached them.
-
-            // A constraint like `'r: 'x` can come from our constraint
-            // graph.
-            let fr_static = self.universal_regions.fr_static;
-            let outgoing_edges_from_graph =
-                self.constraint_graph.outgoing_edges(r, &self.constraints, fr_static);
-
-            // Always inline this closure because it can be hot.
-            let mut handle_constraint = #[inline(always)]
-            |constraint: OutlivesConstraint| {
-                debug_assert_eq!(constraint.sup, r);
-                let sub_region = constraint.sub;
-                if let Trace::NotVisited = context[sub_region] {
-                    context[sub_region] = Trace::FromOutlivesConstraint(constraint);
-                    deque.push_back(sub_region);
+                RegionErrorKind::UnexpectedHiddenRegion {
+                    opaque_type_def_id,
+                    hidden_ty,
+                    member_region,
+                } => {
+                    let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
+                    opaque_types::unexpected_hidden_region_diagnostic(
+                        self.infcx.tcx,
+                        Some(region_scope_tree),
+                        opaque_type_def_id,
+                        hidden_ty,
+                        member_region,
+                    )
+                    .buffer(&mut self.errors_buffer);
                 }
-            };
 
-            // This loop can be hot.
-            for constraint in outgoing_edges_from_graph {
-                handle_constraint(constraint);
-            }
+                RegionErrorKind::BoundUniversalRegionError {
+                    longer_fr,
+                    fr_origin,
+                    error_element,
+                } => {
+                    let error_region = self.regioncx.region_from_element(longer_fr, error_element);
+
+                    // Find the code to blame for the fact that `longer_fr` outlives `error_fr`.
+                    let (_, span) = self.regioncx.find_outlives_blame_span(
+                        &self.body,
+                        longer_fr,
+                        fr_origin,
+                        error_region,
+                    );
+
+                    // FIXME: improve this error message
+                    self.infcx
+                        .tcx
+                        .sess
+                        .struct_span_err(span, "higher-ranked subtype error")
+                        .buffer(&mut self.errors_buffer);
+                }
 
-            // Member constraints can also give rise to `'r: 'x` edges that
-            // were not part of the graph initially, so watch out for those.
-            // (But they are extremely rare; this loop is very cold.)
-            for constraint in self.applied_member_constraints(r) {
-                let p_c = &self.member_constraints[constraint.member_constraint_index];
-                let constraint = OutlivesConstraint {
-                    sup: r,
-                    sub: constraint.min_choice,
-                    locations: Locations::All(p_c.definition_span),
-                    category: ConstraintCategory::OpaqueType,
-                };
-                handle_constraint(constraint);
+                RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => {
+                    if is_reported {
+                        self.report_region_error(
+                            longer_fr,
+                            fr_origin,
+                            shorter_fr,
+                            &mut outlives_suggestion,
+                        );
+                    } else {
+                        // We only report the first error, so as not to overwhelm the user. See
+                        // `RegRegionErrorKind` docs.
+                        //
+                        // FIXME: currently we do nothing with these, but perhaps we can do better?
+                        // FIXME: try collecting these constraints on the outlives suggestion
+                        // builder. Does it make the suggestions any better?
+                        debug!(
+                            "Unreported region error: can't prove that {:?}: {:?}",
+                            longer_fr, shorter_fr
+                        );
+                    }
+                }
             }
         }
 
-        None
+        // Emit one outlives suggestions for each MIR def we borrowck
+        outlives_suggestion.add_suggestion(self);
     }
 
     /// Report an error because the universal region `fr` was required to outlive
@@ -429,38 +269,38 @@ fn find_constraint_paths_between_regions(
     /// ```
     ///
     /// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
-    pub(in crate::borrow_check) fn report_error<'a>(
-        &'a self,
-        mbcx: &MirBorrowckCtxt<'a, 'tcx>,
+    pub(in crate::borrow_check) fn report_region_error(
+        &mut self,
         fr: RegionVid,
         fr_origin: NLLRegionVariableOrigin,
         outlived_fr: RegionVid,
         outlives_suggestion: &mut OutlivesSuggestionBuilder,
-        renctx: &mut RegionErrorNamingCtx,
-    ) -> DiagnosticBuilder<'a> {
-        debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
+    ) {
+        debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
 
-        let (category, _, span) = self.best_blame_constraint(&mbcx.body, fr, fr_origin, |r| {
-            self.provides_universal_region(r, fr, outlived_fr)
-        });
+        let (category, _, span) =
+            self.regioncx.best_blame_constraint(&self.body, fr, fr_origin, |r| {
+                self.regioncx.provides_universal_region(r, fr, outlived_fr)
+            });
 
-        debug!("report_error: category={:?} {:?}", category, span);
+        debug!("report_region_error: category={:?} {:?}", category, span);
         // Check if we can use one of the "nice region errors".
         if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
-            let tables = mbcx.infcx.tcx.typeck_tables_of(mbcx.mir_def_id);
-            let nice = NiceRegionError::new_from_span(mbcx.infcx, span, o, f, Some(tables));
+            let tables = self.infcx.tcx.typeck_tables_of(self.mir_def_id);
+            let nice = NiceRegionError::new_from_span(self.infcx, span, o, f, Some(tables));
             if let Some(diag) = nice.try_report_from_nll() {
-                return diag;
+                diag.buffer(&mut self.errors_buffer);
+                return;
             }
         }
 
         let (fr_is_local, outlived_fr_is_local): (bool, bool) = (
-            self.universal_regions.is_local_free_region(fr),
-            self.universal_regions.is_local_free_region(outlived_fr),
+            self.regioncx.universal_regions().is_local_free_region(fr),
+            self.regioncx.universal_regions().is_local_free_region(outlived_fr),
         );
 
         debug!(
-            "report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}",
+            "report_region_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}",
             fr_is_local, outlived_fr_is_local, category
         );
 
@@ -473,52 +313,30 @@ pub(in crate::borrow_check) fn report_error<'a>(
             span,
         };
 
-        match (category, fr_is_local, outlived_fr_is_local) {
-            (ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(mbcx.infcx, fr) => {
-                self.report_fnmut_error(mbcx, &errci, renctx)
+        let diag = match (category, fr_is_local, outlived_fr_is_local) {
+            (ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(fr) => {
+                self.report_fnmut_error(&errci)
             }
             (ConstraintCategory::Assignment, true, false)
             | (ConstraintCategory::CallArgument, true, false) => {
-                let mut db = self.report_escaping_data_error(mbcx, &errci, renctx);
+                let mut db = self.report_escaping_data_error(&errci);
 
-                outlives_suggestion.intermediate_suggestion(mbcx, &errci, renctx, &mut db);
+                outlives_suggestion.intermediate_suggestion(self, &errci, &mut db);
                 outlives_suggestion.collect_constraint(fr, outlived_fr);
 
                 db
             }
             _ => {
-                let mut db = self.report_general_error(mbcx, &errci, renctx);
+                let mut db = self.report_general_error(&errci);
 
-                outlives_suggestion.intermediate_suggestion(mbcx, &errci, renctx, &mut db);
+                outlives_suggestion.intermediate_suggestion(self, &errci, &mut db);
                 outlives_suggestion.collect_constraint(fr, outlived_fr);
 
                 db
             }
-        }
-    }
-
-    /// We have a constraint `fr1: fr2` that is not satisfied, where
-    /// `fr2` represents some universal region. Here, `r` is some
-    /// region where we know that `fr1: r` and this function has the
-    /// job of determining whether `r` is "to blame" for the fact that
-    /// `fr1: fr2` is required.
-    ///
-    /// This is true under two conditions:
-    ///
-    /// - `r == fr2`
-    /// - `fr2` is `'static` and `r` is some placeholder in a universe
-    ///   that cannot be named by `fr1`; in that case, we will require
-    ///   that `fr1: 'static` because it is the only way to `fr1: r` to
-    ///   be satisfied. (See `add_incompatible_universe`.)
-    fn provides_universal_region(&self, r: RegionVid, fr1: RegionVid, fr2: RegionVid) -> bool {
-        debug!("provides_universal_region(r={:?}, fr1={:?}, fr2={:?})", r, fr1, fr2);
-        let result = {
-            r == fr2 || {
-                fr2 == self.universal_regions.fr_static && self.cannot_name_placeholder(fr1, r)
-            }
         };
-        debug!("provides_universal_region: result = {:?}", result);
-        result
+
+        diag.buffer(&mut self.errors_buffer);
     }
 
     /// Report a specialized error when `FnMut` closures return a reference to a captured variable.
@@ -537,15 +355,10 @@ fn provides_universal_region(&self, r: RegionVid, fr1: RegionVid, fr2: RegionVid
     ///            executing...
     ///    = note: ...therefore, returned references to captured variables will escape the closure
     /// ```
-    fn report_fnmut_error(
-        &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
-        errci: &ErrorConstraintInfo,
-        renctx: &mut RegionErrorNamingCtx,
-    ) -> DiagnosticBuilder<'_> {
+    fn report_fnmut_error(&self, errci: &ErrorConstraintInfo) -> DiagnosticBuilder<'tcx> {
         let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
 
-        let mut diag = mbcx
+        let mut diag = self
             .infcx
             .tcx
             .sess
@@ -553,7 +366,8 @@ fn report_fnmut_error(
 
         // We should check if the return type of this closure is in fact a closure - in that
         // case, we can special case the error further.
-        let return_type_is_closure = self.universal_regions.unnormalized_output_ty.is_closure();
+        let return_type_is_closure =
+            self.regioncx.universal_regions().unnormalized_output_ty.is_closure();
         let message = if return_type_is_closure {
             "returns a closure that contains a reference to a captured variable, which then \
              escapes the closure body"
@@ -563,7 +377,7 @@ fn report_fnmut_error(
 
         diag.span_label(*span, message);
 
-        match self.give_region_a_name(mbcx, renctx, *outlived_fr).unwrap().source {
+        match self.give_region_a_name(*outlived_fr).unwrap().source {
             RegionNameSource::NamedEarlyBoundRegion(fr_span)
             | RegionNameSource::NamedFreeRegion(fr_span)
             | RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _)
@@ -598,30 +412,25 @@ fn report_fnmut_error(
     /// LL |     ref_obj(x)
     ///    |     ^^^^^^^^^^ `x` escapes the function body here
     /// ```
-    fn report_escaping_data_error(
-        &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
-        errci: &ErrorConstraintInfo,
-        renctx: &mut RegionErrorNamingCtx,
-    ) -> DiagnosticBuilder<'_> {
+    fn report_escaping_data_error(&self, errci: &ErrorConstraintInfo) -> DiagnosticBuilder<'tcx> {
         let ErrorConstraintInfo { span, category, .. } = errci;
 
-        let fr_name_and_span = self.get_var_name_and_span_for_region(
-            mbcx.infcx.tcx,
-            &mbcx.body,
-            &mbcx.local_names,
-            &mbcx.upvars,
+        let fr_name_and_span = self.regioncx.get_var_name_and_span_for_region(
+            self.infcx.tcx,
+            &self.body,
+            &self.local_names,
+            &self.upvars,
             errci.fr,
         );
-        let outlived_fr_name_and_span = self.get_var_name_and_span_for_region(
-            mbcx.infcx.tcx,
-            &mbcx.body,
-            &mbcx.local_names,
-            &mbcx.upvars,
+        let outlived_fr_name_and_span = self.regioncx.get_var_name_and_span_for_region(
+            self.infcx.tcx,
+            &self.body,
+            &self.local_names,
+            &self.upvars,
             errci.outlived_fr,
         );
 
-        let escapes_from = match self.universal_regions.defining_ty {
+        let escapes_from = match self.regioncx.universal_regions().defining_ty {
             DefiningTy::Closure(..) => "closure",
             DefiningTy::Generator(..) => "generator",
             DefiningTy::FnDef(..) => "function",
@@ -634,15 +443,15 @@ fn report_escaping_data_error(
             || (*category == ConstraintCategory::Assignment && escapes_from == "function")
             || escapes_from == "const"
         {
-            return self.report_general_error(
-                mbcx,
-                &ErrorConstraintInfo { fr_is_local: true, outlived_fr_is_local: false, ..*errci },
-                renctx,
-            );
+            return self.report_general_error(&ErrorConstraintInfo {
+                fr_is_local: true,
+                outlived_fr_is_local: false,
+                ..*errci
+            });
         }
 
         let mut diag =
-            borrowck_errors::borrowed_data_escapes_closure(mbcx.infcx.tcx, *span, escapes_from);
+            borrowck_errors::borrowed_data_escapes_closure(self.infcx.tcx, *span, escapes_from);
 
         if let Some((Some(outlived_fr_name), outlived_fr_span)) = outlived_fr_name_and_span {
             diag.span_label(
@@ -684,12 +493,7 @@ fn report_escaping_data_error(
     ///    |     ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it
     ///    |                    is returning data with lifetime `'b`
     /// ```
-    fn report_general_error(
-        &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
-        errci: &ErrorConstraintInfo,
-        renctx: &mut RegionErrorNamingCtx,
-    ) -> DiagnosticBuilder<'_> {
+    fn report_general_error(&self, errci: &ErrorConstraintInfo) -> DiagnosticBuilder<'tcx> {
         let ErrorConstraintInfo {
             fr,
             fr_is_local,
@@ -701,14 +505,14 @@ fn report_general_error(
         } = errci;
 
         let mut diag =
-            mbcx.infcx.tcx.sess.struct_span_err(*span, "lifetime may not live long enough");
+            self.infcx.tcx.sess.struct_span_err(*span, "lifetime may not live long enough");
 
         let mir_def_name =
-            if mbcx.infcx.tcx.is_closure(mbcx.mir_def_id) { "closure" } else { "function" };
+            if self.infcx.tcx.is_closure(self.mir_def_id) { "closure" } else { "function" };
 
-        let fr_name = self.give_region_a_name(mbcx, renctx, *fr).unwrap();
+        let fr_name = self.give_region_a_name(*fr).unwrap();
         fr_name.highlight_region_name(&mut diag);
-        let outlived_fr_name = self.give_region_a_name(mbcx, renctx, *outlived_fr).unwrap();
+        let outlived_fr_name = self.give_region_a_name(*outlived_fr).unwrap();
         outlived_fr_name.highlight_region_name(&mut diag);
 
         match (category, outlived_fr_is_local, fr_is_local) {
@@ -735,7 +539,7 @@ fn report_general_error(
             }
         }
 
-        self.add_static_impl_trait_suggestion(mbcx.infcx, &mut diag, *fr, fr_name, *outlived_fr);
+        self.add_static_impl_trait_suggestion(&mut diag, *fr, fr_name, *outlived_fr);
 
         diag
     }
@@ -751,8 +555,7 @@ fn report_general_error(
     /// ```
     fn add_static_impl_trait_suggestion(
         &self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        diag: &mut DiagnosticBuilder<'_>,
+        diag: &mut DiagnosticBuilder<'tcx>,
         fr: RegionVid,
         // We need to pass `fr_name` - computing it again will label it twice.
         fr_name: RegionName,
@@ -761,11 +564,12 @@ fn add_static_impl_trait_suggestion(
         if let (Some(f), Some(ty::RegionKind::ReStatic)) =
             (self.to_error_region(fr), self.to_error_region(outlived_fr))
         {
-            if let Some((ty::TyS { kind: ty::Opaque(did, substs), .. }, _)) = infcx
+            if let Some((ty::TyS { kind: ty::Opaque(did, substs), .. }, _)) = self
+                .infcx
                 .tcx
                 .is_suitable_region(f)
                 .map(|r| r.def_id)
-                .map(|id| infcx.tcx.return_type_impl_trait(id))
+                .map(|id| self.infcx.tcx.return_type_impl_trait(id))
                 .unwrap_or(None)
             {
                 // Check whether or not the impl trait return type is intended to capture
@@ -773,8 +577,8 @@ fn add_static_impl_trait_suggestion(
                 //
                 // eg. check for `impl Trait + 'static` instead of `impl Trait`.
                 let has_static_predicate = {
-                    let predicates_of = infcx.tcx.predicates_of(*did);
-                    let bounds = predicates_of.instantiate(infcx.tcx, substs);
+                    let predicates_of = self.infcx.tcx.predicates_of(*did);
+                    let bounds = predicates_of.instantiate(self.infcx.tcx, substs);
 
                     let mut found = false;
                     for predicate in bounds.predicates {
@@ -802,8 +606,8 @@ fn add_static_impl_trait_suggestion(
                     diag.help(&format!("consider replacing `{}` with `{}`", fr_name, static_str));
                 } else {
                     // Otherwise, we should suggest adding a constraint on the return type.
-                    let span = infcx.tcx.def_span(*did);
-                    if let Ok(snippet) = infcx.tcx.sess.source_map().span_to_snippet(span) {
+                    let span = self.infcx.tcx.def_span(*did);
+                    if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
                         let suggestable_fr_name = if fr_name.was_named() {
                             fr_name.to_string()
                         } else {
@@ -830,130 +634,4 @@ fn add_static_impl_trait_suggestion(
             }
         }
     }
-
-    crate fn free_region_constraint_info(
-        &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
-        borrow_region: RegionVid,
-        outlived_region: RegionVid,
-    ) -> (ConstraintCategory, bool, Span, Option<RegionName>) {
-        let (category, from_closure, span) = self.best_blame_constraint(
-            &mbcx.body,
-            borrow_region,
-            NLLRegionVariableOrigin::FreeRegion,
-            |r| self.provides_universal_region(r, borrow_region, outlived_region),
-        );
-
-        let mut renctx = RegionErrorNamingCtx::new();
-        let outlived_fr_name = self.give_region_a_name(mbcx, &mut renctx, outlived_region);
-
-        (category, from_closure, span, outlived_fr_name)
-    }
-
-    // Finds some region R such that `fr1: R` and `R` is live at
-    // `elem`.
-    crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid {
-        debug!("find_sub_region_live_at(fr1={:?}, elem={:?})", fr1, elem);
-        self.find_constraint_paths_between_regions(fr1, |r| {
-            // First look for some `r` such that `fr1: r` and `r` is live at `elem`
-            debug!(
-                "find_sub_region_live_at: liveness_constraints for {:?} are {:?}",
-                r,
-                self.liveness_constraints.region_value_str(r),
-            );
-            self.liveness_constraints.contains(r, elem)
-        })
-        .or_else(|| {
-            // If we fail to find that, we may find some `r` such that
-            // `fr1: r` and `r` is a placeholder from some universe
-            // `fr1` cannot name. This would force `fr1` to be
-            // `'static`.
-            self.find_constraint_paths_between_regions(fr1, |r| {
-                self.cannot_name_placeholder(fr1, r)
-            })
-        })
-        .or_else(|| {
-            // If we fail to find THAT, it may be that `fr1` is a
-            // placeholder that cannot "fit" into its SCC. In that
-            // case, there should be some `r` where `fr1: r`, both
-            // `fr1` and `r` are in the same SCC, and `fr1` is a
-            // placeholder that `r` cannot name. We can blame that
-            // edge.
-            self.find_constraint_paths_between_regions(fr1, |r| {
-                self.constraint_sccs.scc(fr1) == self.constraint_sccs.scc(r)
-                    && self.cannot_name_placeholder(r, fr1)
-            })
-        })
-        .map(|(_path, r)| r)
-        .unwrap()
-    }
-
-    // Finds a good span to blame for the fact that `fr1` outlives `fr2`.
-    crate fn find_outlives_blame_span(
-        &self,
-        body: &Body<'tcx>,
-        fr1: RegionVid,
-        fr1_origin: NLLRegionVariableOrigin,
-        fr2: RegionVid,
-    ) -> (ConstraintCategory, Span) {
-        let (category, _, span) = self.best_blame_constraint(body, fr1, fr1_origin, |r| {
-            self.provides_universal_region(r, fr1, fr2)
-        });
-        (category, span)
-    }
-
-    fn retrieve_closure_constraint_info(
-        &self,
-        body: &Body<'tcx>,
-        constraint: &OutlivesConstraint,
-    ) -> (ConstraintCategory, bool, Span) {
-        let loc = match constraint.locations {
-            Locations::All(span) => return (constraint.category, false, span),
-            Locations::Single(loc) => loc,
-        };
-
-        let opt_span_category =
-            self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub));
-        opt_span_category.map(|&(category, span)| (category, true, span)).unwrap_or((
-            constraint.category,
-            false,
-            body.source_info(loc).span,
-        ))
-    }
-
-    /// Returns `true` if a closure is inferred to be an `FnMut` closure.
-    crate fn is_closure_fn_mut(&self, infcx: &InferCtxt<'_, 'tcx>, fr: RegionVid) -> bool {
-        if let Some(ty::ReFree(free_region)) = self.to_error_region(fr) {
-            if let ty::BoundRegion::BrEnv = free_region.bound_region {
-                if let DefiningTy::Closure(def_id, substs) = self.universal_regions.defining_ty {
-                    let closure_kind_ty = substs.as_closure().kind_ty(def_id, infcx.tcx);
-                    return Some(ty::ClosureKind::FnMut) == closure_kind_ty.to_opt_closure_kind();
-                }
-            }
-        }
-
-        false
-    }
-
-    /// If `r2` represents a placeholder region, then this returns
-    /// `true` if `r1` cannot name that placeholder in its
-    /// value; otherwise, returns `false`.
-    fn cannot_name_placeholder(&self, r1: RegionVid, r2: RegionVid) -> bool {
-        debug!("cannot_name_value_of(r1={:?}, r2={:?})", r1, r2);
-
-        match self.definitions[r2].origin {
-            NLLRegionVariableOrigin::Placeholder(placeholder) => {
-                let universe1 = self.definitions[r1].universe;
-                debug!(
-                    "cannot_name_value_of: universe1={:?} placeholder={:?}",
-                    universe1, placeholder
-                );
-                universe1.cannot_name(placeholder.universe)
-            }
-
-            NLLRegionVariableOrigin::FreeRegion | NLLRegionVariableOrigin::Existential { .. } => {
-                false
-            }
-        }
-    }
 }
index 734e3861c62de1b03721e96ccb767e2434f6b5bf..47eb2d8940af402c9c0959fffb678e70d902167a 100644 (file)
@@ -2,18 +2,14 @@
 
 use rustc::ty::print::RegionHighlightMode;
 use rustc::ty::subst::{GenericArgKind, SubstsRef};
-use rustc::ty::{self, RegionVid, Ty, TyCtxt};
-use rustc_data_structures::fx::FxHashMap;
+use rustc::ty::{self, RegionVid, Ty};
 use rustc_errors::DiagnosticBuilder;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_span::symbol::kw;
 use rustc_span::{symbol::Symbol, Span, DUMMY_SP};
 
-use crate::borrow_check::{
-    nll::ToRegionVid, region_infer::RegionInferenceContext, universal_regions::DefiningTy,
-    MirBorrowckCtxt,
-};
+use crate::borrow_check::{nll::ToRegionVid, universal_regions::DefiningTy, MirBorrowckCtxt};
 
 /// A name for a particular region used in emitting diagnostics. This name could be a generated
 /// name like `'1`, a name used by the user like `'a`, or a name like `'static`.
     AnonRegionFromAsyncFn(Span),
 }
 
-/// Records region names that have been assigned before so that we can use the same ones in later
-/// diagnostics.
-#[derive(Debug, Clone)]
-crate struct RegionErrorNamingCtx {
-    /// Record the region names generated for each region in the given
-    /// MIR def so that we can reuse them later in help/error messages.
-    renctx: FxHashMap<RegionVid, RegionName>,
-
-    /// The counter for generating new region names.
-    counter: usize,
-}
-
-impl RegionErrorNamingCtx {
-    crate fn new() -> Self {
-        Self { counter: 1, renctx: FxHashMap::default() }
-    }
-
-    /// Get the name of `region` if it has previously been named.
-    crate fn get(&self, region: &RegionVid) -> Option<&RegionName> {
-        self.renctx.get(region)
-    }
-
-    /// Give `region` the name `name`.
-    crate fn insert(&mut self, region: RegionVid, name: RegionName) {
-        self.renctx.insert(region, name);
-    }
-
-    /// Creates a synthetic region named `'N`, where `N` is the next value of the counter. Then,
-    /// increment the counter.
-    ///
-    /// The name is not memoized. A separate call to `insert` should be made later. (Currently,
-    /// this happens at the end of `give_region_a_name`).
-    crate fn synthesize_region_name(&mut self) -> Symbol {
-        let c = self.counter;
-        self.counter += 1;
-
-        Symbol::intern(&format!("'{:?}", c))
-    }
-}
-
 impl RegionName {
     crate fn was_named(&self) -> bool {
         match self.source {
@@ -161,7 +117,16 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-impl<'tcx> RegionInferenceContext<'tcx> {
+impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
+    /// Generate a synthetic region named `'N`, where `N` is the next value of the counter. Then,
+    /// increment the counter.
+    ///
+    /// This is _not_ idempotent. Call `give_region_a_name` when possible.
+    fn synthesize_region_name(&self) -> Symbol {
+        let c = self.next_region_name.replace_with(|counter| *counter + 1);
+        Symbol::intern(&format!("'{:?}", c))
+    }
+
     /// Maps from an internal MIR region vid to something that we can
     /// report to the user. In some cases, the region vids will map
     /// directly to lifetimes that the user has a name for (e.g.,
@@ -170,6 +135,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// that end, this function takes a "diagnostic" so that it can
     /// create auxiliary notes as needed.
     ///
+    /// The names are memoized, so this is both cheap to recompute and idempotent.
+    ///
     /// Example (function arguments):
     ///
     /// Suppose we are trying to give a name to the lifetime of the
@@ -187,29 +154,28 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// ```
     ///
     /// and then return the name `'1` for us to use.
-    crate fn give_region_a_name(
-        &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
-        renctx: &mut RegionErrorNamingCtx,
-        fr: RegionVid,
-    ) -> Option<RegionName> {
-        debug!("give_region_a_name(fr={:?}, counter={:?})", fr, renctx.counter);
+    crate fn give_region_a_name(&self, fr: RegionVid) -> Option<RegionName> {
+        debug!(
+            "give_region_a_name(fr={:?}, counter={:?})",
+            fr,
+            self.next_region_name.try_borrow().unwrap()
+        );
 
-        assert!(self.universal_regions.is_universal_region(fr));
+        assert!(self.regioncx.universal_regions().is_universal_region(fr));
 
-        if let Some(value) = renctx.get(&fr) {
+        if let Some(value) = self.region_names.try_borrow_mut().unwrap().get(&fr) {
             return Some(value.clone());
         }
 
         let value = self
-            .give_name_from_error_region(mbcx, fr, renctx)
-            .or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(mbcx, fr, renctx))
-            .or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(mbcx, fr, renctx))
-            .or_else(|| self.give_name_if_anonymous_region_appears_in_output(mbcx, fr, renctx))
-            .or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(mbcx, fr, renctx));
+            .give_name_from_error_region(fr)
+            .or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(fr))
+            .or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr))
+            .or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr))
+            .or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr));
 
         if let Some(ref value) = value {
-            renctx.insert(fr, value.clone());
+            self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone());
         }
 
         debug!("give_region_a_name: gave name {:?}", value);
@@ -220,15 +186,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// *user* has a name for. In that case, we'll be able to map
     /// `fr` to a `Region<'tcx>`, and that region will be one of
     /// named variants.
-    fn give_name_from_error_region(
-        &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
-        fr: RegionVid,
-        renctx: &mut RegionErrorNamingCtx,
-    ) -> Option<RegionName> {
+    fn give_name_from_error_region(&self, fr: RegionVid) -> Option<RegionName> {
         let error_region = self.to_error_region(fr)?;
 
-        let tcx = mbcx.infcx.tcx;
+        let tcx = self.infcx.tcx;
 
         debug!("give_region_a_name: error_region = {:?}", error_region);
         match error_region {
@@ -267,7 +228,7 @@ fn give_name_from_error_region(
                         // happen if we have an elided name in an async fn for example: the
                         // compiler will generate a region named `'_`, but reporting such a name is
                         // not actually useful, so we synthesize a name for it instead.
-                        let name = renctx.synthesize_region_name();
+                        let name = self.synthesize_region_name();
                         Some(RegionName {
                             name,
                             source: RegionNameSource::AnonRegionFromAsyncFn(span),
@@ -276,13 +237,13 @@ fn give_name_from_error_region(
                 }
 
                 ty::BoundRegion::BrEnv => {
-                    let mir_hir_id = mbcx
+                    let mir_hir_id = self
                         .infcx
                         .tcx
                         .hir()
-                        .as_local_hir_id(mbcx.mir_def_id)
+                        .as_local_hir_id(self.mir_def_id)
                         .expect("non-local mir");
-                    let def_ty = self.universal_regions.defining_ty;
+                    let def_ty = self.regioncx.universal_regions().defining_ty;
 
                     if let DefiningTy::Closure(def_id, substs) = def_ty {
                         let args_span = if let hir::ExprKind::Closure(_, _, _, span, _) =
@@ -292,7 +253,7 @@ fn give_name_from_error_region(
                         } else {
                             bug!("Closure is not defined by a closure expr");
                         };
-                        let region_name = renctx.synthesize_region_name();
+                        let region_name = self.synthesize_region_name();
 
                         let closure_kind_ty = substs.as_closure().kind_ty(def_id, tcx);
                         let note = match closure_kind_ty.to_opt_closure_kind() {
@@ -346,38 +307,30 @@ fn give_name_from_error_region(
     /// ```
     fn give_name_if_anonymous_region_appears_in_arguments(
         &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
         fr: RegionVid,
-        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
-        let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs();
-        let argument_index = self.get_argument_index_for_region(mbcx.infcx.tcx, fr)?;
-
-        let arg_ty =
-            self.universal_regions.unnormalized_input_tys[implicit_inputs + argument_index];
-        if let Some(region_name) = self.give_name_if_we_can_match_hir_ty_from_argument(
-            mbcx,
-            fr,
-            arg_ty,
-            argument_index,
-            renctx,
-        ) {
+        let implicit_inputs = self.regioncx.universal_regions().defining_ty.implicit_inputs();
+        let argument_index = self.regioncx.get_argument_index_for_region(self.infcx.tcx, fr)?;
+
+        let arg_ty = self.regioncx.universal_regions().unnormalized_input_tys
+            [implicit_inputs + argument_index];
+        if let Some(region_name) =
+            self.give_name_if_we_can_match_hir_ty_from_argument(fr, arg_ty, argument_index)
+        {
             return Some(region_name);
         }
 
-        self.give_name_if_we_cannot_match_hir_ty(mbcx, fr, arg_ty, renctx)
+        self.give_name_if_we_cannot_match_hir_ty(fr, arg_ty)
     }
 
     fn give_name_if_we_can_match_hir_ty_from_argument(
         &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
         needle_fr: RegionVid,
         argument_ty: Ty<'tcx>,
         argument_index: usize,
-        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
-        let mir_hir_id = mbcx.infcx.tcx.hir().as_local_hir_id(mbcx.mir_def_id)?;
-        let fn_decl = mbcx.infcx.tcx.hir().fn_decl_by_hir_id(mir_hir_id)?;
+        let mir_hir_id = self.infcx.tcx.hir().as_local_hir_id(self.mir_def_id)?;
+        let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(mir_hir_id)?;
         let argument_hir_ty: &hir::Ty<'_> = fn_decl.inputs.get(argument_index)?;
         match argument_hir_ty.kind {
             // This indicates a variable with no type annotation, like
@@ -387,13 +340,7 @@ fn give_name_if_we_can_match_hir_ty_from_argument(
             // (`give_name_if_anonymous_region_appears_in_arguments`).
             hir::TyKind::Infer => None,
 
-            _ => self.give_name_if_we_can_match_hir_ty(
-                mbcx.infcx.tcx,
-                needle_fr,
-                argument_ty,
-                argument_hir_ty,
-                renctx,
-            ),
+            _ => self.give_name_if_we_can_match_hir_ty(needle_fr, argument_ty, argument_hir_ty),
         }
     }
 
@@ -410,15 +357,13 @@ fn give_name_if_we_can_match_hir_ty_from_argument(
     /// ```
     fn give_name_if_we_cannot_match_hir_ty(
         &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
         needle_fr: RegionVid,
         argument_ty: Ty<'tcx>,
-        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
-        let counter = renctx.counter;
+        let counter = *self.next_region_name.try_borrow().unwrap();
         let mut highlight = RegionHighlightMode::default();
         highlight.highlighting_region_vid(needle_fr, counter);
-        let type_name = mbcx.infcx.extract_type_name(&argument_ty, Some(highlight)).0;
+        let type_name = self.infcx.extract_type_name(&argument_ty, Some(highlight)).0;
 
         debug!(
             "give_name_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}",
@@ -426,10 +371,11 @@ fn give_name_if_we_cannot_match_hir_ty(
         );
         let assigned_region_name = if type_name.find(&format!("'{}", counter)).is_some() {
             // Only add a label if we can confirm that a region was labelled.
-            let argument_index = self.get_argument_index_for_region(mbcx.infcx.tcx, needle_fr)?;
-            let (_, span) = self.get_argument_name_and_span_for_region(
-                &mbcx.body,
-                &mbcx.local_names,
+            let argument_index =
+                self.regioncx.get_argument_index_for_region(self.infcx.tcx, needle_fr)?;
+            let (_, span) = self.regioncx.get_argument_name_and_span_for_region(
+                &self.body,
+                &self.local_names,
                 argument_index,
             );
 
@@ -437,7 +383,7 @@ fn give_name_if_we_cannot_match_hir_ty(
                 // This counter value will already have been used, so this function will increment
                 // it so the next value will be used next and return the region name that would
                 // have been used.
-                name: renctx.synthesize_region_name(),
+                name: self.synthesize_region_name(),
                 source: RegionNameSource::CannotMatchHirTy(span, type_name),
             })
         } else {
@@ -470,11 +416,9 @@ fn give_name_if_we_cannot_match_hir_ty(
     /// to highlighting that closest type instead.
     fn give_name_if_we_can_match_hir_ty(
         &self,
-        tcx: TyCtxt<'tcx>,
         needle_fr: RegionVid,
         argument_ty: Ty<'tcx>,
         argument_hir_ty: &hir::Ty<'_>,
-        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
         let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty<'_>)> =
             &mut vec![(argument_ty, argument_hir_ty)];
@@ -492,10 +436,10 @@ fn give_name_if_we_can_match_hir_ty(
                     hir::TyKind::Rptr(_lifetime, referent_hir_ty),
                 ) => {
                     if region.to_region_vid() == needle_fr {
-                        let region_name = renctx.synthesize_region_name();
+                        let region_name = self.synthesize_region_name();
 
                         // Just grab the first character, the `&`.
-                        let source_map = tcx.sess.source_map();
+                        let source_map = self.infcx.tcx.sess.source_map();
                         let ampersand_span = source_map.start_point(hir_ty.span);
 
                         return Some(RegionName {
@@ -525,7 +469,6 @@ fn give_name_if_we_can_match_hir_ty(
                                     substs,
                                     needle_fr,
                                     last_segment,
-                                    renctx,
                                     search_stack,
                                 ) {
                                     return Some(name);
@@ -570,7 +513,6 @@ fn match_adt_and_segment<'hir>(
         substs: SubstsRef<'tcx>,
         needle_fr: RegionVid,
         last_segment: &'hir hir::PathSegment<'hir>,
-        renctx: &mut RegionErrorNamingCtx,
         search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty<'hir>)>,
     ) -> Option<RegionName> {
         // Did the user give explicit arguments? (e.g., `Foo<..>`)
@@ -582,7 +524,7 @@ fn match_adt_and_segment<'hir>(
             | hir::LifetimeName::Error
             | hir::LifetimeName::Static
             | hir::LifetimeName::Underscore => {
-                let region_name = renctx.synthesize_region_name();
+                let region_name = self.synthesize_region_name();
                 let ampersand_span = lifetime.span;
                 Some(RegionName {
                     name: region_name,
@@ -663,16 +605,14 @@ fn try_match_adt_and_generic_args<'hir>(
     ///  | let x = Some(&22);
     ///        - fully elaborated type of `x` is `Option<&'1 u32>`
     /// ```
-    fn give_name_if_anonymous_region_appears_in_upvars(
-        &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
-        fr: RegionVid,
-        renctx: &mut RegionErrorNamingCtx,
-    ) -> Option<RegionName> {
-        let upvar_index = self.get_upvar_index_for_region(mbcx.infcx.tcx, fr)?;
-        let (upvar_name, upvar_span) =
-            self.get_upvar_name_and_span_for_region(mbcx.infcx.tcx, &mbcx.upvars, upvar_index);
-        let region_name = renctx.synthesize_region_name();
+    fn give_name_if_anonymous_region_appears_in_upvars(&self, fr: RegionVid) -> Option<RegionName> {
+        let upvar_index = self.regioncx.get_upvar_index_for_region(self.infcx.tcx, fr)?;
+        let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
+            self.infcx.tcx,
+            &self.upvars,
+            upvar_index,
+        );
+        let region_name = self.synthesize_region_name();
 
         Some(RegionName {
             name: region_name,
@@ -684,25 +624,20 @@ fn give_name_if_anonymous_region_appears_in_upvars(
     /// must be a closure since, in a free fn, such an argument would
     /// have to either also appear in an argument (if using elision)
     /// or be early bound (named, not in argument).
-    fn give_name_if_anonymous_region_appears_in_output(
-        &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
-        fr: RegionVid,
-        renctx: &mut RegionErrorNamingCtx,
-    ) -> Option<RegionName> {
-        let tcx = mbcx.infcx.tcx;
+    fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Option<RegionName> {
+        let tcx = self.infcx.tcx;
 
-        let return_ty = self.universal_regions.unnormalized_output_ty;
+        let return_ty = self.regioncx.universal_regions().unnormalized_output_ty;
         debug!("give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty);
         if !tcx.any_free_region_meets(&return_ty, |r| r.to_region_vid() == fr) {
             return None;
         }
 
         let mut highlight = RegionHighlightMode::default();
-        highlight.highlighting_region_vid(fr, renctx.counter);
-        let type_name = mbcx.infcx.extract_type_name(&return_ty, Some(highlight)).0;
+        highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap());
+        let type_name = self.infcx.extract_type_name(&return_ty, Some(highlight)).0;
 
-        let mir_hir_id = tcx.hir().as_local_hir_id(mbcx.mir_def_id).expect("non-local mir");
+        let mir_hir_id = tcx.hir().as_local_hir_id(self.mir_def_id).expect("non-local mir");
 
         let (return_span, mir_description) = match tcx.hir().get(mir_hir_id) {
             hir::Node::Expr(hir::Expr {
@@ -719,14 +654,14 @@ fn give_name_if_anonymous_region_appears_in_output(
                 kind: hir::ImplItemKind::Method(method_sig, _),
                 ..
             }) => (method_sig.decl.output.span(), ""),
-            _ => (mbcx.body.span, ""),
+            _ => (self.body.span, ""),
         };
 
         Some(RegionName {
             // This counter value will already have been used, so this function will increment it
             // so the next value will be used next and return the region name that would have been
             // used.
-            name: renctx.synthesize_region_name(),
+            name: self.synthesize_region_name(),
             source: RegionNameSource::AnonRegionFromOutput(
                 return_span,
                 mir_description.to_string(),
@@ -737,32 +672,30 @@ fn give_name_if_anonymous_region_appears_in_output(
 
     fn give_name_if_anonymous_region_appears_in_yield_ty(
         &self,
-        mbcx: &MirBorrowckCtxt<'_, 'tcx>,
         fr: RegionVid,
-        renctx: &mut RegionErrorNamingCtx,
     ) -> Option<RegionName> {
         // Note: generators from `async fn` yield `()`, so we don't have to
         // worry about them here.
-        let yield_ty = self.universal_regions.yield_ty?;
+        let yield_ty = self.regioncx.universal_regions().yield_ty?;
         debug!("give_name_if_anonymous_region_appears_in_yield_ty: yield_ty = {:?}", yield_ty,);
 
-        let tcx = mbcx.infcx.tcx;
+        let tcx = self.infcx.tcx;
 
         if !tcx.any_free_region_meets(&yield_ty, |r| r.to_region_vid() == fr) {
             return None;
         }
 
         let mut highlight = RegionHighlightMode::default();
-        highlight.highlighting_region_vid(fr, renctx.counter);
-        let type_name = mbcx.infcx.extract_type_name(&yield_ty, Some(highlight)).0;
+        highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap());
+        let type_name = self.infcx.extract_type_name(&yield_ty, Some(highlight)).0;
 
-        let mir_hir_id = tcx.hir().as_local_hir_id(mbcx.mir_def_id).expect("non-local mir");
+        let mir_hir_id = tcx.hir().as_local_hir_id(self.mir_def_id).expect("non-local mir");
 
         let yield_span = match tcx.hir().get(mir_hir_id) {
             hir::Node::Expr(hir::Expr {
                 kind: hir::ExprKind::Closure(_, _, _, span, _), ..
             }) => (tcx.sess.source_map().end_point(*span)),
-            _ => mbcx.body.span,
+            _ => self.body.span,
         };
 
         debug!(
@@ -772,7 +705,7 @@ fn give_name_if_anonymous_region_appears_in_yield_ty(
         );
 
         Some(RegionName {
-            name: renctx.synthesize_region_name(),
+            name: self.synthesize_region_name(),
             source: RegionNameSource::AnonRegionFromYieldTy(yield_span, type_name),
         })
     }
index 9e3d2a7d5f63c214e6326b4900d6cf67cc5e8b76..5f3585ce8b119927ce127559f86994da3963d049 100644 (file)
@@ -16,7 +16,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         fr: RegionVid,
     ) -> Option<(Option<Symbol>, Span)> {
         debug!("get_var_name_and_span_for_region(fr={:?})", fr);
-        assert!(self.universal_regions.is_universal_region(fr));
+        assert!(self.universal_regions().is_universal_region(fr));
 
         debug!("get_var_name_and_span_for_region: attempting upvar");
         self.get_upvar_index_for_region(tcx, fr)
@@ -35,7 +35,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// Search the upvars (if any) to find one that references fr. Return its index.
     crate fn get_upvar_index_for_region(&self, tcx: TyCtxt<'tcx>, fr: RegionVid) -> Option<usize> {
         let upvar_index =
-            self.universal_regions.defining_ty.upvar_tys(tcx).position(|upvar_ty| {
+            self.universal_regions().defining_ty.upvar_tys(tcx).position(|upvar_ty| {
                 debug!("get_upvar_index_for_region: upvar_ty={:?}", upvar_ty);
                 tcx.any_free_region_meets(&upvar_ty, |r| {
                     let r = r.to_region_vid();
@@ -44,7 +44,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 })
             })?;
 
-        let upvar_ty = self.universal_regions.defining_ty.upvar_tys(tcx).nth(upvar_index);
+        let upvar_ty = self.universal_regions().defining_ty.upvar_tys(tcx).nth(upvar_index);
 
         debug!(
             "get_upvar_index_for_region: found {:?} in upvar {} which has type {:?}",
@@ -85,9 +85,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         tcx: TyCtxt<'tcx>,
         fr: RegionVid,
     ) -> Option<usize> {
-        let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs();
+        let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs();
         let argument_index =
-            self.universal_regions.unnormalized_input_tys.iter().skip(implicit_inputs).position(
+            self.universal_regions().unnormalized_input_tys.iter().skip(implicit_inputs).position(
                 |arg_ty| {
                     debug!("get_argument_index_for_region: arg_ty = {:?}", arg_ty);
                     tcx.any_free_region_meets(arg_ty, |r| r.to_region_vid() == fr)
@@ -96,7 +96,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         debug!(
             "get_argument_index_for_region: found {:?} in argument {} which has type {:?}",
-            fr, argument_index, self.universal_regions.unnormalized_input_tys[argument_index],
+            fr,
+            argument_index,
+            self.universal_regions().unnormalized_input_tys[argument_index],
         );
 
         Some(argument_index)
@@ -110,7 +112,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         local_names: &IndexVec<Local, Option<Symbol>>,
         argument_index: usize,
     ) -> (Option<Symbol>, Span) {
-        let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs();
+        let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs();
         let argument_local = Local::new(implicit_inputs + argument_index + 1);
         debug!("get_argument_name_and_span_for_region: argument_local={:?}", argument_local);
 
index 7b0a103fd00383effcbd24cc91092986002362c7..90927069242b19e2cf032b2891558178fc642d28 100644 (file)
@@ -1,6 +1,6 @@
 //! This query borrow-checks the MIR to (further) ensure it is not broken.
 
-use rustc::infer::{opaque_types, InferCtxt};
+use rustc::infer::InferCtxt;
 use rustc::lint::builtin::MUTABLE_BORROW_RESERVATION_CONFLICT;
 use rustc::lint::builtin::UNUSED_MUT;
 use rustc::mir::{
@@ -11,7 +11,8 @@
 use rustc::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
 use rustc::mir::{Terminator, TerminatorKind};
 use rustc::ty::query::Providers;
-use rustc::ty::{self, TyCtxt};
+use rustc::ty::{self, RegionVid, TyCtxt};
+
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder};
@@ -21,6 +22,7 @@
 use rustc_index::vec::IndexVec;
 
 use smallvec::SmallVec;
+use std::cell::RefCell;
 use std::collections::BTreeMap;
 use std::mem;
 use std::rc::Rc;
@@ -39,9 +41,7 @@
 use crate::dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
 use crate::transform::MirSource;
 
-use self::diagnostics::{
-    AccessKind, OutlivesSuggestionBuilder, RegionErrorKind, RegionErrorNamingCtx, RegionErrors,
-};
+use self::diagnostics::{AccessKind, RegionName};
 use self::flows::Flows;
 use self::location::LocationTable;
 use self::prefixes::PrefixSet;
@@ -285,13 +285,15 @@ fn do_mir_borrowck<'a, 'tcx>(
         move_error_reported: BTreeMap::new(),
         uninitialized_error_reported: Default::default(),
         errors_buffer,
-        nonlexical_regioncx: regioncx,
+        regioncx,
         used_mut: Default::default(),
         used_mut_upvars: SmallVec::new(),
         borrow_set,
         dominators,
         upvars,
         local_names,
+        region_names: RefCell::default(),
+        next_region_name: RefCell::new(1),
     };
 
     // Compute and report region errors, if any.
@@ -476,10 +478,9 @@ fn do_mir_borrowck<'a, 'tcx>(
     /// If the function we're checking is a closure, then we'll need to report back the list of
     /// mutable upvars that have been used. This field keeps track of them.
     used_mut_upvars: SmallVec<[Field; 8]>,
-    /// Non-lexical region inference context, if NLL is enabled. This
-    /// contains the results from region inference and lets us e.g.
+    /// Region inference context. This contains the results from region inference and lets us e.g.
     /// find out which CFG points are contained in each borrow region.
-    nonlexical_regioncx: Rc<RegionInferenceContext<'tcx>>,
+    regioncx: Rc<RegionInferenceContext<'tcx>>,
 
     /// The set of borrows extracted from the MIR
     borrow_set: Rc<BorrowSet<'tcx>>,
@@ -492,6 +493,13 @@ fn do_mir_borrowck<'a, 'tcx>(
 
     /// Names of local (user) variables (extracted from `var_debug_info`).
     local_names: IndexVec<Local, Option<Name>>,
+
+    /// Record the region names generated for each region in the given
+    /// MIR def so that we can reuse them later in help/error messages.
+    region_names: RefCell<FxHashMap<RegionVid, RegionName>>,
+
+    /// The counter for generating new region names.
+    next_region_name: RefCell<usize>,
 }
 
 // Check that:
@@ -631,7 +639,7 @@ fn visit_terminator_entry(
 
                 debug!(
                     "visit_terminator_drop \
-                        loc: {:?} term: {:?} drop_place: {:?} drop_place_ty: {:?} span: {:?}",
+                     loc: {:?} term: {:?} drop_place: {:?} drop_place_ty: {:?} span: {:?}",
                     loc, term, drop_place, drop_place_ty, span
                 );
 
@@ -1465,120 +1473,6 @@ fn check_activations(&mut self, location: Location, span: Span, flow_state: &Flo
             // initial reservation.
         }
     }
-
-    /// Produces nice borrowck error diagnostics for all the errors collected in `nll_errors`.
-    fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) {
-        // Iterate through all the errors, producing a diagnostic for each one. The diagnostics are
-        // buffered in the `MirBorrowckCtxt`.
-
-        // FIXME(mark-i-m): Would be great to get rid of the naming context.
-        let mut region_naming = RegionErrorNamingCtx::new();
-        let mut outlives_suggestion = OutlivesSuggestionBuilder::default();
-
-        for nll_error in nll_errors.into_iter() {
-            match nll_error {
-                RegionErrorKind::TypeTestDoesNotLiveLongEnough { span, generic } => {
-                    // FIXME. We should handle this case better. It
-                    // indicates that we have e.g., some region variable
-                    // whose value is like `'a+'b` where `'a` and `'b` are
-                    // distinct unrelated univesal regions that are not
-                    // known to outlive one another. It'd be nice to have
-                    // some examples where this arises to decide how best
-                    // to report it; we could probably handle it by
-                    // iterating over the universal regions and reporting
-                    // an error that multiple bounds are required.
-                    self.infcx
-                        .tcx
-                        .sess
-                        .struct_span_err(span, &format!("`{}` does not live long enough", generic))
-                        .buffer(&mut self.errors_buffer);
-                }
-
-                RegionErrorKind::TypeTestGenericBoundError {
-                    span,
-                    generic,
-                    lower_bound_region,
-                } => {
-                    let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
-                    self.infcx
-                        .construct_generic_bound_failure(
-                            region_scope_tree,
-                            span,
-                            None,
-                            generic,
-                            lower_bound_region,
-                        )
-                        .buffer(&mut self.errors_buffer);
-                }
-
-                RegionErrorKind::UnexpectedHiddenRegion {
-                    opaque_type_def_id,
-                    hidden_ty,
-                    member_region,
-                } => {
-                    let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id);
-                    opaque_types::unexpected_hidden_region_diagnostic(
-                        self.infcx.tcx,
-                        Some(region_scope_tree),
-                        opaque_type_def_id,
-                        hidden_ty,
-                        member_region,
-                    )
-                    .buffer(&mut self.errors_buffer);
-                }
-
-                RegionErrorKind::BoundUniversalRegionError {
-                    longer_fr,
-                    fr_origin,
-                    error_region,
-                } => {
-                    // Find the code to blame for the fact that `longer_fr` outlives `error_fr`.
-                    let (_, span) = self.nonlexical_regioncx.find_outlives_blame_span(
-                        &self.body,
-                        longer_fr,
-                        fr_origin,
-                        error_region,
-                    );
-
-                    // FIXME: improve this error message
-                    self.infcx
-                        .tcx
-                        .sess
-                        .struct_span_err(span, "higher-ranked subtype error")
-                        .buffer(&mut self.errors_buffer);
-                }
-
-                RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => {
-                    if is_reported {
-                        let db = self.nonlexical_regioncx.report_error(
-                            self,
-                            longer_fr,
-                            fr_origin,
-                            shorter_fr,
-                            &mut outlives_suggestion,
-                            &mut region_naming,
-                        );
-
-                        db.buffer(&mut self.errors_buffer);
-                    } else {
-                        // We only report the first error, so as not to overwhelm the user. See
-                        // `RegRegionErrorKind` docs.
-                        //
-                        // FIXME: currently we do nothing with these, but perhaps we can do better?
-                        // FIXME: try collecting these constraints on the outlives suggestion
-                        // builder. Does it make the suggestions any better?
-                        debug!(
-                            "Unreported region error: can't prove that {:?}: {:?}",
-                            longer_fr, shorter_fr
-                        );
-                    }
-                }
-            }
-        }
-
-        // Emit one outlives suggestions for each MIR def we borrowck
-        outlives_suggestion.add_suggestion(self, &mut region_naming);
-    }
 }
 
 impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
@@ -2225,7 +2119,7 @@ fn is_mutable<'d>(
                             let upvar = &self.upvars[field.index()];
                             debug!(
                                 "upvar.mutability={:?} local_mutation_is_allowed={:?} \
-                                place={:?}",
+                                 place={:?}",
                                 upvar, is_local_mutation_allowed, place
                             );
                             match (upvar.mutability, is_local_mutation_allowed) {
index 7d2384f8a7de70958ad6c799144c48f6a315a18b..26d9cf2e0450fe02d82d69d73b6154434b672834 100644 (file)
@@ -1,3 +1,4 @@
+use std::collections::VecDeque;
 use std::rc::Rc;
 
 use rustc::infer::canonical::QueryOutlivesConstraint;
@@ -43,49 +44,48 @@ pub struct RegionInferenceContext<'tcx> {
     /// variables are identified by their index (`RegionVid`). The
     /// definition contains information about where the region came
     /// from as well as its final inferred value.
-    pub(in crate::borrow_check) definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,
+    definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,
 
     /// The liveness constraints added to each region. For most
     /// regions, these start out empty and steadily grow, though for
     /// each universally quantified region R they start out containing
     /// the entire CFG and `end(R)`.
-    pub(in crate::borrow_check) liveness_constraints: LivenessValues<RegionVid>,
+    liveness_constraints: LivenessValues<RegionVid>,
 
     /// The outlives constraints computed by the type-check.
-    pub(in crate::borrow_check) constraints: Rc<OutlivesConstraintSet>,
+    constraints: Rc<OutlivesConstraintSet>,
 
     /// The constraint-set, but in graph form, making it easy to traverse
     /// the constraints adjacent to a particular region. Used to construct
     /// the SCC (see `constraint_sccs`) and for error reporting.
-    pub(in crate::borrow_check) constraint_graph: Rc<NormalConstraintGraph>,
+    constraint_graph: Rc<NormalConstraintGraph>,
 
     /// The SCC computed from `constraints` and the constraint
     /// graph. We have an edge from SCC A to SCC B if `A: B`. Used to
     /// compute the values of each region.
-    pub(in crate::borrow_check) constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
+    constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
 
     /// Reverse of the SCC constraint graph -- i.e., an edge `A -> B`
     /// exists if `B: A`. Computed lazilly.
-    pub(in crate::borrow_check) rev_constraint_graph: Option<Rc<VecGraph<ConstraintSccIndex>>>,
+    rev_constraint_graph: Option<Rc<VecGraph<ConstraintSccIndex>>>,
 
     /// The "R0 member of [R1..Rn]" constraints, indexed by SCC.
-    pub(in crate::borrow_check) member_constraints:
-        Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>,
+    member_constraints: Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>,
 
     /// Records the member constraints that we applied to each scc.
     /// This is useful for error reporting. Once constraint
     /// propagation is done, this vector is sorted according to
     /// `member_region_scc`.
-    pub(in crate::borrow_check) member_constraints_applied: Vec<AppliedMemberConstraint>,
+    member_constraints_applied: Vec<AppliedMemberConstraint>,
 
     /// Map closure bounds to a `Span` that should be used for error reporting.
-    pub(in crate::borrow_check) closure_bounds_mapping:
+    closure_bounds_mapping:
         FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
 
     /// Contains the minimum universe of any variable within the same
     /// SCC. We will ensure that no SCC contains values that are not
     /// visible from this index.
-    pub(in crate::borrow_check) scc_universes: IndexVec<ConstraintSccIndex, ty::UniverseIndex>,
+    scc_universes: IndexVec<ConstraintSccIndex, ty::UniverseIndex>,
 
     /// Contains a "representative" from each SCC. This will be the
     /// minimal RegionVid belonging to that universe. It is used as a
@@ -94,23 +94,23 @@ pub struct RegionInferenceContext<'tcx> {
     /// of its SCC and be sure that -- if they have the same repr --
     /// they *must* be equal (though not having the same repr does not
     /// mean they are unequal).
-    pub(in crate::borrow_check) scc_representatives: IndexVec<ConstraintSccIndex, ty::RegionVid>,
+    scc_representatives: IndexVec<ConstraintSccIndex, ty::RegionVid>,
 
     /// The final inferred values of the region variables; we compute
     /// one value per SCC. To get the value for any given *region*,
     /// you first find which scc it is a part of.
-    pub(in crate::borrow_check) scc_values: RegionValues<ConstraintSccIndex>,
+    scc_values: RegionValues<ConstraintSccIndex>,
 
     /// Type constraints that we check after solving.
-    pub(in crate::borrow_check) type_tests: Vec<TypeTest<'tcx>>,
+    type_tests: Vec<TypeTest<'tcx>>,
 
     /// Information about the universally quantified regions in scope
     /// on this function.
-    pub(in crate::borrow_check) universal_regions: Rc<UniversalRegions<'tcx>>,
+    universal_regions: Rc<UniversalRegions<'tcx>>,
 
     /// Information about how the universally quantified regions in
     /// scope on this function relate to one another.
-    pub(in crate::borrow_check) universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
+    universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
 }
 
 /// Each time that `apply_member_constraint` is successful, it appends
@@ -225,6 +225,13 @@ enum RegionRelationCheckResult {
     Error,
 }
 
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+enum Trace {
+    StartRegion,
+    FromOutlivesConstraint(OutlivesConstraint),
+    NotVisited,
+}
+
 impl<'tcx> RegionInferenceContext<'tcx> {
     /// Creates a new region inference context with a total of
     /// `num_region_variables` valid inference variables; the first N
@@ -838,39 +845,22 @@ fn check_type_tests(
             }
 
             // Type-test failed. Report the error.
-
-            // Try to convert the lower-bound region into something named we can print for the user.
-            let lower_bound_region = self.to_error_region(type_test.lower_bound);
+            let erased_generic_kind = infcx.tcx.erase_regions(&type_test.generic_kind);
 
             // Skip duplicate-ish errors.
-            let type_test_span = type_test.locations.span(body);
-            let erased_generic_kind = tcx.erase_regions(&type_test.generic_kind);
-            if !deduplicate_errors.insert((
+            if deduplicate_errors.insert((
                 erased_generic_kind,
-                lower_bound_region,
+                type_test.lower_bound,
                 type_test.locations,
             )) {
-                continue;
-            } else {
                 debug!(
                     "check_type_test: reporting error for erased_generic_kind={:?}, \
                      lower_bound_region={:?}, \
                      type_test.locations={:?}",
-                    erased_generic_kind, lower_bound_region, type_test.locations,
+                    erased_generic_kind, type_test.lower_bound, type_test.locations,
                 );
-            }
 
-            if let Some(lower_bound_region) = lower_bound_region {
-                errors_buffer.push(RegionErrorKind::TypeTestGenericBoundError {
-                    span: type_test_span,
-                    generic: type_test.generic_kind,
-                    lower_bound_region,
-                });
-            } else {
-                errors_buffer.push(RegionErrorKind::TypeTestDoesNotLiveLongEnough {
-                    span: type_test_span,
-                    generic: type_test.generic_kind,
-                });
+                errors_buffer.push(RegionErrorKind::TypeTestError { type_test: type_test.clone() });
             }
         }
     }
@@ -1355,7 +1345,7 @@ fn check_polonius_subset_errors(
         for (longer_fr, shorter_fr) in subset_errors.into_iter() {
             debug!(
                 "check_polonius_subset_errors: subset_error longer_fr={:?},\
-                shorter_fr={:?}",
+                 shorter_fr={:?}",
                 longer_fr, shorter_fr
             );
 
@@ -1572,23 +1562,9 @@ fn check_bound_universal_region(
         debug!("check_bound_universal_region: error_element = {:?}", error_element);
 
         // Find the region that introduced this `error_element`.
-        let error_region = match error_element {
-            RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l),
-            RegionElement::RootUniversalRegion(r) => r,
-            RegionElement::PlaceholderRegion(error_placeholder) => self
-                .definitions
-                .iter_enumerated()
-                .filter_map(|(r, definition)| match definition.origin {
-                    NLLRegionVariableOrigin::Placeholder(p) if p == error_placeholder => Some(r),
-                    _ => None,
-                })
-                .next()
-                .unwrap(),
-        };
-
         errors_buffer.push(RegionErrorKind::BoundUniversalRegionError {
             longer_fr,
-            error_region,
+            error_element,
             fr_origin: NLLRegionVariableOrigin::Placeholder(placeholder),
         });
     }
@@ -1628,6 +1604,425 @@ fn check_member_constraints(
             });
         }
     }
+
+    /// We have a constraint `fr1: fr2` that is not satisfied, where
+    /// `fr2` represents some universal region. Here, `r` is some
+    /// region where we know that `fr1: r` and this function has the
+    /// job of determining whether `r` is "to blame" for the fact that
+    /// `fr1: fr2` is required.
+    ///
+    /// This is true under two conditions:
+    ///
+    /// - `r == fr2`
+    /// - `fr2` is `'static` and `r` is some placeholder in a universe
+    ///   that cannot be named by `fr1`; in that case, we will require
+    ///   that `fr1: 'static` because it is the only way to `fr1: r` to
+    ///   be satisfied. (See `add_incompatible_universe`.)
+    crate fn provides_universal_region(
+        &self,
+        r: RegionVid,
+        fr1: RegionVid,
+        fr2: RegionVid,
+    ) -> bool {
+        debug!("provides_universal_region(r={:?}, fr1={:?}, fr2={:?})", r, fr1, fr2);
+        let result = {
+            r == fr2 || {
+                fr2 == self.universal_regions.fr_static && self.cannot_name_placeholder(fr1, r)
+            }
+        };
+        debug!("provides_universal_region: result = {:?}", result);
+        result
+    }
+
+    /// If `r2` represents a placeholder region, then this returns
+    /// `true` if `r1` cannot name that placeholder in its
+    /// value; otherwise, returns `false`.
+    crate fn cannot_name_placeholder(&self, r1: RegionVid, r2: RegionVid) -> bool {
+        debug!("cannot_name_value_of(r1={:?}, r2={:?})", r1, r2);
+
+        match self.definitions[r2].origin {
+            NLLRegionVariableOrigin::Placeholder(placeholder) => {
+                let universe1 = self.definitions[r1].universe;
+                debug!(
+                    "cannot_name_value_of: universe1={:?} placeholder={:?}",
+                    universe1, placeholder
+                );
+                universe1.cannot_name(placeholder.universe)
+            }
+
+            NLLRegionVariableOrigin::FreeRegion | NLLRegionVariableOrigin::Existential { .. } => {
+                false
+            }
+        }
+    }
+
+    crate fn retrieve_closure_constraint_info(
+        &self,
+        body: &Body<'tcx>,
+        constraint: &OutlivesConstraint,
+    ) -> (ConstraintCategory, bool, Span) {
+        let loc = match constraint.locations {
+            Locations::All(span) => return (constraint.category, false, span),
+            Locations::Single(loc) => loc,
+        };
+
+        let opt_span_category =
+            self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub));
+        opt_span_category.map(|&(category, span)| (category, true, span)).unwrap_or((
+            constraint.category,
+            false,
+            body.source_info(loc).span,
+        ))
+    }
+
+    /// Finds a good span to blame for the fact that `fr1` outlives `fr2`.
+    crate fn find_outlives_blame_span(
+        &self,
+        body: &Body<'tcx>,
+        fr1: RegionVid,
+        fr1_origin: NLLRegionVariableOrigin,
+        fr2: RegionVid,
+    ) -> (ConstraintCategory, Span) {
+        let (category, _, span) = self.best_blame_constraint(body, fr1, fr1_origin, |r| {
+            self.provides_universal_region(r, fr1, fr2)
+        });
+        (category, span)
+    }
+
+    /// Walks the graph of constraints (where `'a: 'b` is considered
+    /// an edge `'a -> 'b`) to find all paths from `from_region` to
+    /// `to_region`. The paths are accumulated into the vector
+    /// `results`. The paths are stored as a series of
+    /// `ConstraintIndex` values -- in other words, a list of *edges*.
+    ///
+    /// Returns: a series of constraints as well as the region `R`
+    /// that passed the target test.
+    crate fn find_constraint_paths_between_regions(
+        &self,
+        from_region: RegionVid,
+        target_test: impl Fn(RegionVid) -> bool,
+    ) -> Option<(Vec<OutlivesConstraint>, RegionVid)> {
+        let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions);
+        context[from_region] = Trace::StartRegion;
+
+        // Use a deque so that we do a breadth-first search. We will
+        // stop at the first match, which ought to be the shortest
+        // path (fewest constraints).
+        let mut deque = VecDeque::new();
+        deque.push_back(from_region);
+
+        while let Some(r) = deque.pop_front() {
+            debug!(
+                "find_constraint_paths_between_regions: from_region={:?} r={:?} value={}",
+                from_region,
+                r,
+                self.region_value_str(r),
+            );
+
+            // Check if we reached the region we were looking for. If so,
+            // we can reconstruct the path that led to it and return it.
+            if target_test(r) {
+                let mut result = vec![];
+                let mut p = r;
+                loop {
+                    match context[p] {
+                        Trace::NotVisited => {
+                            bug!("found unvisited region {:?} on path to {:?}", p, r)
+                        }
+
+                        Trace::FromOutlivesConstraint(c) => {
+                            result.push(c);
+                            p = c.sup;
+                        }
+
+                        Trace::StartRegion => {
+                            result.reverse();
+                            return Some((result, r));
+                        }
+                    }
+                }
+            }
+
+            // Otherwise, walk over the outgoing constraints and
+            // enqueue any regions we find, keeping track of how we
+            // reached them.
+
+            // A constraint like `'r: 'x` can come from our constraint
+            // graph.
+            let fr_static = self.universal_regions.fr_static;
+            let outgoing_edges_from_graph =
+                self.constraint_graph.outgoing_edges(r, &self.constraints, fr_static);
+
+            // Always inline this closure because it can be hot.
+            let mut handle_constraint = #[inline(always)]
+            |constraint: OutlivesConstraint| {
+                debug_assert_eq!(constraint.sup, r);
+                let sub_region = constraint.sub;
+                if let Trace::NotVisited = context[sub_region] {
+                    context[sub_region] = Trace::FromOutlivesConstraint(constraint);
+                    deque.push_back(sub_region);
+                }
+            };
+
+            // This loop can be hot.
+            for constraint in outgoing_edges_from_graph {
+                handle_constraint(constraint);
+            }
+
+            // Member constraints can also give rise to `'r: 'x` edges that
+            // were not part of the graph initially, so watch out for those.
+            // (But they are extremely rare; this loop is very cold.)
+            for constraint in self.applied_member_constraints(r) {
+                let p_c = &self.member_constraints[constraint.member_constraint_index];
+                let constraint = OutlivesConstraint {
+                    sup: r,
+                    sub: constraint.min_choice,
+                    locations: Locations::All(p_c.definition_span),
+                    category: ConstraintCategory::OpaqueType,
+                };
+                handle_constraint(constraint);
+            }
+        }
+
+        None
+    }
+
+    /// Finds some region R such that `fr1: R` and `R` is live at `elem`.
+    crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid {
+        debug!("find_sub_region_live_at(fr1={:?}, elem={:?})", fr1, elem);
+        self.find_constraint_paths_between_regions(fr1, |r| {
+            // First look for some `r` such that `fr1: r` and `r` is live at `elem`
+            debug!(
+                "find_sub_region_live_at: liveness_constraints for {:?} are {:?}",
+                r,
+                self.liveness_constraints.region_value_str(r),
+            );
+            self.liveness_constraints.contains(r, elem)
+        })
+        .or_else(|| {
+            // If we fail to find that, we may find some `r` such that
+            // `fr1: r` and `r` is a placeholder from some universe
+            // `fr1` cannot name. This would force `fr1` to be
+            // `'static`.
+            self.find_constraint_paths_between_regions(fr1, |r| {
+                self.cannot_name_placeholder(fr1, r)
+            })
+        })
+        .or_else(|| {
+            // If we fail to find THAT, it may be that `fr1` is a
+            // placeholder that cannot "fit" into its SCC. In that
+            // case, there should be some `r` where `fr1: r`, both
+            // `fr1` and `r` are in the same SCC, and `fr1` is a
+            // placeholder that `r` cannot name. We can blame that
+            // edge.
+            self.find_constraint_paths_between_regions(fr1, |r| {
+                self.constraint_sccs.scc(fr1) == self.constraint_sccs.scc(r)
+                    && self.cannot_name_placeholder(r, fr1)
+            })
+        })
+        .map(|(_path, r)| r)
+        .unwrap()
+    }
+
+    /// Get the region outlived by `longer_fr` and live at `element`.
+    crate fn region_from_element(&self, longer_fr: RegionVid, element: RegionElement) -> RegionVid {
+        match element {
+            RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l),
+            RegionElement::RootUniversalRegion(r) => r,
+            RegionElement::PlaceholderRegion(error_placeholder) => self
+                .definitions
+                .iter_enumerated()
+                .filter_map(|(r, definition)| match definition.origin {
+                    NLLRegionVariableOrigin::Placeholder(p) if p == error_placeholder => Some(r),
+                    _ => None,
+                })
+                .next()
+                .unwrap(),
+        }
+    }
+
+    /// Get the region definition of `r`.
+    crate fn region_definition(&self, r: RegionVid) -> &RegionDefinition<'tcx> {
+        &self.definitions[r]
+    }
+
+    /// Check if the SCC of `r` contains `upper`.
+    crate fn upper_bound_in_region_scc(&self, r: RegionVid, upper: RegionVid) -> bool {
+        let r_scc = self.constraint_sccs.scc(r);
+        self.scc_values.contains(r_scc, upper)
+    }
+
+    crate fn universal_regions(&self) -> &UniversalRegions<'tcx> {
+        self.universal_regions.as_ref()
+    }
+
+    /// Tries to find the best constraint to blame for the fact that
+    /// `R: from_region`, where `R` is some region that meets
+    /// `target_test`. This works by following the constraint graph,
+    /// creating a constraint path that forces `R` to outlive
+    /// `from_region`, and then finding the best choices within that
+    /// path to blame.
+    crate fn best_blame_constraint(
+        &self,
+        body: &Body<'tcx>,
+        from_region: RegionVid,
+        from_region_origin: NLLRegionVariableOrigin,
+        target_test: impl Fn(RegionVid) -> bool,
+    ) -> (ConstraintCategory, bool, Span) {
+        debug!(
+            "best_blame_constraint(from_region={:?}, from_region_origin={:?})",
+            from_region, from_region_origin
+        );
+
+        // Find all paths
+        let (path, target_region) =
+            self.find_constraint_paths_between_regions(from_region, target_test).unwrap();
+        debug!(
+            "best_blame_constraint: path={:#?}",
+            path.iter()
+                .map(|&c| format!(
+                    "{:?} ({:?}: {:?})",
+                    c,
+                    self.constraint_sccs.scc(c.sup),
+                    self.constraint_sccs.scc(c.sub),
+                ))
+                .collect::<Vec<_>>()
+        );
+
+        // Classify each of the constraints along the path.
+        let mut categorized_path: Vec<(ConstraintCategory, bool, Span)> = path
+            .iter()
+            .map(|constraint| {
+                if constraint.category == ConstraintCategory::ClosureBounds {
+                    self.retrieve_closure_constraint_info(body, &constraint)
+                } else {
+                    (constraint.category, false, constraint.locations.span(body))
+                }
+            })
+            .collect();
+        debug!("best_blame_constraint: categorized_path={:#?}", categorized_path);
+
+        // To find the best span to cite, we first try to look for the
+        // final constraint that is interesting and where the `sup` is
+        // not unified with the ultimate target region. The reason
+        // for this is that we have a chain of constraints that lead
+        // from the source to the target region, something like:
+        //
+        //    '0: '1 ('0 is the source)
+        //    '1: '2
+        //    '2: '3
+        //    '3: '4
+        //    '4: '5
+        //    '5: '6 ('6 is the target)
+        //
+        // Some of those regions are unified with `'6` (in the same
+        // SCC).  We want to screen those out. After that point, the
+        // "closest" constraint we have to the end is going to be the
+        // most likely to be the point where the value escapes -- but
+        // we still want to screen for an "interesting" point to
+        // highlight (e.g., a call site or something).
+        let target_scc = self.constraint_sccs.scc(target_region);
+        let mut range = 0..path.len();
+
+        // As noted above, when reporting an error, there is typically a chain of constraints
+        // leading from some "source" region which must outlive some "target" region.
+        // In most cases, we prefer to "blame" the constraints closer to the target --
+        // but there is one exception. When constraints arise from higher-ranked subtyping,
+        // we generally prefer to blame the source value,
+        // as the "target" in this case tends to be some type annotation that the user gave.
+        // Therefore, if we find that the region origin is some instantiation
+        // of a higher-ranked region, we start our search from the "source" point
+        // rather than the "target", and we also tweak a few other things.
+        //
+        // An example might be this bit of Rust code:
+        //
+        // ```rust
+        // let x: fn(&'static ()) = |_| {};
+        // let y: for<'a> fn(&'a ()) = x;
+        // ```
+        //
+        // In MIR, this will be converted into a combination of assignments and type ascriptions.
+        // In particular, the 'static is imposed through a type ascription:
+        //
+        // ```rust
+        // x = ...;
+        // AscribeUserType(x, fn(&'static ())
+        // y = x;
+        // ```
+        //
+        // We wind up ultimately with constraints like
+        //
+        // ```rust
+        // !a: 'temp1 // from the `y = x` statement
+        // 'temp1: 'temp2
+        // 'temp2: 'static // from the AscribeUserType
+        // ```
+        //
+        // and here we prefer to blame the source (the y = x statement).
+        let blame_source = match from_region_origin {
+            NLLRegionVariableOrigin::FreeRegion
+            | NLLRegionVariableOrigin::Existential { from_forall: false } => true,
+            NLLRegionVariableOrigin::Placeholder(_)
+            | NLLRegionVariableOrigin::Existential { from_forall: true } => false,
+        };
+
+        let find_region = |i: &usize| {
+            let constraint = path[*i];
+
+            let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup);
+
+            if blame_source {
+                match categorized_path[*i].0 {
+                    ConstraintCategory::OpaqueType
+                    | ConstraintCategory::Boring
+                    | ConstraintCategory::BoringNoLocation
+                    | ConstraintCategory::Internal => false,
+                    ConstraintCategory::TypeAnnotation
+                    | ConstraintCategory::Return
+                    | ConstraintCategory::Yield => true,
+                    _ => constraint_sup_scc != target_scc,
+                }
+            } else {
+                match categorized_path[*i].0 {
+                    ConstraintCategory::OpaqueType
+                    | ConstraintCategory::Boring
+                    | ConstraintCategory::BoringNoLocation
+                    | ConstraintCategory::Internal => false,
+                    _ => true,
+                }
+            }
+        };
+
+        let best_choice =
+            if blame_source { range.rev().find(find_region) } else { range.find(find_region) };
+
+        debug!(
+            "best_blame_constraint: best_choice={:?} blame_source={}",
+            best_choice, blame_source
+        );
+
+        if let Some(i) = best_choice {
+            if let Some(next) = categorized_path.get(i + 1) {
+                if categorized_path[i].0 == ConstraintCategory::Return
+                    && next.0 == ConstraintCategory::OpaqueType
+                {
+                    // The return expression is being influenced by the return type being
+                    // impl Trait, point at the return type and not the return expr.
+                    return *next;
+                }
+            }
+            return categorized_path[i];
+        }
+
+        // If that search fails, that is.. unusual. Maybe everything
+        // is in the same SCC or something. In that case, find what
+        // appears to be the most interesting point to report to the
+        // user via an even more ad-hoc guess.
+        categorized_path.sort_by(|p0, p1| p0.0.cmp(&p1.0));
+        debug!("`: sorted_path={:#?}", categorized_path);
+
+        *categorized_path.first().unwrap()
+    }
 }
 
 impl<'tcx> RegionDefinition<'tcx> {
index e17efebfef824f8443cc46872d03d29048bfa5b8..3126d44014b4ea3d0943c3497794c6a38e7dec9b 100644 (file)
@@ -114,7 +114,7 @@ pub struct PlaceholderIndex { DEBUG_FORMAT = "PlaceholderIndex({})" }
 
 /// An individual element in a region value -- the value of a
 /// particular region variable consists of a set of these elements.
-#[derive(Debug)]
+#[derive(Debug, Clone)]
 crate enum RegionElement {
     /// A point in the control-flow graph.
     Location(Location),
index 947bbef4379f5ab780af9363246c4d620b623af6..a92abc98cf4c18d98a83151081bc1be544396adc 100644 (file)
@@ -27,7 +27,6 @@
     TyCtxt, UserType, UserTypeAnnotationIndex,
 };
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_error_codes::*;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
index cb676821fd438ee407774a6e1eea3d34ed0d42cf..0bcdf9ae3c1f20866644e42a44dbfb534a32c90a 100644 (file)
@@ -580,10 +580,9 @@ pub fn get_size_and_align(
                 let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
                 Ok((layout.size, layout.align.abi))
             }
-            Some(GlobalAlloc::Memory(alloc)) =>
-            // Need to duplicate the logic here, because the global allocations have
-            // different associated types than the interpreter-local ones.
-            {
+            Some(GlobalAlloc::Memory(alloc)) => {
+                // Need to duplicate the logic here, because the global allocations have
+                // different associated types than the interpreter-local ones.
                 Ok((alloc.size, alloc.align))
             }
             Some(GlobalAlloc::Function(_)) => bug!("We already checked function pointers above"),
index b37eff3f40626a44691236aebd04761982d09822..d1c08da6cbee55da6b4c287974897bdcb9ad121b 100644 (file)
@@ -684,16 +684,14 @@ pub fn read_discriminant(
                             let variant_index = variants_start
                                 .checked_add(variant_index_relative)
                                 .expect("oveflow computing absolute variant idx");
-                            assert!(
-                                (variant_index as usize)
-                                    < rval
-                                        .layout
-                                        .ty
-                                        .ty_adt_def()
-                                        .expect("tagged layout for non adt")
-                                        .variants
-                                        .len()
-                            );
+                            let variants_len = rval
+                                .layout
+                                .ty
+                                .ty_adt_def()
+                                .expect("tagged layout for non adt")
+                                .variants
+                                .len();
+                            assert!((variant_index as usize) < variants_len);
                             (u128::from(variant_index), VariantIdx::from_u32(variant_index))
                         } else {
                             (u128::from(dataful_variant.as_u32()), dataful_variant)
index 8888e3fd4632a2a3e1549dea0f646c29e537257f..4f96cb698915d25146c45e2bff6d9528bf49e772 100644 (file)
@@ -432,12 +432,11 @@ pub fn mplace_field(
             // happens at run-time so that's okay.
             let align = match self.size_and_align_of(base.meta, field_layout)? {
                 Some((_, align)) => align,
-                None if offset == Size::ZERO =>
-                // An extern type at offset 0, we fall back to its static alignment.
-                // FIXME: Once we have made decisions for how to handle size and alignment
-                // of `extern type`, this should be adapted.  It is just a temporary hack
-                // to get some code to work that probably ought to work.
-                {
+                None if offset == Size::ZERO => {
+                    // An extern type at offset 0, we fall back to its static alignment.
+                    // FIXME: Once we have made decisions for how to handle size and alignment
+                    // of `extern type`, this should be adapted.  It is just a temporary hack
+                    // to get some code to work that probably ought to work.
                     field_layout.align.abi
                 }
                 None => bug!("Cannot compute offset for extern type field at non-0 offset"),
index 6934ec0bdb6aa56aad958961a8fbf5fc9552e0ac..aa2b3040a716f49a757207d8c33b88d1bd3386e5 100644 (file)
@@ -114,14 +114,11 @@ fn write_path(out: &mut String, path: &Vec<PathElem>) {
             ClosureVar(name) => write!(out, ".<closure-var({})>", name),
             TupleElem(idx) => write!(out, ".{}", idx),
             ArrayElem(idx) => write!(out, "[{}]", idx),
-            Deref =>
-            // This does not match Rust syntax, but it is more readable for long paths -- and
+            // `.<deref>` does not match Rust syntax, but it is more readable for long paths -- and
             // some of the other items here also are not Rust syntax.  Actually we can't
             // even use the usual syntax because we are just showing the projections,
             // not the root.
-            {
-                write!(out, ".<deref>")
-            }
+            Deref => write!(out, ".<deref>"),
             Tag => write!(out, ".<enum-tag>"),
             DynDowncast => write!(out, ".<dyn-downcast>"),
         }
@@ -206,9 +203,8 @@ fn aggregate_field_path_elem(&mut self, layout: TyLayout<'tcx>, field: usize) ->
             ty::Adt(def, ..) if def.is_enum() => {
                 // we might be projecting *to* a variant, or to a field *in*a variant.
                 match layout.variants {
-                    layout::Variants::Single { index } =>
-                    // Inside a variant
-                    {
+                    layout::Variants::Single { index } => {
+                        // Inside a variant
                         PathElem::Field(def.variants[index].fields[field].ident.name)
                     }
                     _ => bug!(),
index 1c25b269b18fd1fd15f2479e2957e618f36f6b3e..5e42ba3279027953cefa1c0b7aa889d5804c7be7 100644 (file)
@@ -7,7 +7,7 @@
 #![feature(nll)]
 #![feature(in_band_lifetimes)]
 #![feature(inner_deref)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
index f5f00c9343561dd318954d91df45fe9258fa2be5..f4611c32e0a32a21bcb40794d66e3d0442d84ed4 100644 (file)
@@ -418,7 +418,7 @@ fn check_recursion_limit<'tcx>(
     let recursion_depth = recursion_depths.get(&def_id).cloned().unwrap_or(0);
     debug!(" => recursion depth={}", recursion_depth);
 
-    let recursion_depth = if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
+    let adjusted_recursion_depth = if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
         // HACK: drop_in_place creates tight monomorphization loops. Give
         // it more margin.
         recursion_depth / 4
@@ -429,7 +429,7 @@ fn check_recursion_limit<'tcx>(
     // Code that needs to instantiate the same function recursively
     // more than the recursion limit is assumed to be causing an
     // infinite expansion.
-    if recursion_depth > *tcx.sess.recursion_limit.get() {
+    if adjusted_recursion_depth > *tcx.sess.recursion_limit.get() {
         let error = format!("reached the recursion limit while instantiating `{}`", instance);
         if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) {
             tcx.sess.span_fatal(tcx.hir().span(hir_id), &error);
@@ -954,7 +954,7 @@ fn visit_item(&mut self, item: &'v hir::Item<'v>) {
                 // Nothing to do, just keep recursing.
             }
 
-            hir::ItemKind::Impl(..) => {
+            hir::ItemKind::Impl { .. } => {
                 if self.mode == MonoItemCollectionMode::Eager {
                     create_mono_items_for_default_impls(self.tcx, item, self.output);
                 }
@@ -1098,7 +1098,7 @@ fn create_mono_items_for_default_impls<'tcx>(
     output: &mut Vec<MonoItem<'tcx>>,
 ) {
     match item.kind {
-        hir::ItemKind::Impl(_, _, _, ref generics, .., ref impl_item_refs) => {
+        hir::ItemKind::Impl { ref generics, ref items, .. } => {
             for param in generics.params {
                 match param.kind {
                     hir::GenericParamKind::Lifetime { .. } => {}
@@ -1119,7 +1119,7 @@ fn create_mono_items_for_default_impls<'tcx>(
                 let param_env = ty::ParamEnv::reveal_all();
                 let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref);
                 let overridden_methods: FxHashSet<_> =
-                    impl_item_refs.iter().map(|iiref| iiref.ident.modern()).collect();
+                    items.iter().map(|iiref| iiref.ident.modern()).collect();
                 for method in tcx.provided_trait_methods(trait_ref.def_id) {
                     if overridden_methods.contains(&method.ident.modern()) {
                         continue;
index edb4eb4d7c34454617c03482c8a2fb2fa9f2f53a..3263905eadb81691ed9c0bd5df569a76aa63d2d5 100644 (file)
@@ -10,8 +10,6 @@
 
 use super::{ConstKind, Item};
 
-use rustc_error_codes::*;
-
 /// An operation that is not *always* allowed in a const context.
 pub trait NonConstOp: std::fmt::Debug {
     /// Whether this operation can be evaluated by miri.
index 10a4b7d92b764a266610c206fcfe978bf6384457..1d5fb33ee8e81bf9c4bbccefb4212dbc74230d53 100644 (file)
@@ -6,7 +6,6 @@
 use rustc::traits::{self, TraitEngine};
 use rustc::ty::cast::CastTy;
 use rustc::ty::{self, TyCtxt};
-use rustc_error_codes::*;
 use rustc_errors::struct_span_err;
 use rustc_hir::{def_id::DefId, HirId};
 use rustc_index::bit_set::BitSet;
index 072cdf2ebba3a26386190276493c2e5f37490ab5..4e943547f07f5773c8f22b4b274a801dead1aae4 100644 (file)
@@ -18,8 +18,6 @@
 use crate::const_eval::{is_const_fn, is_min_const_fn};
 use crate::util;
 
-use rustc_error_codes::*;
-
 pub struct UnsafetyChecker<'a, 'tcx> {
     body: &'a Body<'tcx>,
     const_context: bool,
index 5cbee929019dd8a9fe23add24f1f01a6c14a20c0..d645f6cf183b4f435a1b33788de2256fa89edb6c 100644 (file)
@@ -288,8 +288,6 @@ fn stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
     }
 }
 
-type Const<'tcx> = OpTy<'tcx>;
-
 /// Finds optimization opportunities on the MIR.
 struct ConstPropagator<'mir, 'tcx> {
     ecx: InterpCx<'mir, 'tcx, ConstPropMachine>,
@@ -387,7 +385,7 @@ fn new(
         }
     }
 
-    fn get_const(&self, local: Local) -> Option<Const<'tcx>> {
+    fn get_const(&self, local: Local) -> Option<OpTy<'tcx>> {
         if local == RETURN_PLACE {
             // Try to read the return place as an immediate so that if it is representable as a
             // scalar, we can handle it as such, but otherwise, just return the value as is.
@@ -466,11 +464,7 @@ fn use_ecx<F, T>(&mut self, source_info: SourceInfo, f: F) -> Option<T>
         r
     }
 
-    fn eval_constant(
-        &mut self,
-        c: &Constant<'tcx>,
-        source_info: SourceInfo,
-    ) -> Option<Const<'tcx>> {
+    fn eval_constant(&mut self, c: &Constant<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> {
         self.ecx.tcx.span = c.span;
 
         // FIXME we need to revisit this for #67176
@@ -510,12 +504,12 @@ fn eval_constant(
         }
     }
 
-    fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
+    fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> {
         trace!("eval_place(place={:?})", place);
         self.use_ecx(source_info, |this| this.ecx.eval_place_to_op(place, None))
     }
 
-    fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
+    fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> {
         match *op {
             Operand::Constant(ref c) => self.eval_constant(c, source_info),
             Operand::Move(ref place) | Operand::Copy(ref place) => {
@@ -636,28 +630,11 @@ fn const_prop(
                 self.check_binary_op(*op, left, right, source_info, place_layout, overflow_check)?;
             }
 
-            // Work around: avoid ICE in miri. FIXME(wesleywiser)
-            // The Miri engine ICEs when taking a reference to an uninitialized unsized
-            // local. There's nothing it can do here: taking a reference needs an allocation
-            // which needs to know the size. Normally that's okay as during execution
-            // (e.g. for CTFE) it can never happen. But here in const_prop
-            // unknown data is uninitialized, so if e.g. a function argument is unsized
-            // and has a reference taken, we get an ICE.
+            // Do not try creating references (#67862)
             Rvalue::Ref(_, _, place_ref) => {
-                trace!("checking Ref({:?})", place_ref);
+                trace!("skipping Ref({:?})", place_ref);
 
-                if let Some(local) = place_ref.as_local() {
-                    let alive = if let LocalValue::Live(_) = self.ecx.frame().locals[local].value {
-                        true
-                    } else {
-                        false
-                    };
-
-                    if !alive {
-                        trace!("skipping Ref({:?}) to uninitialized local", place);
-                        return None;
-                    }
-                }
+                return None;
             }
 
             _ => {}
@@ -681,7 +658,7 @@ fn operand_from_scalar(&self, scalar: Scalar, ty: Ty<'tcx>, span: Span) -> Opera
     fn replace_with_const(
         &mut self,
         rval: &mut Rvalue<'tcx>,
-        value: Const<'tcx>,
+        value: OpTy<'tcx>,
         source_info: SourceInfo,
     ) {
         trace!("attepting to replace {:?} with {:?}", rval, value);
index 7034556740849f7a260e3baa5f034117cf0ca043..d927553c72e8b4afdc1bd9eb2b31ba70688d9555 100644 (file)
@@ -309,7 +309,11 @@ fn check_terminator(
 ) -> McfResult {
     let span = terminator.source_info.span;
     match &terminator.kind {
-        TerminatorKind::Goto { .. } | TerminatorKind::Return | TerminatorKind::Resume => Ok(()),
+        TerminatorKind::FalseEdges { .. }
+        | TerminatorKind::FalseUnwind { .. }
+        | TerminatorKind::Goto { .. }
+        | TerminatorKind::Return
+        | TerminatorKind::Resume => Ok(()),
 
         TerminatorKind::Drop { location, .. } => check_place(tcx, location, span, def_id, body),
         TerminatorKind::DropAndReplace { location, value, .. } => {
@@ -317,13 +321,10 @@ fn check_terminator(
             check_operand(tcx, value, span, def_id, body)
         }
 
-        TerminatorKind::FalseEdges { .. } | TerminatorKind::SwitchInt { .. }
-            if !feature_allowed(tcx, def_id, sym::const_if_match) =>
-        {
+        TerminatorKind::SwitchInt { .. } if !feature_allowed(tcx, def_id, sym::const_if_match) => {
             Err((span, "loops and conditional expressions are not stable in const fn".into()))
         }
 
-        TerminatorKind::FalseEdges { .. } => Ok(()),
         TerminatorKind::SwitchInt { discr, switch_ty: _, values: _, targets: _ } => {
             check_operand(tcx, discr, span, def_id, body)
         }
@@ -367,13 +368,5 @@ fn check_terminator(
         TerminatorKind::Assert { cond, expected: _, msg: _, target: _, cleanup: _ } => {
             check_operand(tcx, cond, span, def_id, body)
         }
-
-        TerminatorKind::FalseUnwind { .. } if feature_allowed(tcx, def_id, sym::const_loop) => {
-            Ok(())
-        }
-
-        TerminatorKind::FalseUnwind { .. } => {
-            Err((span, "loops are not allowed in const fn".into()))
-        }
     }
 }
index c275eecfb33b629f574d521ef0a03f8e843e911b..d8ee059f1a6b6eb5c87fc0cdb1023e564987a23a 100644 (file)
@@ -1,5 +1,4 @@
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc_error_codes::*;
 use rustc_errors::{struct_span_err, DiagnosticBuilder, DiagnosticId};
 use rustc_span::{MultiSpan, Span};
 
index 79c730327559783bc5c60bc77c57d20eaa10b910..f0d1d4c6515ce66abf06f75036d88b47912590a8 100644 (file)
@@ -25,4 +25,3 @@ rustc_span = { path = "../librustc_span" }
 rustc_target = { path = "../librustc_target" }
 syntax = { path = "../libsyntax" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
-rustc_error_codes = { path = "../librustc_error_codes" }
index 6214453e64f7866144c1fe9b58c4ab0dd1bfaccd..44ff493b5b4f0370f99bc1047e2af32b8521f2ea 100644 (file)
@@ -65,7 +65,7 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
         } else if cx.body_owner_kind.is_fn_or_closure() {
             // fetch the fully liberated fn signature (that is, all bound
             // types/lifetimes replaced)
-            let fn_sig = cx.tables().liberated_fn_sigs()[id].clone();
+            let fn_sig = cx.tables().liberated_fn_sigs()[id];
             let fn_def_id = tcx.hir().local_def_id(id);
 
             let ty = tcx.type_of(fn_def_id);
index 97e718118292d3d7ff6dc3a183bade320a9df448..d6786ea24797340d6ffcdc7416910b834a65c9a9 100644 (file)
@@ -411,18 +411,21 @@ fn make_mirror_unadjusted<'a, 'tcx>(
             let def_id = cx.tcx.hir().local_def_id(count.hir_id);
             let substs = InternalSubsts::identity_for_item(cx.tcx, def_id);
             let span = cx.tcx.def_span(def_id);
-            let count =
-                match cx.tcx.const_eval_resolve(cx.param_env, def_id, substs, None, Some(span)) {
-                    Ok(cv) => cv.eval_usize(cx.tcx, cx.param_env),
-                    Err(ErrorHandled::Reported) => 0,
-                    Err(ErrorHandled::TooGeneric) => {
-                        let span = cx.tcx.def_span(def_id);
-                        cx.tcx
-                            .sess
-                            .span_err(span, "array lengths can't depend on generic parameters");
-                        0
-                    }
-                };
+            let count = match cx.tcx.const_eval_resolve(
+                ty::ParamEnv::reveal_all(),
+                def_id,
+                substs,
+                None,
+                Some(span),
+            ) {
+                Ok(cv) => cv.eval_usize(cx.tcx, ty::ParamEnv::reveal_all()),
+                Err(ErrorHandled::Reported) => 0,
+                Err(ErrorHandled::TooGeneric) => {
+                    let span = cx.tcx.def_span(def_id);
+                    cx.tcx.sess.span_err(span, "array lengths can't depend on generic parameters");
+                    0
+                }
+            };
 
             ExprKind::Repeat { value: v.to_ref(), count }
         }
index 84d57a89c983e28a1efef295813493dad96109ca..eac52da7ba4ae133b3f51bbd0f7fddbebffff86d 100644 (file)
@@ -9,7 +9,6 @@
 use rustc::session::parse::feature_err;
 use rustc::session::Session;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc_error_codes::*;
 use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::*;
index 205e25f7f8f0c6d19c1303dac6986cd2c6f46134..2657050583071ed5f9dd85d68c52e96b46753b6a 100644 (file)
@@ -28,8 +28,6 @@
 use std::cmp::Ordering;
 use std::fmt;
 
-use rustc_error_codes::*;
-
 #[derive(Clone, Debug)]
 crate enum PatternError {
     AssocConstInPattern(Span),
index 5a17f36e1da25a3c80b7ffd6f3f248b143b1c50b..42292d635bc75f65e83f9c7ee7d4d4cf899488f9 100644 (file)
@@ -5,7 +5,7 @@
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(crate_visibility_modifier)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(bool_to_option)]
 #![recursion_limit = "256"]
 
index aa159c55ff2846ed68784580de6b32b46334bcf2..8071bc6312b368e6a2a61f937b9cf5237a2d36c5 100644 (file)
@@ -16,7 +16,6 @@ rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_lexer = { path = "../librustc_lexer" }
 rustc_errors = { path = "../librustc_errors" }
-rustc_error_codes = { path = "../librustc_error_codes" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc_session = { path = "../librustc_session" }
 rustc_span = { path = "../librustc_span" }
index 8467acc759c2b5cd25e93d1c047df0349d3b2121..bf696faf2f3f48a3bf458a88bdb924cfd8449d72 100644 (file)
@@ -10,7 +10,6 @@
 
 use crate::{parse_in, validate_attr};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_error_codes::*;
 use rustc_errors::{error_code, struct_span_err, Applicability, Handler};
 use rustc_feature::{Feature, Features, State as FeatureState};
 use rustc_feature::{
index 9227e968ecc4f2522593d96aa759923c7d55047f..08f4f210152dd5825b98abe38a7902896b0e0381 100644 (file)
@@ -2,7 +2,7 @@
 
 #![feature(bool_to_option)]
 #![feature(crate_visibility_modifier)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 
 use syntax::ast;
 use syntax::print::pprust;
index 6a18c63017ed6cce86d937470f4ac42fece74c47..80bc5c158a64f947bb25984211ef21e8b9c858cd 100644 (file)
@@ -1,7 +1,6 @@
 use super::{BlockMode, Parser, PathStyle, SemiColonMode, SeqSep, TokenExpectType, TokenType};
 
 use rustc_data_structures::fx::FxHashSet;
-use rustc_error_codes::*;
 use rustc_errors::{pluralize, struct_span_err};
 use rustc_errors::{Applicability, DiagnosticBuilder, Handler, PResult};
 use rustc_span::source_map::Spanned;
index d4756dff49a9d8cd6ac4ebb5f1b4486b0d29ea85..5076aafe4ebd5c99e6df3c40683d1bd664a88c07 100644 (file)
@@ -3,7 +3,6 @@
 
 use crate::maybe_whole;
 
-use rustc_error_codes::*;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult, StashKey};
 use rustc_span::source_map::{self, respan, Span, Spanned};
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -634,15 +633,15 @@ fn parse_item_impl(
                 let constness = constness.map(|c| c.node);
                 let trait_ref = TraitRef { path, constness, ref_id: ty_first.id };
 
-                ItemKind::Impl(
+                ItemKind::Impl {
                     unsafety,
                     polarity,
                     defaultness,
                     generics,
-                    Some(trait_ref),
-                    ty_second,
-                    impl_items,
-                )
+                    of_trait: Some(trait_ref),
+                    self_ty: ty_second,
+                    items: impl_items,
+                }
             }
             None => {
                 // Reject `impl const Type {}` here
@@ -653,15 +652,15 @@ fn parse_item_impl(
                 }
 
                 // impl Type
-                ItemKind::Impl(
+                ItemKind::Impl {
                     unsafety,
                     polarity,
                     defaultness,
                     generics,
-                    None,
-                    ty_first,
-                    impl_items,
-                )
+                    of_trait: None,
+                    self_ty: ty_first,
+                    items: impl_items,
+                }
             }
         };
 
index 1368230168e07ef5a8f0faabdf7ca7f85e95c0ed..4a9016394d2582af6ff82790bed8994a9c504101 100644 (file)
@@ -33,8 +33,6 @@
 use std::path::PathBuf;
 use std::{cmp, mem, slice};
 
-use rustc_error_codes::*;
-
 bitflags::bitflags! {
     struct Restrictions: u8 {
         const STMT_EXPR         = 1 << 0;
index 549acf67d38245038dad6c5d196a664f00e44d82..edb9044df9206012ac9593682e0d0d9197a2ee63 100644 (file)
@@ -659,7 +659,6 @@ fn parse_pat_range_begin_with(
     }
 
     pub(super) fn error_inclusive_range_with_no_end(&self, span: Span) {
-        use rustc_error_codes::E0586;
         struct_span_err!(self.sess.span_diagnostic, span, E0586, "inclusive range with no end")
             .span_suggestion_short(
                 span,
index 065a3b14428c700f4691f6ba6721bf4f911cdd73..d1875a6c940b136c06c31a81eb9ed2ba519af84e 100644 (file)
@@ -3,7 +3,6 @@
 
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
 
-use rustc_error_codes::*;
 use rustc_errors::{pluralize, struct_span_err, Applicability, PResult};
 use rustc_span::source_map::Span;
 use rustc_span::symbol::{kw, sym};
index 639d8639c4bb28281dde9d59de9f2072aebf6be1..338808f6d4a0f56734d77559a426ba42c1240066 100644 (file)
@@ -20,4 +20,3 @@ rustc_session = { path = "../librustc_session" }
 rustc_target = { path = "../librustc_target" }
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
-rustc_error_codes = { path = "../librustc_error_codes" }
index 39ba2fbc63b4392dace79cacf1f9dc047e43a4cd..faa85f68fab860f0dbe9809fd4d2e69a28613398 100644 (file)
@@ -12,7 +12,6 @@
 use rustc::session::parse::feature_err;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
-use rustc_error_codes::*;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
index f2778b2aa6bcd220d38ba71e8c9a341243302851..2ff9d744f2c4d771c782d03bd5854905d64e3dad 100644 (file)
@@ -405,10 +405,10 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     }
                 }
             }
-            hir::ItemKind::Impl(.., ref opt_trait, _, impl_item_refs) => {
-                for impl_item_ref in impl_item_refs {
+            hir::ItemKind::Impl { ref of_trait, items, .. } => {
+                for impl_item_ref in items {
                     let impl_item = self.krate.impl_item(impl_item_ref.id);
-                    if opt_trait.is_some()
+                    if of_trait.is_some()
                         || has_allow_dead_code_or_lang_attr(
                             self.tcx,
                             impl_item.hir_id,
@@ -586,7 +586,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                 | hir::ItemKind::Struct(..)
                 | hir::ItemKind::Union(..)
                 | hir::ItemKind::Trait(..)
-                | hir::ItemKind::Impl(..) => {
+                | hir::ItemKind::Impl { .. } => {
                     // FIXME(66095): Because item.span is annotated with things
                     // like expansion data, and ident.span isn't, we use the
                     // def_span method if it's part of a macro invocation
index 028d7c662758a4adf87b3dd69c2e94d8851e7fd4..d36114fd3b5b5f04ba0fff88eea5bef33a000a45 100644 (file)
@@ -12,8 +12,6 @@
 use syntax::attr;
 use syntax::entry::EntryPointType;
 
-use rustc_error_codes::*;
-
 struct EntryContext<'a, 'tcx> {
     session: &'a Session,
 
index 2c26707a518508da0e5bee0e374855f9f302f8e8..782199003c72a744bc1f9320cb72906735241c67 100644 (file)
@@ -11,8 +11,6 @@
 use rustc_span::{sym, Span};
 use rustc_target::spec::abi::Abi::RustIntrinsic;
 
-use rustc_error_codes::*;
-
 fn check_mod_intrinsics(tcx: TyCtxt<'_>, module_def_id: DefId) {
     tcx.hir().visit_item_likes_in_module(module_def_id, &mut ItemVisitor { tcx }.as_deep_visitor());
 }
index 65eb07b989d83ab871380cb6048a096c1aa056ad..d746f097928eaaccfe5ae29ab717f3e04ec3a7c5 100644 (file)
@@ -7,7 +7,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![recursion_limit = "256"]
 
 #[macro_use]
index 8ae729128978655b9268599607bc97a8960b800d..2e306a1b4f2a1b2b17badb0624dc5c55b2d3567e 100644 (file)
@@ -15,8 +15,6 @@
 use rustc_span::{sym, Span};
 use syntax::ast::{Attribute, MetaItem, MetaItemKind};
 
-use rustc_error_codes::*;
-
 fn new_lib_features() -> LibFeatures {
     LibFeatures { stable: Default::default(), unstable: Default::default() }
 }
index 5ad5795c777d48bee1c011cc0abacfd4d7b9a369..69d6b38005c4c7ea02f0571e9f0d61a52e83ef4c 100644 (file)
@@ -1,7 +1,5 @@
 use Context::*;
 
-use rustc::session::Session;
-
 use rustc::hir::map::Map;
 use rustc::ty::query::Providers;
 use rustc::ty::TyCtxt;
@@ -10,10 +8,9 @@
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{Destination, Movability, Node};
+use rustc_session::Session;
 use rustc_span::Span;
 
-use rustc_error_codes::*;
-
 #[derive(Clone, Copy, Debug, PartialEq)]
 enum Context {
     Normal,
index 5ce677f52cea670a016596344af2f270a0aad1ce..667898046ac3623dfedcf05b7a331e5ecc5d8b76 100644 (file)
@@ -35,7 +35,7 @@ fn item_might_be_inlined(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>, attrs: Codegen
         hir::ItemKind::Fn(ref sig, ..) if sig.header.is_const() => {
             return true;
         }
-        hir::ItemKind::Impl(..) | hir::ItemKind::Fn(..) => {
+        hir::ItemKind::Impl { .. } | hir::ItemKind::Fn(..) => {
             let generics = tcx.generics_of(tcx.hir().local_def_id(item.hir_id));
             generics.requires_monomorphization(tcx)
         }
@@ -181,7 +181,7 @@ fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool {
                             // does too.
                             let impl_hir_id = self.tcx.hir().as_local_hir_id(impl_did).unwrap();
                             match self.tcx.hir().expect_item(impl_hir_id).kind {
-                                hir::ItemKind::Impl(..) => {
+                                hir::ItemKind::Impl { .. } => {
                                     let generics = self.tcx.generics_of(impl_did);
                                     generics.requires_monomorphization(self.tcx)
                                 }
@@ -266,7 +266,7 @@ fn propagate_node(&mut self, node: &Node<'tcx>, search_item: hir::HirId) {
                     | hir::ItemKind::Static(..)
                     | hir::ItemKind::Mod(..)
                     | hir::ItemKind::ForeignMod(..)
-                    | hir::ItemKind::Impl(..)
+                    | hir::ItemKind::Impl { .. }
                     | hir::ItemKind::Trait(..)
                     | hir::ItemKind::TraitAlias(..)
                     | hir::ItemKind::Struct(..)
@@ -349,9 +349,9 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
         }
 
         // We need only trait impls here, not inherent impls, and only non-exported ones
-        if let hir::ItemKind::Impl(.., Some(ref trait_ref), _, ref impl_item_refs) = item.kind {
+        if let hir::ItemKind::Impl { of_trait: Some(ref trait_ref), ref items, .. } = item.kind {
             if !self.access_levels.is_reachable(item.hir_id) {
-                self.worklist.extend(impl_item_refs.iter().map(|ii_ref| ii_ref.id.hir_id));
+                self.worklist.extend(items.iter().map(|ii_ref| ii_ref.id.hir_id));
 
                 let trait_def_id = match trait_ref.path.res {
                     Res::Def(DefKind::Trait, def_id) => def_id,
index af37d218d68f08b1ecf4f0327fa68cfd161113c1..320b433190e5e89761211554f5bc44e1fb118a4c 100644 (file)
@@ -26,8 +26,6 @@
 use std::mem::replace;
 use std::num::NonZeroU32;
 
-use rustc_error_codes::*;
-
 #[derive(PartialEq)]
 enum AnnotationKind {
     // Annotation is required if not inherited from unstable parents
@@ -91,7 +89,7 @@ fn annotate<F>(
                 // deprecated_since and its reason.
                 if let Some(parent_stab) = self.parent_stab {
                     if parent_stab.rustc_depr.is_some() && stab.rustc_depr.is_none() {
-                        stab.rustc_depr = parent_stab.rustc_depr.clone()
+                        stab.rustc_depr = parent_stab.rustc_depr
                     }
                 }
 
@@ -219,11 +217,11 @@ fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
             // they don't have their own stability. They still can be annotated as unstable
             // and propagate this unstability to children, but this annotation is completely
             // optional. They inherit stability from their parents when unannotated.
-            hir::ItemKind::Impl(.., None, _, _) | hir::ItemKind::ForeignMod(..) => {
+            hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod(..) => {
                 self.in_trait_impl = false;
                 kind = AnnotationKind::Container;
             }
-            hir::ItemKind::Impl(.., Some(_), _, _) => {
+            hir::ItemKind::Impl { of_trait: Some(_), .. } => {
                 self.in_trait_impl = true;
             }
             hir::ItemKind::Struct(ref sd, _) => {
@@ -308,7 +306,7 @@ fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
             // they don't have their own stability. They still can be annotated as unstable
             // and propagate this unstability to children, but this annotation is completely
             // optional. They inherit stability from their parents when unannotated.
-            hir::ItemKind::Impl(.., None, _, _) | hir::ItemKind::ForeignMod(..) => {}
+            hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod(..) => {}
 
             _ => self.check_missing_stability(i.hir_id, i.span, i.kind.descriptive_variant()),
         }
@@ -463,9 +461,9 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
             // For implementations of traits, check the stability of each item
             // individually as it's possible to have a stable trait with unstable
             // items.
-            hir::ItemKind::Impl(.., Some(ref t), _, impl_item_refs) => {
+            hir::ItemKind::Impl { of_trait: Some(ref t), items, .. } => {
                 if let Res::Def(DefKind::Trait, trait_did) = t.path.res {
-                    for impl_item_ref in impl_item_refs {
+                    for impl_item_ref in items {
                         let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                         let trait_item_def_id = self
                             .tcx
index 41e6c699c340ec592b1a243ddc377b34b154a0ef..2214838c84683d57f28d1474e340904d296ebb48 100644 (file)
@@ -18,4 +18,3 @@ rustc_lint = { path = "../librustc_lint" }
 rustc_metadata = { path = "../librustc_metadata" }
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
-rustc_error_codes = { path = "../librustc_error_codes" }
index 65661ec24f07f9a57ac7c092bdb097ab90dc8e9f..84549c0dd4554930f09626911ef46d9bc56d8241 100644 (file)
@@ -3,7 +3,6 @@
 use crate::Registry;
 use rustc::middle::cstore::MetadataLoader;
 use rustc::session::Session;
-use rustc_error_codes::*;
 use rustc_errors::struct_span_err;
 use rustc_metadata::locator;
 use rustc_span::symbol::sym;
index 795b6c107fe944040c209b51d553361519eda551..4f341b545156ce009dd826adecae703a82392e75 100644 (file)
@@ -16,5 +16,4 @@ rustc_typeck = { path = "../librustc_typeck" }
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
 rustc_data_structures = { path = "../librustc_data_structures" }
-rustc_error_codes = { path = "../librustc_error_codes" }
 log = "0.4"
index 70d4841ec244b15b91fabb6e6c9ffa8eb76058ea..634905450d4ede4a514088f33f05db70ec2eb941 100644 (file)
@@ -27,8 +27,6 @@
 use std::marker::PhantomData;
 use std::{cmp, fmt, mem};
 
-use rustc_error_codes::*;
-
 ////////////////////////////////////////////////////////////////////////////////
 /// Generic infrastructure used to implement specific visitors below.
 ////////////////////////////////////////////////////////////////////////////////
@@ -255,8 +253,8 @@ fn def_id_visibility<'tcx>(
                 Node::ImplItem(impl_item) => {
                     match tcx.hir().get(tcx.hir().get_parent_item(hir_id)) {
                         Node::Item(item) => match &item.kind {
-                            hir::ItemKind::Impl(.., None, _, _) => &impl_item.vis,
-                            hir::ItemKind::Impl(.., Some(trait_ref), _, _) => {
+                            hir::ItemKind::Impl { of_trait: None, .. } => &impl_item.vis,
+                            hir::ItemKind::Impl { of_trait: Some(trait_ref), .. } => {
                                 return def_id_visibility(tcx, trait_ref.path.res.def_id());
                             }
                             kind => bug!("unexpected item kind: {:?}", kind),
@@ -686,7 +684,7 @@ fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
 
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         let inherited_item_level = match item.kind {
-            hir::ItemKind::Impl(..) => {
+            hir::ItemKind::Impl { .. } => {
                 Option::<AccessLevel>::of_impl(item.hir_id, self.tcx, &self.access_levels)
             }
             // Foreign modules inherit level from parents.
@@ -730,9 +728,9 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                     }
                 }
             }
-            hir::ItemKind::Impl(.., ref trait_ref, _, impl_item_refs) => {
-                for impl_item_ref in impl_item_refs {
-                    if trait_ref.is_some() || impl_item_ref.vis.node.is_pub() {
+            hir::ItemKind::Impl { ref of_trait, items, .. } => {
+                for impl_item_ref in items {
+                    if of_trait.is_some() || impl_item_ref.vis.node.is_pub() {
                         self.update(impl_item_ref.id.hir_id, item_level);
                     }
                 }
@@ -827,11 +825,11 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                 }
             }
             // Visit everything except for private impl items.
-            hir::ItemKind::Impl(.., impl_item_refs) => {
+            hir::ItemKind::Impl { items, .. } => {
                 if item_level.is_some() {
                     self.reach(item.hir_id, item_level).generics().predicates().ty().trait_ref();
 
-                    for impl_item_ref in impl_item_refs {
+                    for impl_item_ref in items {
                         let impl_item_level = self.get(impl_item_ref.id.hir_id);
                         if impl_item_level.is_some() {
                             self.reach(impl_item_ref.id.hir_id, impl_item_level)
@@ -1510,7 +1508,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
             // (i.e., we could just return here to not check them at
             // all, or some worse estimation of whether an impl is
             // publicly visible).
-            hir::ItemKind::Impl(.., ref g, ref trait_ref, ref self_, impl_item_refs) => {
+            hir::ItemKind::Impl { generics: ref g, ref of_trait, ref self_ty, items, .. } => {
                 // `impl [... for] Private` is never visible.
                 let self_contains_private;
                 // `impl [... for] Public<...>`, but not `impl [... for]
@@ -1525,7 +1523,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                         at_outer_type: true,
                         outer_type_is_public_path: false,
                     };
-                    visitor.visit_ty(&self_);
+                    visitor.visit_ty(&self_ty);
                     self_contains_private = visitor.contains_private;
                     self_is_public_path = visitor.outer_type_is_public_path;
                 }
@@ -1533,7 +1531,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                 // Miscellaneous info about the impl:
 
                 // `true` iff this is `impl Private for ...`.
-                let not_private_trait = trait_ref.as_ref().map_or(
+                let not_private_trait = of_trait.as_ref().map_or(
                     true, // no trait counts as public trait
                     |tr| {
                         let did = tr.path.res.def_id();
@@ -1554,8 +1552,8 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                 // directly because we might have `impl<T: Foo<Private>> ...`,
                 // and we shouldn't warn about the generics if all the methods
                 // are private (because `T` won't be visible externally).
-                let trait_or_some_public_method = trait_ref.is_some()
-                    || impl_item_refs.iter().any(|impl_item_ref| {
+                let trait_or_some_public_method = of_trait.is_some()
+                    || items.iter().any(|impl_item_ref| {
                         let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                         match impl_item.kind {
                             hir::ImplItemKind::Const(..) | hir::ImplItemKind::Method(..) => {
@@ -1570,9 +1568,9 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                 if !self_contains_private && not_private_trait && trait_or_some_public_method {
                     intravisit::walk_generics(self, g);
 
-                    match *trait_ref {
+                    match of_trait {
                         None => {
-                            for impl_item_ref in impl_item_refs {
+                            for impl_item_ref in items {
                                 // This is where we choose whether to walk down
                                 // further into the impl to check its items. We
                                 // should only walk into public items so that we
@@ -1594,7 +1592,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                                 }
                             }
                         }
-                        Some(ref tr) => {
+                        Some(tr) => {
                             // Any private types in a trait impl fall into three
                             // categories.
                             // 1. mentioned in the trait definition
@@ -1611,7 +1609,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                             intravisit::walk_path(self, &tr.path);
 
                             // Those in 3. are warned with this call.
-                            for impl_item_ref in impl_item_refs {
+                            for impl_item_ref in items {
                                 let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                                 if let hir::ImplItemKind::TyAlias(ref ty) = impl_item.kind {
                                     self.visit_ty(ty);
@@ -1619,11 +1617,11 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
                             }
                         }
                     }
-                } else if trait_ref.is_none() && self_is_public_path {
+                } else if of_trait.is_none() && self_is_public_path {
                     // `impl Public<Private> { ... }`. Any public static
                     // methods will be visible as `Public::foo`.
                     let mut found_pub_static = false;
-                    for impl_item_ref in impl_item_refs {
+                    for impl_item_ref in items {
                         if self.item_is_public(&impl_item_ref.id.hir_id, &impl_item_ref.vis) {
                             let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                             match impl_item_ref.kind {
@@ -1997,12 +1995,12 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
             // Subitems of inherent impls have their own publicity.
             // A trait impl is public when both its type and its trait are public
             // Subitems of trait impls have inherited publicity.
-            hir::ItemKind::Impl(.., ref trait_ref, _, impl_item_refs) => {
+            hir::ItemKind::Impl { ref of_trait, items, .. } => {
                 let impl_vis = ty::Visibility::of_impl(item.hir_id, tcx, &Default::default());
                 self.check(item.hir_id, impl_vis).generics().predicates();
-                for impl_item_ref in impl_item_refs {
+                for impl_item_ref in items {
                     let impl_item = tcx.hir().impl_item(impl_item_ref.id);
-                    let impl_item_vis = if trait_ref.is_none() {
+                    let impl_item_vis = if of_trait.is_none() {
                         min(
                             ty::Visibility::from_hir(&impl_item.vis, item.hir_id, tcx),
                             impl_vis,
index af37e7b5b76ac5132918f256ba415cc0d2197a42..c4cc6b09c736edd4d76353458f70e8fa6eb959d0 100644 (file)
@@ -23,7 +23,6 @@ rustc_expand = { path = "../librustc_expand" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_hir = { path = "../librustc_hir" }
 rustc_metadata = { path = "../librustc_metadata" }
-rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_session = { path = "../librustc_session" }
 rustc_span = { path = "../librustc_span" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
index e8ed64a18702d0259c4540a930d92cf7de9008f0..7ff076268ab820f90ec53fe33dadab7c5831b93b 100644 (file)
@@ -21,7 +21,6 @@
 use rustc::middle::cstore::CrateStore;
 use rustc::ty;
 use rustc_data_structures::sync::Lrc;
-use rustc_error_codes::*;
 use rustc_errors::{struct_span_err, Applicability};
 use rustc_expand::base::SyntaxExtension;
 use rustc_expand::expand::AstFragment;
@@ -815,7 +814,7 @@ fn build_reduced_graph_for_item(&mut self, item: &'b Item) {
             }
 
             // These items do not add names to modules.
-            ItemKind::Impl(..) | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {}
+            ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {}
 
             ItemKind::MacroDef(..) | ItemKind::Mac(_) => unreachable!(),
         }
index f564ea644bdc1c3a3bc32be0999d3f5f4cfcfb9d..696ba0e994c7dbd095481e2c47cdd8c60befc9a1 100644 (file)
@@ -104,7 +104,7 @@ fn visit_item(&mut self, i: &'a Item) {
         // Pick the def data. This need not be unique, but the more
         // information we encapsulate into, the better
         let def_data = match &i.kind {
-            ItemKind::Impl(..) => DefPathData::Impl,
+            ItemKind::Impl { .. } => DefPathData::Impl,
             ItemKind::Mod(..) if i.ident.name == kw::Invalid => {
                 return visit::walk_item(self, i);
             }
index 974206797549906f2e40c5f690353338e037b385..3d4384cabe20460b6a4690888ac869ba00814980 100644 (file)
@@ -8,7 +8,7 @@
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_feature::BUILTIN_ATTRIBUTES;
 use rustc_hir::def::Namespace::{self, *};
-use rustc_hir::def::{self, DefKind, NonMacroAttrKind};
+use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::SourceMap;
 
 use crate::imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
 use crate::path_names_to_string;
-use crate::VisResolutionError;
+use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind};
 use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot};
+use crate::{NameBinding, NameBindingKind, PrivacyError, VisResolutionError};
 use crate::{ParentScope, PathResult, ResolutionError, Resolver, Scope, ScopeSet, Segment};
 
-use rustc_error_codes::*;
-
 type Res = def::Res<ast::NodeId>;
 
 /// A vector of spans and replacements, a message and applicability.
@@ -802,6 +801,163 @@ fn lookup_import_candidates_from_module<FilterFn>(
         }
         false
     }
+
+    fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: bool) -> String {
+        let res = b.res();
+        if b.span.is_dummy() {
+            let add_built_in = match b.res() {
+                // These already contain the "built-in" prefix or look bad with it.
+                Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod => false,
+                _ => true,
+            };
+            let (built_in, from) = if from_prelude {
+                ("", " from prelude")
+            } else if b.is_extern_crate()
+                && !b.is_import()
+                && self.session.opts.externs.get(&ident.as_str()).is_some()
+            {
+                ("", " passed with `--extern`")
+            } else if add_built_in {
+                (" built-in", "")
+            } else {
+                ("", "")
+            };
+
+            let article = if built_in.is_empty() { res.article() } else { "a" };
+            format!(
+                "{a}{built_in} {thing}{from}",
+                a = article,
+                thing = res.descr(),
+                built_in = built_in,
+                from = from
+            )
+        } else {
+            let introduced = if b.is_import() { "imported" } else { "defined" };
+            format!("the {thing} {introduced} here", thing = res.descr(), introduced = introduced)
+        }
+    }
+
+    crate fn report_ambiguity_error(&self, ambiguity_error: &AmbiguityError<'_>) {
+        let AmbiguityError { kind, ident, b1, b2, misc1, misc2 } = *ambiguity_error;
+        let (b1, b2, misc1, misc2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() {
+            // We have to print the span-less alternative first, otherwise formatting looks bad.
+            (b2, b1, misc2, misc1, true)
+        } else {
+            (b1, b2, misc1, misc2, false)
+        };
+
+        let mut err = struct_span_err!(
+            self.session,
+            ident.span,
+            E0659,
+            "`{ident}` is ambiguous ({why})",
+            ident = ident,
+            why = kind.descr()
+        );
+        err.span_label(ident.span, "ambiguous name");
+
+        let mut could_refer_to = |b: &NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| {
+            let what = self.binding_description(b, ident, misc == AmbiguityErrorMisc::FromPrelude);
+            let note_msg = format!(
+                "`{ident}` could{also} refer to {what}",
+                ident = ident,
+                also = also,
+                what = what
+            );
+
+            let thing = b.res().descr();
+            let mut help_msgs = Vec::new();
+            if b.is_glob_import()
+                && (kind == AmbiguityKind::GlobVsGlob
+                    || kind == AmbiguityKind::GlobVsExpanded
+                    || kind == AmbiguityKind::GlobVsOuter && swapped != also.is_empty())
+            {
+                help_msgs.push(format!(
+                    "consider adding an explicit import of \
+                     `{ident}` to disambiguate",
+                    ident = ident
+                ))
+            }
+            if b.is_extern_crate() && ident.span.rust_2018() {
+                help_msgs.push(format!(
+                    "use `::{ident}` to refer to this {thing} unambiguously",
+                    ident = ident,
+                    thing = thing,
+                ))
+            }
+            if misc == AmbiguityErrorMisc::SuggestCrate {
+                help_msgs.push(format!(
+                    "use `crate::{ident}` to refer to this {thing} unambiguously",
+                    ident = ident,
+                    thing = thing,
+                ))
+            } else if misc == AmbiguityErrorMisc::SuggestSelf {
+                help_msgs.push(format!(
+                    "use `self::{ident}` to refer to this {thing} unambiguously",
+                    ident = ident,
+                    thing = thing,
+                ))
+            }
+
+            err.span_note(b.span, &note_msg);
+            for (i, help_msg) in help_msgs.iter().enumerate() {
+                let or = if i == 0 { "" } else { "or " };
+                err.help(&format!("{}{}", or, help_msg));
+            }
+        };
+
+        could_refer_to(b1, misc1, "");
+        could_refer_to(b2, misc2, " also");
+        err.emit();
+    }
+
+    crate fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) {
+        let PrivacyError { ident, binding, .. } = *privacy_error;
+        let session = &self.session;
+        let mk_struct_span_error = |is_constructor| {
+            let mut descr = binding.res().descr().to_string();
+            if is_constructor {
+                descr += " constructor";
+            }
+            if binding.is_import() {
+                descr += " import";
+            }
+
+            let mut err =
+                struct_span_err!(session, ident.span, E0603, "{} `{}` is private", descr, ident);
+
+            err.span_label(ident.span, &format!("this {} is private", descr));
+            err.span_note(
+                session.source_map().def_span(binding.span),
+                &format!("the {} `{}` is defined here", descr, ident),
+            );
+
+            err
+        };
+
+        let mut err = if let NameBindingKind::Res(
+            Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id),
+            _,
+        ) = binding.kind
+        {
+            let def_id = (&*self).parent(ctor_def_id).expect("no parent for a constructor");
+            if let Some(fields) = self.field_names.get(&def_id) {
+                let mut err = mk_struct_span_error(true);
+                let first_field = fields.first().expect("empty field list in the map");
+                err.span_label(
+                    fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)),
+                    "a constructor is private if any of the fields is private",
+                );
+                err
+            } else {
+                mk_struct_span_error(false)
+            }
+        } else {
+            mk_struct_span_error(false)
+        };
+
+        err.emit();
+    }
 }
 
 impl<'a, 'b> ImportResolver<'a, 'b> {
index 5bd10303162b295711ce9e076d04b7f22a632d84..55ce51e0ff057508c783226910adebf394c653b1 100644 (file)
@@ -29,8 +29,6 @@
 use syntax::unwrap_or;
 use syntax::util::lev_distance::find_best_match_for_name;
 
-use rustc_error_codes::*;
-
 use log::*;
 
 use std::cell::Cell;
@@ -319,7 +317,11 @@ impl<'a> Resolver<'a> {
                        // Remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE`
                        !(self.last_import_segment && binding.is_extern_crate())
                         {
-                            self.privacy_errors.push(PrivacyError(path_span, ident, binding));
+                            self.privacy_errors.push(PrivacyError {
+                                ident,
+                                binding,
+                                dedup_span: path_span,
+                            });
                         }
 
                         Ok(binding)
index defca4944bcd819fac9dbadbf9120b8fbeb36ba9..5e08ac8e2c38a869724132bb5d89667b38255605 100644 (file)
@@ -31,8 +31,6 @@
 use std::collections::BTreeSet;
 use std::mem::replace;
 
-use rustc_error_codes::*;
-
 mod diagnostics;
 
 type Res = def::Res<NodeId>;
@@ -797,14 +795,14 @@ fn resolve_item(&mut self, item: &Item) {
                 self.resolve_adt(item, generics);
             }
 
-            ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) => {
-                self.resolve_implementation(
-                    generics,
-                    opt_trait_ref,
-                    &self_type,
-                    item.id,
-                    impl_items,
-                )
+            ItemKind::Impl {
+                ref generics,
+                ref of_trait,
+                ref self_ty,
+                items: ref impl_items,
+                ..
+            } => {
+                self.resolve_implementation(generics, of_trait, &self_ty, item.id, impl_items);
             }
 
             ItemKind::Trait(.., ref generics, ref bounds, ref trait_items) => {
index 151f3e834e5de83c59307d6630a0722b9a3db2e8..6a98c9e59a9ce250ebcf7c8f0c88787b97f5b5ec 100644 (file)
@@ -6,7 +6,6 @@
 
 use rustc::session::config::nightly_options;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_error_codes::*;
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, DefKind};
index 8d5afb194a17500ce953e892931a06538dc388a9..5d132191f9208b86a783eb13b4610c4771ddaf86 100644 (file)
@@ -2,12 +2,9 @@
 //!
 //! Module structure of the crate is built here.
 //! Paths in macros, imports, expressions, types, patterns are resolved here.
-//! Label names are resolved here as well.
+//! Label and lifetime names are resolved here as well.
 //!
 //! Type-relative name resolution (methods, fields, associated items) happens in `librustc_typeck`.
-//! Lifetime names are resolved in `librustc/middle/resolve_lifetime.rs`.
-
-// ignore-tidy-filelength
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(bool_to_option)]
@@ -33,7 +30,7 @@
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_expand::base::SyntaxExtension;
 use rustc_hir::def::Namespace::*;
-use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PartialRes};
+use rustc_hir::def::{self, CtorOf, DefKind, NonMacroAttrKind, PartialRes};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::PrimTy::{self, Bool, Char, Float, Int, Str, Uint};
 use rustc_hir::{GlobMap, TraitMap};
@@ -64,8 +61,6 @@
 use late::{HasGenericParams, PathSource, Rib, RibKind::*};
 use macros::{LegacyBinding, LegacyScope};
 
-use rustc_error_codes::*;
-
 type Res = def::Res<NodeId>;
 
 mod build_reduced_graph;
@@ -604,7 +599,11 @@ fn is_import(&self) -> bool {
     }
 }
 
-struct PrivacyError<'a>(Span, Ident, &'a NameBinding<'a>);
+struct PrivacyError<'a> {
+    ident: Ident,
+    binding: &'a NameBinding<'a>,
+    dedup_span: Span,
+}
 
 struct UseError<'a> {
     err: DiagnosticBuilder<'a>,
@@ -2446,115 +2445,6 @@ fn disambiguate_legacy_vs_modern(
         }
     }
 
-    fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: bool) -> String {
-        let res = b.res();
-        if b.span.is_dummy() {
-            let add_built_in = match b.res() {
-                // These already contain the "built-in" prefix or look bad with it.
-                Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod => false,
-                _ => true,
-            };
-            let (built_in, from) = if from_prelude {
-                ("", " from prelude")
-            } else if b.is_extern_crate()
-                && !b.is_import()
-                && self.session.opts.externs.get(&ident.as_str()).is_some()
-            {
-                ("", " passed with `--extern`")
-            } else if add_built_in {
-                (" built-in", "")
-            } else {
-                ("", "")
-            };
-
-            let article = if built_in.is_empty() { res.article() } else { "a" };
-            format!(
-                "{a}{built_in} {thing}{from}",
-                a = article,
-                thing = res.descr(),
-                built_in = built_in,
-                from = from
-            )
-        } else {
-            let introduced = if b.is_import() { "imported" } else { "defined" };
-            format!("the {thing} {introduced} here", thing = res.descr(), introduced = introduced)
-        }
-    }
-
-    fn report_ambiguity_error(&self, ambiguity_error: &AmbiguityError<'_>) {
-        let AmbiguityError { kind, ident, b1, b2, misc1, misc2 } = *ambiguity_error;
-        let (b1, b2, misc1, misc2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() {
-            // We have to print the span-less alternative first, otherwise formatting looks bad.
-            (b2, b1, misc2, misc1, true)
-        } else {
-            (b1, b2, misc1, misc2, false)
-        };
-
-        let mut err = struct_span_err!(
-            self.session,
-            ident.span,
-            E0659,
-            "`{ident}` is ambiguous ({why})",
-            ident = ident,
-            why = kind.descr()
-        );
-        err.span_label(ident.span, "ambiguous name");
-
-        let mut could_refer_to = |b: &NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| {
-            let what = self.binding_description(b, ident, misc == AmbiguityErrorMisc::FromPrelude);
-            let note_msg = format!(
-                "`{ident}` could{also} refer to {what}",
-                ident = ident,
-                also = also,
-                what = what
-            );
-
-            let thing = b.res().descr();
-            let mut help_msgs = Vec::new();
-            if b.is_glob_import()
-                && (kind == AmbiguityKind::GlobVsGlob
-                    || kind == AmbiguityKind::GlobVsExpanded
-                    || kind == AmbiguityKind::GlobVsOuter && swapped != also.is_empty())
-            {
-                help_msgs.push(format!(
-                    "consider adding an explicit import of \
-                     `{ident}` to disambiguate",
-                    ident = ident
-                ))
-            }
-            if b.is_extern_crate() && ident.span.rust_2018() {
-                help_msgs.push(format!(
-                    "use `::{ident}` to refer to this {thing} unambiguously",
-                    ident = ident,
-                    thing = thing,
-                ))
-            }
-            if misc == AmbiguityErrorMisc::SuggestCrate {
-                help_msgs.push(format!(
-                    "use `crate::{ident}` to refer to this {thing} unambiguously",
-                    ident = ident,
-                    thing = thing,
-                ))
-            } else if misc == AmbiguityErrorMisc::SuggestSelf {
-                help_msgs.push(format!(
-                    "use `self::{ident}` to refer to this {thing} unambiguously",
-                    ident = ident,
-                    thing = thing,
-                ))
-            }
-
-            err.span_note(b.span, &note_msg);
-            for (i, help_msg) in help_msgs.iter().enumerate() {
-                let or = if i == 0 { "" } else { "or " };
-                err.help(&format!("{}{}", or, help_msg));
-            }
-        };
-
-        could_refer_to(b1, misc1, "");
-        could_refer_to(b2, misc2, " also");
-        err.emit();
-    }
-
     fn report_errors(&mut self, krate: &Crate) {
         self.report_with_use_injections(krate);
 
@@ -2575,43 +2465,9 @@ fn report_errors(&mut self, krate: &Crate) {
         }
 
         let mut reported_spans = FxHashSet::default();
-        for &PrivacyError(dedup_span, ident, binding) in &self.privacy_errors {
-            if reported_spans.insert(dedup_span) {
-                let session = &self.session;
-                let mk_struct_span_error = |is_constructor| {
-                    struct_span_err!(
-                        session,
-                        ident.span,
-                        E0603,
-                        "{}{} `{}` is private",
-                        binding.res().descr(),
-                        if is_constructor { " constructor" } else { "" },
-                        ident.name,
-                    )
-                };
-
-                let mut err = if let NameBindingKind::Res(
-                    Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id),
-                    _,
-                ) = binding.kind
-                {
-                    let def_id = (&*self).parent(ctor_def_id).expect("no parent for a constructor");
-                    if let Some(fields) = self.field_names.get(&def_id) {
-                        let mut err = mk_struct_span_error(true);
-                        let first_field = fields.first().expect("empty field list in the map");
-                        err.span_label(
-                            fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)),
-                            "a constructor is private if any of the fields is private",
-                        );
-                        err
-                    } else {
-                        mk_struct_span_error(false)
-                    }
-                } else {
-                    mk_struct_span_error(false)
-                };
-
-                err.emit();
+        for error in &self.privacy_errors {
+            if reported_spans.insert(error.dedup_span) {
+                self.report_privacy_error(error);
             }
         }
     }
index d6143eec73c00f3e7d22d16c4443fd4754b1a37d..a2ca80cf5f30a9e48bb0a94ab64fcc7f9e371583 100644 (file)
@@ -30,8 +30,6 @@
 
 use log::debug;
 
-use rustc_error_codes::*;
-
 // This counts the no of times a lifetime is used
 #[derive(Clone, Copy, Debug)]
 pub enum LifetimeUseSet<'tcx> {
@@ -416,11 +414,11 @@ fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
             | hir::ItemKind::Union(_, ref generics)
             | hir::ItemKind::Trait(_, _, ref generics, ..)
             | hir::ItemKind::TraitAlias(ref generics, ..)
-            | hir::ItemKind::Impl(_, _, _, ref generics, ..) => {
+            | hir::ItemKind::Impl { ref generics, .. } => {
                 // Impls permit `'_` to be used and it is equivalent to "some fresh lifetime name".
                 // This is not true for other kinds of items.x
                 let track_lifetime_uses = match item.kind {
-                    hir::ItemKind::Impl(..) => true,
+                    hir::ItemKind::Impl { .. } => true,
                     _ => false,
                 };
                 // These kinds of items have only early-bound lifetime parameters.
@@ -1638,7 +1636,7 @@ fn visit_early_late<F>(
             }
             match parent.kind {
                 hir::ItemKind::Trait(_, _, ref generics, ..)
-                | hir::ItemKind::Impl(_, _, _, ref generics, ..) => {
+                | hir::ItemKind::Impl { ref generics, .. } => {
                     index += generics.params.len() as u32;
                 }
                 _ => {}
@@ -2067,12 +2065,12 @@ fn visit_fn_like_elision(
             }
 
             Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Method(_, body), .. }) => {
-                if let hir::ItemKind::Impl(.., ref self_ty, ref impl_items) =
+                if let hir::ItemKind::Impl { ref self_ty, ref items, .. } =
                     self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind
                 {
                     impl_self = Some(self_ty);
                     assoc_item_kind =
-                        impl_items.iter().find(|ii| ii.id.hir_id == parent).map(|ii| ii.kind);
+                        items.iter().find(|ii| ii.id.hir_id == parent).map(|ii| ii.kind);
                 }
                 Some(body)
             }
index 2f2ba560fa20a8d9d814f1e9b851de10ef0d1eca..d252fc542c325ca4bc1553a5695cf48b85617e51 100644 (file)
@@ -1300,8 +1300,8 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                 self.process_struct(item, def, ty_params)
             }
             Enum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
-            Impl(.., ref ty_params, ref trait_ref, ref typ, ref impl_items) => {
-                self.process_impl(item, ty_params, trait_ref, &typ, impl_items)
+            Impl { ref generics, ref of_trait, ref self_ty, ref items, .. } => {
+                self.process_impl(item, generics, of_trait, &self_ty, items)
             }
             Trait(_, _, ref generics, ref trait_refs, ref methods) => {
                 self.process_trait(item, generics, trait_refs, methods)
index c3221d925bc3b54b9a7271e5e982bb5254d1f621..537fe198a0c39f944cbd17924e644bf8c455d14d 100644 (file)
@@ -305,8 +305,8 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     attributes: lower_attributes(item.attrs.clone(), self),
                 }))
             }
-            ast::ItemKind::Impl(.., ref trait_ref, ref typ, ref impls) => {
-                if let ast::TyKind::Path(None, ref path) = typ.kind {
+            ast::ItemKind::Impl { ref of_trait, ref self_ty, ref items, .. } => {
+                if let ast::TyKind::Path(None, ref path) = self_ty.kind {
                     // Common case impl for a struct or something basic.
                     if generated_code(path.span) {
                         return None;
@@ -317,14 +317,14 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     let impl_id = self.next_impl_id();
                     let span = self.span_from_span(sub_span);
 
-                    let type_data = self.lookup_def_id(typ.id);
+                    let type_data = self.lookup_def_id(self_ty.id);
                     type_data.map(|type_data| {
                         Data::RelationData(
                             Relation {
                                 kind: RelationKind::Impl { id: impl_id },
                                 span: span.clone(),
                                 from: id_from_def_id(type_data),
-                                to: trait_ref
+                                to: of_trait
                                     .as_ref()
                                     .and_then(|t| self.lookup_def_id(t.ref_id))
                                     .map(id_from_def_id)
@@ -332,14 +332,14 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                             },
                             Impl {
                                 id: impl_id,
-                                kind: match *trait_ref {
+                                kind: match *of_trait {
                                     Some(_) => ImplKind::Direct,
                                     None => ImplKind::Inherent,
                                 },
                                 span: span,
                                 value: String::new(),
                                 parent: None,
-                                children: impls
+                                children: items
                                     .iter()
                                     .map(|i| id_from_node_id(i.id, self))
                                     .collect(),
@@ -405,9 +405,9 @@ pub fn get_method_data(&self, id: ast::NodeId, ident: ast::Ident, span: Span) ->
         {
             Some(impl_id) => match self.tcx.hir().get_if_local(impl_id) {
                 Some(Node::Item(item)) => match item.kind {
-                    hir::ItemKind::Impl(.., ref ty, _) => {
+                    hir::ItemKind::Impl { ref self_ty, .. } => {
                         let mut qualname = String::from("<");
-                        qualname.push_str(&self.tcx.hir().hir_to_pretty_string(ty.hir_id));
+                        qualname.push_str(&self.tcx.hir().hir_to_pretty_string(self_ty.hir_id));
 
                         let trait_id = self.tcx.trait_id_of_impl(impl_id);
                         let mut decl_id = None;
index e7b86cfba4f7d58c716f8cc915a58b4957ef4a53..779d3f55018d56f88980ead8dac6f8cbe25fa11f 100644 (file)
@@ -482,15 +482,15 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
 
                 Ok(sig)
             }
-            ast::ItemKind::Impl(
+            ast::ItemKind::Impl {
                 unsafety,
                 polarity,
                 defaultness,
                 ref generics,
-                ref opt_trait,
-                ref ty,
-                _,
-            ) => {
+                ref of_trait,
+                ref self_ty,
+                items: _,
+            } => {
                 let mut text = String::new();
                 if let ast::Defaultness::Default = defaultness {
                     text.push_str("default ");
@@ -505,7 +505,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
 
                 text.push(' ');
 
-                let trait_sig = if let Some(ref t) = *opt_trait {
+                let trait_sig = if let Some(ref t) = *of_trait {
                     if polarity == ast::ImplPolarity::Negative {
                         text.push('!');
                     }
@@ -517,7 +517,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
                     text_sig(String::new())
                 };
 
-                let ty_sig = ty.make(offset + text.len(), id, scx)?;
+                let ty_sig = self_ty.make(offset + text.len(), id, scx)?;
                 text.push_str(&ty_sig.text);
 
                 text.push_str(" {}");
index 377ea141ed57c6678162534a7e0515ebeb0600f0..47c23bc4dcf98c4f074ab88106323720cf9a4d16 100644 (file)
@@ -10,7 +10,6 @@ path = "lib.rs"
 
 [dependencies]
 log = "0.4"
-rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_feature = { path = "../librustc_feature" }
 rustc_target = { path = "../librustc_target" }
index 4b5736adc17c3f0d4de30fed1499ece9bae4792a..2a0ed27b63b08f7c23f56ab2069a2265b0652fb7 100644 (file)
@@ -923,8 +923,12 @@ fn parse_symbol_mangling_version(
     self_profile: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
         parse_switch_with_opt_path, [UNTRACKED],
         "run the self profiler and output the raw event data"),
+    // keep this in sync with the event filter names in librustc_data_structures/profiling.rs
     self_profile_events: Option<Vec<String>> = (None, parse_opt_comma_list, [UNTRACKED],
-        "specifies which kinds of events get recorded by the self profiler"),
+        "specifies which kinds of events get recorded by the self profiler;
+        for example: `-Z self-profile-events=default,query-keys`
+        all options: none, all, default, generic-activity, query-provider, query-cache-hit
+                     query-blocked, incr-cache-load, query-keys"),
     emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED],
         "emits a section containing stack size metadata"),
     plt: Option<bool> = (None, parse_opt_bool, [TRACKED],
index a98cf929095ead3aa73ea261caace287291f0e14..72c68fcb244c95e65b7b463cac311e4cc5f44f72 100644 (file)
@@ -6,7 +6,6 @@
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{Lock, Lrc, Once};
-use rustc_error_codes::E0658;
 use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler};
 use rustc_errors::{error_code, Applicability, DiagnosticBuilder};
 use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures};
index fb5fcf4a8303badacd9ae0bdc69ec90b8607e7bb..9c7c0f0c8b0eca79346dd05357cf2fede430baa2 100644 (file)
@@ -473,20 +473,23 @@ pub fn is_multiline(&self, sp: Span) -> bool {
         lo.line != hi.line
     }
 
-    pub fn span_to_lines(&self, sp: Span) -> FileLinesResult {
-        debug!("span_to_lines(sp={:?})", sp);
-
+    pub fn is_valid_span(&self, sp: Span) -> Result<(Loc, Loc), SpanLinesError> {
         let lo = self.lookup_char_pos(sp.lo());
         debug!("span_to_lines: lo={:?}", lo);
         let hi = self.lookup_char_pos(sp.hi());
         debug!("span_to_lines: hi={:?}", hi);
-
         if lo.file.start_pos != hi.file.start_pos {
             return Err(SpanLinesError::DistinctSources(DistinctSources {
                 begin: (lo.file.name.clone(), lo.file.start_pos),
                 end: (hi.file.name.clone(), hi.file.start_pos),
             }));
         }
+        Ok((lo, hi))
+    }
+
+    pub fn span_to_lines(&self, sp: Span) -> FileLinesResult {
+        debug!("span_to_lines(sp={:?})", sp);
+        let (lo, hi) = self.is_valid_span(sp)?;
         assert!(hi.line >= lo.line);
 
         let mut lines = Vec::with_capacity(hi.line - lo.line + 1);
index 17413e77f900719b17575df8da916d186a8268dc..84c6d720b8e00c5e58d36075fb671f16cf7a251a 100644 (file)
@@ -11,7 +11,7 @@
 #![feature(box_syntax)]
 #![feature(bool_to_option)]
 #![feature(nll)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 
 #[macro_use]
 extern crate log;
index 4b10b08ddd94cd6c5f1ab370b3cc16e2cd76e7ff..0b18352df330764c0d37dd468494b300e8e3c1df 100644 (file)
@@ -400,7 +400,7 @@ fn u_canonicalize_goal(
         &mut self,
         value: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>,
     ) -> (Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>, UniverseMap) {
-        (value.clone(), UniverseMap)
+        (*value, UniverseMap)
     }
 
     fn invert_goal(
index 315efe5cf71e75b5f52a81f00216020e6b4d6b6f..7df27e67d5b1c2a64adcc75942be2295cf512d99 100644 (file)
@@ -195,8 +195,8 @@ enum NodeKind {
         },
 
         Node::Item(item) => match item.kind {
-            ItemKind::Impl(.., Some(..), _, _) => NodeKind::TraitImpl,
-            ItemKind::Impl(.., None, _, _) => NodeKind::InherentImpl,
+            ItemKind::Impl { of_trait: Some(_), .. } => NodeKind::TraitImpl,
+            ItemKind::Impl { of_trait: None, .. } => NodeKind::InherentImpl,
             ItemKind::Fn(..) => NodeKind::Fn,
             _ => NodeKind::Other,
         },
index 2548d2cff976611b1b056f8f4806932ae8e078ba..e5ec98743e0aeeaf989f23974f7376065031f461 100644 (file)
@@ -8,7 +8,7 @@
 #![feature(bool_to_option)]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![recursion_limit = "256"]
 
 #[macro_use]
index fc8beb67e4adade93ad0985adf7944647ef476f0..d47e54366b55018b386d3324d7c66f7ca3af73b1 100644 (file)
@@ -128,8 +128,8 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
     let parent_def_id = tcx.hir().local_def_id(parent_id);
     let parent_item = tcx.hir().expect_item(parent_id);
     match parent_item.kind {
-        hir::ItemKind::Impl(.., ref impl_item_refs) => {
-            if let Some(impl_item_ref) = impl_item_refs.iter().find(|i| i.id.hir_id == id) {
+        hir::ItemKind::Impl { ref items, .. } => {
+            if let Some(impl_item_ref) = items.iter().find(|i| i.id.hir_id == id) {
                 let assoc_item =
                     associated_item_from_impl_item_ref(tcx, parent_def_id, impl_item_ref);
                 debug_assert_eq!(assoc_item.def_id, def_id);
@@ -194,8 +194,8 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
                 .map(|trait_item_ref| trait_item_ref.id)
                 .map(|id| tcx.hir().local_def_id(id.hir_id)),
         ),
-        hir::ItemKind::Impl(.., ref impl_item_refs) => tcx.arena.alloc_from_iter(
-            impl_item_refs
+        hir::ItemKind::Impl { ref items, .. } => tcx.arena.alloc_from_iter(
+            items
                 .iter()
                 .map(|impl_item_ref| impl_item_ref.id)
                 .map(|id| tcx.hir().local_def_id(id.hir_id)),
index 84e5f56d9c208456ee22139fc78073a91a8fa71a..4b27d86dd02a741380e74f1ab36ce598df884fd0 100644 (file)
@@ -22,4 +22,3 @@ smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 syntax = { path = "../libsyntax" }
 rustc_span = { path = "../librustc_span" }
 rustc_index = { path = "../librustc_index" }
-rustc_error_codes = { path = "../librustc_error_codes" }
index a3be264ddc12837e222c0287fe6c0c9698e5d147..047c14cfbcff7fcf27c589fd30fabeca638ea3dc 100644 (file)
@@ -39,7 +39,6 @@
 use std::slice;
 
 use rustc::mir::interpret::LitToConstInput;
-use rustc_error_codes::*;
 
 #[derive(Debug)]
 pub struct PathSeg(pub DefId, pub usize);
@@ -1320,10 +1319,10 @@ fn add_predicates_for_ast_type_binding(
                 // those that do.
                 self.one_bound_for_assoc_type(
                     || traits::supertraits(tcx, trait_ref),
-                    &trait_ref.print_only_trait_path().to_string(),
+                    || trait_ref.print_only_trait_path().to_string(),
                     binding.item_name,
                     path_span,
-                    match binding.kind {
+                    || match binding.kind {
                         ConvertedBindingKind::Equality(ty) => Some(ty.to_string()),
                         _ => None,
                     },
@@ -1880,10 +1879,10 @@ fn find_bound_for_assoc_item(
                     predicates.iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref()),
                 )
             },
-            &param_name.as_str(),
+            || param_name.to_string(),
             assoc_name,
             span,
-            None,
+            || None,
         )
     }
 
@@ -1892,10 +1891,10 @@ fn find_bound_for_assoc_item(
     fn one_bound_for_assoc_type<I>(
         &self,
         all_candidates: impl Fn() -> I,
-        ty_param_name: &str,
+        ty_param_name: impl Fn() -> String,
         assoc_name: ast::Ident,
         span: Span,
-        is_equality: Option<String>,
+        is_equality: impl Fn() -> Option<String>,
     ) -> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
     where
         I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
@@ -1908,7 +1907,7 @@ fn one_bound_for_assoc_type<I>(
             None => {
                 self.complain_about_assoc_type_not_found(
                     all_candidates,
-                    ty_param_name,
+                    &ty_param_name(),
                     assoc_name,
                     span,
                 );
@@ -1921,6 +1920,7 @@ fn one_bound_for_assoc_type<I>(
         if let Some(bound2) = matching_candidates.next() {
             debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2);
 
+            let is_equality = is_equality();
             let bounds = iter::once(bound).chain(iter::once(bound2)).chain(matching_candidates);
             let mut err = if is_equality.is_some() {
                 // More specific Error Index entry.
@@ -1930,7 +1930,7 @@ fn one_bound_for_assoc_type<I>(
                     E0222,
                     "ambiguous associated type `{}` in bounds of `{}`",
                     assoc_name,
-                    ty_param_name
+                    ty_param_name()
                 )
             } else {
                 struct_span_err!(
@@ -1939,7 +1939,7 @@ fn one_bound_for_assoc_type<I>(
                     E0221,
                     "ambiguous associated type `{}` in bounds of `{}`",
                     assoc_name,
-                    ty_param_name
+                    ty_param_name()
                 )
             };
             err.span_label(span, format!("ambiguous associated type `{}`", assoc_name));
@@ -1977,7 +1977,7 @@ fn one_bound_for_assoc_type<I>(
                             "use fully qualified syntax to disambiguate",
                             format!(
                                 "<{} as {}>::{}",
-                                ty_param_name,
+                                ty_param_name(),
                                 bound.print_only_trait_path(),
                                 assoc_name,
                             ),
@@ -1987,7 +1987,7 @@ fn one_bound_for_assoc_type<I>(
                 } else {
                     err.note(&format!(
                         "associated type `{}` could derive from `{}`",
-                        ty_param_name,
+                        ty_param_name(),
                         bound.print_only_trait_path(),
                     ));
                 }
@@ -1996,7 +1996,7 @@ fn one_bound_for_assoc_type<I>(
                 err.help(&format!(
                     "consider introducing a new type parameter `T` and adding `where` constraints:\
                      \n    where\n        T: {},\n{}",
-                    ty_param_name,
+                    ty_param_name(),
                     where_bounds.join(",\n"),
                 ));
             }
@@ -2110,10 +2110,10 @@ pub fn associated_path_to_ty(
 
                 self.one_bound_for_assoc_type(
                     || traits::supertraits(tcx, ty::Binder::bind(trait_ref)),
-                    "Self",
+                    || "Self".to_string(),
                     assoc_ident,
                     span,
-                    None,
+                    || None,
                 )?
             }
             (&ty::Param(_), Res::SelfTy(Some(param_did), None))
index 8d6b74c3015c93772984a84e1e7e0b79d73489db..3ea5de9a8375dce87632cdcf572b319d90a35fdb 100644 (file)
@@ -13,8 +13,6 @@
 use rustc_span::Span;
 use syntax::ast::Ident;
 
-use rustc_error_codes::*;
-
 use std::iter;
 
 #[derive(Copy, Clone, Debug)]
index 58f407b89027851a9211630cfe4ae4d6cc2794b5..b33cc52b238e3bf668a46dea59a9a3ab961d156c 100644 (file)
@@ -8,7 +8,6 @@
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::{infer, traits};
-use rustc_error_codes::*;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::Res;
index cbbfe2d6278957a13d6ce25c1d76a4adeaa3835b..d254a84df72ce5b9264398ea352ccc02f0a71786 100644 (file)
@@ -49,8 +49,6 @@
 use rustc_span::Span;
 use syntax::ast;
 
-use rustc_error_codes::*;
-
 /// Reifies a cast check to be checked once we have full type information for
 /// a function context.
 pub struct CastCheck<'tcx> {
index 6bb7f4995b6ec54a121311125144779fb130535f..084e6c8d083c5be9999ec2f02e17d1dfc1ab238b 100644 (file)
@@ -175,7 +175,7 @@ fn deduce_expectations_from_expected_type(
             }
             ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),
             ty::FnPtr(sig) => {
-                let expected_sig = ExpectedSig { cause_span: None, sig: sig.skip_binder().clone() };
+                let expected_sig = ExpectedSig { cause_span: None, sig: *sig.skip_binder() };
                 (Some(expected_sig), Some(ty::ClosureKind::Fn))
             }
             _ => (None, None),
index 1afb703ca1506818d6b938f1fb1a13ad1fc9135c..8c8e0642dffcefebe832494a7901a164d587951a 100644 (file)
 //! sort of a minor point so I've opted to leave it for later -- after all,
 //! we may want to adjust precisely when coercions occur.
 
+use crate::astconv::AstConv;
 use crate::check::{FnCtxt, Needs};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::infer::{Coercion, InferOk, InferResult};
 use rustc::session::parse::feature_err;
+use rustc::traits::object_safety_violations;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode};
 use rustc::ty::adjustment::{
     Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast,
 use rustc::ty::relate::RelateResult;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty, TypeAndMut};
-use rustc_error_codes::*;
 use rustc_errors::{struct_span_err, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_span;
 use rustc_span::symbol::sym;
+use rustc_span::{self, Span};
 use rustc_target::spec::abi::Abi;
 use smallvec::{smallvec, SmallVec};
 use std::ops::Deref;
@@ -1222,6 +1223,7 @@ fn coerce_inner<'a>(
                 };
 
                 let mut err;
+                let mut unsized_return = false;
                 match cause.code {
                     ObligationCauseCode::ReturnNoExpression => {
                         err = struct_span_err!(
@@ -1243,6 +1245,9 @@ fn coerce_inner<'a>(
                             parent_id,
                             expression.map(|expr| (expr, blk_id)),
                         );
+                        if !fcx.tcx.features().unsized_locals {
+                            unsized_return = self.is_return_ty_unsized(fcx, blk_id);
+                        }
                     }
                     ObligationCauseCode::ReturnValue(id) => {
                         err = self.report_return_mismatched_types(
@@ -1254,6 +1259,10 @@ fn coerce_inner<'a>(
                             id,
                             None,
                         );
+                        if !fcx.tcx.features().unsized_locals {
+                            let id = fcx.tcx.hir().get_parent_node(id);
+                            unsized_return = self.is_return_ty_unsized(fcx, id);
+                        }
                     }
                     _ => {
                         err = fcx.report_mismatched_types(cause, expected, found, coercion_error);
@@ -1282,7 +1291,7 @@ fn coerce_inner<'a>(
                     .filter(|e| fcx.is_assign_to_bool(e, self.expected_ty()))
                     .is_some();
 
-                err.emit_unless(assign_to_bool);
+                err.emit_unless(assign_to_bool || unsized_return);
 
                 self.final_ty = Some(fcx.tcx.types.err);
             }
@@ -1302,7 +1311,7 @@ fn report_return_mismatched_types<'a>(
         let mut err = fcx.report_mismatched_types(cause, expected, found, ty_err);
 
         let mut pointing_at_return_type = false;
-        let mut return_sp = None;
+        let mut fn_output = None;
 
         // Verify that this is a tail expression of a function, otherwise the
         // label pointing out the cause for the type coercion will be wrong
@@ -1339,19 +1348,98 @@ fn report_return_mismatched_types<'a>(
                 );
             }
             if !pointing_at_return_type {
-                return_sp = Some(fn_decl.output.span()); // `impl Trait` return type
+                fn_output = Some(&fn_decl.output); // `impl Trait` return type
             }
         }
-        if let (Some(sp), Some(return_sp)) = (fcx.ret_coercion_span.borrow().as_ref(), return_sp) {
-            err.span_label(return_sp, "expected because this return type...");
-            err.span_label( *sp, format!(
-                "...is found to be `{}` here",
-                fcx.resolve_vars_with_obligations(expected),
-            ));
+        if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.borrow().as_ref(), fn_output) {
+            self.add_impl_trait_explanation(&mut err, fcx, expected, *sp, fn_output);
         }
         err
     }
 
+    fn add_impl_trait_explanation<'a>(
+        &self,
+        err: &mut DiagnosticBuilder<'a>,
+        fcx: &FnCtxt<'a, 'tcx>,
+        expected: Ty<'tcx>,
+        sp: Span,
+        fn_output: &hir::FunctionRetTy<'_>,
+    ) {
+        let return_sp = fn_output.span();
+        err.span_label(return_sp, "expected because this return type...");
+        err.span_label(
+            sp,
+            format!("...is found to be `{}` here", fcx.resolve_vars_with_obligations(expected)),
+        );
+        let impl_trait_msg = "for information on `impl Trait`, see \
+                <https://doc.rust-lang.org/book/ch10-02-traits.html\
+                #returning-types-that-implement-traits>";
+        let trait_obj_msg = "for information on trait objects, see \
+                <https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
+                #using-trait-objects-that-allow-for-values-of-different-types>";
+        err.note("to return `impl Trait`, all returned values must be of the same type");
+        err.note(impl_trait_msg);
+        let snippet = fcx
+            .tcx
+            .sess
+            .source_map()
+            .span_to_snippet(return_sp)
+            .unwrap_or_else(|_| "dyn Trait".to_string());
+        let mut snippet_iter = snippet.split_whitespace();
+        let has_impl = snippet_iter.next().map_or(false, |s| s == "impl");
+        // Only suggest `Box<dyn Trait>` if `Trait` in `impl Trait` is object safe.
+        let mut is_object_safe = false;
+        if let hir::FunctionRetTy::Return(ty) = fn_output {
+            // Get the return type.
+            if let hir::TyKind::Def(..) = ty.kind {
+                let ty = AstConv::ast_ty_to_ty(fcx, ty);
+                // Get the `impl Trait`'s `DefId`.
+                if let ty::Opaque(def_id, _) = ty.kind {
+                    let hir_id = fcx.tcx.hir().as_local_hir_id(def_id).unwrap();
+                    // Get the `impl Trait`'s `Item` so that we can get its trait bounds and
+                    // get the `Trait`'s `DefId`.
+                    if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }) =
+                        fcx.tcx.hir().expect_item(hir_id).kind
+                    {
+                        // Are of this `impl Trait`'s traits object safe?
+                        is_object_safe = bounds.iter().all(|bound| {
+                            bound.trait_def_id().map_or(false, |def_id| {
+                                object_safety_violations(fcx.tcx, def_id).is_empty()
+                            })
+                        })
+                    }
+                }
+            }
+        };
+        if has_impl {
+            if is_object_safe {
+                err.help(&format!(
+                    "you can instead return a boxed trait object using `Box<dyn {}>`",
+                    &snippet[5..]
+                ));
+            } else {
+                err.help(&format!(
+                    "if the trait `{}` were object safe, you could return a boxed trait object",
+                    &snippet[5..]
+                ));
+            }
+            err.note(trait_obj_msg);
+        }
+        err.help("alternatively, create a new `enum` with a variant for each returned type");
+    }
+
+    fn is_return_ty_unsized(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool {
+        if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id) {
+            if let hir::FunctionRetTy::Return(ty) = fn_decl.output {
+                let ty = AstConv::ast_ty_to_ty(fcx, ty);
+                if let ty::Dynamic(..) = ty.kind {
+                    return true;
+                }
+            }
+        }
+        false
+    }
+
     pub fn complete<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Ty<'tcx> {
         if let Some(final_ty) = self.final_ty {
             final_ty
index c35661ac649fc8e70e2d017c2929fcdf8bb7ac6f..414f80d84b672bc9bc87022e96391b3ae88ee1e6 100644 (file)
@@ -15,8 +15,6 @@
 
 use super::{potentially_plural_count, FnCtxt, Inherited};
 
-use rustc_error_codes::*;
-
 /// Checks that a method from an impl conforms to the signature of
 /// the same method as declared in the trait.
 ///
index 88e7a265ebbcf52ce1d8f3db502ed6b1a0ced97a..f4aa53a5a938998e53e832403a5abe1663cdf2fe 100644 (file)
@@ -14,8 +14,6 @@
 
 use rustc_span::Span;
 
-use rustc_error_codes::*;
-
 /// This function confirms that the `Drop` implementation identified by
 /// `drop_impl_did` is not any more specialized than the type it is
 /// attached to (Issue #8142).
index 35342de59a08254effd5be747367d83b03c02139..201a09fdc63faa2ba2beeee7a676ed004c73b7d3 100644 (file)
@@ -38,8 +38,6 @@
 use syntax::ast;
 use syntax::util::lev_distance::find_best_match_for_name;
 
-use rustc_error_codes::*;
-
 use std::fmt::Display;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
index 0441514c83c9d05e28fad6112ec13a7040e1fc99..3572eda5c1399006db8cfc33f03d6a70181a27e6 100644 (file)
@@ -6,7 +6,6 @@
 use rustc::traits::{ObligationCause, ObligationCauseCode};
 use rustc::ty::subst::Subst;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc_error_codes::*;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_span::symbol::Symbol;
index b2542cc27a55119831ad054554313e39a0027f3f..9d8f57119ddded32a2cc051f715a415bfee8fbdf 100644 (file)
@@ -38,8 +38,6 @@
 use syntax::ast;
 use syntax::util::lev_distance::{find_best_match_for_name, lev_distance};
 
-use rustc_error_codes::*;
-
 use smallvec::{smallvec, SmallVec};
 
 use self::CandidateKind::*;
index d6c0d9c77b4950a2963361724abc64a261c45ad3..88de2654cea54802d0f1dd559b59b45b4718ebd5 100644 (file)
@@ -21,8 +21,6 @@
 use syntax::ast;
 use syntax::util::lev_distance;
 
-use rustc_error_codes::*;
-
 use std::cmp::Ordering;
 
 use super::probe::Mode;
index baf9ae1ac291151811f81bf4d9b992476cbb081b..f7df630fb90b19daad8ee8b291c4847726310fab 100644 (file)
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_hir::{ExprKind, GenericArg, HirIdMap, ItemKind, Node, PatKind, QPath};
+use rustc_hir::{ExprKind, GenericArg, HirIdMap, Item, ItemKind, Node, PatKind, QPath};
 use rustc_index::vec::Idx;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::source_map::{original_sp, DUMMY_SP};
 use syntax::attr;
 use syntax::util::parser::ExprPrecedence;
 
-use rustc_error_codes::*;
-
 use std::cell::{Cell, Ref, RefCell, RefMut};
 use std::cmp;
 use std::collections::hash_map::Entry;
@@ -1709,17 +1707,11 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) {
             check_enum(tcx, it.span, &enum_definition.variants, it.hir_id);
         }
         hir::ItemKind::Fn(..) => {} // entirely within check_item_body
-        hir::ItemKind::Impl(.., ref impl_item_refs) => {
+        hir::ItemKind::Impl { ref items, .. } => {
             debug!("ItemKind::Impl {} with id {}", it.ident, it.hir_id);
             let impl_def_id = tcx.hir().local_def_id(it.hir_id);
             if let Some(impl_trait_ref) = tcx.impl_trait_ref(impl_def_id) {
-                check_impl_items_against_trait(
-                    tcx,
-                    it.span,
-                    impl_def_id,
-                    impl_trait_ref,
-                    impl_item_refs,
-                );
+                check_impl_items_against_trait(tcx, it.span, impl_def_id, impl_trait_ref, items);
                 let trait_def_id = impl_trait_ref.def_id;
                 check_on_unimplemented(tcx, trait_def_id, it);
             }
@@ -2312,44 +2304,81 @@ fn check_packed(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) {
                 "type has conflicting packed and align representation hints"
             )
             .emit();
-        } else if check_packed_inner(tcx, def_id, &mut Vec::new()) {
-            struct_span_err!(
-                tcx.sess,
-                sp,
-                E0588,
-                "packed type cannot transitively contain a `[repr(align)]` type"
-            )
-            .emit();
+        } else {
+            if let Some(def_spans) = check_packed_inner(tcx, def_id, &mut vec![]) {
+                let mut err = struct_span_err!(
+                    tcx.sess,
+                    sp,
+                    E0588,
+                    "packed type cannot transitively contain a `#[repr(align)]` type"
+                );
+
+                let hir = tcx.hir();
+                if let Some(hir_id) = hir.as_local_hir_id(def_spans[0].0) {
+                    if let Node::Item(Item { ident, .. }) = hir.get(hir_id) {
+                        err.span_note(
+                            tcx.def_span(def_spans[0].0),
+                            &format!("`{}` has a `#[repr(align)]` attribute", ident),
+                        );
+                    }
+                }
+
+                if def_spans.len() > 2 {
+                    let mut first = true;
+                    for (adt_def, span) in def_spans.iter().skip(1).rev() {
+                        if let Some(hir_id) = hir.as_local_hir_id(*adt_def) {
+                            if let Node::Item(Item { ident, .. }) = hir.get(hir_id) {
+                                err.span_note(
+                                    *span,
+                                    &if first {
+                                        format!(
+                                            "`{}` contains a field of type `{}`",
+                                            tcx.type_of(def_id),
+                                            ident
+                                        )
+                                    } else {
+                                        format!("...which contains a field of type `{}`", ident)
+                                    },
+                                );
+                                first = false;
+                            }
+                        }
+                    }
+                }
+
+                err.emit();
+            }
         }
     }
 }
 
-fn check_packed_inner(tcx: TyCtxt<'_>, def_id: DefId, stack: &mut Vec<DefId>) -> bool {
-    let t = tcx.type_of(def_id);
-    if stack.contains(&def_id) {
-        debug!("check_packed_inner: {:?} is recursive", t);
-        return false;
-    }
-    if let ty::Adt(def, substs) = t.kind {
+fn check_packed_inner(
+    tcx: TyCtxt<'_>,
+    def_id: DefId,
+    stack: &mut Vec<DefId>,
+) -> Option<Vec<(DefId, Span)>> {
+    if let ty::Adt(def, substs) = tcx.type_of(def_id).kind {
         if def.is_struct() || def.is_union() {
-            if tcx.adt_def(def.did).repr.align.is_some() {
-                return true;
+            if def.repr.align.is_some() {
+                return Some(vec![(def.did, DUMMY_SP)]);
             }
-            // push struct def_id before checking fields
+
             stack.push(def_id);
             for field in &def.non_enum_variant().fields {
-                let f = field.ty(tcx, substs);
-                if let ty::Adt(def, _) = f.kind {
-                    if check_packed_inner(tcx, def.did, stack) {
-                        return true;
+                if let ty::Adt(def, _) = field.ty(tcx, substs).kind {
+                    if !stack.contains(&def.did) {
+                        if let Some(mut defs) = check_packed_inner(tcx, def.did, stack) {
+                            defs.push((def.did, field.ident.span));
+                            return Some(defs);
+                        }
                     }
                 }
             }
-            // only need to pop if not early out
             stack.pop();
         }
     }
-    false
+
+    None
 }
 
 /// Emit an error when encountering more or less than one variant in a transparent enum.
index edf9d19dea37785ad58b35e6966d3878d4739dbc..91e1731ac458b9e6de7aaed52145119659c753a2 100644 (file)
@@ -11,8 +11,6 @@
 use rustc_span::Span;
 use syntax::ast::Ident;
 
-use rustc_error_codes::*;
-
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Checks a `a <op>= b`
     pub fn check_binop_assign(
index 1478b35a25ddc8785ff54d8f1b576ee4a5772e75..f9dee0e477f793f055fa5c5cf6b649826ba362e1 100644 (file)
@@ -15,8 +15,6 @@
 use syntax::ast;
 use syntax::util::lev_distance::find_best_match_for_name;
 
-use rustc_error_codes::*;
-
 use std::cmp;
 use std::collections::hash_map::Entry::{Occupied, Vacant};
 
index a496a6e12ce1a0f7d5c4ce0c54c47068fc434410..910e680de69dc6c56872ac9ec82cf60971b8cce7 100644 (file)
@@ -18,8 +18,6 @@
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ParItemLikeVisitor;
 
-use rustc_error_codes::*;
-
 /// Helper type of a temporary returned by `.for_item(...)`.
 /// This is necessary because we can't write the following bound:
 ///
@@ -97,7 +95,7 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: DefId) {
         //
         // won't be allowed unless there's an *explicit* implementation of `Send`
         // for `T`
-        hir::ItemKind::Impl(_, _, defaultness, _, ref trait_ref, ref self_ty, _) => {
+        hir::ItemKind::Impl { defaultness, ref of_trait, ref self_ty, .. } => {
             let is_auto = tcx
                 .impl_trait_ref(tcx.hir().local_def_id(item.hir_id))
                 .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id));
@@ -107,11 +105,11 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: DefId) {
             }
             match polarity {
                 ty::ImplPolarity::Positive => {
-                    check_impl(tcx, item, self_ty, trait_ref);
+                    check_impl(tcx, item, self_ty, of_trait);
                 }
                 ty::ImplPolarity::Negative => {
                     // FIXME(#27579): what amount of WF checking do we need for neg impls?
-                    if trait_ref.is_some() && !is_auto {
+                    if of_trait.is_some() && !is_auto {
                         struct_span_err!(
                             tcx.sess,
                             item.span,
index 8b3db15c02b4ecd18337b651dacb9bacb4ae26b9..79a006a898a893adacda9798c9ab4869ea5523c2 100644 (file)
@@ -12,7 +12,6 @@
 use rustc::ty::adjustment::CoerceUnsizedInfo;
 use rustc::ty::TypeFoldable;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc_error_codes::*;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -57,7 +56,7 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: DefId) {
 
     let impl_hir_id = tcx.hir().as_local_hir_id(impl_did).expect("foreign Drop impl on non-ADT");
     let sp = match tcx.hir().expect_item(impl_hir_id).kind {
-        ItemKind::Impl(.., ty, _) => ty.span,
+        ItemKind::Impl { self_ty, .. } => self_ty.span,
         _ => bug!("expected Drop impl item"),
     };
 
@@ -94,7 +93,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: DefId) {
         Ok(()) => {}
         Err(CopyImplementationError::InfrigingFields(fields)) => {
             let item = tcx.hir().expect_item(impl_hir_id);
-            let span = if let ItemKind::Impl(.., Some(ref tr), _, _) = item.kind {
+            let span = if let ItemKind::Impl { of_trait: Some(ref tr), .. } = item.kind {
                 tr.path.span
             } else {
                 span
@@ -113,7 +112,8 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: DefId) {
         }
         Err(CopyImplementationError::NotAnAdt) => {
             let item = tcx.hir().expect_item(impl_hir_id);
-            let span = if let ItemKind::Impl(.., ref ty, _) = item.kind { ty.span } else { span };
+            let span =
+                if let ItemKind::Impl { self_ty, .. } = item.kind { self_ty.span } else { span };
 
             struct_span_err!(
                 tcx.sess,
@@ -490,7 +490,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
                     return err_info;
                 } else if diff_fields.len() > 1 {
                     let item = tcx.hir().expect_item(impl_hir_id);
-                    let span = if let ItemKind::Impl(.., Some(ref t), _, _) = item.kind {
+                    let span = if let ItemKind::Impl { of_trait: Some(ref t), .. } = item.kind {
                         t.path.span
                     } else {
                         tcx.hir().span(impl_hir_id)
index 673c1bd9fd83103ec99bfa9d65adc420b2eb29ee..d4c89b7e037938a67bcb73e85bed437a632ae50c 100644 (file)
@@ -16,8 +16,6 @@
 use rustc_span::Span;
 use syntax::ast;
 
-use rustc_error_codes::*;
-
 /// On-demand query: yields a map containing all types mapped to their inherent impls.
 pub fn crate_inherent_impls(tcx: TyCtxt<'_>, crate_num: CrateNum) -> &CrateInherentImpls {
     assert_eq!(crate_num, LOCAL_CRATE);
@@ -47,7 +45,7 @@ struct InherentCollect<'tcx> {
 impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
     fn visit_item(&mut self, item: &hir::Item<'_>) {
         let ty = match item.kind {
-            hir::ItemKind::Impl(.., None, ref ty, _) => ty,
+            hir::ItemKind::Impl { of_trait: None, ref self_ty, .. } => self_ty,
             _ => return,
         };
 
index a9228c7f6bb4c86dc655dbbce9e8c2020f44de3e..d60c3cfba9a5bca1c1d80216cf602489387dd5e3 100644 (file)
@@ -6,8 +6,6 @@
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 
-use rustc_error_codes::*;
-
 pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, crate_num: CrateNum) {
     assert_eq!(crate_num, LOCAL_CRATE);
     let krate = tcx.hir().krate();
index fd685e77b418ccc09543a761f73638c3f7f48b1a..5583e3418b2a8a7a1dbe41c46806da7cf0f51f7b 100644 (file)
@@ -8,7 +8,6 @@
 use rustc::traits;
 use rustc::ty::query::Providers;
 use rustc::ty::{self, TyCtxt, TypeFoldable};
-use rustc_error_codes::*;
 use rustc_errors::struct_span_err;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::HirId;
index 1878f9385a891696e2a63d66075f4162585a6b9a..80521666476e6e187ad3e05f9910f74402835656 100644 (file)
@@ -7,8 +7,6 @@
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 
-use rustc_error_codes::*;
-
 pub fn check(tcx: TyCtxt<'_>) {
     let mut orphan = OrphanChecker { tcx };
     tcx.hir().krate().visit_all_item_likes(&mut orphan);
@@ -27,7 +25,7 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> {
     fn visit_item(&mut self, item: &hir::Item<'_>) {
         let def_id = self.tcx.hir().local_def_id(item.hir_id);
         // "Trait" impl
-        if let hir::ItemKind::Impl(.., generics, Some(tr), impl_ty, _) = &item.kind {
+        if let hir::ItemKind::Impl { generics, of_trait: Some(ref tr), self_ty, .. } = &item.kind {
             debug!(
                 "coherence2::orphan check: trait impl {}",
                 self.tcx.hir().node_to_string(item.hir_id)
@@ -72,7 +70,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                         let msg = format!("{} is not defined in the current crate{}", ty, postfix);
                         if *is_target_ty {
                             // Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
-                            err.span_label(impl_ty.span, &msg);
+                            err.span_label(self_ty.span, &msg);
                         } else {
                             // Point at `C<B>` in `impl<A, B> for C<B> in D<A>`
                             err.span_label(tr.path.span, &msg);
index 3f4035b0998d64c4d756cb0b485db4c674859202..a6044217403634c08f818c63f11e9d9f5e9ca32e 100644 (file)
@@ -7,8 +7,6 @@
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::Unsafety;
 
-use rustc_error_codes::*;
-
 pub fn check(tcx: TyCtxt<'_>) {
     let mut unsafety = UnsafetyChecker { tcx };
     tcx.hir().krate().visit_all_item_likes(&mut unsafety);
@@ -88,7 +86,7 @@ fn check_unsafety_coherence(
 
 impl ItemLikeVisitor<'v> for UnsafetyChecker<'tcx> {
     fn visit_item(&mut self, item: &'v hir::Item<'v>) {
-        if let hir::ItemKind::Impl(unsafety, polarity, _, ref generics, ..) = item.kind {
+        if let hir::ItemKind::Impl { unsafety, polarity, ref generics, .. } = item.kind {
             self.check_unsafety_coherence(item, Some(generics), unsafety, polarity);
         }
     }
index dca3289747e4ce92c52ac07bc20a5e84eb01549f..9eee31c3a5763bf6a4cbe30cf88718498420dcd9 100644 (file)
@@ -47,8 +47,6 @@
 use syntax::ast::{Ident, MetaItemKind};
 use syntax::attr::{list_contains_name, mark_used, InlineAttr, OptimizeAttr};
 
-use rustc_error_codes::*;
-
 struct OnlySelfBounds(bool);
 
 ///////////////////////////////////////////////////////////////////////////
@@ -184,7 +182,7 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir
         | hir::ItemKind::Enum(_, generics)
         | hir::ItemKind::TraitAlias(generics, _)
         | hir::ItemKind::Trait(_, _, generics, ..)
-        | hir::ItemKind::Impl(_, _, _, generics, ..)
+        | hir::ItemKind::Impl { generics, .. }
         | hir::ItemKind::Struct(_, generics) => (generics, true),
         hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. })
         | hir::ItemKind::TyAlias(_, generics) => (generics, false),
@@ -401,7 +399,7 @@ fn type_param_predicates(
         Node::Item(item) => {
             match item.kind {
                 ItemKind::Fn(.., ref generics, _)
-                | ItemKind::Impl(_, _, _, ref generics, ..)
+                | ItemKind::Impl { ref generics, .. }
                 | ItemKind::TyAlias(_, ref generics)
                 | ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. })
                 | ItemKind::Enum(_, ref generics)
@@ -531,7 +529,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) {
             tcx.predicates_of(def_id);
             convert_enum_variant_types(tcx, def_id, &enum_definition.variants);
         }
-        hir::ItemKind::Impl(..) => {
+        hir::ItemKind::Impl { .. } => {
             tcx.generics_of(def_id);
             tcx.type_of(def_id);
             tcx.impl_trait_ref(def_id);
@@ -1052,9 +1050,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
 
         Node::Item(item) => {
             match item.kind {
-                ItemKind::Fn(.., ref generics, _) | ItemKind::Impl(_, _, _, ref generics, ..) => {
-                    generics
-                }
+                ItemKind::Fn(.., ref generics, _) | ItemKind::Impl { ref generics, .. } => generics,
 
                 ItemKind::TyAlias(_, ref generics)
                 | ItemKind::Enum(_, ref generics)
@@ -1338,7 +1334,9 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                         icx.to_ty(ty)
                     }
                 }
-                ItemKind::TyAlias(ref ty, _) | ItemKind::Impl(.., ref ty, _) => icx.to_ty(ty),
+                ItemKind::TyAlias(ref self_ty, _) | ItemKind::Impl { ref self_ty, .. } => {
+                    icx.to_ty(self_ty)
+                }
                 ItemKind::Fn(..) => {
                     let substs = InternalSubsts::identity_for_item(tcx, def_id);
                     tcx.mk_fn_def(def_id, substs)
@@ -1956,12 +1954,10 @@ fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
 
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
     match tcx.hir().expect_item(hir_id).kind {
-        hir::ItemKind::Impl(.., ref opt_trait_ref, _, _) => {
-            opt_trait_ref.as_ref().map(|ast_trait_ref| {
-                let selfty = tcx.type_of(def_id);
-                AstConv::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty)
-            })
-        }
+        hir::ItemKind::Impl { ref of_trait, .. } => of_trait.as_ref().map(|ast_trait_ref| {
+            let selfty = tcx.type_of(def_id);
+            AstConv::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty)
+        }),
         _ => bug!(),
     }
 }
@@ -1971,19 +1967,21 @@ fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
     let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
     let item = tcx.hir().expect_item(hir_id);
     match &item.kind {
-        hir::ItemKind::Impl(_, hir::ImplPolarity::Negative, ..) => {
+        hir::ItemKind::Impl { polarity: hir::ImplPolarity::Negative, .. } => {
             if is_rustc_reservation {
                 tcx.sess.span_err(item.span, "reservation impls can't be negative");
             }
             ty::ImplPolarity::Negative
         }
-        hir::ItemKind::Impl(_, hir::ImplPolarity::Positive, _, _, None, _, _) => {
+        hir::ItemKind::Impl { polarity: hir::ImplPolarity::Positive, of_trait: None, .. } => {
             if is_rustc_reservation {
                 tcx.sess.span_err(item.span, "reservation impls can't be inherent");
             }
             ty::ImplPolarity::Positive
         }
-        hir::ItemKind::Impl(_, hir::ImplPolarity::Positive, _, _, Some(_tr), _, _) => {
+        hir::ItemKind::Impl {
+            polarity: hir::ImplPolarity::Positive, of_trait: Some(_), ..
+        } => {
             if is_rustc_reservation {
                 ty::ImplPolarity::Reservation
             } else {
@@ -2142,7 +2140,7 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
 
         Node::Item(item) => {
             match item.kind {
-                ItemKind::Impl(_, _, defaultness, ref generics, ..) => {
+                ItemKind::Impl { defaultness, ref generics, .. } => {
                     if defaultness.is_default() {
                         is_default_impl_trait = tcx.impl_trait_ref(def_id);
                     }
@@ -2359,7 +2357,7 @@ fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter:
     // before uses of `U`.  This avoids false ambiguity errors
     // in trait checking. See `setup_constraining_predicates`
     // for details.
-    if let Node::Item(&Item { kind: ItemKind::Impl(..), .. }) = node {
+    if let Node::Item(&Item { kind: ItemKind::Impl { .. }, .. }) = node {
         let self_ty = tcx.type_of(def_id);
         let trait_ref = tcx.impl_trait_ref(def_id);
         cgp::setup_constraining_predicates(
index fb87b285fa29f56e139ea257cfdcb815ed643c0a..e9c18b59da9824146f05b46ff3381a198d69f783 100644 (file)
@@ -20,8 +20,6 @@
 
 use rustc_span::Span;
 
-use rustc_error_codes::*;
-
 /// Checks that all the type/lifetime parameters on an impl also
 /// appear in the trait ref or self type (or are constrained by a
 /// where-clause). These rules are needed to ensure that, given a
@@ -75,10 +73,10 @@ struct ImplWfCheck<'tcx> {
 
 impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> {
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        if let hir::ItemKind::Impl(.., ref impl_item_refs) = item.kind {
+        if let hir::ItemKind::Impl { ref items, .. } = item.kind {
             let impl_def_id = self.tcx.hir().local_def_id(item.hir_id);
-            enforce_impl_params_are_constrained(self.tcx, impl_def_id, impl_item_refs);
-            enforce_impl_items_are_distinct(self.tcx, impl_item_refs);
+            enforce_impl_params_are_constrained(self.tcx, impl_def_id, items);
+            enforce_impl_items_are_distinct(self.tcx, items);
         }
     }
 
index b951883ac195a2888c8b9803765d3e823e61e264..7e63a0254e845e96c8230dd5d4da5f1a8a9f0294 100644 (file)
@@ -64,7 +64,7 @@
 #![feature(exhaustive_patterns)]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(try_blocks)]
 #![feature(never_type)]
 #![recursion_limit = "256"]
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
 
-use rustc_error_codes::*;
-
 use std::iter;
 
 use astconv::{AstConv, Bounds};
index 908429c8dc48a8b215cde8db0ffd4635c412bac7..980d58ad939d76253ce51f9dde20a0669ba8f4ab 100644 (file)
@@ -4,8 +4,6 @@
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_span::symbol::sym;
 
-use rustc_error_codes::*;
-
 pub fn test_inferred_outlives(tcx: TyCtxt<'_>) {
     tcx.hir().krate().visit_all_item_likes(&mut OutlivesTest { tcx });
 }
index 068814723f52d758e6a578062a5e6887f90c5db1..99b7b2001a9e9a29812a2ecf8ec6d3ec7da509c2 100644 (file)
@@ -3,8 +3,6 @@
 use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc_span::Span;
 
-use rustc_error_codes::*;
-
 pub trait StructuredDiagnostic<'tcx> {
     fn session(&self) -> &Session;
 
index 2f41bee1819cd32dce67b698112d11c556e76aa8..ee94b1015a1f48979f14f3fb897d03a7fc8a5a5e 100644 (file)
@@ -4,8 +4,6 @@
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_span::symbol::sym;
 
-use rustc_error_codes::*;
-
 pub fn test_variance(tcx: TyCtxt<'_>) {
     tcx.hir().krate().visit_all_item_likes(&mut VarianceTest { tcx });
 }
index 56013ee3a816ffb42106d29d2bd2b9bd1e3fd6c6..f37f6921cebaf4f5c3a1360237be99c8a0cf4136 100644 (file)
@@ -239,7 +239,7 @@ fn handle_lifetimes<'cx>(
         //  constraint, and add it to our list. Since we make sure to never re-add
         //  deleted items, this process will always finish.
         while !vid_map.is_empty() {
-            let target = vid_map.keys().next().expect("Keys somehow empty").clone();
+            let target = *vid_map.keys().next().expect("Keys somehow empty");
             let deps = vid_map.remove(&target).expect("Entry somehow missing");
 
             for smaller in deps.smaller.iter() {
index c7e0f1e9e704ba0683a838307205f56a39ac8341..8a6abe036dc14b9305901af1892cd7c573401317 100644 (file)
@@ -273,6 +273,22 @@ fn build_type_alias(cx: &DocContext<'_>, did: DefId) -> clean::Typedef {
     clean::Typedef {
         type_: cx.tcx.type_of(did).clean(cx),
         generics: (cx.tcx.generics_of(did), predicates).clean(cx),
+        item_type: build_type_alias_type(cx, did),
+    }
+}
+
+fn build_type_alias_type(cx: &DocContext<'_>, did: DefId) -> Option<clean::Type> {
+    let type_ = cx.tcx.type_of(did).clean(cx);
+    type_.def_id().and_then(|did| build_ty(cx, did))
+}
+
+pub fn build_ty(cx: &DocContext, did: DefId) -> Option<clean::Type> {
+    match cx.tcx.def_kind(did)? {
+        DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::Const | DefKind::Static => {
+            Some(cx.tcx.type_of(did).clean(cx))
+        }
+        DefKind::TyAlias => build_type_alias_type(cx, did),
+        _ => None,
     }
 }
 
@@ -331,7 +347,7 @@ pub fn build_impl(
 
     let for_ = if let Some(hir_id) = tcx.hir().as_local_hir_id(did) {
         match tcx.hir().expect_item(hir_id).kind {
-            hir::ItemKind::Impl(.., ref t, _) => t.clean(cx),
+            hir::ItemKind::Impl { self_ty, .. } => self_ty.clean(cx),
             _ => panic!("did given to build_impl was not an impl"),
         }
     } else {
@@ -351,9 +367,9 @@ pub fn build_impl(
     let predicates = tcx.explicit_predicates_of(did);
     let (trait_items, generics) = if let Some(hir_id) = tcx.hir().as_local_hir_id(did) {
         match tcx.hir().expect_item(hir_id).kind {
-            hir::ItemKind::Impl(.., ref gen, _, _, ref item_ids) => (
-                item_ids.iter().map(|ii| tcx.hir().impl_item(ii.id).clean(cx)).collect::<Vec<_>>(),
-                gen.clean(cx),
+            hir::ItemKind::Impl { ref generics, ref items, .. } => (
+                items.iter().map(|item| tcx.hir().impl_item(item.id).clean(cx)).collect::<Vec<_>>(),
+                generics.clean(cx),
             ),
             _ => panic!("did given to build_impl was not an impl"),
         }
index be9654612f504e91163a02adc414d459735c08bd..20a5a6c54984d0bed6dd310df67780dbdd35cc8e 100644 (file)
@@ -1122,7 +1122,9 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
                 MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx))
             }
             hir::ImplItemKind::TyAlias(ref ty) => {
-                TypedefItem(Typedef { type_: ty.clean(cx), generics: Generics::default() }, true)
+                let type_ = ty.clean(cx);
+                let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
+                TypedefItem(Typedef { type_, generics: Generics::default(), item_type }, true)
             }
             hir::ImplItemKind::OpaqueTy(ref bounds) => OpaqueTyItem(
                 OpaqueTy { bounds: bounds.clean(cx), generics: Generics::default() },
@@ -1282,10 +1284,13 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
 
                     AssocTypeItem(bounds, ty.clean(cx))
                 } else {
+                    let type_ = cx.tcx.type_of(self.def_id).clean(cx);
+                    let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
                     TypedefItem(
                         Typedef {
-                            type_: cx.tcx.type_of(self.def_id).clean(cx),
+                            type_,
                             generics: Generics { params: Vec::new(), where_predicates: Vec::new() },
+                            item_type,
                         },
                         true,
                     )
@@ -1989,6 +1994,8 @@ fn clean(&self, _: &DocContext<'_>) -> String {
 
 impl Clean<Item> for doctree::Typedef<'_> {
     fn clean(&self, cx: &DocContext<'_>) -> Item {
+        let type_ = self.ty.clean(cx);
+        let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
         Item {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
@@ -1997,10 +2004,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item {
             visibility: self.vis.clean(cx),
             stability: cx.stability(self.id).clean(cx),
             deprecation: cx.deprecation(self.id).clean(cx),
-            inner: TypedefItem(
-                Typedef { type_: self.ty.clean(cx), generics: self.gen.clean(cx) },
-                false,
-            ),
+            inner: TypedefItem(Typedef { type_, generics: self.gen.clean(cx), item_type }, false),
         }
     }
 }
@@ -2101,7 +2105,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
             build_deref_target_impls(cx, &items, &mut ret);
         }
 
-        let provided = trait_
+        let provided: FxHashSet<String> = trait_
             .def_id()
             .map(|did| {
                 cx.tcx
@@ -2112,7 +2116,12 @@ fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
             })
             .unwrap_or_default();
 
-        ret.push(Item {
+        let for_ = self.for_.clean(cx);
+        let type_alias = for_.def_id().and_then(|did| match cx.tcx.def_kind(did) {
+            Some(DefKind::TyAlias) => Some(cx.tcx.type_of(did).clean(cx)),
+            _ => None,
+        });
+        let make_item = |trait_: Option<Type>, for_: Type, items: Vec<Item>| Item {
             name: None,
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
@@ -2123,15 +2132,19 @@ fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
             inner: ImplItem(Impl {
                 unsafety: self.unsafety,
                 generics: self.generics.clean(cx),
-                provided_trait_methods: provided,
+                provided_trait_methods: provided.clone(),
                 trait_,
-                for_: self.for_.clean(cx),
+                for_,
                 items,
                 polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)),
                 synthetic: false,
                 blanket_impl: None,
             }),
-        });
+        };
+        if let Some(type_alias) = type_alias {
+            ret.push(make_item(trait_.clone(), type_alias, items.clone()));
+        }
+        ret.push(make_item(trait_, for_, items));
         ret
     }
 }
index 5d8e27ecadb828dbe8edbd7db05671ddf777c39c..79a078ca7a991abdaf58ccdf8728d6e22b466fbf 100644 (file)
@@ -1406,6 +1406,14 @@ pub struct PathSegment {
 pub struct Typedef {
     pub type_: Type,
     pub generics: Generics,
+    // Type of target item.
+    pub item_type: Option<Type>,
+}
+
+impl GetDefId for Typedef {
+    fn def_id(&self) -> Option<DefId> {
+        self.type_.def_id()
+    }
 }
 
 #[derive(Clone, Debug)]
index aa52b769c38ed3af420ccd1085260b5bb6acbb7e..5bea1b56141591d90ee7e386d5f579ea0a40249e 100644 (file)
@@ -41,7 +41,7 @@ pub fn render_with_highlighting(
     let fm = sess
         .source_map()
         .new_source_file(FileName::Custom(String::from("rustdoc-highlighting")), src.to_owned());
-    let highlight_result = {
+    let highlight_result = rustc_driver::catch_fatal_errors(|| {
         let lexer = lexer::StringReader::new(&sess, fm, None);
         let mut classifier = Classifier::new(lexer, sess.source_map());
 
@@ -51,7 +51,8 @@ pub fn render_with_highlighting(
         } else {
             Ok(String::from_utf8_lossy(&highlighted_source).into_owned())
         }
-    };
+    })
+    .unwrap_or(Err(()));
 
     match highlight_result {
         Ok(highlighted_source) => {
index c5f88f9f7f421d5ed93aaf62fe82a57e68ab6084..c87964af0200cf8c7ca8c1da2e87c04c58f0b8d8 100644 (file)
@@ -380,7 +380,10 @@ fn next(&mut self) -> Option<Self::Item> {
                     }
                     _ => {}
                 }
-                self.buf.push_back(event);
+                match event {
+                    Event::Start(Tag::Link(_, _, _)) | Event::End(Tag::Link(..)) => {}
+                    event => self.buf.push_back(event),
+                }
             }
             let id = self.id_map.derive(id);
 
@@ -395,7 +398,7 @@ fn next(&mut self) -> Option<Self::Item> {
 
             let start_tags = format!(
                 "<h{level} id=\"{id}\" class=\"section-header\">\
-                                      <a href=\"#{id}\">",
+                    <a href=\"#{id}\">",
                 id = id,
                 level = level
             );
index 2d932eb7668c41041ee767be827f74d3c91834a0..9406803825350e82abb50b9987f47f73dfc8dbc2 100644 (file)
@@ -3469,20 +3469,23 @@ fn render_deref_methods(
     deref_mut: bool,
 ) {
     let deref_type = impl_.inner_impl().trait_.as_ref().unwrap();
-    let target = impl_
+    let (target, real_target) = impl_
         .inner_impl()
         .items
         .iter()
         .filter_map(|item| match item.inner {
-            clean::TypedefItem(ref t, true) => Some(&t.type_),
+            clean::TypedefItem(ref t, true) => Some(match *t {
+                clean::Typedef { item_type: Some(ref type_), .. } => (type_, &t.type_),
+                _ => (&t.type_, &t.type_),
+            }),
             _ => None,
         })
         .next()
         .expect("Expected associated type binding");
     let what =
-        AssocItemRender::DerefFor { trait_: deref_type, type_: target, deref_mut_: deref_mut };
+        AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut };
     if let Some(did) = target.def_id() {
-        render_assoc_items(w, cx, container_item, did, what)
+        render_assoc_items(w, cx, container_item, did, what);
     } else {
         if let Some(prim) = target.primitive_type() {
             if let Some(&did) = cx.cache.primitive_locations.get(&prim) {
@@ -4123,12 +4126,15 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
                 .filter(|i| i.inner_impl().trait_.is_some())
                 .find(|i| i.inner_impl().trait_.def_id() == c.deref_trait_did)
             {
-                if let Some(target) = impl_
+                if let Some((target, real_target)) = impl_
                     .inner_impl()
                     .items
                     .iter()
                     .filter_map(|item| match item.inner {
-                        clean::TypedefItem(ref t, true) => Some(&t.type_),
+                        clean::TypedefItem(ref t, true) => Some(match *t {
+                            clean::Typedef { item_type: Some(ref type_), .. } => (type_, &t.type_),
+                            _ => (&t.type_, &t.type_),
+                        }),
                         _ => None,
                     })
                     .next()
@@ -4147,7 +4153,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
                                 "{:#}",
                                 impl_.inner_impl().trait_.as_ref().unwrap().print()
                             )),
-                            Escape(&format!("{:#}", target.print()))
+                            Escape(&format!("{:#}", real_target.print()))
                         ));
                         out.push_str("</a>");
                         let mut ret = impls
index 22507443b0842fa2d56842cf4fb8890ba7e7a0d9..f1f83acdda59e81cb16f0593ae59ea5b5970a684 100644 (file)
@@ -277,7 +277,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                 | clean::StructFieldItem(..)
                 | clean::VariantItem(..) => (
                     (
-                        Some(*self.parent_stack.last().unwrap()),
+                        Some(*self.parent_stack.last().expect("parent_stack is empty")),
                         Some(&self.stack[..self.stack.len() - 1]),
                     ),
                     false,
@@ -286,7 +286,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                     if self.parent_stack.is_empty() {
                         ((None, None), false)
                     } else {
-                        let last = self.parent_stack.last().unwrap();
+                        let last = self.parent_stack.last().expect("parent_stack is empty 2");
                         let did = *last;
                         let path = match self.paths.get(&did) {
                             // The current stack not necessarily has correlation
@@ -468,7 +468,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
                         self.impls.entry(did).or_insert(vec![]).push(impl_item.clone());
                     }
                 } else {
-                    let trait_did = impl_item.trait_did().unwrap();
+                    let trait_did = impl_item.trait_did().expect("no trait did");
                     self.orphan_trait_impls.push((trait_did, dids, impl_item));
                 }
                 None
@@ -478,10 +478,10 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
         });
 
         if pushed {
-            self.stack.pop().unwrap();
+            self.stack.pop().expect("stack already empty");
         }
         if parent_pushed {
-            self.parent_stack.pop().unwrap();
+            self.parent_stack.pop().expect("parent stack already empty");
         }
         self.stripped_mod = orig_stripped_mod;
         self.parent_is_trait_impl = orig_parent_is_trait_impl;
@@ -594,7 +594,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
     for item in search_index {
         item.parent_idx = item.parent.map(|nodeid| {
             if nodeid_to_pathid.contains_key(&nodeid) {
-                *nodeid_to_pathid.get(&nodeid).unwrap()
+                *nodeid_to_pathid.get(&nodeid).expect("no pathid")
             } else {
                 let pathid = lastpathid;
                 nodeid_to_pathid.insert(nodeid, pathid);
@@ -639,7 +639,7 @@ struct CrateData<'a> {
             items: crate_items,
             paths: crate_paths,
         })
-        .unwrap()
+        .expect("failed serde conversion")
     )
 }
 
index 1da00e3a47b8268db9e73c0a87bdc028cb719fa2..403c8d0160d8aea1fb882e275e01fec8bf14c4d3 100644 (file)
@@ -23,7 +23,6 @@
 extern crate rustc;
 extern crate rustc_data_structures;
 extern crate rustc_driver;
-extern crate rustc_error_codes;
 extern crate rustc_errors;
 extern crate rustc_expand;
 extern crate rustc_feature;
index 0bab4423b3dfdb38449d97465df38b52620a4b07..2903fd9dcd6602734033bcddf2ecf4b3cb860a62 100644 (file)
@@ -40,7 +40,7 @@ fn check_rust_syntax(&self, item: &clean::Item, dox: &str, code_block: RustCodeB
             dox[code_block.code].to_owned(),
         );
 
-        let validation_status = {
+        let validation_status = rustc_driver::catch_fatal_errors(|| {
             let mut has_syntax_errors = false;
             let mut only_whitespace = true;
             // even if there is a syntax error, we need to run the lexer over the whole file
@@ -61,7 +61,8 @@ fn check_rust_syntax(&self, item: &clean::Item, dox: &str, code_block: RustCodeB
             } else {
                 None
             }
-        };
+        })
+        .unwrap_or(Some(CodeBlockInvalid::SyntaxError));
 
         if let Some(code_block_invalid) = validation_status {
             let mut diag = if let Some(sp) =
index f899e722a561573085add3ad490a14c6b2e33ed3..d89dc2adafeb36734717150496fa46b4e3fc7396 100644 (file)
@@ -43,7 +43,7 @@ pub fn run(options: Options) -> i32 {
     let crate_types = if options.proc_macro_crate {
         vec![config::CrateType::ProcMacro]
     } else {
-        vec![config::CrateType::Dylib]
+        vec![config::CrateType::Rlib]
     };
 
     let sessopts = config::Options {
@@ -117,12 +117,16 @@ pub fn run(options: Options) -> i32 {
                     intravisit::walk_crate(this, krate);
                 });
             });
+            compiler.session().abort_if_errors();
 
             let ret: Result<_, ErrorReported> = Ok(collector.tests);
             ret
         })
-    })
-    .expect("compiler aborted in rustdoc!");
+    });
+    let tests = match tests {
+        Ok(tests) => tests,
+        Err(ErrorReported) => return 1,
+    };
 
     test_args.insert(0, "rustdoctest".to_string());
 
@@ -905,8 +909,8 @@ fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
     }
 
     fn visit_item(&mut self, item: &'hir hir::Item) {
-        let name = if let hir::ItemKind::Impl(.., ref ty, _) = item.kind {
-            self.map.hir_to_pretty_string(ty.hir_id)
+        let name = if let hir::ItemKind::Impl { ref self_ty, .. } = item.kind {
+            self.map.hir_to_pretty_string(self_ty.hir_id)
         } else {
             item.ident.to_string()
         };
index 5fa9270959cca50a2bc7cf2504956f60192c69aa..fdff18779e7954364834429ac03cec4a16d267da 100644 (file)
@@ -558,27 +558,27 @@ fn visit_item(
                 om.trait_aliases.push(t);
             }
 
-            hir::ItemKind::Impl(
+            hir::ItemKind::Impl {
                 unsafety,
                 polarity,
                 defaultness,
                 ref generics,
-                ref trait_,
-                for_,
-                ref item_ids,
-            ) => {
+                ref of_trait,
+                self_ty,
+                ref items,
+            } => {
                 // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
                 // them up regardless of where they're located.
-                if !self.inlining && trait_.is_none() {
+                if !self.inlining && of_trait.is_none() {
                     let items =
-                        item_ids.iter().map(|ii| self.cx.tcx.hir().impl_item(ii.id)).collect();
+                        items.iter().map(|item| self.cx.tcx.hir().impl_item(item.id)).collect();
                     let i = Impl {
                         unsafety,
                         polarity,
                         defaultness,
                         generics,
-                        trait_,
-                        for_,
+                        trait_: of_trait,
+                        for_: self_ty,
                         items,
                         attrs: &item.attrs,
                         id: item.hir_id,
index f90647472c6787ee401474fa63ef7de2ebe98251..c8fae91fcf3a5c5e236a5bb8c3af9ddba1e9bb78 100644 (file)
 #![feature(shrink_to)]
 #![feature(slice_concat_ext)]
 #![feature(slice_internals)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(specialization)]
 #![feature(staged_api)]
 #![feature(std_internals)]
index 0b6e728dceb1d49719d9130d575f2ba8b3d0a273..5bc8fe5ae6d791bd59edee9cbe418d11ca9a4af0 100644 (file)
@@ -65,7 +65,7 @@
 ///
 /// |  Platform |               System call                                            |
 /// |:---------:|:--------------------------------------------------------------------:|
-/// | Cloud ABI | [clock_time_get (Monotonic Clock)]                                   |
+/// | CloudABI  | [clock_time_get (Monotonic Clock)]                                   |
 /// | SGX       | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
 /// | UNIX      | [clock_gettime (Monotonic Clock)]                                    |
 /// | Darwin    | [mach_absolute_time]                                                 |
@@ -79,7 +79,7 @@
 /// [__wasi_clock_time_get (Monotonic Clock)]: https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-api.md#clock_time_get
 /// [clock_gettime (Monotonic Clock)]: https://linux.die.net/man/3/clock_gettime
 /// [mach_absolute_time]: https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/services/services.html
-/// [clock_time_get (Monotonic Clock)]: https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt
+/// [clock_time_get (Monotonic Clock)]: https://nuxi.nl/cloudabi/#clock_time_get
 ///
 /// **Disclaimer:** These system calls might change over time.
 ///
 ///
 /// |  Platform |               System call                                            |
 /// |:---------:|:--------------------------------------------------------------------:|
-/// | Cloud ABI | [clock_time_get (Realtime Clock)]                                    |
+/// | CloudABI  | [clock_time_get (Realtime Clock)]                                    |
 /// | SGX       | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
 /// | UNIX      | [clock_gettime (Realtime Clock)]                                     |
 /// | DARWIN    | [gettimeofday]                                                       |
 /// | WASI      | [__wasi_clock_time_get (Realtime Clock)]                             |
 /// | Windows   | [GetSystemTimeAsFileTime]                                            |
 ///
-/// [clock_time_get (Realtime Clock)]: https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt
+/// [clock_time_get (Realtime Clock)]: https://nuxi.nl/cloudabi/#clock_time_get
 /// [`insecure_time` usercall]: https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#method.insecure_time
 /// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode
 /// [gettimeofday]: http://man7.org/linux/man-pages/man2/gettimeofday.2.html
index 7d9f715e9feb8c809ead5da130cfa946e95081b4..2e647d2a1e0810c59243467974ca13e81dd1d619 100644 (file)
@@ -21,5 +21,4 @@ rustc_index = { path = "../librustc_index" }
 rustc_lexer = { path = "../librustc_lexer" }
 rustc_macros = { path = "../librustc_macros" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
-rustc_error_codes = { path = "../librustc_error_codes" }
 rustc_session = { path = "../librustc_session" }
index 331eb109ec0b47ec8ce22ce666ec6611df87dc03..a5a4eb1583bedc10cb14aff332471431e2930b49 100644 (file)
@@ -2614,15 +2614,18 @@ pub enum ItemKind {
     /// An implementation.
     ///
     /// E.g., `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`.
-    Impl(
-        Unsafety,
-        ImplPolarity,
-        Defaultness,
-        Generics,
-        Option<TraitRef>, // (optional) trait this impl implements
-        P<Ty>,            // self
-        Vec<AssocItem>,
-    ),
+    Impl {
+        unsafety: Unsafety,
+        polarity: ImplPolarity,
+        defaultness: Defaultness,
+        generics: Generics,
+
+        /// The trait being implemented, if any.
+        of_trait: Option<TraitRef>,
+
+        self_ty: P<Ty>,
+        items: Vec<AssocItem>,
+    },
     /// A macro invocation.
     ///
     /// E.g., `foo!(..)`.
@@ -2649,7 +2652,7 @@ pub fn descriptive_variant(&self) -> &str {
             ItemKind::Union(..) => "union",
             ItemKind::Trait(..) => "trait",
             ItemKind::TraitAlias(..) => "trait alias",
-            ItemKind::Mac(..) | ItemKind::MacroDef(..) | ItemKind::Impl(..) => "item",
+            ItemKind::Mac(..) | ItemKind::MacroDef(..) | ItemKind::Impl { .. } => "item",
         }
     }
 }
index 70f4f47621a348ce36acbef9d39d83b42db36d6c..6cfe4f2de1e96b1ae1857f64de39aae50d8e7da3 100644 (file)
@@ -12,8 +12,6 @@
 use rustc_span::{symbol::sym, symbol::Symbol, Span};
 use std::num::NonZeroU32;
 
-use rustc_error_codes::*;
-
 pub fn is_builtin_attr(attr: &Attribute) -> bool {
     attr.is_doc_comment() || attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some()
 }
index 0184a3214b5b4985748e5d17f6e99f4d52be8f35..b0c2aa3dbb28ead5ef9079041b1e7228b6d2866a 100644 (file)
@@ -13,7 +13,7 @@
 #![feature(label_break_value)]
 #![feature(nll)]
 #![feature(try_trait)]
-#![feature(slice_patterns)]
+#![cfg_attr(bootstrap, feature(slice_patterns))]
 #![feature(unicode_internals)]
 #![recursion_limit = "256"]
 
index 58d4e46111b83adb5dc7344c014724dd4b793d0a..750d054e8a0f2d4891709681bb960be492545b91 100644 (file)
@@ -918,10 +918,18 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
             vis.visit_variant_data(variant_data);
             vis.visit_generics(generics);
         }
-        ItemKind::Impl(_unsafety, _polarity, _defaultness, generics, trait_ref, ty, items) => {
+        ItemKind::Impl {
+            unsafety: _,
+            polarity: _,
+            defaultness: _,
+            generics,
+            of_trait,
+            self_ty,
+            items,
+        } => {
             vis.visit_generics(generics);
-            visit_opt(trait_ref, |trait_ref| vis.visit_trait_ref(trait_ref));
-            vis.visit_ty(ty);
+            visit_opt(of_trait, |trait_ref| vis.visit_trait_ref(trait_ref));
+            vis.visit_ty(self_ty);
             items.flat_map_in_place(|item| vis.flat_map_impl_item(item));
         }
         ItemKind::Trait(_is_auto, _unsafety, generics, bounds, items) => {
index 11c8cb8ef750017b1137cbb7266f1871799c3ea1..bc67980c454c0c4093e868a882d8c9d1ba345bc3 100644 (file)
@@ -1226,15 +1226,15 @@ fn print_associated_type(
                 self.head(visibility_qualified(&item.vis, "union"));
                 self.print_struct(struct_def, generics, item.ident, item.span, true);
             }
-            ast::ItemKind::Impl(
+            ast::ItemKind::Impl {
                 unsafety,
                 polarity,
                 defaultness,
                 ref generics,
-                ref opt_trait,
-                ref ty,
-                ref impl_items,
-            ) => {
+                ref of_trait,
+                ref self_ty,
+                ref items,
+            } => {
                 self.head("");
                 self.print_visibility(&item.vis);
                 self.print_defaultness(defaultness);
@@ -1250,19 +1250,19 @@ fn print_associated_type(
                     self.s.word("!");
                 }
 
-                if let Some(ref t) = *opt_trait {
+                if let Some(ref t) = *of_trait {
                     self.print_trait_ref(t);
                     self.s.space();
                     self.word_space("for");
                 }
 
-                self.print_type(ty);
+                self.print_type(self_ty);
                 self.print_where_clause(&generics.where_clause);
 
                 self.s.space();
                 self.bopen();
                 self.print_inner_attributes(&item.attrs);
-                for impl_item in impl_items {
+                for impl_item in items {
                     self.print_assoc_item(impl_item);
                 }
                 self.bclose(item.span);
index 3c2ebacbc4e346a7c2d403cb5035f9b933dafced..d03a9dfc167588b0f83930e2a0c108e0fff781d1 100644 (file)
@@ -308,11 +308,19 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             visitor.visit_generics(generics);
             visitor.visit_enum_def(enum_definition, generics, item.id, item.span)
         }
-        ItemKind::Impl(_, _, _, ref generics, ref opt_trait_reference, ref typ, ref impl_items) => {
+        ItemKind::Impl {
+            unsafety: _,
+            polarity: _,
+            defaultness: _,
+            ref generics,
+            ref of_trait,
+            ref self_ty,
+            ref items,
+        } => {
             visitor.visit_generics(generics);
-            walk_list!(visitor, visit_trait_ref, opt_trait_reference);
-            visitor.visit_ty(typ);
-            walk_list!(visitor, visit_impl_item, impl_items);
+            walk_list!(visitor, visit_trait_ref, of_trait);
+            visitor.visit_ty(self_ty);
+            walk_list!(visitor, visit_impl_item, items);
         }
         ItemKind::Struct(ref struct_definition, ref generics)
         | ItemKind::Union(ref struct_definition, ref generics) => {
index 45669d120c7c276cc8391f5c30857b3e011b399e..e99473177e8384ce3603c32138358fd29db661da 100644 (file)
@@ -153,12 +153,13 @@ pub fn test_main_static_abort(tests: &[&TestDescAndFn]) {
     // If we're being run in SpawnedSecondary mode, run the test here. run_test
     // will then exit the process.
     if let Ok(name) = env::var(SECONDARY_TEST_INVOKER_VAR) {
+        env::remove_var(SECONDARY_TEST_INVOKER_VAR);
         let test = tests
             .iter()
             .filter(|test| test.desc.name.as_slice() == name)
             .map(make_owned_test)
             .next()
-            .expect("couldn't find a test with the provided name");
+            .expect(&format!("couldn't find a test with the provided name '{}'", name));
         let TestDescAndFn { desc, testfn } = test;
         let testfn = match testfn {
             StaticTestFn(f) => f,
@@ -485,9 +486,7 @@ fn run_test_inner(
         }
         StaticBenchFn(benchfn) => {
             // Benchmarks aren't expected to panic, so we run them all in-process.
-            crate::bench::benchmark(desc, monitor_ch, opts.nocapture, |harness| {
-                (benchfn.clone())(harness)
-            });
+            crate::bench::benchmark(desc, monitor_ch, opts.nocapture, benchfn);
         }
         DynTestFn(f) => {
             match strategy {
index 9330ec5a4c1df5fc1fa62f993ed6a04da68cb040..cd87134ab77e6bacb2128137065b328b9c35e0e5 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 9330ec5a4c1df5fc1fa62f993ed6a04da68cb040
+Subproject commit cd87134ab77e6bacb2128137065b328b9c35e0e5
index d5ddfb5e1c24ca9fa126a010342d88655ed217dc..27fb3cb1380d33b32b2d6a5dcb039e988d20eaf4 100644 (file)
@@ -4,7 +4,7 @@
 
 #![feature(start)]
 
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<drop_in_place_intrinsic::StructWithDtor[0]> @@ drop_in_place_intrinsic-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<drop_in_place_intrinsic::StructWithDtor[0]> @@ drop_in_place_intrinsic-cgu.0[Internal]
 struct StructWithDtor(u32);
 
 impl Drop for StructWithDtor {
@@ -16,7 +16,7 @@ fn drop(&mut self) {}
 #[start]
 fn start(_: isize, _: *const *const u8) -> isize {
 
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]; 2]> @@ drop_in_place_intrinsic-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]; 2]> @@ drop_in_place_intrinsic-cgu.0[Internal]
     let x = [StructWithDtor(0), StructWithDtor(1)];
 
     drop_slice_in_place(&x);
@@ -31,7 +31,6 @@ fn drop_slice_in_place(x: &[StructWithDtor]) {
         // not have drop-glue for the unsized [StructWithDtor]. This has to be
         // generated though when the drop_in_place() intrinsic is used.
         //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]]> @@ drop_in_place_intrinsic-cgu.0[Internal]
-        //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]]> @@ drop_in_place_intrinsic-cgu.0[Internal]
         ::std::ptr::drop_in_place(x as *const _ as *mut [StructWithDtor]);
     }
 }
index 94e79f0b32044cb1601a44a1b03f15e04ad8b033..675bdfdb4d250b412ce6c39c691bb68683baa06b 100644 (file)
@@ -37,7 +37,7 @@ enum EnumNoDrop<T1, T2> {
 struct NonGenericNoDrop(i32);
 
 struct NonGenericWithDrop(i32);
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::NonGenericWithDrop[0]> @@ generic_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::NonGenericWithDrop[0]> @@ generic_drop_glue-cgu.0[Internal]
 
 impl Drop for NonGenericWithDrop {
     //~ MONO_ITEM fn generic_drop_glue::{{impl}}[2]::drop[0]
@@ -47,11 +47,11 @@ fn drop(&mut self) {}
 //~ MONO_ITEM fn generic_drop_glue::start[0]
 #[start]
 fn start(_: isize, _: *const *const u8) -> isize {
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<i8, char>> @@ generic_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<i8, char>> @@ generic_drop_glue-cgu.0[Internal]
     //~ MONO_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0]<i8, char>
     let _ = StructWithDrop { x: 0i8, y: 'a' }.x;
 
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]>> @@ generic_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]>> @@ generic_drop_glue-cgu.0[Internal]
     //~ MONO_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]>
     let _ = StructWithDrop { x: "&str", y: NonGenericNoDrop(0) }.y;
 
@@ -60,17 +60,17 @@ fn start(_: isize, _: *const *const u8) -> isize {
 
     // This is supposed to generate drop-glue because it contains a field that
     // needs to be dropped.
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::StructNoDrop[0]<generic_drop_glue::NonGenericWithDrop[0], f64>> @@ generic_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::StructNoDrop[0]<generic_drop_glue::NonGenericWithDrop[0], f64>> @@ generic_drop_glue-cgu.0[Internal]
     let _ = StructNoDrop { x: NonGenericWithDrop(0), y: 0f64 }.y;
 
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::EnumWithDrop[0]<i32, i64>> @@ generic_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::EnumWithDrop[0]<i32, i64>> @@ generic_drop_glue-cgu.0[Internal]
     //~ MONO_ITEM fn generic_drop_glue::{{impl}}[1]::drop[0]<i32, i64>
     let _ = match EnumWithDrop::A::<i32, i64>(0) {
         EnumWithDrop::A(x) => x,
         EnumWithDrop::B(x) => x as i32
     };
 
-    //~MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::EnumWithDrop[0]<f64, f32>> @@ generic_drop_glue-cgu.0[Internal]
+    //~MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::EnumWithDrop[0]<f64, f32>> @@ generic_drop_glue-cgu.0[Internal]
     //~ MONO_ITEM fn generic_drop_glue::{{impl}}[1]::drop[0]<f64, f32>
     let _ = match EnumWithDrop::B::<f64, f32>(1.0) {
         EnumWithDrop::A(x) => x,
index e79b069b25c13d8f55464a4684d765fec998d410..db0390b58c84a3523030edc262d37f31c4739606 100644 (file)
@@ -24,13 +24,13 @@ fn bar(&self) {}
 fn start(_: isize, _: *const *const u8) -> isize {
     let s1 = Struct { _a: 0u32 };
 
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<instantiation_through_vtable::Struct[0]<u32>> @@ instantiation_through_vtable-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<instantiation_through_vtable::Struct[0]<u32>> @@ instantiation_through_vtable-cgu.0[Internal]
     //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0]<u32>
     //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0]<u32>
     let _ = &s1 as &Trait;
 
     let s1 = Struct { _a: 0u64 };
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<instantiation_through_vtable::Struct[0]<u64>> @@ instantiation_through_vtable-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<instantiation_through_vtable::Struct[0]<u64>> @@ instantiation_through_vtable-cgu.0[Internal]
     //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0]<u64>
     //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0]<u64>
     let _ = &s1 as &Trait;
index f13952bb7810ecc78fb35263245db1396f401411..a899b8b2c8b9cf1a831e8ad9d965849c4373ab99 100644 (file)
@@ -5,7 +5,7 @@
 #![deny(dead_code)]
 #![feature(start)]
 
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<non_generic_drop_glue::StructWithDrop[0]> @@ non_generic_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<non_generic_drop_glue::StructWithDrop[0]> @@ non_generic_drop_glue-cgu.0[Internal]
 struct StructWithDrop {
     x: i32
 }
@@ -19,7 +19,7 @@ struct StructNoDrop {
     x: i32
 }
 
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<non_generic_drop_glue::EnumWithDrop[0]> @@ non_generic_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<non_generic_drop_glue::EnumWithDrop[0]> @@ non_generic_drop_glue-cgu.0[Internal]
 enum EnumWithDrop {
     A(i32)
 }
index 14545a33b59450fceaecea870c3ba82747eb05e3..7e29af43538fd317391d05976dcf3ca1c9af371b 100644 (file)
@@ -5,11 +5,11 @@
 #![deny(dead_code)]
 #![feature(start)]
 
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::Root[0]> @@ transitive_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::Root[0]> @@ transitive_drop_glue-cgu.0[Internal]
 struct Root(Intermediate);
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::Intermediate[0]> @@ transitive_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::Intermediate[0]> @@ transitive_drop_glue-cgu.0[Internal]
 struct Intermediate(Leaf);
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::Leaf[0]> @@ transitive_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::Leaf[0]> @@ transitive_drop_glue-cgu.0[Internal]
 struct Leaf;
 
 impl Drop for Leaf {
@@ -30,15 +30,15 @@ fn drop(&mut self) {}
 fn start(_: isize, _: *const *const u8) -> isize {
     let _ = Root(Intermediate(Leaf));
 
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::RootGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal]
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::IntermediateGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal]
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::LeafGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::RootGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::IntermediateGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::LeafGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal]
     //~ MONO_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0]<u32>
     let _ = RootGen(IntermediateGen(LeafGen(0u32)));
 
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::RootGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal]
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::IntermediateGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal]
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::LeafGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::RootGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::IntermediateGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::LeafGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal]
     //~ MONO_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0]<i16>
     let _ = RootGen(IntermediateGen(LeafGen(0i16)));
 
index 54aff575f9117110718e542a57687f8b27654943..d77de53ce010d270811647d817be812e7b37a3f7 100644 (file)
@@ -5,7 +5,7 @@
 #![deny(dead_code)]
 #![feature(start)]
 
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<tuple_drop_glue::Dropped[0]> @@ tuple_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<tuple_drop_glue::Dropped[0]> @@ tuple_drop_glue-cgu.0[Internal]
 struct Dropped;
 
 impl Drop for Dropped {
@@ -16,11 +16,11 @@ fn drop(&mut self) {}
 //~ MONO_ITEM fn tuple_drop_glue::start[0]
 #[start]
 fn start(_: isize, _: *const *const u8) -> isize {
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue-cgu.0[Internal]
     let x = (0u32, Dropped);
 
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(i16, (tuple_drop_glue::Dropped[0], bool))> @@ tuple_drop_glue-cgu.0[Internal]
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(tuple_drop_glue::Dropped[0], bool)> @@ tuple_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(i16, (tuple_drop_glue::Dropped[0], bool))> @@ tuple_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(tuple_drop_glue::Dropped[0], bool)> @@ tuple_drop_glue-cgu.0[Internal]
     let x = (0i16, (Dropped, true));
 
     0
index fd794df37608b131fb566dbe8060c86fd2bbf0b0..1ed60dcf265ff03893f4a1283b55eb3541892a3c 100644 (file)
@@ -48,13 +48,13 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Wrapper<U>> for Wrapper<T>
 fn start(_: isize, _: *const *const u8) -> isize {
     // simple case
     let bool_sized = &true;
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<bool> @@ unsizing-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<bool> @@ unsizing-cgu.0[Internal]
     //~ MONO_ITEM fn unsizing::{{impl}}[0]::foo[0]
     let _bool_unsized = bool_sized as &Trait;
 
     let char_sized = &'a';
 
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<char> @@ unsizing-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<char> @@ unsizing-cgu.0[Internal]
     //~ MONO_ITEM fn unsizing::{{impl}}[1]::foo[0]
     let _char_unsized = char_sized as &Trait;
 
@@ -64,13 +64,13 @@ fn start(_: isize, _: *const *const u8) -> isize {
         _b: 2,
         _c: 3.0f64
     };
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<f64> @@ unsizing-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<f64> @@ unsizing-cgu.0[Internal]
     //~ MONO_ITEM fn unsizing::{{impl}}[2]::foo[0]
     let _struct_unsized = struct_sized as &Struct<Trait>;
 
     // custom coercion
     let wrapper_sized = Wrapper(&0u32);
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<u32> @@ unsizing-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<u32> @@ unsizing-cgu.0[Internal]
     //~ MONO_ITEM fn unsizing::{{impl}}[3]::foo[0]
     let _wrapper_sized = wrapper_sized as Wrapper<Trait>;
 
index 0f3d72d16a96ed17796d2705ea7f1f85146ae620..f85ae0c0774866f42fff66d9ec85e68b5a8ca101 100644 (file)
 // aux-build:cgu_extern_drop_glue.rs
 extern crate cgu_extern_drop_glue;
 
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<cgu_extern_drop_glue::Struct[0]> @@ extern_drop_glue[Internal] extern_drop_glue-mod1[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<cgu_extern_drop_glue::Struct[0]> @@ extern_drop_glue[Internal] extern_drop_glue-mod1[Internal]
 
 struct LocalStruct(cgu_extern_drop_glue::Struct);
 
 //~ MONO_ITEM fn extern_drop_glue::user[0] @@ extern_drop_glue[External]
 pub fn user()
 {
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<extern_drop_glue::LocalStruct[0]> @@ extern_drop_glue[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::LocalStruct[0]> @@ extern_drop_glue[Internal]
     let _ = LocalStruct(cgu_extern_drop_glue::Struct(0));
 }
 
@@ -30,7 +30,7 @@ pub mod mod1 {
     //~ MONO_ITEM fn extern_drop_glue::mod1[0]::user[0] @@ extern_drop_glue-mod1[External]
     pub fn user()
     {
-        //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<extern_drop_glue::mod1[0]::LocalStruct[0]> @@ extern_drop_glue-mod1[Internal]
+        //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::mod1[0]::LocalStruct[0]> @@ extern_drop_glue-mod1[Internal]
         let _ = LocalStruct(cgu_extern_drop_glue::Struct(0));
     }
 }
index 938d4ffb693c9f3c41b9af58d763e11c7ccfe45f..366af4d4c386b51dafc29568a98db3e010d2d6d1 100644 (file)
@@ -7,7 +7,7 @@
 #![allow(dead_code)]
 #![crate_type="rlib"]
 
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<local_drop_glue::Struct[0]> @@ local_drop_glue[Internal] local_drop_glue-mod1[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::Struct[0]> @@ local_drop_glue[Internal] local_drop_glue-mod1[Internal]
 struct Struct {
     _a: u32
 }
@@ -17,7 +17,7 @@ impl Drop for Struct {
     fn drop(&mut self) {}
 }
 
-//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<local_drop_glue::Outer[0]> @@ local_drop_glue[Internal]
+//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::Outer[0]> @@ local_drop_glue[Internal]
 struct Outer {
     _a: Struct
 }
@@ -36,10 +36,10 @@ pub mod mod1
 {
     use super::Struct;
 
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<local_drop_glue::mod1[0]::Struct2[0]> @@ local_drop_glue-mod1[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::mod1[0]::Struct2[0]> @@ local_drop_glue-mod1[Internal]
     struct Struct2 {
         _a: Struct,
-        //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(u32, local_drop_glue::Struct[0])> @@ local_drop_glue-mod1[Internal]
+        //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, local_drop_glue::Struct[0])> @@ local_drop_glue-mod1[Internal]
         _b: (u32, Struct),
     }
 
index 5d23a4e13cbada2c736aab539bd590b1b22261a5..06e2ef6bb225718b77a50c7270570b01d3020527 100644 (file)
@@ -66,7 +66,7 @@ fn do_something_else(&self, x: T) -> T { x }
 //~ MONO_ITEM fn vtable_through_const::start[0]
 #[start]
 fn start(_: isize, _: *const *const u8) -> isize {
-    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<u32> @@ vtable_through_const[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<u32> @@ vtable_through_const[Internal]
 
     // Since Trait1::do_something() is instantiated via its default implementation,
     // it is considered a generic and is instantiated here only because it is
index 959929fbafbf10424f937f4b3b0c2eb68eb8832a..0c7f3bb2020a9de28ebcf17891d8c996e95dad4f 100644 (file)
@@ -21,7 +21,7 @@ pub fn droppy() {
 // regular function exit. We used to have problems with quadratic growths of drop calls in such
 // functions.
 // FIXME(eddyb) the `void @` forces a match on the instruction, instead of the
-// comment, that's `; call core::ptr::real_drop_in_place::<drop::SomeUniqueName>`
+// comment, that's `; call core::intrinsics::drop_in_place::<drop::SomeUniqueName>`
 // for the `v0` mangling, should switch to matching on that once `legacy` is gone.
 // CHECK-NOT: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName
 // CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName
index 5808a8be176d4f15ec0a9f3866765b54375b3983..ca539fb7462a5eb176eabc7eef5686632748c428 100644 (file)
@@ -1,5 +1,5 @@
 fn main() {
-    *(&(4, 5).1);
+    *(&(4, 5).1); // This does not currently propagate (#67862)
 }
 
 // END RUST SOURCE
@@ -35,7 +35,7 @@ fn main() {
 //     ...
 //     _4 = const main::promoted[0];
 //     _2 = &((*_4).1: i32);
-//     _1 = const 5i32;
+//     _1 = (*_2);
 //     ...
 // }
 // END rustc.main.ConstProp.after.mir
index ccecaeac96b83daa95d6305b28d58cd8bc408062..1c88a9e4d5a32ab04c2e18d22d3c6ce4fc50390f 100644 (file)
@@ -113,8 +113,8 @@ fn main() {
 //     }
 // }
 // END rustc.main-{{closure}}.EraseRegions.after.mir
-// START rustc.ptr-real_drop_in_place.Test.SimplifyCfg-make_shim.after.mir
-// fn  std::ptr::real_drop_in_place(_1: &mut Test) -> () {
+// START rustc.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
+// fn  std::intrinsics::drop_in_place(_1: *mut Test) -> () {
 //     ...
 //     bb0: {
 //         Retag([raw] _1);
@@ -126,4 +126,4 @@ fn main() {
 //         return;
 //     }
 // }
-// END rustc.ptr-real_drop_in_place.Test.SimplifyCfg-make_shim.after.mir
+// END rustc.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
index 5a37b67229c37a14b4dc4b8c0a261ca818aa6202..a25375594d3e17c413d3974f381a92fd4266e09c 100644 (file)
@@ -6,7 +6,7 @@ fn main() {
 
 // END RUST SOURCE
 
-// START rustc.ptr-real_drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir
+// START rustc.ptr-drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir
 // let mut _2: usize;
 // let mut _3: usize;
 // let mut _4: usize;
@@ -87,4 +87,4 @@ fn main() {
 //     _3 = Len((*_1));
 //     switchInt(move _2) -> [0usize: bb8, otherwise: bb14];
 // }
-// END rustc.ptr-real_drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir
+// END rustc.ptr-drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir
index f2e1864096ea974f9290d9f44a149ad1195197dd..d587d237227ad0b632ff5b64ea4f541ce2182eb3 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(box_syntax)]
-#![feature(slice_patterns)]
 
 fn move_out_from_end() {
     let a = [box 1, box 2];
index f4d848dfc7ad12084dcf1ddee976683794cc7a8f..88cfb62a0d0948acb1e35fcf957aad33669cac13 100644 (file)
@@ -45,7 +45,7 @@ fn main() {
 // }
 // END rustc.E-V-{{constant}}.mir_map.0.mir
 
-// START rustc.ptr-real_drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir
+// START rustc.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir
 //     bb0: {
 //     goto -> bb7;
 // }
@@ -71,7 +71,7 @@ fn main() {
 //     _2 = &mut (*_1);
 //     _3 = const <std::vec::Vec<i32> as std::ops::Drop>::drop(move _2) -> [return: bb6, unwind: bb5];
 // }
-// END rustc.ptr-real_drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir
+// END rustc.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir
 
 // START rustc.Test-X-{{constructor}}.mir_map.0.mir
 // fn Test::X(_1: usize) -> Test {
diff --git a/src/test/run-make-fulldeps/issue64319/Makefile b/src/test/run-make-fulldeps/issue64319/Makefile
new file mode 100644 (file)
index 0000000..5592f5a
--- /dev/null
@@ -0,0 +1,39 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# Different optimization levels imply different values for `-Zshare-generics`,
+# so try out a whole bunch of combinations to make sure everything is compatible
+all:
+       # First up, try some defaults
+       $(RUSTC) --crate-type rlib foo.rs
+       $(RUSTC) --crate-type dylib bar.rs -C opt-level=3
+
+       # Next try mixing up some things explicitly
+       $(RUSTC) --crate-type rlib foo.rs -Z share-generics=no
+       $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no
+       $(RUSTC) --crate-type rlib foo.rs -Z share-generics=no
+       $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes
+       $(RUSTC) --crate-type rlib foo.rs -Z share-generics=yes
+       $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no
+       $(RUSTC) --crate-type rlib foo.rs -Z share-generics=yes
+       $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes
+
+       # Now combine a whole bunch of options together
+       $(RUSTC) --crate-type rlib foo.rs
+       $(RUSTC) --crate-type dylib bar.rs
+       $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no
+       $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes
+       $(RUSTC) --crate-type dylib bar.rs -C opt-level=1
+       $(RUSTC) --crate-type dylib bar.rs -C opt-level=1 -Z share-generics=no
+       $(RUSTC) --crate-type dylib bar.rs -C opt-level=1 -Z share-generics=yes
+       $(RUSTC) --crate-type dylib bar.rs -C opt-level=2
+       $(RUSTC) --crate-type dylib bar.rs -C opt-level=2 -Z share-generics=no
+       $(RUSTC) --crate-type dylib bar.rs -C opt-level=2 -Z share-generics=yes
+       $(RUSTC) --crate-type dylib bar.rs -C opt-level=3
+       $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 -Z share-generics=no
+       $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 -Z share-generics=yes
+       $(RUSTC) --crate-type dylib bar.rs -C opt-level=s
+       $(RUSTC) --crate-type dylib bar.rs -C opt-level=s -Z share-generics=no
+       $(RUSTC) --crate-type dylib bar.rs -C opt-level=s -Z share-generics=yes
+       $(RUSTC) --crate-type dylib bar.rs -C opt-level=z
+       $(RUSTC) --crate-type dylib bar.rs -C opt-level=z -Z share-generics=no
+       $(RUSTC) --crate-type dylib bar.rs -C opt-level=z -Z share-generics=yes
diff --git a/src/test/run-make-fulldeps/issue64319/bar.rs b/src/test/run-make-fulldeps/issue64319/bar.rs
new file mode 100644 (file)
index 0000000..3895c0b
--- /dev/null
@@ -0,0 +1,5 @@
+extern crate foo;
+
+pub fn bar() {
+    foo::foo();
+}
diff --git a/src/test/run-make-fulldeps/issue64319/foo.rs b/src/test/run-make-fulldeps/issue64319/foo.rs
new file mode 100644 (file)
index 0000000..c54a238
--- /dev/null
@@ -0,0 +1,9 @@
+pub fn foo() {
+    bar::<usize>();
+}
+
+pub fn bar<T>() {
+    baz();
+}
+
+fn baz() {}
diff --git a/src/test/run-make-fulldeps/sanitizer-address/Makefile b/src/test/run-make-fulldeps/sanitizer-address/Makefile
deleted file mode 100644 (file)
index 7f5e904..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# needs-sanitizer-support
-
--include ../tools.mk
-
-LOG := $(TMPDIR)/log.txt
-
-# NOTE the address sanitizer only supports x86_64 linux and macOS
-
-ifeq ($(TARGET),x86_64-apple-darwin)
-EXTRA_RUSTFLAG=-C rpath
-else
-ifeq ($(TARGET),x86_64-unknown-linux-gnu)
-
-# Apparently there are very specific Linux kernels, notably the one that's
-# currently on Travis CI, which contain a buggy commit that triggers failures in
-# the ASan implementation, detailed at google/sanitizers#837. As noted in
-# google/sanitizers#856 the "fix" is to avoid using PIE binaries, so we pass a
-# different relocation model to avoid generating a PIE binary. Once Travis is no
-# longer running kernel 4.4.0-93 we can remove this and pass an empty set of
-# flags again.
-EXTRA_RUSTFLAG=-C relocation-model=dynamic-no-pic
-endif
-endif
-
-all:
-       $(RUSTC) -g -Z sanitizer=address -Z print-link-args $(EXTRA_RUSTFLAG) overflow.rs | $(CGREP) rustc_rt.asan
-       # Verify that stack buffer overflow is detected:
-       $(TMPDIR)/overflow 2>&1 | $(CGREP) stack-buffer-overflow
-       # Verify that variable name is included in address sanitizer report:
-       $(TMPDIR)/overflow 2>&1 | $(CGREP) "'xs'"
diff --git a/src/test/run-make-fulldeps/sanitizer-address/overflow.rs b/src/test/run-make-fulldeps/sanitizer-address/overflow.rs
deleted file mode 100644 (file)
index b997a74..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
-    let xs = [0, 1, 2, 3];
-    let _y = unsafe { *xs.as_ptr().offset(4) };
-}
diff --git a/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile b/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile
deleted file mode 100644 (file)
index 2a23f0f..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
--include ../tools.mk
-
-all:
-       $(RUSTC) -Z sanitizer=leak --target i686-unknown-linux-gnu hello.rs 2>&1 | \
-               $(CGREP) 'LeakSanitizer only works with the `x86_64-unknown-linux-gnu` or `x86_64-apple-darwin` target'
diff --git a/src/test/run-make-fulldeps/sanitizer-invalid-target/hello.rs b/src/test/run-make-fulldeps/sanitizer-invalid-target/hello.rs
deleted file mode 100644 (file)
index d3dd5ed..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#![feature(no_core)]
-#![no_core]
-#![no_main]
diff --git a/src/test/run-make-fulldeps/sanitizer-leak/Makefile b/src/test/run-make-fulldeps/sanitizer-leak/Makefile
deleted file mode 100644 (file)
index da37033..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
--include ../tools.mk
-
-# needs-sanitizer-support
-
-all:
-       $(RUSTC) -O -Z sanitizer=leak -Z print-link-args leak.rs | $(CGREP) rustc_rt.lsan
-       $(TMPDIR)/leak 2>&1 | $(CGREP) 'detected memory leaks'
diff --git a/src/test/run-make-fulldeps/sanitizer-leak/leak.rs b/src/test/run-make-fulldeps/sanitizer-leak/leak.rs
deleted file mode 100644 (file)
index fb0a917..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#![feature(test)]
-
-use std::hint::black_box;
-use std::mem;
-
-fn main() {
-    for _ in 0..10 {
-        let xs = vec![1, 2, 3];
-        // Prevent compiler from removing the memory allocation.
-        let xs = black_box(xs);
-        mem::forget(xs);
-    }
-}
diff --git a/src/test/run-make-fulldeps/sanitizer-memory/Makefile b/src/test/run-make-fulldeps/sanitizer-memory/Makefile
deleted file mode 100644 (file)
index 8bc9df1..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
--include ../tools.mk
-
-# needs-sanitizer-support
-# only-linux
-# only-x86_64
-
-all:
-       $(RUSTC) -g -Z sanitizer=memory -Z print-link-args uninit.rs | $(CGREP) rustc_rt.msan
-       $(TMPDIR)/uninit 2>&1 | $(CGREP) use-of-uninitialized-value
-       $(RUSTC) -g -Z sanitizer=memory -Z print-link-args maybeuninit.rs | $(CGREP) rustc_rt.msan
-       $(TMPDIR)/maybeuninit 2>&1 | $(CGREP) use-of-uninitialized-value
diff --git a/src/test/run-make-fulldeps/sanitizer-memory/maybeuninit.rs b/src/test/run-make-fulldeps/sanitizer-memory/maybeuninit.rs
deleted file mode 100644 (file)
index a9ae85f..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-use std::mem::MaybeUninit;
-
-fn main() {
-    // This is technically not sound -- but we're literally trying to test
-    // that the sanitizer catches this, so I guess "intentionally unsound"?
-    let xs: [u8; 4] = unsafe { MaybeUninit::uninit().assume_init() };
-    let y = xs[0] + xs[1];
-}
diff --git a/src/test/run-make-fulldeps/sanitizer-memory/uninit.rs b/src/test/run-make-fulldeps/sanitizer-memory/uninit.rs
deleted file mode 100644 (file)
index eae5250..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-fn main() {
-    // This is technically not sound -- but we're literally trying to test
-    // that the sanitizer catches this, so I guess "intentionally unsound"?
-    #[allow(deprecated)]
-    let xs: [u8; 4] = unsafe { std::mem::uninitialized() };
-    let y = xs[0] + xs[1];
-}
diff --git a/src/test/run-make-fulldeps/share-generics-dylib/Makefile b/src/test/run-make-fulldeps/share-generics-dylib/Makefile
new file mode 100644 (file)
index 0000000..c6b5efc
--- /dev/null
@@ -0,0 +1,22 @@
+# This test makes sure all generic instances get re-exported from Rust dylibs for use by
+# `-Zshare-generics`. There are two rlibs (`instance_provider_a` and `instance_provider_b`)
+# which both provide an instance of `Cell<i32>::set`. There is `instance_user_dylib` which is
+# supposed to re-export both these instances, and then there are `instance_user_a_rlib` and
+# `instance_user_b_rlib` which each rely on a specific instance to be available.
+#
+# In the end everything is linked together into `linked_leaf`. If `instance_user_dylib` does
+# not export both then we'll get an `undefined reference` error for one of the instances.
+#
+# This is regression test for https://github.com/rust-lang/rust/issues/67276.
+
+-include ../../run-make-fulldeps/tools.mk
+
+COMMON_ARGS=-Cprefer-dynamic -Zshare-generics=yes -Ccodegen-units=1 -Zsymbol-mangling-version=v0
+
+all:
+       $(RUSTC) instance_provider_a.rs $(COMMON_ARGS) --crate-type=rlib
+       $(RUSTC) instance_provider_b.rs $(COMMON_ARGS) --crate-type=rlib
+       $(RUSTC) instance_user_dylib.rs $(COMMON_ARGS) --crate-type=dylib
+       $(RUSTC) instance_user_a_rlib.rs $(COMMON_ARGS) --crate-type=rlib
+       $(RUSTC) instance_user_b_rlib.rs $(COMMON_ARGS) --crate-type=rlib
+       $(RUSTC) linked_leaf.rs $(COMMON_ARGS) --crate-type=bin
diff --git a/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_a.rs b/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_a.rs
new file mode 100644 (file)
index 0000000..b4e125a
--- /dev/null
@@ -0,0 +1,6 @@
+use std::cell::Cell;
+
+pub fn foo() {
+    let a: Cell<i32> = Cell::new(1);
+    a.set(123);
+}
diff --git a/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_b.rs b/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_b.rs
new file mode 100644 (file)
index 0000000..f613db8
--- /dev/null
@@ -0,0 +1,6 @@
+use std::cell::Cell;
+
+pub fn foo() {
+    let b: Cell<i32> = Cell::new(1);
+    b.set(123);
+}
diff --git a/src/test/run-make-fulldeps/share-generics-dylib/instance_user_a_rlib.rs b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_a_rlib.rs
new file mode 100644 (file)
index 0000000..c8e6ab9
--- /dev/null
@@ -0,0 +1,9 @@
+extern crate instance_provider_a as upstream;
+use std::cell::Cell;
+
+pub fn foo() {
+    upstream::foo();
+
+    let b: Cell<i32> = Cell::new(1);
+    b.set(123);
+}
diff --git a/src/test/run-make-fulldeps/share-generics-dylib/instance_user_b_rlib.rs b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_b_rlib.rs
new file mode 100644 (file)
index 0000000..7c34af6
--- /dev/null
@@ -0,0 +1,9 @@
+extern crate instance_provider_b as upstream;
+use std::cell::Cell;
+
+pub fn foo() {
+    upstream::foo();
+
+    let b: Cell<i32> = Cell::new(1);
+    b.set(123);
+}
diff --git a/src/test/run-make-fulldeps/share-generics-dylib/instance_user_dylib.rs b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_dylib.rs
new file mode 100644 (file)
index 0000000..7c8368e
--- /dev/null
@@ -0,0 +1,7 @@
+extern crate instance_provider_a;
+extern crate instance_provider_b;
+
+pub fn foo() {
+    instance_provider_a::foo();
+    instance_provider_b::foo();
+}
diff --git a/src/test/run-make-fulldeps/share-generics-dylib/linked_leaf.rs b/src/test/run-make-fulldeps/share-generics-dylib/linked_leaf.rs
new file mode 100644 (file)
index 0000000..e510dad
--- /dev/null
@@ -0,0 +1,15 @@
+extern crate instance_user_dylib;
+extern crate instance_user_a_rlib;
+extern crate instance_user_b_rlib;
+
+use std::cell::Cell;
+
+fn main() {
+
+    instance_user_a_rlib::foo();
+    instance_user_b_rlib::foo();
+    instance_user_dylib::foo();
+
+    let a: Cell<i32> = Cell::new(1);
+    a.set(123);
+}
index 34e92c421047d26acbb0a48886b75bf937b9344a..72037dd74be355d9d0ada09fbff99b0774fd15d3 100644 (file)
@@ -93,3 +93,9 @@ pub fn empty_rust_with_whitespace() {}
 ///
 pub fn indent_after_fenced() {}
 //~^^^ WARNING could not parse code block as Rust code
+
+/// ```
+/// "invalid
+/// ```
+pub fn invalid() {}
+//~^^^^ WARNING could not parse code block as Rust code
index 32cc20755ecf4b189a20dd1cc61f4f73f8296e4e..a90d3bbb979f66ad7edf09e2f2b24bb91af954c6 100644 (file)
@@ -132,3 +132,18 @@ LL | ///     \____/
    |
    = note: error from rustc: unknown start of token: \
 
+warning: could not parse code block as Rust code
+  --> $DIR/invalid-syntax.rs:97:5
+   |
+LL |   /// ```
+   |  _____^
+LL | | /// "invalid
+LL | | /// ```
+   | |_______^
+   |
+   = note: error from rustc: unterminated double quote string
+help: mark blocks that do not contain Rust code as text
+   |
+LL | /// ```text
+   |     ^^^^^^^
+
diff --git a/src/test/rustdoc-ui/test-compile-fail1.rs b/src/test/rustdoc-ui/test-compile-fail1.rs
new file mode 100644 (file)
index 0000000..a053902
--- /dev/null
@@ -0,0 +1,8 @@
+// compile-flags:--test
+
+/// ```
+/// assert!(true)
+/// ```
+pub fn f() {}
+
+pub fn f() {}
diff --git a/src/test/rustdoc-ui/test-compile-fail1.stderr b/src/test/rustdoc-ui/test-compile-fail1.stderr
new file mode 100644 (file)
index 0000000..2b38ba9
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0428]: the name `f` is defined multiple times
+ --> $DIR/test-compile-fail1.rs:8:1
+  |
+6 | pub fn f() {}
+  | ---------- previous definition of the value `f` here
+7 | 
+8 | pub fn f() {}
+  | ^^^^^^^^^^ `f` redefined here
+  |
+  = note: `f` must be defined only once in the value namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/rustdoc-ui/test-compile-fail2.rs b/src/test/rustdoc-ui/test-compile-fail2.rs
new file mode 100644 (file)
index 0000000..651ded0
--- /dev/null
@@ -0,0 +1,3 @@
+// compile-flags:--test
+
+fail
diff --git a/src/test/rustdoc-ui/test-compile-fail2.stderr b/src/test/rustdoc-ui/test-compile-fail2.stderr
new file mode 100644 (file)
index 0000000..cee5b63
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected one of `!` or `::`, found `<eof>`
+ --> $DIR/test-compile-fail2.rs:3:1
+  |
+3 | fail
+  | ^^^^ expected one of `!` or `::`
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/test-compile-fail3.rs b/src/test/rustdoc-ui/test-compile-fail3.rs
new file mode 100644 (file)
index 0000000..faa30ad
--- /dev/null
@@ -0,0 +1,3 @@
+// compile-flags:--test
+
+"fail
diff --git a/src/test/rustdoc-ui/test-compile-fail3.stderr b/src/test/rustdoc-ui/test-compile-fail3.stderr
new file mode 100644 (file)
index 0000000..7a2f181
--- /dev/null
@@ -0,0 +1,8 @@
+error: unterminated double quote string
+ --> $DIR/test-compile-fail3.rs:3:1
+  |
+3 | "fail
+  | ^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/test-no_std.rs b/src/test/rustdoc-ui/test-no_std.rs
new file mode 100644 (file)
index 0000000..166a873
--- /dev/null
@@ -0,0 +1,12 @@
+// compile-flags:--test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// build-pass
+
+#![no_std]
+
+extern crate alloc;
+
+/// ```
+/// assert!(true)
+/// ```
+pub fn f() {}
diff --git a/src/test/rustdoc-ui/test-no_std.stdout b/src/test/rustdoc-ui/test-no_std.stdout
new file mode 100644 (file)
index 0000000..9cdcac2
--- /dev/null
@@ -0,0 +1,6 @@
+
+running 1 test
+test $DIR/test-no_std.rs - f (line 9) ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
+
index ae8fbe4a2a800d2d7440558bffde05fb184ee297..afef86ec9c77f265f481bb0d6d73accece4a4664 100644 (file)
@@ -33,3 +33,10 @@ pub fn ok() {}
 /// <script>alert("not valid Rust");</script>
 /// ```
 pub fn escape() {}
+
+// @has bad_codeblock_syntax/fn.unterminated.html
+// @has - '//*[@class="docblock"]/pre/code' '"unterminated'
+/// ```
+/// "unterminated
+/// ```
+pub fn unterminated() {}
diff --git a/src/test/rustdoc/deref-typedef.rs b/src/test/rustdoc/deref-typedef.rs
new file mode 100644 (file)
index 0000000..770f8d7
--- /dev/null
@@ -0,0 +1,33 @@
+#![crate_name = "foo"]
+
+// @has 'foo/struct.Bar.html'
+// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref<Target = FooC>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_a"]' 'pub fn foo_a(&self)'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_b"]' 'pub fn foo_b(&self)'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_c"]' 'pub fn foo_c(&self)'
+// @has '-' '//*[@class="sidebar-title"]' 'Methods from Deref<Target=FooC>'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_a"]' 'foo_a'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_b"]' 'foo_b'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_c"]' 'foo_c'
+
+pub struct FooA;
+pub type FooB = FooA;
+pub type FooC = FooB;
+
+impl FooA {
+    pub fn foo_a(&self) {}
+}
+
+impl FooB {
+    pub fn foo_b(&self) {}
+}
+
+impl FooC {
+    pub fn foo_c(&self) {}
+}
+
+pub struct Bar;
+impl std::ops::Deref for Bar {
+    type Target = FooC;
+    fn deref(&self) -> &Self::Target { unimplemented!() }
+}
diff --git a/src/test/rustdoc/remove-url-from-headings.rs b/src/test/rustdoc/remove-url-from-headings.rs
new file mode 100644 (file)
index 0000000..9761c1d
--- /dev/null
@@ -0,0 +1,17 @@
+#![crate_name = "foo"]
+
+// @has foo/fn.foo.html
+// !@has - '//a[@href="http://a.a"]'
+// @has - '//a[@href="#implementing-stuff-somewhere"]' 'Implementing stuff somewhere'
+// @has - '//a[@href="#another-one-urg"]' 'Another one urg'
+
+/// fooo
+///
+/// # Implementing [stuff](http://a.a "title") somewhere
+///
+/// hello
+///
+/// # Another [one][two] urg
+///
+/// [two]: http://a.a
+pub fn foo() {}
diff --git a/src/test/ui/array-slice-vec/slice-pat-type-mismatches.rs b/src/test/ui/array-slice-vec/slice-pat-type-mismatches.rs
new file mode 100644 (file)
index 0000000..34adb42
--- /dev/null
@@ -0,0 +1,36 @@
+fn main() {
+    match "foo".to_string() {
+        ['f', 'o', ..] => {}
+        //~^ ERROR expected an array or slice, found `std::string::String`
+        _ => { }
+    };
+
+    // Note that this one works with default binding modes.
+    match &[0, 1, 2] {
+        [..] => {}
+    };
+
+    match &[0, 1, 2] {
+        &[..] => {} // ok
+    };
+
+    match [0, 1, 2] {
+        [0] => {}, //~ ERROR pattern requires
+
+        [0, 1, x @ ..] => {
+            let a: [_; 1] = x;
+        }
+        [0, 1, 2, 3, x @ ..] => {} //~ ERROR pattern requires
+    };
+
+    match does_not_exist { //~ ERROR cannot find value `does_not_exist` in this scope
+        [] => {}
+    };
+}
+
+fn another_fn_to_avoid_suppression() {
+    match Default::default()
+    {
+        [] => {}  //~ ERROR type annotations needed
+    };
+}
diff --git a/src/test/ui/array-slice-vec/slice-pat-type-mismatches.stderr b/src/test/ui/array-slice-vec/slice-pat-type-mismatches.stderr
new file mode 100644 (file)
index 0000000..c454814
--- /dev/null
@@ -0,0 +1,36 @@
+error[E0425]: cannot find value `does_not_exist` in this scope
+  --> $DIR/slice-pat-type-mismatches.rs:26:11
+   |
+LL |     match does_not_exist {
+   |           ^^^^^^^^^^^^^^ not found in this scope
+
+error[E0529]: expected an array or slice, found `std::string::String`
+  --> $DIR/slice-pat-type-mismatches.rs:3:9
+   |
+LL |         ['f', 'o', ..] => {}
+   |         ^^^^^^^^^^^^^^ pattern cannot match with input type `std::string::String`
+
+error[E0527]: pattern requires 1 element but array has 3
+  --> $DIR/slice-pat-type-mismatches.rs:18:9
+   |
+LL |         [0] => {},
+   |         ^^^ expected 3 elements
+
+error[E0528]: pattern requires at least 4 elements but array has 3
+  --> $DIR/slice-pat-type-mismatches.rs:23:9
+   |
+LL |         [0, 1, 2, 3, x @ ..] => {}
+   |         ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 3 elements
+
+error[E0282]: type annotations needed
+  --> $DIR/slice-pat-type-mismatches.rs:34:9
+   |
+LL |         [] => {}
+   |         ^^ cannot infer type
+   |
+   = note: type must be known at this point
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0282, E0425, E0527, E0528, E0529.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.rs b/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.rs
new file mode 100644 (file)
index 0000000..97e3362
--- /dev/null
@@ -0,0 +1,11 @@
+fn main() {
+    let a: &[u8] = &[];
+    match a {
+        [1, tail @ .., tail @ ..] => {},
+        //~^ ERROR identifier `tail` is bound more than once in the same pattern
+        //~| ERROR `..` can only be used once per slice pattern
+        _ => ()
+    }
+}
+
+const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
diff --git a/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.stderr b/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.stderr
new file mode 100644 (file)
index 0000000..4d60787
--- /dev/null
@@ -0,0 +1,24 @@
+error[E0416]: identifier `tail` is bound more than once in the same pattern
+  --> $DIR/subslice-only-once-semantic-restriction.rs:4:24
+   |
+LL |         [1, tail @ .., tail @ ..] => {},
+   |                        ^^^^ used in a pattern more than once
+
+error: `..` can only be used once per slice pattern
+  --> $DIR/subslice-only-once-semantic-restriction.rs:4:31
+   |
+LL |         [1, tail @ .., tail @ ..] => {},
+   |                    --         ^^ can only be used once per slice pattern
+   |                    |
+   |                    previously used here
+
+error[E0308]: mismatched types
+  --> $DIR/subslice-only-once-semantic-restriction.rs:11:30
+   |
+LL | const RECOVERY_WITNESS: () = 0;
+   |                              ^ expected `()`, found integer
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0308, E0416.
+For more information about an error, try `rustc --explain E0308`.
index 0e767d9613a996b7f591cfb472aab1d58b6e82f9..69c33921868cfd0a62c2b909a021f14f8b5ebacd 100644 (file)
@@ -2,7 +2,7 @@
 
 // run-pass
 
-#![feature(slice_patterns, const_fn, const_if_match)]
+#![feature(const_fn, const_if_match)]
 #[derive(PartialEq, Debug, Clone)]
 struct N(u8);
 
index 5444f8a9051bdae248ee4b09fb684ecc93f09053..0b793fa0120e99f1f1988b409a4e444ad4d3e2ff 100644 (file)
@@ -2,8 +2,6 @@
 
 // run-pass
 
-#![feature(slice_patterns)]
-
 #[derive(PartialEq, Debug, Clone)]
 struct N(u8);
 
index 1ebf3def78876b5622c6713f2d4f00f660a7377c..e05790911f52d9b3e0ca2eb9fcb233ba7607edbf 100644 (file)
@@ -4,8 +4,6 @@
 
 // run-pass
 
-#![feature(slice_patterns)]
-
 #![allow(unreachable_patterns)]
 
 use std::convert::identity;
index 5253bc1b2143067768edf9dc5c2863e0b224fdd3..fdeb7e4fda640a5c118ab5eed6d1cae4a1d4e5c8 100644 (file)
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(slice_patterns)]
-
 fn a() {
     let x = [1, 2, 3];
     match x {
index f416160db242247af496b9fcec2a33b7e61fc6a5..998899271e4114a05c461eae5c6345ae9b7a4f7c 100644 (file)
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(slice_patterns)]
-
 use std::fmt::Debug;
 
 fn foldl<T, U, F>(values: &[T],
index f0602c328b071af010092e6b513c8970b72ede24..ed34f074a929aa53fb1617434f54846da5aa041a 100644 (file)
@@ -1,7 +1,6 @@
 // run-pass
-#![allow(unused_variables)]
 
-#![feature(slice_patterns)]
+#![allow(unused_variables)]
 
 pub fn main() {
     let x = &[1, 2, 3, 4, 5];
index 49c736bd72847377503b7942da89fa5e126d0986..7009244aa189a9e79b54b9494dc4ec840ef85e0b 100644 (file)
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(slice_patterns)]
-
 fn a() {
     let x = [1];
     match x {
index 3c7b160dcc54038a9e218761b84e6c3c86184cac..5f1699227d8e601634a2b2ff0e91e28b3226ae9b 100644 (file)
@@ -1,7 +1,5 @@
 // run-pass
 
-#![feature(slice_patterns)]
-
 struct Foo {
     string: &'static str
 }
index 645c903c6bab20c62e86e9953397592ee55ca7bd..ceeebbca5195a3584af408e1ee3502588e542479 100644 (file)
@@ -2,15 +2,15 @@
 // edition:2018
 // compile-flags: --crate-type lib
 
-use std::{
-    cell::RefCell,
-    fmt::Debug,
-    rc::Rc,
-};
+use std::{cell::RefCell, fmt::Debug, rc::Rc};
 
-fn non_sync() -> impl Debug { RefCell::new(()) }
+fn non_sync() -> impl Debug {
+    RefCell::new(())
+}
 
-fn non_send() -> impl Debug { Rc::new(()) }
+fn non_send() -> impl Debug {
+    Rc::new(())
+}
 
 fn take_ref<T>(_: &T) {}
 
@@ -53,5 +53,4 @@ pub fn pass_assert() {
     //~^ ERROR future cannot be sent between threads safely
     assert_send(non_sync_with_method_call());
     //~^ ERROR future cannot be sent between threads safely
-    //~^^ ERROR future cannot be sent between threads safely
 }
index 5c870ca2d0276825fe84e72a4054d53c6c1a6e32..105fd23ecfb6639d5ea5cdcc28da7d3490fde923 100644 (file)
@@ -62,27 +62,5 @@ LL |     }
 LL | }
    | - `f` is later dropped here
 
-error: future cannot be sent between threads safely
-  --> $DIR/async-fn-nonsend.rs:54:5
-   |
-LL | fn assert_send(_: impl Send) {}
-   |    -----------         ---- required by this bound in `assert_send`
-...
-LL |     assert_send(non_sync_with_method_call());
-   |     ^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
-   |
-   = help: within `std::fmt::ArgumentV1<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)`
-note: future is not `Send` as this value is used across an await
-  --> $DIR/async-fn-nonsend.rs:43:9
-   |
-LL |     let f: &mut std::fmt::Formatter = panic!();
-   |         - has type `&mut std::fmt::Formatter<'_>`
-LL |     if non_sync().fmt(f).unwrap() == () {
-LL |         fut().await;
-   |         ^^^^^^^^^^^ await occurs here, with `f` maybe used later
-LL |     }
-LL | }
-   | - `f` is later dropped here
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
index 77d0885c38d58a75c4624102d11dd7d638573a35..f59dbc263840077dbb02bb71b9717ec71494230f 100644 (file)
@@ -1,8 +1,17 @@
 error: future cannot be sent between threads safely
   --> $DIR/issue-64130-4-async-move.rs:15:17
    |
-LL | pub fn foo() -> impl Future + Send {
-   |                 ^^^^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
+LL |   pub fn foo() -> impl Future + Send {
+   |                   ^^^^^^^^^^^^^^^^^^ future returned by `foo` is not `Send`
+...
+LL | /     async move {
+LL | |         match client.status() {
+LL | |             200 => {
+LL | |                 let _x = get().await;
+...  |
+LL | |         }
+LL | |     }
+   | |_____- this returned value is of type `impl std::future::Future`
    |
    = help: the trait `std::marker::Sync` is not implemented for `(dyn std::any::Any + std::marker::Send + 'static)`
 note: future is not `Send` as this value is used across an await
index 4271ffb7b1b4dcb94e9781052af844f70c4c9467..0d0dbcaf40f4349de9c61afe800c7842080d79dc 100644 (file)
@@ -1,7 +1,8 @@
 // run-pass
+
 #![feature(never_type, never_type_fallback)]
 #![feature(exhaustive_patterns)]
-#![feature(slice_patterns)]
+
 #![allow(unreachable_patterns)]
 #![allow(unreachable_code)]
 #![allow(unused_variables)]
index ac733ef6e9c862c7b96628fefb8ad34ecc26072c..048e1e5e9b4b6b81297e637a6abb2423ddf49369 100644 (file)
@@ -1,7 +1,6 @@
 // run-pass
-// #47096
 
-#![feature(slice_patterns)]
+// Regression test for #47096.
 
 fn foo(s: &[i32]) -> &[i32] {
     let &[ref xs @ ..] = s;
index e87745705da08d922c674a80904209d4e2e921d7..f0c988c01c2b843291ac193cf42fc1a68337f7d8 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn main() {
     let buf = &[0u8; 4];
index 9b06a86a7b91ea7a813b3aa329428bd05d49f104..af95eb95df04cab1cc6f854423e9963442372448 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) -> &'static str {
     match (l1, l2) {
index 5326fa612a87bed365fa28a763af3d040a1f3391..187c2983633e7dcb3a18e34bfa56102393ccfd0f 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn main() {
     let x = [(), ()];
index a70ccb7aa4b73ccd51c7f5cbee83a09a70ac9eb0..0229ca37a692aa3d2a8ff5001e62b4eec0a92656 100644 (file)
@@ -1,6 +1,5 @@
 // Check that closure captures for slice patterns are inferred correctly
 
-#![feature(slice_patterns)]
 #![allow(unused_variables)]
 
 // run-pass
index 984eb8804b7a2ea7be683182b4fc62e25c070ba4..32057d5c126ed4782b78bd0575d724c05388984f 100644 (file)
@@ -1,7 +1,5 @@
 // Check that closure captures for slice patterns are inferred correctly
 
-#![feature(slice_patterns)]
-
 fn arr_by_ref(mut x: [String; 3]) {
     let f = || {
         let [ref y, ref z @ ..] = x;
index c5b27f5f8b4032d34ae46e4f041d5f4f67c0ad77..483975e5778a893c5cd5ef750c11c9f51753f2dc 100644 (file)
@@ -1,5 +1,5 @@
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-closures-slice-patterns.rs:9:13
+  --> $DIR/borrowck-closures-slice-patterns.rs:7:13
    |
 LL |     let f = || {
    |             -- immutable borrow occurs here
@@ -13,7 +13,7 @@ LL |     f();
    |     - immutable borrow later used here
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-closures-slice-patterns.rs:18:13
+  --> $DIR/borrowck-closures-slice-patterns.rs:16:13
    |
 LL |     let mut f = || {
    |                 -- mutable borrow occurs here
@@ -27,7 +27,7 @@ LL |     f();
    |     - mutable borrow later used here
 
 error[E0382]: borrow of moved value: `x`
-  --> $DIR/borrowck-closures-slice-patterns.rs:27:5
+  --> $DIR/borrowck-closures-slice-patterns.rs:25:5
    |
 LL | fn arr_by_move(x: [String; 3]) {
    |                - move occurs because `x` has type `[std::string::String; 3]`, which does not implement the `Copy` trait
@@ -40,7 +40,7 @@ LL |     &x;
    |     ^^ value borrowed here after move
 
 error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-closures-slice-patterns.rs:35:13
+  --> $DIR/borrowck-closures-slice-patterns.rs:33:13
    |
 LL |     let f = || {
    |             -- immutable borrow occurs here
@@ -54,7 +54,7 @@ LL |     f();
    |     - immutable borrow later used here
 
 error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access
-  --> $DIR/borrowck-closures-slice-patterns.rs:44:13
+  --> $DIR/borrowck-closures-slice-patterns.rs:42:13
    |
 LL |     let mut f = || {
    |                 -- closure construction occurs here
@@ -68,7 +68,7 @@ LL |     f();
    |     - first borrow later used here
 
 error[E0382]: borrow of moved value: `x`
-  --> $DIR/borrowck-closures-slice-patterns.rs:53:5
+  --> $DIR/borrowck-closures-slice-patterns.rs:51:5
    |
 LL | fn arr_box_by_move(x: Box<[String; 3]>) {
    |                    - move occurs because `x` has type `std::boxed::Box<[std::string::String; 3]>`, which does not implement the `Copy` trait
@@ -81,7 +81,7 @@ LL |     &x;
    |     ^^ value borrowed here after move
 
 error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-closures-slice-patterns.rs:61:13
+  --> $DIR/borrowck-closures-slice-patterns.rs:59:13
    |
 LL |     let f = || {
    |             -- immutable borrow occurs here
@@ -95,7 +95,7 @@ LL |     f();
    |     - immutable borrow later used here
 
 error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access
-  --> $DIR/borrowck-closures-slice-patterns.rs:70:13
+  --> $DIR/borrowck-closures-slice-patterns.rs:68:13
    |
 LL |     let mut f = || {
    |                 -- closure construction occurs here
index 8425960aa8600bdb0280840a488e464f690c041c..c8bfbe0729c59032e489b84c9f51445cded345f7 100644 (file)
@@ -1,7 +1,5 @@
 // ignore-tidy-linelength
 
-#![feature(slice_patterns)]
-
 pub struct Foo {
   x: u32
 }
index 4213523d2fa4b1d188f13172e8828808f8eb0ebe..075e0e2e4515e69a99a5f472ec9473cc0c33d6fe 100644 (file)
@@ -1,5 +1,5 @@
 error[E0499]: cannot borrow `x` as mutable more than once at a time
-  --> $DIR/borrowck-describe-lvalue.rs:258:13
+  --> $DIR/borrowck-describe-lvalue.rs:256:13
    |
 LL |             let y = &mut x;
    |                     ------ first mutable borrow occurs here
@@ -9,7 +9,7 @@ LL |             *y = 1;
    |             ------ first borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
-  --> $DIR/borrowck-describe-lvalue.rs:268:20
+  --> $DIR/borrowck-describe-lvalue.rs:266:20
    |
 LL |                    let y = &mut x;
    |                            ------ first mutable borrow occurs here
@@ -19,7 +19,7 @@ LL |                    *y = 1;
    |                    ------ first borrow later used here
 
 error: captured variable cannot escape `FnMut` closure body
-  --> $DIR/borrowck-describe-lvalue.rs:266:16
+  --> $DIR/borrowck-describe-lvalue.rs:264:16
    |
 LL |              || {
    |               - inferred to be a `FnMut` closure
@@ -35,7 +35,7 @@ LL | |                 }
    = note: ...therefore, they cannot allow references to captured variables to escape
 
 error[E0503]: cannot use `f.x` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:41:9
+  --> $DIR/borrowck-describe-lvalue.rs:39:9
    |
 LL |         let x = f.x();
    |                 - borrow of `f` occurs here
@@ -45,7 +45,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `g.0` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:48:9
+  --> $DIR/borrowck-describe-lvalue.rs:46:9
    |
 LL |         let x = g.x();
    |                 - borrow of `g` occurs here
@@ -55,7 +55,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `h.0` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:55:9
+  --> $DIR/borrowck-describe-lvalue.rs:53:9
    |
 LL |         let x = &mut h.0;
    |                 -------- borrow of `h.0` occurs here
@@ -65,7 +65,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `e.0` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:63:20
+  --> $DIR/borrowck-describe-lvalue.rs:61:20
    |
 LL |         let x = e.x();
    |                 - borrow of `e` occurs here
@@ -77,7 +77,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `u.a` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:71:9
+  --> $DIR/borrowck-describe-lvalue.rs:69:9
    |
 LL |         let x = &mut u.a;
    |                 -------- borrow of `u.a` occurs here
@@ -87,7 +87,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `f.x` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:78:9
+  --> $DIR/borrowck-describe-lvalue.rs:76:9
    |
 LL |         let x = f.x();
    |                 - borrow of `*f` occurs here
@@ -97,7 +97,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `g.0` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:85:9
+  --> $DIR/borrowck-describe-lvalue.rs:83:9
    |
 LL |         let x = g.x();
    |                 - borrow of `*g` occurs here
@@ -107,7 +107,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `h.0` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:92:9
+  --> $DIR/borrowck-describe-lvalue.rs:90:9
    |
 LL |         let x = &mut h.0;
    |                 -------- borrow of `h.0` occurs here
@@ -117,7 +117,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `e.0` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:100:20
+  --> $DIR/borrowck-describe-lvalue.rs:98:20
    |
 LL |         let x = e.x();
    |                 - borrow of `*e` occurs here
@@ -129,7 +129,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `u.a` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:109:9
+  --> $DIR/borrowck-describe-lvalue.rs:107:9
    |
 LL |         let x = &mut u.a;
    |                 -------- borrow of `u.a` occurs here
@@ -139,7 +139,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:117:15
+  --> $DIR/borrowck-describe-lvalue.rs:115:15
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -151,7 +151,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:122:18
+  --> $DIR/borrowck-describe-lvalue.rs:120:18
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -163,7 +163,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:127:25
+  --> $DIR/borrowck-describe-lvalue.rs:125:25
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -175,7 +175,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:132:28
+  --> $DIR/borrowck-describe-lvalue.rs:130:28
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -187,7 +187,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:143:15
+  --> $DIR/borrowck-describe-lvalue.rs:141:15
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -199,7 +199,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:148:18
+  --> $DIR/borrowck-describe-lvalue.rs:146:18
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -211,7 +211,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:153:15
+  --> $DIR/borrowck-describe-lvalue.rs:151:15
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -223,7 +223,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `v[..]` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:158:18
+  --> $DIR/borrowck-describe-lvalue.rs:156:18
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -235,7 +235,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `e` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:171:13
+  --> $DIR/borrowck-describe-lvalue.rs:169:13
    |
 LL |         let x = &mut e;
    |                 ------ borrow of `e` occurs here
@@ -247,7 +247,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0502]: cannot borrow `e.0` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-describe-lvalue.rs:171:18
+  --> $DIR/borrowck-describe-lvalue.rs:169:18
    |
 LL |         let x = &mut e;
    |                 ------ mutable borrow occurs here
@@ -259,7 +259,7 @@ LL |         drop(x);
    |              - 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:175:23
+  --> $DIR/borrowck-describe-lvalue.rs:173:23
    |
 LL |         let x = &mut e;
    |                 ------ mutable borrow occurs here
@@ -271,7 +271,7 @@ LL |         drop(x);
    |              - 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:188:22
+  --> $DIR/borrowck-describe-lvalue.rs:186:22
    |
 LL |         let x = &mut s;
    |                 ------ mutable borrow occurs here
@@ -283,7 +283,7 @@ LL |         drop(x);
    |              - 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:194:28
+  --> $DIR/borrowck-describe-lvalue.rs:192:28
    |
 LL |         let x = &mut s;
    |                 ------ mutable borrow occurs here
@@ -295,7 +295,7 @@ LL |         drop(x);
    |              - mutable borrow later used here
 
 error[E0503]: cannot use `*v` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:236:9
+  --> $DIR/borrowck-describe-lvalue.rs:234:9
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -306,7 +306,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0503]: cannot use `v[_].y` because it was mutably borrowed
-  --> $DIR/borrowck-describe-lvalue.rs:236:9
+  --> $DIR/borrowck-describe-lvalue.rs:234:9
    |
 LL |         let x = &mut v;
    |                 ------ borrow of `v` occurs here
@@ -317,7 +317,7 @@ LL |         drop(x);
    |              - borrow later used here
 
 error[E0502]: cannot borrow `v[..].x` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-describe-lvalue.rs:247:24
+  --> $DIR/borrowck-describe-lvalue.rs:245:24
    |
 LL |         let x = &mut v;
    |                 ------ mutable borrow occurs here
@@ -329,7 +329,7 @@ LL |         drop(x);
    |              - 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:210:29
+  --> $DIR/borrowck-describe-lvalue.rs:208:29
    |
 LL |             let x = &mut block;
    |                     ---------- mutable borrow occurs here
@@ -340,7 +340,7 @@ LL |             drop(x);
    |                  - 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:225:33
+  --> $DIR/borrowck-describe-lvalue.rs:223:33
    |
 LL |             let x = &mut block;
    |                     ---------- mutable borrow occurs here
@@ -351,7 +351,7 @@ LL |             drop(x);
    |                  - mutable borrow later used here
 
 error[E0382]: use of moved value: `x`
-  --> $DIR/borrowck-describe-lvalue.rs:278:22
+  --> $DIR/borrowck-describe-lvalue.rs:276:22
    |
 LL |                 drop(x);
    |                      - value moved here
index 232d43679b4840c4b616d66b9db780b00e906f01..c1513fcba8a66819626769f73a6d17796d043bef 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn array() -> [(String, String); 3] {
     Default::default()
 }
index e46a58a8a35007d358b703cb5b891e481bf105e6..84930b000ccb3a5a122c1fa25b438d2a39b727d4 100644 (file)
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-match.rs:15:14
+  --> $DIR/borrowck-move-out-from-array-match.rs:13:14
    |
 LL |         [_, _, _x] => {}
    |                -- value moved here
@@ -10,7 +10,7 @@ LL |         [.., _y] => {}
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-match.rs:25:14
+  --> $DIR/borrowck-move-out-from-array-match.rs:23:14
    |
 LL |         [_, _, (_x, _)] => {}
    |                 -- value moved here
@@ -21,7 +21,7 @@ LL |         [.., _y] => {}
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..].0`
-  --> $DIR/borrowck-move-out-from-array-match.rs:35:15
+  --> $DIR/borrowck-move-out-from-array-match.rs:33:15
    |
 LL |         [_, _, (_x, _)] => {}
    |                 -- value moved here
@@ -32,7 +32,7 @@ LL |         [.., (_y, _)] => {}
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-match.rs:46:11
+  --> $DIR/borrowck-move-out-from-array-match.rs:44:11
    |
 LL |         [_x, _, _] => {}
    |          -- value moved here
@@ -43,7 +43,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-match.rs:57:11
+  --> $DIR/borrowck-move-out-from-array-match.rs:55:11
    |
 LL |         [.., _x] => {}
    |              -- value moved here
@@ -54,7 +54,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-match.rs:68:11
+  --> $DIR/borrowck-move-out-from-array-match.rs:66:11
    |
 LL |         [(_x, _), _, _] => {}
    |           -- value moved here
@@ -65,7 +65,7 @@ LL |     match a {
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-match.rs:79:11
+  --> $DIR/borrowck-move-out-from-array-match.rs:77:11
    |
 LL |         [.., (_x, _)] => {}
    |               -- value moved here
@@ -76,7 +76,7 @@ LL |     match a {
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..].0`
-  --> $DIR/borrowck-move-out-from-array-match.rs:91:11
+  --> $DIR/borrowck-move-out-from-array-match.rs:89:11
    |
 LL |         [_y @ .., _, _] => {}
    |          ------- value moved here
@@ -87,7 +87,7 @@ LL |         [(_x, _), _, _] => {}
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..].0`
-  --> $DIR/borrowck-move-out-from-array-match.rs:101:15
+  --> $DIR/borrowck-move-out-from-array-match.rs:99:15
    |
 LL |         [_, _, _y @ ..] => {}
    |                ------- value moved here
@@ -98,7 +98,7 @@ LL |         [.., (_x, _)] => {}
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-match.rs:112:11
+  --> $DIR/borrowck-move-out-from-array-match.rs:110:11
    |
 LL |         [x @ .., _] => {}
    |          ------ value moved here
index e5e61697c68c6070145b50bc52569444710d4ae7..056b8e672bd93a5cab6658e05ce651added16f80 100644 (file)
@@ -3,8 +3,6 @@
 // Once the bug is fixed, the test, which is derived from a
 // passing test for `let` statements, should become check-pass.
 
-#![feature(slice_patterns)]
-
 fn array() -> [(String, String); 3] {
     Default::default()
 }
index 72cd4207cce65e6986b171720cb1f9795f9bd4bf..ff5eab2442c83312dd43695f0b9e89cf68191efe 100644 (file)
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:19:11
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:17:11
    |
 LL |         [_, _, _x] => {}
    |                -- value moved here
@@ -10,7 +10,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:30:11
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:28:11
    |
 LL |         [_, _, (_x, _)] => {}
    |                 -- value moved here
@@ -21,7 +21,7 @@ LL |     match a {
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:43:11
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:41:11
    |
 LL |         [_x, _, _] => {}
    |          -- value moved here
@@ -32,7 +32,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:54:11
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:52:11
    |
 LL |         [.., _x] => {}
    |              -- value moved here
@@ -43,7 +43,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:65:11
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:63:11
    |
 LL |         [(_x, _), _, _] => {}
    |           -- value moved here
@@ -54,7 +54,7 @@ LL |     match a {
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:76:11
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:74:11
    |
 LL |         [.., (_x, _)] => {}
    |               -- value moved here
@@ -65,7 +65,7 @@ LL |     match a {
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:87:11
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:85:11
    |
 LL |         [_, _y @ ..] => {}
    |             ------- value moved here
@@ -76,7 +76,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:98:11
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:96:11
    |
 LL |         [_y @ .., _] => {}
    |          ------- value moved here
@@ -87,7 +87,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:111:11
+  --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:109:11
    |
 LL |         [x @ .., _, _] => {}
    |          ------ value moved here
index 8f274cf73cb0ec3b05f889717d050f228c1328b8..c91b4286b6478038a46840d2b924f22c3dc6d66d 100644 (file)
@@ -1,7 +1,5 @@
 // check-pass
 
-#![feature(slice_patterns)]
-
 fn array() -> [(String, String); 3] {
     Default::default()
 }
index 1ca3df52ada91c5800a97d071277d84322a62c8e..604a25cdcc1d689ecebacc42584aacd06ca4a69d 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn array() -> [(String, String); 3] {
     Default::default()
 }
index 028442a4c07ea227ed50a963cd29668b7c4589fa..0ef63105cfbd3212953a94c654a134be6c6c1906 100644 (file)
@@ -1,5 +1,5 @@
 error[E0382]: borrow of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:15:14
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:13:14
    |
 LL |         [_, _, _x] => {}
    |                -- value moved here
@@ -10,7 +10,7 @@ LL |         [.., ref _y] => {}
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:25:14
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:23:14
    |
 LL |         [_, _, (_x, _)] => {}
    |                 -- value moved here
@@ -21,7 +21,7 @@ LL |         [.., ref _y] => {}
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..].0`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:35:15
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:33:15
    |
 LL |         [_, _, (_x, _)] => {}
    |                 -- value moved here
@@ -32,7 +32,7 @@ LL |         [.., (ref _y, _)] => {}
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:46:11
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:44:11
    |
 LL |         [_x, _, _] => {}
    |          -- value moved here
@@ -43,7 +43,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:57:11
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:55:11
    |
 LL |         [.., _x] => {}
    |              -- value moved here
@@ -54,7 +54,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:68:11
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:66:11
    |
 LL |         [(_x, _), _, _] => {}
    |           -- value moved here
@@ -65,7 +65,7 @@ LL |     match a {
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:79:11
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:77:11
    |
 LL |         [.., (_x, _)] => {}
    |               -- value moved here
@@ -76,7 +76,7 @@ LL |     match a {
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:91:11
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:89:11
    |
 LL |         [_y @ .., _, _] => {}
    |          ------- value moved here
@@ -87,7 +87,7 @@ LL |         [(ref _x, _), _, _] => {}
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:101:15
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:99:15
    |
 LL |         [_, _, _y @ ..] => {}
    |                ------- value moved here
@@ -98,7 +98,7 @@ LL |         [.., (ref _x, _)] => {}
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:112:11
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:110:11
    |
 LL |         [x @ .., _] => {}
    |          ------ value moved here
@@ -109,7 +109,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:125:5
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:123:5
    |
 LL |         [_, _, _x] => {}
    |                -- value moved here
@@ -120,7 +120,7 @@ LL |     a[2] = Default::default();
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:133:5
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:131:5
    |
 LL |         [_, _, (_x, _)] => {}
    |                 -- value moved here
@@ -131,7 +131,7 @@ LL |     a[2].1 = Default::default();
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:141:5
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:139:5
    |
 LL |         [_, _, _x @ ..] => {}
    |                ------- value moved here
@@ -142,7 +142,7 @@ LL |     a[0] = Default::default();
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-match.rs:149:5
+  --> $DIR/borrowck-move-out-from-array-use-match.rs:147:5
    |
 LL |         [_, _, _x @ ..] => {}
    |                ------- value moved here
index 79fe593009652e920c5721fd9478c953e897456a..5afd6835dcfb60b0c98bd8b4bccf4887eb631174 100644 (file)
@@ -3,8 +3,6 @@
 // Once the bug is fixed, the test, which is derived from a
 // passing test for `let` statements, should become check-pass.
 
-#![feature(slice_patterns)]
-
 fn array() -> [(String, String); 3] {
     Default::default()
 }
index 43ba2b664a1e1c7e82a4090e61cc03ed8806b473..a4042ce7db336192c64086777a9a6105cc62be34 100644 (file)
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:19:11
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:17:11
    |
 LL |         [_, _, _x] => {}
    |                -- value moved here
@@ -10,7 +10,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:30:11
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:28:11
    |
 LL |         [_, _, (_x, _)] => {}
    |                 -- value moved here
@@ -21,7 +21,7 @@ LL |     match a {
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:43:11
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:41:11
    |
 LL |         [_x, _, _] => {}
    |          -- value moved here
@@ -32,7 +32,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:54:11
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:52:11
    |
 LL |         [.., _x] => {}
    |              -- value moved here
@@ -43,7 +43,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:65:11
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:63:11
    |
 LL |         [(_x, _), _, _] => {}
    |           -- value moved here
@@ -54,7 +54,7 @@ LL |     match a {
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:76:11
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:74:11
    |
 LL |         [.., (_x, _)] => {}
    |               -- value moved here
@@ -65,7 +65,7 @@ LL |     match a {
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:87:11
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:85:11
    |
 LL |         [_, _y @ ..] => {}
    |             ------- value moved here
@@ -76,7 +76,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:98:11
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:96:11
    |
 LL |         [_y @ .., _] => {}
    |          ------- value moved here
@@ -87,7 +87,7 @@ LL |     match a {
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:111:11
+  --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:109:11
    |
 LL |         [x @ .., _, _] => {}
    |          ------ value moved here
index 57ce2417570b0985f9787fbb4b1a601bce7441a3..e3498cef37719005a50df2f946b65fbed90c273f 100644 (file)
@@ -1,7 +1,5 @@
 // check-pass
 
-#![feature(slice_patterns)]
-
 fn array() -> [(String, String); 3] {
     Default::default()
 }
index 778beefbf2c85d59767e01cdc117e7d0ac2aa7ae..ad08367a3b5b31ecf3866abd0fd1098aecefd695 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn array() -> [(String, String); 3] {
     Default::default()
 }
index 2a7b89132c1b7a71c31d74a5be8b3870a7198e42..7ad4116645e9351d87f1eef6d814f3cd85c9ca15 100644 (file)
@@ -1,5 +1,5 @@
 error[E0382]: borrow of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-use.rs:12:14
+  --> $DIR/borrowck-move-out-from-array-use.rs:10:14
    |
 LL |     let [_, _, _x] = a;
    |                -- value moved here
@@ -9,7 +9,7 @@ LL |     let [.., ref _y] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-use.rs:18:14
+  --> $DIR/borrowck-move-out-from-array-use.rs:16:14
    |
 LL |     let [_, _, (_x, _)] = a;
    |                 -- value moved here
@@ -19,7 +19,7 @@ LL |     let [.., ref _y] = a;
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..].0`
-  --> $DIR/borrowck-move-out-from-array-use.rs:24:15
+  --> $DIR/borrowck-move-out-from-array-use.rs:22:15
    |
 LL |     let [_, _, (_x, _)] = a;
    |                 -- value moved here
@@ -29,7 +29,7 @@ LL |     let [.., (ref _y, _)] = a;
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:32:10
+  --> $DIR/borrowck-move-out-from-array-use.rs:30:10
    |
 LL |     let [_x, _, _] = a;
    |          -- value moved here
@@ -39,7 +39,7 @@ LL |     let [ref _y @ .., _, _] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:38:16
+  --> $DIR/borrowck-move-out-from-array-use.rs:36:16
    |
 LL |     let [.., _x] = a;
    |              -- value moved here
@@ -49,7 +49,7 @@ LL |     let [_, _, ref _y @ ..] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:44:10
+  --> $DIR/borrowck-move-out-from-array-use.rs:42:10
    |
 LL |     let [(_x, _), _, _] = a;
    |           -- value moved here
@@ -59,7 +59,7 @@ LL |     let [ref _y @ .., _, _] = a;
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:50:16
+  --> $DIR/borrowck-move-out-from-array-use.rs:48:16
    |
 LL |     let [.., (_x, _)] = a;
    |               -- value moved here
@@ -69,7 +69,7 @@ LL |     let [_, _, ref _y @ ..] = a;
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-use.rs:56:11
+  --> $DIR/borrowck-move-out-from-array-use.rs:54:11
    |
 LL |     let [_y @ .., _, _] = a;
    |          ------- value moved here
@@ -79,7 +79,7 @@ LL |     let [(ref _x, _), _, _] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array-use.rs:62:15
+  --> $DIR/borrowck-move-out-from-array-use.rs:60:15
    |
 LL |     let [_, _, _y @ ..] = a;
    |                ------- value moved here
@@ -89,7 +89,7 @@ LL |     let [.., (ref _x, _)] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: borrow of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:70:13
+  --> $DIR/borrowck-move-out-from-array-use.rs:68:13
    |
 LL |     let [x @ .., _] = a;
    |          ------ value moved here
@@ -99,7 +99,7 @@ LL |     let [_, ref _y @ ..] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:78:5
+  --> $DIR/borrowck-move-out-from-array-use.rs:76:5
    |
 LL |     let [_, _, _x] = a;
    |                -- value moved here
@@ -109,7 +109,7 @@ LL |     a[2] = Default::default();
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:84:5
+  --> $DIR/borrowck-move-out-from-array-use.rs:82:5
    |
 LL |     let [_, _, (_x, _)] = a;
    |                 -- value moved here
@@ -119,7 +119,7 @@ LL |     a[2].1 = Default::default();
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:90:5
+  --> $DIR/borrowck-move-out-from-array-use.rs:88:5
    |
 LL |     let [_, _, _x @ ..] = a;
    |                ------- value moved here
@@ -129,7 +129,7 @@ LL |     a[0] = Default::default();
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array-use.rs:96:5
+  --> $DIR/borrowck-move-out-from-array-use.rs:94:5
    |
 LL |     let [_, _, _x @ ..] = a;
    |                ------- value moved here
index f9d3f6f2c0724e9adcf5d2aabc0ddc0c627f5569..83755812f4b32315da27118643ef8cd79471ed58 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn array() -> [(String, String); 3] {
     Default::default()
 }
index 08134a2a323e73410c934ca248499f71eff33ff3..b7babd93ed7a638244a594ff060fc62fad8a86cb 100644 (file)
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array.rs:12:14
+  --> $DIR/borrowck-move-out-from-array.rs:10:14
    |
 LL |     let [_, _, _x] = a;
    |                -- value moved here
@@ -9,7 +9,7 @@ LL |     let [.., _y] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..]`
-  --> $DIR/borrowck-move-out-from-array.rs:18:14
+  --> $DIR/borrowck-move-out-from-array.rs:16:14
    |
 LL |     let [_, _, (_x, _)] = a;
    |                 -- value moved here
@@ -19,7 +19,7 @@ LL |     let [.., _y] = a;
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..].0`
-  --> $DIR/borrowck-move-out-from-array.rs:24:15
+  --> $DIR/borrowck-move-out-from-array.rs:22:15
    |
 LL |     let [_, _, (_x, _)] = a;
    |                 -- value moved here
@@ -29,7 +29,7 @@ LL |     let [.., (_y, _)] = a;
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array.rs:32:10
+  --> $DIR/borrowck-move-out-from-array.rs:30:10
    |
 LL |     let [_x, _, _] = a;
    |          -- value moved here
@@ -39,7 +39,7 @@ LL |     let [_y @ .., _, _] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array.rs:38:16
+  --> $DIR/borrowck-move-out-from-array.rs:36:16
    |
 LL |     let [.., _x] = a;
    |              -- value moved here
@@ -49,7 +49,7 @@ LL |     let [_, _, _y @ ..] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array.rs:44:10
+  --> $DIR/borrowck-move-out-from-array.rs:42:10
    |
 LL |     let [(_x, _), _, _] = a;
    |           -- value moved here
@@ -59,7 +59,7 @@ LL |     let [_y @ .., _, _] = a;
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array.rs:50:16
+  --> $DIR/borrowck-move-out-from-array.rs:48:16
    |
 LL |     let [.., (_x, _)] = a;
    |               -- value moved here
@@ -69,7 +69,7 @@ LL |     let [_, _, _y @ ..] = a;
    = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..].0`
-  --> $DIR/borrowck-move-out-from-array.rs:56:11
+  --> $DIR/borrowck-move-out-from-array.rs:54:11
    |
 LL |     let [_y @ .., _, _] = a;
    |          ------- value moved here
@@ -79,7 +79,7 @@ LL |     let [(_x, _), _, _] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a[..].0`
-  --> $DIR/borrowck-move-out-from-array.rs:62:15
+  --> $DIR/borrowck-move-out-from-array.rs:60:15
    |
 LL |     let [_, _, _y @ ..] = a;
    |                ------- value moved here
@@ -89,7 +89,7 @@ LL |     let [.., (_x, _)] = a;
    = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-move-out-from-array.rs:70:13
+  --> $DIR/borrowck-move-out-from-array.rs:68:13
    |
 LL |     let [x @ .., _] = a;
    |          ------ value moved here
index fa9a3c217db77ec0eefc88d5128f6e1fcaa2f271..8ece81a3c845e9209a20699ff9664cfc854cbcde 100644 (file)
@@ -1,7 +1,5 @@
 // Test that we do not permit moves from &[] matched by a vec pattern.
 
-#![feature(slice_patterns)]
-
 #[derive(Clone, Debug)]
 struct Foo {
     string: String
index 8fb4c062c0363772f5e529b179000cbad372f0e9..a345c1238f02c3bdb2322c33b72d7fc83dea2fd3 100644 (file)
@@ -1,5 +1,5 @@
 error[E0508]: cannot move out of type `[Foo]`, a non-copy slice
-  --> $DIR/borrowck-move-out-of-vec-tail.rs:19:19
+  --> $DIR/borrowck-move-out-of-vec-tail.rs:17:19
    |
 LL |             match tail {
    |                   ^^^^ cannot move out of here
index 7d91a212647233da54b45bb2da896856ef64250e..a8e56f648e2e538c4bbe34d4b94563ccbdac5fce 100644 (file)
@@ -1,7 +1,5 @@
 // check-pass
 
-#![feature(slice_patterns)]
-
 fn nop(_s: &[& i32]) {}
 fn nop_subslice(_s: &[i32]) {}
 
index f03a2ab8fa8e456c53111e94bc6a52df144f495c..6b210d73228f864ddb77ecf02e8ee31397f50d49 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn nop(_s: &[& i32]) {}
 fn nop_subslice(_s: &[i32]) {}
 
index e50e7eb3e22301b5c98be9a1776b2c588830242d..0432aaf51d29f50a6c22be7fa34e08ad0f1560ae 100644 (file)
@@ -1,5 +1,5 @@
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:8:13
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:6:13
    |
 LL |     let [ref first, ref second, ..] = *s;
    |                     ---------- immutable borrow occurs here
@@ -9,7 +9,7 @@ LL |     nop(&[first, second, second2, third]);
    |                  ------ 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-array.rs:14:14
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:12:14
    |
 LL |     let [.., ref fourth, ref third, _, ref first] = *s;
    |                          --------- immutable borrow occurs here
@@ -19,7 +19,7 @@ LL |     nop(&[first, third, third2, fourth]);
    |                  ----- 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-array.rs:21:16
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:19:16
    |
 LL |     let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s;
    |                 ------------- immutable borrow occurs here
@@ -30,7 +30,7 @@ LL |     nop(&[from_begin2, from_end1, from_end3, from_end4]);
    |                                              --------- 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-array.rs:23:19
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:21:19
    |
 LL |     let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s;
    |                                ------------- immutable borrow occurs here
@@ -41,7 +41,7 @@ LL |     nop(&[from_begin3, from_end1, from_end3, from_end4]);
    |                                   --------- 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-array.rs:28:14
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:26:14
    |
 LL |     let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s;
    |                                               --------------- immutable borrow occurs here
@@ -52,7 +52,7 @@ LL |     nop(&[from_begin0, from_begin1, from_begin3, from_end3]);
    |                                     ----------- 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-array.rs:34:13
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:32:13
    |
 LL |     let [ref first, ref second, ..] = *s;
    |                     ---------- immutable borrow occurs here
@@ -62,7 +62,7 @@ LL |     nop(&[first, second]);
    |                  ------ 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-array.rs:41:10
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:39:10
    |
 LL |     let [.., ref second, ref first] = *s;
    |              ---------- immutable borrow occurs here
@@ -72,7 +72,7 @@ LL |     nop(&[first, second]);
    |                  ------ 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-array.rs:48:10
+  --> $DIR/borrowck-slice-pattern-element-loan-array.rs:46:10
    |
 LL |     let [_,  ref s1 @ ..] = *s;
    |              ----------- immutable borrow occurs here
index 048813b2b93e6fd6970eabe2df65509f36217369..4367596c6ea88066acf6dbc32f341b57b83c14a0 100644 (file)
@@ -1,7 +1,4 @@
 // run-pass
-//compile-flags: -Z borrowck=mir
-
-#![feature(slice_patterns)]
 
 fn mut_head_tail<'a, A>(v: &'a mut [A]) -> Option<(&'a mut A, &'a mut [A])> {
     match *v {
index e69071f87720b9fb68046671a5b477c96458b9e7..6390dc3a91a0d922f81b9fd4a3025ed103da0fbd 100644 (file)
@@ -1,7 +1,5 @@
 // check-pass
 
-#![feature(slice_patterns)]
-
 fn nop(_s: &[& i32]) {}
 fn nop_subslice(_s: &[i32]) {}
 
index 2ef98741dc35aeacf6188e3a20caefbe505b38fa..0e1c90a1cd83d5e9727baa27b091571777c49985 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn nop(_s: &[& i32]) {}
 fn nop_subslice(_s: &[i32]) {}
 
index b6f5ac64b20612fcff81373d3453289dd6a1f7f1..d3388e071aa5349820cf42dc7e010d031f96f152 100644 (file)
@@ -1,5 +1,5 @@
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:8:20
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:6:20
    |
 LL |     if let [ref first, ref second, ..] = *s {
    |                        ---------- immutable borrow occurs here
@@ -9,7 +9,7 @@ LL |             nop(&[first, second, second2, third]);
    |                          ------ 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-slice.rs:16:21
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:14:21
    |
 LL |     if let [.., ref fourth, ref third, _, ref first] = *s {
    |                             --------- immutable borrow occurs here
@@ -19,7 +19,7 @@ LL |             nop(&[first, third, third2, fourth]);
    |                          ----- 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-slice.rs:24:20
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:22:20
    |
 LL |     if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
    |                    ------------- immutable borrow occurs here
@@ -29,7 +29,7 @@ LL |             nop(&[from_begin1, from_end1, from_end3, from_end4]);
    |                                                      --------- 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-slice.rs:27:23
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:25:23
    |
 LL |     if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
    |                                   ------------- immutable borrow occurs here
@@ -40,7 +40,7 @@ LL |             nop(&[from_begin2, from_end1, from_end3, from_end4]);
    |                                           --------- 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-slice.rs:30:26
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:28:26
    |
 LL |     if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
    |                                   ------------- immutable borrow occurs here
@@ -51,7 +51,7 @@ LL |             nop(&[from_begin3, from_end1, from_end3, from_end4]);
    |                                           --------- 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-slice.rs:35:21
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:33:21
    |
 LL |     if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s {
    |                                                  --------------- immutable borrow occurs here
@@ -61,7 +61,7 @@ LL |             nop(&[from_begin0, from_begin1, from_begin3, from_end2]);
    |                                             ----------- 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-slice.rs:38:21
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:36:21
    |
 LL |     if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s {
    |                                                  --------------- immutable borrow occurs here
@@ -72,7 +72,7 @@ LL |             nop(&[from_begin0, from_begin1, from_begin3, from_end3]);
    |                                             ----------- 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-slice.rs:41:21
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:39:21
    |
 LL |     if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s {
    |                              --------------- immutable borrow occurs here
@@ -83,7 +83,7 @@ LL |             nop(&[from_begin0, from_begin1, from_begin3, from_end4]);
    |                                ----------- 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-slice.rs:49:20
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:47:20
    |
 LL |     if let [ref first, ref second, ..] = *s {
    |                        ---------- immutable borrow occurs here
@@ -93,7 +93,7 @@ LL |             nop(&[first, second]);
    |                          ------ 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-slice.rs:58:17
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:56:17
    |
 LL |     if let [.., ref second, ref first] = *s {
    |                 ---------- immutable borrow occurs here
@@ -103,7 +103,7 @@ LL |             nop(&[first, second]);
    |                          ------ 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-slice.rs:67:17
+  --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:65:17
    |
 LL |     if let [_, _, _, ref s1 @ ..] = *s {
    |                      ----------- immutable borrow occurs here
index 53a9bcef74a22beb410ed391a74f3b13a5fbd117..cd853b83363ab622c36c32d092bae2def7122e3b 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn a<'a>() -> &'a [isize] {
     let vec = vec![1, 2, 3, 4];
     let vec: &[isize] = &vec;
index da6d9293b408a6c714c99e66931993b073603000..170982b1693fb1ee69e208fda4e7068418582576 100644 (file)
@@ -1,5 +1,5 @@
 error[E0515]: cannot return value referencing local variable `vec`
-  --> $DIR/borrowck-vec-pattern-element-loan.rs:10:5
+  --> $DIR/borrowck-vec-pattern-element-loan.rs:8:5
    |
 LL |     let vec: &[isize] = &vec;
    |                         ---- `vec` is borrowed here
@@ -8,7 +8,7 @@ LL |     tail
    |     ^^^^ returns a value referencing data owned by the current function
 
 error[E0515]: cannot return value referencing local variable `vec`
-  --> $DIR/borrowck-vec-pattern-element-loan.rs:20:5
+  --> $DIR/borrowck-vec-pattern-element-loan.rs:18:5
    |
 LL |     let vec: &[isize] = &vec;
    |                         ---- `vec` is borrowed here
@@ -17,7 +17,7 @@ LL |     init
    |     ^^^^ returns a value referencing data owned by the current function
 
 error[E0515]: cannot return value referencing local variable `vec`
-  --> $DIR/borrowck-vec-pattern-element-loan.rs:30:5
+  --> $DIR/borrowck-vec-pattern-element-loan.rs:28:5
    |
 LL |     let vec: &[isize] = &vec;
    |                         ---- `vec` is borrowed here
index dd9023f6d9f791846a404f09068cfd0e9d152fa2..05859c95d174d9dedc1c5b7dc1d84c80a7fe84f6 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn a() {
     let mut v = vec![1, 2, 3];
     let vb: &mut [isize] = &mut v;
index 251f44592905dddd5e41a1bf735f4fb86954dcc3..5141fcc1bb261f4a454a406506c2f117c571adaf 100644 (file)
@@ -1,5 +1,5 @@
 error[E0499]: cannot borrow `v` as mutable more than once at a time
-  --> $DIR/borrowck-vec-pattern-loan-from-mut.rs:8:13
+  --> $DIR/borrowck-vec-pattern-loan-from-mut.rs:6:13
    |
 LL |     let vb: &mut [isize] = &mut v;
    |                            ------ first mutable borrow occurs here
index 420223009a45b2f0c5624e1ef178921ae4058f96..9b8ba2ea8adc5df61562a5d2c785169d3e1ca82b 100644 (file)
@@ -1,7 +1,3 @@
-// http://rust-lang.org/COPYRIGHT.
-
-#![feature(slice_patterns)]
-
 fn main() {
     let mut a = [1, 2, 3, 4];
     let t = match a {
index 9f8e6fe3b6898dcdbae751c069093f151aee5c94..ff70ba9fcca8b5145983d135fe1cb7d6630dc868 100644 (file)
@@ -1,5 +1,5 @@
 error[E0506]: cannot assign to `a[_]` because it is borrowed
-  --> $DIR/borrowck-vec-pattern-move-tail.rs:12:5
+  --> $DIR/borrowck-vec-pattern-move-tail.rs:8:5
    |
 LL |         [1, 2, ref tail @ ..] => tail,
    |                ------------- borrow of `a[_]` occurs here
index e274d105e05034f4e0fb2512cc98fa981dd60de9..67b6c12ba803a230a09266750e53ec004f8b2698 100644 (file)
@@ -1,6 +1,5 @@
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(slice_patterns)]
 
 fn a() {
     let mut vec = [box 1, box 2, box 3];
index a3324f25d0bb5968c52f611958544f5a6366f395..e2c0852dd83c696113d89c46b5fcac54a6bc92be 100644 (file)
@@ -1,5 +1,5 @@
 error[E0506]: cannot assign to `vec[_]` because it is borrowed
-  --> $DIR/borrowck-vec-pattern-nesting.rs:10:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:9:13
    |
 LL |         [box ref _a, _, _] => {
    |              ------ borrow of `vec[_]` occurs here
@@ -11,7 +11,7 @@ LL |             _a.use_ref();
    |             -- borrow later used here
 
 error[E0506]: cannot assign to `vec[_]` because it is borrowed
-  --> $DIR/borrowck-vec-pattern-nesting.rs:24:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:23:13
    |
 LL |         &mut [ref _b @ ..] => {
    |               ----------- borrow of `vec[_]` occurs here
@@ -23,7 +23,7 @@ LL |             _b.use_ref();
    |             -- borrow later used here
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:35:11
+  --> $DIR/borrowck-vec-pattern-nesting.rs:34:11
    |
 LL |     match vec {
    |           ^^^ cannot move out of here
@@ -45,7 +45,7 @@ LL |         ] => {
    |
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:47:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:46:13
    |
 LL |     let a = vec[0];
    |             ^^^^^^
@@ -55,7 +55,7 @@ LL |     let a = vec[0];
    |             help: consider borrowing here: `&vec[0]`
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:56:11
+  --> $DIR/borrowck-vec-pattern-nesting.rs:55:11
    |
 LL |     match vec {
    |           ^^^ cannot move out of here
@@ -74,7 +74,7 @@ LL |          _b] => {}
    |
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:66:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:65:13
    |
 LL |     let a = vec[0];
    |             ^^^^^^
@@ -84,7 +84,7 @@ LL |     let a = vec[0];
    |             help: consider borrowing here: `&vec[0]`
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:75:11
+  --> $DIR/borrowck-vec-pattern-nesting.rs:74:11
    |
 LL |     match vec {
    |           ^^^ cannot move out of here
@@ -100,7 +100,7 @@ LL |         &mut [_a, _b, _c] => {}
    = note: move occurs because these variables have types that don't implement the `Copy` trait
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:86:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:85:13
    |
 LL |     let a = vec[0];
    |             ^^^^^^
index c35be2f6be62c02f48a9569aa9d02a7085346122..39872825cd2a461d832bc074782f9b12c41d921f 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn a<'a>() -> &'a isize {
     let vec = vec![1, 2, 3, 4];
     let vec: &[isize] = &vec;
index c1290a6f63f33018dd4e3dc95f965f29c4903e3e..7e21c55f21b5fa7e901eba7b7136f3892ab2fb5d 100644 (file)
@@ -1,5 +1,5 @@
 error[E0515]: cannot return value referencing local variable `vec`
-  --> $DIR/borrowck-vec-pattern-tail-element-loan.rs:10:5
+  --> $DIR/borrowck-vec-pattern-tail-element-loan.rs:8:5
    |
 LL |     let vec: &[isize] = &vec;
    |                         ---- `vec` is borrowed here
index 8b70b15fa6e50e8e7b8dcbe776908785e1e42d66..89107e799bd2207c4f26a4f62e38ceb0cf27c35a 100644 (file)
@@ -87,12 +87,12 @@ error[E0597]: `ap1` does not live long enough
   --> $DIR/variadic-ffi-4.rs:24:11
    |
 LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
-   |                                                    - let's call the lifetime of this reference `'1`
+   |                                                    - let's call the lifetime of this reference `'3`
 LL |     ap0 = &mut ap1;
    |     ------^^^^^^^^
    |     |     |
    |     |     borrowed value does not live long enough
-   |     assignment requires that `ap1` is borrowed for `'1`
+   |     assignment requires that `ap1` is borrowed for `'3`
 ...
 LL | }
    | - `ap1` dropped here while still borrowed
index 303d83d342625c5379f07a4612f219988e77e7b9..44e5c6a99f7278afa26185f706b35b6134521964 100644 (file)
@@ -29,7 +29,7 @@ error[E0308]: mismatched types
   --> $DIR/coerce-expect-unsized-ascribed.rs:13:13
    |
 LL |     let _ = box { |x| (x as u8) }: Box<dyn Fn(i32) -> _>;
-   |             ^^^^^^^^^^^^^^^^^^^^^ expected trait `std::ops::Fn`, found closure
+   |             ^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::ops::Fn`, found closure
    |
    = note: expected struct `std::boxed::Box<dyn std::ops::Fn(i32) -> u8>`
               found struct `std::boxed::Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:13:19: 13:32]>`
@@ -38,7 +38,7 @@ error[E0308]: mismatched types
   --> $DIR/coerce-expect-unsized-ascribed.rs:14:13
    |
 LL |     let _ = box if true { false } else { true }: Box<dyn Debug>;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `std::fmt::Debug`, found `bool`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::fmt::Debug`, found `bool`
    |
    = note: expected struct `std::boxed::Box<dyn std::fmt::Debug>`
               found struct `std::boxed::Box<bool>`
@@ -47,7 +47,7 @@ error[E0308]: mismatched types
   --> $DIR/coerce-expect-unsized-ascribed.rs:15:13
    |
 LL |     let _ = box match true { true => 'a', false => 'b' }: Box<dyn Debug>;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `std::fmt::Debug`, found `char`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::fmt::Debug`, found `char`
    |
    = note: expected struct `std::boxed::Box<dyn std::fmt::Debug>`
               found struct `std::boxed::Box<char>`
@@ -83,7 +83,7 @@ error[E0308]: mismatched types
   --> $DIR/coerce-expect-unsized-ascribed.rs:21:13
    |
 LL |     let _ = &{ |x| (x as u8) }: &dyn Fn(i32) -> _;
-   |             ^^^^^^^^^^^^^^^^^^ expected trait `std::ops::Fn`, found closure
+   |             ^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::ops::Fn`, found closure
    |
    = note: expected reference `&dyn std::ops::Fn(i32) -> u8`
               found reference `&[closure@$DIR/coerce-expect-unsized-ascribed.rs:21:16: 21:29]`
@@ -92,7 +92,7 @@ error[E0308]: mismatched types
   --> $DIR/coerce-expect-unsized-ascribed.rs:22:13
    |
 LL |     let _ = &if true { false } else { true }: &dyn Debug;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `std::fmt::Debug`, found `bool`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::fmt::Debug`, found `bool`
    |
    = note: expected reference `&dyn std::fmt::Debug`
               found reference `&bool`
@@ -101,7 +101,7 @@ error[E0308]: mismatched types
   --> $DIR/coerce-expect-unsized-ascribed.rs:23:13
    |
 LL |     let _ = &match true { true => 'a', false => 'b' }: &dyn Debug;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait `std::fmt::Debug`, found `char`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::fmt::Debug`, found `char`
    |
    = note: expected reference `&dyn std::fmt::Debug`
               found reference `&char`
@@ -119,7 +119,7 @@ error[E0308]: mismatched types
   --> $DIR/coerce-expect-unsized-ascribed.rs:26:13
    |
 LL |     let _ = Box::new(|x| (x as u8)): Box<dyn Fn(i32) -> _>;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^ expected trait `std::ops::Fn`, found closure
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::ops::Fn`, found closure
    |
    = note: expected struct `std::boxed::Box<dyn std::ops::Fn(i32) -> _>`
               found struct `std::boxed::Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:26:22: 26:35]>`
index 5c37468130c64bca9af6ef06f4b46cf05021f302..6e5afcdb8bb68ce650dbba5ccee012f483c950f7 100644 (file)
@@ -3,6 +3,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_vec_partial_eq_array<A, B>() -> impl PartialEq<[B; 33]>
    |                                           ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
+...
+LL |     Vec::<A>::new()
+   |     --------------- this returned value is of type `std::vec::Vec<A>`
    |
    = note: required because of the requirements on the impl of `std::cmp::PartialEq<[B; 33]>` for `std::vec::Vec<A>`
    = note: the return type of a function must have a statically known size
@@ -12,6 +15,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_vec_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]>
    |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
+...
+LL |     Vec::<A>::new()
+   |     --------------- this returned value is of type `std::vec::Vec<A>`
    |
    = note: required because of the requirements on the impl of `std::cmp::PartialEq<&'a [B; 33]>` for `std::vec::Vec<A>`
    = note: the return type of a function must have a statically known size
@@ -21,6 +27,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_vecdeque_partial_eq_array<A, B>() -> impl PartialEq<[B; 33]>
    |                                                ^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
+...
+LL |     VecDeque::<A>::new()
+   |     -------------------- this returned value is of type `std::collections::VecDeque<A>`
    |
    = note: required because of the requirements on the impl of `std::cmp::PartialEq<[B; 33]>` for `std::collections::VecDeque<A>`
    = note: the return type of a function must have a statically known size
@@ -30,6 +39,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_vecdeque_partial_eq_ref_array<'a, A, B>() -> impl PartialEq<&'a [B; 33]>
    |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
+...
+LL |     VecDeque::<A>::new()
+   |     -------------------- this returned value is of type `std::collections::VecDeque<A>`
    |
    = note: required because of the requirements on the impl of `std::cmp::PartialEq<&'a [B; 33]>` for `std::collections::VecDeque<A>`
    = note: the return type of a function must have a statically known size
@@ -39,6 +51,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_vecdeque_partial_eq_ref_mut_array<'a, A, B>() -> impl PartialEq<&'a mut [B; 33]>
    |                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[B; 33]`
+...
+LL |     VecDeque::<A>::new()
+   |     -------------------- this returned value is of type `std::collections::VecDeque<A>`
    |
    = note: required because of the requirements on the impl of `std::cmp::PartialEq<&'a mut [B; 33]>` for `std::collections::VecDeque<A>`
    = note: the return type of a function must have a statically known size
index bfdff8e3bbe61599026772b8321c1bff56deab25..4869f48363447db0fc0bbbb4aecc566a91860d86 100644 (file)
@@ -11,6 +11,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_iterator() -> impl Iterator<Item = i32> {
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
@@ -28,6 +31,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_double_ended_iterator() -> impl DoubleEndedIterator {
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::iter::DoubleEndedIterator` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
@@ -45,6 +51,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_exact_size_iterator() -> impl ExactSizeIterator {
    |                                    ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::iter::ExactSizeIterator` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
@@ -62,6 +71,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_fused_iterator() -> impl FusedIterator {
    |                               ^^^^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::iter::FusedIterator` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
@@ -79,6 +91,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_trusted_len() -> impl TrustedLen {
    |                            ^^^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::iter::TrustedLen` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
@@ -96,6 +111,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_clone() -> impl Clone {
    |                      ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::clone::Clone` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
@@ -113,6 +131,9 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32
    |
 LL | pub fn no_debug() -> impl Debug {
    |                      ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]`
+LL |
+LL |     IntoIter::new([0i32; 33])
+   |     ------------------------- this returned value is of type `std::array::IntoIter<i32, 33usize>`
    |
    = note: required because of the requirements on the impl of `std::fmt::Debug` for `std::array::IntoIter<i32, 33usize>`
    = note: the return type of a function must have a statically known size
diff --git a/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs
new file mode 100644 (file)
index 0000000..30fbfda
--- /dev/null
@@ -0,0 +1,18 @@
+// check-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+fn takes_closure_of_array_3<F>(f: F) where F: Fn([i32; 3]) {
+    f([1, 2, 3]);
+}
+
+fn takes_closure_of_array_3_apit(f: impl Fn([i32; 3])) {
+    f([1, 2, 3]);
+}
+
+fn returns_closure_of_array_3() -> impl Fn([i32; 3]) {
+    |_| {}
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.stderr b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.stderr
new file mode 100644 (file)
index 0000000..7f37f3e
--- /dev/null
@@ -0,0 +1,8 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/integer-literal-generic-arg-in-where-clause.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
index 64aeb46894d169b63303972a07371c471d5498aa..af63d1f75a77022b0bd1a8894b12b40d4c76927a 100644 (file)
@@ -1,4 +1,5 @@
 // build-pass
+// ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors)
 
 #![warn(const_err)]
 
index 50ad8e83e905cc0ad842642cc1986511d0ebb74f..e93aa324784c3820629c81cfa1c7f99acb56d1ad 100644 (file)
@@ -1,17 +1,17 @@
 warning: index out of bounds: the len is 3 but the index is 4
-  --> $DIR/array-literal-index-oob.rs:6:8
+  --> $DIR/array-literal-index-oob.rs:7:8
    |
 LL |     &{ [1, 2, 3][4] };
    |        ^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/array-literal-index-oob.rs:3:9
+  --> $DIR/array-literal-index-oob.rs:4:9
    |
 LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
 warning: reaching this expression at runtime will panic or abort
-  --> $DIR/array-literal-index-oob.rs:6:8
+  --> $DIR/array-literal-index-oob.rs:7:8
    |
 LL |     &{ [1, 2, 3][4] };
    |     ---^^^^^^^^^^^^--
@@ -19,7 +19,7 @@ LL |     &{ [1, 2, 3][4] };
    |        indexing out of bounds: the len is 3 but the index is 4
 
 warning: erroneous constant used
-  --> $DIR/array-literal-index-oob.rs:6:5
+  --> $DIR/array-literal-index-oob.rs:7:5
    |
 LL |     &{ [1, 2, 3][4] };
    |     ^^^^^^^^^^^^^^^^^ referenced constant has errors
diff --git a/src/test/ui/consts/associated_const_generic.rs b/src/test/ui/consts/associated_const_generic.rs
new file mode 100644 (file)
index 0000000..dee376c
--- /dev/null
@@ -0,0 +1,25 @@
+// check-pass
+
+trait TraitA {
+    const VALUE: usize;
+}
+
+struct A;
+impl TraitA for A {
+    const VALUE: usize = 1;
+}
+
+trait TraitB {
+    type MyA: TraitA;
+    const VALUE: usize = Self::MyA::VALUE;
+}
+
+struct B;
+impl TraitB for B {
+    type MyA = A;
+}
+
+fn main() {
+    let _ = [0; A::VALUE];
+    let _ = [0; B::VALUE]; // Indirectly refers to `A::VALUE`
+}
index fee232185d29a93559f1a59058116a6139c76fc6..22f863fb15ac4ab887c4b6098d1592e5c68b33a2 100644 (file)
@@ -1,4 +1,5 @@
 // build-pass
+// ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors)
 // compile-flags: -O
 
 #![warn(const_err)]
index 4de22fdf4ab1e4627d510fee7687bc45a7baa68d..b4330deb3ef10376e5c0d5ece726b913a15df298 100644 (file)
@@ -1,59 +1,59 @@
 warning: this expression will panic at runtime
-  --> $DIR/promoted_errors.rs:8:14
+  --> $DIR/promoted_errors.rs:9:14
    |
 LL |     let _x = 0u32 - 1;
    |              ^^^^^^^^ attempt to subtract with overflow
    |
 note: lint level defined here
-  --> $DIR/promoted_errors.rs:4:9
+  --> $DIR/promoted_errors.rs:5:9
    |
 LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
 warning: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:10:20
+  --> $DIR/promoted_errors.rs:11:20
    |
 LL |     println!("{}", 1 / (1 - 1));
    |                    ^^^^^^^^^^^
 
 warning: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors.rs:10:20
+  --> $DIR/promoted_errors.rs:11:20
    |
 LL |     println!("{}", 1 / (1 - 1));
    |                    ^^^^^^^^^^^ dividing by zero
 
 warning: erroneous constant used
-  --> $DIR/promoted_errors.rs:10:20
+  --> $DIR/promoted_errors.rs:11:20
    |
 LL |     println!("{}", 1 / (1 - 1));
    |                    ^^^^^^^^^^^ referenced constant has errors
 
 warning: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:14:14
+  --> $DIR/promoted_errors.rs:15:14
    |
 LL |     let _x = 1 / (1 - 1);
    |              ^^^^^^^^^^^
 
 warning: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:16:20
+  --> $DIR/promoted_errors.rs:17:20
    |
 LL |     println!("{}", 1 / (false as u32));
    |                    ^^^^^^^^^^^^^^^^^^
 
 warning: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors.rs:16:20
+  --> $DIR/promoted_errors.rs:17:20
    |
 LL |     println!("{}", 1 / (false as u32));
    |                    ^^^^^^^^^^^^^^^^^^ dividing by zero
 
 warning: erroneous constant used
-  --> $DIR/promoted_errors.rs:16:20
+  --> $DIR/promoted_errors.rs:17:20
    |
 LL |     println!("{}", 1 / (false as u32));
    |                    ^^^^^^^^^^^^^^^^^^ referenced constant has errors
 
 warning: attempt to divide by zero
-  --> $DIR/promoted_errors.rs:20:14
+  --> $DIR/promoted_errors.rs:21:14
    |
 LL |     let _x = 1 / (false as u32);
    |              ^^^^^^^^^^^^^^^^^^
index 41a989d91c5d3f13407a9560d34abeaed015e21f..62c77f76d9064ca7325cc14369ea7dc2b59ecb03 100644 (file)
@@ -1,4 +1,5 @@
 // build-pass
+// ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors)
 // compile-flags: -C overflow-checks=on -O
 
 #![warn(const_err)]
index 4f7ba8bf385d3c036d18ee05de861ee988691f25..a4dad295edd793f22805c8b5ca10886f2ee55396 100644 (file)
@@ -1,65 +1,65 @@
 warning: attempt to subtract with overflow
-  --> $DIR/promoted_errors2.rs:7:20
+  --> $DIR/promoted_errors2.rs:8:20
    |
 LL |     println!("{}", 0u32 - 1);
    |                    ^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/promoted_errors2.rs:4:9
+  --> $DIR/promoted_errors2.rs:5:9
    |
 LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
 warning: attempt to subtract with overflow
-  --> $DIR/promoted_errors2.rs:9:14
+  --> $DIR/promoted_errors2.rs:10:14
    |
 LL |     let _x = 0u32 - 1;
    |              ^^^^^^^^
 
 warning: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:11:20
+  --> $DIR/promoted_errors2.rs:12:20
    |
 LL |     println!("{}", 1 / (1 - 1));
    |                    ^^^^^^^^^^^
 
 warning: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors2.rs:11:20
+  --> $DIR/promoted_errors2.rs:12:20
    |
 LL |     println!("{}", 1 / (1 - 1));
    |                    ^^^^^^^^^^^ dividing by zero
 
 warning: erroneous constant used
-  --> $DIR/promoted_errors2.rs:11:20
+  --> $DIR/promoted_errors2.rs:12:20
    |
 LL |     println!("{}", 1 / (1 - 1));
    |                    ^^^^^^^^^^^ referenced constant has errors
 
 warning: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:15:14
+  --> $DIR/promoted_errors2.rs:16:14
    |
 LL |     let _x = 1 / (1 - 1);
    |              ^^^^^^^^^^^
 
 warning: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:17:20
+  --> $DIR/promoted_errors2.rs:18:20
    |
 LL |     println!("{}", 1 / (false as u32));
    |                    ^^^^^^^^^^^^^^^^^^
 
 warning: reaching this expression at runtime will panic or abort
-  --> $DIR/promoted_errors2.rs:17:20
+  --> $DIR/promoted_errors2.rs:18:20
    |
 LL |     println!("{}", 1 / (false as u32));
    |                    ^^^^^^^^^^^^^^^^^^ dividing by zero
 
 warning: erroneous constant used
-  --> $DIR/promoted_errors2.rs:17:20
+  --> $DIR/promoted_errors2.rs:18:20
    |
 LL |     println!("{}", 1 / (false as u32));
    |                    ^^^^^^^^^^^^^^^^^^ referenced constant has errors
 
 warning: attempt to divide by zero
-  --> $DIR/promoted_errors2.rs:21:14
+  --> $DIR/promoted_errors2.rs:22:14
    |
 LL |     let _x = 1 / (false as u32);
    |              ^^^^^^^^^^^^^^^^^^
index 5fec36e44bd8c874e49fc510810ce36f692b3f96..60b06a497d6de58c24f73e4284402ad844cb5cf1 100644 (file)
@@ -1,5 +1,4 @@
 // check-pass
-#![feature(slice_patterns)]
 
 fn main() {
     match &[0, 1] as &[i32] {
diff --git a/src/test/ui/consts/issue-67529.rs b/src/test/ui/consts/issue-67529.rs
new file mode 100644 (file)
index 0000000..df4bc66
--- /dev/null
@@ -0,0 +1,11 @@
+// compile-flags: -Z mir-opt-level=2
+// run-pass
+
+struct Baz<T: ?Sized> {
+    a: T
+}
+
+fn main() {
+    let d : Baz<[i32; 4]> = Baz { a: [1,2,3,4] };
+    assert_eq!([1, 2, 3, 4], d.a);
+}
diff --git a/src/test/ui/consts/issue-67640.rs b/src/test/ui/consts/issue-67640.rs
new file mode 100644 (file)
index 0000000..bc0ee8d
--- /dev/null
@@ -0,0 +1,24 @@
+// compile-flags: -Z mir-opt-level=3
+// run-pass
+
+struct X {
+    x: isize
+}
+
+fn f1(a: &mut X, b: &mut isize, c: isize) -> isize {
+    let r = a.x + *b + c;
+    a.x = 0;
+    *b = 10;
+    return r;
+}
+
+fn f2<F>(a: isize, f: F) -> isize where F: FnOnce(isize) { f(1); return a; }
+
+pub fn main() {
+    let mut a = X {x: 1};
+    let mut b = 2;
+    let c = 3;
+    assert_eq!(f1(&mut a, &mut b, c), 6);
+    assert_eq!(a.x, 0);
+    assert_eq!(f2(a.x, |_| a.x = 50), 0);
+}
diff --git a/src/test/ui/consts/issue-67641.rs b/src/test/ui/consts/issue-67641.rs
new file mode 100644 (file)
index 0000000..f50fba2
--- /dev/null
@@ -0,0 +1,24 @@
+// compile-flags: -Z mir-opt-level=2
+// run-pass
+
+use std::cell::Cell;
+
+#[derive(Debug)]
+struct B<'a> {
+    a: [Cell<Option<&'a B<'a>>>; 2]
+}
+
+impl<'a> B<'a> {
+    fn new() -> B<'a> {
+        B { a: [Cell::new(None), Cell::new(None)] }
+    }
+}
+
+fn f() {
+    let b2 = B::new();
+    b2.a[0].set(Some(&b2));
+}
+
+fn main() {
+    f();
+}
diff --git a/src/test/ui/consts/issue-67862.rs b/src/test/ui/consts/issue-67862.rs
new file mode 100644 (file)
index 0000000..84f7215
--- /dev/null
@@ -0,0 +1,18 @@
+// compile-flags: -Z mir-opt-level=2
+// run-pass
+
+fn e220() -> (i64, i64) {
+    #[inline(never)]
+    fn get_displacement() -> [i64; 2] {
+        [139776, 963904]
+    }
+
+    let res = get_displacement();
+    match (&res[0], &res[1]) {
+        (arg0, arg1) => (*arg0, *arg1),
+    }
+}
+
+fn main() {
+    assert_eq!(e220(), (139776, 963904));
+}
index 2cdeb598c8cc617fb414a1edf820c01c07c3578a..2439d527bd1970752c3e8a5378c1ebbb6ef144ff 100644 (file)
@@ -7,17 +7,17 @@ LL |     let _v: Vec<i32> = Vec::new();
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/libcore/ptr/mod.rs:LL:COL
    |
-LL | / unsafe fn real_drop_in_place<T: ?Sized>(to_drop: &mut T) {
+LL | / pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
 LL | |     // Code here does not matter - this is replaced by the
 LL | |     // real drop glue by the compiler.
-LL | |     real_drop_in_place(to_drop)
+LL | |     drop_in_place(to_drop)
 LL | | }
    | |_^ calling non-const function `<std::vec::Vec<i32> as std::ops::Drop>::drop`
    | 
   ::: $DIR/drop.rs:23:1
    |
 LL |   };
-   |   - inside call to `std::ptr::real_drop_in_place::<std::vec::Vec<i32>> - shim(Some(std::vec::Vec<i32>))` at $DIR/drop.rs:23:1
+   |   - inside call to `std::intrinsics::drop_in_place::<std::vec::Vec<i32>> - shim(Some(std::vec::Vec<i32>))` at $DIR/drop.rs:23:1
 
 error: aborting due to previous error
 
index 655c31763ef44de23047c172d2e49c815d50dfbd..0d7fb845a40eeffb1cba2bc8193a1c8455e27d92 100644 (file)
@@ -10,7 +10,7 @@ error: internal compiler error: mutable allocation in constant
 LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:346:17
+thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:356:17
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 
 error: internal compiler error: unexpected panic
index fb92196b2bd56b57a6628d46a5e9e0a2ee2137f8..34e7cad935aebafe29533ad710a429872f05fb11 100644 (file)
@@ -33,12 +33,10 @@ fn main() {
     //~^ ERROR mismatched types
     //~| expected trait object `dyn T`
     //~| found reference `&_`
-    //~| expected trait `T`, found reference
     let &&&x = &(&1isize as &dyn T);
     //~^ ERROR mismatched types
     //~| expected trait object `dyn T`
     //~| found reference `&_`
-    //~| expected trait `T`, found reference
     let box box x = box 1isize as Box<dyn T>;
     //~^ ERROR mismatched types
     //~| expected trait object `dyn T`
index c78166f411d2855d8c3fb287720631bc7b7fe71c..f99bf2ffdc9d45dc85d7915d7776762ed0a5e6f2 100644 (file)
@@ -22,31 +22,31 @@ error[E0308]: mismatched types
 LL |     let &&x = &1isize as &dyn T;
    |          ^^
    |          |
-   |          expected trait `T`, found reference
+   |          expected trait object `dyn T`, found reference
    |          help: you can probably remove the explicit borrow: `x`
    |
    = note: expected trait object `dyn T`
                  found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/destructure-trait-ref.rs:37:11
+  --> $DIR/destructure-trait-ref.rs:36:11
    |
 LL |     let &&&x = &(&1isize as &dyn T);
    |           ^^
    |           |
-   |           expected trait `T`, found reference
+   |           expected trait object `dyn T`, found reference
    |           help: you can probably remove the explicit borrow: `x`
    |
    = note: expected trait object `dyn T`
                  found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/destructure-trait-ref.rs:42:13
+  --> $DIR/destructure-trait-ref.rs:40:13
    |
 LL |     let box box x = box 1isize as Box<dyn T>;
    |             ^^^^^   ------------------------ this expression has type `std::boxed::Box<dyn T>`
    |             |
-   |             expected trait `T`, found struct `std::boxed::Box`
+   |             expected trait object `dyn T`, found struct `std::boxed::Box`
    |
    = note: expected trait object `dyn T`
                     found struct `std::boxed::Box<_>`
index 91063edf0f6c4badf45a759ad86bcb9722290287..30a896059449373fe6dd5c37f0b44e3b2b6b5dd9 100644 (file)
@@ -7,7 +7,6 @@
 // edition:2018
 // ignore-wasm32-bare compiled with panic=abort by default
 
-#![feature(slice_patterns)]
 #![allow(unused)]
 
 use std::{
index 0f0ec0ba460c8e91c339e1455a2270054c7c8504..b4406204a5db9f214d60c1ea01c1a995e380d4dc 100644 (file)
@@ -1,11 +1,10 @@
 // run-pass
-#![allow(unused_assignments)]
-#![allow(unused_variables)]
-
 // ignore-wasm32-bare compiled with panic=abort by default
 
 #![feature(generators, generator_trait, untagged_unions)]
-#![feature(slice_patterns)]
+
+#![allow(unused_assignments)]
+#![allow(unused_variables)]
 
 use std::cell::{Cell, RefCell};
 use std::mem::ManuallyDrop;
index e3b621b909a0c186ca7e6e477f1112a23b008754..d05b3937c998ccfaec6541d8347cda5ce09a0fa7 100644 (file)
@@ -32,7 +32,7 @@ pub fn main() {
     let z: Box<dyn ToBar> = Box::new(Bar1 {f: 36});
     f5.2 = Bar1 {f: 36};
     //~^ ERROR mismatched types
-    //~| expected trait `ToBar`, found struct `Bar1`
+    //~| expected trait object `dyn ToBar`, found struct `Bar1`
     //~| expected trait object `dyn ToBar`
     //~| found struct `Bar1`
     //~| ERROR the size for values of type
index dc03f38e103874d1964d2b20b2d28e8190ea60e4..0b6f9df2d83ee367656f58eef7faa62cea479631 100644 (file)
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/dst-bad-assign-3.rs:33:12
    |
 LL |     f5.2 = Bar1 {f: 36};
-   |            ^^^^^^^^^^^^ expected trait `ToBar`, found struct `Bar1`
+   |            ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1`
    |
    = note: expected trait object `dyn ToBar`
                     found struct `Bar1`
index ed94242f5bfd072ebef41fc7407eaf9b60fa35e4..496e01ae005326748fd9f162e8642ed0ff1b1d4c 100644 (file)
@@ -34,7 +34,7 @@ pub fn main() {
     let z: Box<dyn ToBar> = Box::new(Bar1 {f: 36});
     f5.ptr = Bar1 {f: 36};
     //~^ ERROR mismatched types
-    //~| expected trait `ToBar`, found struct `Bar1`
+    //~| expected trait object `dyn ToBar`, found struct `Bar1`
     //~| expected trait object `dyn ToBar`
     //~| found struct `Bar1`
     //~| ERROR the size for values of type
index 8031f162482e39b0624f50735ab341b4bd78c38f..434c460759fb4c4192d54e31d09e7add449e9db2 100644 (file)
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/dst-bad-assign.rs:35:14
    |
 LL |     f5.ptr = Bar1 {f: 36};
-   |              ^^^^^^^^^^^^ expected trait `ToBar`, found struct `Bar1`
+   |              ^^^^^^^^^^^^ expected trait object `dyn ToBar`, found struct `Bar1`
    |
    = note: expected trait object `dyn ToBar`
                     found struct `Bar1`
index 17d03b14fc6e176487c59800b2d0db61de867108..0a337c9611c8b9b17b29b5fa6287670365acb078 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn main() {
     let r = &[1, 2];
     match r {
index 0f566091145bffaf32458f923677a520690719ea..21615f954c3637dff7d0d926c07eb98d944b2a1c 100644 (file)
@@ -1,5 +1,5 @@
 error[E0528]: pattern requires at least 3 elements but array has 2
-  --> $DIR/E0528.rs:6:10
+  --> $DIR/E0528.rs:4:10
    |
 LL |         &[a, b, c, rest @ ..] => {
    |          ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 2 elements
index 444005e086f1be3024418a36e3afc2bb7d4c6dde..724d04954a3c7da1a2926c17d78a364691e17172 100644 (file)
@@ -2,7 +2,13 @@ error[E0603]: constant `PRIVATE` is private
   --> $DIR/E0603.rs:6:17
    |
 LL |     SomeModule::PRIVATE;
-   |                 ^^^^^^^
+   |                 ^^^^^^^ this constant is private
+   |
+note: the constant `PRIVATE` is defined here
+  --> $DIR/E0603.rs:2:5
+   |
+LL |     const PRIVATE: u32 = 0x_a_bad_1dea_u32;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0746.fixed b/src/test/ui/error-codes/E0746.fixed
new file mode 100644 (file)
index 0000000..ca8319a
--- /dev/null
@@ -0,0 +1,18 @@
+// run-rustfix
+#![allow(dead_code)]
+struct Struct;
+trait Trait {}
+impl Trait for Struct {}
+impl Trait for u32 {}
+
+fn foo() -> impl Trait { Struct }
+//~^ ERROR E0746
+
+fn bar() -> impl Trait { //~ ERROR E0746
+    if true {
+        return 0;
+    }
+    42
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0746.rs b/src/test/ui/error-codes/E0746.rs
new file mode 100644 (file)
index 0000000..bf5ba8f
--- /dev/null
@@ -0,0 +1,18 @@
+// run-rustfix
+#![allow(dead_code)]
+struct Struct;
+trait Trait {}
+impl Trait for Struct {}
+impl Trait for u32 {}
+
+fn foo() -> dyn Trait { Struct }
+//~^ ERROR E0746
+
+fn bar() -> dyn Trait { //~ ERROR E0746
+    if true {
+        return 0;
+    }
+    42
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0746.stderr b/src/test/ui/error-codes/E0746.stderr
new file mode 100644 (file)
index 0000000..e7a8fd3
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0746]: return type cannot have an unboxed trait object
+  --> $DIR/E0746.rs:8:13
+   |
+LL | fn foo() -> dyn Trait { Struct }
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: return `impl Trait` instead, as all return paths are of type `Struct`, which implements `Trait`
+   |
+LL | fn foo() -> impl Trait { Struct }
+   |             ^^^^^^^^^^
+
+error[E0746]: return type cannot have an unboxed trait object
+  --> $DIR/E0746.rs:11:13
+   |
+LL | fn bar() -> dyn Trait {
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: return `impl Trait` instead, as all return paths are of type `{integer}`, which implements `Trait`
+   |
+LL | fn bar() -> impl Trait {
+   |             ^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0746`.
index 6b80d99b3afe9a534c7f133dd20dfaed5fbe645c..9b69b3733642b4aac6d6505073c0b0f164c4e181 100644 (file)
@@ -8,7 +8,13 @@ error[E0603]: constant `FOO` is private
   --> $DIR/error-festival.rs:22:10
    |
 LL |     foo::FOO;
-   |          ^^^
+   |          ^^^ this constant is private
+   |
+note: the constant `FOO` is defined here
+  --> $DIR/error-festival.rs:7:5
+   |
+LL |     const FOO: u32 = 0;
+   |     ^^^^^^^^^^^^^^^^^^^
 
 error[E0368]: binary assignment operation `+=` cannot be applied to type `&str`
   --> $DIR/error-festival.rs:12:5
index e02952e0fe092a9387b6b424368a931957b03953..8160775ab589eeebe1e4598a4eb7a5abc1316dfa 100644 (file)
@@ -2,7 +2,13 @@ error[E0603]: function `unexported` is private
   --> $DIR/export-import.rs:1:8
    |
 LL | use m::unexported;
-   |        ^^^^^^^^^^
+   |        ^^^^^^^^^^ this function is private
+   |
+note: the function `unexported` is defined here
+  --> $DIR/export-import.rs:7:5
+   |
+LL |     fn unexported() { }
+   |     ^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index b5a2c12c436d07f4d38e72b912775cf993e7835f..f4537a2fb6fae35648298003403e659b365cf1d4 100644 (file)
@@ -2,7 +2,13 @@ error[E0603]: enum `Y` is private
   --> $DIR/export-tag-variant.rs:7:26
    |
 LL | fn main() { let z = foo::Y::Y1; }
-   |                          ^
+   |                          ^ this enum is private
+   |
+note: the enum `Y` is defined here
+  --> $DIR/export-tag-variant.rs:4:5
+   |
+LL |     enum Y { Y1 }
+   |     ^^^^^^
 
 error: aborting due to previous error
 
index a3668a502cdd4aefce9d7f9907921677a6c4666e..107f531c09a3a458d1be7724527578aa61ed5f9e 100644 (file)
@@ -26,7 +26,13 @@ error[E0603]: function `z` is private
   --> $DIR/export.rs:10:18
    |
 LL | fn main() { foo::z(10); }
-   |                  ^
+   |                  ^ this function is private
+   |
+note: the function `z` is defined here
+  --> $DIR/export.rs:5:5
+   |
+LL |     fn z(y: isize) { log(debug, y); }
+   |     ^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
index e0a5cd5e98f4b72ddc533640fc691ef0151252a1..cda1227cc8e924e0210eff954ca5299a261813ab 100644 (file)
@@ -3,10 +3,10 @@ mod foo {
 }
 
 // Check that private crates can be used from outside their modules, albeit with warnings
-use foo::core::cell; //~ ERROR crate `core` is private
+use foo::core::cell; //~ ERROR crate import `core` is private
 
 fn f() {
-    foo::core::cell::Cell::new(0); //~ ERROR crate `core` is private
+    foo::core::cell::Cell::new(0); //~ ERROR crate import `core` is private
 
     use foo::*;
     mod core {} // Check that private crates are not glob imported
index 38c791ab83237e6a5889ec8bf90e528f3938499c..d0c073d67a4ee22e77a816c9979775aa2538fb59 100644 (file)
@@ -1,14 +1,26 @@
-error[E0603]: crate `core` is private
+error[E0603]: crate import `core` is private
   --> $DIR/extern-crate-visibility.rs:6:10
    |
 LL | use foo::core::cell;
-   |          ^^^^
+   |          ^^^^ this crate import is private
+   |
+note: the crate import `core` is defined here
+  --> $DIR/extern-crate-visibility.rs:2:5
+   |
+LL |     extern crate core;
+   |     ^^^^^^^^^^^^^^^^^^
 
-error[E0603]: crate `core` is private
+error[E0603]: crate import `core` is private
   --> $DIR/extern-crate-visibility.rs:9:10
    |
 LL |     foo::core::cell::Cell::new(0);
-   |          ^^^^
+   |          ^^^^ this crate import is private
+   |
+note: the crate import `core` is defined here
+  --> $DIR/extern-crate-visibility.rs:2:5
+   |
+LL |     extern crate core;
+   |     ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/feature-gates/feature-gate-slice-patterns.rs b/src/test/ui/feature-gates/feature-gate-slice-patterns.rs
deleted file mode 100644 (file)
index f2a1b13..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// Test that slice pattern syntax with `..` is gated by `slice_patterns` feature gate
-
-fn main() {
-    let x = [1, 2, 3, 4, 5];
-    match x {
-        [1, 2, ..] => {} //~ ERROR subslice patterns are unstable
-        [1, .., 5] => {} //~ ERROR subslice patterns are unstable
-        [.., 4, 5] => {} //~ ERROR subslice patterns are unstable
-    }
-
-    let x = [ 1, 2, 3, 4, 5 ];
-    match x {
-        [ xs @ .., 4, 5 ] => {} //~ ERROR subslice patterns are unstable
-        [ 1, xs @ .., 5 ] => {} //~ ERROR subslice patterns are unstable
-        [ 1, 2, xs @ .. ] => {} //~ ERROR subslice patterns are unstable
-    }
-}
diff --git a/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr b/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr
deleted file mode 100644 (file)
index d4946a4..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-error[E0658]: subslice patterns are unstable
-  --> $DIR/feature-gate-slice-patterns.rs:6:16
-   |
-LL |         [1, 2, ..] => {}
-   |                ^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/feature-gate-slice-patterns.rs:7:13
-   |
-LL |         [1, .., 5] => {}
-   |             ^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/feature-gate-slice-patterns.rs:8:10
-   |
-LL |         [.., 4, 5] => {}
-   |          ^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/feature-gate-slice-patterns.rs:13:11
-   |
-LL |         [ xs @ .., 4, 5 ] => {}
-   |           ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/feature-gate-slice-patterns.rs:14:14
-   |
-LL |         [ 1, xs @ .., 5 ] => {}
-   |              ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/feature-gate-slice-patterns.rs:15:17
-   |
-LL |         [ 1, 2, xs @ .. ] => {}
-   |                 ^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
index 017990076931bdff276322bfb199d15057368e42..ca2350ff7577f113e0da014c6e12ed49b7a595e8 100644 (file)
@@ -38,7 +38,7 @@ LL |     type C where Self: Copy = String;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
    |
    = note: required because of the requirements on the impl of `std::marker::Copy` for `Fooy<T>`
-   = note: the requirement `Fooy<T>: std::marker::Copy` appears on the associated impl typebut not on the corresponding associated trait type
+   = note: the requirement `Fooy<T>: std::marker::Copy` appears on the associated impl type but not on the corresponding associated trait type
 
 error: aborting due to 3 previous errors
 
index 80fb4dd0f314aa9d8ddee07b7839e431370bb62b..0649dc0ec58366f015b782d6cdc1f116ee46d406 100644 (file)
@@ -2,7 +2,13 @@ error[E0603]: function `f` is private
   --> $DIR/privacy.rs:16:14
    |
 LL |         foo::f()
-   |              ^
+   |              ^ this function is private
+   |
+note: the function `f` is defined here
+  --> $DIR/privacy.rs:4:5
+   |
+LL |     fn f() {}
+   |     ^^^^^^
 
 error: aborting due to previous error
 
index 8c046a289fad2f16f79ac65a5f320d789c92b289..5980e1a857f26f3d858c7cd7e3bdf8ce0f7f968e 100644 (file)
@@ -3,9 +3,6 @@
 #![allow(non_shorthand_field_patterns)]
 #![allow(dead_code)]
 #![allow(unused_variables)]
-// pretty-expanded FIXME #23616
-
-#![feature(slice_patterns)]
 
 struct Foo(isize, isize, isize, isize);
 struct Bar{a: isize, b: isize, c: isize, d: isize}
diff --git a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs
new file mode 100644 (file)
index 0000000..b70a51d
--- /dev/null
@@ -0,0 +1,34 @@
+#![allow(bare_trait_objects)]
+struct Struct;
+trait Trait {}
+impl Trait for Struct {}
+impl Trait for u32 {}
+
+fn fuz() -> (usize, Trait) { (42, Struct) }
+//~^ ERROR E0277
+//~| ERROR E0308
+fn bar() -> (usize, dyn Trait) { (42, Struct) }
+//~^ ERROR E0277
+//~| ERROR E0308
+fn bap() -> Trait { Struct }
+//~^ ERROR E0746
+fn ban() -> dyn Trait { Struct }
+//~^ ERROR E0746
+fn bak() -> dyn Trait { unimplemented!() } //~ ERROR E0277
+// Suggest using `Box<dyn Trait>`
+fn bal() -> dyn Trait { //~ ERROR E0746
+    if true {
+        return Struct;
+    }
+    42
+}
+
+// Suggest using `impl Trait`
+fn bat() -> dyn Trait { //~ ERROR E0746
+    if true {
+        return 0;
+    }
+    42
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/src/test/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
new file mode 100644 (file)
index 0000000..977a7ef
--- /dev/null
@@ -0,0 +1,113 @@
+error[E0308]: mismatched types
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:35
+   |
+LL | fn fuz() -> (usize, Trait) { (42, Struct) }
+   |                                   ^^^^^^ expected trait object `dyn Trait`, found struct `Struct`
+   |
+   = note: expected trait object `(dyn Trait + 'static)`
+                    found struct `Struct`
+
+error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:7:13
+   |
+LL | fn fuz() -> (usize, Trait) { (42, Struct) }
+   |             ^^^^^^^^^^^^^^   ------------ this returned value is of type `(usize, (dyn Trait + 'static))`
+   |             |
+   |             doesn't have a size known at compile-time
+   |
+   = help: within `(usize, (dyn Trait + 'static))`, the trait `std::marker::Sized` is not implemented for `(dyn Trait + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `(usize, (dyn Trait + 'static))`
+   = note: the return type of a function must have a statically known size
+
+error[E0308]: mismatched types
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:39
+   |
+LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
+   |                                       ^^^^^^ expected trait object `dyn Trait`, found struct `Struct`
+   |
+   = note: expected trait object `(dyn Trait + 'static)`
+                    found struct `Struct`
+
+error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:10:13
+   |
+LL | fn bar() -> (usize, dyn Trait) { (42, Struct) }
+   |             ^^^^^^^^^^^^^^^^^^   ------------ this returned value is of type `(usize, (dyn Trait + 'static))`
+   |             |
+   |             doesn't have a size known at compile-time
+   |
+   = help: within `(usize, (dyn Trait + 'static))`, the trait `std::marker::Sized` is not implemented for `(dyn Trait + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `(usize, (dyn Trait + 'static))`
+   = note: the return type of a function must have a statically known size
+
+error[E0746]: return type cannot have an unboxed trait object
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:13:13
+   |
+LL | fn bap() -> Trait { Struct }
+   |             ^^^^^ doesn't have a size known at compile-time
+   |
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: return `impl Trait` instead, as all return paths are of type `Struct`, which implements `Trait`
+   |
+LL | fn bap() -> impl Trait { Struct }
+   |             ^^^^^^^^^^
+
+error[E0746]: return type cannot have an unboxed trait object
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:13
+   |
+LL | fn ban() -> dyn Trait { Struct }
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: return `impl Trait` instead, as all return paths are of type `Struct`, which implements `Trait`
+   |
+LL | fn ban() -> impl Trait { Struct }
+   |             ^^^^^^^^^^
+
+error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:17:13
+   |
+LL | fn bak() -> dyn Trait { unimplemented!() }
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `(dyn Trait + 'static)`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: the return type of a function must have a statically known size
+
+error[E0746]: return type cannot have an unboxed trait object
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13
+   |
+LL | fn bal() -> dyn Trait {
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = note: if all the returned values were of the same type you could use `impl Trait` as the return type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = note: you can create a new `enum` with a variant for each returned type
+help: return a boxed trait object instead
+   |
+LL | fn bal() -> Box<dyn Trait> {
+LL |     if true {
+LL |         return Box::new(Struct);
+LL |     }
+LL |     Box::new(42)
+   |
+
+error[E0746]: return type cannot have an unboxed trait object
+  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:27:13
+   |
+LL | fn bat() -> dyn Trait {
+   |             ^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+help: return `impl Trait` instead, as all return paths are of type `{integer}`, which implements `Trait`
+   |
+LL | fn bat() -> impl Trait {
+   |             ^^^^^^^^^^
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0277, E0308, E0746.
+For more information about an error, try `rustc --explain E0277`.
index e53524e58d663d8c3a5bd7afd4a39cffeedb9956..9178358b60a9c140a8f19870d3ac1f5225898865 100644 (file)
@@ -9,6 +9,12 @@ LL |         return 1_i32;
 LL |     }
 LL |     0_u32
    |     ^^^^^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: if the trait `Foo` were object safe, you could return a boxed trait object
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error[E0277]: cannot add `impl Foo` to `u32`
   --> $DIR/equality.rs:24:11
diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.rs
new file mode 100644 (file)
index 0000000..ab3086c
--- /dev/null
@@ -0,0 +1,35 @@
+#![allow(bare_trait_objects)]
+trait NotObjectSafe {
+    fn foo() -> Self;
+}
+
+struct A;
+struct B;
+
+impl NotObjectSafe for A {
+    fn foo() -> Self {
+        A
+    }
+}
+
+impl NotObjectSafe for B {
+    fn foo() -> Self {
+        B
+    }
+}
+
+fn car() -> dyn NotObjectSafe { //~ ERROR the trait `NotObjectSafe` cannot be made into an object
+    if true {
+        return A;
+    }
+    B
+}
+
+fn cat() -> Box<dyn NotObjectSafe> { //~ ERROR the trait `NotObjectSafe` cannot be made into an
+    if true {
+        return Box::new(A);
+    }
+    Box::new(B)
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-dyn-trait.stderr
new file mode 100644 (file)
index 0000000..0c8d267
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0038]: the trait `NotObjectSafe` cannot be made into an object
+  --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:21:1
+   |
+LL |     fn foo() -> Self;
+   |        --- associated function `foo` has no `self` parameter
+...
+LL | fn car() -> dyn NotObjectSafe {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
+
+error[E0038]: the trait `NotObjectSafe` cannot be made into an object
+  --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:28:1
+   |
+LL |     fn foo() -> Self;
+   |        --- associated function `foo` has no `self` parameter
+...
+LL | fn cat() -> Box<dyn NotObjectSafe> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.rs
new file mode 100644 (file)
index 0000000..5035150
--- /dev/null
@@ -0,0 +1,46 @@
+trait NotObjectSafe {
+    fn foo() -> Self;
+}
+
+trait ObjectSafe {
+    fn bar(&self);
+}
+
+struct A;
+struct B;
+
+impl NotObjectSafe for A {
+    fn foo() -> Self {
+        A
+    }
+}
+
+impl NotObjectSafe for B {
+    fn foo() -> Self {
+        B
+    }
+}
+
+impl ObjectSafe for A {
+    fn bar(&self) {}
+}
+
+impl ObjectSafe for B {
+    fn bar(&self) {}
+}
+
+fn can() -> impl NotObjectSafe {
+    if true {
+        return A;
+    }
+    B //~ ERROR mismatched types
+}
+
+fn cat() -> impl ObjectSafe {
+    if true {
+        return A;
+    }
+    B //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr b/src/test/ui/impl-trait/object-unsafe-trait-in-return-position-impl-trait.stderr
new file mode 100644 (file)
index 0000000..dd4260f
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0308]: mismatched types
+  --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:36:5
+   |
+LL | fn can() -> impl NotObjectSafe {
+   |             ------------------ expected because this return type...
+LL |     if true {
+LL |         return A;
+   |                - ...is found to be `A` here
+LL |     }
+LL |     B
+   |     ^ expected struct `A`, found struct `B`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: if the trait `NotObjectSafe` were object safe, you could return a boxed trait object
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
+
+error[E0308]: mismatched types
+  --> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:43:5
+   |
+LL | fn cat() -> impl ObjectSafe {
+   |             --------------- expected because this return type...
+LL |     if true {
+LL |         return A;
+   |                - ...is found to be `A` here
+LL |     }
+LL |     B
+   |     ^ expected struct `A`, found struct `B`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn ObjectSafe>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
index 6b320b198a0b10c7da5a4c02dcf56864b72ed457..5219ffacd15c077e8a015623488adf92664f8f5c 100644 (file)
@@ -13,11 +13,17 @@ error[E0432]: unresolved import `foo`
 LL |     use foo;
    |         ^^^ no `foo` in the root
 
-error[E0603]: unresolved item `foo` is private
+error[E0603]: unresolved item import `foo` is private
   --> $DIR/import.rs:15:10
    |
 LL |     zed::foo();
-   |          ^^^
+   |          ^^^ this unresolved item import is private
+   |
+note: the unresolved item import `foo` is defined here
+  --> $DIR/import.rs:10:9
+   |
+LL |     use foo;
+   |         ^^^
 
 error: aborting due to 3 previous errors
 
index 1b4f652c9fc2f1acf060f0224a074885a03a6e4a..75bb4206f97d6642b271a9fba70ea6e0aa9eb4da 100644 (file)
@@ -9,6 +9,6 @@ mod parser {
     use ParseOptions;
 }
 
-pub use parser::ParseOptions; //~ ERROR struct `ParseOptions` is private
+pub use parser::ParseOptions; //~ ERROR struct import `ParseOptions` is private
 
 fn main() {}
index d3b43783ee9c8c8e2c8eef8346f9c1045e5099bb..f16d2adb3656e9f155437d852d43ef8d68adf179 100644 (file)
@@ -1,8 +1,14 @@
-error[E0603]: struct `ParseOptions` is private
+error[E0603]: struct import `ParseOptions` is private
   --> $DIR/issue-55884-2.rs:12:17
    |
 LL | pub use parser::ParseOptions;
-   |                 ^^^^^^^^^^^^
+   |                 ^^^^^^^^^^^^ this struct import is private
+   |
+note: the struct import `ParseOptions` is defined here
+  --> $DIR/issue-55884-2.rs:9:9
+   |
+LL |     use ParseOptions;
+   |         ^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 4388e2c276b8ebbda2cc938f14eee86f1ce75251..b173884080f8092af94d014350a758cd175f3bbb 100644 (file)
@@ -10,17 +10,29 @@ note: consider marking `foo` as `pub` in the imported module
 LL |         pub use super::foo;
    |                 ^^^^^^^^^^
 
-error[E0603]: module `foo` is private
+error[E0603]: module import `foo` is private
   --> $DIR/reexports.rs:33:15
    |
 LL |     use b::a::foo::S;
-   |               ^^^
+   |               ^^^ this module import is private
+   |
+note: the module import `foo` is defined here
+  --> $DIR/reexports.rs:21:17
+   |
+LL |         pub use super::foo; // This is OK since the value `foo` is visible enough.
+   |                 ^^^^^^^^^^
 
-error[E0603]: module `foo` is private
+error[E0603]: module import `foo` is private
   --> $DIR/reexports.rs:34:15
    |
 LL |     use b::b::foo::S as T;
-   |               ^^^
+   |               ^^^ this module import is private
+   |
+note: the module import `foo` is defined here
+  --> $DIR/reexports.rs:26:17
+   |
+LL |         pub use super::*; // This is also OK since the value `foo` is visible enough.
+   |                 ^^^^^^^^
 
 warning: glob import doesn't reexport anything because no candidate is public enough
   --> $DIR/reexports.rs:9:17
index b341e8e0592883863299c6e7800402a3f0363d12..d7280d2583a7697d0cc7c66c5ba2cee4bcdc9210 100644 (file)
@@ -38,7 +38,13 @@ error[E0603]: function `quz` is private
   --> $DIR/unresolved-imports-used.rs:9:10
    |
 LL | use qux::quz;
-   |          ^^^
+   |          ^^^ this function is private
+   |
+note: the function `quz` is defined here
+  --> $DIR/unresolved-imports-used.rs:5:4
+   |
+LL |    fn quz() {}
+   |    ^^^^^^^^
 
 error: unused import: `qux::quy`
   --> $DIR/unresolved-imports-used.rs:16:5
index 59d4fedcd2b40e5edd868c6effbb5a95f4917be9..4ed7028c0a06b550c436b25cecf4a51d6863f8b9 100644 (file)
@@ -2,7 +2,13 @@ error[E0603]: struct `S` is private
   --> $DIR/issue-10545.rs:6:14
    |
 LL | fn foo(_: a::S) {
-   |              ^
+   |              ^ this struct is private
+   |
+note: the struct `S` is defined here
+  --> $DIR/issue-10545.rs:2:5
+   |
+LL |     struct S;
+   |     ^^^^^^^^^
 
 error: aborting due to previous error
 
index c3e4412b042d7706834743de0a93cb487a1a0939..bfb4d31323b13c1ca85653e698ff8bdf6314b958 100644 (file)
@@ -2,7 +2,13 @@ error[E0603]: trait `Foo` is private
   --> $DIR/issue-11593.rs:7:24
    |
 LL | impl private_trait_xc::Foo for Bar {}
-   |                        ^^^
+   |                        ^^^ this trait is private
+   |
+note: the trait `Foo` is defined here
+  --> $DIR/auxiliary/private-trait-xc.rs:1:1
+   |
+LL | trait Foo {}
+   | ^^^^^^^^^
 
 error: aborting due to previous error
 
index 35cb2476992ac1b379f06c39e70b0c0df4928609..898ac10f7d9a92587f28812df1247ba695bcb686 100644 (file)
@@ -2,13 +2,25 @@ error[E0603]: enum `Foo` is private
   --> $DIR/issue-11680.rs:6:21
    |
 LL |     let _b = other::Foo::Bar(1);
-   |                     ^^^
+   |                     ^^^ this enum is private
+   |
+note: the enum `Foo` is defined here
+  --> $DIR/auxiliary/issue-11680.rs:1:1
+   |
+LL | enum Foo {
+   | ^^^^^^^^
 
 error[E0603]: enum `Foo` is private
   --> $DIR/issue-11680.rs:9:27
    |
 LL |     let _b = other::test::Foo::Bar(1);
-   |                           ^^^
+   |                           ^^^ this enum is private
+   |
+note: the enum `Foo` is defined here
+  --> $DIR/auxiliary/issue-11680.rs:6:5
+   |
+LL |     enum Foo {
+   |     ^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 086613180746362a414dbb7abb33dc348402311c..0481c1fd9e1bbdb4e5d67e96396ce3087b6c9e6e 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(slice_patterns)]
 #![deny(unreachable_patterns)]
 
 fn main() {
index f27425e28c61d3d9b12af0af8aea6658c8c2ce89..754b94bab75ebb2acc5753c20bb0417cba3cc7ec 100644 (file)
@@ -1,11 +1,11 @@
 error: unreachable pattern
-  --> $DIR/issue-12369.rs:10:9
+  --> $DIR/issue-12369.rs:9:9
    |
 LL |         &[10,a, ref rest @ ..] => 10
    |         ^^^^^^^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/issue-12369.rs:2:9
+  --> $DIR/issue-12369.rs:1:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
index 643d9a2fc69e9b922daae1393334fc6df8af3426..1b2a37de475398dec728af32f67174998c0e9a4c 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) {
     match (l1, l2) {
     //~^ ERROR: cannot move out of type `[T]`, a non-copy slice
index 9d9a88f4f9b06353a1a0a73c1f600d281e712ed4..2a88d8f0524ace1bc740cd2dd6aad769efb46f1b 100644 (file)
@@ -1,5 +1,5 @@
 error[E0508]: cannot move out of type `[T]`, a non-copy slice
-  --> $DIR/issue-12567.rs:4:11
+  --> $DIR/issue-12567.rs:2:11
    |
 LL |     match (l1, l2) {
    |           ^^^^^^^^ cannot move out of here
@@ -13,7 +13,7 @@ LL |         (&[hd1, ..], &[hd2, ..])
    = note: move occurs because these variables have types that don't implement the `Copy` trait
 
 error[E0508]: cannot move out of type `[T]`, a non-copy slice
-  --> $DIR/issue-12567.rs:4:11
+  --> $DIR/issue-12567.rs:2:11
    |
 LL |     match (l1, l2) {
    |           ^^^^^^^^ cannot move out of here
index b280de3158fede7567b64391c728f6464b685e13..f211d623ab12bd4a975c279c392048207740c1b2 100644 (file)
@@ -2,7 +2,13 @@ error[E0603]: unit struct `C` is private
   --> $DIR/issue-13407.rs:6:8
    |
 LL |     A::C = 1;
-   |        ^
+   |        ^ this unit struct is private
+   |
+note: the unit struct `C` is defined here
+  --> $DIR/issue-13407.rs:2:5
+   |
+LL |     struct C;
+   |     ^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-13407.rs:6:12
index 8e5001e3b694d6926aca7e499674170f47454dfc..f90cb18b6fc9d0d7e91a374369fc0c21b9282732 100644 (file)
@@ -2,13 +2,25 @@ error[E0603]: struct `Foo` is private
   --> $DIR/issue-13641.rs:9:8
    |
 LL |     a::Foo::new();
-   |        ^^^
+   |        ^^^ this struct is private
+   |
+note: the struct `Foo` is defined here
+  --> $DIR/issue-13641.rs:2:5
+   |
+LL |     struct Foo;
+   |     ^^^^^^^^^^^
 
 error[E0603]: enum `Bar` is private
   --> $DIR/issue-13641.rs:11:8
    |
 LL |     a::Bar::new();
-   |        ^^^
+   |        ^^^ this enum is private
+   |
+note: the enum `Bar` is defined here
+  --> $DIR/issue-13641.rs:4:5
+   |
+LL |     enum Bar {}
+   |     ^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index b11b1cda38ae127d39b64c94f873227064444b9c..4dd6981d448e54e7856783a7689da2787f41a607 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn main() {
     let mut x: &[_] = &[1, 2, 3, 4];
index ee977541137db66e351a7a3e7f004873d0e6d8c1..47b207ea9cbf5e290738fc389d41572f3f08ad08 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn main() {
     assert_eq!(count_members(&[1, 2, 3, 4]), 4);
index 562ad940423c292afa779c49bcddf42307d7d1a5..e0a1ca8a5ac319347fcae50dcf6c9b8ff7234449 100644 (file)
@@ -2,7 +2,13 @@ error[E0603]: function `bar` is private
   --> $DIR/issue-16725.rs:6:19
    |
 LL |     unsafe { foo::bar(); }
-   |                   ^^^
+   |                   ^^^ this function is private
+   |
+note: the function `bar` is defined here
+  --> $DIR/auxiliary/issue-16725.rs:2:5
+   |
+LL |     fn bar();
+   |     ^^^^^^^^^
 
 error: aborting due to previous error
 
index 0b0de8a52590b76beeebc6b9b24f1252b4f3d0df..07d825ba9cb3b2c490b8bee72e5a806f56b7563a 100644 (file)
@@ -2,13 +2,25 @@ error[E0603]: constant `B` is private
   --> $DIR/issue-17718-const-privacy.rs:5:8
    |
 LL | use a::B;
-   |        ^
+   |        ^ this constant is private
+   |
+note: the constant `B` is defined here
+  --> $DIR/issue-17718-const-privacy.rs:13:5
+   |
+LL |     const B: usize = 3;
+   |     ^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: constant `BAR` is private
   --> $DIR/issue-17718-const-privacy.rs:8:5
    |
 LL |     BAR,
-   |     ^^^
+   |     ^^^ this constant is private
+   |
+note: the constant `BAR` is defined here
+  --> $DIR/auxiliary/issue-17718-const-privacy.rs:4:1
+   |
+LL | const BAR: usize = 3;
+   | ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index fefa3f2f8730465b7bcb9916a2a96c9adca23041..126e01de5ee3f7b3fdcb6f432bf0923833b8e870 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn main() {
     assert_eq!(match [0u8; 1024] {
index f275c6338b194e977199ecbc22870632506decbd..62c96840b3bc4ad6dcfd0e50482d69abee2f5e67 100644 (file)
@@ -1,7 +1,6 @@
 // run-pass
-// Test that we do not ICE when pattern matching an array against a slice.
 
-#![feature(slice_patterns)]
+// Test that we do not ICE when pattern matching an array against a slice.
 
 fn main() {
     match "foo".as_bytes() {
diff --git a/src/test/ui/issues/issue-26548.rs b/src/test/ui/issues/issue-26548.rs
deleted file mode 100644 (file)
index 6ee8c0f..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-//~ ERROR cycle detected when computing layout of
-//~| NOTE ...which requires computing layout of
-//~| NOTE ...which again requires computing layout of
-
-// build-fail
-
-trait Mirror { type It: ?Sized; }
-impl<T: ?Sized> Mirror for T { type It = Self; }
-struct S(Option<<S as Mirror>::It>);
-
-fn main() { //~ NOTE cycle used when processing `main`
-    let _s = S(None);
-}
diff --git a/src/test/ui/issues/issue-26548.stderr b/src/test/ui/issues/issue-26548.stderr
deleted file mode 100644 (file)
index 3c21367..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0391]: cycle detected when computing layout of `std::option::Option<S>`
-   |
-   = note: ...which requires computing layout of `S`...
-   = note: ...which again requires computing layout of `std::option::Option<S>`, completing the cycle
-note: cycle used when processing `main`
-  --> $DIR/issue-26548.rs:11:1
-   |
-LL | fn main() {
-   | ^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0391`.
index 00e09f3f0776476d4f9431085237ceefb403c934..b9d34b0555aee515694e36e9fb8b5021de4498f3 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 pub struct History<'a> { pub _s: &'a str }
 
 impl<'a> History<'a> {
index d1157cda92bf8948bc217fc15158bad4880b6809..1282fd7d3c238f734644ad909cb2c9dcfc20f40b 100644 (file)
@@ -1,5 +1,5 @@
 error[E0515]: cannot return value referencing function parameter
-  --> $DIR/issue-26619.rs:7:76
+  --> $DIR/issue-26619.rs:5:76
    |
 LL |         for s in vec!["1|2".to_string()].into_iter().filter_map(|ref line| self.make_entry(line)) {
    |                                                                  --------  ^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
index 7bbe0bc5ff154136612da4dfb79ef2457afcd8dc..58bd775f295fc61a1e6e9126cade57d32e3e683b 100644 (file)
@@ -2,7 +2,13 @@ error[E0603]: module `n` is private
   --> $DIR/issue-28388-2.rs:7:8
    |
 LL | use m::n::{};
-   |        ^
+   |        ^ this module is private
+   |
+note: the module `n` is defined here
+  --> $DIR/issue-28388-2.rs:4:5
+   |
+LL |     mod n {}
+   |     ^^^^^
 
 error: aborting due to previous error
 
index d30fd28a4a351e57b6c97185311fa5d5375bafff..1bfa211ef796263cda34427c9677ed953b982cf2 100644 (file)
@@ -8,7 +8,13 @@ error[E0603]: struct `A` is private
   --> $DIR/issue-29161.rs:13:8
    |
 LL |     a::A::default();
-   |        ^
+   |        ^ this struct is private
+   |
+note: the struct `A` is defined here
+  --> $DIR/issue-29161.rs:2:5
+   |
+LL |     struct A;
+   |     ^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 31b3aba6bc20422b27433e05eec5d5eb2b3cc020..458e999c3faa2b5425c7a8c425a8bbcc28f3b0b5 100644 (file)
@@ -1,5 +1,4 @@
 // check-pass
-#![feature(slice_patterns)]
 
 fn check(list: &[u8]) {
     match list {
diff --git a/src/test/ui/issues/issue-38591.rs b/src/test/ui/issues/issue-38591.rs
deleted file mode 100644 (file)
index 2f594b4..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// check-pass
-
-struct S<T> {
-    t : T,
-    s : Box<S<fn(u : T)>>
-}
-
-fn f(x : S<u32>) {}
-
-fn main () {}
index 81d881c100bb6936024cf9c349642d96e2d99fb7..c0695f8216512209097f7eb3c8fb684b6e38ff59 100644 (file)
@@ -1,3 +1,8 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
+
 fn main() {
     let a = std::sys::imp::process::process_common::StdioPipes { ..panic!() };
     //~^ ERROR failed to resolve: could not find `imp` in `sys` [E0433]
index 5762e3d6ac00a990ecc7f7e7b2912a6600ecc928..ba0f1336ff09d79c0fc20142d11d6e6a22d2bd6d 100644 (file)
@@ -1,14 +1,20 @@
 error[E0433]: failed to resolve: could not find `imp` in `sys`
-  --> $DIR/issue-38857.rs:2:23
+  --> $DIR/issue-38857.rs:7:23
    |
 LL |     let a = std::sys::imp::process::process_common::StdioPipes { ..panic!() };
    |                       ^^^ could not find `imp` in `sys`
 
 error[E0603]: module `sys` is private
-  --> $DIR/issue-38857.rs:2:18
+  --> $DIR/issue-38857.rs:7:18
    |
 LL |     let a = std::sys::imp::process::process_common::StdioPipes { ..panic!() };
-   |                  ^^^
+   |                  ^^^ this module is private
+   |
+note: the module `sys` is defined here
+  --> $SRC_DIR/libstd/lib.rs:LL:COL
+   |
+LL | mod sys;
+   | ^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index ce594a3f9bb27e269246e53f66d155c998591870..3fa8ed4af28fa3b43a8ffdd3256f0f5ee54d033c 100644 (file)
@@ -2,7 +2,13 @@ error[E0603]: function `fly` is private
   --> $DIR/issue-3993.rs:1:10
    |
 LL | use zoo::fly;
-   |          ^^^
+   |          ^^^ this function is private
+   |
+note: the function `fly` is defined here
+  --> $DIR/issue-3993.rs:4:5
+   |
+LL |     fn fly() {}
+   |     ^^^^^^^^
 
 error: aborting due to previous error
 
index 427d03b679d5f8daedcf05895e3c5b35408dd5c3..e0c196e518ba34b16df02161d597ad84f1b7461e 100644 (file)
@@ -3,6 +3,9 @@ error[E0277]: the trait bound `impl Trait<<u32 as std::ops::Add>::Output>: Trait
    |
 LL | ) -> Either<impl Trait<<u32 as Add<u32>>::Output>, impl Trait<<u32 as Add<u32>>::Output>> {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<u32>` is not implemented for `impl Trait<<u32 as std::ops::Add>::Output>`
+...
+LL |     add_generic(value, 1u32)
+   |     ------------------------ this returned value is of type `Either<impl Trait<<u32 as std::ops::Add>::Output>, impl Trait<<u32 as std::ops::Add>::Output>>`
    |
    = note: the return type of a function must have a statically known size
 
@@ -11,6 +14,9 @@ error[E0277]: the trait bound `impl Trait<<u32 as std::ops::Add>::Output>: Trait
    |
 LL | ) -> Either<impl Trait<<u32 as Add<u32>>::Output>, impl Trait<<u32 as Add<u32>>::Output>> {
    |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<u32>` is not implemented for `impl Trait<<u32 as std::ops::Add>::Output>`
+...
+LL |     add_generic(value, 1u32)
+   |     ------------------------ this returned value is of type `Either<impl Trait<<u32 as std::ops::Add>::Output>, impl Trait<<u32 as std::ops::Add>::Output>>`
    |
    = note: the return type of a function must have a statically known size
 
index c2de1d095505a462765725ca9a118f481204d953..d886ecc11d17b6abb726ae9ace156011e29c69f1 100644 (file)
@@ -14,6 +14,9 @@ error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at
    |
 LL |     -> Struct {
    |        ^^^^^^ doesn't have a size known at compile-time
+LL |
+LL |     Struct { r: r }
+   |     --------------- this returned value is of type `Struct`
    |
    = help: within `Struct`, the trait `std::marker::Sized` is not implemented for `(dyn A + 'static)`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
index 5b70bd6e5ff54923a8ed319fc23d84966d305138..b7323f09daff2ebc84ee46158381fbfdd3e8ff68 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 use std::ops::Add;
 
index 228582d0001daafdf6bca1198a862316cc9e1da0..e43fb6d0edfb9e730892d6cb0a3eef0fb090b8d2 100644 (file)
@@ -3,6 +3,9 @@ error[E0277]: the trait bound `std::result::Result<(), _>: Future` is not satisf
    |
 LL | fn foo() -> impl Future<Item=(), Error=Box<dyn Error>> {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Future` is not implemented for `std::result::Result<(), _>`
+LL |
+LL |     Ok(())
+   |     ------ this returned value is of type `std::result::Result<(), _>`
    |
    = note: the return type of a function must have a statically known size
 
diff --git a/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs b/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs
new file mode 100644 (file)
index 0000000..c2b8195
--- /dev/null
@@ -0,0 +1,29 @@
+#![deny(non_snake_case)]
+#![allow(unused_variables)]
+#![allow(dead_code)]
+
+enum Foo {
+    Bad {
+        lowerCamelCaseName: bool,
+        //~^ ERROR structure field `lowerCamelCaseName` should have a snake case name
+    },
+    Good {
+        snake_case_name: bool,
+    },
+}
+
+fn main() {
+    let b = Foo::Bad { lowerCamelCaseName: true };
+
+    match b {
+        Foo::Bad { lowerCamelCaseName } => {}
+        Foo::Good { snake_case_name: lowerCamelCaseBinding } => { }
+        //~^ ERROR variable `lowerCamelCaseBinding` should have a snake case name
+    }
+
+    if let Foo::Good { snake_case_name: anotherLowerCamelCaseBinding } = b { }
+    //~^ ERROR variable `anotherLowerCamelCaseBinding` should have a snake case name
+
+    if let Foo::Bad { lowerCamelCaseName: yetAnotherLowerCamelCaseBinding } = b { }
+    //~^ ERROR variable `yetAnotherLowerCamelCaseBinding` should have a snake case name
+}
diff --git a/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr b/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr
new file mode 100644 (file)
index 0000000..68956f2
--- /dev/null
@@ -0,0 +1,32 @@
+error: structure field `lowerCamelCaseName` should have a snake case name
+  --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:7:9
+   |
+LL |         lowerCamelCaseName: bool,
+   |         ^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `lower_camel_case_name`
+   |
+note: lint level defined here
+  --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:1:9
+   |
+LL | #![deny(non_snake_case)]
+   |         ^^^^^^^^^^^^^^
+
+error: variable `lowerCamelCaseBinding` should have a snake case name
+  --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:20:38
+   |
+LL |         Foo::Good { snake_case_name: lowerCamelCaseBinding } => { }
+   |                                      ^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `lower_camel_case_binding`
+
+error: variable `anotherLowerCamelCaseBinding` should have a snake case name
+  --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:24:41
+   |
+LL |     if let Foo::Good { snake_case_name: anotherLowerCamelCaseBinding } = b { }
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `another_lower_camel_case_binding`
+
+error: variable `yetAnotherLowerCamelCaseBinding` should have a snake case name
+  --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:27:43
+   |
+LL |     if let Foo::Bad { lowerCamelCaseName: yetAnotherLowerCamelCaseBinding } = b { }
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `yet_another_lower_camel_case_binding`
+
+error: aborting due to 4 previous errors
+
index 9b44421808e88450e1b87453e0011613a1a3570e..72994d1652cd0d8c702d35ae15825820a5c26ac9 100644 (file)
@@ -2,7 +2,14 @@ error[E0603]: constant `baz` is private
   --> $DIR/macro-local-data-key-priv.rs:8:10
    |
 LL |     bar::baz.with(|_| ());
-   |          ^^^
+   |          ^^^ this constant is private
+   |
+note: the constant `baz` is defined here
+  --> $DIR/macro-local-data-key-priv.rs:4:5
+   |
+LL |     thread_local!(static baz: f64 = 0.0);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/marker_trait_attr/issue-61651-type-mismatch.rs b/src/test/ui/marker_trait_attr/issue-61651-type-mismatch.rs
new file mode 100644 (file)
index 0000000..0af7066
--- /dev/null
@@ -0,0 +1,17 @@
+// check-pass
+// Regression test for issue #61651
+// Verifies that we don't try to constrain inference
+// variables due to the presence of multiple applicable
+// marker trait impls
+
+#![feature(marker_trait_attr)]
+
+#[marker] // Remove this line and it works?!?
+trait Foo<T> {}
+impl Foo<u16> for u8 {}
+impl Foo<[u8; 1]> for u8 {}
+fn foo<T: Foo<U>, U>(_: T) -> U { unimplemented!() }
+
+fn main() {
+    let _: u16 = foo(0_u8);
+}
diff --git a/src/test/ui/match/match-vec-mismatch.rs b/src/test/ui/match/match-vec-mismatch.rs
deleted file mode 100644 (file)
index a0ef927..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#![feature(slice_patterns)]
-
-fn main() {
-    match "foo".to_string() {
-        ['f', 'o', ..] => {}
-        //~^ ERROR expected an array or slice, found `std::string::String`
-        _ => { }
-    };
-
-    // Note that this one works with default binding modes.
-    match &[0, 1, 2] {
-        [..] => {}
-    };
-
-    match &[0, 1, 2] {
-        &[..] => {} // ok
-    };
-
-    match [0, 1, 2] {
-        [0] => {}, //~ ERROR pattern requires
-
-        [0, 1, x @ ..] => {
-            let a: [_; 1] = x;
-        }
-        [0, 1, 2, 3, x @ ..] => {} //~ ERROR pattern requires
-    };
-
-    match does_not_exist { //~ ERROR cannot find value `does_not_exist` in this scope
-        [] => {}
-    };
-}
-
-fn another_fn_to_avoid_suppression() {
-    match Default::default()
-    {
-        [] => {}  //~ ERROR type annotations needed
-    };
-}
diff --git a/src/test/ui/match/match-vec-mismatch.stderr b/src/test/ui/match/match-vec-mismatch.stderr
deleted file mode 100644 (file)
index a3523bb..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-error[E0425]: cannot find value `does_not_exist` in this scope
-  --> $DIR/match-vec-mismatch.rs:28:11
-   |
-LL |     match does_not_exist {
-   |           ^^^^^^^^^^^^^^ not found in this scope
-
-error[E0529]: expected an array or slice, found `std::string::String`
-  --> $DIR/match-vec-mismatch.rs:5:9
-   |
-LL |         ['f', 'o', ..] => {}
-   |         ^^^^^^^^^^^^^^ pattern cannot match with input type `std::string::String`
-
-error[E0527]: pattern requires 1 element but array has 3
-  --> $DIR/match-vec-mismatch.rs:20:9
-   |
-LL |         [0] => {},
-   |         ^^^ expected 3 elements
-
-error[E0528]: pattern requires at least 4 elements but array has 3
-  --> $DIR/match-vec-mismatch.rs:25:9
-   |
-LL |         [0, 1, 2, 3, x @ ..] => {}
-   |         ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 3 elements
-
-error[E0282]: type annotations needed
-  --> $DIR/match-vec-mismatch.rs:36:9
-   |
-LL |         [] => {}
-   |         ^^ cannot infer type
-   |
-   = note: type must be known at this point
-
-error: aborting due to 5 previous errors
-
-Some errors have detailed explanations: E0282, E0425, E0527, E0528, E0529.
-For more information about an error, try `rustc --explain E0282`.
index 4ca60ddfec27c7c941c3eaa066f7be226cf3e85d..343f00ff291816ae46ca253a1a4237a7439458fe 100644 (file)
@@ -1,7 +1,5 @@
 // Ensure that we cannot move out of a reference to a fixed-size array
 
-#![feature(slice_patterns)]
-
 struct D { _x: u8 }
 
 impl Drop for D { fn drop(&mut self) { } }
index ae3d2f5f2826ac6fed5642bca720cdeb5dbf1c59..fd682e56ae1de444885fa48015d38a7331ed6dfb 100644 (file)
@@ -1,5 +1,5 @@
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
-  --> $DIR/move-out-of-array-ref.rs:10:24
+  --> $DIR/move-out-of-array-ref.rs:8:24
    |
 LL |     let [_, e, _, _] = *a;
    |             -          ^^
@@ -10,7 +10,7 @@ LL |     let [_, e, _, _] = *a;
    |             move occurs because `e` has type `D`, which does not implement the `Copy` trait
 
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
-  --> $DIR/move-out-of-array-ref.rs:15:27
+  --> $DIR/move-out-of-array-ref.rs:13:27
    |
 LL |     let [_, s @ .. , _] = *a;
    |             ------        ^^
@@ -21,7 +21,7 @@ LL |     let [_, s @ .. , _] = *a;
    |             move occurs because `s` has type `[D; 2]`, which does not implement the `Copy` trait
 
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
-  --> $DIR/move-out-of-array-ref.rs:20:24
+  --> $DIR/move-out-of-array-ref.rs:18:24
    |
 LL |     let [_, e, _, _] = *a;
    |             -          ^^
@@ -32,7 +32,7 @@ LL |     let [_, e, _, _] = *a;
    |             move occurs because `e` has type `D`, which does not implement the `Copy` trait
 
 error[E0508]: cannot move out of type `[D; 4]`, a non-copy array
-  --> $DIR/move-out-of-array-ref.rs:25:27
+  --> $DIR/move-out-of-array-ref.rs:23:27
    |
 LL |     let [_, s @ .. , _] = *a;
    |             ------        ^^
index 837e90d6ceb9b687994a9006a1aa2bc53723c33b..77288f1badac5e572484c0b817e360f6c953d9c3 100644 (file)
@@ -3,8 +3,12 @@ error[E0277]: the trait bound `(): T` is not satisfied
    |
 LL | fn should_ret_unit() -> impl T {
    |                         ^^^^^^ the trait `T` is not implemented for `()`
+LL |
+LL |     panic!()
+   |     -------- this returned value is of type `()`
    |
    = note: the return type of a function must have a statically known size
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: aborting due to previous error
 
index d7c191bb5a28d38b1d8159b3c53139239e75e446..8b0be2e7a66b4b78513d025b5beaa62040e88471 100644 (file)
@@ -1,5 +1,5 @@
 #![feature(or_patterns)]
-#![feature(slice_patterns)]
+
 #![allow(incomplete_features)]
 #![deny(unreachable_patterns)]
 
index ce0fe6fc2a3751e05559b1d7b167e1f39c1cbcfd..f0dc3447f31548b58856bd1eef5f295905d6a72d 100644 (file)
@@ -1,5 +1,5 @@
 #![feature(or_patterns)]
-#![feature(slice_patterns)]
+
 #![allow(incomplete_features)]
 #![deny(unreachable_patterns)]
 
index 860c7a1bde5fbb6740b68a82b061d90d017edc6f..81bc1176f572e34d847bd9bd64b059e48331db64 100644 (file)
@@ -1,5 +1,5 @@
 #![feature(or_patterns)]
-#![feature(slice_patterns)]
+
 #![allow(incomplete_features)]
 #![deny(unreachable_patterns)]
 
index fa25161ab50b22ef2d62264fcbccb93c747e53af..ae981ac4cbee3d578edd41def5c0a0b0e620fb36 100644 (file)
@@ -13,7 +13,16 @@ error[E0603]: static `x` is private
   --> $DIR/pub-item-macro.rs:17:23
    |
 LL |     let y: u32 = foo::x;
-   |                       ^
+   |                       ^ this static is private
+   |
+note: the static `x` is defined here
+  --> $DIR/pub-item-macro.rs:4:5
+   |
+LL |     static x: u32 = 0;
+   |     ^^^^^^^^^^^^^^^^^^
+...
+LL |     pub_x!();
+   |     --------- in this macro invocation
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/parser/match-vec-invalid.rs b/src/test/ui/parser/match-vec-invalid.rs
deleted file mode 100644 (file)
index 00f4374..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-fn main() {
-    let a: &[u8] = &[];
-    match a {
-        [1, tail @ .., tail @ ..] => {},
-        //~^ ERROR identifier `tail` is bound more than once in the same pattern
-        //~| ERROR subslice patterns are unstable
-        //~| ERROR subslice patterns are unstable
-        //~| ERROR `..` can only be used once per slice pattern
-        _ => ()
-    }
-}
-
-const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
diff --git a/src/test/ui/parser/match-vec-invalid.stderr b/src/test/ui/parser/match-vec-invalid.stderr
deleted file mode 100644 (file)
index 58343e8..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-error[E0416]: identifier `tail` is bound more than once in the same pattern
-  --> $DIR/match-vec-invalid.rs:4:24
-   |
-LL |         [1, tail @ .., tail @ ..] => {},
-   |                        ^^^^ used in a pattern more than once
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/match-vec-invalid.rs:4:13
-   |
-LL |         [1, tail @ .., tail @ ..] => {},
-   |             ^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error[E0658]: subslice patterns are unstable
-  --> $DIR/match-vec-invalid.rs:4:24
-   |
-LL |         [1, tail @ .., tail @ ..] => {},
-   |                        ^^^^^^^^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
-error: `..` can only be used once per slice pattern
-  --> $DIR/match-vec-invalid.rs:4:31
-   |
-LL |         [1, tail @ .., tail @ ..] => {},
-   |                    --         ^^ can only be used once per slice pattern
-   |                    |
-   |                    previously used here
-
-error[E0308]: mismatched types
-  --> $DIR/match-vec-invalid.rs:13:30
-   |
-LL | const RECOVERY_WITNESS: () = 0;
-   |                              ^ expected `()`, found integer
-
-error: aborting due to 5 previous errors
-
-Some errors have detailed explanations: E0308, E0416, E0658.
-For more information about an error, try `rustc --explain E0308`.
index f27caa5d78c8eaf42be834c1f8963dbadea97f53..7becffa9fe2f7afd50fa2895b74b5bb367c2ac68 100644 (file)
@@ -4,7 +4,6 @@ fn main() {
 
     let Test(&desc[..]) = x;
     //~^ ERROR: expected one of `)`, `,`, `@`, or `|`, found `[`
-    //~^^ ERROR subslice patterns are unstable
 }
 
 const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
index fe9603cb57f1f094905a57f57ec4179dece68ffb..035d0dbfe06d67f459b27bbc5d969a718a93e14d 100644 (file)
@@ -7,22 +7,12 @@ LL |     let Test(&desc[..]) = x;
    |                   expected one of `)`, `,`, `@`, or `|`
    |                   help: missing `,`
 
-error[E0658]: subslice patterns are unstable
-  --> $DIR/pat-lt-bracket-6.rs:5:20
-   |
-LL |     let Test(&desc[..]) = x;
-   |                    ^^
-   |
-   = note: for more information, see https://github.com/rust-lang/rust/issues/62254
-   = help: add `#![feature(slice_patterns)]` to the crate attributes to enable
-
 error[E0308]: mismatched types
-  --> $DIR/pat-lt-bracket-6.rs:10:30
+  --> $DIR/pat-lt-bracket-6.rs:9:30
    |
 LL | const RECOVERY_WITNESS: () = 0;
    |                              ^ expected `()`, found integer
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0308, E0658.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0308`.
index 1d9f341c5146ae1e1cf3ca4c94ed4bb6c5ac8b6b..2cd375da9a56fd5bba460a082a2fec86a8274736 100644 (file)
@@ -1,7 +1,6 @@
 // Test that moving on both sides of an `@` pattern is not allowed.
 
 #![feature(bindings_after_at)]
-#![feature(slice_patterns)]
 
 fn main() {
     struct U; // Not copy!
index f3f8fd655ce0cad831414c69a7f4b5276162c0fb..12ebcb72af11cba13fb6ff6885e69862355ffdc6 100644 (file)
@@ -1,53 +1,53 @@
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:12:9
+  --> $DIR/borrowck-move-and-move.rs:11:9
    |
 LL |     let a @ b = U;
    |         ^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:16:9
+  --> $DIR/borrowck-move-and-move.rs:15:9
    |
 LL |     let a @ (b, c) = (U, U);
    |         ^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:20:9
+  --> $DIR/borrowck-move-and-move.rs:19:9
    |
 LL |     let a @ (b, c) = (u(), u());
    |         ^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:25:9
+  --> $DIR/borrowck-move-and-move.rs:24:9
    |
 LL |         a @ Ok(b) | a @ Err(b) => {}
    |         ^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:25:21
+  --> $DIR/borrowck-move-and-move.rs:24:21
    |
 LL |         a @ Ok(b) | a @ Err(b) => {}
    |                     ^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:37:9
+  --> $DIR/borrowck-move-and-move.rs:36:9
    |
 LL |         xs @ [a, .., b] => {}
    |         ^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:43:9
+  --> $DIR/borrowck-move-and-move.rs:42:9
    |
 LL |         xs @ [_, ys @ .., _] => {}
    |         ^^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-move-and-move.rs:32:12
+  --> $DIR/borrowck-move-and-move.rs:31:12
    |
 LL |     fn fun(a @ b: U) {}
    |            ^^^^^ binds an already bound by-move value by moving it
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:12:13
+  --> $DIR/borrowck-move-and-move.rs:11:13
    |
 LL |     let a @ b = U;
    |         ----^   - move occurs because value has type `main::U`, which does not implement the `Copy` trait
@@ -56,7 +56,7 @@ LL |     let a @ b = U;
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:16:17
+  --> $DIR/borrowck-move-and-move.rs:15:17
    |
 LL |     let a @ (b, c) = (U, U);
    |         --------^-   ------ move occurs because value has type `(main::U, main::U)`, which does not implement the `Copy` trait
@@ -65,7 +65,7 @@ LL |     let a @ (b, c) = (U, U);
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:20:17
+  --> $DIR/borrowck-move-and-move.rs:19:17
    |
 LL |     let a @ (b, c) = (u(), u());
    |         --------^-   ---------- move occurs because value has type `(main::U, main::U)`, which does not implement the `Copy` trait
@@ -74,7 +74,7 @@ LL |     let a @ (b, c) = (u(), u());
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:25:16
+  --> $DIR/borrowck-move-and-move.rs:24:16
    |
 LL |     match Ok(U) {
    |           ----- move occurs because value has type `std::result::Result<main::U, main::U>`, which does not implement the `Copy` trait
@@ -85,7 +85,7 @@ LL |         a @ Ok(b) | a @ Err(b) => {}
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:25:29
+  --> $DIR/borrowck-move-and-move.rs:24:29
    |
 LL |     match Ok(U) {
    |           ----- move occurs because value has type `std::result::Result<main::U, main::U>`, which does not implement the `Copy` trait
@@ -96,7 +96,7 @@ LL |         a @ Ok(b) | a @ Err(b) => {}
    |                     value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:37:22
+  --> $DIR/borrowck-move-and-move.rs:36:22
    |
 LL |     match [u(), u(), u(), u()] {
    |           -------------------- move occurs because value has type `[main::U; 4]`, which does not implement the `Copy` trait
@@ -107,7 +107,7 @@ LL |         xs @ [a, .., b] => {}
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:43:18
+  --> $DIR/borrowck-move-and-move.rs:42:18
    |
 LL |     match [u(), u(), u(), u()] {
    |           -------------------- move occurs because value has type `[main::U; 4]`, which does not implement the `Copy` trait
@@ -118,7 +118,7 @@ LL |         xs @ [_, ys @ .., _] => {}
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:32:16
+  --> $DIR/borrowck-move-and-move.rs:31:16
    |
 LL |     fn fun(a @ b: U) {}
    |            ----^
index afac8d990b4744f8178d2de4a1a2200d02b88bb7..092bd1133dd624692aa7e966222a3eacacc1a81a 100644 (file)
@@ -4,7 +4,6 @@
 
 #![feature(bindings_after_at)]
 #![feature(box_patterns)]
-#![feature(slice_patterns)]
 
 #[derive(Copy, Clone)]
 struct C;
index fce31409e16c434cc508e5b841a0d9e53d973cce..3b2f598dc0157f89b39e75e46001ab846b9b3112 100644 (file)
@@ -2,7 +2,6 @@
 
 #![feature(bindings_after_at)]
 #![feature(box_patterns)]
-#![feature(slice_patterns)]
 
 #[derive(Copy, Clone)]
 struct C;
index 5772fadd1e7418687116fc16f40a23352822630c..e96c15b0fa7ddd604ce2a95994c78f97e30437a8 100644 (file)
@@ -1,23 +1,23 @@
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-at-and-box.rs:17:9
+  --> $DIR/borrowck-pat-at-and-box.rs:16:9
    |
 LL |     let a @ box &b = Box::new(&C);
    |         ^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-at-and-box.rs:21:9
+  --> $DIR/borrowck-pat-at-and-box.rs:20:9
    |
 LL |     let a @ box b = Box::new(C);
    |         ^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-at-and-box.rs:33:25
+  --> $DIR/borrowck-pat-at-and-box.rs:32:25
    |
 LL |     match Box::new(C) { a @ box b => {} }
    |                         ^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0009]: cannot bind by-move and by-ref in the same pattern
-  --> $DIR/borrowck-pat-at-and-box.rs:37:21
+  --> $DIR/borrowck-pat-at-and-box.rs:36:21
    |
 LL |     let ref a @ box b = Box::new(NC);
    |         ------------^
@@ -26,7 +26,7 @@ LL |     let ref a @ box b = Box::new(NC);
    |         by-ref pattern here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:39:9
+  --> $DIR/borrowck-pat-at-and-box.rs:38:9
    |
 LL |     let ref a @ box ref mut b = Box::new(nc());
    |         -----^^^^^^^---------
@@ -35,7 +35,7 @@ LL |     let ref a @ box ref mut b = Box::new(nc());
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:41:9
+  --> $DIR/borrowck-pat-at-and-box.rs:40:9
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         -----^^^^^^^---------
@@ -44,7 +44,7 @@ LL |     let ref a @ box ref mut b = Box::new(NC);
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:43:9
+  --> $DIR/borrowck-pat-at-and-box.rs:42:9
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         -----^^^^^^^---------
@@ -53,7 +53,7 @@ LL |     let ref a @ box ref mut b = Box::new(NC);
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:46:9
+  --> $DIR/borrowck-pat-at-and-box.rs:45:9
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         -----^^^^^^^---------
@@ -62,7 +62,7 @@ LL |     let ref a @ box ref mut b = Box::new(NC);
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:52:9
+  --> $DIR/borrowck-pat-at-and-box.rs:51:9
    |
 LL |     let ref mut a @ box ref b = Box::new(NC);
    |         ---------^^^^^^^-----
@@ -71,7 +71,7 @@ LL |     let ref mut a @ box ref b = Box::new(NC);
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:66:9
+  --> $DIR/borrowck-pat-at-and-box.rs:65:9
    |
 LL |         ref mut a @ box ref b => {
    |         ---------^^^^^^^-----
@@ -80,7 +80,7 @@ LL |         ref mut a @ box ref b => {
    |         mutable borrow occurs here
 
 error[E0009]: cannot bind by-move and by-ref in the same pattern
-  --> $DIR/borrowck-pat-at-and-box.rs:75:38
+  --> $DIR/borrowck-pat-at-and-box.rs:74:38
    |
 LL |         box [Ok(a), ref xs @ .., Err(b)] => {}
    |                     -----------      ^ by-move pattern here
@@ -88,7 +88,7 @@ LL |         box [Ok(a), ref xs @ .., Err(b)] => {}
    |                     by-ref pattern here
 
 error[E0009]: cannot bind by-move and by-ref in the same pattern
-  --> $DIR/borrowck-pat-at-and-box.rs:81:46
+  --> $DIR/borrowck-pat-at-and-box.rs:80:46
    |
 LL |         [Ok(box ref a), ref xs @ .., Err(box b), Err(box ref mut c)] => {}
    |                 -----   -----------          ^           --------- by-ref pattern here
@@ -98,19 +98,19 @@ LL |         [Ok(box ref a), ref xs @ .., Err(box b), Err(box ref mut c)] => {}
    |                 by-ref pattern here
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-at-and-box.rs:25:11
+  --> $DIR/borrowck-pat-at-and-box.rs:24:11
    |
 LL |     fn f1(a @ box &b: Box<&C>) {}
    |           ^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-at-and-box.rs:29:11
+  --> $DIR/borrowck-pat-at-and-box.rs:28:11
    |
 LL |     fn f2(a @ box b: Box<C>) {}
    |           ^^^^^^^^^ binds an already bound by-move value by moving it
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:58:11
+  --> $DIR/borrowck-pat-at-and-box.rs:57:11
    |
 LL |     fn f5(ref mut a @ box ref b: Box<NC>) {
    |           ---------^^^^^^^-----
@@ -119,7 +119,7 @@ LL |     fn f5(ref mut a @ box ref b: Box<NC>) {
    |           mutable borrow occurs here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:17:18
+  --> $DIR/borrowck-pat-at-and-box.rs:16:18
    |
 LL |     let a @ box &b = Box::new(&C);
    |         ---------^   ------------ move occurs because value has type `std::boxed::Box<&C>`, which does not implement the `Copy` trait
@@ -128,7 +128,7 @@ LL |     let a @ box &b = Box::new(&C);
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:21:17
+  --> $DIR/borrowck-pat-at-and-box.rs:20:17
    |
 LL |     let a @ box b = Box::new(C);
    |         --------^   ----------- move occurs because value has type `std::boxed::Box<C>`, which does not implement the `Copy` trait
@@ -137,7 +137,7 @@ LL |     let a @ box b = Box::new(C);
    |         value moved here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:33:33
+  --> $DIR/borrowck-pat-at-and-box.rs:32:33
    |
 LL |     match Box::new(C) { a @ box b => {} }
    |           -----------   --------^
@@ -147,7 +147,7 @@ LL |     match Box::new(C) { a @ box b => {} }
    |           move occurs because value has type `std::boxed::Box<C>`, which does not implement the `Copy` trait
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-at-and-box.rs:46:21
+  --> $DIR/borrowck-pat-at-and-box.rs:45:21
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
    |         ------------^^^^^^^^^
@@ -159,7 +159,7 @@ LL |     drop(a);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:52:25
+  --> $DIR/borrowck-pat-at-and-box.rs:51:25
    |
 LL |     let ref mut a @ box ref b = Box::new(NC);
    |         ----------------^^^^^
@@ -171,7 +171,7 @@ LL |     *a = Box::new(NC);
    |     -- mutable borrow later used here
 
 error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:66:25
+  --> $DIR/borrowck-pat-at-and-box.rs:65:25
    |
 LL |         ref mut a @ box ref b => {
    |         ----------------^^^^^
@@ -183,7 +183,7 @@ LL |             *a = Box::new(NC);
    |             -- mutable borrow later used here
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:25:20
+  --> $DIR/borrowck-pat-at-and-box.rs:24:20
    |
 LL |     fn f1(a @ box &b: Box<&C>) {}
    |           ---------^
@@ -193,7 +193,7 @@ LL |     fn f1(a @ box &b: Box<&C>) {}
    |           move occurs because value has type `std::boxed::Box<&C>`, which does not implement the `Copy` trait
 
 error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-at-and-box.rs:29:19
+  --> $DIR/borrowck-pat-at-and-box.rs:28:19
    |
 LL |     fn f2(a @ box b: Box<C>) {}
    |           --------^
@@ -203,7 +203,7 @@ LL |     fn f2(a @ box b: Box<C>) {}
    |           move occurs because value has type `std::boxed::Box<C>`, which does not implement the `Copy` trait
 
 error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-at-and-box.rs:58:27
+  --> $DIR/borrowck-pat-at-and-box.rs:57:27
    |
 LL |     fn f5(ref mut a @ box ref b: Box<NC>) {
    |           ----------------^^^^^
index be19e5f2a85cabad53abed7a6b2af4b0dfe4c05d..c4ce50c8b9a16313d92168477130159170043b9f 100644 (file)
@@ -2,7 +2,6 @@
 
 // Test `Copy` bindings in the rhs of `@` patterns.
 
-#![feature(slice_patterns)]
 #![feature(bindings_after_at)]
 
 #[derive(Copy, Clone)]
index edf9fb31458909b6d228d56a79980aa9a439fb7f..fb243016a1185f6ae9112823240a42e77c73c124 100644 (file)
@@ -4,7 +4,6 @@
 // of an `@` pattern according to NLL borrowck.
 
 #![feature(bindings_after_at)]
-#![feature(slice_patterns)]
 
 fn main() {
     struct U; // Not copy!
index 559925c282f9ae2ac3b98e4d243aa40544f44152..e8510dfa649990a3aef693dc92f9ff52f78bdc07 100644 (file)
@@ -1,5 +1,4 @@
 #![feature(bindings_after_at)]
-#![feature(slice_patterns)]
 
 enum Option<T> {
     None,
index b5c26a1fa039945c21545307010619bfa0cbf28c..0d7b703f1816b4aa31bc511e3c26bc0f3075af9c 100644 (file)
@@ -1,5 +1,5 @@
 error: cannot borrow `z` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:11:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:10:9
    |
 LL |         ref mut z @ &mut Some(ref a) => {
    |         ---------^^^^^^^^^^^^^-----^
@@ -8,7 +8,7 @@ LL |         ref mut z @ &mut Some(ref a) => {
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:32:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:31:9
    |
 LL |     let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
    |         ---------^^^^-----------------^
@@ -18,7 +18,7 @@ LL |     let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
    |         first mutable borrow occurs here
 
 error: cannot borrow `b` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:32:22
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:31:22
    |
 LL |     let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
    |                      -----^^^---------
@@ -27,7 +27,7 @@ LL |     let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
    |                      immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:36:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:35:9
    |
 LL |     let ref a @ ref mut b = U;
    |         -----^^^---------
@@ -36,7 +36,7 @@ LL |     let ref a @ ref mut b = U;
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:38:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:37:9
    |
 LL |     let ref mut a @ ref b = U;
    |         ---------^^^-----
@@ -45,7 +45,7 @@ LL |     let ref mut a @ ref b = U;
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:40:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:39:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -55,7 +55,7 @@ LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:42:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:41:9
    |
 LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         ---------^^^^-----^^-----^
@@ -65,7 +65,7 @@ LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:45:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:44:9
    |
 LL |     let ref mut a @ ref b = u();
    |         ---------^^^-----
@@ -74,7 +74,7 @@ LL |     let ref mut a @ ref b = u();
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:50:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:49:9
    |
 LL |     let ref a @ ref mut b = u();
    |         -----^^^---------
@@ -83,7 +83,7 @@ LL |     let ref a @ ref mut b = u();
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:56:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:55:9
    |
 LL |     let ref mut a @ ref b = U;
    |         ---------^^^-----
@@ -92,7 +92,7 @@ LL |     let ref mut a @ ref b = U;
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:60:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:59:9
    |
 LL |     let ref a @ ref mut b = U;
    |         -----^^^---------
@@ -101,7 +101,7 @@ LL |     let ref a @ ref mut b = U;
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:66:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:65:9
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
    |         ---------^^^^^^-----^
@@ -110,7 +110,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:66:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:65:33
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
    |                                 ---------^^^^^^^-----^
@@ -119,7 +119,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
    |                                 mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:75:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:74:9
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |         -----^^^^^^---------^
@@ -128,7 +128,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:75:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:74:33
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |                                 -----^^^^^^^---------^
@@ -137,7 +137,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |                                 immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:86:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:85:9
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
    |         -----^^^^^^---------^
@@ -146,7 +146,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false }
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:86:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:85:33
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
    |                                 -----^^^^^^^---------^
@@ -155,7 +155,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false }
    |                                 immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:93:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:92:9
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
    |         ---------^^^^^^-----^
@@ -164,7 +164,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:93:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:92:33
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
    |                                 ---------^^^^^^^-----^
@@ -173,7 +173,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa
    |                                 mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:100:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:99:9
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |         -----^^^^^^---------^
@@ -182,7 +182,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:100:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:99:33
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |                                 -----^^^^^^^---------^
@@ -191,7 +191,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    |                                 immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:108:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:107:9
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |         ---------^^^^^^-----^
@@ -200,7 +200,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:108:33
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:107:33
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |                                 ---------^^^^^^^-----^
@@ -209,7 +209,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    |                                 mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:116:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:115:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -219,7 +219,7 @@ LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:120:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -229,7 +229,7 @@ LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:128:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         -----^^^^---------^^---------^
@@ -239,7 +239,7 @@ LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:133:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:132:9
    |
 LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         ---------^^^^-----^^-----^
@@ -249,7 +249,7 @@ LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:25:11
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:24:11
    |
 LL |     fn f1(ref a @ ref mut b: U) {}
    |           -----^^^---------
@@ -258,7 +258,7 @@ LL |     fn f1(ref a @ ref mut b: U) {}
    |           immutable borrow occurs here
 
 error: cannot borrow `a` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:27:11
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:26:11
    |
 LL |     fn f2(ref mut a @ ref b: U) {}
    |           ---------^^^-----
@@ -267,7 +267,7 @@ LL |     fn f2(ref mut a @ ref b: U) {}
    |           mutable borrow occurs here
 
 error: cannot borrow `a` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:29:11
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:11
    |
 LL |     fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {}
    |           -----^^^^^^^^^^^----------------^^^^^^^^
@@ -276,7 +276,7 @@ LL |     fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {}
    |           immutable borrow occurs here
 
 error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:11:31
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:10:31
    |
 LL |         ref mut z @ &mut Some(ref a) => {
    |         ----------------------^^^^^-
@@ -288,7 +288,7 @@ LL |             **z = None;
    |             ---------- mutable borrow later used here
 
 error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:45:21
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:44:21
    |
 LL |     let ref mut a @ ref b = u();
    |         ------------^^^^^
@@ -300,7 +300,7 @@ LL |     *a = u();
    |     -------- mutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:50:17
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:49:17
    |
 LL |     let ref a @ ref mut b = u();
    |         --------^^^^^^^^^
@@ -312,7 +312,7 @@ LL |     drop(a);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:75:20
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:74:20
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |         -----------^^^^^^^^^-
@@ -324,7 +324,7 @@ LL |             drop(a);
    |                  - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:75:45
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:74:45
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
    |                                 ------------^^^^^^^^^-
@@ -336,7 +336,7 @@ LL |             drop(a);
    |                  - immutable borrow later used here
 
 error[E0594]: cannot assign to `*b`, as it is immutable for the pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:86:61
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:85:61
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
    |                                                             ^^^^^^ cannot assign
@@ -344,7 +344,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false }
    = note: variables bound in patterns are immutable until the end of the pattern guard
 
 error[E0594]: cannot assign to `*a`, as it is immutable for the pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:93:61
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:92:61
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
    |                                                             ^^^^^^^^^^^ cannot assign
@@ -352,7 +352,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa
    = note: variables bound in patterns are immutable until the end of the pattern guard
 
 error[E0507]: cannot move out of `b` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:100:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:99:66
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |                                                                  ^ move occurs because `b` has type `&mut main::U`, which does not implement the `Copy` trait
@@ -360,7 +360,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
 error[E0507]: cannot move out of `b` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:100:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:99:66
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |                                                                  ^ move occurs because `b` has type `&mut main::U`, which does not implement the `Copy` trait
@@ -368,7 +368,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
 error[E0507]: cannot move out of `a` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:108:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:107:66
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |                                                                  ^ move occurs because `a` has type `&mut std::result::Result<main::U, main::U>`, which does not implement the `Copy` trait
@@ -376,7 +376,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
 error[E0507]: cannot move out of `a` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:108:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:107:66
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |                                                                  ^ move occurs because `a` has type `&mut std::result::Result<main::U, main::U>`, which does not implement the `Copy` trait
@@ -384,7 +384,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:18
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:120:18
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         ---------^^^^^^^^^------------
@@ -396,7 +396,7 @@ LL |     drop(a);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:29
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:120:29
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         --------------------^^^^^^^^^-
@@ -408,7 +408,7 @@ LL |     drop(a);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:128:18
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:18
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         ---------^^^^^^^^^------------
@@ -420,7 +420,7 @@ LL |     drop(a);
    |          - immutable borrow later used here
 
 error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:128:29
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:29
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         --------------------^^^^^^^^^-
index 6b8b7545e687db53fca858ba389a269c188b7d29..f425b35630d17565ace97e2472251e6f12912aad 100644 (file)
@@ -1,7 +1,6 @@
 // Test that `ref mut x @ ref mut y` and varieties of that are not allowed.
 
 #![feature(bindings_after_at)]
-#![feature(slice_patterns)]
 
 fn main() {
     struct U;
index 1b5e6c7411703f8c5b60bcee2f3b66805396c50d..d07ad140cc23a72366d6e0eed73f25b842416bbe 100644 (file)
@@ -1,5 +1,5 @@
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:25:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:24:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -8,7 +8,7 @@ LL |     let ref mut a @ ref mut b = U;
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:29:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:28:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -17,7 +17,7 @@ LL |     let ref mut a @ ref mut b = U;
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:32:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:31:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -26,7 +26,7 @@ LL |     let ref mut a @ ref mut b = U;
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:35:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:34:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -35,7 +35,7 @@ LL |     let ref mut a @ ref mut b = U;
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:39:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:38:9
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ---------^^^---------
@@ -44,7 +44,7 @@ LL |     let ref mut a @ ref mut b = U;
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:43:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:42:9
    |
 LL |       let ref mut a @ (
    |           ^--------
@@ -66,7 +66,7 @@ LL | |     ) = (U, [U, U, U]);
    | |_____^
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:53:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:52:9
    |
 LL |       let ref mut a @ (
    |           ^--------
@@ -88,31 +88,31 @@ LL | |         ) = (u(), [u(), u(), u()]);
    | |_________^
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:63:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:62:9
    |
 LL |     let a @ (ref mut b, ref mut c) = (U, U);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:67:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:66:9
    |
 LL |     let a @ (b, [c, d]) = &mut val; // Same as ^--
    |         ^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:71:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:70:9
    |
 LL |     let a @ &mut ref mut b = &mut U;
    |         ^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error[E0007]: cannot bind by-move with sub-bindings
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:74:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:73:9
    |
 LL |     let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:79:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:78:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------^^^^^^---------^
@@ -121,7 +121,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:79:37
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:78:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ---------^^^^^^^---------^
@@ -130,7 +130,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:85:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:84:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------^^^^^^---------^
@@ -139,7 +139,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:85:37
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:84:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ---------^^^^^^^---------^
@@ -148,7 +148,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:92:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:91:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------^^^^^^---------^
@@ -157,7 +157,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:92:37
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:91:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ---------^^^^^^^---------^
@@ -166,7 +166,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:104:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:103:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------^^^^^^---------^
@@ -175,7 +175,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:104:37
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:103:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ---------^^^^^^^---------^
@@ -184,7 +184,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:11:11
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:10:11
    |
 LL |     fn f1(ref mut a @ ref mut b: U) {}
    |           ---------^^^---------
@@ -193,7 +193,7 @@ LL |     fn f1(ref mut a @ ref mut b: U) {}
    |           first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:13:11
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:12:11
    |
 LL |     fn f2(ref mut a @ ref mut b: U) {}
    |           ---------^^^---------
@@ -202,7 +202,7 @@ LL |     fn f2(ref mut a @ ref mut b: U) {}
    |           first mutable borrow occurs here
 
 error: cannot borrow `a` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:16:9
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:15:9
    |
 LL |           ref mut a @ [
    |           ^--------
@@ -220,7 +220,7 @@ LL | |         ] : [[U; 4]; 5]
    | |_________^
 
 error[E0499]: cannot borrow `_` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:25:21
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:24:21
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ------------^^^^^^^^^
@@ -232,7 +232,7 @@ LL |     drop(a);
    |          - first borrow later used here
 
 error[E0499]: cannot borrow `_` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:35:21
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:34:21
    |
 LL |     let ref mut a @ ref mut b = U;
    |         ------------^^^^^^^^^
@@ -244,7 +244,7 @@ LL |     *a = U;
    |     ------ first borrow later used here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:63:25
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:62:25
    |
 LL |     let a @ (ref mut b, ref mut c) = (U, U);
    |         ----------------^^^^^^^^^-   ------ move occurs because value has type `(main::U, main::U)`, which does not implement the `Copy` trait
@@ -253,7 +253,7 @@ LL |     let a @ (ref mut b, ref mut c) = (U, U);
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:67:21
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:66:21
    |
 LL |     let a @ (b, [c, d]) = &mut val; // Same as ^--
    |         ------------^--   -------- move occurs because value has type `&mut (main::U, [main::U; 2])`, which does not implement the `Copy` trait
@@ -262,7 +262,7 @@ LL |     let a @ (b, [c, d]) = &mut val; // Same as ^--
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:71:18
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:70:18
    |
 LL |     let a @ &mut ref mut b = &mut U;
    |         ---------^^^^^^^^^   ------ move occurs because value has type `&mut main::U`, which does not implement the `Copy` trait
@@ -271,7 +271,7 @@ LL |     let a @ &mut ref mut b = &mut U;
    |         value moved here
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:74:30
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:73:30
    |
 LL |     let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
    |         ---------------------^^^^^^^^^-   ----------- move occurs because value has type `&mut (main::U, main::U)`, which does not implement the `Copy` trait
@@ -280,7 +280,7 @@ LL |     let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
    |         value moved here
 
 error[E0499]: cannot borrow `_` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:92:24
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:91:24
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------------^^^^^^^^^-
@@ -292,7 +292,7 @@ LL |             *a = Err(U);
    |             ----------- first borrow later used here
 
 error[E0499]: cannot borrow `_` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:92:53
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:91:53
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ----------------^^^^^^^^^-
@@ -304,7 +304,7 @@ LL |             *a = Err(U);
    |             ----------- first borrow later used here
 
 error[E0499]: cannot borrow `_` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:104:24
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:103:24
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ---------------^^^^^^^^^-
@@ -316,7 +316,7 @@ LL |             drop(a);
    |                  - first borrow later used here
 
 error[E0499]: cannot borrow `_` as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:104:53
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:103:53
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ----------------^^^^^^^^^-
diff --git a/src/test/ui/pattern/issue-53820-slice-pattern-large-array.rs b/src/test/ui/pattern/issue-53820-slice-pattern-large-array.rs
deleted file mode 100644 (file)
index c910cde..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// check-pass
-
-// This used to cause a stack overflow in the compiler.
-
-#![feature(slice_patterns)]
-
-fn main() {
-    const LARGE_SIZE: usize = 1024 * 1024;
-    let [..] = [0u8; LARGE_SIZE];
-    match [0u8; LARGE_SIZE] {
-        [..] => {}
-    }
-}
diff --git a/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs b/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs
deleted file mode 100644 (file)
index 6c54c93..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// check-pass
-#![feature(slice_patterns)]
-#![deny(unreachable_patterns)]
-
-const C0: &'static [u8] = b"\x00";
-
-fn main() {
-    let x: &[u8] = &[0];
-    match x {
-        &[] => {}
-        &[1..=255] => {}
-        C0 => {}
-        &[_, _, ..] => {}
-    }
-}
diff --git a/src/test/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs b/src/test/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs
new file mode 100644 (file)
index 0000000..5b0482d
--- /dev/null
@@ -0,0 +1,11 @@
+// check-pass
+
+// This used to cause a stack overflow during exhaustiveness checking in the compiler.
+
+fn main() {
+    const LARGE_SIZE: usize = 1024 * 1024;
+    let [..] = [0u8; LARGE_SIZE];
+    match [0u8; LARGE_SIZE] {
+        [..] => {}
+    }
+}
diff --git a/src/test/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs b/src/test/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs
new file mode 100644 (file)
index 0000000..54dfa88
--- /dev/null
@@ -0,0 +1,15 @@
+// check-pass
+
+#![deny(unreachable_patterns)]
+
+const C0: &'static [u8] = b"\x00";
+
+fn main() {
+    let x: &[u8] = &[0];
+    match x {
+        &[] => {}
+        &[1..=255] => {}
+        C0 => {}
+        &[_, _, ..] => {}
+    }
+}
index 7541ea3e2e2632988ec80e5def457bcc9a1cb7e7..9b6c8bd5556be346f01a0a2662c503b1b0b0ac32 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(slice_patterns)]
 #![deny(unreachable_patterns)]
 
 fn main() {
index b28646b50cf01e15b4acf33b9c26eb21ec616d75..09484692fab0815b97e1768af4340ca9901eede6 100644 (file)
@@ -1,53 +1,53 @@
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:9:9
+  --> $DIR/match-byte-array-patterns.rs:8:9
    |
 LL |         &[0x41, 0x41, 0x41, 0x41] => {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/match-byte-array-patterns.rs:2:9
+  --> $DIR/match-byte-array-patterns.rs:1:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:15:9
+  --> $DIR/match-byte-array-patterns.rs:14:9
    |
 LL |         b"AAAA" => {},
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:21:9
+  --> $DIR/match-byte-array-patterns.rs:20:9
    |
 LL |         b"AAAA" => {},
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:27:9
+  --> $DIR/match-byte-array-patterns.rs:26:9
    |
 LL |         b"AAAA" => {},
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:35:9
+  --> $DIR/match-byte-array-patterns.rs:34:9
    |
 LL |         &[0x41, 0x41, 0x41, 0x41] => {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:41:9
+  --> $DIR/match-byte-array-patterns.rs:40:9
    |
 LL |         b"AAAA" => {},
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:47:9
+  --> $DIR/match-byte-array-patterns.rs:46:9
    |
 LL |         b"AAAA" => {},
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-byte-array-patterns.rs:53:9
+  --> $DIR/match-byte-array-patterns.rs:52:9
    |
 LL |         b"AAAA" => {},
    |         ^^^^^^^
index af7fd53a1f1e916dc505338cf469b4183ae8a094..92d74b8c229d6000c17bc132b00ee47f4dd82a40 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn check(list: &[Option<()>]) {
     match list {
     //~^ ERROR `&[_, Some(_), .., None, _]` not covered
index 72ae5d5fe3b33e172a1a499ee984a3d1ecc2c149..977a11280819052e33aa801138b4bce408d997ed 100644 (file)
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `&[_, Some(_), .., None, _]` not covered
-  --> $DIR/match-slice-patterns.rs:4:11
+  --> $DIR/match-slice-patterns.rs:2:11
    |
 LL |     match list {
    |           ^^^^ pattern `&[_, Some(_), .., None, _]` not covered
index 78810525bad0f76b4653d3ab4abbf5df382c9f85..3342389be6e4c750818d56f192c959ba60f5df41 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(slice_patterns)]
 #![deny(unreachable_patterns)]
 
 fn main() {
index 415c24ae77ef5271e91bdbd981699289b8e1d748..e9a751074c2e14a8f22327185a87368742cb3115 100644 (file)
@@ -1,23 +1,23 @@
 error: unreachable pattern
-  --> $DIR/match-vec-unreachable.rs:9:9
+  --> $DIR/match-vec-unreachable.rs:8:9
    |
 LL |         [(1, 2), (2, 3), b] => (),
    |         ^^^^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/match-vec-unreachable.rs:2:9
+  --> $DIR/match-vec-unreachable.rs:1:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-vec-unreachable.rs:19:9
+  --> $DIR/match-vec-unreachable.rs:18:9
    |
 LL |         [_, _, _, _, _] => { }
    |         ^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/match-vec-unreachable.rs:27:9
+  --> $DIR/match-vec-unreachable.rs:26:9
    |
 LL |         ['a', 'b', 'c'] => {}
    |         ^^^^^^^^^^^^^^^
index 9423a2891a62085166f6345b8a2f5cda28f12416..d198144790be1d8b6d6140f2a66dbd22bc696367 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 enum T { A(U), B }
 enum U { C, D }
 
index 67c818e19cbdabd19ab2657e8c179d9aa8524ac5..72b4b522198e08f68fd64ff3db11868b0ea58d96 100644 (file)
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `(Some(&[]), Err(_))` not covered
-  --> $DIR/non-exhaustive-match-nested.rs:7:11
+  --> $DIR/non-exhaustive-match-nested.rs:5:11
    |
 LL |     match (l1, l2) {
    |           ^^^^^^^^ pattern `(Some(&[]), Err(_))` not covered
@@ -7,7 +7,7 @@ LL |     match (l1, l2) {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `A(C)` not covered
-  --> $DIR/non-exhaustive-match-nested.rs:17:11
+  --> $DIR/non-exhaustive-match-nested.rs:15:11
    |
 LL | enum T { A(U), B }
    | ------------------
index bfca5352353a7c0c6ad724bc0bb3e8d438f5a391..9947989dc121121f9d6185b3469ae9a171c60851 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(slice_patterns)]
 #![allow(illegal_floating_point_literal_pattern)]
 
 enum T { A, B }
index 577867e4e712294025aaff2a88e562aa05f35538..a06ad5788515cfcabd0a71d106753548035b9f93 100644 (file)
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `A` not covered
-  --> $DIR/non-exhaustive-match.rs:8:11
+  --> $DIR/non-exhaustive-match.rs:7:11
    |
 LL | enum T { A, B }
    | ---------------
@@ -13,7 +13,7 @@ LL |     match x { T::B => { } }
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `false` not covered
-  --> $DIR/non-exhaustive-match.rs:9:11
+  --> $DIR/non-exhaustive-match.rs:8:11
    |
 LL |     match true {
    |           ^^^^ pattern `false` not covered
@@ -21,7 +21,7 @@ LL |     match true {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `Some(_)` not covered
-  --> $DIR/non-exhaustive-match.rs:12:11
+  --> $DIR/non-exhaustive-match.rs:11:11
    |
 LL |     match Some(10) {
    |           ^^^^^^^^ pattern `Some(_)` not covered
@@ -29,7 +29,7 @@ LL |     match Some(10) {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `(_, _, std::i32::MIN..=3i32)` and `(_, _, 5i32..=std::i32::MAX)` not covered
-  --> $DIR/non-exhaustive-match.rs:15:11
+  --> $DIR/non-exhaustive-match.rs:14:11
    |
 LL |     match (2, 3, 4) {
    |           ^^^^^^^^^ patterns `(_, _, std::i32::MIN..=3i32)` and `(_, _, 5i32..=std::i32::MAX)` not covered
@@ -37,7 +37,7 @@ LL |     match (2, 3, 4) {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `(A, A)` not covered
-  --> $DIR/non-exhaustive-match.rs:19:11
+  --> $DIR/non-exhaustive-match.rs:18:11
    |
 LL |     match (T::A, T::A) {
    |           ^^^^^^^^^^^^ pattern `(A, A)` not covered
@@ -45,7 +45,7 @@ LL |     match (T::A, T::A) {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `B` not covered
-  --> $DIR/non-exhaustive-match.rs:23:11
+  --> $DIR/non-exhaustive-match.rs:22:11
    |
 LL | enum T { A, B }
    | ---------------
@@ -59,7 +59,7 @@ LL |     match T::A {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `[]` not covered
-  --> $DIR/non-exhaustive-match.rs:34:11
+  --> $DIR/non-exhaustive-match.rs:33:11
    |
 LL |     match *vec {
    |           ^^^^ pattern `[]` not covered
@@ -67,7 +67,7 @@ LL |     match *vec {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `[_, _, _, _, ..]` not covered
-  --> $DIR/non-exhaustive-match.rs:47:11
+  --> $DIR/non-exhaustive-match.rs:46:11
    |
 LL |     match *vec {
    |           ^^^^ pattern `[_, _, _, _, ..]` not covered
index 4ca1cbcebccf51a94b249e9f5d6dc30535b11137..abb4ea8daf57b5539f0b920c2c0ba11602ab5c3e 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 struct Foo {
     first: bool,
     second: Option<[usize; 4]>
index a0b497dd4c0ba12da984e3e19d19eddccbbf011b..2a9fa07d22fe781e29e2f1fd0704586b301054f4 100644 (file)
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:9:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:7:11
    |
 LL | / struct Foo {
 LL | |     first: bool,
@@ -13,7 +13,7 @@ LL |       match (Foo { first: true, second: None }) {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `Red` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:25:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:23:11
    |
 LL | / enum Color {
 LL | |     Red,
@@ -29,7 +29,7 @@ LL |       match Color::Red {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `East`, `South` and `West` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:37:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:35:11
    |
 LL | / enum Direction {
 LL | |     North, East, South, West
@@ -46,7 +46,7 @@ LL |       match Direction::North {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `Second`, `Third`, `Fourth` and 8 more not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:48:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:46:11
    |
 LL | / enum ExcessiveEnum {
 LL | |     First, Second, Third, Fourth, Fifth, Sixth, Seventh, Eighth, Ninth, Tenth, Eleventh, Twelfth
@@ -59,7 +59,7 @@ LL |       match ExcessiveEnum::First {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `CustomRGBA { a: true, .. }` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:56:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:54:11
    |
 LL | / enum Color {
 LL | |     Red,
@@ -75,7 +75,7 @@ LL |       match Color::Red {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `[Second(true), Second(false)]` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:72:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:70:11
    |
 LL |     match *x {
    |           ^^ pattern `[Second(true), Second(false)]` not covered
@@ -83,7 +83,7 @@ LL |     match *x {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `((), false)` not covered
-  --> $DIR/non-exhaustive-pattern-witness.rs:85:11
+  --> $DIR/non-exhaustive-pattern-witness.rs:83:11
    |
 LL |     match ((), false) {
    |           ^^^^^^^^^^^ pattern `((), false)` not covered
index 41ba2cc4501c089a540a7260071cd88e6ed51b6c..52d1320dad153435950e8e4e5a30a92eff785d42 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 fn main() {
     let s: &[bool] = &[true; 0];
     let s1: &[bool; 1] = &[false; 1];
index 8cb342f33dfa0d917f94f585aedfec03b2db38e4..b3701efef3de2b6919ba1745d1e3e4f23ea7718d 100644 (file)
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `&[false, _]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:10:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:8:11
    |
 LL |     match s2 {
    |           ^^ pattern `&[false, _]` not covered
@@ -7,7 +7,7 @@ LL |     match s2 {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:14:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:12:11
    |
 LL |     match s3 {
    |           ^^ pattern `&[false, ..]` not covered
@@ -15,7 +15,7 @@ LL |     match s3 {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:18:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:16:11
    |
 LL |     match s10 {
    |           ^^^ pattern `&[false, ..]` not covered
@@ -23,7 +23,7 @@ LL |     match s10 {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, true]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:27:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:25:11
    |
 LL |     match s2 {
    |           ^^ pattern `&[false, true]` not covered
@@ -31,7 +31,7 @@ LL |     match s2 {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:32:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:30:11
    |
 LL |     match s3 {
    |           ^^ pattern `&[false, .., true]` not covered
@@ -39,7 +39,7 @@ LL |     match s3 {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:37:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:35:11
    |
 LL |     match s {
    |           ^ pattern `&[false, .., true]` not covered
@@ -47,7 +47,7 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:44:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:42:11
    |
 LL |     match s {
    |           ^ pattern `&[_, ..]` not covered
@@ -55,7 +55,7 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:48:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:46:11
    |
 LL |     match s {
    |           ^ pattern `&[_, _, ..]` not covered
@@ -63,7 +63,7 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:53:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:51:11
    |
 LL |     match s {
    |           ^ pattern `&[false, ..]` not covered
@@ -71,7 +71,7 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false, _, ..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:58:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:56:11
    |
 LL |     match s {
    |           ^ pattern `&[false, _, ..]` not covered
@@ -79,7 +79,7 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[_, .., false]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:64:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:62:11
    |
 LL |     match s {
    |           ^ pattern `&[_, .., false]` not covered
@@ -87,7 +87,7 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[_, _, .., true]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:71:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:69:11
    |
 LL |     match s {
    |           ^ pattern `&[_, _, .., true]` not covered
@@ -95,7 +95,7 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[true, _, .., _]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:78:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:76:11
    |
 LL |     match s {
    |           ^ pattern `&[true, _, .., _]` not covered
@@ -103,7 +103,7 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[..]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:87:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:85:11
    |
 LL |     match s {
    |           ^ pattern `&[..]` not covered
@@ -111,7 +111,7 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[true]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:91:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:89:11
    |
 LL |     match s {
    |           ^ pattern `&[true]` not covered
@@ -119,7 +119,7 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
 error[E0004]: non-exhaustive patterns: `&[false]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:99:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:97:11
    |
 LL |     match s1 {
    |           ^^ pattern `&[false]` not covered
index 3b716bae7720942840a4e49fda5c1e7b74d382cb..cbf64e2c53d0243ae573d380861d936649a10da5 100644 (file)
@@ -1,5 +1,4 @@
 // check-pass
-#![feature(slice_patterns)]
 
 fn main() {
     let s: &[bool] = &[true; 0];
index cd229a0fcbee4fef806df994a720a1de1f1b87e0..7c747b5e0b9d377e39fc599c2d70e07e6440cbcb 100644 (file)
@@ -1,4 +1,3 @@
-#![feature(slice_patterns)]
 #![deny(unreachable_patterns)]
 
 fn main() {
index 333ce170283eaa069a92f44d337e81baa14e8605..e24d10281170dcf3972e3df909cd07c06d8579d3 100644 (file)
@@ -1,41 +1,41 @@
 error: unreachable pattern
-  --> $DIR/slice-patterns-reachability.rs:9:9
+  --> $DIR/slice-patterns-reachability.rs:8:9
    |
 LL |         [true, ..] => {}
    |         ^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/slice-patterns-reachability.rs:2:9
+  --> $DIR/slice-patterns-reachability.rs:1:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/slice-patterns-reachability.rs:10:9
+  --> $DIR/slice-patterns-reachability.rs:9:9
    |
 LL |         [true] => {}
    |         ^^^^^^
 
 error: unreachable pattern
-  --> $DIR/slice-patterns-reachability.rs:15:9
+  --> $DIR/slice-patterns-reachability.rs:14:9
    |
 LL |         [.., true] => {}
    |         ^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/slice-patterns-reachability.rs:16:9
+  --> $DIR/slice-patterns-reachability.rs:15:9
    |
 LL |         [true] => {}
    |         ^^^^^^
 
 error: unreachable pattern
-  --> $DIR/slice-patterns-reachability.rs:21:9
+  --> $DIR/slice-patterns-reachability.rs:20:9
    |
 LL |         [false, .., true] => {}
    |         ^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/slice-patterns-reachability.rs:22:9
+  --> $DIR/slice-patterns-reachability.rs:21:9
    |
 LL |         [false, true] => {}
    |         ^^^^^^^^^^^^^
index 27b86007451d860fe3b6385aa904d665e3fff79f..b663cccbeef0f192da5e7d6b530a45f3bd974925 100644 (file)
@@ -9,6 +9,12 @@ LL |         return 0i32;
 LL |     }
 LL |     1u32
    |     ^^^^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:13:16
@@ -21,6 +27,12 @@ LL |         return 0i32;
 LL |     } else {
 LL |         return 1u32;
    |                ^^^^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:22:9
@@ -33,6 +45,12 @@ LL |         return 0i32;
 LL |     } else {
 LL |         1u32
    |         ^^^^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error[E0308]: `if` and `else` have incompatible types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:31:9
@@ -57,6 +75,12 @@ LL |         0 => return 0i32,
    |                     ---- ...is found to be `i32` here
 LL |         _ => 1u32,
    |              ^^^^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:45:5
@@ -71,6 +95,12 @@ LL | |         1 => 1u32,
 LL | |         _ => 2u32,
 LL | |     }
    | |_____^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error[E0308]: mismatched types
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:59:13
@@ -83,6 +113,12 @@ LL |             return 0i32;
 ...
 LL |             1u32
    |             ^^^^ expected `i32`, found `u32`
+   |
+   = note: to return `impl Trait`, all returned values must be of the same type
+   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
+   = help: you can instead return a boxed trait object using `Box<dyn std::fmt::Display>`
+   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
+   = help: alternatively, create a new `enum` with a variant for each returned type
 
 error: aborting due to 7 previous errors
 
index 230cf95de62065bfe1628623408ec7589e911c43..ae2e1b4b644a384b38348d48d90fd2b43f6cae60 100644 (file)
@@ -2,7 +2,13 @@ error[E0603]: macro `mac` is private
   --> $DIR/decl-macro.rs:8:8
    |
 LL |     m::mac!();
-   |        ^^^
+   |        ^^^ this macro is private
+   |
+note: the macro `mac` is defined here
+  --> $DIR/decl-macro.rs:4:5
+   |
+LL |     macro mac() {}
+   |     ^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 4b9faca045709145d606fd712126c8b56767f15e..8860d8f15f7488a2e3e1a5f77db6cdc63e8e51c0 100644 (file)
@@ -2,19 +2,37 @@ error[E0603]: module `bar` is private
   --> $DIR/privacy-in-paths.rs:24:16
    |
 LL |         ::foo::bar::baz::f();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `bar` is defined here
+  --> $DIR/privacy-in-paths.rs:3:5
+   |
+LL |     mod bar {
+   |     ^^^^^^^
 
 error[E0603]: module `bar` is private
   --> $DIR/privacy-in-paths.rs:25:16
    |
 LL |         ::foo::bar::S::f();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `bar` is defined here
+  --> $DIR/privacy-in-paths.rs:3:5
+   |
+LL |     mod bar {
+   |     ^^^^^^^
 
 error[E0603]: trait `T` is private
   --> $DIR/privacy-in-paths.rs:26:23
    |
 LL |         <() as ::foo::T>::Assoc::f();
-   |                       ^
+   |                       ^ this trait is private
+   |
+note: the trait `T` is defined here
+  --> $DIR/privacy-in-paths.rs:8:5
+   |
+LL |     trait T {
+   |     ^^^^^^^
 
 error: aborting due to 3 previous errors
 
index 2871573130a60c8eb97af63ef38c8e75ea97ca4a..8b12109b3730747f5ca7c548fd1422ad550072c2 100644 (file)
@@ -58,19 +58,37 @@ error[E0603]: trait `Bar` is private
   --> $DIR/privacy-ns2.rs:63:15
    |
 LL |     use foo3::Bar;
-   |               ^^^
+   |               ^^^ this trait is private
+   |
+note: the trait `Bar` is defined here
+  --> $DIR/privacy-ns2.rs:55:5
+   |
+LL |     trait Bar {
+   |     ^^^^^^^^^
 
 error[E0603]: trait `Bar` is private
   --> $DIR/privacy-ns2.rs:67:15
    |
 LL |     use foo3::Bar;
-   |               ^^^
+   |               ^^^ this trait is private
+   |
+note: the trait `Bar` is defined here
+  --> $DIR/privacy-ns2.rs:55:5
+   |
+LL |     trait Bar {
+   |     ^^^^^^^^^
 
 error[E0603]: trait `Bar` is private
   --> $DIR/privacy-ns2.rs:74:16
    |
 LL |     use foo3::{Bar,Baz};
-   |                ^^^
+   |                ^^^ this trait is private
+   |
+note: the trait `Bar` is defined here
+  --> $DIR/privacy-ns2.rs:55:5
+   |
+LL |     trait Bar {
+   |     ^^^^^^^^^
 
 error[E0107]: wrong number of const arguments: expected 0, found 1
   --> $DIR/privacy-ns2.rs:41:18
index 6be14df89d20a4ec65bdb1f817bf703ed71067a2..08640b802a244990320ef68fe24cf75d80ed217f 100644 (file)
@@ -2,7 +2,13 @@ error[E0603]: trait `Bar` is private
   --> $DIR/privacy-ufcs.rs:12:20
    |
 LL |     <i32 as ::foo::Bar>::baz();
-   |                    ^^^
+   |                    ^^^ this trait is private
+   |
+note: the trait `Bar` is defined here
+  --> $DIR/privacy-ufcs.rs:4:5
+   |
+LL |     trait Bar {
+   |     ^^^^^^^^^
 
 error: aborting due to previous error
 
index 29f53cd0e35450e071e90dcd76af26f9ae4bc3ca..215df0dc754410997470dbc1b78447d5b1b2efd2 100644 (file)
@@ -2,79 +2,157 @@ error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:132:18
    |
 LL |         use bar::baz::{foo, bar};
-   |                  ^^^
+   |                  ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:132:18
    |
 LL |         use bar::baz::{foo, bar};
-   |                  ^^^
+   |                  ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:141:18
    |
 LL |         use bar::baz;
-   |                  ^^^
+   |                  ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: module `i` is private
   --> $DIR/privacy1.rs:165:20
    |
 LL |     use self::foo::i::A;
-   |                    ^
+   |                    ^ this module is private
+   |
+note: the module `i` is defined here
+  --> $DIR/privacy1.rs:170:9
+   |
+LL |         mod i {
+   |         ^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:104:16
    |
 LL |         ::bar::baz::A::foo();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:105:16
    |
 LL |         ::bar::baz::A::bar();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:107:16
    |
 LL |         ::bar::baz::A.foo2();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:108:16
    |
 LL |         ::bar::baz::A.bar2();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: trait `B` is private
   --> $DIR/privacy1.rs:112:16
    |
 LL |         ::bar::B::foo();
-   |                ^
+   |                ^ this trait is private
+   |
+note: the trait `B` is defined here
+  --> $DIR/privacy1.rs:40:5
+   |
+LL |     trait B {
+   |     ^^^^^^^
 
 error[E0603]: function `epriv` is private
   --> $DIR/privacy1.rs:118:20
    |
 LL |             ::bar::epriv();
-   |                    ^^^^^
+   |                    ^^^^^ this function is private
+   |
+note: the function `epriv` is defined here
+  --> $DIR/privacy1.rs:65:9
+   |
+LL |         fn epriv();
+   |         ^^^^^^^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:127:16
    |
 LL |         ::bar::baz::foo();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: module `baz` is private
   --> $DIR/privacy1.rs:128:16
    |
 LL |         ::bar::baz::bar();
-   |                ^^^
+   |                ^^^ this module is private
+   |
+note: the module `baz` is defined here
+  --> $DIR/privacy1.rs:50:5
+   |
+LL |     mod baz {
+   |     ^^^^^^^
 
 error[E0603]: trait `B` is private
   --> $DIR/privacy1.rs:157:17
    |
 LL |     impl ::bar::B for f32 { fn foo() -> f32 { 1.0 } }
-   |                 ^
+   |                 ^ this trait is private
+   |
+note: the trait `B` is defined here
+  --> $DIR/privacy1.rs:40:5
+   |
+LL |     trait B {
+   |     ^^^^^^^
 
 error[E0624]: method `bar` is private
   --> $DIR/privacy1.rs:77:9
index 9f2359657bd7c5ca80099c4d329ef639cdf6d236..719dc27ccf4d6bddbded7ff6e8917d8890d7762c 100644 (file)
@@ -4,11 +4,17 @@ error[E0432]: unresolved import `bar::foo`
 LL |     use bar::foo;
    |         ^^^^^^^^ no `foo` in `bar`
 
-error[E0603]: function `foo` is private
+error[E0603]: function import `foo` is private
   --> $DIR/privacy2.rs:23:20
    |
 LL |     use bar::glob::foo;
-   |                    ^^^
+   |                    ^^^ this function import is private
+   |
+note: the function import `foo` is defined here
+  --> $DIR/privacy2.rs:10:13
+   |
+LL |         use foo;
+   |             ^^^
 
 error: requires `sized` lang_item
 
index e4a20f920a062b60e6f16f44fff231632472621e..e34b2d5049b9ef960d8315f21cbf30aaaa13e91c 100644 (file)
@@ -2,7 +2,13 @@ error[E0603]: module `glob` is private
   --> $DIR/privacy4.rs:21:14
    |
 LL |     use bar::glob::gpriv;
-   |              ^^^^
+   |              ^^^^ this module is private
+   |
+note: the module `glob` is defined here
+  --> $DIR/privacy4.rs:13:5
+   |
+LL |     mod glob {
+   |     ^^^^^^^^
 
 error: aborting due to previous error
 
index 2ee83149b695f12c8234d9c47b66fdf90fbff4be..197a857cc3dc435bbc8d6e033378a769bd0d1430 100644 (file)
@@ -5,7 +5,13 @@ LL |     pub struct A(());
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     let a = a::A(());
-   |                ^
+   |                ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/privacy5.rs:6:5
+   |
+LL |     pub struct A(());
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:52:16
@@ -14,7 +20,13 @@ LL |     pub struct B(isize);
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     let b = a::B(2);
-   |                ^
+   |                ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:53:16
@@ -23,7 +35,13 @@ LL |     pub struct C(pub isize, isize);
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     let c = a::C(2, 3);
-   |                ^
+   |                ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:56:12
@@ -32,7 +50,13 @@ LL |     pub struct A(());
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     let a::A(()) = a;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/privacy5.rs:6:5
+   |
+LL |     pub struct A(());
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:57:12
@@ -41,7 +65,13 @@ LL |     pub struct A(());
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     let a::A(_) = a;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/privacy5.rs:6:5
+   |
+LL |     pub struct A(());
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:58:18
@@ -50,7 +80,13 @@ LL |     pub struct A(());
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     match a { a::A(()) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/privacy5.rs:6:5
+   |
+LL |     pub struct A(());
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:59:18
@@ -59,7 +95,13 @@ LL |     pub struct A(());
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     match a { a::A(_) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/privacy5.rs:6:5
+   |
+LL |     pub struct A(());
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:61:12
@@ -68,7 +110,13 @@ LL |     pub struct B(isize);
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     let a::B(_) = b;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:62:12
@@ -77,7 +125,13 @@ LL |     pub struct B(isize);
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     let a::B(_b) = b;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:63:18
@@ -86,7 +140,13 @@ LL |     pub struct B(isize);
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     match b { a::B(_) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:64:18
@@ -95,7 +155,13 @@ LL |     pub struct B(isize);
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     match b { a::B(_b) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:65:18
@@ -104,7 +170,13 @@ LL |     pub struct B(isize);
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     match b { a::B(1) => {} a::B(_) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:65:32
@@ -113,7 +185,13 @@ LL |     pub struct B(isize);
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     match b { a::B(1) => {} a::B(_) => {} }
-   |                                ^
+   |                                ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:68:12
@@ -122,7 +200,13 @@ LL |     pub struct C(pub isize, isize);
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     let a::C(_, _) = c;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:69:12
@@ -131,7 +215,13 @@ LL |     pub struct C(pub isize, isize);
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     let a::C(_a, _) = c;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:70:12
@@ -140,7 +230,13 @@ LL |     pub struct C(pub isize, isize);
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     let a::C(_, _b) = c;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:71:12
@@ -149,7 +245,13 @@ LL |     pub struct C(pub isize, isize);
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     let a::C(_a, _b) = c;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:72:18
@@ -158,7 +260,13 @@ LL |     pub struct C(pub isize, isize);
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     match c { a::C(_, _) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:73:18
@@ -167,7 +275,13 @@ LL |     pub struct C(pub isize, isize);
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     match c { a::C(_a, _) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:74:18
@@ -176,7 +290,13 @@ LL |     pub struct C(pub isize, isize);
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     match c { a::C(_, _b) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:75:18
@@ -185,7 +305,13 @@ LL |     pub struct C(pub isize, isize);
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     match c { a::C(_a, _b) => {} }
-   |                  ^
+   |                  ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:83:17
@@ -194,7 +320,13 @@ LL |     pub struct A(());
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     let a2 = a::A;
-   |                 ^
+   |                 ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/privacy5.rs:6:5
+   |
+LL |     pub struct A(());
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:84:17
@@ -203,7 +335,13 @@ LL |     pub struct B(isize);
    |                  ----- a constructor is private if any of the fields is private
 ...
 LL |     let b2 = a::B;
-   |                 ^
+   |                 ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/privacy5.rs:7:5
+   |
+LL |     pub struct B(isize);
+   |     ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:85:17
@@ -212,271 +350,421 @@ LL |     pub struct C(pub isize, isize);
    |                  ---------------- a constructor is private if any of the fields is private
 ...
 LL |     let c2 = a::C;
-   |                 ^
+   |                 ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/privacy5.rs:8:5
+   |
+LL |     pub struct C(pub isize, isize);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:90:20
    |
 LL |     let a = other::A(());
-   |                    ^
+   |                    ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
 LL | pub struct A(());
    |              -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1
+   |
+LL | pub struct A(());
+   | ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:91:20
    |
 LL |     let b = other::B(2);
-   |                    ^
+   |                    ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:92:20
    |
 LL |     let c = other::C(2, 3);
-   |                    ^
+   |                    ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:95:16
    |
 LL |     let other::A(()) = a;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
 LL | pub struct A(());
    |              -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1
+   |
+LL | pub struct A(());
+   | ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:96:16
    |
 LL |     let other::A(_) = a;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
 LL | pub struct A(());
    |              -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1
+   |
+LL | pub struct A(());
+   | ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:97:22
    |
 LL |     match a { other::A(()) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
 LL | pub struct A(());
    |              -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1
+   |
+LL | pub struct A(());
+   | ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:98:22
    |
 LL |     match a { other::A(_) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
 LL | pub struct A(());
    |              -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1
+   |
+LL | pub struct A(());
+   | ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:100:16
    |
 LL |     let other::B(_) = b;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:101:16
    |
 LL |     let other::B(_b) = b;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:102:22
    |
 LL |     match b { other::B(_) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:103:22
    |
 LL |     match b { other::B(_b) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:104:22
    |
 LL |     match b { other::B(1) => {}
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:105:16
    |
 LL |         other::B(_) => {} }
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:107:16
    |
 LL |     let other::C(_, _) = c;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:108:16
    |
 LL |     let other::C(_a, _) = c;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:109:16
    |
 LL |     let other::C(_, _b) = c;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:110:16
    |
 LL |     let other::C(_a, _b) = c;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:111:22
    |
 LL |     match c { other::C(_, _) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:112:22
    |
 LL |     match c { other::C(_a, _) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:113:22
    |
 LL |     match c { other::C(_, _b) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:114:22
    |
 LL |     match c { other::C(_a, _b) => {} }
-   |                      ^
+   |                      ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `A` is private
   --> $DIR/privacy5.rs:122:21
    |
 LL |     let a2 = other::A;
-   |                     ^
+   |                     ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14
    |
 LL | pub struct A(());
    |              -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `A` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:1:1
+   |
+LL | pub struct A(());
+   | ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `B` is private
   --> $DIR/privacy5.rs:123:21
    |
 LL |     let b2 = other::B;
-   |                     ^
+   |                     ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14
    |
 LL | pub struct B(isize);
    |              ----- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `B` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:2:1
+   |
+LL | pub struct B(isize);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `C` is private
   --> $DIR/privacy5.rs:124:21
    |
 LL |     let c2 = other::C;
-   |                     ^
+   |                     ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14
    |
 LL | pub struct C(pub isize, isize);
    |              ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `C` is defined here
+  --> $DIR/auxiliary/privacy_tuple_struct.rs:3:1
+   |
+LL | pub struct C(pub isize, isize);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 48 previous errors
 
index 0d5435e1c504bc977aefe39c07a17480c456e527..f51b74f6cb53b343d1f56357537a92f4eca7ff1d 100644 (file)
@@ -2,7 +2,13 @@ error[E0603]: function `f` is private
   --> $DIR/private-item-simple.rs:6:8
    |
 LL |     a::f();
-   |        ^
+   |        ^ this function is private
+   |
+note: the function `f` is defined here
+  --> $DIR/private-item-simple.rs:2:5
+   |
+LL |     fn f() {}
+   |     ^^^^^^
 
 error: aborting due to previous error
 
index e6a61fbefb0d80dd87ea7195bc2b5a5068dedb02..aac444b8e3c98054f67a1a7dad6f368682ef72d1 100644 (file)
@@ -26,13 +26,25 @@ error[E0603]: struct `Crate` is private
   --> $DIR/test.rs:38:25
    |
 LL |     use pub_restricted::Crate;
-   |                         ^^^^^
+   |                         ^^^^^ this struct is private
+   |
+note: the struct `Crate` is defined here
+  --> $DIR/auxiliary/pub_restricted.rs:3:1
+   |
+LL | pub(crate) struct Crate;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: function `f` is private
   --> $DIR/test.rs:30:19
    |
 LL |     use foo::bar::f;
-   |                   ^
+   |                   ^ this function is private
+   |
+note: the function `f` is defined here
+  --> $DIR/test.rs:8:9
+   |
+LL |         pub(super) fn f() {}
+   |         ^^^^^^^^^^^^^^^^^
 
 error[E0616]: field `x` of struct `foo::bar::S` is private
   --> $DIR/test.rs:31:5
index a01b8f302cae32a565c32c3f8fe2889a460ec494..50f04b1eae1506649ef2f0196c7b9e015a0272af 100644 (file)
@@ -8,7 +8,7 @@
 mod m {
     use test_macros::Empty;
 }
-use m::Empty; //~ ERROR derive macro `Empty` is private
+use m::Empty; //~ ERROR derive macro import `Empty` is private
 
 // To resolve `empty_helper` we need to resolve `Empty`.
 // During initial resolution `use m::Empty` introduces no entries, so we proceed to `macro_use`,
index a3377ef515f9146eb7ec79345992258f90845f61..3beaedf61d73a722be48a20e30a7d152e69722f6 100644 (file)
@@ -4,11 +4,17 @@ error: cannot find attribute `empty_helper` in this scope
 LL | #[empty_helper]
    |   ^^^^^^^^^^^^
 
-error[E0603]: derive macro `Empty` is private
+error[E0603]: derive macro import `Empty` is private
   --> $DIR/disappearing-resolution.rs:11:8
    |
 LL | use m::Empty;
-   |        ^^^^^
+   |        ^^^^^ this derive macro import is private
+   |
+note: the derive macro import `Empty` is defined here
+  --> $DIR/disappearing-resolution.rs:9:9
+   |
+LL |     use test_macros::Empty;
+   |         ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 276c77f9b4249e44c877d405225ac0e936c9f4f7..c2e1d774e28ac469a07e02fd8e7428707fbfc08c 100644 (file)
@@ -2,7 +2,13 @@ error[E0603]: module `super_sekrit` is private
   --> $DIR/unreachable-variant.rs:6:21
    |
 LL |     let _x = other::super_sekrit::sooper_sekrit::baz;
-   |                     ^^^^^^^^^^^^
+   |                     ^^^^^^^^^^^^ this module is private
+   |
+note: the module `super_sekrit` is defined here
+  --> $DIR/auxiliary/unreachable_variant.rs:1:1
+   |
+LL | mod super_sekrit {
+   | ^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/recursion/issue-26548-recursion-via-normalize.rs b/src/test/ui/recursion/issue-26548-recursion-via-normalize.rs
new file mode 100644 (file)
index 0000000..6ee8c0f
--- /dev/null
@@ -0,0 +1,13 @@
+//~ ERROR cycle detected when computing layout of
+//~| NOTE ...which requires computing layout of
+//~| NOTE ...which again requires computing layout of
+
+// build-fail
+
+trait Mirror { type It: ?Sized; }
+impl<T: ?Sized> Mirror for T { type It = Self; }
+struct S(Option<<S as Mirror>::It>);
+
+fn main() { //~ NOTE cycle used when processing `main`
+    let _s = S(None);
+}
diff --git a/src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr b/src/test/ui/recursion/issue-26548-recursion-via-normalize.stderr
new file mode 100644 (file)
index 0000000..6a83f91
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0391]: cycle detected when computing layout of `std::option::Option<S>`
+   |
+   = note: ...which requires computing layout of `S`...
+   = note: ...which again requires computing layout of `std::option::Option<S>`, completing the cycle
+note: cycle used when processing `main`
+  --> $DIR/issue-26548-recursion-via-normalize.rs:11:1
+   |
+LL | fn main() {
+   | ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs
new file mode 100644 (file)
index 0000000..d9996b8
--- /dev/null
@@ -0,0 +1,17 @@
+// Dropck shouldn't hit a recursion limit from checking `S<u32>` since it has
+// no free regions or type parameters.
+// Codegen however, has to error for the infinitely many `drop_in_place`
+// functions it has been asked to create.
+// build-fail
+
+struct S<T> {
+    t: T,
+    s: Box<S<fn(u: T)>>,
+}
+
+fn f(x: S<u32>) {}
+
+fn main() {
+    // Force instantiation.
+    f as fn(_);
+}
diff --git a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr
new file mode 100644 (file)
index 0000000..de6df4c
--- /dev/null
@@ -0,0 +1,4 @@
+error: reached the recursion limit while instantiating `std::intrinsics::drop_in_place::<S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(u32))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>> - shim(Some(S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(u32))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>))`
+
+error: aborting due to previous error
+
index a3610345173a7e01341f0c0864bf44f8b17ca915..67d87eb5cd520077ade2237ccdc81e1a8409952b 100644 (file)
@@ -16,34 +16,34 @@ union UB {
 }
 
 #[repr(packed)]
-struct SC(SA); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+struct SC(SA); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
 
 #[repr(packed)]
-struct SD(SB); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+struct SD(SB); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
 
 #[repr(packed)]
-struct SE(UA); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+struct SE(UA); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
 
 #[repr(packed)]
-struct SF(UB); //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+struct SF(UB); //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
 
 #[repr(packed)]
-union UC { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+union UC { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
     a: UA
 }
 
 #[repr(packed)]
-union UD { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+union UD { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
     n: UB
 }
 
 #[repr(packed)]
-union UE { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+union UE { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
     a: SA
 }
 
 #[repr(packed)]
-union UF { //~ ERROR: packed type cannot transitively contain a `[repr(align)]` type
+union UF { //~ ERROR: packed type cannot transitively contain a `#[repr(align)]` type
     n: SB
 }
 
index df001d6b5f2a4c0ed8b40bcd22914a506747f35b..32f9bb8bf33d9705ebc2bc018fd4b4d7661e279f 100644 (file)
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:19:1
    |
 LL | struct SC(SA);
    | ^^^^^^^^^^^^^^
+   |
+note: `SA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:5:1
+   |
+LL | struct SA(i32);
+   | ^^^^^^^^^^^^^^^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:22:1
    |
 LL | struct SD(SB);
    | ^^^^^^^^^^^^^^
+   |
+note: `SA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:5:1
+   |
+LL | struct SA(i32);
+   | ^^^^^^^^^^^^^^^
+note: `SD` contains a field of type `SB`
+  --> $DIR/repr-packed-contains-align.rs:22:11
+   |
+LL | struct SD(SB);
+   |           ^^
+note: ...which contains a field of type `SA`
+  --> $DIR/repr-packed-contains-align.rs:7:11
+   |
+LL | struct SB(SA);
+   |           ^^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:25:1
    |
 LL | struct SE(UA);
    | ^^^^^^^^^^^^^^
+   |
+note: `UA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:10:1
+   |
+LL | / union UA {
+LL | |     i: i32
+LL | | }
+   | |_^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:28:1
    |
 LL | struct SF(UB);
    | ^^^^^^^^^^^^^^
+   |
+note: `UA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:10:1
+   |
+LL | / union UA {
+LL | |     i: i32
+LL | | }
+   | |_^
+note: `SF` contains a field of type `UB`
+  --> $DIR/repr-packed-contains-align.rs:28:11
+   |
+LL | struct SF(UB);
+   |           ^^
+note: ...which contains a field of type `UA`
+  --> $DIR/repr-packed-contains-align.rs:15:5
+   |
+LL |     a: UA
+   |     ^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:31:1
    |
 LL | / union UC {
 LL | |     a: UA
+LL | | }
+   | |_^
+   |
+note: `UA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:10:1
+   |
+LL | / union UA {
+LL | |     i: i32
 LL | | }
    | |_^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:36:1
    |
 LL | / union UD {
 LL | |     n: UB
 LL | | }
    | |_^
+   |
+note: `UA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:10:1
+   |
+LL | / union UA {
+LL | |     i: i32
+LL | | }
+   | |_^
+note: `UD` contains a field of type `UB`
+  --> $DIR/repr-packed-contains-align.rs:37:5
+   |
+LL |     n: UB
+   |     ^
+note: ...which contains a field of type `UA`
+  --> $DIR/repr-packed-contains-align.rs:15:5
+   |
+LL |     a: UA
+   |     ^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:41:1
    |
 LL | / union UE {
 LL | |     a: SA
 LL | | }
    | |_^
+   |
+note: `SA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:5:1
+   |
+LL | struct SA(i32);
+   | ^^^^^^^^^^^^^^^
 
-error[E0588]: packed type cannot transitively contain a `[repr(align)]` type
+error[E0588]: packed type cannot transitively contain a `#[repr(align)]` type
   --> $DIR/repr-packed-contains-align.rs:46:1
    |
 LL | / union UF {
 LL | |     n: SB
 LL | | }
    | |_^
+   |
+note: `SA` has a `#[repr(align)]` attribute
+  --> $DIR/repr-packed-contains-align.rs:5:1
+   |
+LL | struct SA(i32);
+   | ^^^^^^^^^^^^^^^
+note: `UF` contains a field of type `SB`
+  --> $DIR/repr-packed-contains-align.rs:47:5
+   |
+LL |     n: SB
+   |     ^
+note: ...which contains a field of type `SA`
+  --> $DIR/repr-packed-contains-align.rs:7:11
+   |
+LL | struct SB(SA);
+   |           ^^
 
 error: aborting due to 8 previous errors
 
index 688720e8cd3885e9a96a2f6f6042ef2cd0e93dc4..08a1d790197a6384740304397043239d0d97aa95 100644 (file)
@@ -253,25 +253,49 @@ error[E0603]: enum `Z` is private
   --> $DIR/privacy-enum-ctor.rs:57:22
    |
 LL |     let _: Z = m::n::Z;
-   |                      ^
+   |                      ^ this enum is private
+   |
+note: the enum `Z` is defined here
+  --> $DIR/privacy-enum-ctor.rs:11:9
+   |
+LL |         pub(in m) enum Z {
+   |         ^^^^^^^^^^^^^^^^
 
 error[E0603]: enum `Z` is private
   --> $DIR/privacy-enum-ctor.rs:61:22
    |
 LL |     let _: Z = m::n::Z::Fn;
-   |                      ^
+   |                      ^ this enum is private
+   |
+note: the enum `Z` is defined here
+  --> $DIR/privacy-enum-ctor.rs:11:9
+   |
+LL |         pub(in m) enum Z {
+   |         ^^^^^^^^^^^^^^^^
 
 error[E0603]: enum `Z` is private
   --> $DIR/privacy-enum-ctor.rs:64:22
    |
 LL |     let _: Z = m::n::Z::Struct;
-   |                      ^
+   |                      ^ this enum is private
+   |
+note: the enum `Z` is defined here
+  --> $DIR/privacy-enum-ctor.rs:11:9
+   |
+LL |         pub(in m) enum Z {
+   |         ^^^^^^^^^^^^^^^^
 
 error[E0603]: enum `Z` is private
   --> $DIR/privacy-enum-ctor.rs:68:22
    |
 LL |     let _: Z = m::n::Z::Unit {};
-   |                      ^
+   |                      ^ this enum is private
+   |
+note: the enum `Z` is defined here
+  --> $DIR/privacy-enum-ctor.rs:11:9
+   |
+LL |         pub(in m) enum Z {
+   |         ^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/privacy-enum-ctor.rs:27:20
index f1a1de4d9c0fd118520db027ab2d6a4676bed996..1673ec46ba488c7260acc7468a318e7f14b3874e 100644 (file)
@@ -45,7 +45,13 @@ LL |         pub(in m) struct Z(pub(in m::n) u8);
    |                            --------------- a constructor is private if any of the fields is private
 ...
 LL |         n::Z;
-   |            ^
+   |            ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `Z` is defined here
+  --> $DIR/privacy-struct-ctor.rs:12:9
+   |
+LL |         pub(in m) struct Z(pub(in m::n) u8);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `S` is private
   --> $DIR/privacy-struct-ctor.rs:29:8
@@ -54,7 +60,13 @@ LL |     pub struct S(u8);
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     m::S;
-   |        ^
+   |        ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `S` is defined here
+  --> $DIR/privacy-struct-ctor.rs:6:5
+   |
+LL |     pub struct S(u8);
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `S` is private
   --> $DIR/privacy-struct-ctor.rs:31:19
@@ -63,7 +75,13 @@ LL |     pub struct S(u8);
    |                  -- a constructor is private if any of the fields is private
 ...
 LL |     let _: S = m::S(2);
-   |                   ^
+   |                   ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `S` is defined here
+  --> $DIR/privacy-struct-ctor.rs:6:5
+   |
+LL |     pub struct S(u8);
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `Z` is private
   --> $DIR/privacy-struct-ctor.rs:35:11
@@ -72,29 +90,47 @@ LL |         pub(in m) struct Z(pub(in m::n) u8);
    |                            --------------- a constructor is private if any of the fields is private
 ...
 LL |     m::n::Z;
-   |           ^
+   |           ^ this tuple struct constructor is private
+   |
+note: the tuple struct constructor `Z` is defined here
+  --> $DIR/privacy-struct-ctor.rs:12:9
+   |
+LL |         pub(in m) struct Z(pub(in m::n) u8);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `S` is private
   --> $DIR/privacy-struct-ctor.rs:41:16
    |
 LL |     xcrate::m::S;
-   |                ^
+   |                ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy-struct-ctor.rs:2:18
    |
 LL |     pub struct S(u8);
    |                  -- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `S` is defined here
+  --> $DIR/auxiliary/privacy-struct-ctor.rs:2:5
+   |
+LL |     pub struct S(u8);
+   |     ^^^^^^^^^^^^^^^^^
 
 error[E0603]: tuple struct constructor `Z` is private
   --> $DIR/privacy-struct-ctor.rs:45:19
    |
 LL |     xcrate::m::n::Z;
-   |                   ^
+   |                   ^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/privacy-struct-ctor.rs:5:28
    |
 LL |         pub(in m) struct Z(pub(in m::n) u8);
    |                            --------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `Z` is defined here
+  --> $DIR/auxiliary/privacy-struct-ctor.rs:5:9
+   |
+LL |         pub(in m) struct Z(pub(in m::n) u8);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 10 previous errors
 
index 1484b8c4a1f13e6f519ce65dee4914826b5925bf..363a0e3e649d9a5fe66432509252cd7ad9ca9291 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(slice_patterns)]
-
 pub fn main() {
     let sl: &[u8] = b"foo";
 
index f1e91a05f082fd8653bb28dddc6bfb6db932e68f..c234fdf46ed2d8651c493a77adcf66e7506fbf5d 100644 (file)
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: `&[]` not covered
-  --> $DIR/slice.rs:6:11
+  --> $DIR/slice.rs:4:11
    |
 LL |     match sl {
    |           ^^ pattern `&[]` not covered
index 944965a15e3d02941dfcb95189bfe5786d8a1836..f992988c93fcc502972030e0adb401823930ba9a 100644 (file)
@@ -14,18 +14,30 @@ error[E0603]: tuple struct constructor `TupleStruct` is private
   --> $DIR/struct.rs:23:32
    |
 LL |     let ts_explicit = structs::TupleStruct(640, 480);
-   |                                ^^^^^^^^^^^
+   |                                ^^^^^^^^^^^ this tuple struct constructor is private
    | 
   ::: $DIR/auxiliary/structs.rs:11:24
    |
 LL | pub struct TupleStruct(pub u16, pub u16);
    |                        ---------------- a constructor is private if any of the fields is private
+   |
+note: the tuple struct constructor `TupleStruct` is defined here
+  --> $DIR/auxiliary/structs.rs:11:1
+   |
+LL | pub struct TupleStruct(pub u16, pub u16);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: unit struct `UnitStruct` is private
   --> $DIR/struct.rs:32:32
    |
 LL |     let us_explicit = structs::UnitStruct;
-   |                                ^^^^^^^^^^
+   |                                ^^^^^^^^^^ this unit struct is private
+   |
+note: the unit struct `UnitStruct` is defined here
+  --> $DIR/auxiliary/structs.rs:8:1
+   |
+LL | pub struct UnitStruct;
+   | ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0639]: cannot create non-exhaustive struct using struct expression
   --> $DIR/struct.rs:7:14
index d9d6ea21b8bd4dccce0e8365873285e99ed9e6b6..2a438753a2c70148ee734037a7b4fb1a1922840a 100644 (file)
@@ -2,31 +2,61 @@ error[E0603]: tuple variant `Tuple` is private
   --> $DIR/variant.rs:11:48
    |
 LL |     let variant_tuple = NonExhaustiveVariants::Tuple(640);
-   |                                                ^^^^^
+   |                                                ^^^^^ this tuple variant is private
+   |
+note: the tuple variant `Tuple` is defined here
+  --> $DIR/auxiliary/variants.rs:5:23
+   |
+LL |     #[non_exhaustive] Tuple(u32),
+   |                       ^^^^^^^^^^
 
 error[E0603]: unit variant `Unit` is private
   --> $DIR/variant.rs:14:47
    |
 LL |     let variant_unit = NonExhaustiveVariants::Unit;
-   |                                               ^^^^
+   |                                               ^^^^ this unit variant is private
+   |
+note: the unit variant `Unit` is defined here
+  --> $DIR/auxiliary/variants.rs:4:23
+   |
+LL |     #[non_exhaustive] Unit,
+   |                       ^^^^
 
 error[E0603]: unit variant `Unit` is private
   --> $DIR/variant.rs:18:32
    |
 LL |         NonExhaustiveVariants::Unit => "",
-   |                                ^^^^
+   |                                ^^^^ this unit variant is private
+   |
+note: the unit variant `Unit` is defined here
+  --> $DIR/auxiliary/variants.rs:4:23
+   |
+LL |     #[non_exhaustive] Unit,
+   |                       ^^^^
 
 error[E0603]: tuple variant `Tuple` is private
   --> $DIR/variant.rs:20:32
    |
 LL |         NonExhaustiveVariants::Tuple(fe_tpl) => "",
-   |                                ^^^^^
+   |                                ^^^^^ this tuple variant is private
+   |
+note: the tuple variant `Tuple` is defined here
+  --> $DIR/auxiliary/variants.rs:5:23
+   |
+LL |     #[non_exhaustive] Tuple(u32),
+   |                       ^^^^^^^^^^
 
 error[E0603]: tuple variant `Tuple` is private
   --> $DIR/variant.rs:26:35
    |
 LL |     if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct {
-   |                                   ^^^^^
+   |                                   ^^^^^ this tuple variant is private
+   |
+note: the tuple variant `Tuple` is defined here
+  --> $DIR/auxiliary/variants.rs:5:23
+   |
+LL |     #[non_exhaustive] Tuple(u32),
+   |                       ^^^^^^^^^^
 
 error[E0639]: cannot create non-exhaustive variant using struct expression
   --> $DIR/variant.rs:8:26
index 38b0941aad0a6060a1aea3ee7eb6ab2b68695478..33229a205f4d8dc4b4911de2b67440fab2290786 100644 (file)
@@ -1,5 +1,4 @@
 // run-pass
-#![feature(slice_patterns)]
 
 fn slice_pat() {
     let sl: &[u8] = b"foo";
diff --git a/src/test/ui/sanitizer-address.rs b/src/test/ui/sanitizer-address.rs
new file mode 100644 (file)
index 0000000..d27a30a
--- /dev/null
@@ -0,0 +1,21 @@
+// needs-sanitizer-support
+// only-x86_64
+//
+// compile-flags: -Z sanitizer=address -O
+//
+// run-fail
+// error-pattern: AddressSanitizer: stack-buffer-overflow
+// error-pattern: 'xs' <== Memory access at offset
+
+#![feature(test)]
+
+use std::hint::black_box;
+use std::mem;
+
+fn main() {
+    let xs = [0, 1, 2, 3];
+    // Avoid optimizing everything out.
+    let xs = black_box(xs.as_ptr());
+    let code = unsafe { *xs.offset(4) };
+    std::process::exit(code);
+}
diff --git a/src/test/ui/sanitizer-leak.rs b/src/test/ui/sanitizer-leak.rs
new file mode 100644 (file)
index 0000000..5c2f2cb
--- /dev/null
@@ -0,0 +1,21 @@
+// needs-sanitizer-support
+// only-x86_64
+//
+// compile-flags: -Z sanitizer=leak -O
+//
+// run-fail
+// error-pattern: LeakSanitizer: detected memory leaks
+
+#![feature(test)]
+
+use std::hint::black_box;
+use std::mem;
+
+fn main() {
+    for _ in 0..10 {
+        let xs = vec![1, 2, 3];
+        // Prevent compiler from removing the memory allocation.
+        let xs = black_box(xs);
+        mem::forget(xs);
+    }
+}
diff --git a/src/test/ui/sanitizer-memory.rs b/src/test/ui/sanitizer-memory.rs
new file mode 100644 (file)
index 0000000..3e1cf45
--- /dev/null
@@ -0,0 +1,44 @@
+// needs-sanitizer-support
+// only-linux
+// only-x86_64
+//
+// compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins -O
+//
+// run-fail
+// error-pattern: MemorySanitizer: use-of-uninitialized-value
+// error-pattern: Uninitialized value was created by an allocation
+// error-pattern: in the stack frame of function 'random'
+//
+// This test case intentionally limits the usage of the std,
+// since it will be linked with an uninstrumented version of it.
+
+#![feature(core_intrinsics)]
+#![feature(start)]
+#![feature(test)]
+
+use std::hint::black_box;
+use std::mem::MaybeUninit;
+
+#[inline(never)]
+#[no_mangle]
+fn random() -> [isize; 32] {
+    let r = unsafe { MaybeUninit::uninit().assume_init() };
+    // Avoid optimizing everything out.
+    black_box(r)
+}
+
+#[inline(never)]
+#[no_mangle]
+fn xor(a: &[isize]) -> isize {
+    let mut s = 0;
+    for i in 0..a.len() {
+        s = s ^ a[i];
+    }
+    s
+}
+
+#[start]
+fn main(_: isize, _: *const *const u8) -> isize {
+    let r = random();
+    xor(&r)
+}
diff --git a/src/test/ui/sanitizer-unsupported-target.rs b/src/test/ui/sanitizer-unsupported-target.rs
new file mode 100644 (file)
index 0000000..444333c
--- /dev/null
@@ -0,0 +1,7 @@
+// ignore-tidy-linelength
+// compile-flags: -Z sanitizer=leak --target i686-unknown-linux-gnu
+// error-pattern: error: LeakSanitizer only works with the `x86_64-unknown-linux-gnu` or `x86_64-apple-darwin` target
+
+#![feature(no_core)]
+#![no_core]
+#![no_main]
diff --git a/src/test/ui/sanitizer-unsupported-target.stderr b/src/test/ui/sanitizer-unsupported-target.stderr
new file mode 100644 (file)
index 0000000..38be58d
--- /dev/null
@@ -0,0 +1,4 @@
+error: LeakSanitizer only works with the `x86_64-unknown-linux-gnu` or `x86_64-apple-darwin` target
+
+error: aborting due to previous error
+
index 8185e82ee830ec449db518a955fb19cd3025d4ce..6b801972f4179bd5002c5d3594e0c44cfafa3942 100644 (file)
@@ -6,11 +6,11 @@ pub fn f() {}
 }
 
 mod bar {
-    use foo::bar::f as g; //~ ERROR module `bar` is private
+    use foo::bar::f as g; //~ ERROR module import `bar` is private
 
     use foo as f;
     pub use foo::*;
 }
 
-use bar::f::f; //~ ERROR module `f` is private
+use bar::f::f; //~ ERROR module import `f` is private
 fn main() {}
index 7c66fdf60b1d4205e4d83c74490161b4f35ae615..cd8ec13794c6f13d6abe6df2c78bb1ea10c76d0a 100644 (file)
@@ -1,14 +1,26 @@
-error[E0603]: module `bar` is private
+error[E0603]: module import `bar` is private
   --> $DIR/shadowed-use-visibility.rs:9:14
    |
 LL |     use foo::bar::f as g;
-   |              ^^^
+   |              ^^^ this module import is private
+   |
+note: the module import `bar` is defined here
+  --> $DIR/shadowed-use-visibility.rs:4:9
+   |
+LL |     use foo as bar;
+   |         ^^^^^^^^^^
 
-error[E0603]: module `f` is private
+error[E0603]: module import `f` is private
   --> $DIR/shadowed-use-visibility.rs:15:10
    |
 LL | use bar::f::f;
-   |          ^
+   |          ^ this module import is private
+   |
+note: the module import `f` is defined here
+  --> $DIR/shadowed-use-visibility.rs:11:9
+   |
+LL |     use foo as f;
+   |         ^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index f12e9198b0d7c274f767b703d1892845e66e5019..1815897f17a60ee22708c17f1fa3d3fb79969b4b 100644 (file)
@@ -1,3 +1,8 @@
+// FIXME: missing sysroot spans (#53081)
+// ignore-i586-unknown-linux-gnu
+// ignore-i586-unknown-linux-musl
+// ignore-i686-unknown-linux-musl
+
 fn main() {
     let _ = std::thread::thread_info::current_thread();
     //~^ERROR module `thread_info` is private
index c3edd62a15edac3ca5c418d07223a77b0727d11c..3a974164f94734f7634bd330bf2681527f05b3f3 100644 (file)
@@ -1,8 +1,14 @@
 error[E0603]: module `thread_info` is private
-  --> $DIR/stability-in-private-module.rs:2:26
+  --> $DIR/stability-in-private-module.rs:7:26
    |
 LL |     let _ = std::thread::thread_info::current_thread();
-   |                          ^^^^^^^^^^^
+   |                          ^^^^^^^^^^^ this module is private
+   |
+note: the module `thread_info` is defined here
+  --> $SRC_DIR/libstd/thread/mod.rs:LL:COL
+   |
+LL | use crate::sys_common::thread_info;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 95bcf07633565d31adc9b8a43ae6db370fe92836..f6cd40412dd843f635931d69f235f16b241adcca 100644 (file)
@@ -2,13 +2,25 @@ error[E0603]: static `private` is private
   --> $DIR/static-priv-by-default2.rs:15:30
    |
 LL |     use child::childs_child::private;
-   |                              ^^^^^^^
+   |                              ^^^^^^^ this static is private
+   |
+note: the static `private` is defined here
+  --> $DIR/static-priv-by-default2.rs:7:9
+   |
+LL |         static private: isize = 0;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: static `private` is private
   --> $DIR/static-priv-by-default2.rs:23:33
    |
 LL |     use static_priv_by_default::private;
-   |                                 ^^^^^^^
+   |                                 ^^^^^^^ this static is private
+   |
+note: the static `private` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:3:1
+   |
+LL | static private: isize = 0;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 39241b6b3fc1da18c779ac6dd58962e2a3cd60fd..0203b7b5242e5187f18357ad74343796ec96ee4b 100644 (file)
@@ -2,13 +2,25 @@ error[E0603]: enum `Bar` is private
   --> $DIR/struct-variant-privacy-xc.rs:4:33
    |
 LL | fn f(b: struct_variant_privacy::Bar) {
-   |                                 ^^^
+   |                                 ^^^ this enum is private
+   |
+note: the enum `Bar` is defined here
+  --> $DIR/auxiliary/struct_variant_privacy.rs:1:1
+   |
+LL | enum Bar {
+   | ^^^^^^^^
 
 error[E0603]: enum `Bar` is private
   --> $DIR/struct-variant-privacy-xc.rs:6:33
    |
 LL |         struct_variant_privacy::Bar::Baz { a: _a } => {}
-   |                                 ^^^
+   |                                 ^^^ this enum is private
+   |
+note: the enum `Bar` is defined here
+  --> $DIR/auxiliary/struct_variant_privacy.rs:1:1
+   |
+LL | enum Bar {
+   | ^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index 127a6501044856e647b82dfba40513c04e64e575..d1b603f9d46fc027afc9eec22501c0e07d505160 100644 (file)
@@ -2,13 +2,25 @@ error[E0603]: enum `Bar` is private
   --> $DIR/struct-variant-privacy.rs:7:14
    |
 LL | fn f(b: foo::Bar) {
-   |              ^^^
+   |              ^^^ this enum is private
+   |
+note: the enum `Bar` is defined here
+  --> $DIR/struct-variant-privacy.rs:2:5
+   |
+LL |     enum Bar {
+   |     ^^^^^^^^
 
 error[E0603]: enum `Bar` is private
   --> $DIR/struct-variant-privacy.rs:9:14
    |
 LL |         foo::Bar::Baz { a: _a } => {}
-   |              ^^^
+   |              ^^^ this enum is private
+   |
+note: the enum `Bar` is defined here
+  --> $DIR/struct-variant-privacy.rs:2:5
+   |
+LL |     enum Bar {
+   |     ^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index b0679ea1d3df2daf38c3174e8d599e6972a30d36..b7bf5a150ea8ba90eaf29dcbfadeb1d993ee490a 100644 (file)
@@ -11,6 +11,7 @@
 #![cfg(test)]
 
 use std::io::Write;
+use std::env;
 
 #[test]
 fn it_works() {
@@ -35,3 +36,13 @@ fn it_fails() {
 fn it_exits() {
     std::process::exit(123);
 }
+
+#[test]
+fn no_residual_environment() {
+    for (key, _) in env::vars() {
+        // Look for keys like __RUST_TEST_INVOKE.
+        if key.contains("TEST_INVOKE") {
+            panic!("shouldn't have '{}' in environment", key);
+        }
+    }
+}
index 46adcfbc2eb4a387d7449247456c281855ffdabf..2f4bc32ed6a1f3de8ac5c7cfc967fb10415d3d0e 100644 (file)
@@ -1,9 +1,10 @@
 
-running 4 tests
+running 5 tests
 test it_exits ... FAILED
 test it_fails ... FAILED
 test it_panics ... ok
 test it_works ... ok
+test no_residual_environment ... ok
 
 failures:
 
@@ -17,7 +18,7 @@ testing123
 testing321
 thread 'main' panicked at 'assertion failed: `(left == right)`
   left: `2`,
- right: `5`', $DIR/test-panic-abort.rs:31:5
+ right: `5`', $DIR/test-panic-abort.rs:32:5
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 
 
@@ -25,5 +26,5 @@ failures:
     it_exits
     it_fails
 
-test result: FAILED. 2 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out
+test result: FAILED. 3 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out
 
index 44beb9dc1e534f4a9ead2a5d51807f7d7ce12ac6..2f6d35f01be62be86783118e1faa5368275448e3 100644 (file)
@@ -88,6 +88,7 @@ fn main() {
     is_sync_send!((1..));
     is_sync_send!(repeat(1));
     is_sync_send!(empty::<usize>());
+    is_sync_send!(empty::<*mut i32>());
     is_sync_send!(once(1));
 
     // for option.rs
index 929c35a9e1122cbac1f1bac170fa9dff0d19d7cd..97006ae50a0bf3a509f95e73f425ddc549d0c97d 100644 (file)
@@ -1,8 +1,6 @@
 // run-pass
 // pretty-expanded FIXME #23616
 
-#![feature(slice_patterns)]
-
 fn f<T,>(_: T,) {}
 
 struct Foo<T,>(T);
index d4c7c7c74529eaa4a7d8e6335af8b8988588b4d1..9e8414f9c15febcbefaf8bc19d018a87e3ea50a6 100644 (file)
@@ -18,6 +18,8 @@ LL | type Underconstrained<T: std::fmt::Debug> = impl 'static;
 ...
 LL | fn underconstrained<U>(_: U) -> Underconstrained<U> {
    |                     - help: consider restricting this bound: `U: std::fmt::Debug`
+LL |     5u32
+   |     ---- this returned value is of type `u32`
    |
    = help: the trait `std::fmt::Debug` is not implemented for `U`
    = note: the return type of a function must have a statically known size
@@ -30,6 +32,8 @@ LL | type Underconstrained2<T: std::fmt::Debug> = impl 'static;
 ...
 LL | fn underconstrained2<U, V>(_: U, _: V) -> Underconstrained2<V> {
    |                         - help: consider restricting this bound: `V: std::fmt::Debug`
+LL |     5u32
+   |     ---- this returned value is of type `u32`
    |
    = help: the trait `std::fmt::Debug` is not implemented for `V`
    = note: the return type of a function must have a statically known size
index 14c09ade7dde32c4e606a0a764fc0dac7f4c877a..a656b20c23ec3a6f249367ea3560836f650b7d70 100644 (file)
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
 LL | fn ice(x: Box<dyn Iterator<Item=()>>) {
    |                                       - possibly return type missing here?
 LL |     *x
-   |     ^^ expected `()`, found trait `std::iter::Iterator`
+   |     ^^ expected `()`, found trait object `dyn std::iter::Iterator`
    |
    = note: expected unit type `()`
            found trait object `(dyn std::iter::Iterator<Item = ()> + 'static)`
index 1bf01184a08e7c4bbb169c82498262663a8cc4f3..58c726d2185c4d3d13ec6cfb6813933a17295877 100644 (file)
@@ -2,7 +2,7 @@
 #![feature(box_syntax)]
 #![feature(never_type)]
 #![feature(exhaustive_patterns)]
-#![feature(slice_patterns)]
+
 #![deny(unreachable_patterns)]
 
 mod foo {
index f7438cce22967332e64de9cb39eea2fe90778eb2..3f38a6cae7b819055e7ca742b419b2763dc86e31 100644 (file)
@@ -44,13 +44,25 @@ error[E0603]: struct `Foo` is private
   --> $DIR/use-from-trait-xc.rs:14:24
    |
 LL | use use_from_trait_xc::Foo::new;
-   |                        ^^^
+   |                        ^^^ this struct is private
+   |
+note: the struct `Foo` is defined here
+  --> $DIR/auxiliary/use-from-trait-xc.rs:9:1
+   |
+LL | struct Foo;
+   | ^^^^^^^^^^^
 
 error[E0603]: struct `Foo` is private
   --> $DIR/use-from-trait-xc.rs:17:24
    |
 LL | use use_from_trait_xc::Foo::C;
-   |                        ^^^
+   |                        ^^^ this struct is private
+   |
+note: the struct `Foo` is defined here
+  --> $DIR/auxiliary/use-from-trait-xc.rs:9:1
+   |
+LL | struct Foo;
+   | ^^^^^^^^^^^
 
 error: aborting due to 9 previous errors
 
index 0c800ec35e4094d87ef71904ad06b724795cde81..4852759286ae632fee1fa9bba6dd25f849c157e3 100644 (file)
@@ -2,13 +2,25 @@ error[E0603]: module `bar` is private
   --> $DIR/use-mod-3.rs:1:10
    |
 LL | use foo::bar::{
-   |          ^^^
+   |          ^^^ this module is private
+   |
+note: the module `bar` is defined here
+  --> $DIR/use-mod-3.rs:9:5
+   |
+LL |     mod bar { pub type Bar = isize; }
+   |     ^^^^^^^
 
 error[E0603]: module `bar` is private
   --> $DIR/use-mod-3.rs:4:10
    |
 LL | use foo::bar::{
-   |          ^^^
+   |          ^^^ this module is private
+   |
+note: the module `bar` is defined here
+  --> $DIR/use-mod-3.rs:9:5
+   |
+LL |     mod bar { pub type Bar = isize; }
+   |     ^^^^^^^
 
 error: aborting due to 2 previous errors
 
index da52b4249e31954c8a4fee6c359e1f568fc2324f..842069d6135cbeba743ebd75c0c94da2fd55b5f9 100644 (file)
@@ -2,61 +2,121 @@ error[E0603]: static `j` is private
   --> $DIR/xcrate-private-by-default.rs:23:29
    |
 LL |     static_priv_by_default::j;
-   |                             ^
+   |                             ^ this static is private
+   |
+note: the static `j` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:47:1
+   |
+LL | static j: isize = 0;
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0603]: function `k` is private
   --> $DIR/xcrate-private-by-default.rs:25:29
    |
 LL |     static_priv_by_default::k;
-   |                             ^
+   |                             ^ this function is private
+   |
+note: the function `k` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:48:1
+   |
+LL | fn k() {}
+   | ^^^^^^
 
 error[E0603]: unit struct `l` is private
   --> $DIR/xcrate-private-by-default.rs:27:29
    |
 LL |     static_priv_by_default::l;
-   |                             ^
+   |                             ^ this unit struct is private
+   |
+note: the unit struct `l` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:49:1
+   |
+LL | struct l;
+   | ^^^^^^^^^
 
 error[E0603]: enum `m` is private
   --> $DIR/xcrate-private-by-default.rs:29:35
    |
 LL |     foo::<static_priv_by_default::m>();
-   |                                   ^
+   |                                   ^ this enum is private
+   |
+note: the enum `m` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:50:1
+   |
+LL | enum m {}
+   | ^^^^^^
 
 error[E0603]: type alias `n` is private
   --> $DIR/xcrate-private-by-default.rs:31:35
    |
 LL |     foo::<static_priv_by_default::n>();
-   |                                   ^
+   |                                   ^ this type alias is private
+   |
+note: the type alias `n` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:51:1
+   |
+LL | type n = isize;
+   | ^^^^^^^^^^^^^^^
 
 error[E0603]: module `foo` is private
   --> $DIR/xcrate-private-by-default.rs:35:29
    |
 LL |     static_priv_by_default::foo::a;
-   |                             ^^^
+   |                             ^^^ this module is private
+   |
+note: the module `foo` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:12:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error[E0603]: module `foo` is private
   --> $DIR/xcrate-private-by-default.rs:37:29
    |
 LL |     static_priv_by_default::foo::b;
-   |                             ^^^
+   |                             ^^^ this module is private
+   |
+note: the module `foo` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:12:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error[E0603]: module `foo` is private
   --> $DIR/xcrate-private-by-default.rs:39:29
    |
 LL |     static_priv_by_default::foo::c;
-   |                             ^^^
+   |                             ^^^ this module is private
+   |
+note: the module `foo` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:12:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error[E0603]: module `foo` is private
   --> $DIR/xcrate-private-by-default.rs:41:35
    |
 LL |     foo::<static_priv_by_default::foo::d>();
-   |                                   ^^^
+   |                                   ^^^ this module is private
+   |
+note: the module `foo` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:12:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error[E0603]: module `foo` is private
   --> $DIR/xcrate-private-by-default.rs:43:35
    |
 LL |     foo::<static_priv_by_default::foo::e>();
-   |                                   ^^^
+   |                                   ^^^ this module is private
+   |
+note: the module `foo` is defined here
+  --> $DIR/auxiliary/static_priv_by_default.rs:12:1
+   |
+LL | mod foo {
+   | ^^^^^^^
 
 error: aborting due to 10 previous errors
 
index 920cdb59e1edf2c4cb2f266fa521f12c1b97a499..fd0428f622feee209e6014b802f5717d48d9e978 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 920cdb59e1edf2c4cb2f266fa521f12c1b97a499
+Subproject commit fd0428f622feee209e6014b802f5717d48d9e978