about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRich Kadel <richkadel@google.com>2020-06-15 16:44:23 -0700
committerGitHub <noreply@github.com>2020-06-15 16:44:23 -0700
commit395256a5dd74ccef046083d6e025a6d046379040 (patch)
treeb5cfdca90f9475d68f44b52f0df8b8d417733287
parentd139a720a2c0ad7066c43edad6ec6c2aa9613740 (diff)
parentf315c35a77e40bd11ce81fedc0556be0f410bbf4 (diff)
downloadrust-395256a5dd74ccef046083d6e025a6d046379040.tar.gz
rust-395256a5dd74ccef046083d6e025a6d046379040.zip
Merge pull request #3 from rust-lang/master
update from origin 2020-06-15
-rw-r--r--.github/workflows/ci.yml14
-rw-r--r--Cargo.lock10
-rw-r--r--config.toml.example2
-rw-r--r--src/bootstrap/builder.rs3
-rw-r--r--src/bootstrap/compile.rs8
-rw-r--r--src/bootstrap/dist.rs8
-rw-r--r--src/bootstrap/mk/Makefile.in10
-rw-r--r--src/bootstrap/native.rs2
-rw-r--r--src/bootstrap/test.rs12
-rw-r--r--src/bootstrap/tool.rs30
-rw-r--r--src/ci/azure-pipelines/auto.yml4
-rw-r--r--src/ci/azure-pipelines/steps/run.yml4
-rw-r--r--src/ci/docker/scripts/musl-toolchain.sh10
-rw-r--r--src/ci/docker/scripts/musl.sh2
-rw-r--r--src/ci/docker/wasm32/Dockerfile3
-rw-r--r--src/ci/github-actions/ci.yml10
-rwxr-xr-xsrc/ci/scripts/install-msys2-packages.sh27
-rwxr-xr-xsrc/ci/scripts/install-msys2.sh35
-rw-r--r--src/doc/rustdoc/src/documentation-tests.md2
-rw-r--r--src/doc/unstable-book/src/library-features/asm.md6
-rw-r--r--src/etc/debugger_pretty_printers_common.py401
-rw-r--r--src/etc/gdb_load_rust_pretty_printers.py4
-rw-r--r--src/etc/gdb_lookup.py92
-rw-r--r--src/etc/gdb_providers.py385
-rwxr-xr-xsrc/etc/gdb_rust_pretty_printing.py466
-rw-r--r--src/etc/lldb_commands19
-rw-r--r--src/etc/lldb_lookup.py115
-rw-r--r--src/etc/lldb_providers.py715
-rw-r--r--src/etc/lldb_rust_formatters.py305
-rwxr-xr-xsrc/etc/rust-lldb10
-rw-r--r--src/etc/rust_types.py113
-rw-r--r--src/liballoc/rc.rs4
-rw-r--r--src/liballoc/rc/tests.rs4
-rw-r--r--src/liballoc/sync/tests.rs4
-rw-r--r--src/liballoc/tests/str.rs4
-rw-r--r--src/liballoc/tests/vec.rs18
-rw-r--r--src/liballoc/vec.rs10
-rw-r--r--src/libcore/cell.rs36
-rw-r--r--src/libcore/char/convert.rs11
-rw-r--r--src/libcore/char/methods.rs62
-rw-r--r--src/libcore/convert/num.rs6
-rw-r--r--src/libcore/future/mod.rs1
-rw-r--r--src/libcore/iter/traits/iterator.rs4
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/num/mod.rs69
-rw-r--r--src/libcore/num/wrapping.rs7
-rw-r--r--src/libcore/option.rs8
-rw-r--r--src/libcore/ptr/const_ptr.rs4
-rw-r--r--src/libcore/ptr/mod.rs18
-rw-r--r--src/libcore/slice/mod.rs12
-rw-r--r--src/libcore/str/mod.rs18
-rw-r--r--src/libcore/str/pattern.rs55
-rw-r--r--src/libcore/sync/atomic.rs8
-rw-r--r--src/libcore/tests/num/mod.rs32
-rw-r--r--src/libcore/tests/ptr.rs2
-rw-r--r--src/libcore/tests/slice.rs4
-rw-r--r--src/librustc_apfloat/lib.rs6
-rw-r--r--src/librustc_apfloat/tests/ieee.rs4
-rw-r--r--src/librustc_arena/lib.rs29
-rw-r--r--src/librustc_ast/ast.rs24
-rw-r--r--src/librustc_ast/mut_visit.rs5
-rw-r--r--src/librustc_ast/tokenstream.rs2
-rw-r--r--src/librustc_ast/util/parser.rs2
-rw-r--r--src/librustc_ast/visit.rs2
-rw-r--r--src/librustc_ast_lowering/expr.rs34
-rw-r--r--src/librustc_ast_lowering/item.rs80
-rw-r--r--src/librustc_ast_lowering/lib.rs150
-rw-r--r--src/librustc_ast_passes/feature_gate.rs8
-rw-r--r--src/librustc_ast_pretty/pprust.rs10
-rw-r--r--src/librustc_builtin_macros/asm.rs49
-rw-r--r--src/librustc_builtin_macros/deriving/generic/ty.rs6
-rw-r--r--src/librustc_builtin_macros/source_util.rs5
-rw-r--r--src/librustc_codegen_llvm/abi.rs2
-rw-r--r--src/librustc_codegen_llvm/back/write.rs22
-rw-r--r--src/librustc_codegen_llvm/llvm/diagnostic.rs12
-rw-r--r--src/librustc_codegen_llvm/llvm/ffi.rs15
-rw-r--r--src/librustc_codegen_ssa/back/write.rs20
-rw-r--r--src/librustc_codegen_ssa/mir/block.rs20
-rw-r--r--src/librustc_codegen_ssa/mir/constant.rs2
-rw-r--r--src/librustc_data_structures/base_n/tests.rs4
-rw-r--r--src/librustc_error_codes/error_codes.rs3
-rw-r--r--src/librustc_error_codes/error_codes/E0446.md32
-rw-r--r--src/librustc_error_codes/error_codes/E0493.md12
-rw-r--r--src/librustc_error_codes/error_codes/E0642.md2
-rw-r--r--src/librustc_error_codes/error_codes/E0648.md11
-rw-r--r--src/librustc_error_codes/error_codes/E0666.md18
-rw-r--r--src/librustc_error_codes/error_codes/E0724.md24
-rw-r--r--src/librustc_error_codes/error_codes/E0762.md13
-rw-r--r--src/librustc_errors/annotate_snippet_emitter_writer.rs8
-rw-r--r--src/librustc_errors/diagnostic.rs23
-rw-r--r--src/librustc_errors/diagnostic_builder.rs13
-rw-r--r--src/librustc_errors/lib.rs5
-rw-r--r--src/librustc_expand/base.rs3
-rw-r--r--src/librustc_expand/build.rs2
-rw-r--r--src/librustc_expand/mbe/macro_check.rs7
-rw-r--r--src/librustc_expand/mbe/macro_parser.rs4
-rw-r--r--src/librustc_expand/mbe/macro_rules.rs12
-rw-r--r--src/librustc_expand/mbe/quoted.rs14
-rw-r--r--src/librustc_expand/proc_macro_server.rs8
-rw-r--r--src/librustc_feature/active.rs6
-rw-r--r--src/librustc_hir/arena.rs70
-rw-r--r--src/librustc_hir/def.rs8
-rw-r--r--src/librustc_hir/definitions.rs6
-rw-r--r--src/librustc_hir/hir.rs27
-rw-r--r--src/librustc_hir/intravisit.rs8
-rw-r--r--src/librustc_hir_pretty/lib.rs34
-rw-r--r--src/librustc_incremental/persist/dirty_clean.rs1
-rw-r--r--src/librustc_infer/infer/canonical/query_response.rs2
-rw-r--r--src/librustc_infer/infer/error_reporting/mod.rs4
-rw-r--r--src/librustc_infer/infer/error_reporting/need_type_info.rs8
-rw-r--r--src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs3
-rw-r--r--src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs3
-rw-r--r--src/librustc_interface/callbacks.rs2
-rw-r--r--src/librustc_interface/passes.rs21
-rw-r--r--src/librustc_lexer/src/lib.rs4
-rw-r--r--src/librustc_lexer/src/unescape.rs2
-rw-r--r--src/librustc_lint/array_into_iter.rs2
-rw-r--r--src/librustc_lint/builtin.rs6
-rw-r--r--src/librustc_lint/types.rs124
-rw-r--r--src/librustc_lint/unused.rs2
-rw-r--r--src/librustc_llvm/build.rs1
-rw-r--r--src/librustc_llvm/lib.rs8
-rw-r--r--src/librustc_macros/src/query.rs4
-rw-r--r--src/librustc_metadata/creader.rs2
-rw-r--r--src/librustc_metadata/lib.rs2
-rw-r--r--src/librustc_metadata/rmeta/decoder.rs23
-rw-r--r--src/librustc_metadata/rmeta/encoder.rs58
-rw-r--r--src/librustc_metadata/rmeta/mod.rs5
-rw-r--r--src/librustc_middle/arena.rs76
-rw-r--r--src/librustc_middle/dep_graph/dep_node.rs27
-rw-r--r--src/librustc_middle/hir/map/mod.rs45
-rw-r--r--src/librustc_middle/hir/mod.rs20
-rw-r--r--src/librustc_middle/lib.rs2
-rw-r--r--src/librustc_middle/lint.rs4
-rw-r--r--src/librustc_middle/mir/mod.rs56
-rw-r--r--src/librustc_middle/mir/query.rs10
-rw-r--r--src/librustc_middle/mir/type_foldable.rs3
-rw-r--r--src/librustc_middle/mir/visit.rs5
-rw-r--r--src/librustc_middle/query/mod.rs19
-rw-r--r--src/librustc_middle/traits/specialization_graph.rs17
-rw-r--r--src/librustc_middle/ty/codec.rs142
-rw-r--r--src/librustc_middle/ty/error.rs4
-rw-r--r--src/librustc_middle/ty/layout.rs2
-rw-r--r--src/librustc_middle/ty/mod.rs43
-rw-r--r--src/librustc_middle/ty/print/pretty.rs14
-rw-r--r--src/librustc_middle/ty/query/on_disk_cache.rs60
-rw-r--r--src/librustc_middle/ty/query/profiling_support.rs41
-rw-r--r--src/librustc_middle/ty/query/values.rs20
-rw-r--r--src/librustc_middle/ty/relate.rs15
-rw-r--r--src/librustc_middle/ty/sty.rs7
-rw-r--r--src/librustc_middle/ty/util.rs62
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs78
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs2
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/mod.rs150
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/move_errors.rs2
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs4
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/region_errors.rs57
-rw-r--r--src/librustc_mir/borrow_check/invalidation.rs3
-rw-r--r--src/librustc_mir/borrow_check/mod.rs35
-rw-r--r--src/librustc_mir/borrow_check/nll.rs7
-rw-r--r--src/librustc_mir/borrow_check/path_utils.rs38
-rw-r--r--src/librustc_mir/borrow_check/region_infer/dump_mir.rs13
-rw-r--r--src/librustc_mir/borrow_check/region_infer/mod.rs18
-rw-r--r--src/librustc_mir/borrow_check/type_check/free_region_relations.rs8
-rw-r--r--src/librustc_mir/borrow_check/type_check/mod.rs27
-rw-r--r--src/librustc_mir/const_eval/error.rs5
-rw-r--r--src/librustc_mir/const_eval/eval_queries.rs33
-rw-r--r--src/librustc_mir/dataflow/framework/direction.rs2
-rw-r--r--src/librustc_mir/dataflow/framework/tests.rs2
-rw-r--r--src/librustc_mir/dataflow/move_paths/builder.rs3
-rw-r--r--src/librustc_mir/interpret/cast.rs7
-rw-r--r--src/librustc_mir/interpret/eval_context.rs35
-rw-r--r--src/librustc_mir/interpret/intern.rs5
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs4
-rw-r--r--src/librustc_mir/interpret/intrinsics/caller_location.rs39
-rw-r--r--src/librustc_mir/interpret/memory.rs20
-rw-r--r--src/librustc_mir/interpret/operand.rs4
-rw-r--r--src/librustc_mir/interpret/place.rs48
-rw-r--r--src/librustc_mir/interpret/step.rs2
-rw-r--r--src/librustc_mir/interpret/terminator.rs1
-rw-r--r--src/librustc_mir/interpret/traits.rs26
-rw-r--r--src/librustc_mir/monomorphize/collector.rs16
-rw-r--r--src/librustc_mir/shim.rs2
-rw-r--r--src/librustc_mir/transform/check_consts/mod.rs1
-rw-r--r--src/librustc_mir/transform/check_consts/ops.rs16
-rw-r--r--src/librustc_mir/transform/check_consts/post_drop_elaboration.rs119
-rw-r--r--src/librustc_mir/transform/check_consts/qualifs.rs6
-rw-r--r--src/librustc_mir/transform/check_consts/validation.rs41
-rw-r--r--src/librustc_mir/transform/check_packed_ref.rs2
-rw-r--r--src/librustc_mir/transform/const_prop.rs23
-rw-r--r--src/librustc_mir/transform/mod.rs49
-rw-r--r--src/librustc_mir/transform/nrvo.rs4
-rw-r--r--src/librustc_mir/transform/promote_consts.rs3
-rw-r--r--src/librustc_mir/transform/qualify_min_const_fn.rs9
-rw-r--r--src/librustc_mir/transform/simplify_try.rs10
-rw-r--r--src/librustc_mir/util/elaborate_drops.rs2
-rw-r--r--src/librustc_mir/util/pretty.rs22
-rw-r--r--src/librustc_mir_build/build/expr/into.rs9
-rw-r--r--src/librustc_mir_build/build/matches/mod.rs48
-rw-r--r--src/librustc_mir_build/build/matches/simplify.rs4
-rw-r--r--src/librustc_mir_build/build/matches/test.rs1
-rw-r--r--src/librustc_mir_build/hair/cx/expr.rs37
-rw-r--r--src/librustc_mir_build/hair/mod.rs5
-rw-r--r--src/librustc_mir_build/hair/pattern/_match.rs544
-rw-r--r--src/librustc_mir_build/hair/pattern/const_to_pat.rs5
-rw-r--r--src/librustc_parse/lexer/mod.rs12
-rw-r--r--src/librustc_parse/parser/diagnostics.rs2
-rw-r--r--src/librustc_parse/parser/expr.rs6
-rw-r--r--src/librustc_parse/parser/generics.rs9
-rw-r--r--src/librustc_parse/parser/mod.rs6
-rw-r--r--src/librustc_passes/check_attr.rs2
-rw-r--r--src/librustc_passes/dead.rs4
-rw-r--r--src/librustc_passes/intrinsicck.rs2
-rw-r--r--src/librustc_passes/layout_test.rs7
-rw-r--r--src/librustc_passes/liveness.rs2
-rw-r--r--src/librustc_passes/reachable.rs4
-rw-r--r--src/librustc_privacy/lib.rs16
-rw-r--r--src/librustc_query_system/dep_graph/dep_node.rs9
-rw-r--r--src/librustc_query_system/lib.rs2
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs14
-rw-r--r--src/librustc_resolve/diagnostics.rs14
-rw-r--r--src/librustc_resolve/late.rs2
-rw-r--r--src/librustc_resolve/late/diagnostics.rs5
-rw-r--r--src/librustc_resolve/late/lifetimes.rs79
-rw-r--r--src/librustc_resolve/lib.rs3
-rw-r--r--src/librustc_resolve/macros.rs18
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs84
-rw-r--r--src/librustc_save_analysis/lib.rs95
-rw-r--r--src/librustc_save_analysis/sig.rs26
-rw-r--r--src/librustc_serialize/lib.rs2
-rw-r--r--src/librustc_serialize/serialize.rs36
-rw-r--r--src/librustc_session/config.rs2
-rw-r--r--src/librustc_session/lint/builtin.rs1
-rw-r--r--src/librustc_session/parse.rs4
-rw-r--r--src/librustc_session/session.rs3
-rw-r--r--src/librustc_span/def_id.rs2
-rw-r--r--src/librustc_span/hygiene.rs13
-rw-r--r--src/librustc_span/lib.rs16
-rw-r--r--src/librustc_span/source_map.rs4
-rw-r--r--src/librustc_span/symbol.rs2
-rw-r--r--src/librustc_target/abi/call/avr.rs59
-rw-r--r--src/librustc_target/abi/call/mod.rs4
-rw-r--r--src/librustc_target/spec/aarch64_apple_ios.rs2
-rw-r--r--src/librustc_target/spec/aarch64_apple_tvos.rs2
-rw-r--r--src/librustc_target/spec/abi.rs8
-rw-r--r--src/librustc_target/spec/apple_sdk_base.rs2
-rw-r--r--src/librustc_target/spec/avr_unknown_unknown.rs17
-rw-r--r--src/librustc_target/spec/freestanding_base.rs30
-rw-r--r--src/librustc_target/spec/mod.rs3
-rw-r--r--src/librustc_target/spec/windows_gnu_base.rs9
-rw-r--r--src/librustc_trait_selection/infer.rs4
-rw-r--r--src/librustc_trait_selection/lib.rs1
-rw-r--r--src/librustc_trait_selection/opaque_types.rs96
-rw-r--r--src/librustc_trait_selection/traits/error_reporting/mod.rs45
-rw-r--r--src/librustc_trait_selection/traits/mod.rs2
-rw-r--r--src/librustc_trait_selection/traits/project.rs11
-rw-r--r--src/librustc_trait_selection/traits/select/candidate_assembly.rs10
-rw-r--r--src/librustc_trait_selection/traits/select/mod.rs8
-rw-r--r--src/librustc_trait_selection/traits/structural_match.rs46
-rw-r--r--src/librustc_ty/ty.rs2
-rw-r--r--src/librustc_typeck/astconv.rs27
-rw-r--r--src/librustc_typeck/check/coercion.rs4
-rw-r--r--src/librustc_typeck/check/compare_method.rs2
-rw-r--r--src/librustc_typeck/check/demand.rs455
-rw-r--r--src/librustc_typeck/check/expr.rs27
-rw-r--r--src/librustc_typeck/check/method/probe.rs5
-rw-r--r--src/librustc_typeck/check/method/suggest.rs4
-rw-r--r--src/librustc_typeck/check/mod.rs26
-rw-r--r--src/librustc_typeck/check/op.rs8
-rw-r--r--src/librustc_typeck/check/wfcheck.rs191
-rw-r--r--src/librustc_typeck/check/writeback.rs2
-rw-r--r--src/librustc_typeck/collect.rs51
-rw-r--r--src/librustc_typeck/collect/type_of.rs91
-rw-r--r--src/librustc_typeck/expr_use_visitor.rs2
-rw-r--r--src/librustc_typeck/impl_wf_check.rs7
-rw-r--r--src/librustdoc/clean/mod.rs7
-rw-r--r--src/librustdoc/html/sources.rs2
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs102
-rw-r--r--src/librustdoc/test.rs6
-rw-r--r--src/libstd/Cargo.toml2
-rw-r--r--src/libstd/f32.rs57
-rw-r--r--src/libstd/f64.rs183
-rw-r--r--src/libstd/ffi/c_str.rs187
-rw-r--r--src/libstd/ffi/mod.rs2
-rw-r--r--src/libstd/io/buffered.rs10
-rw-r--r--src/libstd/io/cursor.rs2
-rw-r--r--src/libstd/net/addr.rs45
-rw-r--r--src/libstd/num.rs37
-rw-r--r--src/libstd/sync/condvar.rs1
-rw-r--r--src/libstd/sync/mpsc/mod.rs3
-rw-r--r--src/libstd/sync/mutex.rs54
-rw-r--r--src/libstd/sys/cloudabi/condvar.rs2
-rw-r--r--src/libstd/sys/hermit/condvar.rs2
-rw-r--r--src/libstd/sys/hermit/net.rs131
-rw-r--r--src/libstd/sys/unix/android.rs2
-rw-r--r--src/libstd/sys/unix/condvar.rs8
-rw-r--r--src/libstd/sys/unix/ext/net.rs2
-rw-r--r--src/libstd/sys/unix/fd.rs10
-rw-r--r--src/libstd/sys/unix/fs.rs2
-rw-r--r--src/libstd/sys/unix/net.rs6
-rw-r--r--src/libstd/sys/unix/thread.rs2
-rw-r--r--src/libstd/sys/vxworks/condvar.rs8
-rw-r--r--src/libstd/sys/vxworks/fd.rs6
-rw-r--r--src/libstd/sys/vxworks/net.rs6
-rw-r--r--src/libstd/sys/vxworks/thread.rs2
-rw-r--r--src/libstd/sys/wasi/mod.rs2
-rw-r--r--src/libstd/sys/wasi/thread.rs2
-rw-r--r--src/libstd/sys/wasm/condvar_atomics.rs4
-rw-r--r--src/libstd/sys/wasm/thread.rs2
-rw-r--r--src/libstd/sys/windows/handle.rs10
-rw-r--r--src/libstd/sys/windows/io.rs4
-rw-r--r--src/libstd/sys/windows/mod.rs2
-rw-r--r--src/libstd/sys/windows/net.rs8
-rw-r--r--src/libstd/sys_common/net.rs6
-rw-r--r--src/libstd/thread/mod.rs1
-rw-r--r--src/libstd/time.rs4
-rw-r--r--src/libunwind/build.rs6
-rw-r--r--src/rustllvm/PassWrapper.cpp7
-rw-r--r--src/rustllvm/RustWrapper.cpp47
-rw-r--r--src/test/debuginfo/associated-types.rs4
-rw-r--r--src/test/debuginfo/borrowed-struct.rs12
-rw-r--r--src/test/debuginfo/borrowed-tuple.rs12
-rw-r--r--src/test/debuginfo/box.rs4
-rw-r--r--src/test/debuginfo/boxed-struct.rs8
-rw-r--r--src/test/debuginfo/by-value-self-argument-in-trait-impl.rs8
-rw-r--r--src/test/debuginfo/c-style-enum-in-composite.rs29
-rw-r--r--src/test/debuginfo/cross-crate-spans.rs8
-rw-r--r--src/test/debuginfo/destructured-fn-argument.rs32
-rw-r--r--src/test/debuginfo/destructured-for-loop-variable.rs8
-rw-r--r--src/test/debuginfo/destructured-local.rs32
-rw-r--r--src/test/debuginfo/empty-string.rs6
-rw-r--r--src/test/debuginfo/enum-thinlto.rs3
-rw-r--r--src/test/debuginfo/evec-in-struct.rs20
-rw-r--r--src/test/debuginfo/function-prologue-stepping-regular.rs4
-rw-r--r--src/test/debuginfo/gdb-pretty-struct-and-enums.rs4
-rw-r--r--src/test/debuginfo/generator-objects.rs8
-rw-r--r--src/test/debuginfo/generic-function.rs4
-rw-r--r--src/test/debuginfo/generic-method-on-generic-struct.rs20
-rw-r--r--src/test/debuginfo/issue-22656.rs9
-rw-r--r--src/test/debuginfo/issue-57822.rs4
-rw-r--r--src/test/debuginfo/method-on-struct.rs10
-rw-r--r--src/test/debuginfo/method-on-trait.rs20
-rw-r--r--src/test/debuginfo/method-on-tuple-struct.rs20
-rw-r--r--src/test/debuginfo/packed-struct-with-destructor.rs32
-rw-r--r--src/test/debuginfo/packed-struct.rs16
-rw-r--r--src/test/debuginfo/pretty-huge-vec.rs7
-rw-r--r--src/test/debuginfo/pretty-std-collections.rs66
-rw-r--r--src/test/debuginfo/pretty-std.rs3
-rw-r--r--src/test/debuginfo/pretty-uninitialized-vec.rs4
-rw-r--r--src/test/debuginfo/rc_arc.rs37
-rw-r--r--src/test/debuginfo/self-in-default-method.rs10
-rw-r--r--src/test/debuginfo/self-in-generic-default-method.rs10
-rw-r--r--src/test/debuginfo/simple-struct.rs24
-rw-r--r--src/test/debuginfo/simple-tuple.rs28
-rw-r--r--src/test/debuginfo/struct-in-struct.rs32
-rw-r--r--src/test/debuginfo/struct-with-destructor.rs16
-rw-r--r--src/test/debuginfo/tuple-in-tuple.rs28
-rw-r--r--src/test/debuginfo/tuple-struct.rs24
-rw-r--r--src/test/debuginfo/union-smoke.rs6
-rw-r--r--src/test/debuginfo/var-captured-in-nested-closure.rs16
-rw-r--r--src/test/debuginfo/var-captured-in-sendable-closure.rs4
-rw-r--r--src/test/debuginfo/var-captured-in-stack-closure.rs16
-rw-r--r--src/test/debuginfo/vec-slices.rs22
-rw-r--r--src/test/debuginfo/vec.rs4
-rw-r--r--src/test/mir-opt/const_prop/bad_op_div_by_zero/rustc.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/const_prop/bad_op_mod_by_zero/rustc.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/simplify-arm/rustc.id.SimplifyArmIdentity.diff17
-rw-r--r--src/test/mir-opt/simplify-arm/rustc.id.SimplifyBranchSame.diff9
-rw-r--r--src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyArmIdentity.diff34
-rw-r--r--src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyBranchSame.diff43
-rw-r--r--src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyArmIdentity.diff19
-rw-r--r--src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyBranchSame.diff10
-rw-r--r--src/test/mir-opt/simplify_try_if_let/rustc.{{impl}}-append.SimplifyArmIdentity.diff11
-rw-r--r--src/test/pretty/asm.pp1
-rw-r--r--src/test/pretty/asm.rs1
-rw-r--r--src/test/rustdoc-ui/doctest-output.rs15
-rw-r--r--src/test/rustdoc-ui/doctest-output.stdout7
-rw-r--r--src/test/rustdoc/auxiliary/intra-link-proc-macro-macro.rs35
-rw-r--r--src/test/rustdoc/auxiliary/issue-73061.rs17
-rw-r--r--src/test/rustdoc/intra-link-proc-macro.rs27
-rw-r--r--src/test/rustdoc/issue-73061-cross-crate-opaque-assoc-type.rs14
-rw-r--r--src/test/rustdoc/show-const-contents.rs8
-rw-r--r--src/test/ui-fulldeps/pprust-expr-roundtrip.rs4
-rw-r--r--src/test/ui/asm/bad-template.rs2
-rw-r--r--src/test/ui/asm/bad-template.stderr18
-rw-r--r--src/test/ui/asm/parse-error.stderr2
-rw-r--r--src/test/ui/asm/srcloc.rs3
-rw-r--r--src/test/ui/asm/srcloc.stderr14
-rw-r--r--src/test/ui/asm/sym.rs52
-rw-r--r--src/test/ui/associated-type-bounds/duplicate.rs6
-rw-r--r--src/test/ui/associated-type-bounds/duplicate.stderr198
-rw-r--r--src/test/ui/async-await/issue-69446-fnmut-capture.rs22
-rw-r--r--src/test/ui/async-await/issue-69446-fnmut-capture.stderr19
-rw-r--r--src/test/ui/async-await/issue-73050.rs12
-rw-r--r--src/test/ui/binop/binop-consume-args.stderr70
-rw-r--r--src/test/ui/binop/binop-move-semantics.stderr21
-rw-r--r--src/test/ui/borrowck/borrowck-describe-lvalue.stderr3
-rw-r--r--src/test/ui/borrowck/borrowck-unboxed-closures.stderr7
-rw-r--r--src/test/ui/closure_context/issue-42065.stderr7
-rw-r--r--src/test/ui/codemap_tests/tab_3.stderr8
-rw-r--r--src/test/ui/codemap_tests/unicode.stderr2
-rw-r--r--src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr2
-rw-r--r--src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.rs20
-rw-r--r--src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.stderr10
-rw-r--r--src/test/ui/consts/const-eval/infinite_loop.stderr4
-rw-r--r--src/test/ui/consts/const-eval/shift_overflow.rs2
-rw-r--r--src/test/ui/consts/const-eval/shift_overflow.stderr4
-rw-r--r--src/test/ui/consts/const-int-arithmetic.rs24
-rw-r--r--src/test/ui/consts/const-int-conversion-rpass.rs4
-rw-r--r--src/test/ui/consts/const-int-conversion.rs2
-rw-r--r--src/test/ui/consts/const-int-conversion.stderr4
-rw-r--r--src/test/ui/consts/const-int-overflowing-rpass.rs8
-rw-r--r--src/test/ui/consts/const-int-pow-rpass.rs6
-rw-r--r--src/test/ui/consts/const-int-saturating-arith.rs32
-rw-r--r--src/test/ui/consts/const-int-unchecked.rs4
-rw-r--r--src/test/ui/consts/const-int-unchecked.stderr8
-rw-r--r--src/test/ui/consts/const-int-wrapping-rpass.rs8
-rw-r--r--src/test/ui/consts/const-match-check.eval1.stderr4
-rw-r--r--src/test/ui/consts/const-match-check.eval2.stderr4
-rw-r--r--src/test/ui/consts/const-match-check.matchck.stderr16
-rw-r--r--src/test/ui/consts/const-pattern-irrefutable.rs6
-rw-r--r--src/test/ui/consts/const-pattern-irrefutable.stderr6
-rw-r--r--src/test/ui/consts/const-size_of-cycle.stderr4
-rw-r--r--src/test/ui/consts/const_limit/const_eval_limit_reached.stderr23
-rw-r--r--src/test/ui/consts/control-flow/drop-fail.precise.stderr15
-rw-r--r--src/test/ui/consts/control-flow/drop-fail.rs (renamed from src/test/ui/consts/control-flow/drop-failure.rs)13
-rw-r--r--src/test/ui/consts/control-flow/drop-fail.stock.stderr (renamed from src/test/ui/consts/control-flow/drop-failure.stderr)8
-rw-r--r--src/test/ui/consts/control-flow/drop-pass.rs (renamed from src/test/ui/consts/control-flow/drop-success.rs)2
-rw-r--r--src/test/ui/consts/control-flow/drop-precise.rs20
-rw-r--r--src/test/ui/consts/enum-discr-type-err.stderr8
-rw-r--r--src/test/ui/consts/miri_unleashed/ptr_arith.rs5
-rw-r--r--src/test/ui/consts/miri_unleashed/ptr_arith.stderr4
-rw-r--r--src/test/ui/consts/recursive-zst-static.default.stderr4
-rw-r--r--src/test/ui/consts/recursive-zst-static.unleash.stderr4
-rw-r--r--src/test/ui/consts/uninhabited-const-issue-61744.rs4
-rw-r--r--src/test/ui/consts/uninhabited-const-issue-61744.stderr8
-rw-r--r--src/test/ui/derived-errors/issue-31997-1.stderr4
-rw-r--r--src/test/ui/enum-discriminant/issue-70509-partial_eq.rs2
-rw-r--r--src/test/ui/enum-discriminant/repr128.rs16
-rw-r--r--src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.rs9
-rw-r--r--src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr12
-rw-r--r--src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs24
-rw-r--r--src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr70
-rw-r--r--src/test/ui/ffi_returns_twice.stderr1
-rw-r--r--src/test/ui/for/for-loop-refutable-pattern-error-message.stderr4
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr140
-rw-r--r--src/test/ui/hygiene/no_implicit_prelude.stderr4
-rw-r--r--src/test/ui/hygiene/unpretty-debug.stdout4
-rw-r--r--src/test/ui/impl-trait-in-bindings-issue-73003.rs8
-rw-r--r--src/test/ui/impl-trait-in-bindings-issue-73003.stderr11
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak.rs2
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak.stderr188
-rw-r--r--src/test/ui/impl-trait/auto-trait.rs14
-rw-r--r--src/test/ui/impl-trait/auto-trait.stderr8
-rw-r--r--src/test/ui/impl-trait/issue-55872-1.stderr8
-rw-r--r--src/test/ui/impl-trait/issue-55872-2.stderr4
-rw-r--r--src/test/ui/impl-trait/issue-60473.rs10
-rw-r--r--src/test/ui/impl-trait/issue-60473.stderr16
-rw-r--r--src/test/ui/impl-trait/issue-67166.rs4
-rw-r--r--src/test/ui/impl-trait/issue-67166.stderr16
-rw-r--r--src/test/ui/impl-trait/negative-reasoning.rs15
-rw-r--r--src/test/ui/impl-trait/negative-reasoning.stderr10
-rw-r--r--src/test/ui/impl-trait/where-allowed.stderr12
-rw-r--r--src/test/ui/infinite/infinite-recursion-const-fn.stderr8
-rw-r--r--src/test/ui/infinite/infinite-tag-type-recursion.stderr5
-rw-r--r--src/test/ui/issues/issue-12127.stderr7
-rw-r--r--src/test/ui/issues/issue-17431-1.stderr7
-rw-r--r--src/test/ui/issues/issue-17431-2.stderr14
-rw-r--r--src/test/ui/issues/issue-17431-3.stderr7
-rw-r--r--src/test/ui/issues/issue-17431-4.stderr7
-rw-r--r--src/test/ui/issues/issue-17431-5.stderr7
-rw-r--r--src/test/ui/issues/issue-17431-6.stderr5
-rw-r--r--src/test/ui/issues/issue-17431-7.stderr5
-rw-r--r--src/test/ui/issues/issue-17546.stderr10
-rw-r--r--src/test/ui/issues/issue-20605.stderr4
-rw-r--r--src/test/ui/issues/issue-2718-a.stderr5
-rw-r--r--src/test/ui/issues/issue-3008-1.stderr5
-rw-r--r--src/test/ui/issues/issue-3008-2.stderr7
-rw-r--r--src/test/ui/issues/issue-3008-3.stderr5
-rw-r--r--src/test/ui/issues/issue-31910.stderr5
-rw-r--r--src/test/ui/issues/issue-32326.stderr5
-rw-r--r--src/test/ui/issues/issue-33941.rs1
-rw-r--r--src/test/ui/issues/issue-33941.stderr12
-rw-r--r--src/test/ui/issues/issue-34721.stderr9
-rw-r--r--src/test/ui/issues/issue-3779.stderr7
-rw-r--r--src/test/ui/issues/issue-40510-1.stderr8
-rw-r--r--src/test/ui/issues/issue-40510-3.stderr4
-rw-r--r--src/test/ui/issues/issue-44216-add-instant.rs2
-rw-r--r--src/test/ui/issues/issue-44216-add-system-time.rs2
-rw-r--r--src/test/ui/issues/issue-44216-sub-instant.rs2
-rw-r--r--src/test/ui/issues/issue-44216-sub-system-time.rs2
-rw-r--r--src/test/ui/issues/issue-49824.stderr3
-rw-r--r--src/test/ui/issues/issue-57271.stderr10
-rw-r--r--src/test/ui/issues/issue-60662.stdout2
-rw-r--r--src/test/ui/issues/issue-61108.stderr8
-rw-r--r--src/test/ui/issues/issue-64559.stderr8
-rw-r--r--src/test/ui/issues/issue-72554.stderr5
-rw-r--r--src/test/ui/issues/issue-72839-error-overflow.rs19
-rw-r--r--src/test/ui/issues/issue-72839-error-overflow.stderr9
-rw-r--r--src/test/ui/issues/issue-72933-match-stack-overflow.rs5208
-rw-r--r--src/test/ui/issues/issue-8460.rs20
-rw-r--r--src/test/ui/iterators/iter-step-overflow-debug.rs4
-rw-r--r--src/test/ui/iterators/iter-step-overflow-ndebug.rs8
-rw-r--r--src/test/ui/iterators/iter-sum-overflow-debug.rs8
-rw-r--r--src/test/ui/iterators/iter-sum-overflow-ndebug.rs16
-rw-r--r--src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs8
-rw-r--r--src/test/ui/iterators/skip-count-overflow.rs2
-rw-r--r--src/test/ui/lexical-scopes.stderr5
-rw-r--r--src/test/ui/lint/expansion-time-include.rs4
-rw-r--r--src/test/ui/lint/expansion-time.rs23
-rw-r--r--src/test/ui/lint/expansion-time.stderr56
-rw-r--r--src/test/ui/lint/inline-trait-and-foreign-items.stderr4
-rw-r--r--src/test/ui/lint/lint-ctypes-66202.rs17
-rw-r--r--src/test/ui/lint/opaque-ty-ffi-unsafe.rs3
-rw-r--r--src/test/ui/lint/opaque-ty-ffi-unsafe.stderr6
-rw-r--r--src/test/ui/match/issue-72896.rs23
-rw-r--r--src/test/ui/moves/move-fn-self-receiver.rs74
-rw-r--r--src/test/ui/moves/move-fn-self-receiver.stderr158
-rw-r--r--src/test/ui/moves/moves-based-on-type-access-to-field.stderr8
-rw-r--r--src/test/ui/moves/moves-based-on-type-exprs.stderr16
-rw-r--r--src/test/ui/nll/issue-53040.stderr8
-rw-r--r--src/test/ui/no-implicit-prelude-nested.stderr48
-rw-r--r--src/test/ui/no-implicit-prelude.stderr16
-rw-r--r--src/test/ui/numbers-arithmetic/i128.rs2
-rw-r--r--src/test/ui/numbers-arithmetic/int-abs-overflow.rs10
-rw-r--r--src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs4
-rw-r--r--src/test/ui/numbers-arithmetic/promoted_overflow_opt.rs2
-rw-r--r--src/test/ui/numbers-arithmetic/u128.rs4
-rw-r--r--src/test/ui/numeric/const-scope.stderr10
-rw-r--r--src/test/ui/numeric/numeric-cast-binop.fixed320
-rw-r--r--src/test/ui/numeric/numeric-cast-binop.rs320
-rw-r--r--src/test/ui/numeric/numeric-cast-binop.stderr1385
-rw-r--r--src/test/ui/once-cant-call-twice-on-heap.stderr7
-rw-r--r--src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs6
-rw-r--r--src/test/ui/or-patterns/exhaustiveness-non-exhaustive.stderr12
-rw-r--r--src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr8
-rw-r--r--src/test/ui/parser/issue-8537.stderr2
-rw-r--r--src/test/ui/parser/lex-bad-char-literals-4.stderr3
-rw-r--r--src/test/ui/parser/lex-bad-char-literals-7.stderr3
-rw-r--r--src/test/ui/pattern/usefulness/exhaustive_integer_patterns.stderr28
-rw-r--r--src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr4
-rw-r--r--src/test/ui/pattern/usefulness/match-non-exhaustive.stderr4
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-match.rs4
-rw-r--r--src/test/ui/pattern/usefulness/non-exhaustive-match.stderr4
-rw-r--r--src/test/ui/pattern/usefulness/refutable-pattern-errors.rs2
-rw-r--r--src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr4
-rw-r--r--src/test/ui/precise_pointer_size_matching.stderr8
-rw-r--r--src/test/ui/privacy/private-in-public-assoc-ty.rs9
-rw-r--r--src/test/ui/privacy/private-in-public-assoc-ty.stderr25
-rw-r--r--src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr60
-rw-r--r--src/test/ui/proc-macro/empty-where-clause.rs18
-rw-r--r--src/test/ui/proc-macro/empty-where-clause.stderr21
-rw-r--r--src/test/ui/proc-macro/mixed-site-span.stderr4
-rw-r--r--src/test/ui/recursion/recursive-enum.stderr5
-rw-r--r--src/test/ui/recursion/recursive-static-definition.stderr4
-rw-r--r--src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr8
-rw-r--r--src/test/ui/repeat_count.rs3
-rw-r--r--src/test/ui/repeat_count.stderr21
-rw-r--r--src/test/ui/resolve/use_suggestion.stderr8
-rw-r--r--src/test/ui/resolve/use_suggestion_placement.stderr4
-rw-r--r--src/test/ui/rfc-2091-track-caller/call-chain.rs28
-rw-r--r--src/test/ui/save-analysis/issue-68621.stderr4
-rw-r--r--src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs6
-rw-r--r--src/test/ui/simd/simd-intrinsic-generic-bitmask.rs2
-rw-r--r--src/test/ui/simd/simd-intrinsic-generic-reduction.rs2
-rw-r--r--src/test/ui/sized-cycle-note.stderr14
-rw-r--r--src/test/ui/span/E0072.stderr7
-rw-r--r--src/test/ui/span/multiline-span-E0072.stderr7
-rw-r--r--src/test/ui/span/recursive-type-field.stderr19
-rw-r--r--src/test/ui/suggestions/const-pat-non-exaustive-let-new-var.rs2
-rw-r--r--src/test/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr2
-rw-r--r--src/test/ui/traits/trait-alias/issue-60021-assoc-method-resolve.rs19
-rw-r--r--src/test/ui/traits/trait-alias/issue-72415-assoc-const-resolve.rs14
-rw-r--r--src/test/ui/type-alias-impl-trait/bound_reduction2.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr8
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_underconstrained.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr8
-rw-r--r--src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs18
-rw-r--r--src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr15
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs24
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr8
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-60371.stderr8
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-60564.rs7
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-60564.stderr14
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-62000-associate-impl-trait-lifetimes.rs38
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-63279.stderr6
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs22
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr11
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs23
-rw-r--r--src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr6
-rw-r--r--src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr10
-rw-r--r--src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs14
-rw-r--r--src/test/ui/type/type-recursive.stderr7
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr7
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr7
-rw-r--r--src/test/ui/union/union-nonrepresentable.stderr7
-rw-r--r--src/test/ui/unop-move-semantics.stderr7
-rw-r--r--src/test/ui/unsized-locals/borrow-after-move.stderr8
-rw-r--r--src/test/ui/unsized-locals/double-move.stderr8
-rw-r--r--src/test/ui/use/use-after-move-self-based-on-type.stderr8
-rw-r--r--src/test/ui/use/use-after-move-self.stderr8
-rw-r--r--src/test/ui/variance/variance-associated-types2.nll.stderr12
-rw-r--r--src/test/ui/variance/variance-associated-types2.rs17
-rw-r--r--src/test/ui/variance/variance-associated-types2.stderr18
-rw-r--r--src/test/ui/walk-struct-literal-with.stderr8
-rw-r--r--src/test/ui/write-to-static-mut-in-static.stderr4
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/atomic_ordering.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/booleans.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/bytecount.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/checked_conversions.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/consts.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/double_parens.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/duration_subsec.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/entry.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/enum_clike.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/explicit_write.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/format.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/functions.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/get_last_with_len.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/if_let_mutex.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/if_let_some_result.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/infinite_iter.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/len_zero.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_async_fn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/map_clone.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/map_unit_fn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/misc.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_doc.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_inline.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_reference.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/open_options.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/option_env_unwrap.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/path_buf_push_overwrite.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/precedence.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/ranges.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_pattern_matching.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/strings.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/to_digit_is_some.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/types.rs58
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_io_amount.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/useless_conversion.rs2
-rwxr-xr-xsrc/tools/clippy/clippy_lints/src/utils/ast_utils.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/hir_utils.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/inspector.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/mod.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/ptr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/verbose_file_reads.rs4
-rw-r--r--src/tools/clippy/tests/ui/cast.rs10
-rw-r--r--src/tools/clippy/tests/ui/implicit_saturating_sub.rs14
-rw-r--r--src/tools/clippy/tests/ui/implicit_saturating_sub.stderr14
-rw-r--r--src/tools/compiletest/src/header/tests.rs6
-rw-r--r--src/tools/compiletest/src/main.rs8
-rw-r--r--src/tools/compiletest/src/runtest.rs31
-rw-r--r--src/tools/compiletest/src/util.rs3
-rw-r--r--src/tools/unicode-table-generator/src/raw_emitter.rs2
-rw-r--r--triagebot.toml80
677 files changed, 15724 insertions, 5434 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c3c95226aeb..bf3c22744f1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -102,9 +102,6 @@ jobs:
       - name: install MSYS2
         run: src/ci/scripts/install-msys2.sh
         if: success() && !env.SKIP_JOB
-      - name: install MSYS2 packages
-        run: src/ci/scripts/install-msys2-packages.sh
-        if: success() && !env.SKIP_JOB
       - name: install MinGW
         run: src/ci/scripts/install-mingw.sh
         if: success() && !env.SKIP_JOB
@@ -212,9 +209,6 @@ jobs:
       - name: install MSYS2
         run: src/ci/scripts/install-msys2.sh
         if: success() && !env.SKIP_JOB
-      - name: install MSYS2 packages
-        run: src/ci/scripts/install-msys2-packages.sh
-        if: success() && !env.SKIP_JOB
       - name: install MinGW
         run: src/ci/scripts/install-mingw.sh
         if: success() && !env.SKIP_JOB
@@ -434,11 +428,6 @@ jobs:
               NO_DEBUG_ASSERTIONS: 1
               NO_LLVM_ASSERTIONS: 1
             os: windows-latest-xl
-          - name: x86_64-msvc-aux
-            env:
-              RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1
-              RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc"
-            os: windows-latest-xl
           - name: x86_64-msvc-cargo
             env:
               SCRIPT: python x.py test src/tools/cargotest src/tools/cargo
@@ -564,9 +553,6 @@ jobs:
       - name: install MSYS2
         run: src/ci/scripts/install-msys2.sh
         if: success() && !env.SKIP_JOB
-      - name: install MSYS2 packages
-        run: src/ci/scripts/install-msys2-packages.sh
-        if: success() && !env.SKIP_JOB
       - name: install MinGW
         run: src/ci/scripts/install-mingw.sh
         if: success() && !env.SKIP_JOB
diff --git a/Cargo.lock b/Cargo.lock
index 01510b71681..009767934d4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -282,7 +282,7 @@ checksum = "716960a18f978640f25101b5cbf1c6f6b0d3192fab36a2d98ca96f0ecbe41010"
 
 [[package]]
 name = "cargo"
-version = "0.46.0"
+version = "0.47.0"
 dependencies = [
  "anyhow",
  "atty",
@@ -1434,9 +1434,9 @@ dependencies = [
 
 [[package]]
 name = "hermit-abi"
-version = "0.1.13"
+version = "0.1.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71"
+checksum = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909"
 dependencies = [
  "compiler_builtins",
  "libc",
@@ -1848,9 +1848,9 @@ dependencies = [
 
 [[package]]
 name = "libgit2-sys"
-version = "0.12.5+1.0.0"
+version = "0.12.7+1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3eadeec65514971355bf7134967a543f71372f35b53ac6c7143e7bd157f07535"
+checksum = "bcd07968649bcb7b9351ecfde53ca4d27673cccfdf57c84255ec18710f3153e0"
 dependencies = [
  "cc",
  "libc",
diff --git a/config.toml.example b/config.toml.example
index cf8fe4e082a..d995554913f 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -69,7 +69,7 @@
 # the same format as above, but since these targets are experimental, they are
 # not built by default and the experimental Rust compilation targets that depend
 # on them will not work unless the user opts in to building them.
-#experimental-targets = ""
+#experimental-targets = "AVR"
 
 # Cap the number of parallel linker invocations when compiling LLVM.
 # This can be useful when building LLVM with debug info, which significantly
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index ffdd8485181..ea5300bdfc0 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -52,6 +52,8 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash {
     /// it's been assembled.
     type Output: Clone;
 
+    /// Whether this step is run by default as part of its respective phase.
+    /// `true` here can still be overwritten by `should_run` calling `default_condition`.
     const DEFAULT: bool = false;
 
     /// If true, then this rule should be skipped if --target was specified, but --host was not
@@ -371,7 +373,6 @@ impl<'a> Builder<'a> {
                 test::UiFullDeps,
                 test::Rustdoc,
                 test::Pretty,
-                test::RunPassValgrindPretty,
                 test::Crate,
                 test::CrateLibrustc,
                 test::CrateRustdoc,
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index b3999118e3d..c09b73b0420 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -983,7 +983,13 @@ pub fn stream_cargo(
     for line in stdout.lines() {
         let line = t!(line);
         match serde_json::from_str::<CargoMessage<'_>>(&line) {
-            Ok(msg) => cb(msg),
+            Ok(msg) => {
+                if builder.config.json_output {
+                    // Forward JSON to stdout.
+                    println!("{}", line);
+                }
+                cb(msg)
+            }
             // If this was informational, just print it out and continue
             Err(_) => println!("{}", line),
         }
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 5e966d7055b..a752d8045f7 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -619,19 +619,21 @@ impl Step for DebuggerScripts {
             cp_debugger_script("natvis/libcore.natvis");
             cp_debugger_script("natvis/libstd.natvis");
         } else {
-            cp_debugger_script("debugger_pretty_printers_common.py");
+            cp_debugger_script("rust_types.py");
 
             // gdb debugger scripts
             builder.install(&builder.src.join("src/etc/rust-gdb"), &sysroot.join("bin"), 0o755);
             builder.install(&builder.src.join("src/etc/rust-gdbgui"), &sysroot.join("bin"), 0o755);
 
             cp_debugger_script("gdb_load_rust_pretty_printers.py");
-            cp_debugger_script("gdb_rust_pretty_printing.py");
+            cp_debugger_script("gdb_lookup.py");
+            cp_debugger_script("gdb_providers.py");
 
             // lldb debugger scripts
             builder.install(&builder.src.join("src/etc/rust-lldb"), &sysroot.join("bin"), 0o755);
 
-            cp_debugger_script("lldb_rust_formatters.py");
+            cp_debugger_script("lldb_lookup.py");
+            cp_debugger_script("lldb_providers.py");
         }
     }
 }
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index d8c97fc7414..12a1734e21c 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -6,12 +6,6 @@ Q := @
 BOOTSTRAP_ARGS :=
 endif
 
-ifdef EXCLUDE_CARGO
-AUX_ARGS :=
-else
-AUX_ARGS := src/tools/cargo src/tools/cargotest
-endif
-
 BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py
 
 all:
@@ -48,8 +42,8 @@ check:
 	$(Q)$(BOOTSTRAP) test $(BOOTSTRAP_ARGS)
 check-aux:
 	$(Q)$(BOOTSTRAP) test \
-		src/test/run-pass-valgrind/pretty \
-		$(AUX_ARGS) \
+		src/tools/cargo \
+		src/tools/cargotest \
 		$(BOOTSTRAP_ARGS)
 check-bootstrap:
 	$(Q)$(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap_test.py
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 5b6e9534843..252a6316e57 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -144,7 +144,7 @@ impl Step for Llvm {
 
         let llvm_exp_targets = match builder.config.llvm_experimental_targets {
             Some(ref s) => s,
-            None => "",
+            None => "AVR",
         };
 
         let assertions = if builder.config.llvm_assertions { "ON" } else { "OFF" };
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index a99e39ed354..b8c57515658 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -154,6 +154,7 @@ impl Step for Cargotest {
     fn run(self, builder: &Builder<'_>) {
         let compiler = builder.compiler(self.stage, self.host);
         builder.ensure(compile::Rustc { compiler, target: compiler.host });
+        let cargo = builder.ensure(tool::Cargo { compiler, target: compiler.host });
 
         // Note that this is a short, cryptic, and not scoped directory name. This
         // is currently to minimize the length of path on Windows where we otherwise
@@ -165,7 +166,7 @@ impl Step for Cargotest {
         let mut cmd = builder.tool_cmd(Tool::CargoTest);
         try_run(
             builder,
-            cmd.arg(&builder.initial_cargo)
+            cmd.arg(&cargo)
                 .arg(&out_dir)
                 .env("RUSTC", builder.rustc(compiler))
                 .env("RUSTDOC", builder.rustdoc(compiler)),
@@ -553,7 +554,7 @@ impl Step for Clippy {
 
         builder.add_rustc_lib_path(compiler, &mut cargo);
 
-        try_run(builder, &mut cargo.into());
+        builder.run(&mut cargo.into());
     }
 }
 
@@ -929,13 +930,6 @@ host_test!(UiFullDeps { path: "src/test/ui-fulldeps", mode: "ui", suite: "ui-ful
 host_test!(Rustdoc { path: "src/test/rustdoc", mode: "rustdoc", suite: "rustdoc" });
 
 host_test!(Pretty { path: "src/test/pretty", mode: "pretty", suite: "pretty" });
-test!(RunPassValgrindPretty {
-    path: "src/test/run-pass-valgrind/pretty",
-    mode: "pretty",
-    suite: "run-pass-valgrind",
-    default: false,
-    host: true
-});
 
 default_test!(RunMake { path: "src/test/run-make", mode: "run-make", suite: "run-make" });
 
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 6cd9f9029c9..9c95de0a81e 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -595,6 +595,7 @@ macro_rules! tool_extended {
        $toolstate:ident,
        $path:expr,
        $tool_name:expr,
+       stable = $stable:expr,
        $extra_deps:block;)+) => {
         $(
             #[derive(Debug, Clone, Hash, PartialEq, Eq)]
@@ -606,17 +607,22 @@ macro_rules! tool_extended {
 
         impl Step for $name {
             type Output = Option<PathBuf>;
-            const DEFAULT: bool = true;
+            const DEFAULT: bool = true; // Overwritten below
             const ONLY_HOSTS: bool = true;
 
             fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
                 let builder = run.builder;
                 run.path($path).default_condition(
                     builder.config.extended
-                        && builder.config.tools.as_ref().map_or(true, |tools| {
-                            tools.iter().any(|tool| match tool.as_ref() {
-                                "clippy" => $tool_name == "clippy-driver",
-                                x => $tool_name == x,
+                        && builder.config.tools.as_ref().map_or(
+                            // By default, on nightly/dev enable all tools, else only
+                            // build stable tools.
+                            $stable || builder.build.unstable_features(),
+                            // If `tools` is set, search list for this tool.
+                            |tools| {
+                                tools.iter().any(|tool| match tool.as_ref() {
+                                    "clippy" => $tool_name == "clippy-driver",
+                                    x => $tool_name == x,
                             })
                         }),
                 )
@@ -652,12 +658,12 @@ macro_rules! tool_extended {
 // Note: tools need to be also added to `Builder::get_step_descriptions` in `build.rs`
 // to make `./x.py build <tool>` work.
 tool_extended!((self, builder),
-    Cargofmt, rustfmt, "src/tools/rustfmt", "cargo-fmt", {};
-    CargoClippy, clippy, "src/tools/clippy", "cargo-clippy", {};
-    Clippy, clippy, "src/tools/clippy", "clippy-driver", {};
-    Miri, miri, "src/tools/miri", "miri", {};
-    CargoMiri, miri, "src/tools/miri/cargo-miri", "cargo-miri", {};
-    Rls, rls, "src/tools/rls", "rls", {
+    Cargofmt, rustfmt, "src/tools/rustfmt", "cargo-fmt", stable=true, {};
+    CargoClippy, clippy, "src/tools/clippy", "cargo-clippy", stable=true, {};
+    Clippy, clippy, "src/tools/clippy", "clippy-driver", stable=true, {};
+    Miri, miri, "src/tools/miri", "miri", stable=false, {};
+    CargoMiri, miri, "src/tools/miri/cargo-miri", "cargo-miri", stable=false, {};
+    Rls, rls, "src/tools/rls", "rls", stable=true, {
         builder.ensure(Clippy {
             compiler: self.compiler,
             target: self.target,
@@ -665,7 +671,7 @@ tool_extended!((self, builder),
         });
         self.extra_features.push("clippy".to_owned());
     };
-    Rustfmt, rustfmt, "src/tools/rustfmt", "rustfmt", {};
+    Rustfmt, rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, {};
 );
 
 impl<'a> Builder<'a> {
diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml
index f8fa7b727d1..3de27bc54c5 100644
--- a/src/ci/azure-pipelines/auto.yml
+++ b/src/ci/azure-pipelines/auto.yml
@@ -142,10 +142,6 @@ jobs:
         # FIXME(#59637)
         NO_DEBUG_ASSERTIONS: 1
         NO_LLVM_ASSERTIONS: 1
-      # MSVC aux tests
-      x86_64-msvc-aux:
-        RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1
-        INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
       x86_64-msvc-cargo:
         SCRIPT: python x.py test src/tools/cargotest src/tools/cargo
         INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld
diff --git a/src/ci/azure-pipelines/steps/run.yml b/src/ci/azure-pipelines/steps/run.yml
index 85ff3e52a84..e43116c06b6 100644
--- a/src/ci/azure-pipelines/steps/run.yml
+++ b/src/ci/azure-pipelines/steps/run.yml
@@ -82,10 +82,6 @@ steps:
   displayName: Install msys2
   condition: and(succeeded(), not(variables.SKIP_JOB))
 
-- bash: src/ci/scripts/install-msys2-packages.sh
-  displayName: Install msys2 packages
-  condition: and(succeeded(), not(variables.SKIP_JOB))
-
 - bash: src/ci/scripts/install-mingw.sh
   displayName: Install MinGW
   condition: and(succeeded(), not(variables.SKIP_JOB))
diff --git a/src/ci/docker/scripts/musl-toolchain.sh b/src/ci/docker/scripts/musl-toolchain.sh
index 74ba2f0eadb..1ae412340cb 100644
--- a/src/ci/docker/scripts/musl-toolchain.sh
+++ b/src/ci/docker/scripts/musl-toolchain.sh
@@ -3,7 +3,7 @@
 #
 # Versions of the toolchain components are configurable in `musl-cross-make/Makefile` and
 # musl unlike GLIBC is forward compatible so upgrading it shouldn't break old distributions.
-# Right now we have: Binutils 2.27, GCC 6.4.0, musl 1.1.22.
+# Right now we have: Binutils 2.31.1, GCC 9.2.0, musl 1.1.24.
 set -ex
 
 hide_output() {
@@ -33,11 +33,13 @@ shift
 # Apparently applying `-fPIC` everywhere allows them to link successfully.
 export CFLAGS="-fPIC $CFLAGS"
 
-git clone https://github.com/richfelker/musl-cross-make -b v0.9.8
+git clone https://github.com/richfelker/musl-cross-make # -b v0.9.9
 cd musl-cross-make
+# A few commits ahead of v0.9.9 to include the cowpatch fix:
+git checkout a54eb56f33f255dfca60be045f12a5cfaf5a72a9
 
-hide_output make -j$(nproc) TARGET=$TARGET
-hide_output make install TARGET=$TARGET OUTPUT=$OUTPUT
+hide_output make -j$(nproc) TARGET=$TARGET MUSL_VER=1.1.24
+hide_output make install TARGET=$TARGET MUSL_VER=1.1.24 OUTPUT=$OUTPUT
 
 cd -
 
diff --git a/src/ci/docker/scripts/musl.sh b/src/ci/docker/scripts/musl.sh
index d847c407aba..58393a5719a 100644
--- a/src/ci/docker/scripts/musl.sh
+++ b/src/ci/docker/scripts/musl.sh
@@ -24,7 +24,7 @@ shift
 # Apparently applying `-fPIC` everywhere allows them to link successfully.
 export CFLAGS="-fPIC $CFLAGS"
 
-MUSL=musl-1.1.22
+MUSL=musl-1.1.24
 
 # may have been downloaded in a previous run
 if [ ! -d $MUSL ]; then
diff --git a/src/ci/docker/wasm32/Dockerfile b/src/ci/docker/wasm32/Dockerfile
index 91c492d03c1..8232539edda 100644
--- a/src/ci/docker/wasm32/Dockerfile
+++ b/src/ci/docker/wasm32/Dockerfile
@@ -27,6 +27,9 @@ ENV PATH=$PATH:/emsdk-portable
 ENV PATH=$PATH:/emsdk-portable/upstream/emscripten/
 ENV PATH=$PATH:/emsdk-portable/node/12.9.1_64bit/bin/
 ENV BINARYEN_ROOT=/emsdk-portable/upstream/
+ENV EMSDK=/emsdk-portable
+ENV EM_CONFIG=/emsdk-portable/.emscripten
+ENV EM_CACHE=/emsdk-portable/upstream/emscripten/cache
 
 ENV TARGETS=wasm32-unknown-emscripten
 
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index 92fec593a54..a052d0879a3 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -147,10 +147,6 @@ x--expand-yaml-anchors--remove:
         run: src/ci/scripts/install-msys2.sh
         <<: *step
 
-      - name: install MSYS2 packages
-        run: src/ci/scripts/install-msys2-packages.sh
-        <<: *step
-
       - name: install MinGW
         run: src/ci/scripts/install-mingw.sh
         <<: *step
@@ -496,12 +492,6 @@ jobs:
               NO_LLVM_ASSERTIONS: 1
             <<: *job-windows-xl
 
-          - name: x86_64-msvc-aux
-            env:
-              RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1
-              RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
-            <<: *job-windows-xl
-
           - name: x86_64-msvc-cargo
             env:
               SCRIPT: python x.py test src/tools/cargotest src/tools/cargo
diff --git a/src/ci/scripts/install-msys2-packages.sh b/src/ci/scripts/install-msys2-packages.sh
deleted file mode 100755
index ff7479c05d0..00000000000
--- a/src/ci/scripts/install-msys2-packages.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/bash
-
-set -euo pipefail
-IFS=$'\n\t'
-
-source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
-
-if isWindows; then
-    pacman -S --noconfirm --needed base-devel ca-certificates make diffutils tar \
-        binutils
-
-    # Detect the native Python version installed on the agent. On GitHub
-    # Actions, the C:\hostedtoolcache\windows\Python directory contains a
-    # subdirectory for each installed Python version.
-    #
-    # The -V flag of the sort command sorts the input by version number.
-    native_python_version="$(ls /c/hostedtoolcache/windows/Python | sort -Vr | head -n 1)"
-
-    # Make sure we use the native python interpreter instead of some msys equivalent
-    # one way or another. The msys interpreters seem to have weird path conversions
-    # baked in which break LLVM's build system one way or another, so let's use the
-    # native version which keeps everything as native as possible.
-    python_home="/c/hostedtoolcache/windows/Python/${native_python_version}/x64"
-    cp "${python_home}/python.exe" "${python_home}/python3.exe"
-    ciCommandAddPath "C:\\hostedtoolcache\\windows\\Python\\${native_python_version}\\x64"
-    ciCommandAddPath "C:\\hostedtoolcache\\windows\\Python\\${native_python_version}\\x64\\Scripts"
-fi
diff --git a/src/ci/scripts/install-msys2.sh b/src/ci/scripts/install-msys2.sh
index 3c3b5007f86..3a0c965a677 100755
--- a/src/ci/scripts/install-msys2.sh
+++ b/src/ci/scripts/install-msys2.sh
@@ -1,10 +1,6 @@
 #!/bin/bash
 # Download and install MSYS2, needed primarily for the test suite (run-make) but
 # also used by the MinGW toolchain for assembling things.
-#
-# FIXME: we should probe the default azure image and see if we can use the MSYS2
-# toolchain there. (if there's even one there). For now though this gets the job
-# done.
 
 set -euo pipefail
 IFS=$'\n\t'
@@ -12,17 +8,26 @@ IFS=$'\n\t'
 source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
 
 if isWindows; then
-    # Pre-followed the api/v2 URL to the CDN since the API can be a bit flakey
-    curl -sSL https://packages.chocolatey.org/msys2.20190524.0.0.20191030.nupkg > \
-        msys2.nupkg
-    curl -sSL https://packages.chocolatey.org/chocolatey-core.extension.1.3.5.1.nupkg > \
-        chocolatey-core.extension.nupkg
-    choco install -s . msys2 \
-        --params="/InstallDir:$(ciCheckoutPath)/msys2 /NoPath" -y --no-progress
-    rm msys2.nupkg chocolatey-core.extension.nupkg
-    mkdir -p "$(ciCheckoutPath)/msys2/home/${USERNAME}"
-    ciCommandAddPath "$(ciCheckoutPath)/msys2/usr/bin"
+    msys2Path="c:/msys64"
+    mkdir -p "${msys2Path}/home/${USERNAME}"
+    ciCommandAddPath "${msys2Path}/usr/bin"
 
     echo "switching shell to use our own bash"
-    ciCommandSetEnv CI_OVERRIDE_SHELL "$(ciCheckoutPath)/msys2/usr/bin/bash.exe"
+    ciCommandSetEnv CI_OVERRIDE_SHELL "${msys2Path}/usr/bin/bash.exe"
+
+    # Detect the native Python version installed on the agent. On GitHub
+    # Actions, the C:\hostedtoolcache\windows\Python directory contains a
+    # subdirectory for each installed Python version.
+    #
+    # The -V flag of the sort command sorts the input by version number.
+    native_python_version="$(ls /c/hostedtoolcache/windows/Python | sort -Vr | head -n 1)"
+
+    # Make sure we use the native python interpreter instead of some msys equivalent
+    # one way or another. The msys interpreters seem to have weird path conversions
+    # baked in which break LLVM's build system one way or another, so let's use the
+    # native version which keeps everything as native as possible.
+    python_home="/c/hostedtoolcache/windows/Python/${native_python_version}/x64"
+    cp "${python_home}/python.exe" "${python_home}/python3.exe"
+    ciCommandAddPath "C:\\hostedtoolcache\\windows\\Python\\${native_python_version}\\x64"
+    ciCommandAddPath "C:\\hostedtoolcache\\windows\\Python\\${native_python_version}\\x64\\Scripts"
 fi
diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/documentation-tests.md
index efadae1c5fb..18010bebcf0 100644
--- a/src/doc/rustdoc/src/documentation-tests.md
+++ b/src/doc/rustdoc/src/documentation-tests.md
@@ -416,7 +416,7 @@ without including it in your main documentation. For example, you could write th
 `lib.rs` to test your README as part of your doctests:
 
 ```rust,ignore
-#![feature(extern_doc)]
+#![feature(external_doc)]
 
 #[doc(include="../README.md")]
 #[cfg(doctest)]
diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md
index ea560a6d709..fbb40f1d2f3 100644
--- a/src/doc/unstable-book/src/library-features/asm.md
+++ b/src/doc/unstable-book/src/library-features/asm.md
@@ -201,7 +201,7 @@ fn mul(a: u64, b: u64) -> u128 {
         );
     }
 
-    (hi as u128) << 64 + lo as u128
+    ((hi as u128) << 64) + lo as u128
 }
 ```
 
@@ -382,7 +382,9 @@ The macro will initially be supported only on ARM, AArch64, x86, x86-64 and RISC
 
 The assembler template uses the same syntax as [format strings][format-syntax] (i.e. placeholders are specified by curly braces). The corresponding arguments are accessed in order, by index, or by name. However, implicit named arguments (introduced by [RFC #2795][rfc-2795]) are not supported.
 
-As with format strings, named arguments must appear after positional arguments. Explicit register operands must appear at the end of the operand list, after any named arguments if any. Explicit register operands cannot be used by placeholders in the template string. All other operands must appear at least once in the template string, otherwise a compiler error is generated.
+As with format strings, named arguments must appear after positional arguments. Explicit register operands must appear at the end of the operand list, after named arguments if any.
+
+Explicit register operands cannot be used by placeholders in the template string. All other named and positional operands must appear at least once in the template string, otherwise a compiler error is generated.
 
 The exact assembly code syntax is target-specific and opaque to the compiler except for the way operands are substituted into the template string to form the code passed to the assembler.
 
diff --git a/src/etc/debugger_pretty_printers_common.py b/src/etc/debugger_pretty_printers_common.py
deleted file mode 100644
index b3f8f50636b..00000000000
--- a/src/etc/debugger_pretty_printers_common.py
+++ /dev/null
@@ -1,401 +0,0 @@
-"""
-This module provides an abstraction layer over common Rust pretty printing
-functionality needed by both GDB and LLDB.
-"""
-
-import re
-
-# Type codes that indicate the kind of type as it appears in DWARF debug
-# information. This code alone is not sufficient to determine the Rust type.
-# For example structs, tuples, fat pointers, or enum variants will all have
-# DWARF_TYPE_CODE_STRUCT.
-DWARF_TYPE_CODE_STRUCT = 1
-DWARF_TYPE_CODE_UNION  = 2
-DWARF_TYPE_CODE_PTR    = 3
-DWARF_TYPE_CODE_ARRAY  = 4
-DWARF_TYPE_CODE_ENUM   = 5
-
-# These constants specify the most specific kind of type that could be
-# determined for a given value.
-TYPE_KIND_UNKNOWN           = -1
-TYPE_KIND_EMPTY             = 0
-TYPE_KIND_SLICE             = 1
-TYPE_KIND_REGULAR_STRUCT    = 2
-TYPE_KIND_TUPLE             = 3
-TYPE_KIND_TUPLE_STRUCT      = 4
-TYPE_KIND_CSTYLE_VARIANT    = 5
-TYPE_KIND_TUPLE_VARIANT     = 6
-TYPE_KIND_STRUCT_VARIANT    = 7
-TYPE_KIND_STR_SLICE         = 8
-TYPE_KIND_STD_VEC           = 9
-TYPE_KIND_STD_STRING        = 10
-TYPE_KIND_REGULAR_ENUM      = 11
-TYPE_KIND_COMPRESSED_ENUM   = 12
-TYPE_KIND_SINGLETON_ENUM    = 13
-TYPE_KIND_CSTYLE_ENUM       = 14
-TYPE_KIND_PTR               = 15
-TYPE_KIND_FIXED_SIZE_VEC    = 16
-TYPE_KIND_REGULAR_UNION     = 17
-TYPE_KIND_OS_STRING         = 18
-TYPE_KIND_STD_VECDEQUE      = 19
-TYPE_KIND_STD_BTREESET      = 20
-TYPE_KIND_STD_BTREEMAP      = 21
-
-ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$"
-ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR"
-
-# Slice related constants
-SLICE_FIELD_NAME_DATA_PTR = "data_ptr"
-SLICE_FIELD_NAME_LENGTH = "length"
-SLICE_FIELD_NAMES = [SLICE_FIELD_NAME_DATA_PTR, SLICE_FIELD_NAME_LENGTH]
-
-# std::Vec<> related constants
-STD_VEC_FIELD_NAME_LENGTH = "len"
-STD_VEC_FIELD_NAME_BUF = "buf"
-STD_VEC_FIELD_NAMES = [STD_VEC_FIELD_NAME_BUF,
-                       STD_VEC_FIELD_NAME_LENGTH]
-
-# std::collections::VecDeque<> related constants
-STD_VECDEQUE_FIELD_NAME_TAIL = "tail"
-STD_VECDEQUE_FIELD_NAME_HEAD = "head"
-STD_VECDEQUE_FIELD_NAME_BUF = "buf"
-STD_VECDEQUE_FIELD_NAMES = [STD_VECDEQUE_FIELD_NAME_TAIL,
-                            STD_VECDEQUE_FIELD_NAME_HEAD,
-                            STD_VECDEQUE_FIELD_NAME_BUF]
-
-# std::collections::BTreeSet<> related constants
-STD_BTREESET_FIELD_NAMES = ["map"]
-
-# std::collections::BTreeMap<> related constants
-STD_BTREEMAP_FIELD_NAMES = ["root", "length"]
-
-# std::String related constants
-STD_STRING_FIELD_NAMES = ["vec"]
-
-# std::ffi::OsString related constants
-OS_STRING_FIELD_NAMES = ["inner"]
-
-
-class Type(object):
-    """
-    This class provides a common interface for type-oriented operations.
-    Sub-classes are supposed to wrap a debugger-specific type-object and
-    provide implementations for the abstract methods in this class.
-    """
-
-    def __init__(self):
-        self.__type_kind = None
-
-    def get_unqualified_type_name(self):
-        """
-        Implementations of this method should return the unqualified name of the
-        type-object they are wrapping. Some examples:
-
-        'int' -> 'int'
-        'std::vec::Vec<std::string::String>' -> 'Vec<std::string::String>'
-        '&std::option::Option<std::string::String>' -> '&std::option::Option<std::string::String>'
-
-        As you can see, type arguments stay fully qualified.
-        """
-        raise NotImplementedError("Override this method")
-
-    def get_dwarf_type_kind(self):
-        """
-        Implementations of this method should return the correct
-        DWARF_TYPE_CODE_* value for the wrapped type-object.
-        """
-        raise NotImplementedError("Override this method")
-
-    def get_fields(self):
-        """
-        Implementations of this method should return a list of field-objects of
-        this type. For Rust-enums (i.e. with DWARF_TYPE_CODE_UNION) these field-
-        objects represent the variants of the enum. Field-objects must have a
-        `name` attribute that gives their name as specified in DWARF.
-        """
-        assert ((self.get_dwarf_type_kind() == DWARF_TYPE_CODE_STRUCT) or
-                (self.get_dwarf_type_kind() == DWARF_TYPE_CODE_UNION))
-        raise NotImplementedError("Override this method")
-
-    def get_wrapped_value(self):
-        """
-        Returns the debugger-specific type-object wrapped by this object. This
-        is sometimes needed for doing things like pointer-arithmetic in GDB.
-        """
-        raise NotImplementedError("Override this method")
-
-    def get_type_kind(self):
-        """This method returns the TYPE_KIND_* value for this type-object."""
-        if self.__type_kind is None:
-            dwarf_type_code = self.get_dwarf_type_kind()
-
-            if dwarf_type_code == DWARF_TYPE_CODE_STRUCT:
-                self.__type_kind = self.__classify_struct()
-            elif dwarf_type_code == DWARF_TYPE_CODE_UNION:
-                self.__type_kind = self.__classify_union()
-            elif dwarf_type_code == DWARF_TYPE_CODE_PTR:
-                self.__type_kind = TYPE_KIND_PTR
-            elif dwarf_type_code == DWARF_TYPE_CODE_ARRAY:
-                self.__type_kind = TYPE_KIND_FIXED_SIZE_VEC
-            else:
-                self.__type_kind = TYPE_KIND_UNKNOWN
-        return self.__type_kind
-
-    def __classify_struct(self):
-        assert self.get_dwarf_type_kind() == DWARF_TYPE_CODE_STRUCT
-
-        unqualified_type_name = self.get_unqualified_type_name()
-
-        # STR SLICE
-        if unqualified_type_name == "&str":
-            return TYPE_KIND_STR_SLICE
-
-        # REGULAR SLICE
-        if (unqualified_type_name.startswith(("&[", "&mut [")) and
-            unqualified_type_name.endswith("]") and
-            self.__conforms_to_field_layout(SLICE_FIELD_NAMES)):
-            return TYPE_KIND_SLICE
-
-        fields = self.get_fields()
-        field_count = len(fields)
-
-        # EMPTY STRUCT
-        if field_count == 0:
-            return TYPE_KIND_EMPTY
-
-        # STD VEC
-        if (unqualified_type_name.startswith("Vec<") and
-            self.__conforms_to_field_layout(STD_VEC_FIELD_NAMES)):
-            return TYPE_KIND_STD_VEC
-
-        # STD COLLECTION VECDEQUE
-        if (unqualified_type_name.startswith("VecDeque<") and
-            self.__conforms_to_field_layout(STD_VECDEQUE_FIELD_NAMES)):
-            return TYPE_KIND_STD_VECDEQUE
-
-        # STD COLLECTION BTREESET
-        if (unqualified_type_name.startswith("BTreeSet<") and
-                self.__conforms_to_field_layout(STD_BTREESET_FIELD_NAMES)):
-            return TYPE_KIND_STD_BTREESET
-
-        # STD COLLECTION BTREEMAP
-        if (unqualified_type_name.startswith("BTreeMap<") and
-                self.__conforms_to_field_layout(STD_BTREEMAP_FIELD_NAMES)):
-            return TYPE_KIND_STD_BTREEMAP
-
-        # STD STRING
-        if (unqualified_type_name.startswith("String") and
-            self.__conforms_to_field_layout(STD_STRING_FIELD_NAMES)):
-            return TYPE_KIND_STD_STRING
-
-        # OS STRING
-        if (unqualified_type_name == "OsString" and
-            self.__conforms_to_field_layout(OS_STRING_FIELD_NAMES)):
-            return TYPE_KIND_OS_STRING
-
-        # ENUM VARIANTS
-        if fields[0].name == ENUM_DISR_FIELD_NAME:
-            if field_count == 1:
-                return TYPE_KIND_CSTYLE_VARIANT
-            elif self.__all_fields_conform_to_tuple_field_naming(1):
-                return TYPE_KIND_TUPLE_VARIANT
-            else:
-                return TYPE_KIND_STRUCT_VARIANT
-
-        # TUPLE
-        if self.__all_fields_conform_to_tuple_field_naming(0):
-            if unqualified_type_name.startswith("("):
-                return TYPE_KIND_TUPLE
-            else:
-                return TYPE_KIND_TUPLE_STRUCT
-
-        # REGULAR STRUCT
-        return TYPE_KIND_REGULAR_STRUCT
-
-    def __classify_union(self):
-        assert self.get_dwarf_type_kind() == DWARF_TYPE_CODE_UNION
-
-        union_members = self.get_fields()
-        union_member_count = len(union_members)
-        if union_member_count == 0:
-            return TYPE_KIND_EMPTY
-
-        first_variant_name = union_members[0].name
-        if first_variant_name is None:
-            if union_member_count == 1:
-                return TYPE_KIND_SINGLETON_ENUM
-            else:
-                return TYPE_KIND_REGULAR_ENUM
-        elif first_variant_name.startswith(ENCODED_ENUM_PREFIX):
-            assert union_member_count == 1
-            return TYPE_KIND_COMPRESSED_ENUM
-        else:
-            return TYPE_KIND_REGULAR_UNION
-
-    def __conforms_to_field_layout(self, expected_fields):
-        actual_fields = self.get_fields()
-        actual_field_count = len(actual_fields)
-
-        if actual_field_count != len(expected_fields):
-            return False
-
-        for i in range(0, actual_field_count):
-            if actual_fields[i].name != expected_fields[i]:
-                return False
-
-        return True
-
-    def __all_fields_conform_to_tuple_field_naming(self, start_index):
-        fields = self.get_fields()
-        field_count = len(fields)
-
-        for i in range(start_index, field_count):
-            field_name = fields[i].name
-            if (field_name is None) or (re.match(r"__\d+$", field_name) is None):
-                return False
-        return True
-
-
-class Value(object):
-    """
-    This class provides a common interface for value-oriented operations.
-    Sub-classes are supposed to wrap a debugger-specific value-object and
-    provide implementations for the abstract methods in this class.
-    """
-    def __init__(self, ty):
-        self.type = ty
-
-    def get_child_at_index(self, index):
-        """Returns the value of the field, array element or variant at the given index"""
-        raise NotImplementedError("Override this method")
-
-    def as_integer(self):
-        """
-        Try to convert the wrapped value into a Python integer. This should
-        always succeed for values that are pointers or actual integers.
-        """
-        raise NotImplementedError("Override this method")
-
-    def get_wrapped_value(self):
-        """
-        Returns the debugger-specific value-object wrapped by this object. This
-        is sometimes needed for doing things like pointer-arithmetic in GDB.
-        """
-        raise NotImplementedError("Override this method")
-
-
-class EncodedEnumInfo(object):
-    """
-    This class provides facilities for handling enum values with compressed
-    encoding where a non-null field in one variant doubles as the discriminant.
-    """
-
-    def __init__(self, enum_val):
-        assert enum_val.type.get_type_kind() == TYPE_KIND_COMPRESSED_ENUM
-        variant_name = enum_val.type.get_fields()[0].name
-        last_separator_index = variant_name.rfind("$")
-        start_index = len(ENCODED_ENUM_PREFIX)
-        indices_substring = variant_name[start_index:last_separator_index].split("$")
-        self.__enum_val = enum_val
-        self.__disr_field_indices = [int(index) for index in indices_substring]
-        self.__null_variant_name = variant_name[last_separator_index + 1:]
-
-    def is_null_variant(self):
-        ty = self.__enum_val.type
-        sole_variant_val = self.__enum_val.get_child_at_index(0)
-        discriminant_val = sole_variant_val
-        for disr_field_index in self.__disr_field_indices:
-            discriminant_val = discriminant_val.get_child_at_index(disr_field_index)
-
-        # If the discriminant field is a fat pointer we have to consider the
-        # first word as the true discriminant
-        if discriminant_val.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_STRUCT:
-            discriminant_val = discriminant_val.get_child_at_index(0)
-
-        return discriminant_val.as_integer() == 0
-
-    def get_non_null_variant_val(self):
-        return self.__enum_val.get_child_at_index(0)
-
-    def get_null_variant_name(self):
-        return self.__null_variant_name
-
-
-def get_discriminant_value_as_integer(enum_val):
-    assert enum_val.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_UNION
-    # we can take any variant here because the discriminant has to be the same
-    # for all of them.
-    variant_val = enum_val.get_child_at_index(0)
-    disr_val = variant_val.get_child_at_index(0)
-    return disr_val.as_integer()
-
-
-def extract_length_ptr_and_cap_from_std_vec(vec_val):
-    assert vec_val.type.get_type_kind() == TYPE_KIND_STD_VEC
-    length_field_index = STD_VEC_FIELD_NAMES.index(STD_VEC_FIELD_NAME_LENGTH)
-    buf_field_index = STD_VEC_FIELD_NAMES.index(STD_VEC_FIELD_NAME_BUF)
-
-    length = vec_val.get_child_at_index(length_field_index).as_integer()
-    buf = vec_val.get_child_at_index(buf_field_index)
-
-    vec_ptr_val = buf.get_child_at_index(0)
-    capacity = buf.get_child_at_index(1).as_integer()
-    data_ptr = vec_ptr_val.get_child_at_index(0)
-    assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR
-    return (length, data_ptr, capacity)
-
-
-def extract_tail_head_ptr_and_cap_from_std_vecdeque(vec_val):
-    assert vec_val.type.get_type_kind() == TYPE_KIND_STD_VECDEQUE
-    tail_field_index = STD_VECDEQUE_FIELD_NAMES.index(STD_VECDEQUE_FIELD_NAME_TAIL)
-    head_field_index = STD_VECDEQUE_FIELD_NAMES.index(STD_VECDEQUE_FIELD_NAME_HEAD)
-    buf_field_index = STD_VECDEQUE_FIELD_NAMES.index(STD_VECDEQUE_FIELD_NAME_BUF)
-
-    tail = vec_val.get_child_at_index(tail_field_index).as_integer()
-    head = vec_val.get_child_at_index(head_field_index).as_integer()
-    buf = vec_val.get_child_at_index(buf_field_index)
-
-    vec_ptr_val = buf.get_child_at_index(0)
-    capacity = buf.get_child_at_index(1).as_integer()
-    data_ptr = vec_ptr_val.get_child_at_index(0)
-    assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR
-    return (tail, head, data_ptr, capacity)
-
-
-def extract_length_and_ptr_from_slice(slice_val):
-    assert (slice_val.type.get_type_kind() == TYPE_KIND_SLICE or
-            slice_val.type.get_type_kind() == TYPE_KIND_STR_SLICE)
-
-    length_field_index = SLICE_FIELD_NAMES.index(SLICE_FIELD_NAME_LENGTH)
-    ptr_field_index = SLICE_FIELD_NAMES.index(SLICE_FIELD_NAME_DATA_PTR)
-
-    length = slice_val.get_child_at_index(length_field_index).as_integer()
-    data_ptr = slice_val.get_child_at_index(ptr_field_index)
-
-    assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR
-    return (length, data_ptr)
-
-
-UNQUALIFIED_TYPE_MARKERS = frozenset(["(", "[", "&", "*"])
-
-
-def extract_type_name(qualified_type_name):
-    """Extracts the type name from a fully qualified path"""
-    if qualified_type_name[0] in UNQUALIFIED_TYPE_MARKERS:
-        return qualified_type_name
-
-    end_of_search = qualified_type_name.find("<")
-    if end_of_search < 0:
-        end_of_search = len(qualified_type_name)
-
-    index = qualified_type_name.rfind("::", 0, end_of_search)
-    if index < 0:
-        return qualified_type_name
-    else:
-        return qualified_type_name[index + 2:]
-
-
-try:
-    compat_str = unicode  # Python 2
-except NameError:
-    compat_str = str
diff --git a/src/etc/gdb_load_rust_pretty_printers.py b/src/etc/gdb_load_rust_pretty_printers.py
index fe38c49d270..856b5df2de7 100644
--- a/src/etc/gdb_load_rust_pretty_printers.py
+++ b/src/etc/gdb_load_rust_pretty_printers.py
@@ -1,3 +1,3 @@
 import gdb
-import gdb_rust_pretty_printing
-gdb_rust_pretty_printing.register_printers(gdb.current_objfile())
+import gdb_lookup
+gdb_lookup.register_printers(gdb.current_objfile())
diff --git a/src/etc/gdb_lookup.py b/src/etc/gdb_lookup.py
new file mode 100644
index 00000000000..2a46eaadad6
--- /dev/null
+++ b/src/etc/gdb_lookup.py
@@ -0,0 +1,92 @@
+import gdb
+import re
+
+from gdb_providers import *
+from rust_types import *
+
+
+rust_enabled = 'set language rust' in gdb.execute('complete set language ru', to_string=True)
+_gdb_version_matched = re.search('([0-9]+)\\.([0-9]+)', gdb.VERSION)
+gdb_version = [int(num) for num in _gdb_version_matched.groups()] if _gdb_version_matched else []
+
+def register_printers(objfile):
+    objfile.pretty_printers.append(lookup)
+
+
+# BACKCOMPAT: rust 1.35
+def is_hashbrown_hashmap(hash_map):
+    return len(hash_map.type.fields()) == 1
+
+
+def classify_rust_type(type):
+    type_class = type.code
+    if type_class == gdb.TYPE_CODE_STRUCT:
+        return classify_struct(type.tag, type.fields())
+    if type_class == gdb.TYPE_CODE_UNION:
+        return classify_union(type.fields())
+
+    return RustType.OTHER
+
+
+def check_enum_discriminant(valobj):
+    content = valobj[valobj.type.fields()[0]]
+    fields = content.type.fields()
+    if len(fields) > 1:
+        discriminant = int(content[fields[0]]) + 1
+        if discriminant > len(fields):
+            # invalid discriminant
+            return False
+    return True
+
+
+def lookup(valobj):
+    rust_type = classify_rust_type(valobj.type)
+
+    if rust_type == RustType.ENUM:
+        # use enum provider only for GDB <7.12
+        if gdb_version[0] < 7 or (gdb_version[0] == 7 and gdb_version[1] < 12):
+            if check_enum_discriminant(valobj):
+                return EnumProvider(valobj)
+
+    if rust_type == RustType.STD_STRING:
+        return StdStringProvider(valobj)
+    if rust_type == RustType.STD_OS_STRING:
+        return StdOsStringProvider(valobj)
+    if rust_type == RustType.STD_STR and not rust_enabled:
+        return StdStrProvider(valobj)
+
+    if rust_type == RustType.STD_VEC:
+        return StdVecProvider(valobj)
+    if rust_type == RustType.STD_VEC_DEQUE:
+        return StdVecDequeProvider(valobj)
+    if rust_type == RustType.STD_BTREE_SET:
+        return StdBTreeSetProvider(valobj)
+    if rust_type == RustType.STD_BTREE_MAP:
+        return StdBTreeMapProvider(valobj)
+    if rust_type == RustType.STD_HASH_MAP:
+        if is_hashbrown_hashmap(valobj):
+            return StdHashMapProvider(valobj)
+        else:
+            return StdOldHashMapProvider(valobj)
+    if rust_type == RustType.STD_HASH_SET:
+        hash_map = valobj["map"]
+        if is_hashbrown_hashmap(hash_map):
+            return StdHashMapProvider(hash_map, show_values=False)
+        else:
+            return StdOldHashMapProvider(hash_map, show_values=False)
+
+    if rust_type == RustType.STD_RC:
+        return StdRcProvider(valobj)
+    if rust_type == RustType.STD_ARC:
+        return StdRcProvider(valobj, is_atomic=True)
+
+    if rust_type == RustType.STD_CELL:
+        return StdCellProvider(valobj)
+    if rust_type == RustType.STD_REF:
+        return StdRefProvider(valobj)
+    if rust_type == RustType.STD_REF_MUT:
+        return StdRefProvider(valobj)
+    if rust_type == RustType.STD_REF_CELL:
+        return StdRefCellProvider(valobj)
+
+    return None
diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py
new file mode 100644
index 00000000000..cec9c56a235
--- /dev/null
+++ b/src/etc/gdb_providers.py
@@ -0,0 +1,385 @@
+from sys import version_info
+
+import gdb
+from gdb import lookup_type
+
+if version_info[0] >= 3:
+    xrange = range
+
+ZERO_FIELD = "__0"
+FIRST_FIELD = "__1"
+
+
+def unwrap_unique_or_non_null(unique_or_nonnull):
+    # BACKCOMPAT: rust 1.32
+    # https://github.com/rust-lang/rust/commit/7a0911528058e87d22ea305695f4047572c5e067
+    ptr = unique_or_nonnull["pointer"]
+    return ptr if ptr.type.code == gdb.TYPE_CODE_PTR else ptr[ZERO_FIELD]
+
+
+class EnumProvider:
+    def __init__(self, valobj):
+        content = valobj[valobj.type.fields()[0]]
+        fields = content.type.fields()
+        self.empty = len(fields) == 0
+        if not self.empty:
+            if len(fields) == 1:
+                discriminant = 0
+            else:
+                discriminant = int(content[fields[0]]) + 1
+            self.active_variant = content[fields[discriminant]]
+            self.name = fields[discriminant].name
+            self.full_name = "{}::{}".format(valobj.type.name, self.name)
+        else:
+            self.full_name = valobj.type.name
+
+    def to_string(self):
+        return self.full_name
+
+    def children(self):
+        if not self.empty:
+            yield self.name, self.active_variant
+
+
+class StdStringProvider:
+    def __init__(self, valobj):
+        self.valobj = valobj
+        vec = valobj["vec"]
+        self.length = int(vec["len"])
+        self.data_ptr = unwrap_unique_or_non_null(vec["buf"]["ptr"])
+
+    def to_string(self):
+        return self.data_ptr.lazy_string(encoding="utf-8", length=self.length)
+
+    @staticmethod
+    def display_hint():
+        return "string"
+
+
+class StdOsStringProvider:
+    def __init__(self, valobj):
+        self.valobj = valobj
+        buf = self.valobj["inner"]["inner"]
+        is_windows = "Wtf8Buf" in buf.type.name
+        vec = buf[ZERO_FIELD] if is_windows else buf
+
+        self.length = int(vec["len"])
+        self.data_ptr = unwrap_unique_or_non_null(vec["buf"]["ptr"])
+
+    def to_string(self):
+        return self.data_ptr.lazy_string(encoding="utf-8", length=self.length)
+
+    def display_hint(self):
+        return "string"
+
+
+class StdStrProvider:
+    def __init__(self, valobj):
+        self.valobj = valobj
+        self.length = int(valobj["length"])
+        self.data_ptr = valobj["data_ptr"]
+
+    def to_string(self):
+        return self.data_ptr.lazy_string(encoding="utf-8", length=self.length)
+
+    @staticmethod
+    def display_hint():
+        return "string"
+
+
+class StdVecProvider:
+    def __init__(self, valobj):
+        self.valobj = valobj
+        self.length = int(valobj["len"])
+        self.data_ptr = unwrap_unique_or_non_null(valobj["buf"]["ptr"])
+
+    def to_string(self):
+        return "Vec(size={})".format(self.length)
+
+    def children(self):
+        saw_inaccessible = False
+        for index in xrange(self.length):
+            element_ptr = self.data_ptr + index
+            if saw_inaccessible:
+                return
+            try:
+                # rust-lang/rust#64343: passing deref expr to `str` allows
+                # catching exception on garbage pointer
+                str(element_ptr.dereference())
+                yield "[{}]".format(index), element_ptr.dereference()
+            except RuntimeError:
+                saw_inaccessible = True
+                yield str(index), "inaccessible"
+
+    @staticmethod
+    def display_hint():
+        return "array"
+
+
+class StdVecDequeProvider:
+    def __init__(self, valobj):
+        self.valobj = valobj
+        self.head = int(valobj["head"])
+        self.tail = int(valobj["tail"])
+        self.cap = int(valobj["buf"]["cap"])
+        self.data_ptr = unwrap_unique_or_non_null(valobj["buf"]["ptr"])
+        if self.head >= self.tail:
+            self.size = self.head - self.tail
+        else:
+            self.size = self.cap + self.head - self.tail
+
+    def to_string(self):
+        return "VecDeque(size={})".format(self.size)
+
+    def children(self):
+        for index in xrange(0, self.size):
+            value = (self.data_ptr + ((self.tail + index) % self.cap)).dereference()
+            yield "[{}]".format(index), value
+
+    @staticmethod
+    def display_hint():
+        return "array"
+
+
+class StdRcProvider:
+    def __init__(self, valobj, is_atomic=False):
+        self.valobj = valobj
+        self.is_atomic = is_atomic
+        self.ptr = unwrap_unique_or_non_null(valobj["ptr"])
+        self.value = self.ptr["data" if is_atomic else "value"]
+        self.strong = self.ptr["strong"]["v" if is_atomic else "value"]["value"]
+        self.weak = self.ptr["weak"]["v" if is_atomic else "value"]["value"] - 1
+
+    def to_string(self):
+        if self.is_atomic:
+            return "Arc(strong={}, weak={})".format(int(self.strong), int(self.weak))
+        else:
+            return "Rc(strong={}, weak={})".format(int(self.strong), int(self.weak))
+
+    def children(self):
+        yield "value", self.value
+        yield "strong", self.strong
+        yield "weak", self.weak
+
+
+class StdCellProvider:
+    def __init__(self, valobj):
+        self.value = valobj["value"]["value"]
+
+    def to_string(self):
+        return "Cell"
+
+    def children(self):
+        yield "value", self.value
+
+
+class StdRefProvider:
+    def __init__(self, valobj):
+        self.value = valobj["value"].dereference()
+        self.borrow = valobj["borrow"]["borrow"]["value"]["value"]
+
+    def to_string(self):
+        borrow = int(self.borrow)
+        if borrow >= 0:
+            return "Ref(borrow={})".format(borrow)
+        else:
+            return "Ref(borrow_mut={})".format(-borrow)
+
+    def children(self):
+        yield "*value", self.value
+        yield "borrow", self.borrow
+
+
+class StdRefCellProvider:
+    def __init__(self, valobj):
+        self.value = valobj["value"]["value"]
+        self.borrow = valobj["borrow"]["value"]["value"]
+
+    def to_string(self):
+        borrow = int(self.borrow)
+        if borrow >= 0:
+            return "RefCell(borrow={})".format(borrow)
+        else:
+            return "RefCell(borrow_mut={})".format(-borrow)
+
+    def children(self):
+        yield "value", self.value
+        yield "borrow", self.borrow
+
+
+# Yield each key (and optionally value) from a BoxedNode.
+def children_of_node(boxed_node, height, want_values):
+    def cast_to_internal(node):
+        internal_type_name = str(node.type.target()).replace("LeafNode", "InternalNode", 1)
+        internal_type = lookup_type(internal_type_name)
+        return node.cast(internal_type.pointer())
+
+    node_ptr = unwrap_unique_or_non_null(boxed_node["ptr"])
+    node_ptr = cast_to_internal(node_ptr) if height > 0 else node_ptr
+    leaf = node_ptr["data"] if height > 0 else node_ptr.dereference()
+    keys = leaf["keys"]
+    values = leaf["vals"]
+    length = int(leaf["len"])
+
+    for i in xrange(0, length + 1):
+        if height > 0:
+            child_ptr = node_ptr["edges"][i]["value"]["value"]
+            for child in children_of_node(child_ptr, height - 1, want_values):
+                yield child
+        if i < length:
+            if want_values:
+                yield keys[i]["value"]["value"], values[i]["value"]["value"]
+            else:
+                yield keys[i]["value"]["value"]
+
+
+class StdBTreeSetProvider:
+    def __init__(self, valobj):
+        self.valobj = valobj
+
+    def to_string(self):
+        return "BTreeSet(size={})".format(self.valobj["map"]["length"])
+
+    def children(self):
+        inner_map = self.valobj["map"]
+        if inner_map["length"] > 0:
+            root = inner_map["root"]
+            if "core::option::Option<" in root.type.name:
+                type_name = str(root.type.name).replace("core::option::Option<", "", 1)[:-1]
+                root = root.cast(gdb.lookup_type(type_name))
+
+            node_ptr = root["node"]
+            for i, child in enumerate(children_of_node(node_ptr, root["height"], False)):
+                yield "[{}]".format(i), child
+
+    @staticmethod
+    def display_hint():
+        return "array"
+
+
+class StdBTreeMapProvider:
+    def __init__(self, valobj):
+        self.valobj = valobj
+
+    def to_string(self):
+        return "BTreeMap(size={})".format(self.valobj["length"])
+
+    def children(self):
+        if self.valobj["length"] > 0:
+            root = self.valobj["root"]
+            if "core::option::Option<" in root.type.name:
+                type_name = str(root.type.name).replace("core::option::Option<", "", 1)[:-1]
+                root = root.cast(gdb.lookup_type(type_name))
+
+            node_ptr = root["node"]
+            for i, child in enumerate(children_of_node(node_ptr, root["height"], True)):
+                yield "key{}".format(i), child[0]
+                yield "val{}".format(i), child[1]
+
+    @staticmethod
+    def display_hint():
+        return "map"
+
+
+# BACKCOMPAT: rust 1.35
+class StdOldHashMapProvider:
+    def __init__(self, valobj, show_values=True):
+        self.valobj = valobj
+        self.show_values = show_values
+
+        self.table = self.valobj["table"]
+        self.size = int(self.table["size"])
+        self.hashes = self.table["hashes"]
+        self.hash_uint_type = self.hashes.type
+        self.hash_uint_size = self.hashes.type.sizeof
+        self.modulo = 2 ** self.hash_uint_size
+        self.data_ptr = self.hashes[ZERO_FIELD]["pointer"]
+
+        self.capacity_mask = int(self.table["capacity_mask"])
+        self.capacity = (self.capacity_mask + 1) % self.modulo
+
+        marker = self.table["marker"].type
+        self.pair_type = marker.template_argument(0)
+        self.pair_type_size = self.pair_type.sizeof
+
+        self.valid_indices = []
+        for idx in range(self.capacity):
+            data_ptr = self.data_ptr.cast(self.hash_uint_type.pointer())
+            address = data_ptr + idx
+            hash_uint = address.dereference()
+            hash_ptr = hash_uint[ZERO_FIELD]["pointer"]
+            if int(hash_ptr) != 0:
+                self.valid_indices.append(idx)
+
+    def to_string(self):
+        if self.show_values:
+            return "HashMap(size={})".format(self.size)
+        else:
+            return "HashSet(size={})".format(self.size)
+
+    def children(self):
+        start = int(self.data_ptr) & ~1
+
+        hashes = self.hash_uint_size * self.capacity
+        align = self.pair_type_size
+        len_rounded_up = (((((hashes + align) % self.modulo - 1) % self.modulo) & ~(
+                (align - 1) % self.modulo)) % self.modulo - hashes) % self.modulo
+
+        pairs_offset = hashes + len_rounded_up
+        pairs_start = gdb.Value(start + pairs_offset).cast(self.pair_type.pointer())
+
+        for index in range(self.size):
+            table_index = self.valid_indices[index]
+            idx = table_index & self.capacity_mask
+            element = (pairs_start + idx).dereference()
+            if self.show_values:
+                yield "key{}".format(index), element[ZERO_FIELD]
+                yield "val{}".format(index), element[FIRST_FIELD]
+            else:
+                yield "[{}]".format(index), element[ZERO_FIELD]
+
+    def display_hint(self):
+        return "map" if self.show_values else "array"
+
+
+class StdHashMapProvider:
+    def __init__(self, valobj, show_values=True):
+        self.valobj = valobj
+        self.show_values = show_values
+
+        table = self.valobj["base"]["table"]
+        capacity = int(table["bucket_mask"]) + 1
+        ctrl = table["ctrl"]["pointer"]
+
+        self.size = int(table["items"])
+        self.data_ptr = table["data"]["pointer"]
+        self.pair_type = self.data_ptr.dereference().type
+
+        self.valid_indices = []
+        for idx in range(capacity):
+            address = ctrl + idx
+            value = address.dereference()
+            is_presented = value & 128 == 0
+            if is_presented:
+                self.valid_indices.append(idx)
+
+    def to_string(self):
+        if self.show_values:
+            return "HashMap(size={})".format(self.size)
+        else:
+            return "HashSet(size={})".format(self.size)
+
+    def children(self):
+        pairs_start = self.data_ptr
+
+        for index in range(self.size):
+            idx = self.valid_indices[index]
+            element = (pairs_start + idx).dereference()
+            if self.show_values:
+                yield "key{}".format(index), element[ZERO_FIELD]
+                yield "val{}".format(index), element[FIRST_FIELD]
+            else:
+                yield "[{}]".format(index), element[ZERO_FIELD]
+
+    def display_hint(self):
+        return "map" if self.show_values else "array"
diff --git a/src/etc/gdb_rust_pretty_printing.py b/src/etc/gdb_rust_pretty_printing.py
deleted file mode 100755
index d580329cb50..00000000000
--- a/src/etc/gdb_rust_pretty_printing.py
+++ /dev/null
@@ -1,466 +0,0 @@
-import gdb
-import re
-import sys
-import debugger_pretty_printers_common as rustpp
-
-# We want a version of `range` which doesn't allocate an intermediate list,
-# specifically it should use a lazy iterator. In Python 2 this was `xrange`, but
-# if we're running with Python 3 then we need to use `range` instead.
-if sys.version_info[0] >= 3:
-    xrange = range
-
-rust_enabled = 'set language rust' in gdb.execute('complete set language ru', to_string=True)
-
-# The btree pretty-printers fail in a confusing way unless
-# https://sourceware.org/bugzilla/show_bug.cgi?id=21763 is fixed.
-# This fix went in 8.1, so check for that.
-# See https://github.com/rust-lang/rust/issues/56730
-gdb_81 = False
-_match = re.search('([0-9]+)\\.([0-9]+)', gdb.VERSION)
-if _match:
-    if int(_match.group(1)) > 8 or (int(_match.group(1)) == 8 and int(_match.group(2)) >= 1):
-        gdb_81 = True
-
-# ===============================================================================
-# GDB Pretty Printing Module for Rust
-# ===============================================================================
-
-
-class GdbType(rustpp.Type):
-
-    def __init__(self, ty):
-        super(GdbType, self).__init__()
-        self.ty = ty
-        self.fields = None
-
-    def get_unqualified_type_name(self):
-        tag = self.ty.tag
-
-        if tag is None:
-            return tag
-
-        return rustpp.extract_type_name(tag).replace("&'static ", "&")
-
-    def get_dwarf_type_kind(self):
-        if self.ty.code == gdb.TYPE_CODE_STRUCT:
-            return rustpp.DWARF_TYPE_CODE_STRUCT
-
-        if self.ty.code == gdb.TYPE_CODE_UNION:
-            return rustpp.DWARF_TYPE_CODE_UNION
-
-        if self.ty.code == gdb.TYPE_CODE_PTR:
-            return rustpp.DWARF_TYPE_CODE_PTR
-
-        if self.ty.code == gdb.TYPE_CODE_ENUM:
-            return rustpp.DWARF_TYPE_CODE_ENUM
-
-    def get_fields(self):
-        assert ((self.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_STRUCT) or
-                (self.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_UNION))
-        if self.fields is None:
-            self.fields = list(self.ty.fields())
-        return self.fields
-
-    def get_wrapped_value(self):
-        return self.ty
-
-
-class GdbValue(rustpp.Value):
-    def __init__(self, gdb_val):
-        super(GdbValue, self).__init__(GdbType(gdb_val.type))
-        self.gdb_val = gdb_val
-        self.children = {}
-
-    def get_child_at_index(self, index):
-        child = self.children.get(index)
-        if child is None:
-            gdb_field = get_field_at_index(self.gdb_val, index)
-            child = GdbValue(self.gdb_val[gdb_field])
-            self.children[index] = child
-        return child
-
-    def as_integer(self):
-        if self.gdb_val.type.code == gdb.TYPE_CODE_PTR:
-            as_str = rustpp.compat_str(self.gdb_val).split()[0]
-            return int(as_str, 0)
-        return int(self.gdb_val)
-
-    def get_wrapped_value(self):
-        return self.gdb_val
-
-
-def register_printers(objfile):
-    """Registers Rust pretty printers for the given objfile"""
-    objfile.pretty_printers.append(rust_pretty_printer_lookup_function)
-
-
-def rust_pretty_printer_lookup_function(gdb_val):
-    """
-    Returns the correct Rust pretty printer for the given value
-    if there is one
-    """
-
-    val = GdbValue(gdb_val)
-    type_kind = val.type.get_type_kind()
-
-    if type_kind == rustpp.TYPE_KIND_SLICE:
-        return RustSlicePrinter(val)
-
-    if type_kind == rustpp.TYPE_KIND_STD_VEC:
-        return RustStdVecPrinter(val)
-
-    if type_kind == rustpp.TYPE_KIND_STD_VECDEQUE:
-        return RustStdVecDequePrinter(val)
-
-    if type_kind == rustpp.TYPE_KIND_STD_BTREESET and gdb_81:
-        return RustStdBTreeSetPrinter(val)
-
-    if type_kind == rustpp.TYPE_KIND_STD_BTREEMAP and gdb_81:
-        return RustStdBTreeMapPrinter(val)
-
-    if type_kind == rustpp.TYPE_KIND_STD_STRING:
-        return RustStdStringPrinter(val)
-
-    if type_kind == rustpp.TYPE_KIND_OS_STRING:
-        return RustOsStringPrinter(val)
-
-    # Checks after this point should only be for "compiler" types --
-    # things that gdb's Rust language support knows about.
-    if rust_enabled:
-        return None
-
-    if type_kind == rustpp.TYPE_KIND_EMPTY:
-        return RustEmptyPrinter(val)
-
-    if type_kind == rustpp.TYPE_KIND_REGULAR_STRUCT:
-        return RustStructPrinter(val,
-                                 omit_first_field=False,
-                                 omit_type_name=False,
-                                 is_tuple_like=False)
-
-    if type_kind == rustpp.TYPE_KIND_STRUCT_VARIANT:
-        return RustStructPrinter(val,
-                                 omit_first_field=True,
-                                 omit_type_name=False,
-                                 is_tuple_like=False)
-
-    if type_kind == rustpp.TYPE_KIND_STR_SLICE:
-        return RustStringSlicePrinter(val)
-
-    if type_kind == rustpp.TYPE_KIND_TUPLE:
-        return RustStructPrinter(val,
-                                 omit_first_field=False,
-                                 omit_type_name=True,
-                                 is_tuple_like=True)
-
-    if type_kind == rustpp.TYPE_KIND_TUPLE_STRUCT:
-        return RustStructPrinter(val,
-                                 omit_first_field=False,
-                                 omit_type_name=False,
-                                 is_tuple_like=True)
-
-    if type_kind == rustpp.TYPE_KIND_CSTYLE_VARIANT:
-        return RustCStyleVariantPrinter(val.get_child_at_index(0))
-
-    if type_kind == rustpp.TYPE_KIND_TUPLE_VARIANT:
-        return RustStructPrinter(val,
-                                 omit_first_field=True,
-                                 omit_type_name=False,
-                                 is_tuple_like=True)
-
-    if type_kind == rustpp.TYPE_KIND_SINGLETON_ENUM:
-        variant = get_field_at_index(gdb_val, 0)
-        return rust_pretty_printer_lookup_function(gdb_val[variant])
-
-    if type_kind == rustpp.TYPE_KIND_REGULAR_ENUM:
-        # This is a regular enum, extract the discriminant
-        discriminant_val = rustpp.get_discriminant_value_as_integer(val)
-        variant = get_field_at_index(gdb_val, discriminant_val)
-        return rust_pretty_printer_lookup_function(gdb_val[variant])
-
-    if type_kind == rustpp.TYPE_KIND_COMPRESSED_ENUM:
-        encoded_enum_info = rustpp.EncodedEnumInfo(val)
-        if encoded_enum_info.is_null_variant():
-            return IdentityPrinter(encoded_enum_info.get_null_variant_name())
-
-        non_null_val = encoded_enum_info.get_non_null_variant_val()
-        return rust_pretty_printer_lookup_function(non_null_val.get_wrapped_value())
-
-    # No pretty printer has been found
-    return None
-
-
-# =------------------------------------------------------------------------------
-# Pretty Printer Classes
-# =------------------------------------------------------------------------------
-class RustEmptyPrinter(object):
-    def __init__(self, val):
-        self.__val = val
-
-    def to_string(self):
-        return self.__val.type.get_unqualified_type_name()
-
-
-class RustStructPrinter(object):
-    def __init__(self, val, omit_first_field, omit_type_name, is_tuple_like):
-        self.__val = val
-        self.__omit_first_field = omit_first_field
-        self.__omit_type_name = omit_type_name
-        self.__is_tuple_like = is_tuple_like
-
-    def to_string(self):
-        if self.__omit_type_name:
-            return None
-        return self.__val.type.get_unqualified_type_name()
-
-    def children(self):
-        cs = []
-        wrapped_value = self.__val.get_wrapped_value()
-
-        for number, field in enumerate(self.__val.type.get_fields()):
-            field_value = wrapped_value[field.name]
-            if self.__is_tuple_like:
-                cs.append((str(number), field_value))
-            else:
-                cs.append((field.name, field_value))
-
-        if self.__omit_first_field:
-            cs = cs[1:]
-
-        return cs
-
-    def display_hint(self):
-        if self.__is_tuple_like:
-            return "array"
-        else:
-            return ""
-
-
-class RustSlicePrinter(object):
-    def __init__(self, val):
-        self.__val = val
-
-    @staticmethod
-    def display_hint():
-        return "array"
-
-    def to_string(self):
-        (length, data_ptr) = rustpp.extract_length_and_ptr_from_slice(self.__val)
-        return (self.__val.type.get_unqualified_type_name() +
-                ("(len: %i)" % length))
-
-    def children(self):
-        (length, data_ptr) = rustpp.extract_length_and_ptr_from_slice(self.__val)
-        assert data_ptr.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_PTR
-        raw_ptr = data_ptr.get_wrapped_value()
-
-        for index in xrange(0, length):
-            yield (str(index), (raw_ptr + index).dereference())
-
-
-class RustStringSlicePrinter(object):
-    def __init__(self, val):
-        self.__val = val
-
-    def to_string(self):
-        (length, data_ptr) = rustpp.extract_length_and_ptr_from_slice(self.__val)
-        raw_ptr = data_ptr.get_wrapped_value()
-        return raw_ptr.lazy_string(encoding="utf-8", length=length)
-
-    def display_hint(self):
-        return "string"
-
-
-class RustStdVecPrinter(object):
-    def __init__(self, val):
-        self.__val = val
-
-    @staticmethod
-    def display_hint():
-        return "array"
-
-    def to_string(self):
-        (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec(self.__val)
-        return (self.__val.type.get_unqualified_type_name() +
-                ("(len: %i, cap: %i)" % (length, cap)))
-
-    def children(self):
-        saw_inaccessible = False
-        (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec(self.__val)
-        gdb_ptr = data_ptr.get_wrapped_value()
-        for index in xrange(0, length):
-            if saw_inaccessible:
-                return
-            try:
-                # rust-lang/rust#64343: passing deref expr to `str` allows
-                # catching exception on garbage pointer
-                str((gdb_ptr + index).dereference())
-                yield (str(index), (gdb_ptr + index).dereference())
-            except RuntimeError:
-                saw_inaccessible = True
-                yield (str(index), "inaccessible")
-
-
-class RustStdVecDequePrinter(object):
-    def __init__(self, val):
-        self.__val = val
-
-    @staticmethod
-    def display_hint():
-        return "array"
-
-    def to_string(self):
-        (tail, head, data_ptr, cap) = \
-            rustpp.extract_tail_head_ptr_and_cap_from_std_vecdeque(self.__val)
-        if head >= tail:
-            size = head - tail
-        else:
-            size = cap + head - tail
-        return (self.__val.type.get_unqualified_type_name() +
-                ("(len: %i, cap: %i)" % (size, cap)))
-
-    def children(self):
-        (tail, head, data_ptr, cap) = \
-            rustpp.extract_tail_head_ptr_and_cap_from_std_vecdeque(self.__val)
-        gdb_ptr = data_ptr.get_wrapped_value()
-        if head >= tail:
-            size = head - tail
-        else:
-            size = cap + head - tail
-        for index in xrange(0, size):
-            yield (str(index), (gdb_ptr + ((tail + index) % cap)).dereference())
-
-
-# Yield each key (and optionally value) from a BoxedNode.
-def children_of_node(boxed_node, height, want_values):
-    node_ptr = boxed_node['ptr']['pointer']
-    if height > 0:
-        type_name = str(node_ptr.type.target()).replace('LeafNode', 'InternalNode', 1)
-        node_type = gdb.lookup_type(type_name)
-        node_ptr = node_ptr.cast(node_type.pointer())
-        leaf = node_ptr['data']
-    else:
-        leaf = node_ptr.dereference()
-    keys = leaf['keys']
-    if want_values:
-        values = leaf['vals']
-    length = int(leaf['len'])
-    for i in xrange(0, length + 1):
-        if height > 0:
-            child_ptr = node_ptr['edges'][i]['value']['value']
-            for child in children_of_node(child_ptr, height - 1, want_values):
-                yield child
-        if i < length:
-            if want_values:
-                yield (keys[i]['value']['value'], values[i]['value']['value'])
-            else:
-                yield keys[i]['value']['value']
-
-
-class RustStdBTreeSetPrinter(object):
-    def __init__(self, val):
-        self.__val = val
-
-    @staticmethod
-    def display_hint():
-        return "array"
-
-    def to_string(self):
-        return (self.__val.type.get_unqualified_type_name() +
-                ("(len: %i)" % self.__val.get_wrapped_value()['map']['length']))
-
-    def children(self):
-        prev_idx = None
-        innermap = GdbValue(self.__val.get_wrapped_value()['map'])
-        if innermap.get_wrapped_value()['length'] > 0:
-            root = GdbValue(innermap.get_wrapped_value()['root'])
-            type_name = str(root.type.ty.name).replace('core::option::Option<', '', 1)[:-1]
-            root = root.get_wrapped_value().cast(gdb.lookup_type(type_name))
-            node_ptr = root['node']
-            i = 0
-            for child in children_of_node(node_ptr, root['height'], False):
-                yield (str(i), child)
-                i = i + 1
-
-
-class RustStdBTreeMapPrinter(object):
-    def __init__(self, val):
-        self.__val = val
-
-    @staticmethod
-    def display_hint():
-        return "map"
-
-    def to_string(self):
-        return (self.__val.type.get_unqualified_type_name() +
-                ("(len: %i)" % self.__val.get_wrapped_value()['length']))
-
-    def children(self):
-        if self.__val.get_wrapped_value()['length'] > 0:
-            root = GdbValue(self.__val.get_wrapped_value()['root'])
-            type_name = str(root.type.ty.name).replace('core::option::Option<', '', 1)[:-1]
-            root = root.get_wrapped_value().cast(gdb.lookup_type(type_name))
-            node_ptr = root['node']
-            i = 0
-            for child in children_of_node(node_ptr, root['height'], True):
-                yield (str(i), child[0])
-                yield (str(i), child[1])
-                i = i + 1
-
-
-class RustStdStringPrinter(object):
-    def __init__(self, val):
-        self.__val = val
-
-    def to_string(self):
-        vec = self.__val.get_child_at_index(0)
-        (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec(vec)
-        return data_ptr.get_wrapped_value().lazy_string(encoding="utf-8",
-                                                        length=length)
-
-    def display_hint(self):
-        return "string"
-
-
-class RustOsStringPrinter(object):
-    def __init__(self, val):
-        self.__val = val
-
-    def to_string(self):
-        buf = self.__val.get_child_at_index(0)
-        vec = buf.get_child_at_index(0)
-        if vec.type.get_unqualified_type_name() == "Wtf8Buf":
-            vec = vec.get_child_at_index(0)
-
-        (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec(
-            vec)
-        return data_ptr.get_wrapped_value().lazy_string(length=length)
-
-    def display_hint(self):
-        return "string"
-
-
-class RustCStyleVariantPrinter(object):
-    def __init__(self, val):
-        assert val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_ENUM
-        self.__val = val
-
-    def to_string(self):
-        return str(self.__val.get_wrapped_value())
-
-
-class IdentityPrinter(object):
-    def __init__(self, string):
-        self.string = string
-
-    def to_string(self):
-        return self.string
-
-
-def get_field_at_index(gdb_val, index):
-    i = 0
-    for field in gdb_val.type.fields():
-        if i == index:
-            return field
-        i += 1
-    return None
diff --git a/src/etc/lldb_commands b/src/etc/lldb_commands
new file mode 100644
index 00000000000..f470c62d899
--- /dev/null
+++ b/src/etc/lldb_commands
@@ -0,0 +1,19 @@
+command script import \"$RUSTC_SYSROOT/lib/rustlib/etc/lldb_lookup.py\"
+type synthetic add -l lldb_lookup.synthetic_lookup -x \".*\" --category Rust
+type summary add -F lldb_lookup.summary_lookup  -e -x -h \"^(alloc::([a-z_]+::)+)String$\" --category Rust
+type summary add -F lldb_lookup.summary_lookup  -e -x -h \"^&str$\" --category Rust
+type summary add -F lldb_lookup.summary_lookup  -e -x -h \"^&\\[.+\\]$\" --category Rust
+type summary add -F lldb_lookup.summary_lookup  -e -x -h \"^(std::ffi::([a-z_]+::)+)OsString$\" --category Rust
+type summary add -F lldb_lookup.summary_lookup  -e -x -h \"^(alloc::([a-z_]+::)+)Vec<.+>$\" --category Rust
+type summary add -F lldb_lookup.summary_lookup  -e -x -h \"^(alloc::([a-z_]+::)+)VecDeque<.+>$\" --category Rust
+type summary add -F lldb_lookup.summary_lookup  -e -x -h \"^(alloc::([a-z_]+::)+)BTreeSet<.+>$\" --category Rust
+type summary add -F lldb_lookup.summary_lookup  -e -x -h \"^(alloc::([a-z_]+::)+)BTreeMap<.+>$\" --category Rust
+type summary add -F lldb_lookup.summary_lookup  -e -x -h \"^(std::collections::([a-z_]+::)+)HashMap<.+>$\" --category Rust
+type summary add -F lldb_lookup.summary_lookup  -e -x -h \"^(std::collections::([a-z_]+::)+)HashSet<.+>$\" --category Rust
+type summary add -F lldb_lookup.summary_lookup  -e -x -h \"^(alloc::([a-z_]+::)+)Rc<.+>$\" --category Rust
+type summary add -F lldb_lookup.summary_lookup  -e -x -h \"^(alloc::([a-z_]+::)+)Arc<.+>$\" --category Rust
+type summary add -F lldb_lookup.summary_lookup  -e -x -h \"^(core::([a-z_]+::)+)Cell<.+>$\" --category Rust
+type summary add -F lldb_lookup.summary_lookup  -e -x -h \"^(core::([a-z_]+::)+)Ref<.+>$\" --category Rust
+type summary add -F lldb_lookup.summary_lookup  -e -x -h \"^(core::([a-z_]+::)+)RefMut<.+>$\" --category Rust
+type summary add -F lldb_lookup.summary_lookup  -e -x -h \"^(core::([a-z_]+::)+)RefCell<.+>$\" --category Rust
+type category enable Rust
diff --git a/src/etc/lldb_lookup.py b/src/etc/lldb_lookup.py
new file mode 100644
index 00000000000..13420fbaf0a
--- /dev/null
+++ b/src/etc/lldb_lookup.py
@@ -0,0 +1,115 @@
+import lldb
+
+from lldb_providers import *
+from rust_types import RustType, classify_struct, classify_union
+
+
+# BACKCOMPAT: rust 1.35
+def is_hashbrown_hashmap(hash_map):
+    return len(hash_map.type.fields) == 1
+
+
+def classify_rust_type(type):
+    type_class = type.GetTypeClass()
+    if type_class == lldb.eTypeClassStruct:
+        return classify_struct(type.name, type.fields)
+    if type_class == lldb.eTypeClassUnion:
+        return classify_union(type.fields)
+
+    return RustType.OTHER
+
+
+def summary_lookup(valobj, dict):
+    # type: (SBValue, dict) -> str
+    """Returns the summary provider for the given value"""
+    rust_type = classify_rust_type(valobj.GetType())
+
+    if rust_type == RustType.STD_STRING:
+        return StdStringSummaryProvider(valobj, dict)
+    if rust_type == RustType.STD_OS_STRING:
+        return StdOsStringSummaryProvider(valobj, dict)
+    if rust_type == RustType.STD_STR:
+        return StdStrSummaryProvider(valobj, dict)
+
+    if rust_type == RustType.STD_VEC:
+        return SizeSummaryProvider(valobj, dict)
+    if rust_type == RustType.STD_VEC_DEQUE:
+        return SizeSummaryProvider(valobj, dict)
+    if rust_type == RustType.STD_SLICE:
+        return SizeSummaryProvider(valobj, dict)
+
+    if rust_type == RustType.STD_HASH_MAP:
+        return SizeSummaryProvider(valobj, dict)
+    if rust_type == RustType.STD_HASH_SET:
+        return SizeSummaryProvider(valobj, dict)
+
+    if rust_type == RustType.STD_RC:
+        return StdRcSummaryProvider(valobj, dict)
+    if rust_type == RustType.STD_ARC:
+        return StdRcSummaryProvider(valobj, dict)
+
+    if rust_type == RustType.STD_REF:
+        return StdRefSummaryProvider(valobj, dict)
+    if rust_type == RustType.STD_REF_MUT:
+        return StdRefSummaryProvider(valobj, dict)
+    if rust_type == RustType.STD_REF_CELL:
+        return StdRefSummaryProvider(valobj, dict)
+
+    return ""
+
+
+def synthetic_lookup(valobj, dict):
+    # type: (SBValue, dict) -> object
+    """Returns the synthetic provider for the given value"""
+    rust_type = classify_rust_type(valobj.GetType())
+
+    if rust_type == RustType.STRUCT:
+        return StructSyntheticProvider(valobj, dict)
+    if rust_type == RustType.STRUCT_VARIANT:
+        return StructSyntheticProvider(valobj, dict, is_variant=True)
+    if rust_type == RustType.TUPLE:
+        return TupleSyntheticProvider(valobj, dict)
+    if rust_type == RustType.TUPLE_VARIANT:
+        return TupleSyntheticProvider(valobj, dict, is_variant=True)
+    if rust_type == RustType.EMPTY:
+        return EmptySyntheticProvider(valobj, dict)
+    if rust_type == RustType.REGULAR_ENUM:
+        discriminant = valobj.GetChildAtIndex(0).GetChildAtIndex(0).GetValueAsUnsigned()
+        return synthetic_lookup(valobj.GetChildAtIndex(discriminant), dict)
+    if rust_type == RustType.SINGLETON_ENUM:
+        return synthetic_lookup(valobj.GetChildAtIndex(0), dict)
+
+    if rust_type == RustType.STD_VEC:
+        return StdVecSyntheticProvider(valobj, dict)
+    if rust_type == RustType.STD_VEC_DEQUE:
+        return StdVecDequeSyntheticProvider(valobj, dict)
+    if rust_type == RustType.STD_SLICE:
+        return StdSliceSyntheticProvider(valobj, dict)
+
+    if rust_type == RustType.STD_HASH_MAP:
+        if is_hashbrown_hashmap(valobj):
+            return StdHashMapSyntheticProvider(valobj, dict)
+        else:
+            return StdOldHashMapSyntheticProvider(valobj, dict)
+    if rust_type == RustType.STD_HASH_SET:
+        hash_map = valobj.GetChildAtIndex(0)
+        if is_hashbrown_hashmap(hash_map):
+            return StdHashMapSyntheticProvider(hash_map, dict, show_values=False)
+        else:
+            return StdOldHashMapSyntheticProvider(hash_map, dict, show_values=False)
+
+    if rust_type == RustType.STD_RC:
+        return StdRcSyntheticProvider(valobj, dict)
+    if rust_type == RustType.STD_ARC:
+        return StdRcSyntheticProvider(valobj, dict, is_atomic=True)
+
+    if rust_type == RustType.STD_CELL:
+        return StdCellSyntheticProvider(valobj, dict)
+    if rust_type == RustType.STD_REF:
+        return StdRefSyntheticProvider(valobj, dict)
+    if rust_type == RustType.STD_REF_MUT:
+        return StdRefSyntheticProvider(valobj, dict)
+    if rust_type == RustType.STD_REF_CELL:
+        return StdRefSyntheticProvider(valobj, dict, is_cell=True)
+
+    return DefaultSynthteticProvider(valobj, dict)
diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py
new file mode 100644
index 00000000000..3c7817b3a61
--- /dev/null
+++ b/src/etc/lldb_providers.py
@@ -0,0 +1,715 @@
+import sys
+
+from lldb import SBValue, SBData, SBError, eBasicTypeLong, eBasicTypeUnsignedLong, \
+    eBasicTypeUnsignedChar
+
+# from lldb.formatters import Logger
+
+####################################################################################################
+# This file contains two kinds of pretty-printers: summary and synthetic.
+#
+# Important classes from LLDB module:
+#   SBValue: the value of a variable, a register, or an expression
+#   SBType:  the data type; each SBValue has a corresponding SBType
+#
+# Summary provider is a function with the type `(SBValue, dict) -> str`.
+#   The first parameter is the object encapsulating the actual variable being displayed;
+#   The second parameter is an internal support parameter used by LLDB, and you should not touch it.
+#
+# Synthetic children is the way to provide a children-based representation of the object's value.
+# Synthetic provider is a class that implements the following interface:
+#
+#     class SyntheticChildrenProvider:
+#         def __init__(self, SBValue, dict)
+#         def num_children(self)
+#         def get_child_index(self, str)
+#         def get_child_at_index(self, int)
+#         def update(self)
+#         def has_children(self)
+#         def get_value(self)
+#
+#
+# You can find more information and examples here:
+#   1. https://lldb.llvm.org/varformats.html
+#   2. https://lldb.llvm.org/python-reference.html
+#   3. https://lldb.llvm.org/python_reference/lldb.formatters.cpp.libcxx-pysrc.html
+#   4. https://github.com/llvm-mirror/lldb/tree/master/examples/summaries/cocoa
+####################################################################################################
+
+PY3 = sys.version_info[0] == 3
+
+
+class ValueBuilder:
+    def __init__(self, valobj):
+        # type: (SBValue) -> ValueBuilder
+        self.valobj = valobj
+        process = valobj.GetProcess()
+        self.endianness = process.GetByteOrder()
+        self.pointer_size = process.GetAddressByteSize()
+
+    def from_int(self, name, value):
+        # type: (str, int) -> SBValue
+        type = self.valobj.GetType().GetBasicType(eBasicTypeLong)
+        data = SBData.CreateDataFromSInt64Array(self.endianness, self.pointer_size, [value])
+        return self.valobj.CreateValueFromData(name, data, type)
+
+    def from_uint(self, name, value):
+        # type: (str, int) -> SBValue
+        type = self.valobj.GetType().GetBasicType(eBasicTypeUnsignedLong)
+        data = SBData.CreateDataFromUInt64Array(self.endianness, self.pointer_size, [value])
+        return self.valobj.CreateValueFromData(name, data, type)
+
+
+def unwrap_unique_or_non_null(unique_or_nonnull):
+    # BACKCOMPAT: rust 1.32
+    # https://github.com/rust-lang/rust/commit/7a0911528058e87d22ea305695f4047572c5e067
+    ptr = unique_or_nonnull.GetChildMemberWithName("pointer")
+    return ptr if ptr.TypeIsPointerType() else ptr.GetChildAtIndex(0)
+
+
+class DefaultSynthteticProvider:
+    def __init__(self, valobj, dict):
+        # type: (SBValue, dict) -> DefaultSynthteticProvider
+        # logger = Logger.Logger()
+        # logger >> "Default synthetic provider for " + str(valobj.GetName())
+        self.valobj = valobj
+
+    def num_children(self):
+        # type: () -> int
+        return self.valobj.GetNumChildren()
+
+    def get_child_index(self, name):
+        # type: (str) -> int
+        return self.valobj.GetIndexOfChildWithName(name)
+
+    def get_child_at_index(self, index):
+        # type: (int) -> SBValue
+        return self.valobj.GetChildAtIndex(index)
+
+    def update(self):
+        # type: () -> None
+        pass
+
+    def has_children(self):
+        # type: () -> bool
+        return self.valobj.MightHaveChildren()
+
+
+class EmptySyntheticProvider:
+    def __init__(self, valobj, dict):
+        # type: (SBValue, dict) -> EmptySyntheticProvider
+        # logger = Logger.Logger()
+        # logger >> "[EmptySyntheticProvider] for " + str(valobj.GetName())
+        self.valobj = valobj
+
+    def num_children(self):
+        # type: () -> int
+        return 0
+
+    def get_child_index(self, name):
+        # type: (str) -> int
+        return None
+
+    def get_child_at_index(self, index):
+        # type: (int) -> SBValue
+        return None
+
+    def update(self):
+        # type: () -> None
+        pass
+
+    def has_children(self):
+        # type: () -> bool
+        return False
+
+
+def SizeSummaryProvider(valobj, dict):
+    # type: (SBValue, dict) -> str
+    return 'size=' + str(valobj.GetNumChildren())
+
+
+def vec_to_string(vec):
+    length = vec.GetNumChildren()
+    chars = [vec.GetChildAtIndex(i).GetValueAsUnsigned() for i in range(length)]
+    return bytes(chars).decode(errors='replace') if PY3 else "".join(chr(char) for char in chars)
+
+
+def StdStringSummaryProvider(valobj, dict):
+    # type: (SBValue, dict) -> str
+    # logger = Logger.Logger()
+    # logger >> "[StdStringSummaryProvider] for " + str(valobj.GetName())
+    vec = valobj.GetChildAtIndex(0)
+    return '"%s"' % vec_to_string(vec)
+
+
+def StdOsStringSummaryProvider(valobj, dict):
+    # type: (SBValue, dict) -> str
+    # logger = Logger.Logger()
+    # logger >> "[StdOsStringSummaryProvider] for " + str(valobj.GetName())
+    buf = valobj.GetChildAtIndex(0).GetChildAtIndex(0)
+    is_windows = "Wtf8Buf" in buf.type.name
+    vec = buf.GetChildAtIndex(0) if is_windows else buf
+    return '"%s"' % vec_to_string(vec)
+
+
+def StdStrSummaryProvider(valobj, dict):
+    # type: (SBValue, dict) -> str
+    # logger = Logger.Logger()
+    # logger >> "[StdStrSummaryProvider] for " + str(valobj.GetName())
+
+    length = valobj.GetChildMemberWithName("length").GetValueAsUnsigned()
+    if length == 0:
+        return '""'
+
+    data_ptr = valobj.GetChildMemberWithName("data_ptr")
+
+    start = data_ptr.GetValueAsUnsigned()
+    error = SBError()
+    process = data_ptr.GetProcess()
+    data = process.ReadMemory(start, length, error)
+    data = data.decode(encoding='UTF-8') if PY3 else data
+    return '"%s"' % data
+
+
+class StructSyntheticProvider:
+    """Pretty-printer for structs and struct enum variants"""
+
+    def __init__(self, valobj, dict, is_variant=False):
+        # type: (SBValue, dict, bool) -> StructSyntheticProvider
+        # logger = Logger.Logger()
+        self.valobj = valobj
+        self.is_variant = is_variant
+        self.type = valobj.GetType()
+        self.fields = {}
+
+        if is_variant:
+            self.fields_count = self.type.GetNumberOfFields() - 1
+            real_fields = self.type.fields[1:]
+        else:
+            self.fields_count = self.type.GetNumberOfFields()
+            real_fields = self.type.fields
+
+        for number, field in enumerate(real_fields):
+            self.fields[field.name] = number
+
+    def num_children(self):
+        # type: () -> int
+        return self.fields_count
+
+    def get_child_index(self, name):
+        # type: (str) -> int
+        return self.fields.get(name, -1)
+
+    def get_child_at_index(self, index):
+        # type: (int) -> SBValue
+        if self.is_variant:
+            field = self.type.GetFieldAtIndex(index + 1)
+        else:
+            field = self.type.GetFieldAtIndex(index)
+        return self.valobj.GetChildMemberWithName(field.name)
+
+    def update(self):
+        # type: () -> None
+        pass
+
+    def has_children(self):
+        # type: () -> bool
+        return True
+
+
+class TupleSyntheticProvider:
+    """Pretty-printer for tuples and tuple enum variants"""
+
+    def __init__(self, valobj, dict, is_variant=False):
+        # type: (SBValue, dict, bool) -> TupleSyntheticProvider
+        # logger = Logger.Logger()
+        self.valobj = valobj
+        self.is_variant = is_variant
+        self.type = valobj.GetType()
+
+        if is_variant:
+            self.size = self.type.GetNumberOfFields() - 1
+        else:
+            self.size = self.type.GetNumberOfFields()
+
+    def num_children(self):
+        # type: () -> int
+        return self.size
+
+    def get_child_index(self, name):
+        # type: (str) -> int
+        if name.isdigit():
+            return int(name)
+        else:
+            return -1
+
+    def get_child_at_index(self, index):
+        # type: (int) -> SBValue
+        if self.is_variant:
+            field = self.type.GetFieldAtIndex(index + 1)
+        else:
+            field = self.type.GetFieldAtIndex(index)
+        element = self.valobj.GetChildMemberWithName(field.name)
+        return self.valobj.CreateValueFromData(str(index), element.GetData(), element.GetType())
+
+    def update(self):
+        # type: () -> None
+        pass
+
+    def has_children(self):
+        # type: () -> bool
+        return True
+
+
+class StdVecSyntheticProvider:
+    """Pretty-printer for alloc::vec::Vec<T>
+
+    struct Vec<T> { buf: RawVec<T>, len: usize }
+    struct RawVec<T> { ptr: Unique<T>, cap: usize, ... }
+    rust 1.31.1: struct Unique<T: ?Sized> { pointer: NonZero<*const T>, ... }
+    rust 1.33.0: struct Unique<T: ?Sized> { pointer: *const T, ... }
+    struct NonZero<T>(T)
+    """
+
+    def __init__(self, valobj, dict):
+        # type: (SBValue, dict) -> StdVecSyntheticProvider
+        # logger = Logger.Logger()
+        # logger >> "[StdVecSyntheticProvider] for " + str(valobj.GetName())
+        self.valobj = valobj
+        self.update()
+
+    def num_children(self):
+        # type: () -> int
+        return self.length
+
+    def get_child_index(self, name):
+        # type: (str) -> int
+        index = name.lstrip('[').rstrip(']')
+        if index.isdigit():
+            return int(index)
+        else:
+            return -1
+
+    def get_child_at_index(self, index):
+        # type: (int) -> SBValue
+        start = self.data_ptr.GetValueAsUnsigned()
+        address = start + index * self.element_type_size
+        element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.element_type)
+        return element
+
+    def update(self):
+        # type: () -> None
+        self.length = self.valobj.GetChildMemberWithName("len").GetValueAsUnsigned()
+        self.buf = self.valobj.GetChildMemberWithName("buf")
+
+        self.data_ptr = unwrap_unique_or_non_null(self.buf.GetChildMemberWithName("ptr"))
+
+        self.element_type = self.data_ptr.GetType().GetPointeeType()
+        self.element_type_size = self.element_type.GetByteSize()
+
+    def has_children(self):
+        # type: () -> bool
+        return True
+
+
+class StdSliceSyntheticProvider:
+    def __init__(self, valobj, dict):
+        self.valobj = valobj
+        self.update()
+
+    def num_children(self):
+        # type: () -> int
+        return self.length
+
+    def get_child_index(self, name):
+        # type: (str) -> int
+        index = name.lstrip('[').rstrip(']')
+        if index.isdigit():
+            return int(index)
+        else:
+            return -1
+
+    def get_child_at_index(self, index):
+        # type: (int) -> SBValue
+        start = self.data_ptr.GetValueAsUnsigned()
+        address = start + index * self.element_type_size
+        element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.element_type)
+        return element
+
+    def update(self):
+        # type: () -> None
+        self.length = self.valobj.GetChildMemberWithName("length").GetValueAsUnsigned()
+        self.data_ptr = self.valobj.GetChildMemberWithName("data_ptr")
+
+        self.element_type = self.data_ptr.GetType().GetPointeeType()
+        self.element_type_size = self.element_type.GetByteSize()
+
+    def has_children(self):
+        # type: () -> bool
+        return True
+
+
+class StdVecDequeSyntheticProvider:
+    """Pretty-printer for alloc::collections::vec_deque::VecDeque<T>
+
+    struct VecDeque<T> { tail: usize, head: usize, buf: RawVec<T> }
+    """
+
+    def __init__(self, valobj, dict):
+        # type: (SBValue, dict) -> StdVecDequeSyntheticProvider
+        # logger = Logger.Logger()
+        # logger >> "[StdVecDequeSyntheticProvider] for " + str(valobj.GetName())
+        self.valobj = valobj
+        self.update()
+
+    def num_children(self):
+        # type: () -> int
+        return self.size
+
+    def get_child_index(self, name):
+        # type: (str) -> int
+        index = name.lstrip('[').rstrip(']')
+        if index.isdigit() and self.tail <= index and (self.tail + index) % self.cap < self.head:
+            return int(index)
+        else:
+            return -1
+
+    def get_child_at_index(self, index):
+        # type: (int) -> SBValue
+        start = self.data_ptr.GetValueAsUnsigned()
+        address = start + ((index + self.tail) % self.cap) * self.element_type_size
+        element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.element_type)
+        return element
+
+    def update(self):
+        # type: () -> None
+        self.head = self.valobj.GetChildMemberWithName("head").GetValueAsUnsigned()
+        self.tail = self.valobj.GetChildMemberWithName("tail").GetValueAsUnsigned()
+        self.buf = self.valobj.GetChildMemberWithName("buf")
+        self.cap = self.buf.GetChildMemberWithName("cap").GetValueAsUnsigned()
+        if self.head >= self.tail:
+            self.size = self.head - self.tail
+        else:
+            self.size = self.cap + self.head - self.tail
+
+        self.data_ptr = unwrap_unique_or_non_null(self.buf.GetChildMemberWithName("ptr"))
+
+        self.element_type = self.data_ptr.GetType().GetPointeeType()
+        self.element_type_size = self.element_type.GetByteSize()
+
+    def has_children(self):
+        # type: () -> bool
+        return True
+
+
+# BACKCOMPAT: rust 1.35
+class StdOldHashMapSyntheticProvider:
+    """Pretty-printer for std::collections::hash::map::HashMap<K, V, S>
+
+    struct HashMap<K, V, S> {..., table: RawTable<K, V>, ... }
+    struct RawTable<K, V> { capacity_mask: usize, size: usize, hashes: TaggedHashUintPtr, ... }
+    """
+
+    def __init__(self, valobj, dict, show_values=True):
+        # type: (SBValue, dict, bool) -> StdOldHashMapSyntheticProvider
+        self.valobj = valobj
+        self.show_values = show_values
+        self.update()
+
+    def num_children(self):
+        # type: () -> int
+        return self.size
+
+    def get_child_index(self, name):
+        # type: (str) -> int
+        index = name.lstrip('[').rstrip(']')
+        if index.isdigit():
+            return int(index)
+        else:
+            return -1
+
+    def get_child_at_index(self, index):
+        # type: (int) -> SBValue
+        # logger = Logger.Logger()
+        start = self.data_ptr.GetValueAsUnsigned() & ~1
+
+        # See `libstd/collections/hash/table.rs:raw_bucket_at
+        hashes = self.hash_uint_size * self.capacity
+        align = self.pair_type_size
+        # See `libcore/alloc.rs:padding_needed_for`
+        len_rounded_up = (((((hashes + align) % self.modulo - 1) % self.modulo) & ~(
+                (align - 1) % self.modulo)) % self.modulo - hashes) % self.modulo
+        # len_rounded_up = ((hashes + align - 1) & ~(align - 1)) - hashes
+
+        pairs_offset = hashes + len_rounded_up
+        pairs_start = start + pairs_offset
+
+        table_index = self.valid_indices[index]
+        idx = table_index & self.capacity_mask
+        address = pairs_start + idx * self.pair_type_size
+        element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.pair_type)
+        if self.show_values:
+            return element
+        else:
+            key = element.GetChildAtIndex(0)
+            return self.valobj.CreateValueFromData("[%s]" % index, key.GetData(), key.GetType())
+
+    def update(self):
+        # type: () -> None
+        # logger = Logger.Logger()
+
+        self.table = self.valobj.GetChildMemberWithName("table")  # type: SBValue
+        self.size = self.table.GetChildMemberWithName("size").GetValueAsUnsigned()
+        self.hashes = self.table.GetChildMemberWithName("hashes")
+        self.hash_uint_type = self.hashes.GetType()
+        self.hash_uint_size = self.hashes.GetType().GetByteSize()
+        self.modulo = 2 ** self.hash_uint_size
+        self.data_ptr = self.hashes.GetChildAtIndex(0).GetChildAtIndex(0)
+
+        self.capacity_mask = self.table.GetChildMemberWithName("capacity_mask").GetValueAsUnsigned()
+        self.capacity = (self.capacity_mask + 1) % self.modulo
+
+        marker = self.table.GetChildMemberWithName("marker").GetType()  # type: SBType
+        self.pair_type = marker.template_args[0]
+        self.pair_type_size = self.pair_type.GetByteSize()
+
+        self.valid_indices = []
+        for idx in range(self.capacity):
+            address = self.data_ptr.GetValueAsUnsigned() + idx * self.hash_uint_size
+            hash_uint = self.data_ptr.CreateValueFromAddress("[%s]" % idx, address,
+                                                             self.hash_uint_type)
+            hash_ptr = hash_uint.GetChildAtIndex(0).GetChildAtIndex(0)
+            if hash_ptr.GetValueAsUnsigned() != 0:
+                self.valid_indices.append(idx)
+
+        # logger >> "Valid indices: {}".format(str(self.valid_indices))
+
+    def has_children(self):
+        # type: () -> bool
+        return True
+
+
+class StdHashMapSyntheticProvider:
+    """Pretty-printer for hashbrown's HashMap"""
+
+    def __init__(self, valobj, dict, show_values=True):
+        # type: (SBValue, dict, bool) -> StdHashMapSyntheticProvider
+        self.valobj = valobj
+        self.show_values = show_values
+        self.update()
+
+    def num_children(self):
+        # type: () -> int
+        return self.size
+
+    def get_child_index(self, name):
+        # type: (str) -> int
+        index = name.lstrip('[').rstrip(']')
+        if index.isdigit():
+            return int(index)
+        else:
+            return -1
+
+    def get_child_at_index(self, index):
+        # type: (int) -> SBValue
+        pairs_start = self.data_ptr.GetValueAsUnsigned()
+        idx = self.valid_indices[index]
+        address = pairs_start + idx * self.pair_type_size
+        element = self.data_ptr.CreateValueFromAddress("[%s]" % index, address, self.pair_type)
+        if self.show_values:
+            return element
+        else:
+            key = element.GetChildAtIndex(0)
+            return self.valobj.CreateValueFromData("[%s]" % index, key.GetData(), key.GetType())
+
+    def update(self):
+        # type: () -> None
+        table = self.valobj.GetChildMemberWithName("base").GetChildMemberWithName("table")
+        capacity = table.GetChildMemberWithName("bucket_mask").GetValueAsUnsigned() + 1
+        ctrl = table.GetChildMemberWithName("ctrl").GetChildAtIndex(0)
+
+        self.size = table.GetChildMemberWithName("items").GetValueAsUnsigned()
+        self.data_ptr = table.GetChildMemberWithName("data").GetChildAtIndex(0)
+        self.pair_type = self.data_ptr.Dereference().GetType()
+        self.pair_type_size = self.pair_type.GetByteSize()
+
+        u8_type = self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar)
+        u8_type_size = self.valobj.GetTarget().GetBasicType(eBasicTypeUnsignedChar).GetByteSize()
+
+        self.valid_indices = []
+        for idx in range(capacity):
+            address = ctrl.GetValueAsUnsigned() + idx * u8_type_size
+            value = ctrl.CreateValueFromAddress("ctrl[%s]" % idx, address,
+                                                u8_type).GetValueAsUnsigned()
+            is_present = value & 128 == 0
+            if is_present:
+                self.valid_indices.append(idx)
+
+    def has_children(self):
+        # type: () -> bool
+        return True
+
+
+def StdRcSummaryProvider(valobj, dict):
+    # type: (SBValue, dict) -> str
+    strong = valobj.GetChildMemberWithName("strong").GetValueAsUnsigned()
+    weak = valobj.GetChildMemberWithName("weak").GetValueAsUnsigned()
+    return "strong={}, weak={}".format(strong, weak)
+
+
+class StdRcSyntheticProvider:
+    """Pretty-printer for alloc::rc::Rc<T> and alloc::sync::Arc<T>
+
+    struct Rc<T> { ptr: NonNull<RcBox<T>>, ... }
+    rust 1.31.1: struct NonNull<T> { pointer: NonZero<*const T> }
+    rust 1.33.0: struct NonNull<T> { pointer: *const T }
+    struct NonZero<T>(T)
+    struct RcBox<T> { strong: Cell<usize>, weak: Cell<usize>, value: T }
+    struct Cell<T> { value: UnsafeCell<T> }
+    struct UnsafeCell<T> { value: T }
+
+    struct Arc<T> { ptr: NonNull<ArcInner<T>>, ... }
+    struct ArcInner<T> { strong: atomic::AtomicUsize, weak: atomic::AtomicUsize, data: T }
+    struct AtomicUsize { v: UnsafeCell<usize> }
+    """
+
+    def __init__(self, valobj, dict, is_atomic=False):
+        # type: (SBValue, dict, bool) -> StdRcSyntheticProvider
+        self.valobj = valobj
+
+        self.ptr = unwrap_unique_or_non_null(self.valobj.GetChildMemberWithName("ptr"))
+
+        self.value = self.ptr.GetChildMemberWithName("data" if is_atomic else "value")
+
+        self.strong = self.ptr.GetChildMemberWithName("strong").GetChildAtIndex(
+            0).GetChildMemberWithName("value")
+        self.weak = self.ptr.GetChildMemberWithName("weak").GetChildAtIndex(
+            0).GetChildMemberWithName("value")
+
+        self.value_builder = ValueBuilder(valobj)
+
+        self.update()
+
+    def num_children(self):
+        # type: () -> int
+        # Actually there are 3 children, but only the `value` should be shown as a child
+        return 1
+
+    def get_child_index(self, name):
+        # type: (str) -> int
+        if name == "value":
+            return 0
+        if name == "strong":
+            return 1
+        if name == "weak":
+            return 2
+        return -1
+
+    def get_child_at_index(self, index):
+        # type: (int) -> SBValue
+        if index == 0:
+            return self.value
+        if index == 1:
+            return self.value_builder.from_uint("strong", self.strong_count)
+        if index == 2:
+            return self.value_builder.from_uint("weak", self.weak_count)
+
+        return None
+
+    def update(self):
+        # type: () -> None
+        self.strong_count = self.strong.GetValueAsUnsigned()
+        self.weak_count = self.weak.GetValueAsUnsigned() - 1
+
+    def has_children(self):
+        # type: () -> bool
+        return True
+
+
+class StdCellSyntheticProvider:
+    """Pretty-printer for std::cell::Cell"""
+
+    def __init__(self, valobj, dict):
+        # type: (SBValue, dict) -> StdCellSyntheticProvider
+        self.valobj = valobj
+        self.value = valobj.GetChildMemberWithName("value").GetChildAtIndex(0)
+
+    def num_children(self):
+        # type: () -> int
+        return 1
+
+    def get_child_index(self, name):
+        # type: (str) -> int
+        if name == "value":
+            return 0
+        return -1
+
+    def get_child_at_index(self, index):
+        # type: (int) -> SBValue
+        if index == 0:
+            return self.value
+        return None
+
+    def update(self):
+        # type: () -> None
+        pass
+
+    def has_children(self):
+        # type: () -> bool
+        return True
+
+
+def StdRefSummaryProvider(valobj, dict):
+    # type: (SBValue, dict) -> str
+    borrow = valobj.GetChildMemberWithName("borrow").GetValueAsSigned()
+    return "borrow={}".format(borrow) if borrow >= 0 else "borrow_mut={}".format(-borrow)
+
+
+class StdRefSyntheticProvider:
+    """Pretty-printer for std::cell::Ref, std::cell::RefMut, and std::cell::RefCell"""
+
+    def __init__(self, valobj, dict, is_cell=False):
+        # type: (SBValue, dict, bool) -> StdRefSyntheticProvider
+        self.valobj = valobj
+
+        borrow = valobj.GetChildMemberWithName("borrow")
+        value = valobj.GetChildMemberWithName("value")
+        if is_cell:
+            self.borrow = borrow.GetChildMemberWithName("value").GetChildMemberWithName("value")
+            self.value = value.GetChildMemberWithName("value")
+        else:
+            self.borrow = borrow.GetChildMemberWithName("borrow").GetChildMemberWithName(
+                "value").GetChildMemberWithName("value")
+            self.value = value.Dereference()
+
+        self.value_builder = ValueBuilder(valobj)
+
+        self.update()
+
+    def num_children(self):
+        # type: () -> int
+        # Actually there are 2 children, but only the `value` should be shown as a child
+        return 1
+
+    def get_child_index(self, name):
+        if name == "value":
+            return 0
+        if name == "borrow":
+            return 1
+        return -1
+
+    def get_child_at_index(self, index):
+        # type: (int) -> SBValue
+        if index == 0:
+            return self.value
+        if index == 1:
+            return self.value_builder.from_int("borrow", self.borrow_count)
+        return None
+
+    def update(self):
+        # type: () -> None
+        self.borrow_count = self.borrow.GetValueAsSigned()
+
+    def has_children(self):
+        # type: () -> bool
+        return True
diff --git a/src/etc/lldb_rust_formatters.py b/src/etc/lldb_rust_formatters.py
deleted file mode 100644
index 0c4021b36fb..00000000000
--- a/src/etc/lldb_rust_formatters.py
+++ /dev/null
@@ -1,305 +0,0 @@
-import lldb
-import debugger_pretty_printers_common as rustpp
-
-# ===============================================================================
-# LLDB Pretty Printing Module for Rust
-# ===============================================================================
-
-
-class LldbType(rustpp.Type):
-
-    def __init__(self, ty):
-        super(LldbType, self).__init__()
-        self.ty = ty
-        self.fields = None
-
-    def get_unqualified_type_name(self):
-        qualified_name = self.ty.GetName()
-
-        if qualified_name is None:
-            return qualified_name
-
-        return rustpp.extract_type_name(qualified_name).replace("&'static ", "&")
-
-    def get_dwarf_type_kind(self):
-        type_class = self.ty.GetTypeClass()
-
-        if type_class == lldb.eTypeClassStruct:
-            return rustpp.DWARF_TYPE_CODE_STRUCT
-
-        if type_class == lldb.eTypeClassUnion:
-            return rustpp.DWARF_TYPE_CODE_UNION
-
-        if type_class == lldb.eTypeClassPointer:
-            return rustpp.DWARF_TYPE_CODE_PTR
-
-        if type_class == lldb.eTypeClassArray:
-            return rustpp.DWARF_TYPE_CODE_ARRAY
-
-        if type_class == lldb.eTypeClassEnumeration:
-            return rustpp.DWARF_TYPE_CODE_ENUM
-
-        return None
-
-    def get_fields(self):
-        assert ((self.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_STRUCT) or
-                (self.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_UNION))
-        if self.fields is None:
-            self.fields = list(self.ty.fields)
-        return self.fields
-
-    def get_wrapped_value(self):
-        return self.ty
-
-
-class LldbValue(rustpp.Value):
-    def __init__(self, lldb_val):
-        ty = lldb_val.type
-        wty = LldbType(ty)
-        super(LldbValue, self).__init__(wty)
-        self.lldb_val = lldb_val
-        self.children = {}
-
-    def get_child_at_index(self, index):
-        child = self.children.get(index)
-        if child is None:
-            lldb_field = self.lldb_val.GetChildAtIndex(index)
-            child = LldbValue(lldb_field)
-            self.children[index] = child
-        return child
-
-    def as_integer(self):
-        return self.lldb_val.GetValueAsUnsigned()
-
-    def get_wrapped_value(self):
-        return self.lldb_val
-
-
-def print_val(lldb_val, internal_dict):
-    val = LldbValue(lldb_val)
-    type_kind = val.type.get_type_kind()
-
-    if (type_kind == rustpp.TYPE_KIND_REGULAR_STRUCT or
-        type_kind == rustpp.TYPE_KIND_REGULAR_UNION or
-        type_kind == rustpp.TYPE_KIND_EMPTY):
-        return print_struct_val(val,
-                                internal_dict,
-                                omit_first_field=False,
-                                omit_type_name=False,
-                                is_tuple_like=False)
-
-    if type_kind == rustpp.TYPE_KIND_STRUCT_VARIANT:
-        return print_struct_val(val,
-                                internal_dict,
-                                omit_first_field=True,
-                                omit_type_name=False,
-                                is_tuple_like=False)
-
-    if type_kind == rustpp.TYPE_KIND_SLICE:
-        return print_vec_slice_val(val, internal_dict)
-
-    if type_kind == rustpp.TYPE_KIND_STR_SLICE:
-        return print_str_slice_val(val, internal_dict)
-
-    if type_kind == rustpp.TYPE_KIND_STD_VEC:
-        return print_std_vec_val(val, internal_dict)
-
-    if type_kind == rustpp.TYPE_KIND_STD_STRING:
-        return print_std_string_val(val, internal_dict)
-
-    if type_kind == rustpp.TYPE_KIND_TUPLE:
-        return print_struct_val(val,
-                                internal_dict,
-                                omit_first_field=False,
-                                omit_type_name=True,
-                                is_tuple_like=True)
-
-    if type_kind == rustpp.TYPE_KIND_TUPLE_STRUCT:
-        return print_struct_val(val,
-                                internal_dict,
-                                omit_first_field=False,
-                                omit_type_name=False,
-                                is_tuple_like=True)
-
-    if type_kind == rustpp.TYPE_KIND_CSTYLE_VARIANT:
-        return val.type.get_unqualified_type_name()
-
-    if type_kind == rustpp.TYPE_KIND_TUPLE_VARIANT:
-        return print_struct_val(val,
-                                internal_dict,
-                                omit_first_field=True,
-                                omit_type_name=False,
-                                is_tuple_like=True)
-
-    if type_kind == rustpp.TYPE_KIND_SINGLETON_ENUM:
-        return print_val(lldb_val.GetChildAtIndex(0), internal_dict)
-
-    if type_kind == rustpp.TYPE_KIND_PTR:
-        return print_pointer_val(val, internal_dict)
-
-    if type_kind == rustpp.TYPE_KIND_FIXED_SIZE_VEC:
-        return print_fixed_size_vec_val(val, internal_dict)
-
-    if type_kind == rustpp.TYPE_KIND_REGULAR_ENUM:
-        # This is a regular enum, extract the discriminant
-        discriminant_val = rustpp.get_discriminant_value_as_integer(val)
-        return print_val(lldb_val.GetChildAtIndex(discriminant_val), internal_dict)
-
-    if type_kind == rustpp.TYPE_KIND_COMPRESSED_ENUM:
-        encoded_enum_info = rustpp.EncodedEnumInfo(val)
-        if encoded_enum_info.is_null_variant():
-            return encoded_enum_info.get_null_variant_name()
-
-        non_null_val = encoded_enum_info.get_non_null_variant_val()
-        return print_val(non_null_val.get_wrapped_value(), internal_dict)
-
-    # No pretty printer has been found
-    return lldb_val.GetValue()
-
-
-# =---------------------------------------------------------------------------------------
-# Type-Specialized Printing Functions
-# =---------------------------------------------------------------------------------------
-
-def print_struct_val(val, internal_dict, omit_first_field, omit_type_name, is_tuple_like):
-    """
-    Prints a struct, tuple, or tuple struct value with Rust syntax.
-    Ignores any fields before field_start_index.
-    """
-    assert (val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_STRUCT or
-            val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_UNION)
-
-    if omit_type_name:
-        type_name = ""
-    else:
-        type_name = val.type.get_unqualified_type_name()
-
-    if is_tuple_like:
-        template = "%(type_name)s(%(body)s)"
-        separator = ", "
-    else:
-        template = "%(type_name)s {\n%(body)s\n}"
-        separator = ", \n"
-
-    fields = val.type.get_fields()
-
-    def render_child(child_index):
-        this = ""
-        if not is_tuple_like:
-            field_name = fields[child_index].name
-            this += field_name + ": "
-
-        field_val = val.get_child_at_index(child_index)
-
-        if not field_val.get_wrapped_value().IsValid():
-            field = fields[child_index]
-            # LLDB is not good at handling zero-sized values, so we have to help
-            # it a little
-            if field.GetType().GetByteSize() == 0:
-                return this + rustpp.extract_type_name(field.GetType().GetName())
-            else:
-                return this + "<invalid value>"
-
-        return this + print_val(field_val.get_wrapped_value(), internal_dict)
-
-    if omit_first_field:
-        field_start_index = 1
-    else:
-        field_start_index = 0
-
-    body = separator.join([render_child(idx) for idx in range(field_start_index, len(fields))])
-
-    return template % {"type_name": type_name,
-                       "body": body}
-
-
-def print_pointer_val(val, internal_dict):
-    """Prints a pointer value with Rust syntax"""
-    assert val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_PTR
-    sigil = "&"
-    type_name = val.type.get_unqualified_type_name()
-    if type_name and type_name[0:1] in ["&", "*"]:
-        sigil = type_name[0:1]
-
-    return sigil + hex(val.as_integer())
-
-
-def print_fixed_size_vec_val(val, internal_dict):
-    assert val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_ARRAY
-    lldb_val = val.get_wrapped_value()
-
-    output = "["
-
-    for i in range(lldb_val.num_children):
-        output += print_val(lldb_val.GetChildAtIndex(i), internal_dict)
-        if i != lldb_val.num_children - 1:
-            output += ", "
-
-    output += "]"
-    return output
-
-
-def print_vec_slice_val(val, internal_dict):
-    (length, data_ptr) = rustpp.extract_length_and_ptr_from_slice(val)
-    return "&[%s]" % print_array_of_values(val.get_wrapped_value().GetName(),
-                                           data_ptr,
-                                           length,
-                                           internal_dict)
-
-
-def print_std_vec_val(val, internal_dict):
-    (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec(val)
-    return "vec![%s]" % print_array_of_values(val.get_wrapped_value().GetName(),
-                                              data_ptr,
-                                              length,
-                                              internal_dict)
-
-
-def print_str_slice_val(val, internal_dict):
-    (length, data_ptr) = rustpp.extract_length_and_ptr_from_slice(val)
-    return read_utf8_string(data_ptr, length)
-
-
-def print_std_string_val(val, internal_dict):
-    vec = val.get_child_at_index(0)
-    (length, data_ptr, cap) = rustpp.extract_length_ptr_and_cap_from_std_vec(vec)
-    return read_utf8_string(data_ptr, length)
-
-# =-----------------------------------------------------------------------
-# Helper Functions
-# =-----------------------------------------------------------------------
-
-
-def print_array_of_values(array_name, data_ptr_val, length, internal_dict):
-    """Prints a contiguous memory range, interpreting it as values of the
-       pointee-type of data_ptr_val."""
-
-    data_ptr_type = data_ptr_val.type
-    assert data_ptr_type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_PTR
-
-    element_type = data_ptr_type.get_wrapped_value().GetPointeeType()
-    element_type_size = element_type.GetByteSize()
-
-    start_address = data_ptr_val.as_integer()
-    raw_value = data_ptr_val.get_wrapped_value()
-
-    def render_element(i):
-        address = start_address + i * element_type_size
-        element_val = raw_value.CreateValueFromAddress(array_name + ("[%s]" % i),
-                                                       address,
-                                                       element_type)
-        return print_val(element_val, internal_dict)
-
-    return ', '.join([render_element(i) for i in range(length)])
-
-
-def read_utf8_string(ptr_val, byte_count):
-    if byte_count == 0:
-        return '""'
-    error = lldb.SBError()
-    process = ptr_val.get_wrapped_value().GetProcess()
-    data = process.ReadMemory(ptr_val.as_integer(), byte_count, error)
-    if error.Success():
-        return '"%s"' % data.decode(encoding='UTF-8')
-    else:
-        return '<error: %s>' % error.GetCString()
diff --git a/src/etc/rust-lldb b/src/etc/rust-lldb
index 7b9b40e6b4a..28b32ef1ad5 100755
--- a/src/etc/rust-lldb
+++ b/src/etc/rust-lldb
@@ -30,13 +30,5 @@ EOF
     fi
 fi
 
-# Prepare commands that will be loaded before any file on the command line has been loaded
-script_import="command script import \"$RUSTC_SYSROOT/lib/rustlib/etc/lldb_rust_formatters.py\""
-category_definition="type summary add --no-value --python-function lldb_rust_formatters.print_val -x \".*\" --category Rust"
-category_enable="type category enable Rust"
-
 # Call LLDB with the commands added to the argument list
-exec "$lldb" --one-line-before-file "$script_import" \
-    --one-line-before-file "$category_definition" \
-    --one-line-before-file "$category_enable" \
-    "$@"
+exec "$lldb" --source-before-file ./lldb_commands "$@"
diff --git a/src/etc/rust_types.py b/src/etc/rust_types.py
new file mode 100644
index 00000000000..b49fd19ed4c
--- /dev/null
+++ b/src/etc/rust_types.py
@@ -0,0 +1,113 @@
+import re
+
+
+class RustType(object):
+    OTHER = "Other"
+    STRUCT = "Struct"
+    TUPLE = "Tuple"
+    CSTYLE_VARIANT = "CStyleVariant"
+    TUPLE_VARIANT = "TupleVariant"
+    STRUCT_VARIANT = "StructVariant"
+    ENUM = "Enum"
+    EMPTY = "Empty"
+    SINGLETON_ENUM = "SingletonEnum"
+    REGULAR_ENUM = "RegularEnum"
+    COMPRESSED_ENUM = "CompressedEnum"
+    REGULAR_UNION = "RegularUnion"
+
+    STD_STRING = "StdString"
+    STD_OS_STRING = "StdOsString"
+    STD_STR = "StdStr"
+    STD_SLICE = "StdSlice"
+    STD_VEC = "StdVec"
+    STD_VEC_DEQUE = "StdVecDeque"
+    STD_BTREE_SET = "StdBTreeSet"
+    STD_BTREE_MAP = "StdBTreeMap"
+    STD_HASH_MAP = "StdHashMap"
+    STD_HASH_SET = "StdHashSet"
+    STD_RC = "StdRc"
+    STD_ARC = "StdArc"
+    STD_CELL = "StdCell"
+    STD_REF = "StdRef"
+    STD_REF_MUT = "StdRefMut"
+    STD_REF_CELL = "StdRefCell"
+
+
+STD_STRING_REGEX = re.compile(r"^(alloc::(\w+::)+)String$")
+STD_STR_REGEX = re.compile(r"^&str$")
+STD_SLICE_REGEX = re.compile(r"^&\[.+\]$")
+STD_OS_STRING_REGEX = re.compile(r"^(std::ffi::(\w+::)+)OsString$")
+STD_VEC_REGEX = re.compile(r"^(alloc::(\w+::)+)Vec<.+>$")
+STD_VEC_DEQUE_REGEX = re.compile(r"^(alloc::(\w+::)+)VecDeque<.+>$")
+STD_BTREE_SET_REGEX = re.compile(r"^(alloc::(\w+::)+)BTreeSet<.+>$")
+STD_BTREE_MAP_REGEX = re.compile(r"^(alloc::(\w+::)+)BTreeMap<.+>$")
+STD_HASH_MAP_REGEX = re.compile(r"^(std::collections::(\w+::)+)HashMap<.+>$")
+STD_HASH_SET_REGEX = re.compile(r"^(std::collections::(\w+::)+)HashSet<.+>$")
+STD_RC_REGEX = re.compile(r"^(alloc::(\w+::)+)Rc<.+>$")
+STD_ARC_REGEX = re.compile(r"^(alloc::(\w+::)+)Arc<.+>$")
+STD_CELL_REGEX = re.compile(r"^(core::(\w+::)+)Cell<.+>$")
+STD_REF_REGEX = re.compile(r"^(core::(\w+::)+)Ref<.+>$")
+STD_REF_MUT_REGEX = re.compile(r"^(core::(\w+::)+)RefMut<.+>$")
+STD_REF_CELL_REGEX = re.compile(r"^(core::(\w+::)+)RefCell<.+>$")
+
+TUPLE_ITEM_REGEX = re.compile(r"__\d+$")
+
+ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$"
+ENUM_DISR_FIELD_NAME = "<<variant>>"
+
+STD_TYPE_TO_REGEX = {
+    RustType.STD_STRING: STD_STRING_REGEX,
+    RustType.STD_OS_STRING: STD_OS_STRING_REGEX,
+    RustType.STD_STR: STD_STR_REGEX,
+    RustType.STD_SLICE: STD_SLICE_REGEX,
+    RustType.STD_VEC: STD_VEC_REGEX,
+    RustType.STD_VEC_DEQUE: STD_VEC_DEQUE_REGEX,
+    RustType.STD_HASH_MAP: STD_HASH_MAP_REGEX,
+    RustType.STD_HASH_SET: STD_HASH_SET_REGEX,
+    RustType.STD_BTREE_SET: STD_BTREE_SET_REGEX,
+    RustType.STD_BTREE_MAP: STD_BTREE_MAP_REGEX,
+    RustType.STD_RC: STD_RC_REGEX,
+    RustType.STD_ARC: STD_ARC_REGEX,
+    RustType.STD_REF: STD_REF_REGEX,
+    RustType.STD_REF_MUT: STD_REF_MUT_REGEX,
+    RustType.STD_REF_CELL: STD_REF_CELL_REGEX,
+    RustType.STD_CELL: STD_CELL_REGEX,
+}
+
+def is_tuple_fields(fields):
+    # type: (list) -> bool
+    return all(TUPLE_ITEM_REGEX.match(str(field.name)) for field in fields)
+
+
+def classify_struct(name, fields):
+    if len(fields) == 0:
+        return RustType.EMPTY
+
+    for ty, regex in STD_TYPE_TO_REGEX.items():
+        if regex.match(name):
+            return ty
+
+    if fields[0].name == ENUM_DISR_FIELD_NAME:
+        return RustType.ENUM
+
+    if is_tuple_fields(fields):
+        return RustType.TUPLE
+
+    return RustType.STRUCT
+
+
+def classify_union(fields):
+    if len(fields) == 0:
+        return RustType.EMPTY
+
+    first_variant_name = fields[0].name
+    if first_variant_name is None:
+        if len(fields) == 1:
+            return RustType.SINGLETON_ENUM
+        else:
+            return RustType.REGULAR_ENUM
+    elif first_variant_name.startswith(ENCODED_ENUM_PREFIX):
+        assert len(fields) == 1
+        return RustType.COMPRESSED_ENUM
+    else:
+        return RustType.REGULAR_UNION
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 925bc7d3c02..0327a9f9a96 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -2034,7 +2034,7 @@ trait RcBoxPtr<T: ?Sized> {
         // The reference count will never be zero when this is called;
         // nevertheless, we insert an abort here to hint LLVM at
         // an otherwise missed optimization.
-        if strong == 0 || strong == usize::max_value() {
+        if strong == 0 || strong == usize::MAX {
             abort();
         }
         self.inner().strong.set(strong + 1);
@@ -2058,7 +2058,7 @@ trait RcBoxPtr<T: ?Sized> {
         // The reference count will never be zero when this is called;
         // nevertheless, we insert an abort here to hint LLVM at
         // an otherwise missed optimization.
-        if weak == 0 || weak == usize::max_value() {
+        if weak == 0 || weak == usize::MAX {
             abort();
         }
         self.inner().weak.set(weak + 1);
diff --git a/src/liballoc/rc/tests.rs b/src/liballoc/rc/tests.rs
index 56788bb56d5..e88385faf4f 100644
--- a/src/liballoc/rc/tests.rs
+++ b/src/liballoc/rc/tests.rs
@@ -407,14 +407,14 @@ fn test_from_vec() {
 fn test_downcast() {
     use std::any::Any;
 
-    let r1: Rc<dyn Any> = Rc::new(i32::max_value());
+    let r1: Rc<dyn Any> = Rc::new(i32::MAX);
     let r2: Rc<dyn Any> = Rc::new("abc");
 
     assert!(r1.clone().downcast::<u32>().is_err());
 
     let r1i32 = r1.downcast::<i32>();
     assert!(r1i32.is_ok());
-    assert_eq!(r1i32.unwrap(), Rc::new(i32::max_value()));
+    assert_eq!(r1i32.unwrap(), Rc::new(i32::MAX));
 
     assert!(r2.clone().downcast::<i32>().is_err());
 
diff --git a/src/liballoc/sync/tests.rs b/src/liballoc/sync/tests.rs
index a2bb651e2b7..6f08cd7f123 100644
--- a/src/liballoc/sync/tests.rs
+++ b/src/liballoc/sync/tests.rs
@@ -465,14 +465,14 @@ fn test_from_vec() {
 fn test_downcast() {
     use std::any::Any;
 
-    let r1: Arc<dyn Any + Send + Sync> = Arc::new(i32::max_value());
+    let r1: Arc<dyn Any + Send + Sync> = Arc::new(i32::MAX);
     let r2: Arc<dyn Any + Send + Sync> = Arc::new("abc");
 
     assert!(r1.clone().downcast::<u32>().is_err());
 
     let r1i32 = r1.downcast::<i32>();
     assert!(r1i32.is_ok());
-    assert_eq!(r1i32.unwrap(), Arc::new(i32::max_value()));
+    assert_eq!(r1i32.unwrap(), Arc::new(i32::MAX));
 
     assert!(r2.clone().downcast::<i32>().is_err());
 
diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs
index b703df6f3cb..eee98d45340 100644
--- a/src/liballoc/tests/str.rs
+++ b/src/liballoc/tests/str.rs
@@ -566,13 +566,13 @@ mod slice_index {
                 data: "hello";
                 // note: using 0 specifically ensures that the result of overflowing is 0..0,
                 //       so that `get` doesn't simply return None for the wrong reason.
-                bad: data[0..=usize::max_value()];
+                bad: data[0..=usize::MAX];
                 message: "maximum usize";
             }
 
             in mod rangetoinclusive {
                 data: "hello";
-                bad: data[..=usize::max_value()];
+                bad: data[..=usize::MAX];
                 message: "maximum usize";
             }
         }
diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs
index b73fd95ab6a..a9813a8704f 100644
--- a/src/liballoc/tests/vec.rs
+++ b/src/liballoc/tests/vec.rs
@@ -68,7 +68,7 @@ fn test_reserve() {
 
 #[test]
 fn test_zst_capacity() {
-    assert_eq!(Vec::<()>::new().capacity(), usize::max_value());
+    assert_eq!(Vec::<()>::new().capacity(), usize::MAX);
 }
 
 #[test]
@@ -563,19 +563,19 @@ fn test_drain_inclusive_range() {
 
 #[test]
 fn test_drain_max_vec_size() {
-    let mut v = Vec::<()>::with_capacity(usize::max_value());
+    let mut v = Vec::<()>::with_capacity(usize::MAX);
     unsafe {
-        v.set_len(usize::max_value());
+        v.set_len(usize::MAX);
     }
-    for _ in v.drain(usize::max_value() - 1..) {}
-    assert_eq!(v.len(), usize::max_value() - 1);
+    for _ in v.drain(usize::MAX - 1..) {}
+    assert_eq!(v.len(), usize::MAX - 1);
 
-    let mut v = Vec::<()>::with_capacity(usize::max_value());
+    let mut v = Vec::<()>::with_capacity(usize::MAX);
     unsafe {
-        v.set_len(usize::max_value());
+        v.set_len(usize::MAX);
     }
-    for _ in v.drain(usize::max_value() - 1..=usize::max_value() - 1) {}
-    assert_eq!(v.len(), usize::max_value() - 1);
+    for _ in v.drain(usize::MAX - 1..=usize::MAX - 1) {}
+    assert_eq!(v.len(), usize::MAX - 1);
 }
 
 #[test]
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index 2226737757b..06462fd96d9 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -2779,19 +2779,25 @@ impl<'a, T> Drain<'a, T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(vec_drain_as_slice)]
     /// let mut vec = vec!['a', 'b', 'c'];
     /// let mut drain = vec.drain(..);
     /// assert_eq!(drain.as_slice(), &['a', 'b', 'c']);
     /// let _ = drain.next().unwrap();
     /// assert_eq!(drain.as_slice(), &['b', 'c']);
     /// ```
-    #[unstable(feature = "vec_drain_as_slice", reason = "recently added", issue = "58957")]
+    #[stable(feature = "vec_drain_as_slice", since = "1.46.0")]
     pub fn as_slice(&self) -> &[T] {
         self.iter.as_slice()
     }
 }
 
+#[stable(feature = "vec_drain_as_slice", since = "1.46.0")]
+impl<'a, T> AsRef<[T]> for Drain<'a, T> {
+    fn as_ref(&self) -> &[T] {
+        self.as_slice()
+    }
+}
+
 #[stable(feature = "drain", since = "1.6.0")]
 unsafe impl<T: Sync> Sync for Drain<'_, T> {}
 #[stable(feature = "drain", since = "1.6.0")]
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index c4c1d2824b0..c4293ed7bcf 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -778,18 +778,13 @@ impl<T: ?Sized> RefCell<T> {
     ///
     /// An example of panic:
     ///
-    /// ```
+    /// ```should_panic
     /// use std::cell::RefCell;
-    /// use std::thread;
-    ///
-    /// let result = thread::spawn(move || {
-    ///    let c = RefCell::new(5);
-    ///    let m = c.borrow_mut();
     ///
-    ///    let b = c.borrow(); // this causes a panic
-    /// }).join();
+    /// let c = RefCell::new(5);
     ///
-    /// assert!(result.is_err());
+    /// let m = c.borrow_mut();
+    /// let b = c.borrow(); // this causes a panic
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -858,18 +853,13 @@ impl<T: ?Sized> RefCell<T> {
     ///
     /// An example of panic:
     ///
-    /// ```
+    /// ```should_panic
     /// use std::cell::RefCell;
-    /// use std::thread;
-    ///
-    /// let result = thread::spawn(move || {
-    ///    let c = RefCell::new(5);
-    ///    let m = c.borrow();
     ///
-    ///    let b = c.borrow_mut(); // this causes a panic
-    /// }).join();
+    /// let c = RefCell::new(5);
+    /// let m = c.borrow();
     ///
-    /// assert!(result.is_err());
+    /// let b = c.borrow_mut(); // this causes a panic
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -1163,8 +1153,8 @@ impl<'b> BorrowRef<'b> {
             // Incrementing borrow can result in a non-reading value (<= 0) in these cases:
             // 1. It was < 0, i.e. there are writing borrows, so we can't allow a read borrow
             //    due to Rust's reference aliasing rules
-            // 2. It was isize::max_value() (the max amount of reading borrows) and it overflowed
-            //    into isize::min_value() (the max amount of writing borrows) so we can't allow
+            // 2. It was isize::MAX (the max amount of reading borrows) and it overflowed
+            //    into isize::MIN (the max amount of writing borrows) so we can't allow
             //    an additional read borrow because isize can't represent so many read borrows
             //    (this can only happen if you mem::forget more than a small constant amount of
             //    `Ref`s, which is not good practice)
@@ -1172,7 +1162,7 @@ impl<'b> BorrowRef<'b> {
         } else {
             // Incrementing borrow can result in a reading value (> 0) in these cases:
             // 1. It was = 0, i.e. it wasn't borrowed, and we are taking the first read borrow
-            // 2. It was > 0 and < isize::max_value(), i.e. there were read borrows, and isize
+            // 2. It was > 0 and < isize::MAX, i.e. there were read borrows, and isize
             //    is large enough to represent having one more read borrow
             borrow.set(b);
             Some(BorrowRef { borrow })
@@ -1198,7 +1188,7 @@ impl Clone for BorrowRef<'_> {
         debug_assert!(is_reading(borrow));
         // Prevent the borrow counter from overflowing into
         // a writing borrow.
-        assert!(borrow != isize::max_value());
+        assert!(borrow != isize::MAX);
         self.borrow.set(borrow + 1);
         BorrowRef { borrow: self.borrow }
     }
@@ -1489,7 +1479,7 @@ impl<'b> BorrowRefMut<'b> {
         let borrow = self.borrow.get();
         debug_assert!(is_writing(borrow));
         // Prevent the borrow counter from underflowing.
-        assert!(borrow != isize::min_value());
+        assert!(borrow != isize::MIN);
         self.borrow.set(borrow - 1);
         BorrowRefMut { borrow: self.borrow }
     }
diff --git a/src/libcore/char/convert.rs b/src/libcore/char/convert.rs
index 87c56c4b0a1..d7e39946148 100644
--- a/src/libcore/char/convert.rs
+++ b/src/libcore/char/convert.rs
@@ -278,16 +278,11 @@ impl fmt::Display for CharTryFromError {
 ///
 /// Passing a large radix, causing a panic:
 ///
-/// ```
-/// use std::thread;
+/// ```should_panic
 /// use std::char;
 ///
-/// let result = thread::spawn(|| {
-///     // this panics
-///     let c = char::from_digit(1, 37);
-/// }).join();
-///
-/// assert!(result.is_err());
+/// // this panics
+/// let c = char::from_digit(1, 37);
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs
index bf09b28ff69..dd2f01c679f 100644
--- a/src/libcore/char/methods.rs
+++ b/src/libcore/char/methods.rs
@@ -229,16 +229,11 @@ impl char {
     ///
     /// Passing a large radix, causing a panic:
     ///
-    /// ```
-    /// use std::thread;
+    /// ```should_panic
     /// use std::char;
     ///
-    /// let result = thread::spawn(|| {
-    ///     // this panics
-    ///     let c = char::from_digit(1, 37);
-    /// }).join();
-    ///
-    /// assert!(result.is_err());
+    /// // this panics
+    /// char::from_digit(1, 37);
     /// ```
     #[unstable(feature = "assoc_char_funcs", reason = "recently added", issue = "71763")]
     #[inline]
@@ -282,15 +277,9 @@ impl char {
     ///
     /// Passing a large radix, causing a panic:
     ///
-    /// ```
-    /// use std::thread;
-    ///
-    /// let result = thread::spawn(|| {
-    ///     // this panics
-    ///     '1'.is_digit(37);
-    /// }).join();
-    ///
-    /// assert!(result.is_err());
+    /// ```should_panic
+    /// // this panics
+    /// '1'.is_digit(37);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -337,14 +326,9 @@ impl char {
     ///
     /// Passing a large radix, causing a panic:
     ///
-    /// ```
-    /// use std::thread;
-    ///
-    /// let result = thread::spawn(|| {
-    ///     '1'.to_digit(37);
-    /// }).join();
-    ///
-    /// assert!(result.is_err());
+    /// ```should_panic
+    /// // this panics
+    /// '1'.to_digit(37);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -646,17 +630,11 @@ impl char {
     ///
     /// A buffer that's too small:
     ///
-    /// ```
-    /// use std::thread;
-    ///
-    /// let result = thread::spawn(|| {
-    ///     let mut b = [0; 1];
-    ///
-    ///     // this panics
-    ///    'ß'.encode_utf8(&mut b);
-    /// }).join();
+    /// ```should_panic
+    /// let mut b = [0; 1];
     ///
-    /// assert!(result.is_err());
+    /// // this panics
+    /// 'ß'.encode_utf8(&mut b);
     /// ```
     #[stable(feature = "unicode_encode_char", since = "1.15.0")]
     #[inline]
@@ -687,17 +665,11 @@ impl char {
     ///
     /// A buffer that's too small:
     ///
-    /// ```
-    /// use std::thread;
-    ///
-    /// let result = thread::spawn(|| {
-    ///     let mut b = [0; 1];
-    ///
-    ///     // this panics
-    ///     '𝕊'.encode_utf16(&mut b);
-    /// }).join();
+    /// ```should_panic
+    /// let mut b = [0; 1];
     ///
-    /// assert!(result.is_err());
+    /// // this panics
+    /// '𝕊'.encode_utf16(&mut b);
     /// ```
     #[stable(feature = "unicode_encode_char", since = "1.15.0")]
     #[inline]
diff --git a/src/libcore/convert/num.rs b/src/libcore/convert/num.rs
index 6dd0522f7f6..5ff52a9a11b 100644
--- a/src/libcore/convert/num.rs
+++ b/src/libcore/convert/num.rs
@@ -217,7 +217,7 @@ macro_rules! try_from_upper_bounded {
             /// is outside of the range of the target type.
             #[inline]
             fn try_from(u: $source) -> Result<Self, Self::Error> {
-                if u > (Self::max_value() as $source) {
+                if u > (Self::MAX as $source) {
                     Err(TryFromIntError(()))
                 } else {
                     Ok(u as Self)
@@ -239,8 +239,8 @@ macro_rules! try_from_both_bounded {
             /// is outside of the range of the target type.
             #[inline]
             fn try_from(u: $source) -> Result<Self, Self::Error> {
-                let min = Self::min_value() as $source;
-                let max = Self::max_value() as $source;
+                let min = Self::MIN as $source;
+                let max = Self::MAX as $source;
                 if u < min || u > max {
                     Err(TryFromIntError(()))
                 } else {
diff --git a/src/libcore/future/mod.rs b/src/libcore/future/mod.rs
index 6f6009b47e6..9dbc23f5c04 100644
--- a/src/libcore/future/mod.rs
+++ b/src/libcore/future/mod.rs
@@ -56,6 +56,7 @@ pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
 where
     T: Generator<ResumeTy, Yield = ()>,
 {
+    #[rustc_diagnostic_item = "gen_future"]
     struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T);
 
     // We rely on the fact that async/await futures are immovable in order to create
diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs
index a10b34d931d..fbfcdc3c1a9 100644
--- a/src/libcore/iter/traits/iterator.rs
+++ b/src/libcore/iter/traits/iterator.rs
@@ -2717,12 +2717,12 @@ pub trait Iterator {
     /// ```
     /// let a = [1, 2, 3];
     ///
-    /// let v_cloned: Vec<_> = a.iter().copied().collect();
+    /// let v_copied: Vec<_> = a.iter().copied().collect();
     ///
     /// // copied is the same as .map(|&x| x)
     /// let v_map: Vec<_> = a.iter().map(|&x| x).collect();
     ///
-    /// assert_eq!(v_cloned, vec![1, 2, 3]);
+    /// assert_eq!(v_copied, vec![1, 2, 3]);
     /// assert_eq!(v_map, vec![1, 2, 3]);
     /// ```
     #[stable(feature = "iter_copied", since = "1.36.0")]
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 7d21f9a9a66..fe05e914e6d 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -145,7 +145,6 @@
 #![feature(associated_type_bounds)]
 #![feature(const_type_id)]
 #![feature(const_caller_location)]
-#![feature(option_zip)]
 #![feature(no_niche)] // rust-lang/rust#68303
 
 #[prelude_import]
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index c164e893b4f..b1317bc2121 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -750,9 +750,9 @@ $EndFeature, "
         }
 
         doc_comment! {
-            concat!("Unchecked integer addition. Computes `self + rhs, assuming overflow
+            concat!("Unchecked integer addition. Computes `self + rhs`, assuming overflow
 cannot occur. This results in undefined behavior when `self + rhs > ", stringify!($SelfT),
-"::max_value()` or `self + rhs < ", stringify!($SelfT), "::min_value()`."),
+"::MAX` or `self + rhs < ", stringify!($SelfT), "::MIN`."),
             #[unstable(
                 feature = "unchecked_math",
                 reason = "niche optimization path",
@@ -792,9 +792,9 @@ $EndFeature, "
         }
 
         doc_comment! {
-            concat!("Unchecked integer subtraction. Computes `self - rhs, assuming overflow
+            concat!("Unchecked integer subtraction. Computes `self - rhs`, assuming overflow
 cannot occur. This results in undefined behavior when `self - rhs > ", stringify!($SelfT),
-"::max_value()` or `self - rhs < ", stringify!($SelfT), "::min_value()`."),
+"::MAX` or `self - rhs < ", stringify!($SelfT), "::MIN`."),
             #[unstable(
                 feature = "unchecked_math",
                 reason = "niche optimization path",
@@ -834,9 +834,9 @@ $EndFeature, "
         }
 
         doc_comment! {
-            concat!("Unchecked integer multiplication. Computes `self * rhs, assuming overflow
+            concat!("Unchecked integer multiplication. Computes `self * rhs`, assuming overflow
 cannot occur. This results in undefined behavior when `self * rhs > ", stringify!($SelfT),
-"::max_value()` or `self * rhs < ", stringify!($SelfT), "::min_value()`."),
+"::MAX` or `self * rhs < ", stringify!($SelfT), "::MIN`."),
             #[unstable(
                 feature = "unchecked_math",
                 reason = "niche optimization path",
@@ -871,7 +871,7 @@ $EndFeature, "
                           without modifying the original"]
             #[inline]
             pub const fn checked_div(self, rhs: Self) -> Option<Self> {
-                if rhs == 0 || (self == Self::min_value() && rhs == -1) {
+                if rhs == 0 || (self == Self::MIN && rhs == -1) {
                     None
                 } else {
                     // SAFETY: div by zero and by INT_MIN have been checked above
@@ -900,7 +900,7 @@ assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None);
                           without modifying the original"]
             #[inline]
             pub const fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
-                if rhs == 0 || (self == Self::min_value() && rhs == -1) {
+                if rhs == 0 || (self == Self::MIN && rhs == -1) {
                     None
                 } else {
                     Some(self.div_euclid(rhs))
@@ -929,7 +929,7 @@ $EndFeature, "
                           without modifying the original"]
             #[inline]
             pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
-                if rhs == 0 || (self == Self::min_value() && rhs == -1) {
+                if rhs == 0 || (self == Self::MIN && rhs == -1) {
                     None
                 } else {
                     // SAFETY: div by zero and by INT_MIN have been checked above
@@ -957,7 +957,7 @@ assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None);
                           without modifying the original"]
             #[inline]
             pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
-                if rhs == 0 || (self == Self::min_value() && rhs == -1) {
+                if rhs == 0 || (self == Self::MIN && rhs == -1) {
                     None
                 } else {
                     Some(self.rem_euclid(rhs))
@@ -1236,9 +1236,9 @@ $EndFeature, "
                 match self.checked_mul(rhs) {
                     Some(x) => x,
                     None => if (self < 0) == (rhs < 0) {
-                        Self::max_value()
+                        Self::MAX
                     } else {
-                        Self::min_value()
+                        Self::MIN
                     }
                 }
             }
@@ -1267,8 +1267,8 @@ $EndFeature, "
             pub const fn saturating_pow(self, exp: u32) -> Self {
                 match self.checked_pow(exp) {
                     Some(x) => x,
-                    None if self < 0 && exp % 2 == 1 => Self::min_value(),
-                    None => Self::max_value(),
+                    None if self < 0 && exp % 2 == 1 => Self::MIN,
+                    None => Self::MAX,
                 }
             }
         }
@@ -1738,7 +1738,7 @@ $EndFeature, "
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) {
-                if self == Self::min_value() && rhs == -1 {
+                if self == Self::MIN && rhs == -1 {
                     (self, true)
                 } else {
                     (self / rhs, false)
@@ -1771,7 +1771,7 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringi
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
-                if self == Self::min_value() && rhs == -1 {
+                if self == Self::MIN && rhs == -1 {
                     (self, true)
                 } else {
                     (self.div_euclid(rhs), false)
@@ -1805,7 +1805,7 @@ $EndFeature, "
             #[must_use = "this returns the result of the operation, \
                           without modifying the original"]
             pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
-                if self == Self::min_value() && rhs == -1 {
+                if self == Self::MIN && rhs == -1 {
                     (0, true)
                 } else {
                     (self % rhs, false)
@@ -1838,7 +1838,7 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true));
                           without modifying the original"]
             #[inline]
             pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
-                if self == Self::min_value() && rhs == -1 {
+                if self == Self::MIN && rhs == -1 {
                     (0, true)
                 } else {
                     (self.rem_euclid(rhs), false)
@@ -1869,8 +1869,8 @@ assert_eq!(", stringify!($SelfT), "::MIN.overflowing_neg(), (", stringify!($Self
             #[allow(unused_attributes)]
             #[allow_internal_unstable(const_if_match)]
             pub const fn overflowing_neg(self) -> (Self, bool) {
-                if self == Self::min_value() {
-                    (Self::min_value(), true)
+                if self == Self::MIN {
+                    (Self::MIN, true)
                 } else {
                     (-self, false)
                 }
@@ -1952,7 +1952,7 @@ $EndFeature, "
             #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")]
             #[inline]
             pub const fn overflowing_abs(self) -> (Self, bool) {
-                (self.wrapping_abs(), self == Self::min_value())
+                (self.wrapping_abs(), self == Self::MIN)
             }
         }
 
@@ -2986,9 +2986,9 @@ assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(3), None);", $EndFeat
         }
 
         doc_comment! {
-            concat!("Unchecked integer addition. Computes `self + rhs, assuming overflow
+            concat!("Unchecked integer addition. Computes `self + rhs`, assuming overflow
 cannot occur. This results in undefined behavior when `self + rhs > ", stringify!($SelfT),
-"::max_value()` or `self + rhs < ", stringify!($SelfT), "::min_value()`."),
+"::MAX` or `self + rhs < ", stringify!($SelfT), "::MIN`."),
             #[unstable(
                 feature = "unchecked_math",
                 reason = "niche optimization path",
@@ -3026,9 +3026,9 @@ assert_eq!(0", stringify!($SelfT), ".checked_sub(1), None);", $EndFeature, "
         }
 
         doc_comment! {
-            concat!("Unchecked integer subtraction. Computes `self - rhs, assuming overflow
+            concat!("Unchecked integer subtraction. Computes `self - rhs`, assuming overflow
 cannot occur. This results in undefined behavior when `self - rhs > ", stringify!($SelfT),
-"::max_value()` or `self - rhs < ", stringify!($SelfT), "::min_value()`."),
+"::MAX` or `self - rhs < ", stringify!($SelfT), "::MIN`."),
             #[unstable(
                 feature = "unchecked_math",
                 reason = "niche optimization path",
@@ -3066,9 +3066,9 @@ assert_eq!(", stringify!($SelfT), "::MAX.checked_mul(2), None);", $EndFeature, "
         }
 
         doc_comment! {
-            concat!("Unchecked integer multiplication. Computes `self * rhs, assuming overflow
+            concat!("Unchecked integer multiplication. Computes `self * rhs`, assuming overflow
 cannot occur. This results in undefined behavior when `self * rhs > ", stringify!($SelfT),
-"::max_value()` or `self * rhs < ", stringify!($SelfT), "::min_value()`."),
+"::MAX` or `self * rhs < ", stringify!($SelfT), "::MIN`."),
             #[unstable(
                 feature = "unchecked_math",
                 reason = "niche optimization path",
@@ -3309,7 +3309,8 @@ Basic usage:
 
 ```
 ", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_add(1), 101);
-assert_eq!(200u8.saturating_add(127), 255);", $EndFeature, "
+assert_eq!(", stringify!($SelfT), "::MAX.saturating_add(127), ", stringify!($SelfT), "::MAX);",
+$EndFeature, "
 ```"),
 
             #[stable(feature = "rust1", since = "1.0.0")]
@@ -3366,7 +3367,7 @@ assert_eq!((", stringify!($SelfT), "::MAX).saturating_mul(10), ", stringify!($Se
             pub const fn saturating_mul(self, rhs: Self) -> Self {
                 match self.checked_mul(rhs) {
                     Some(x) => x,
-                    None => Self::max_value(),
+                    None => Self::MAX,
                 }
             }
         }
@@ -3393,7 +3394,7 @@ $EndFeature, "
             pub const fn saturating_pow(self, exp: u32) -> Self {
                 match self.checked_pow(exp) {
                     Some(x) => x,
-                    None => Self::max_value(),
+                    None => Self::MAX,
                 }
             }
         }
@@ -4080,7 +4081,7 @@ Basic usage:
         }
     }
 
-            doc_comment! {
+        doc_comment! {
             concat!("Performs Euclidean division.
 
 Since, for the positive integers, all common
@@ -4178,7 +4179,7 @@ assert!(!10", stringify!($SelfT), ".is_power_of_two());", $EndFeature, "
             // (such as intel pre-haswell) have more efficient ctlz
             // intrinsics when the argument is non-zero.
             let z = unsafe { intrinsics::ctlz_nonzero(p) };
-            <$SelfT>::max_value() >> z
+            <$SelfT>::MAX >> z
         }
 
         doc_comment! {
@@ -5160,9 +5161,9 @@ trait FromStrRadixHelper: PartialOrd + Copy {
 macro_rules! doit {
     ($($t:ty)*) => ($(impl FromStrRadixHelper for $t {
         #[inline]
-        fn min_value() -> Self { Self::min_value() }
+        fn min_value() -> Self { Self::MIN }
         #[inline]
-        fn max_value() -> Self { Self::max_value() }
+        fn max_value() -> Self { Self::MAX }
         #[inline]
         fn from_u32(u: u32) -> Self { u as Self }
         #[inline]
diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs
index bb648ba8c25..f6acb8f8b9a 100644
--- a/src/libcore/num/wrapping.rs
+++ b/src/libcore/num/wrapping.rs
@@ -694,7 +694,7 @@ Basic usage:
 #![feature(wrapping_int_impl)]
 use std::num::Wrapping;
 
-let n = Wrapping(", stringify!($t), "::max_value()) >> 2;
+let n = Wrapping(", stringify!($t), "::MAX) >> 2;
 
 assert_eq!(n.leading_zeros(), 3);
 ```"),
@@ -723,8 +723,7 @@ use std::num::Wrapping;
 
 assert_eq!(Wrapping(100", stringify!($t), ").abs(), Wrapping(100));
 assert_eq!(Wrapping(-100", stringify!($t), ").abs(), Wrapping(100));
-assert_eq!(Wrapping(", stringify!($t), "::min_value()).abs(), Wrapping(", stringify!($t),
-"::min_value()));
+assert_eq!(Wrapping(", stringify!($t), "::MIN).abs(), Wrapping(", stringify!($t), "::MIN));
 assert_eq!(Wrapping(-128i8).abs().0 as u8, 128u8);
 ```"),
                 #[inline]
@@ -823,7 +822,7 @@ Basic usage:
 #![feature(wrapping_int_impl)]
 use std::num::Wrapping;
 
-let n = Wrapping(", stringify!($t), "::max_value()) >> 2;
+let n = Wrapping(", stringify!($t), "::MAX) >> 2;
 
 assert_eq!(n.leading_zeros(), 2);
 ```"),
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index e8483875c97..5f0a12678ff 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -926,7 +926,6 @@ impl<T> Option<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(option_zip)]
     /// let x = Some(1);
     /// let y = Some("hi");
     /// let z = None::<u8>;
@@ -934,9 +933,12 @@ impl<T> Option<T> {
     /// assert_eq!(x.zip(y), Some((1, "hi")));
     /// assert_eq!(x.zip(z), None);
     /// ```
-    #[unstable(feature = "option_zip", issue = "70086")]
+    #[stable(feature = "option_zip_option", since = "1.46.0")]
     pub fn zip<U>(self, other: Option<U>) -> Option<(T, U)> {
-        self.zip_with(other, |a, b| (a, b))
+        match (self, other) {
+            (Some(a), Some(b)) => Some((a, b)),
+            _ => None,
+        }
     }
 
     /// Zips `self` and another `Option` with function `f`.
diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs
index 835183d171a..e39d18d7733 100644
--- a/src/libcore/ptr/const_ptr.rs
+++ b/src/libcore/ptr/const_ptr.rs
@@ -291,7 +291,7 @@ impl<T: ?Sized> *const T {
         T: Sized,
     {
         let pointee_size = mem::size_of::<T>();
-        assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize);
+        assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
         intrinsics::ptr_offset_from(self, origin)
     }
 
@@ -336,7 +336,7 @@ impl<T: ?Sized> *const T {
         T: Sized,
     {
         let pointee_size = mem::size_of::<T>();
-        assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize);
+        assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
 
         let d = isize::wrapping_sub(self as _, origin as _);
         d.wrapping_div(pointee_size as _)
diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs
index ecc70adda41..1be05d5efff 100644
--- a/src/libcore/ptr/mod.rs
+++ b/src/libcore/ptr/mod.rs
@@ -1128,7 +1128,7 @@ pub(crate) unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize {
                 //
                 // Note, that we use wrapping operations here intentionally – the original formula
                 // uses e.g., subtraction `mod n`. It is entirely fine to do them `mod
-                // usize::max_value()` instead, because we take the result `mod n` at the end
+                // usize::MAX` instead, because we take the result `mod n` at the end
                 // anyway.
                 inverse = inverse.wrapping_mul(2usize.wrapping_sub(x.wrapping_mul(inverse)));
                 if going_mod >= m {
@@ -1193,7 +1193,7 @@ pub(crate) unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize {
     }
 
     // Cannot be aligned at all.
-    usize::max_value()
+    usize::MAX
 }
 
 /// Compares raw pointers for equality.
@@ -1345,14 +1345,24 @@ macro_rules! fnptr_impls_safety_abi {
         #[stable(feature = "fnptr_impls", since = "1.4.0")]
         impl<Ret, $($Arg),*> fmt::Pointer for $FnTy {
             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                fmt::Pointer::fmt(&(*self as *const ()), f)
+                // HACK: The intermediate cast as usize is required for AVR
+                // so that the address space of the source function pointer
+                // is preserved in the final function pointer.
+                //
+                // https://github.com/avr-rust/rust/issues/143
+                fmt::Pointer::fmt(&(*self as usize as *const ()), f)
             }
         }
 
         #[stable(feature = "fnptr_impls", since = "1.4.0")]
         impl<Ret, $($Arg),*> fmt::Debug for $FnTy {
             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                fmt::Pointer::fmt(&(*self as *const ()), f)
+                // HACK: The intermediate cast as usize is required for AVR
+                // so that the address space of the source function pointer
+                // is preserved in the final function pointer.
+                //
+                // https://github.com/avr-rust/rust/issues/143
+                fmt::Pointer::fmt(&(*self as usize as *const ()), f)
             }
         }
     }
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 4efb1db7a1a..21ba2b5abcf 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -3043,16 +3043,12 @@ impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
 
     #[inline]
     fn get(self, slice: &[T]) -> Option<&[T]> {
-        if *self.end() == usize::max_value() {
-            None
-        } else {
-            (*self.start()..self.end() + 1).get(slice)
-        }
+        if *self.end() == usize::MAX { None } else { (*self.start()..self.end() + 1).get(slice) }
     }
 
     #[inline]
     fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
-        if *self.end() == usize::max_value() {
+        if *self.end() == usize::MAX {
             None
         } else {
             (*self.start()..self.end() + 1).get_mut(slice)
@@ -3071,7 +3067,7 @@ impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
 
     #[inline]
     fn index(self, slice: &[T]) -> &[T] {
-        if *self.end() == usize::max_value() {
+        if *self.end() == usize::MAX {
             slice_index_overflow_fail();
         }
         (*self.start()..self.end() + 1).index(slice)
@@ -3079,7 +3075,7 @@ impl<T> SliceIndex<[T]> for ops::RangeInclusive<usize> {
 
     #[inline]
     fn index_mut(self, slice: &mut [T]) -> &mut [T] {
-        if *self.end() == usize::max_value() {
+        if *self.end() == usize::MAX {
             slice_index_overflow_fail();
         }
         (*self.start()..self.end() + 1).index_mut(slice)
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 316c2cd55ac..6c4b28499a6 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -1651,7 +1651,7 @@ fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
             // Ascii case, try to skip forward quickly.
             // When the pointer is aligned, read 2 words of data per iteration
             // until we find a word containing a non-ascii byte.
-            if align != usize::max_value() && align.wrapping_sub(index) % usize_bytes == 0 {
+            if align != usize::MAX && 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
@@ -2083,7 +2083,7 @@ mod traits {
         type Output = str;
         #[inline]
         fn get(self, slice: &str) -> Option<&Self::Output> {
-            if *self.end() == usize::max_value() {
+            if *self.end() == usize::MAX {
                 None
             } else {
                 (*self.start()..self.end() + 1).get(slice)
@@ -2091,7 +2091,7 @@ mod traits {
         }
         #[inline]
         fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
-            if *self.end() == usize::max_value() {
+            if *self.end() == usize::MAX {
                 None
             } else {
                 (*self.start()..self.end() + 1).get_mut(slice)
@@ -2107,14 +2107,14 @@ mod traits {
         }
         #[inline]
         fn index(self, slice: &str) -> &Self::Output {
-            if *self.end() == usize::max_value() {
+            if *self.end() == usize::MAX {
                 str_index_overflow_fail();
             }
             (*self.start()..self.end() + 1).index(slice)
         }
         #[inline]
         fn index_mut(self, slice: &mut str) -> &mut Self::Output {
-            if *self.end() == usize::max_value() {
+            if *self.end() == usize::MAX {
                 str_index_overflow_fail();
             }
             (*self.start()..self.end() + 1).index_mut(slice)
@@ -2140,11 +2140,11 @@ mod traits {
         type Output = str;
         #[inline]
         fn get(self, slice: &str) -> Option<&Self::Output> {
-            if self.end == usize::max_value() { None } else { (..self.end + 1).get(slice) }
+            if self.end == usize::MAX { None } else { (..self.end + 1).get(slice) }
         }
         #[inline]
         fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> {
-            if self.end == usize::max_value() { None } else { (..self.end + 1).get_mut(slice) }
+            if self.end == usize::MAX { None } else { (..self.end + 1).get_mut(slice) }
         }
         #[inline]
         unsafe fn get_unchecked(self, slice: &str) -> &Self::Output {
@@ -2156,14 +2156,14 @@ mod traits {
         }
         #[inline]
         fn index(self, slice: &str) -> &Self::Output {
-            if self.end == usize::max_value() {
+            if self.end == usize::MAX {
                 str_index_overflow_fail();
             }
             (..self.end + 1).index(slice)
         }
         #[inline]
         fn index_mut(self, slice: &mut str) -> &mut Self::Output {
-            if self.end == usize::max_value() {
+            if self.end == usize::MAX {
                 str_index_overflow_fail();
             }
             (..self.end + 1).index_mut(slice)
diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs
index 1a2b612b2f9..14f1f293d40 100644
--- a/src/libcore/str/pattern.rs
+++ b/src/libcore/str/pattern.rs
@@ -60,6 +60,43 @@ use crate::slice::memchr;
 /// The trait itself acts as a builder for an associated
 /// `Searcher` type, which does the actual work of finding
 /// occurrences of the pattern in a string.
+///
+/// Depending on the type of the pattern, the behaviour of methods like
+/// [`str::find`] and [`str::contains`] can change. The table below describes
+/// some of those behaviours.
+///
+/// | Pattern type             | Match condition                           |
+/// |--------------------------|-------------------------------------------|
+/// | `&str`                   | is substring                              |
+/// | `char`                   | is contained in string                    |
+/// | `&[char]`                | any char in slice is contained in string  |
+/// | `F: FnMut(char) -> bool` | `F` returns `true` for a char in string   |
+/// | `&&str`                  | is substring                              |
+/// | `&String`                | is substring                              |
+///
+/// # Examples
+/// ```
+/// // &str
+/// assert_eq!("abaaa".find("ba"), Some(1));
+/// assert_eq!("abaaa".find("bac"), None);
+///
+/// // char
+/// assert_eq!("abaaa".find('a'), Some(0));
+/// assert_eq!("abaaa".find('b'), Some(1));
+/// assert_eq!("abaaa".find('c'), None);
+///
+/// // &[char]
+/// assert_eq!("ab".find(&['b', 'a'][..]), Some(0));
+/// assert_eq!("abaaa".find(&['a', 'z'][..]), Some(0));
+/// assert_eq!("abaaa".find(&['c', 'd'][..]), None);
+///
+/// // FnMut(char) -> bool
+/// assert_eq!("abcdef_z".find(|ch| ch > 'd' && ch < 'y'), Some(4));
+/// assert_eq!("abcddd_z".find(|ch| ch > 'd' && ch < 'y'), None);
+/// ```
+///
+/// [`str::find`]: ../../../std/primitive.str.html#method.find
+/// [`str::contains`]: ../../../std/primitive.str.html#method.contains
 pub trait Pattern<'a>: Sized {
     /// Associated searcher for this pattern
     type Searcher: Searcher<'a>;
@@ -80,6 +117,15 @@ pub trait Pattern<'a>: Sized {
         matches!(self.into_searcher(haystack).next(), SearchStep::Match(0, _))
     }
 
+    /// Checks whether the pattern matches at the back of the haystack
+    #[inline]
+    fn is_suffix_of(self, haystack: &'a str) -> bool
+    where
+        Self::Searcher: ReverseSearcher<'a>,
+    {
+        matches!(self.into_searcher(haystack).next_back(), SearchStep::Match(_, j) if haystack.len() == j)
+    }
+
     /// Removes the pattern from the front of haystack, if it matches.
     #[inline]
     fn strip_prefix_of(self, haystack: &'a str) -> Option<&'a str> {
@@ -96,15 +142,6 @@ pub trait Pattern<'a>: Sized {
         }
     }
 
-    /// Checks whether the pattern matches at the back of the haystack
-    #[inline]
-    fn is_suffix_of(self, haystack: &'a str) -> bool
-    where
-        Self::Searcher: ReverseSearcher<'a>,
-    {
-        matches!(self.into_searcher(haystack).next_back(), SearchStep::Match(_, j) if haystack.len() == j)
-    }
-
     /// Removes the pattern from the back of haystack, if it matches.
     #[inline]
     fn strip_suffix_of(self, haystack: &'a str) -> Option<&'a str>
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 477cb24d6be..1cd68f2881b 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -2623,15 +2623,7 @@ unsafe fn atomic_umin<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(target_arch = "wasm32", allow(unused_variables))]
 pub fn fence(order: Ordering) {
-    // On wasm32 it looks like fences aren't implemented in LLVM yet in that
-    // they will cause LLVM to abort. The wasm instruction set doesn't have
-    // fences right now. There's discussion online about the best way for tools
-    // to conventionally implement fences at
-    // https://github.com/WebAssembly/tool-conventions/issues/59. We should
-    // follow that discussion and implement a solution when one comes about!
-    #[cfg(not(target_arch = "wasm32"))]
     // SAFETY: using an atomic fence is safe.
     unsafe {
         match order {
diff --git a/src/libcore/tests/num/mod.rs b/src/libcore/tests/num/mod.rs
index 181bbb8e187..939f1325c84 100644
--- a/src/libcore/tests/num/mod.rs
+++ b/src/libcore/tests/num/mod.rs
@@ -140,8 +140,8 @@ macro_rules! test_impl_from {
     ($fn_name: ident, $Small: ty, $Large: ty) => {
         #[test]
         fn $fn_name() {
-            let small_max = <$Small>::max_value();
-            let small_min = <$Small>::min_value();
+            let small_max = <$Small>::MAX;
+            let small_min = <$Small>::MIN;
             let large_max: $Large = small_max.into();
             let large_min: $Large = small_min.into();
             assert_eq!(large_max as $Small, small_max);
@@ -248,8 +248,8 @@ macro_rules! test_impl_try_from_always_ok {
     ($fn_name:ident, $source:ty, $target: ty) => {
         #[test]
         fn $fn_name() {
-            let max = <$source>::max_value();
-            let min = <$source>::min_value();
+            let max = <$source>::MAX;
+            let min = <$source>::MIN;
             let zero: $source = 0;
             assert_eq!(<$target as TryFrom<$source>>::try_from(max).unwrap(), max as $target);
             assert_eq!(<$target as TryFrom<$source>>::try_from(min).unwrap(), min as $target);
@@ -361,8 +361,8 @@ macro_rules! test_impl_try_from_signed_to_unsigned_upper_ok {
     ($fn_name:ident, $source:ty, $target:ty) => {
         #[test]
         fn $fn_name() {
-            let max = <$source>::max_value();
-            let min = <$source>::min_value();
+            let max = <$source>::MAX;
+            let min = <$source>::MIN;
             let zero: $source = 0;
             let neg_one: $source = -1;
             assert_eq!(<$target as TryFrom<$source>>::try_from(max).unwrap(), max as $target);
@@ -426,8 +426,8 @@ macro_rules! test_impl_try_from_unsigned_to_signed_upper_err {
     ($fn_name:ident, $source:ty, $target:ty) => {
         #[test]
         fn $fn_name() {
-            let max = <$source>::max_value();
-            let min = <$source>::min_value();
+            let max = <$source>::MAX;
+            let min = <$source>::MIN;
             let zero: $source = 0;
             assert!(<$target as TryFrom<$source>>::try_from(max).is_err());
             assert_eq!(<$target as TryFrom<$source>>::try_from(min).unwrap(), min as $target);
@@ -487,11 +487,11 @@ macro_rules! test_impl_try_from_same_sign_err {
     ($fn_name:ident, $source:ty, $target:ty) => {
         #[test]
         fn $fn_name() {
-            let max = <$source>::max_value();
-            let min = <$source>::min_value();
+            let max = <$source>::MAX;
+            let min = <$source>::MIN;
             let zero: $source = 0;
-            let t_max = <$target>::max_value();
-            let t_min = <$target>::min_value();
+            let t_max = <$target>::MAX;
+            let t_min = <$target>::MIN;
             assert!(<$target as TryFrom<$source>>::try_from(max).is_err());
             if min != 0 {
                 assert!(<$target as TryFrom<$source>>::try_from(min).is_err());
@@ -576,11 +576,11 @@ macro_rules! test_impl_try_from_signed_to_unsigned_err {
     ($fn_name:ident, $source:ty, $target:ty) => {
         #[test]
         fn $fn_name() {
-            let max = <$source>::max_value();
-            let min = <$source>::min_value();
+            let max = <$source>::MAX;
+            let min = <$source>::MIN;
             let zero: $source = 0;
-            let t_max = <$target>::max_value();
-            let t_min = <$target>::min_value();
+            let t_max = <$target>::MAX;
+            let t_min = <$target>::MIN;
             assert!(<$target as TryFrom<$source>>::try_from(max).is_err());
             assert!(<$target as TryFrom<$source>>::try_from(min).is_err());
             assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(), zero as $target);
diff --git a/src/libcore/tests/ptr.rs b/src/libcore/tests/ptr.rs
index a008b3319f3..9fea34d668f 100644
--- a/src/libcore/tests/ptr.rs
+++ b/src/libcore/tests/ptr.rs
@@ -357,7 +357,7 @@ fn align_offset_weird_strides() {
 
     unsafe fn test_weird_stride<T>(ptr: *const T, align: usize) -> bool {
         let numptr = ptr as usize;
-        let mut expected = usize::max_value();
+        let mut expected = usize::MAX;
         // Naive but definitely correct way to find the *first* aligned element of stride::<T>.
         for el in 0..align {
             if (numptr + el * ::std::mem::size_of::<T>()) % align == 0 {
diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs
index 54a585415bc..cd46117f763 100644
--- a/src/libcore/tests/slice.rs
+++ b/src/libcore/tests/slice.rs
@@ -1691,8 +1691,8 @@ fn test_copy_within_panics_src_inverted() {
 #[should_panic(expected = "attempted to index slice up to maximum usize")]
 fn test_copy_within_panics_src_out_of_bounds() {
     let mut bytes = *b"Hello, World!";
-    // an inclusive range ending at usize::max_value() would make src_end overflow
-    bytes.copy_within(usize::max_value()..=usize::max_value(), 0);
+    // an inclusive range ending at usize::MAX would make src_end overflow
+    bytes.copy_within(usize::MAX..=usize::MAX, 0);
 }
 
 #[test]
diff --git a/src/librustc_apfloat/lib.rs b/src/librustc_apfloat/lib.rs
index 09a069ab313..ba3adc4a135 100644
--- a/src/librustc_apfloat/lib.rs
+++ b/src/librustc_apfloat/lib.rs
@@ -133,9 +133,9 @@ impl Neg for Round {
 pub type ExpInt = i16;
 
 // \c ilogb error results.
-pub const IEK_INF: ExpInt = ExpInt::max_value();
-pub const IEK_NAN: ExpInt = ExpInt::min_value();
-pub const IEK_ZERO: ExpInt = ExpInt::min_value() + 1;
+pub const IEK_INF: ExpInt = ExpInt::MAX;
+pub const IEK_NAN: ExpInt = ExpInt::MIN;
+pub const IEK_ZERO: ExpInt = ExpInt::MIN + 1;
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub struct ParseError(pub &'static str);
diff --git a/src/librustc_apfloat/tests/ieee.rs b/src/librustc_apfloat/tests/ieee.rs
index e5b06cf225d..2d8bb7d1e8e 100644
--- a/src/librustc_apfloat/tests/ieee.rs
+++ b/src/librustc_apfloat/tests/ieee.rs
@@ -2997,8 +2997,8 @@ fn scalbn() {
     assert!(smallest_f64.scalbn(2099).is_infinite());
 
     // Test for integer overflows when adding to exponent.
-    assert!(smallest_f64.scalbn(-ExpInt::max_value()).is_pos_zero());
-    assert!(largest_f64.scalbn(ExpInt::max_value()).is_infinite());
+    assert!(smallest_f64.scalbn(-ExpInt::MAX).is_pos_zero());
+    assert!(largest_f64.scalbn(ExpInt::MAX).is_infinite());
 
     assert!(largest_denormal_f64.bitwise_eq(largest_denormal_f64.scalbn(0),));
     assert!(neg_largest_denormal_f64.bitwise_eq(neg_largest_denormal_f64.scalbn(0),));
diff --git a/src/librustc_arena/lib.rs b/src/librustc_arena/lib.rs
index 4da336f8e28..4a2a0de0e21 100644
--- a/src/librustc_arena/lib.rs
+++ b/src/librustc_arena/lib.rs
@@ -602,7 +602,7 @@ macro_rules! which_arena_for_type {
 
 #[macro_export]
 macro_rules! declare_arena {
-    ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
+    ([], [$($a:tt $name:ident: $ty:ty, $gen_ty:ty;)*], $tcx:lifetime) => {
         #[derive(Default)]
         pub struct Arena<$tcx> {
             pub dropless: $crate::DroplessArena,
@@ -611,17 +611,17 @@ macro_rules! declare_arena {
         }
 
         #[marker]
-        pub trait ArenaAllocatable {}
+        pub trait ArenaAllocatable<'tcx> {}
 
-        impl<T: Copy> ArenaAllocatable for T {}
+        impl<'tcx, T: Copy> ArenaAllocatable<'tcx> for T {}
 
-        unsafe trait ArenaField<'tcx>: Sized {
+        unsafe trait ArenaField<'tcx>: Sized + ArenaAllocatable<'tcx> {
             /// Returns a specific arena to allocate from.
             /// If `None` is returned, the `DropArena` will be used.
             fn arena<'a>(arena: &'a Arena<'tcx>) -> Option<&'a $crate::TypedArena<Self>>;
         }
 
-        unsafe impl<'tcx, T> ArenaField<'tcx> for T {
+        unsafe impl<'tcx, T: ArenaAllocatable<'tcx>> ArenaField<'tcx> for T {
             #[inline]
             default fn arena<'a>(_: &'a Arena<'tcx>) -> Option<&'a $crate::TypedArena<Self>> {
                 panic!()
@@ -630,18 +630,27 @@ macro_rules! declare_arena {
 
         $(
             #[allow(unused_lifetimes)]
-            impl<$tcx> ArenaAllocatable for $ty {}
-            unsafe impl<$tcx> ArenaField<$tcx> for $ty {
+            impl<$tcx> ArenaAllocatable<$tcx> for $ty {}
+            unsafe impl<$tcx, '_x, '_y, '_z, '_w> ArenaField<$tcx> for $gen_ty where Self: ArenaAllocatable<$tcx> {
                 #[inline]
                 fn arena<'a>(_arena: &'a Arena<$tcx>) -> Option<&'a $crate::TypedArena<Self>> {
-                    $crate::which_arena_for_type!($a[&_arena.$name])
+                    // SAFETY: We only implement `ArenaAllocatable<$tcx>` for
+                    // `$ty`, so `$ty` and Self are the same type
+                    unsafe {
+                        ::std::mem::transmute::<
+                            Option<&'a $crate::TypedArena<$ty>>,
+                            Option<&'a $crate::TypedArena<Self>>,
+                        >(
+                            $crate::which_arena_for_type!($a[&_arena.$name])
+                        )
+                    }
                 }
             }
         )*
 
         impl<'tcx> Arena<'tcx> {
             #[inline]
-            pub fn alloc<T: ArenaAllocatable>(&self, value: T) -> &mut T {
+            pub fn alloc<T: ArenaAllocatable<'tcx>>(&self, value: T) -> &mut T {
                 if !::std::mem::needs_drop::<T>() {
                     return self.dropless.alloc(value);
                 }
@@ -659,7 +668,7 @@ macro_rules! declare_arena {
                 self.dropless.alloc_slice(value)
             }
 
-            pub fn alloc_from_iter<'a, T: ArenaAllocatable>(
+            pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx>>(
                 &'a self,
                 iter: impl ::std::iter::IntoIterator<Item = T>,
             ) -> &'a mut [T] {
diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs
index efcf95ec706..62406552e31 100644
--- a/src/librustc_ast/ast.rs
+++ b/src/librustc_ast/ast.rs
@@ -362,7 +362,11 @@ impl Default for Generics {
     fn default() -> Generics {
         Generics {
             params: Vec::new(),
-            where_clause: WhereClause { predicates: Vec::new(), span: DUMMY_SP },
+            where_clause: WhereClause {
+                has_where_token: false,
+                predicates: Vec::new(),
+                span: DUMMY_SP,
+            },
             span: DUMMY_SP,
         }
     }
@@ -371,6 +375,11 @@ impl Default for Generics {
 /// A where-clause in a definition.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct WhereClause {
+    /// `true` if we ate a `where` token: this can happen
+    /// if we parsed no predicates (e.g. `struct Foo where {}
+    /// This allows us to accurately pretty-print
+    /// in `nt_to_tokenstream`
+    pub has_where_token: bool,
     pub predicates: Vec<WherePredicate>,
     pub span: Span,
 }
@@ -1165,7 +1174,9 @@ pub enum ExprKind {
     /// and the remaining elements are the rest of the arguments.
     /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
     /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
-    MethodCall(PathSegment, Vec<P<Expr>>),
+    /// This `Span` is the span of the function, without the dot and receiver
+    /// (e.g. `foo(a, b)` in `x.foo(a, b)`
+    MethodCall(PathSegment, Vec<P<Expr>>, Span),
     /// A tuple (e.g., `(a, b, c, d)`).
     Tup(Vec<P<Expr>>),
     /// A binary operation (e.g., `a + b`, `a * b`).
@@ -1849,15 +1860,6 @@ impl TyKind {
     pub fn is_unit(&self) -> bool {
         if let TyKind::Tup(ref tys) = *self { tys.is_empty() } else { false }
     }
-
-    /// HACK(type_alias_impl_trait, Centril): A temporary crutch used
-    /// in lowering to avoid making larger changes there and beyond.
-    pub fn opaque_top_hack(&self) -> Option<&GenericBounds> {
-        match self {
-            Self::ImplTrait(_, bounds) => Some(bounds),
-            _ => None,
-        }
-    }
 }
 
 /// Syntax used to declare a trait object.
diff --git a/src/librustc_ast/mut_visit.rs b/src/librustc_ast/mut_visit.rs
index 7ececb814a6..2ffef9d48c1 100644
--- a/src/librustc_ast/mut_visit.rs
+++ b/src/librustc_ast/mut_visit.rs
@@ -786,7 +786,7 @@ pub fn noop_visit_generics<T: MutVisitor>(generics: &mut Generics, vis: &mut T)
 }
 
 pub fn noop_visit_where_clause<T: MutVisitor>(wc: &mut WhereClause, vis: &mut T) {
-    let WhereClause { predicates, span } = wc;
+    let WhereClause { has_where_token: _, predicates, span } = wc;
     visit_vec(predicates, |predicate| vis.visit_where_predicate(predicate));
     vis.visit_span(span);
 }
@@ -1111,11 +1111,12 @@ pub fn noop_visit_expr<T: MutVisitor>(
             vis.visit_expr(f);
             visit_exprs(args, vis);
         }
-        ExprKind::MethodCall(PathSegment { ident, id, args }, exprs) => {
+        ExprKind::MethodCall(PathSegment { ident, id, args }, exprs, span) => {
             vis.visit_ident(ident);
             vis.visit_id(id);
             visit_opt(args, |args| vis.visit_generic_args(args));
             visit_exprs(exprs, vis);
+            vis.visit_span(span);
         }
         ExprKind::Binary(_binop, lhs, rhs) => {
             vis.visit_expr(lhs);
diff --git a/src/librustc_ast/tokenstream.rs b/src/librustc_ast/tokenstream.rs
index 075aaa7e5bc..15ae12ebf10 100644
--- a/src/librustc_ast/tokenstream.rs
+++ b/src/librustc_ast/tokenstream.rs
@@ -392,7 +392,7 @@ impl TokenStream {
                         break;
                     }
                 }
-                token_trees = out.into_iter().map(|t| TokenTree::Token(t)).collect();
+                token_trees = out.into_iter().map(TokenTree::Token).collect();
                 if token_trees.len() != 1 {
                     debug!("break_tokens: broke {:?} to {:?}", tree, token_trees);
                 }
diff --git a/src/librustc_ast/util/parser.rs b/src/librustc_ast/util/parser.rs
index b98cc96b3c6..d8b44a22f2c 100644
--- a/src/librustc_ast/util/parser.rs
+++ b/src/librustc_ast/util/parser.rs
@@ -394,7 +394,7 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
             contains_exterior_struct_lit(&x)
         }
 
-        ast::ExprKind::MethodCall(.., ref exprs) => {
+        ast::ExprKind::MethodCall(.., ref exprs, _) => {
             // X { y: 1 }.bar(...)
             contains_exterior_struct_lit(&exprs[0])
         }
diff --git a/src/librustc_ast/visit.rs b/src/librustc_ast/visit.rs
index 41c02734442..ccab46703df 100644
--- a/src/librustc_ast/visit.rs
+++ b/src/librustc_ast/visit.rs
@@ -726,7 +726,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
             visitor.visit_expr(callee_expression);
             walk_list!(visitor, visit_expr, arguments);
         }
-        ExprKind::MethodCall(ref segment, ref arguments) => {
+        ExprKind::MethodCall(ref segment, ref arguments, _span) => {
             visitor.visit_path_segment(expression.span, segment);
             walk_list!(visitor, visit_expr, arguments);
         }
diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs
index c9037da377e..e59cacfffc9 100644
--- a/src/librustc_ast_lowering/expr.rs
+++ b/src/librustc_ast_lowering/expr.rs
@@ -9,7 +9,7 @@ use rustc_data_structures::thin_vec::ThinVec;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
-use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
+use rustc_span::source_map::{respan, DesugaringKind, ForLoopLoc, Span, Spanned};
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_target::asm;
 use std::collections::hash_map::Entry;
@@ -25,6 +25,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
+        let mut span = e.span;
         ensure_sufficient_stack(|| {
             let kind = match e.kind {
                 ExprKind::Box(ref inner) => hir::ExprKind::Box(self.lower_expr(inner)),
@@ -39,7 +40,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     let f = self.lower_expr(f);
                     hir::ExprKind::Call(f, self.lower_exprs(args))
                 }
-                ExprKind::MethodCall(ref seg, ref args) => {
+                ExprKind::MethodCall(ref seg, ref args, span) => {
                     let hir_seg = self.arena.alloc(self.lower_path_segment(
                         e.span,
                         seg,
@@ -50,9 +51,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         None,
                     ));
                     let args = self.lower_exprs(args);
-                    hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args)
+                    hir::ExprKind::MethodCall(hir_seg, seg.ident.span, args, span)
                 }
                 ExprKind::Binary(binop, ref lhs, ref rhs) => {
+                    span = self.mark_span_with_reason(DesugaringKind::Operator, e.span, None);
                     let binop = self.lower_binop(binop);
                     let lhs = self.lower_expr(lhs);
                     let rhs = self.lower_expr(rhs);
@@ -222,7 +224,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             hir::Expr {
                 hir_id: self.lower_node_id(e.id),
                 kind,
-                span: e.span,
+                span,
                 attrs: e.attrs.iter().map(|a| self.lower_attr(a)).collect::<Vec<_>>().into(),
             }
         })
@@ -237,6 +239,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     fn lower_binop(&mut self, b: BinOp) -> hir::BinOp {
+        let span = self.mark_span_with_reason(DesugaringKind::Operator, b.span, None);
         Spanned {
             node: match b.node {
                 BinOpKind::Add => hir::BinOpKind::Add,
@@ -258,7 +261,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 BinOpKind::Ge => hir::BinOpKind::Ge,
                 BinOpKind::Gt => hir::BinOpKind::Gt,
             },
-            span: b.span,
+            span,
         }
     }
 
@@ -1237,10 +1240,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                                             ) => {
                                                 assert!(!*late);
                                                 let out_op_sp = if input { op_sp2 } else { op_sp };
-                                                let msg = &format!(
-                                                    "use `lateout` instead of \
-                                                     `out` to avoid conflict"
-                                                );
+                                                let msg = "use `lateout` instead of \
+                                                     `out` to avoid conflict";
                                                 err.span_help(out_op_sp, msg);
                                             }
                                             _ => {}
@@ -1362,9 +1363,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
         body: &Block,
         opt_label: Option<Label>,
     ) -> hir::Expr<'hir> {
+        let orig_head_span = head.span;
         // expand <head>
         let mut head = self.lower_expr_mut(head);
-        let desugared_span = self.mark_span_with_reason(DesugaringKind::ForLoop, head.span, None);
+        let desugared_span = self.mark_span_with_reason(
+            DesugaringKind::ForLoop(ForLoopLoc::Head),
+            orig_head_span,
+            None,
+        );
         head.span = desugared_span;
 
         let iter = Ident::with_dummy_span(sym::iter);
@@ -1459,10 +1465,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // `mut iter => { ... }`
         let iter_arm = self.arm(iter_pat, loop_expr);
 
+        let into_iter_span = self.mark_span_with_reason(
+            DesugaringKind::ForLoop(ForLoopLoc::IntoIter),
+            orig_head_span,
+            None,
+        );
+
         // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
         let into_iter_expr = {
             let into_iter_path = &[sym::iter, sym::IntoIterator, sym::into_iter];
-            self.expr_call_std_path(desugared_span, into_iter_path, arena_vec![self; head])
+            self.expr_call_std_path(into_iter_span, into_iter_path, arena_vec![self; head])
         };
 
         let match_expr = self.arena.alloc(self.expr_match(
diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs
index 47d10f86d03..8cfbd408e22 100644
--- a/src/librustc_ast_lowering/item.rs
+++ b/src/librustc_ast_lowering/item.rs
@@ -1,5 +1,5 @@
 use super::{AnonymousLifetimeMode, LoweringContext, ParamMode};
-use super::{ImplTraitContext, ImplTraitPosition, ImplTraitTypeIdVisitor};
+use super::{ImplTraitContext, ImplTraitPosition};
 use crate::Arena;
 
 use rustc_ast::ast::*;
@@ -7,6 +7,7 @@ use rustc_ast::attr;
 use rustc_ast::node_id::NodeMap;
 use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
@@ -165,13 +166,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
             ItemKind::MacroDef(..) => SmallVec::new(),
             ItemKind::Fn(..) | ItemKind::Impl { of_trait: None, .. } => smallvec![i.id],
-            ItemKind::Static(ref ty, ..) | ItemKind::Const(_, ref ty, ..) => {
-                let mut ids = smallvec![i.id];
-                if self.sess.features_untracked().impl_trait_in_bindings {
-                    ImplTraitTypeIdVisitor { ids: &mut ids }.visit_ty(ty);
-                }
-                ids
-            }
             _ => smallvec![i.id],
         };
 
@@ -292,23 +286,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
             ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)),
             ItemKind::ForeignMod(ref nm) => hir::ItemKind::ForeignMod(self.lower_foreign_mod(nm)),
             ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)),
-            ItemKind::TyAlias(_, ref gen, _, Some(ref ty)) => match ty.kind.opaque_top_hack() {
-                None => {
-                    let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
-                    let generics = self.lower_generics(gen, ImplTraitContext::disallowed());
-                    hir::ItemKind::TyAlias(ty, generics)
-                }
-                Some(bounds) => {
-                    let ctx = || ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc);
-                    let ty = hir::OpaqueTy {
-                        generics: self.lower_generics(gen, ctx()),
-                        bounds: self.lower_param_bounds(bounds, ctx()),
-                        impl_trait_fn: None,
-                        origin: hir::OpaqueTyOrigin::TypeAlias,
-                    };
-                    hir::ItemKind::OpaqueTy(ty)
-                }
-            },
+            ItemKind::TyAlias(_, ref gen, _, Some(ref ty)) => {
+                // We lower
+                //
+                // type Foo = impl Trait
+                //
+                // to
+                //
+                // type Foo = Foo1
+                // opaque type Foo1: Trait
+                let ty = self.lower_ty(
+                    ty,
+                    ImplTraitContext::OtherOpaqueTy {
+                        capturable_lifetimes: &mut FxHashSet::default(),
+                        origin: hir::OpaqueTyOrigin::Misc,
+                    },
+                );
+                let generics = self.lower_generics(gen, ImplTraitContext::disallowed());
+                hir::ItemKind::TyAlias(ty, generics)
+            }
             ItemKind::TyAlias(_, ref generics, _, None) => {
                 let ty = self.arena.alloc(self.ty(span, hir::TyKind::Err));
                 let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
@@ -438,8 +434,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
         span: Span,
         body: Option<&Expr>,
     ) -> (&'hir hir::Ty<'hir>, hir::BodyId) {
+        let mut capturable_lifetimes;
         let itctx = if self.sess.features_untracked().impl_trait_in_bindings {
-            ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc)
+            capturable_lifetimes = FxHashSet::default();
+            ImplTraitContext::OtherOpaqueTy {
+                capturable_lifetimes: &mut capturable_lifetimes,
+                origin: hir::OpaqueTyOrigin::Misc,
+            }
         } else {
             ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
         };
@@ -844,16 +845,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         let ty = self.arena.alloc(self.ty(i.span, hir::TyKind::Err));
                         hir::ImplItemKind::TyAlias(ty)
                     }
-                    Some(ty) => match ty.kind.opaque_top_hack() {
-                        None => {
-                            let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
-                            hir::ImplItemKind::TyAlias(ty)
-                        }
-                        Some(bs) => {
-                            let bs = self.lower_param_bounds(bs, ImplTraitContext::disallowed());
-                            hir::ImplItemKind::OpaqueTy(bs)
-                        }
-                    },
+                    Some(ty) => {
+                        let ty = self.lower_ty(
+                            ty,
+                            ImplTraitContext::OtherOpaqueTy {
+                                capturable_lifetimes: &mut FxHashSet::default(),
+                                origin: hir::OpaqueTyOrigin::Misc,
+                            },
+                        );
+                        hir::ImplItemKind::TyAlias(ty)
+                    }
                 };
                 (generics, kind)
             }
@@ -887,12 +888,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             defaultness,
             kind: match &i.kind {
                 AssocItemKind::Const(..) => hir::AssocItemKind::Const,
-                AssocItemKind::TyAlias(.., ty) => {
-                    match ty.as_deref().and_then(|ty| ty.kind.opaque_top_hack()) {
-                        None => hir::AssocItemKind::Type,
-                        Some(_) => hir::AssocItemKind::OpaqueTy,
-                    }
-                }
+                AssocItemKind::TyAlias(..) => hir::AssocItemKind::Type,
                 AssocItemKind::Fn(_, sig, ..) => {
                     hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
                 }
diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs
index 1f8c68f75e9..a722a88a7a1 100644
--- a/src/librustc_ast_lowering/lib.rs
+++ b/src/librustc_ast_lowering/lib.rs
@@ -33,7 +33,7 @@
 #![feature(array_value_iter)]
 #![feature(crate_visibility_modifier)]
 #![feature(marker_trait_attr)]
-#![feature(specialization)] // FIXME: min_specialization does not work
+#![feature(min_specialization)]
 #![feature(or_patterns)]
 #![recursion_limit = "256"]
 
@@ -224,11 +224,30 @@ enum ImplTraitContext<'b, 'a> {
     /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
     /// equivalent to a new opaque type like `type T = impl Debug; fn foo() -> T`.
     ///
-    /// We optionally store a `DefId` for the parent item here so we can look up necessary
-    /// information later. It is `None` when no information about the context should be stored
-    /// (e.g., for consts and statics).
-    OpaqueTy(Option<DefId> /* fn def-ID */, hir::OpaqueTyOrigin),
-
+    ReturnPositionOpaqueTy {
+        /// `DefId` for the parent function, used to look up necessary
+        /// information later.
+        fn_def_id: DefId,
+        /// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn,
+        origin: hir::OpaqueTyOrigin,
+    },
+    /// Impl trait in type aliases, consts and statics.
+    OtherOpaqueTy {
+        /// Set of lifetimes that this opaque type can capture, if it uses
+        /// them. This includes lifetimes bound since we entered this context.
+        /// For example, in
+        ///
+        /// type A<'b> = impl for<'a> Trait<'a, Out = impl Sized + 'a>;
+        ///
+        /// the inner opaque type captures `'a` because it uses it. It doesn't
+        /// need to capture `'b` because it already inherits the lifetime
+        /// parameter from `A`.
+        // FIXME(impl_trait): but `required_region_bounds` will ICE later
+        // anyway.
+        capturable_lifetimes: &'b mut FxHashSet<hir::LifetimeName>,
+        /// Origin: Either OpaqueTyOrigin::Misc or OpaqueTyOrigin::Binding,
+        origin: hir::OpaqueTyOrigin,
+    },
     /// `impl Trait` is not accepted in this position.
     Disallowed(ImplTraitPosition),
 }
@@ -253,7 +272,12 @@ impl<'a> ImplTraitContext<'_, 'a> {
         use self::ImplTraitContext::*;
         match self {
             Universal(params) => Universal(params),
-            OpaqueTy(fn_def_id, origin) => OpaqueTy(*fn_def_id, *origin),
+            ReturnPositionOpaqueTy { fn_def_id, origin } => {
+                ReturnPositionOpaqueTy { fn_def_id: *fn_def_id, origin: *origin }
+            }
+            OtherOpaqueTy { capturable_lifetimes, origin } => {
+                OtherOpaqueTy { capturable_lifetimes, origin: *origin }
+            }
             Disallowed(pos) => Disallowed(*pos),
         }
     }
@@ -1001,6 +1025,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 hir::TypeBindingKind::Equality { ty: self.lower_ty(ty, itctx) }
             }
             AssocTyConstraintKind::Bound { ref bounds } => {
+                let mut capturable_lifetimes;
                 // Piggy-back on the `impl Trait` context to figure out the correct behavior.
                 let (desugar_to_impl_trait, itctx) = match itctx {
                     // We are in the return position:
@@ -1010,7 +1035,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     // so desugar to
                     //
                     //     fn foo() -> impl Iterator<Item = impl Debug>
-                    ImplTraitContext::OpaqueTy(..) => (true, itctx),
+                    ImplTraitContext::ReturnPositionOpaqueTy { .. }
+                    | ImplTraitContext::OtherOpaqueTy { .. } => (true, itctx),
 
                     // We are in the argument position, but within a dyn type:
                     //
@@ -1028,7 +1054,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     //
                     // FIXME: this is only needed until `impl Trait` is allowed in type aliases.
                     ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => {
-                        (true, ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc))
+                        capturable_lifetimes = FxHashSet::default();
+                        (
+                            true,
+                            ImplTraitContext::OtherOpaqueTy {
+                                capturable_lifetimes: &mut capturable_lifetimes,
+                                origin: hir::OpaqueTyOrigin::Misc,
+                            },
+                        )
                     }
 
                     // We are in the parameter position, but not within a dyn type:
@@ -1270,10 +1303,31 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             TyKind::ImplTrait(def_node_id, ref bounds) => {
                 let span = t.span;
                 match itctx {
-                    ImplTraitContext::OpaqueTy(fn_def_id, origin) => {
-                        self.lower_opaque_impl_trait(span, fn_def_id, origin, def_node_id, |this| {
-                            this.lower_param_bounds(bounds, itctx)
-                        })
+                    ImplTraitContext::ReturnPositionOpaqueTy { fn_def_id, origin } => self
+                        .lower_opaque_impl_trait(
+                            span,
+                            Some(fn_def_id),
+                            origin,
+                            def_node_id,
+                            None,
+                            |this| this.lower_param_bounds(bounds, itctx),
+                        ),
+                    ImplTraitContext::OtherOpaqueTy { ref capturable_lifetimes, origin } => {
+                        // Reset capturable lifetimes, any nested impl trait
+                        // types will inherit lifetimes from this opaque type,
+                        // so don't need to capture them again.
+                        let nested_itctx = ImplTraitContext::OtherOpaqueTy {
+                            capturable_lifetimes: &mut FxHashSet::default(),
+                            origin,
+                        };
+                        self.lower_opaque_impl_trait(
+                            span,
+                            None,
+                            origin,
+                            def_node_id,
+                            Some(capturable_lifetimes),
+                            |this| this.lower_param_bounds(bounds, nested_itctx),
+                        )
                     }
                     ImplTraitContext::Universal(in_band_ty_params) => {
                         // Add a definition for the in-band `Param`.
@@ -1351,6 +1405,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         fn_def_id: Option<DefId>,
         origin: hir::OpaqueTyOrigin,
         opaque_ty_node_id: NodeId,
+        capturable_lifetimes: Option<&FxHashSet<hir::LifetimeName>>,
         lower_bounds: impl FnOnce(&mut Self) -> hir::GenericBounds<'hir>,
     ) -> hir::TyKind<'hir> {
         debug!(
@@ -1371,12 +1426,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         let hir_bounds = self.with_hir_id_owner(opaque_ty_node_id, lower_bounds);
 
-        let (lifetimes, lifetime_defs) =
-            self.lifetimes_from_impl_trait_bounds(opaque_ty_node_id, opaque_ty_def_id, &hir_bounds);
+        let (lifetimes, lifetime_defs) = self.lifetimes_from_impl_trait_bounds(
+            opaque_ty_node_id,
+            opaque_ty_def_id,
+            &hir_bounds,
+            capturable_lifetimes,
+        );
 
-        debug!("lower_opaque_impl_trait: lifetimes={:#?}", lifetimes,);
+        debug!("lower_opaque_impl_trait: lifetimes={:#?}", lifetimes);
 
-        debug!("lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs,);
+        debug!("lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs);
 
         self.with_hir_id_owner(opaque_ty_node_id, move |lctx| {
             let opaque_ty_item = hir::OpaqueTy {
@@ -1395,7 +1454,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 lctx.generate_opaque_type(opaque_ty_node_id, opaque_ty_item, span, opaque_ty_span);
 
             // `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
-            hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, lifetimes)
+            hir::TyKind::OpaqueDef(hir::ItemId { id: opaque_ty_id }, lifetimes)
         })
     }
 
@@ -1433,6 +1492,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         opaque_ty_id: NodeId,
         parent_def_id: LocalDefId,
         bounds: hir::GenericBounds<'hir>,
+        lifetimes_to_include: Option<&FxHashSet<hir::LifetimeName>>,
     ) -> (&'hir [hir::GenericArg<'hir>], &'hir [hir::GenericParam<'hir>]) {
         debug!(
             "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \
@@ -1453,6 +1513,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             already_defined_lifetimes: FxHashSet<hir::LifetimeName>,
             output_lifetimes: Vec<hir::GenericArg<'hir>>,
             output_lifetime_params: Vec<hir::GenericParam<'hir>>,
+            lifetimes_to_include: Option<&'r FxHashSet<hir::LifetimeName>>,
         }
 
         impl<'r, 'a, 'v, 'hir> intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r, 'a, 'hir> {
@@ -1538,6 +1599,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
                 if !self.currently_bound_lifetimes.contains(&name)
                     && !self.already_defined_lifetimes.contains(&name)
+                    && self.lifetimes_to_include.map_or(true, |lifetimes| lifetimes.contains(&name))
                 {
                     self.already_defined_lifetimes.insert(name);
 
@@ -1591,6 +1653,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             already_defined_lifetimes: FxHashSet::default(),
             output_lifetimes: Vec::new(),
             output_lifetime_params: Vec::new(),
+            lifetimes_to_include,
         };
 
         for bound in bounds {
@@ -1614,15 +1677,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 visitor.visit_ty(ty);
             }
         }
-        let parent_def_id = self.current_hir_id_owner.last().unwrap().0;
         let ty = l.ty.as_ref().map(|t| {
+            let mut capturable_lifetimes;
             self.lower_ty(
                 t,
                 if self.sess.features_untracked().impl_trait_in_bindings {
-                    ImplTraitContext::OpaqueTy(
-                        Some(parent_def_id.to_def_id()),
-                        hir::OpaqueTyOrigin::Misc,
-                    )
+                    capturable_lifetimes = FxHashSet::default();
+                    ImplTraitContext::OtherOpaqueTy {
+                        capturable_lifetimes: &mut capturable_lifetimes,
+                        origin: hir::OpaqueTyOrigin::Binding,
+                    }
                 } else {
                     ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
                 },
@@ -1725,7 +1789,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 FnRetTy::Ty(ref ty) => {
                     let context = match in_band_ty_params {
                         Some((def_id, _)) if impl_trait_return_allow => {
-                            ImplTraitContext::OpaqueTy(Some(def_id), hir::OpaqueTyOrigin::FnReturn)
+                            ImplTraitContext::ReturnPositionOpaqueTy {
+                                fn_def_id: def_id,
+                                origin: hir::OpaqueTyOrigin::FnReturn,
+                            }
                         }
                         _ => ImplTraitContext::disallowed(),
                     };
@@ -1944,7 +2011,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // Foo = impl Trait` is, internally, created as a child of the
         // async fn, so the *type parameters* are inherited.  It's
         // only the lifetime parameters that we must supply.
-        let opaque_ty_ref = hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, generic_args);
+        let opaque_ty_ref = hir::TyKind::OpaqueDef(hir::ItemId { id: opaque_ty_id }, generic_args);
         let opaque_ty = self.ty(opaque_ty_span, opaque_ty_ref);
         hir::FnRetTy::Return(self.arena.alloc(opaque_ty))
     }
@@ -1962,8 +2029,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 // Not `OpaqueTyOrigin::AsyncFn`: that's only used for the
                 // `impl Future` opaque type that `async fn` implicitly
                 // generates.
-                let context =
-                    ImplTraitContext::OpaqueTy(Some(fn_def_id), hir::OpaqueTyOrigin::FnReturn);
+                let context = ImplTraitContext::ReturnPositionOpaqueTy {
+                    fn_def_id,
+                    origin: hir::OpaqueTyOrigin::FnReturn,
+                };
                 self.lower_ty(ty, context)
             }
             FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])),
@@ -2113,7 +2182,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     default: default.as_ref().map(|x| {
                         self.lower_ty(
                             x,
-                            ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc),
+                            ImplTraitContext::OtherOpaqueTy {
+                                capturable_lifetimes: &mut FxHashSet::default(),
+                                origin: hir::OpaqueTyOrigin::Misc,
+                            },
                         )
                     }),
                     synthetic: param
@@ -2169,8 +2241,28 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             &NodeMap::default(),
             itctx.reborrow(),
         );
+
         let trait_ref = self.with_in_scope_lifetime_defs(&p.bound_generic_params, |this| {
-            this.lower_trait_ref(&p.trait_ref, itctx)
+            // Any impl Trait types defined within this scope can capture
+            // lifetimes bound on this predicate.
+            let lt_def_names = p.bound_generic_params.iter().filter_map(|param| match param.kind {
+                GenericParamKind::Lifetime { .. } => Some(hir::LifetimeName::Param(
+                    ParamName::Plain(param.ident.normalize_to_macros_2_0()),
+                )),
+                _ => None,
+            });
+            if let ImplTraitContext::OtherOpaqueTy { ref mut capturable_lifetimes, .. } = itctx {
+                capturable_lifetimes.extend(lt_def_names.clone());
+            }
+
+            let res = this.lower_trait_ref(&p.trait_ref, itctx.reborrow());
+
+            if let ImplTraitContext::OtherOpaqueTy { ref mut capturable_lifetimes, .. } = itctx {
+                for param in lt_def_names {
+                    capturable_lifetimes.remove(&param);
+                }
+            }
+            res
         });
 
         hir::PolyTraitRef { bound_generic_params, trait_ref, span: p.span }
diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs
index ffd741a7b37..a7b0c9cf81b 100644
--- a/src/librustc_ast_passes/feature_gate.rs
+++ b/src/librustc_ast_passes/feature_gate.rs
@@ -121,6 +121,14 @@ impl<'a> PostExpansionVisitor<'a> {
                     "amdgpu-kernel ABI is experimental and subject to change"
                 );
             }
+            "avr-interrupt" | "avr-non-blocking-interrupt" => {
+                gate_feature_post!(
+                    &self,
+                    abi_avr_interrupt,
+                    span,
+                    "avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change"
+                );
+            }
             "efiapi" => {
                 gate_feature_post!(
                     &self,
diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs
index 872126646f3..b1abc08aa67 100644
--- a/src/librustc_ast_pretty/pprust.rs
+++ b/src/librustc_ast_pretty/pprust.rs
@@ -1818,7 +1818,7 @@ impl<'a> State<'a> {
             ast::ExprKind::Call(ref func, ref args) => {
                 self.print_expr_call(func, &args[..]);
             }
-            ast::ExprKind::MethodCall(ref segment, ref args) => {
+            ast::ExprKind::MethodCall(ref segment, ref args, _) => {
                 self.print_expr_method_call(segment, &args[..]);
             }
             ast::ExprKind::Binary(op, ref lhs, ref rhs) => {
@@ -2593,7 +2593,7 @@ impl<'a> State<'a> {
     }
 
     crate fn print_where_clause(&mut self, where_clause: &ast::WhereClause) {
-        if where_clause.predicates.is_empty() {
+        if where_clause.predicates.is_empty() && !where_clause.has_where_token {
             return;
         }
 
@@ -2739,7 +2739,11 @@ impl<'a> State<'a> {
         }
         let generics = ast::Generics {
             params: Vec::new(),
-            where_clause: ast::WhereClause { predicates: Vec::new(), span: rustc_span::DUMMY_SP },
+            where_clause: ast::WhereClause {
+                has_where_token: false,
+                predicates: Vec::new(),
+                span: rustc_span::DUMMY_SP,
+            },
             span: rustc_span::DUMMY_SP,
         };
         let header = ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() };
diff --git a/src/librustc_builtin_macros/asm.rs b/src/librustc_builtin_macros/asm.rs
index aabd5b5b5c3..480ee97f205 100644
--- a/src/librustc_builtin_macros/asm.rs
+++ b/src/librustc_builtin_macros/asm.rs
@@ -391,7 +391,8 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
         used[*pos] = true;
     }
 
-    let named_pos: FxHashSet<usize> = args.named_args.values().cloned().collect();
+    let named_pos: FxHashMap<usize, Symbol> =
+        args.named_args.iter().map(|(&sym, &idx)| (idx, sym)).collect();
     let mut arg_spans = parser.arg_places.iter().map(|span| template_span.from_inner(*span));
     let mut template = vec![];
     for piece in unverified_pieces {
@@ -405,7 +406,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
                 let operand_idx = match arg.position {
                     parse::ArgumentIs(idx) | parse::ArgumentImplicitlyIs(idx) => {
                         if idx >= args.operands.len()
-                            || named_pos.contains(&idx)
+                            || named_pos.contains_key(&idx)
                             || args.reg_args.contains(&idx)
                         {
                             let msg = format!("invalid reference to argument at index {}", idx);
@@ -426,7 +427,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
                             };
                             err.note(&msg);
 
-                            if named_pos.contains(&idx) {
+                            if named_pos.contains_key(&idx) {
                                 err.span_label(args.operands[idx].1, "named argument");
                                 err.span_note(
                                     args.operands[idx].1,
@@ -457,7 +458,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
 
                 let mut chars = arg.format.ty.chars();
                 let mut modifier = chars.next();
-                if !chars.next().is_none() {
+                if chars.next().is_some() {
                     let span = arg
                         .format
                         .ty_span
@@ -480,27 +481,31 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
         }
     }
 
-    let operands = args.operands;
-    let unused_operands: Vec<_> = used
-        .into_iter()
-        .enumerate()
-        .filter(|&(_, used)| !used)
-        .map(|(idx, _)| {
-            if named_pos.contains(&idx) {
-                // named argument
-                (operands[idx].1, "named argument never used")
+    let mut unused_operands = vec![];
+    let mut help_str = String::new();
+    for (idx, used) in used.into_iter().enumerate() {
+        if !used {
+            let msg = if let Some(sym) = named_pos.get(&idx) {
+                help_str.push_str(&format!(" {{{}}}", sym));
+                "named argument never used"
             } else {
-                // positional argument
-                (operands[idx].1, "argument never used")
-            }
-        })
-        .collect();
+                help_str.push_str(&format!(" {{{}}}", idx));
+                "argument never used"
+            };
+            unused_operands.push((args.operands[idx].1, msg));
+        }
+    }
     match unused_operands.len() {
         0 => {}
         1 => {
             let (sp, msg) = unused_operands.into_iter().next().unwrap();
             let mut err = ecx.struct_span_err(sp, msg);
             err.span_label(sp, msg);
+            err.help(&format!(
+                "if this argument is intentionally unused, \
+                 consider using it in an asm comment: `\"/*{} */\"`",
+                help_str
+            ));
             err.emit();
         }
         _ => {
@@ -511,6 +516,11 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
             for (sp, msg) in unused_operands {
                 err.span_label(sp, msg);
             }
+            err.help(&format!(
+                "if these arguments are intentionally unused, \
+                 consider using them in an asm comment: `\"/*{} */\"`",
+                help_str
+            ));
             err.emit();
         }
     }
@@ -521,7 +531,8 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
         parser.line_spans.iter().map(|span| template_span.from_inner(*span)).collect()
     };
 
-    let inline_asm = ast::InlineAsm { template, operands, options: args.options, line_spans };
+    let inline_asm =
+        ast::InlineAsm { template, operands: args.operands, options: args.options, line_spans };
     P(ast::Expr {
         id: ast::DUMMY_NODE_ID,
         kind: ast::ExprKind::InlineAsm(P(inline_asm)),
diff --git a/src/librustc_builtin_macros/deriving/generic/ty.rs b/src/librustc_builtin_macros/deriving/generic/ty.rs
index 62cbdb19a88..609feb6f259 100644
--- a/src/librustc_builtin_macros/deriving/generic/ty.rs
+++ b/src/librustc_builtin_macros/deriving/generic/ty.rs
@@ -216,7 +216,11 @@ fn mk_ty_param(
 }
 
 fn mk_generics(params: Vec<ast::GenericParam>, span: Span) -> Generics {
-    Generics { params, where_clause: ast::WhereClause { predicates: Vec::new(), span }, span }
+    Generics {
+        params,
+        where_clause: ast::WhereClause { has_where_token: false, predicates: Vec::new(), span },
+        span,
+    }
 }
 
 /// Lifetimes and bounds on type parameters
diff --git a/src/librustc_builtin_macros/source_util.rs b/src/librustc_builtin_macros/source_util.rs
index 67145c6bf43..1b164eae5a3 100644
--- a/src/librustc_builtin_macros/source_util.rs
+++ b/src/librustc_builtin_macros/source_util.rs
@@ -122,6 +122,7 @@ pub fn expand_include<'cx>(
 
     struct ExpandResult<'a> {
         p: Parser<'a>,
+        node_id: ast::NodeId,
     }
     impl<'a> base::MacResult for ExpandResult<'a> {
         fn make_expr(mut self: Box<ExpandResult<'a>>) -> Option<P<ast::Expr>> {
@@ -130,7 +131,7 @@ pub fn expand_include<'cx>(
                 self.p.sess.buffer_lint(
                     &INCOMPLETE_INCLUDE,
                     self.p.token.span,
-                    ast::CRATE_NODE_ID,
+                    self.node_id,
                     "include macro expected single expression in source",
                 );
             }
@@ -158,7 +159,7 @@ pub fn expand_include<'cx>(
         }
     }
 
-    Box::new(ExpandResult { p })
+    Box::new(ExpandResult { p, node_id: cx.resolver.lint_node_id(cx.current_expansion.id) })
 }
 
 // include_str! : read the given file, insert it as a literal string expr
diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs
index 8e9c5f25ccb..099c402703d 100644
--- a/src/librustc_codegen_llvm/abi.rs
+++ b/src/librustc_codegen_llvm/abi.rs
@@ -375,6 +375,8 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> {
         match self.conv {
             Conv::C | Conv::Rust => llvm::CCallConv,
             Conv::AmdGpuKernel => llvm::AmdGpuKernel,
+            Conv::AvrInterrupt => llvm::AvrInterrupt,
+            Conv::AvrNonBlockingInterrupt => llvm::AvrNonBlockingInterrupt,
             Conv::ArmAapcs => llvm::ArmAapcsCallConv,
             Conv::Msp430Intr => llvm::Msp430Intr,
             Conv::PtxKernel => llvm::PtxKernel,
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index 02a9294930d..26f5334668b 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -16,7 +16,7 @@ use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, Mo
 use rustc_codegen_ssa::traits::*;
 use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
 use rustc_data_structures::small_c_str::SmallCStr;
-use rustc_errors::{FatalError, Handler};
+use rustc_errors::{FatalError, Handler, Level};
 use rustc_fs_util::{link_or_copy, path_to_c_string};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::bug;
@@ -242,6 +242,7 @@ impl<'a> Drop for DiagnosticHandlers<'a> {
 fn report_inline_asm(
     cgcx: &CodegenContext<LlvmCodegenBackend>,
     msg: String,
+    level: llvm::DiagnosticLevel,
     mut cookie: c_uint,
     source: Option<(String, Vec<InnerSpan>)>,
 ) {
@@ -251,7 +252,12 @@ fn report_inline_asm(
     if matches!(cgcx.lto, Lto::Fat | Lto::Thin) {
         cookie = 0;
     }
-    cgcx.diag_emitter.inline_asm_error(cookie as u32, msg, source);
+    let level = match level {
+        llvm::DiagnosticLevel::Error => Level::Error,
+        llvm::DiagnosticLevel::Warning => Level::Warning,
+        llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note,
+    };
+    cgcx.diag_emitter.inline_asm_error(cookie as u32, msg, level, source);
 }
 
 unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void, cookie: c_uint) {
@@ -264,6 +270,7 @@ unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void
     // diagnostics.
     let mut have_source = false;
     let mut buffer = String::new();
+    let mut level = llvm::DiagnosticLevel::Error;
     let mut loc = 0;
     let mut ranges = [0; 8];
     let mut num_ranges = ranges.len() / 2;
@@ -273,6 +280,7 @@ unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void
                 diag,
                 msg,
                 buffer,
+                &mut level,
                 &mut loc,
                 ranges.as_mut_ptr(),
                 &mut num_ranges,
@@ -290,7 +298,7 @@ unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void
         (buffer, spans)
     });
 
-    report_inline_asm(cgcx, msg, cookie, source);
+    report_inline_asm(cgcx, msg, level, cookie, source);
 }
 
 unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) {
@@ -301,7 +309,13 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
 
     match llvm::diagnostic::Diagnostic::unpack(info) {
         llvm::diagnostic::InlineAsm(inline) => {
-            report_inline_asm(cgcx, llvm::twine_to_string(inline.message), inline.cookie, None);
+            report_inline_asm(
+                cgcx,
+                llvm::twine_to_string(inline.message),
+                inline.level,
+                inline.cookie,
+                None,
+            );
         }
 
         llvm::diagnostic::Optimization(opt) => {
diff --git a/src/librustc_codegen_llvm/llvm/diagnostic.rs b/src/librustc_codegen_llvm/llvm/diagnostic.rs
index 4347cd06532..47f5c94e70c 100644
--- a/src/librustc_codegen_llvm/llvm/diagnostic.rs
+++ b/src/librustc_codegen_llvm/llvm/diagnostic.rs
@@ -88,6 +88,7 @@ impl OptimizationDiagnostic<'ll> {
 
 #[derive(Copy, Clone)]
 pub struct InlineAsmDiagnostic<'ll> {
+    pub level: super::DiagnosticLevel,
     pub cookie: c_uint,
     pub message: &'ll Twine,
     pub instruction: Option<&'ll Value>,
@@ -98,10 +99,17 @@ impl InlineAsmDiagnostic<'ll> {
         let mut cookie = 0;
         let mut message = None;
         let mut instruction = None;
+        let mut level = super::DiagnosticLevel::Error;
 
-        super::LLVMRustUnpackInlineAsmDiagnostic(di, &mut cookie, &mut message, &mut instruction);
+        super::LLVMRustUnpackInlineAsmDiagnostic(
+            di,
+            &mut level,
+            &mut cookie,
+            &mut message,
+            &mut instruction,
+        );
 
-        InlineAsmDiagnostic { cookie, message: message.unwrap(), instruction }
+        InlineAsmDiagnostic { level, cookie, message: message.unwrap(), instruction }
     }
 }
 
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index 759c2bf1b85..54cf99e1c6d 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -45,6 +45,8 @@ pub enum CallConv {
     X86_64_Win64 = 79,
     X86_VectorCall = 80,
     X86_Intr = 83,
+    AvrNonBlockingInterrupt = 84,
+    AvrInterrupt = 85,
     AmdGpuKernel = 91,
 }
 
@@ -489,6 +491,17 @@ pub enum DiagnosticKind {
     Linker,
 }
 
+/// LLVMRustDiagnosticLevel
+#[derive(Copy, Clone)]
+#[repr(C)]
+#[allow(dead_code)] // Variants constructed by C++.
+pub enum DiagnosticLevel {
+    Error,
+    Warning,
+    Note,
+    Remark,
+}
+
 /// LLVMRustArchiveKind
 #[derive(Copy, Clone)]
 #[repr(C)]
@@ -2054,6 +2067,7 @@ extern "C" {
 
     pub fn LLVMRustUnpackInlineAsmDiagnostic(
         DI: &'a DiagnosticInfo,
+        level_out: &mut DiagnosticLevel,
         cookie_out: &mut c_uint,
         message_out: &mut Option<&'a Twine>,
         instruction_out: &mut Option<&'a Value>,
@@ -2074,6 +2088,7 @@ extern "C" {
         d: &SMDiagnostic,
         message_out: &RustString,
         buffer_out: &RustString,
+        level_out: &mut DiagnosticLevel,
         loc_out: &mut c_uint,
         ranges_out: *mut c_uint,
         num_ranges: &mut usize,
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index cb5c95c11fa..c118e5ebdb7 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -1551,7 +1551,7 @@ fn spawn_work<B: ExtraBackendMethods>(cgcx: CodegenContext<B>, work: WorkItem<B>
 
 enum SharedEmitterMessage {
     Diagnostic(Diagnostic),
-    InlineAsmError(u32, String, Option<(String, Vec<InnerSpan>)>),
+    InlineAsmError(u32, String, Level, Option<(String, Vec<InnerSpan>)>),
     AbortIfErrors,
     Fatal(String),
 }
@@ -1576,9 +1576,10 @@ impl SharedEmitter {
         &self,
         cookie: u32,
         msg: String,
+        level: Level,
         source: Option<(String, Vec<InnerSpan>)>,
     ) {
-        drop(self.sender.send(SharedEmitterMessage::InlineAsmError(cookie, msg, source)));
+        drop(self.sender.send(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)));
     }
 
     pub fn fatal(&self, msg: &str) {
@@ -1631,16 +1632,21 @@ impl SharedEmitterMain {
                     }
                     handler.emit_diagnostic(&d);
                 }
-                Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, source)) => {
+                Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
                     let msg = msg.strip_prefix("error: ").unwrap_or(&msg);
 
+                    let mut err = match level {
+                        Level::Error => sess.struct_err(&msg),
+                        Level::Warning => sess.struct_warn(&msg),
+                        Level::Note => sess.struct_note_without_error(&msg),
+                        _ => bug!("Invalid inline asm diagnostic level"),
+                    };
+
                     // If the cookie is 0 then we don't have span information.
-                    let mut err = if cookie == 0 {
-                        sess.struct_err(&msg)
-                    } else {
+                    if cookie != 0 {
                         let pos = BytePos::from_u32(cookie);
                         let span = Span::with_root_ctxt(pos, pos);
-                        sess.struct_span_err(span, &msg)
+                        err.set_span(span);
                     };
 
                     // Point to the generated assembly if it is available.
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 30a84c4e47b..ef59ad486ee 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -530,6 +530,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         args: &Vec<mir::Operand<'tcx>>,
         destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>,
         cleanup: Option<mir::BasicBlock>,
+        fn_span: Span,
     ) {
         let span = terminator.source_info.span;
         // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
@@ -634,7 +635,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
         if intrinsic == Some("caller_location") {
             if let Some((_, target)) = destination.as_ref() {
-                let location = self.get_caller_location(&mut bx, span);
+                let location = self.get_caller_location(&mut bx, fn_span);
 
                 if let ReturnDest::IndirectOperand(tmp, _) = ret_dest {
                     location.val.store(&mut bx, tmp);
@@ -798,7 +799,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 args.len() + 1,
                 "#[track_caller] fn's must have 1 more argument in their ABI than in their MIR",
             );
-            let location = self.get_caller_location(&mut bx, span);
+            let location = self.get_caller_location(&mut bx, fn_span);
+            debug!(
+                "codegen_call_terminator({:?}): location={:?} (fn_span {:?})",
+                terminator, location, fn_span
+            );
+
             let last_arg = fn_abi.args.last().unwrap();
             self.codegen_argument(&mut bx, location, &mut llargs, last_arg);
         }
@@ -921,12 +927,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         span_bug!(span, "invalid type for asm sym (fn)");
                     }
                 }
-                mir::InlineAsmOperand::SymStatic { ref value } => {
-                    if let Some(def_id) = value.check_static_ptr(bx.tcx()) {
-                        InlineAsmOperandRef::SymStatic { def_id }
-                    } else {
-                        span_bug!(span, "invalid type for asm sym (static)");
-                    }
+                mir::InlineAsmOperand::SymStatic { def_id } => {
+                    InlineAsmOperandRef::SymStatic { def_id }
                 }
             })
             .collect();
@@ -1016,6 +1018,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 ref destination,
                 cleanup,
                 from_hir_call: _,
+                fn_span,
             } => {
                 self.codegen_call_terminator(
                     helper,
@@ -1025,6 +1028,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     args,
                     destination,
                     cleanup,
+                    fn_span,
                 );
             }
             mir::TerminatorKind::GeneratorDrop | mir::TerminatorKind::Yield { .. } => {
diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs
index 574f91e5b4d..11ec62f96ed 100644
--- a/src/librustc_codegen_ssa/mir/constant.rs
+++ b/src/librustc_codegen_ssa/mir/constant.rs
@@ -63,7 +63,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     .tcx()
                     .destructure_const(ty::ParamEnv::reveal_all().and(&c))
                     .fields
-                    .into_iter()
+                    .iter()
                     .map(|field| {
                         if let Some(prim) = field.val.try_to_scalar() {
                             let layout = bx.layout_of(field_ty);
diff --git a/src/librustc_data_structures/base_n/tests.rs b/src/librustc_data_structures/base_n/tests.rs
index a86f991cd0e..b68ef1eb7f4 100644
--- a/src/librustc_data_structures/base_n/tests.rs
+++ b/src/librustc_data_structures/base_n/tests.rs
@@ -12,8 +12,8 @@ fn test_encode() {
         test(35, base);
         test(36, base);
         test(37, base);
-        test(u64::max_value() as u128, base);
-        test(u128::max_value(), base);
+        test(u64::MAX as u128, base);
+        test(u128::MAX, base);
 
         for i in 0..1_000 {
             test(i * 983, base);
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index ec5b3251e68..3fb5e04efc9 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -409,6 +409,7 @@ E0718: include_str!("./error_codes/E0718.md"),
 E0719: include_str!("./error_codes/E0719.md"),
 E0720: include_str!("./error_codes/E0720.md"),
 E0723: include_str!("./error_codes/E0723.md"),
+E0724: include_str!("./error_codes/E0724.md"),
 E0725: include_str!("./error_codes/E0725.md"),
 E0727: include_str!("./error_codes/E0727.md"),
 E0728: include_str!("./error_codes/E0728.md"),
@@ -440,6 +441,7 @@ E0754: include_str!("./error_codes/E0754.md"),
 E0758: include_str!("./error_codes/E0758.md"),
 E0760: include_str!("./error_codes/E0760.md"),
 E0761: include_str!("./error_codes/E0761.md"),
+E0762: include_str!("./error_codes/E0762.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
@@ -616,7 +618,6 @@ E0761: include_str!("./error_codes/E0761.md"),
     E0717, // rustc_promotable without stability attribute
 //  E0721, // `await` keyword
     E0722, // Malformed `#[optimize]` attribute
-    E0724, // `#[ffi_returns_twice]` is only allowed in foreign functions
     E0726, // non-explicit (not `'_`) elided lifetime in unsupported position
 //  E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
     E0755, // `#[ffi_pure]` is only allowed on foreign functions
diff --git a/src/librustc_error_codes/error_codes/E0446.md b/src/librustc_error_codes/error_codes/E0446.md
index 77a1834ece4..6ec47c4962c 100644
--- a/src/librustc_error_codes/error_codes/E0446.md
+++ b/src/librustc_error_codes/error_codes/E0446.md
@@ -4,10 +4,10 @@ Erroneous code example:
 
 ```compile_fail,E0446
 #![deny(private_in_public)]
+struct Bar(u32);
 
-mod Foo {
-    struct Bar(u32);
-
+mod foo {
+    use crate::Bar;
     pub fn bar() -> Bar { // error: private type in public interface
         Bar(0)
     }
@@ -16,15 +16,31 @@ mod Foo {
 fn main() {}
 ```
 
-To solve this error, please ensure that the type is also public. The type
-can be made inaccessible if necessary by placing it into a private inner
-module, but it still has to be marked with `pub`.
+There are two ways to solve this error. The first is to make the public type
+signature only public to a module that also has access to the private type.
+This is done by using pub(crate) or pub(in crate::my_mod::etc)
 Example:
 
 ```
-mod Foo {
-    pub struct Bar(u32); // we set the Bar type public
+struct Bar(u32);
+
+mod foo {
+    use crate::Bar;
+    pub(crate) fn bar() -> Bar { // only public to crate root
+        Bar(0)
+    }
+}
 
+fn main() {}
+```
+
+The other way to solve this error is to make the private type public.
+Example:
+
+```
+pub struct Bar(u32); // we set the Bar type public
+mod foo {
+    use crate::Bar;
     pub fn bar() -> Bar { // ok!
         Bar(0)
     }
diff --git a/src/librustc_error_codes/error_codes/E0493.md b/src/librustc_error_codes/error_codes/E0493.md
index 90a0cbce623..0dcc3b62b4b 100644
--- a/src/librustc_error_codes/error_codes/E0493.md
+++ b/src/librustc_error_codes/error_codes/E0493.md
@@ -1,5 +1,4 @@
-A type with a `Drop` implementation was destructured when trying to initialize
-a static item.
+A value with a custom `Drop` implementation may be dropped during const-eval.
 
 Erroneous code example:
 
@@ -16,13 +15,14 @@ struct Foo {
     field1: DropType,
 }
 
-static FOO: Foo = Foo { ..Foo { field1: DropType::A } }; // error!
+static FOO: Foo = Foo { field1: (DropType::A, DropType::A).1 }; // error!
 ```
 
 The problem here is that if the given type or one of its fields implements the
-`Drop` trait, this `Drop` implementation cannot be called during the static
-type initialization which might cause a memory leak. To prevent this issue,
-you need to instantiate all the static type's fields by hand.
+`Drop` trait, this `Drop` implementation cannot be called within a const
+context since it may run arbitrary, non-const-checked code. To prevent this
+issue, ensure all values with custom a custom `Drop` implementation escape the
+initializer.
 
 ```
 enum DropType {
diff --git a/src/librustc_error_codes/error_codes/E0642.md b/src/librustc_error_codes/error_codes/E0642.md
index 592ada6ecad..c790aa154bd 100644
--- a/src/librustc_error_codes/error_codes/E0642.md
+++ b/src/librustc_error_codes/error_codes/E0642.md
@@ -1,6 +1,6 @@
 Trait methods currently cannot take patterns as arguments.
 
-Example of erroneous code:
+Erroneous code example:
 
 ```compile_fail,E0642
 trait Foo {
diff --git a/src/librustc_error_codes/error_codes/E0648.md b/src/librustc_error_codes/error_codes/E0648.md
index 319bae103f3..d99dc19503d 100644
--- a/src/librustc_error_codes/error_codes/E0648.md
+++ b/src/librustc_error_codes/error_codes/E0648.md
@@ -1,6 +1,15 @@
-`export_name` attributes may not contain null characters (`\0`).
+An `export_name` attribute contains null characters (`\0`).
+
+Erroneous code example:
 
 ```compile_fail,E0648
 #[export_name="\0foo"] // error: `export_name` may not contain null characters
 pub fn bar() {}
 ```
+
+To fix this error, remove the null characters:
+
+```
+#[export_name="foo"] // ok!
+pub fn bar() {}
+```
diff --git a/src/librustc_error_codes/error_codes/E0666.md b/src/librustc_error_codes/error_codes/E0666.md
index 22133683dc5..1a0dc5a5229 100644
--- a/src/librustc_error_codes/error_codes/E0666.md
+++ b/src/librustc_error_codes/error_codes/E0666.md
@@ -1,21 +1,25 @@
-`impl Trait` types cannot appear nested in the
-generic arguments of other `impl Trait` types.
+`impl Trait` types cannot appear nested in the generic arguments of other
+`impl Trait` types.
 
-Example of erroneous code:
+Erroneous code example:
 
 ```compile_fail,E0666
 trait MyGenericTrait<T> {}
 trait MyInnerTrait {}
 
-fn foo(bar: impl MyGenericTrait<impl MyInnerTrait>) {}
+fn foo(
+    bar: impl MyGenericTrait<impl MyInnerTrait>, // error!
+) {}
 ```
 
-Type parameters for `impl Trait` types must be
-explicitly defined as named generic parameters:
+Type parameters for `impl Trait` types must be explicitly defined as named
+generic parameters:
 
 ```
 trait MyGenericTrait<T> {}
 trait MyInnerTrait {}
 
-fn foo<T: MyInnerTrait>(bar: impl MyGenericTrait<T>) {}
+fn foo<T: MyInnerTrait>(
+    bar: impl MyGenericTrait<T>, // ok!
+) {}
 ```
diff --git a/src/librustc_error_codes/error_codes/E0724.md b/src/librustc_error_codes/error_codes/E0724.md
new file mode 100644
index 00000000000..7a7ba154854
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0724.md
@@ -0,0 +1,24 @@
+`#[ffi_returns_twice]` was used on non-foreign function.
+
+Erroneous code example:
+
+```compile_fail,E0724
+#![feature(ffi_returns_twice)]
+#![crate_type = "lib"]
+
+#[ffi_returns_twice] // error!
+pub fn foo() {}
+```
+
+`#[ffi_returns_twice]` can only be used on foreign function declarations.
+For example, we might correct the previous example by declaring
+the function inside of an `extern` block.
+
+```
+#![feature(ffi_returns_twice)]
+
+extern {
+   #[ffi_returns_twice] // ok!
+   pub fn foo();
+}
+```
diff --git a/src/librustc_error_codes/error_codes/E0762.md b/src/librustc_error_codes/error_codes/E0762.md
new file mode 100644
index 00000000000..b01ded4a866
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0762.md
@@ -0,0 +1,13 @@
+A character literal wasn't ended with a quote.
+
+Erroneous code example:
+
+```compile_fail,E0762
+static C: char = '●; // error!
+```
+
+To fix this error, add the missing quote:
+
+```
+static C: char = '●'; // ok!
+```
diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs
index 5b47364e714..265ba59cccb 100644
--- a/src/librustc_errors/annotate_snippet_emitter_writer.rs
+++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs
@@ -159,14 +159,10 @@ impl AnnotateSnippetEmitterWriter {
                             // FIXME(#59346): Not really sure when `fold` should be true or false
                             fold: false,
                             annotations: annotations
-                                .into_iter()
+                                .iter()
                                 .map(|annotation| SourceAnnotation {
                                     range: (annotation.start_col, annotation.end_col),
-                                    label: annotation
-                                        .label
-                                        .as_ref()
-                                        .map(|s| s.as_str())
-                                        .unwrap_or_default(),
+                                    label: annotation.label.as_deref().unwrap_or_default(),
                                     annotation_type: annotation_type_for_level(*level),
                                 })
                                 .collect(),
diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs
index cff83c3d5cd..acaa26c6ad2 100644
--- a/src/librustc_errors/diagnostic.rs
+++ b/src/librustc_errors/diagnostic.rs
@@ -296,6 +296,29 @@ impl Diagnostic {
         self
     }
 
+    pub fn multipart_suggestions(
+        &mut self,
+        msg: &str,
+        suggestions: Vec<Vec<(Span, String)>>,
+        applicability: Applicability,
+    ) -> &mut Self {
+        self.suggestions.push(CodeSuggestion {
+            substitutions: suggestions
+                .into_iter()
+                .map(|suggestion| Substitution {
+                    parts: suggestion
+                        .into_iter()
+                        .map(|(span, snippet)| SubstitutionPart { snippet, span })
+                        .collect(),
+                })
+                .collect(),
+            msg: msg.to_owned(),
+            style: SuggestionStyle::ShowCode,
+            applicability,
+        });
+        self
+    }
+
     /// Prints out a message with for a multipart suggestion without showing the suggested code.
     ///
     /// This is intended to be used for suggestions that are obvious in what the changes need to
diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs
index 2dbd9f4e52f..22bf8fe34aa 100644
--- a/src/librustc_errors/diagnostic_builder.rs
+++ b/src/librustc_errors/diagnostic_builder.rs
@@ -260,6 +260,19 @@ impl<'a> DiagnosticBuilder<'a> {
         self
     }
 
+    pub fn multipart_suggestions(
+        &mut self,
+        msg: &str,
+        suggestions: Vec<Vec<(Span, String)>>,
+        applicability: Applicability,
+    ) -> &mut Self {
+        if !self.0.allow_suggestions {
+            return self;
+        }
+        self.0.diagnostic.multipart_suggestions(msg, suggestions, applicability);
+        self
+    }
+
     pub fn tool_only_multipart_suggestion(
         &mut self,
         msg: &str,
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index e4a560e434a..7261c638ce0 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -581,6 +581,11 @@ impl Handler {
         DiagnosticBuilder::new(self, Level::Help, msg)
     }
 
+    /// Construct a builder at the `Note` level with the `msg`.
+    pub fn struct_note_without_error(&self, msg: &str) -> DiagnosticBuilder<'_> {
+        DiagnosticBuilder::new(self, Level::Note, msg)
+    }
+
     pub fn span_fatal(&self, span: impl Into<MultiSpan>, msg: &str) -> FatalError {
         self.emit_diag_at_span(Diagnostic::new(Fatal, msg), span);
         FatalError
diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs
index 13637e58c93..a57ae798ffc 100644
--- a/src/librustc_expand/base.rs
+++ b/src/librustc_expand/base.rs
@@ -915,6 +915,9 @@ pub trait Resolver {
 
     fn check_unused_macros(&mut self);
 
+    /// Some parent node that is close enough to the given macro call.
+    fn lint_node_id(&mut self, expn_id: ExpnId) -> NodeId;
+
     fn has_derive_copy(&self, expn_id: ExpnId) -> bool;
     fn add_derive_copy(&mut self, expn_id: ExpnId);
     fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result<bool, Indeterminate>;
diff --git a/src/librustc_expand/build.rs b/src/librustc_expand/build.rs
index 6185e014d3c..20d2ea0a215 100644
--- a/src/librustc_expand/build.rs
+++ b/src/librustc_expand/build.rs
@@ -272,7 +272,7 @@ impl<'a> ExtCtxt<'a> {
     ) -> P<ast::Expr> {
         args.insert(0, expr);
         let segment = ast::PathSegment::from_ident(ident.with_span_pos(span));
-        self.expr(span, ast::ExprKind::MethodCall(segment, args))
+        self.expr(span, ast::ExprKind::MethodCall(segment, args, span))
     }
     pub fn expr_block(&self, b: P<ast::Block>) -> P<ast::Expr> {
         self.expr(b.span, ast::ExprKind::Block(b, None))
diff --git a/src/librustc_expand/mbe/macro_check.rs b/src/librustc_expand/mbe/macro_check.rs
index 582c26162ed..ca3e68fa670 100644
--- a/src/librustc_expand/mbe/macro_check.rs
+++ b/src/librustc_expand/mbe/macro_check.rs
@@ -106,7 +106,7 @@
 //! bound.
 use crate::mbe::{KleeneToken, TokenTree};
 
-use rustc_ast::ast::NodeId;
+use rustc_ast::ast::{NodeId, DUMMY_NODE_ID};
 use rustc_ast::token::{DelimToken, Token, TokenKind};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_session::lint::builtin::META_VARIABLE_MISUSE;
@@ -626,5 +626,8 @@ fn ops_is_prefix(
 }
 
 fn buffer_lint(sess: &ParseSess, span: MultiSpan, node_id: NodeId, message: &str) {
-    sess.buffer_lint(&META_VARIABLE_MISUSE, span, node_id, message);
+    // Macros loaded from other crates have dummy node ids.
+    if node_id != DUMMY_NODE_ID {
+        sess.buffer_lint(&META_VARIABLE_MISUSE, span, node_id, message);
+    }
 }
diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs
index 0cf092d912b..db8258a7786 100644
--- a/src/librustc_expand/mbe/macro_parser.rs
+++ b/src/librustc_expand/mbe/macro_parser.rs
@@ -383,7 +383,7 @@ fn nameize<I: Iterator<Item = NamedMatch>>(
                 }
             }
             TokenTree::MetaVarDecl(span, _, id) if id.name == kw::Invalid => {
-                if sess.missing_fragment_specifiers.borrow_mut().remove(&span) {
+                if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() {
                     return Err((span, "missing fragment specifier".to_string()));
                 }
             }
@@ -566,7 +566,7 @@ fn inner_parse_loop<'root, 'tt>(
 
                 // We need to match a metavar (but the identifier is invalid)... this is an error
                 TokenTree::MetaVarDecl(span, _, id) if id.name == kw::Invalid => {
-                    if sess.missing_fragment_specifiers.borrow_mut().remove(&span) {
+                    if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() {
                         return Error(span, "missing fragment specifier".to_string());
                     }
                 }
diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs
index ecadf320f87..8cdb5b09c9e 100644
--- a/src/librustc_expand/mbe/macro_rules.rs
+++ b/src/librustc_expand/mbe/macro_rules.rs
@@ -474,7 +474,9 @@ pub fn compile_declarative_macro(
             .map(|m| {
                 if let MatchedNonterminal(ref nt) = *m {
                     if let NtTT(ref tt) = **nt {
-                        let tt = mbe::quoted::parse(tt.clone().into(), true, sess).pop().unwrap();
+                        let tt = mbe::quoted::parse(tt.clone().into(), true, sess, def.id)
+                            .pop()
+                            .unwrap();
                         valid &= check_lhs_nt_follows(sess, features, &def.attrs, &tt);
                         return tt;
                     }
@@ -491,7 +493,9 @@ pub fn compile_declarative_macro(
             .map(|m| {
                 if let MatchedNonterminal(ref nt) = *m {
                     if let NtTT(ref tt) = **nt {
-                        return mbe::quoted::parse(tt.clone().into(), false, sess).pop().unwrap();
+                        return mbe::quoted::parse(tt.clone().into(), false, sess, def.id)
+                            .pop()
+                            .unwrap();
                     }
                 }
                 sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs")
@@ -509,9 +513,7 @@ pub fn compile_declarative_macro(
         valid &= check_lhs_no_empty_seq(sess, slice::from_ref(lhs));
     }
 
-    // We use CRATE_NODE_ID instead of `def.id` otherwise we may emit buffered lints for a node id
-    // that is not lint-checked and trigger the "failed to process buffered lint here" bug.
-    valid &= macro_check::check_meta_variables(sess, ast::CRATE_NODE_ID, def.span, &lhses, &rhses);
+    valid &= macro_check::check_meta_variables(sess, def.id, def.span, &lhses, &rhses);
 
     let (transparency, transparency_error) = attr::find_transparency(&def.attrs, macro_rules);
     match transparency_error {
diff --git a/src/librustc_expand/mbe/quoted.rs b/src/librustc_expand/mbe/quoted.rs
index 3295f5b392d..de66c2ada40 100644
--- a/src/librustc_expand/mbe/quoted.rs
+++ b/src/librustc_expand/mbe/quoted.rs
@@ -1,6 +1,7 @@
 use crate::mbe::macro_parser;
 use crate::mbe::{Delimited, KleeneOp, KleeneToken, SequenceRepetition, TokenTree};
 
+use rustc_ast::ast::{NodeId, DUMMY_NODE_ID};
 use rustc_ast::token::{self, Token};
 use rustc_ast::tokenstream;
 use rustc_ast_pretty::pprust;
@@ -36,6 +37,7 @@ pub(super) fn parse(
     input: tokenstream::TokenStream,
     expect_matchers: bool,
     sess: &ParseSess,
+    node_id: NodeId,
 ) -> Vec<TokenTree> {
     // Will contain the final collection of `self::TokenTree`
     let mut result = Vec::new();
@@ -46,7 +48,7 @@ pub(super) fn parse(
     while let Some(tree) = trees.next() {
         // Given the parsed tree, if there is a metavar and we are expecting matchers, actually
         // parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`).
-        let tree = parse_tree(tree, &mut trees, expect_matchers, sess);
+        let tree = parse_tree(tree, &mut trees, expect_matchers, sess, node_id);
         match tree {
             TokenTree::MetaVar(start_sp, ident) if expect_matchers => {
                 let span = match trees.next() {
@@ -65,7 +67,10 @@ pub(super) fn parse(
                     }
                     tree => tree.as_ref().map(tokenstream::TokenTree::span).unwrap_or(start_sp),
                 };
-                sess.missing_fragment_specifiers.borrow_mut().insert(span);
+                if node_id != DUMMY_NODE_ID {
+                    // Macros loaded from other crates have dummy node ids.
+                    sess.missing_fragment_specifiers.borrow_mut().insert(span, node_id);
+                }
                 result.push(TokenTree::MetaVarDecl(span, ident, Ident::invalid()));
             }
 
@@ -96,6 +101,7 @@ fn parse_tree(
     trees: &mut impl Iterator<Item = tokenstream::TokenTree>,
     expect_matchers: bool,
     sess: &ParseSess,
+    node_id: NodeId,
 ) -> TokenTree {
     // Depending on what `tree` is, we could be parsing different parts of a macro
     match tree {
@@ -111,7 +117,7 @@ fn parse_tree(
                     sess.span_diagnostic.span_err(span.entire(), &msg);
                 }
                 // Parse the contents of the sequence itself
-                let sequence = parse(tts, expect_matchers, sess);
+                let sequence = parse(tts, expect_matchers, sess, node_id);
                 // Get the Kleene operator and optional separator
                 let (separator, kleene) = parse_sep_and_kleene_op(trees, span.entire(), sess);
                 // Count the number of captured "names" (i.e., named metavars)
@@ -158,7 +164,7 @@ fn parse_tree(
         // descend into the delimited set and further parse it.
         tokenstream::TokenTree::Delimited(span, delim, tts) => TokenTree::Delimited(
             span,
-            Lrc::new(Delimited { delim, tts: parse(tts, expect_matchers, sess) }),
+            Lrc::new(Delimited { delim, tts: parse(tts, expect_matchers, sess, node_id) }),
         ),
     }
 }
diff --git a/src/librustc_expand/proc_macro_server.rs b/src/librustc_expand/proc_macro_server.rs
index 79fa091ba18..ea55674045c 100644
--- a/src/librustc_expand/proc_macro_server.rs
+++ b/src/librustc_expand/proc_macro_server.rs
@@ -582,10 +582,10 @@ impl server::Literal for Rustc<'_> {
         };
 
         // Bounds check the values, preventing addition overflow and OOB spans.
-        if start > u32::max_value() as usize
-            || end > u32::max_value() as usize
-            || (u32::max_value() - start as u32) < span.lo().to_u32()
-            || (u32::max_value() - end as u32) < span.lo().to_u32()
+        if start > u32::MAX as usize
+            || end > u32::MAX as usize
+            || (u32::MAX - start as u32) < span.lo().to_u32()
+            || (u32::MAX - end as u32) < span.lo().to_u32()
             || start >= end
             || end > length
         {
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index fd35cb6c3f7..d186f35a12b 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -574,6 +574,12 @@ declare_features! (
     /// No longer treat an unsafe function as an unsafe block.
     (active, unsafe_block_in_unsafe_fn, "1.45.0", Some(71668), None),
 
+    /// Allows `extern "avr-interrupt" fn()` and `extern "avr-non-blocking-interrupt" fn()`.
+    (active, abi_avr_interrupt, "1.45.0", Some(69664), None),
+
+    /// Be more precise when looking for live drops in a const context.
+    (active, const_precise_live_drops, "1.46.0", Some(73255), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
diff --git a/src/librustc_hir/arena.rs b/src/librustc_hir/arena.rs
index 6ba39666607..f439db71531 100644
--- a/src/librustc_hir/arena.rs
+++ b/src/librustc_hir/arena.rs
@@ -12,41 +12,41 @@ macro_rules! arena_types {
     ($macro:path, $args:tt, $tcx:lifetime) => (
         $macro!($args, [
             // HIR types
-            [few] hir_krate: rustc_hir::Crate<$tcx>,
-            [] arm: rustc_hir::Arm<$tcx>,
-            [] asm_operand: rustc_hir::InlineAsmOperand<$tcx>,
-            [] asm_template: rustc_ast::ast::InlineAsmTemplatePiece,
-            [] attribute: rustc_ast::ast::Attribute,
-            [] block: rustc_hir::Block<$tcx>,
-            [] bare_fn_ty: rustc_hir::BareFnTy<$tcx>,
-            [few] global_asm: rustc_hir::GlobalAsm,
-            [] generic_arg: rustc_hir::GenericArg<$tcx>,
-            [] generic_args: rustc_hir::GenericArgs<$tcx>,
-            [] generic_bound: rustc_hir::GenericBound<$tcx>,
-            [] generic_param: rustc_hir::GenericParam<$tcx>,
-            [] expr: rustc_hir::Expr<$tcx>,
-            [] field: rustc_hir::Field<$tcx>,
-            [] field_pat: rustc_hir::FieldPat<$tcx>,
-            [] fn_decl: rustc_hir::FnDecl<$tcx>,
-            [] foreign_item: rustc_hir::ForeignItem<$tcx>,
-            [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>,
-            [few] inline_asm: rustc_hir::InlineAsm<$tcx>,
-            [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>,
-            [] local: rustc_hir::Local<$tcx>,
-            [few] macro_def: rustc_hir::MacroDef<$tcx>,
-            [] param: rustc_hir::Param<$tcx>,
-            [] pat: rustc_hir::Pat<$tcx>,
-            [] path: rustc_hir::Path<$tcx>,
-            [] path_segment: rustc_hir::PathSegment<$tcx>,
-            [] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>,
-            [] qpath: rustc_hir::QPath<$tcx>,
-            [] stmt: rustc_hir::Stmt<$tcx>,
-            [] struct_field: rustc_hir::StructField<$tcx>,
-            [] trait_item_ref: rustc_hir::TraitItemRef,
-            [] ty: rustc_hir::Ty<$tcx>,
-            [] type_binding: rustc_hir::TypeBinding<$tcx>,
-            [] variant: rustc_hir::Variant<$tcx>,
-            [] where_predicate: rustc_hir::WherePredicate<$tcx>,
+            [few] hir_krate: rustc_hir::Crate<$tcx>, rustc_hir::Crate<'_x>;
+            [] arm: rustc_hir::Arm<$tcx>, rustc_hir::Arm<'_x>;
+            [] asm_operand: rustc_hir::InlineAsmOperand<$tcx>, rustc_hir::InlineAsmOperand<'_x>;
+            [] asm_template: rustc_ast::ast::InlineAsmTemplatePiece, rustc_ast::ast::InlineAsmTemplatePiece;
+            [] attribute: rustc_ast::ast::Attribute, rustc_ast::ast::Attribute;
+            [] block: rustc_hir::Block<$tcx>, rustc_hir::Block<'_x>;
+            [] bare_fn_ty: rustc_hir::BareFnTy<$tcx>, rustc_hir::BareFnTy<'_x>;
+            [few] global_asm: rustc_hir::GlobalAsm, rustc_hir::GlobalAsm;
+            [] generic_arg: rustc_hir::GenericArg<$tcx>, rustc_hir::GenericArg<'_x>;
+            [] generic_args: rustc_hir::GenericArgs<$tcx>, rustc_hir::GenericArgs<'_x>;
+            [] generic_bound: rustc_hir::GenericBound<$tcx>, rustc_hir::GenericBound<'_x>;
+            [] generic_param: rustc_hir::GenericParam<$tcx>, rustc_hir::GenericParam<'_x>;
+            [] expr: rustc_hir::Expr<$tcx>, rustc_hir::Expr<'_x>;
+            [] field: rustc_hir::Field<$tcx>, rustc_hir::Field<'_x>;
+            [] field_pat: rustc_hir::FieldPat<$tcx>, rustc_hir::FieldPat<'_x>;
+            [] fn_decl: rustc_hir::FnDecl<$tcx>, rustc_hir::FnDecl<'_x>;
+            [] foreign_item: rustc_hir::ForeignItem<$tcx>, rustc_hir::ForeignItem<'_x>;
+            [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>, rustc_hir::ImplItemRef<'_x>;
+            [few] inline_asm: rustc_hir::InlineAsm<$tcx>, rustc_hir::InlineAsm<'_x>;
+            [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>, rustc_hir::LlvmInlineAsm<'_x>;
+            [] local: rustc_hir::Local<$tcx>, rustc_hir::Local<'_x>;
+            [few] macro_def: rustc_hir::MacroDef<$tcx>, rustc_hir::MacroDef<'_x>;
+            [] param: rustc_hir::Param<$tcx>, rustc_hir::Param<'_x>;
+            [] pat: rustc_hir::Pat<$tcx>, rustc_hir::Pat<'_x>;
+            [] path: rustc_hir::Path<$tcx>, rustc_hir::Path<'_x>;
+            [] path_segment: rustc_hir::PathSegment<$tcx>, rustc_hir::PathSegment<'_x>;
+            [] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>, rustc_hir::PolyTraitRef<'_x>;
+            [] qpath: rustc_hir::QPath<$tcx>, rustc_hir::QPath<'_x>;
+            [] stmt: rustc_hir::Stmt<$tcx>, rustc_hir::Stmt<'_x>;
+            [] struct_field: rustc_hir::StructField<$tcx>, rustc_hir::StructField<'_x>;
+            [] trait_item_ref: rustc_hir::TraitItemRef, rustc_hir::TraitItemRef;
+            [] ty: rustc_hir::Ty<$tcx>, rustc_hir::Ty<'_x>;
+            [] type_binding: rustc_hir::TypeBinding<$tcx>, rustc_hir::TypeBinding<'_x>;
+            [] variant: rustc_hir::Variant<$tcx>, rustc_hir::Variant<'_x>;
+            [] where_predicate: rustc_hir::WherePredicate<$tcx>, rustc_hir::WherePredicate<'_x>;
         ], $tcx);
     )
 }
diff --git a/src/librustc_hir/def.rs b/src/librustc_hir/def.rs
index 88049f85f45..af1860ca6bf 100644
--- a/src/librustc_hir/def.rs
+++ b/src/librustc_hir/def.rs
@@ -54,15 +54,11 @@ pub enum DefKind {
     /// Refers to the variant itself, `DefKind::Ctor` refers to its constructor if it exists.
     Variant,
     Trait,
-    /// `type Foo = impl Bar;`
-    OpaqueTy,
     /// `type Foo = Bar;`
     TyAlias,
     ForeignTy,
     TraitAlias,
     AssocTy,
-    /// `type Foo = impl Bar;`
-    AssocOpaqueTy,
     TyParam,
 
     // Value namespace
@@ -83,6 +79,7 @@ pub enum DefKind {
     Use,
     ForeignMod,
     AnonConst,
+    OpaqueTy,
     Field,
     LifetimeParam,
     GlobalAsm,
@@ -115,7 +112,6 @@ impl DefKind {
             DefKind::TyAlias => "type alias",
             DefKind::TraitAlias => "trait alias",
             DefKind::AssocTy => "associated type",
-            DefKind::AssocOpaqueTy => "associated opaque type",
             DefKind::Union => "union",
             DefKind::Trait => "trait",
             DefKind::ForeignTy => "foreign type",
@@ -143,7 +139,6 @@ impl DefKind {
         match *self {
             DefKind::AssocTy
             | DefKind::AssocConst
-            | DefKind::AssocOpaqueTy
             | DefKind::AssocFn
             | DefKind::Enum
             | DefKind::OpaqueTy
@@ -168,7 +163,6 @@ impl DefKind {
             | DefKind::ForeignTy
             | DefKind::TraitAlias
             | DefKind::AssocTy
-            | DefKind::AssocOpaqueTy
             | DefKind::TyParam => ns == Namespace::TypeNS,
 
             DefKind::Fn
diff --git a/src/librustc_hir/definitions.rs b/src/librustc_hir/definitions.rs
index 2dd5e27ead2..b63dd653c4d 100644
--- a/src/librustc_hir/definitions.rs
+++ b/src/librustc_hir/definitions.rs
@@ -519,6 +519,12 @@ impl Definitions {
         let old_index = self.placeholder_field_indices.insert(node_id, index);
         assert!(old_index.is_none(), "placeholder field index is reset for a node ID");
     }
+
+    pub fn lint_node_id(&mut self, expn_id: ExpnId) -> ast::NodeId {
+        self.invocation_parents
+            .get(&expn_id)
+            .map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[*id])
+    }
 }
 
 impl DefPathData {
diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs
index 1e305c6d32d..634ab32a285 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -1371,7 +1371,7 @@ pub struct Expr<'hir> {
 
 // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
-rustc_data_structures::static_assert_size!(Expr<'static>, 64);
+rustc_data_structures::static_assert_size!(Expr<'static>, 72);
 
 impl Expr<'_> {
     pub fn precedence(&self) -> ExprPrecedence {
@@ -1568,12 +1568,14 @@ pub enum ExprKind<'hir> {
     /// and the remaining elements are the rest of the arguments.
     /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
     /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
+    /// The final `Span` represents the span of the function and arguments
+    /// (e.g. `foo::<Bar, Baz>(a, b, c, d)` in `x.foo::<Bar, Baz>(a, b, c, d)`
     ///
     /// To resolve the called method to a `DefId`, call [`type_dependent_def_id`] with
     /// the `hir_id` of the `MethodCall` node itself.
     ///
     /// [`type_dependent_def_id`]: ../ty/struct.TypeckTables.html#method.type_dependent_def_id
-    MethodCall(&'hir PathSegment<'hir>, Span, &'hir [Expr<'hir>]),
+    MethodCall(&'hir PathSegment<'hir>, Span, &'hir [Expr<'hir>], Span),
     /// A tuple (e.g., `(a, b, c, d)`).
     Tup(&'hir [Expr<'hir>]),
     /// A binary operation (e.g., `a + b`, `a * b`).
@@ -1919,14 +1921,12 @@ pub enum ImplItemKind<'hir> {
     Fn(FnSig<'hir>, BodyId),
     /// An associated type.
     TyAlias(&'hir Ty<'hir>),
-    /// An associated `type = impl Trait`.
-    OpaqueTy(GenericBounds<'hir>),
 }
 
 impl ImplItemKind<'_> {
     pub fn namespace(&self) -> Namespace {
         match self {
-            ImplItemKind::OpaqueTy(..) | ImplItemKind::TyAlias(..) => Namespace::TypeNS,
+            ImplItemKind::TyAlias(..) => Namespace::TypeNS,
             ImplItemKind::Const(..) | ImplItemKind::Fn(..) => Namespace::ValueNS,
         }
     }
@@ -2016,13 +2016,13 @@ pub struct OpaqueTy<'hir> {
 /// From whence the opaque type came.
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
 pub enum OpaqueTyOrigin {
-    /// `type Foo = impl Trait;`
-    TypeAlias,
     /// `-> impl Trait`
     FnReturn,
     /// `async fn`
     AsyncFn,
-    /// Impl trait in bindings, consts, statics, bounds.
+    /// `let _: impl Trait = ...`
+    Binding,
+    /// Impl trait in type aliases, consts, statics, bounds.
     Misc,
 }
 
@@ -2048,12 +2048,12 @@ pub enum TyKind<'hir> {
     ///
     /// Type parameters may be stored in each `PathSegment`.
     Path(QPath<'hir>),
-    /// A type definition itself. This is currently only used for the `type Foo = impl Trait`
-    /// item that `impl Trait` in return position desugars to.
+    /// A opaque type definition itself. This is currently only used for the
+    /// `opaque type Foo: Trait` item that `impl Trait` in desugars to.
     ///
-    /// The generic argument list contains the lifetimes (and in the future possibly parameters)
-    /// that are actually bound on the `impl Trait`.
-    Def(ItemId, &'hir [GenericArg<'hir>]),
+    /// The generic argument list contains the lifetimes (and in the future
+    /// possibly parameters) that are actually bound on the `impl Trait`.
+    OpaqueDef(ItemId, &'hir [GenericArg<'hir>]),
     /// A trait object type `Bound1 + Bound2 + Bound3`
     /// where `Bound` is a trait or a lifetime.
     TraitObject(&'hir [PolyTraitRef<'hir>], Lifetime),
@@ -2614,7 +2614,6 @@ pub enum AssocItemKind {
     Const,
     Fn { has_self: bool },
     Type,
-    OpaqueTy,
 }
 
 #[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
diff --git a/src/librustc_hir/intravisit.rs b/src/librustc_hir/intravisit.rs
index 97601a3e1ac..23d642731da 100644
--- a/src/librustc_hir/intravisit.rs
+++ b/src/librustc_hir/intravisit.rs
@@ -690,7 +690,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
         TyKind::Path(ref qpath) => {
             visitor.visit_qpath(qpath, typ.hir_id, typ.span);
         }
-        TyKind::Def(item_id, lifetimes) => {
+        TyKind::OpaqueDef(item_id, lifetimes) => {
             visitor.visit_nested_item(item_id);
             walk_list!(visitor, visit_generic_arg, lifetimes);
         }
@@ -1007,10 +1007,6 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
             visitor.visit_id(impl_item.hir_id);
             visitor.visit_ty(ty);
         }
-        ImplItemKind::OpaqueTy(bounds) => {
-            visitor.visit_id(impl_item.hir_id);
-            walk_list!(visitor, visit_param_bound, bounds);
-        }
     }
 }
 
@@ -1090,7 +1086,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
             visitor.visit_expr(callee_expression);
             walk_list!(visitor, visit_expr, arguments);
         }
-        ExprKind::MethodCall(ref segment, _, arguments) => {
+        ExprKind::MethodCall(ref segment, _, arguments, _) => {
             visitor.visit_path_segment(expression.span, segment);
             walk_list!(visitor, visit_expr, arguments);
         }
diff --git a/src/librustc_hir_pretty/lib.rs b/src/librustc_hir_pretty/lib.rs
index e642915b86a..c16b7c63e31 100644
--- a/src/librustc_hir_pretty/lib.rs
+++ b/src/librustc_hir_pretty/lib.rs
@@ -227,6 +227,28 @@ pub fn path_to_string(segment: &hir::Path<'_>) -> String {
     to_string(NO_ANN, |s| s.print_path(segment, false))
 }
 
+pub fn fn_to_string(
+    decl: &hir::FnDecl<'_>,
+    header: hir::FnHeader,
+    name: Option<Symbol>,
+    generics: &hir::Generics<'_>,
+    vis: &hir::Visibility<'_>,
+    arg_names: &[Ident],
+    body_id: Option<hir::BodyId>,
+) -> String {
+    to_string(NO_ANN, |s| s.print_fn(decl, header, name, generics, vis, arg_names, body_id))
+}
+
+pub fn enum_def_to_string(
+    enum_definition: &hir::EnumDef<'_>,
+    generics: &hir::Generics<'_>,
+    name: Symbol,
+    span: rustc_span::Span,
+    visibility: &hir::Visibility<'_>,
+) -> String {
+    to_string(NO_ANN, |s| s.print_enum_def(enum_definition, generics, name, span, visibility))
+}
+
 impl<'a> State<'a> {
     pub fn cbox(&mut self, u: usize) {
         self.s.cbox(u);
@@ -385,7 +407,7 @@ impl<'a> State<'a> {
                     &f.param_names[..],
                 );
             }
-            hir::TyKind::Def(..) => {}
+            hir::TyKind::OpaqueDef(..) => self.s.word("/*impl Trait*/"),
             hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false),
             hir::TyKind::TraitObject(bounds, ref lifetime) => {
                 let mut first = true;
@@ -981,12 +1003,6 @@ impl<'a> State<'a> {
             hir::ImplItemKind::TyAlias(ref ty) => {
                 self.print_associated_type(ii.ident, &ii.generics, None, Some(ty));
             }
-            hir::ImplItemKind::OpaqueTy(bounds) => {
-                self.word_space("type");
-                self.print_ident(ii.ident);
-                self.print_bounds("= impl", bounds);
-                self.s.word(";");
-            }
         }
         self.ann.post(self, AnnNode::SubItem(ii.hir_id))
     }
@@ -1286,7 +1302,7 @@ impl<'a> State<'a> {
             hir::ExprKind::Call(ref func, ref args) => {
                 self.print_expr_call(&func, args);
             }
-            hir::ExprKind::MethodCall(ref segment, _, ref args) => {
+            hir::ExprKind::MethodCall(ref segment, _, ref args, _) => {
                 self.print_expr_method_call(segment, args);
             }
             hir::ExprKind::Binary(op, ref lhs, ref rhs) => {
@@ -2469,7 +2485,7 @@ fn contains_exterior_struct_lit(value: &hir::Expr<'_>) -> bool {
             contains_exterior_struct_lit(&x)
         }
 
-        hir::ExprKind::MethodCall(.., ref exprs) => {
+        hir::ExprKind::MethodCall(.., ref exprs, _) => {
             // `X { y: 1 }.bar(...)`
             contains_exterior_struct_lit(&exprs[0])
         }
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index 9bf992537df..2ee95174dff 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -336,7 +336,6 @@ impl DirtyCleanVisitor<'tcx> {
                 ImplItemKind::Fn(..) => ("Node::ImplItem", LABELS_FN_IN_IMPL),
                 ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_IN_IMPL),
                 ImplItemKind::TyAlias(..) => ("NodeImplType", LABELS_CONST_IN_IMPL),
-                ImplItemKind::OpaqueTy(..) => ("NodeImplType", LABELS_CONST_IN_IMPL),
             },
             _ => self.tcx.sess.span_fatal(
                 attr.span,
diff --git a/src/librustc_infer/infer/canonical/query_response.rs b/src/librustc_infer/infer/canonical/query_response.rs
index ab2393918c3..8af526e3ad3 100644
--- a/src/librustc_infer/infer/canonical/query_response.rs
+++ b/src/librustc_infer/infer/canonical/query_response.rs
@@ -56,7 +56,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     ) -> Fallible<CanonicalizedQueryResponse<'tcx, T>>
     where
         T: Debug + TypeFoldable<'tcx>,
-        Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable,
+        Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
     {
         let query_response = self.make_query_response(inference_vars, answer, fulfill_cx)?;
         let canonical_result = self.canonicalize_response(&query_response);
diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs
index a59a91e3005..12f7a9c0ca5 100644
--- a/src/librustc_infer/infer/error_reporting/mod.rs
+++ b/src/librustc_infer/infer/error_reporting/mod.rs
@@ -224,9 +224,7 @@ fn trait_item_scope_tag(item: &hir::TraitItem<'_>) -> &'static str {
 fn impl_item_scope_tag(item: &hir::ImplItem<'_>) -> &'static str {
     match item.kind {
         hir::ImplItemKind::Fn(..) => "method body",
-        hir::ImplItemKind::Const(..)
-        | hir::ImplItemKind::OpaqueTy(..)
-        | hir::ImplItemKind::TyAlias(..) => "associated item",
+        hir::ImplItemKind::Const(..) | hir::ImplItemKind::TyAlias(..) => "associated item",
     }
 }
 
diff --git a/src/librustc_infer/infer/error_reporting/need_type_info.rs b/src/librustc_infer/infer/error_reporting/need_type_info.rs
index dfc7177921d..1361d5bede6 100644
--- a/src/librustc_infer/infer/error_reporting/need_type_info.rs
+++ b/src/librustc_infer/infer/error_reporting/need_type_info.rs
@@ -107,7 +107,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
     }
 
     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
-        if let ExprKind::MethodCall(_, call_span, exprs) = expr.kind {
+        if let ExprKind::MethodCall(_, call_span, exprs, _) = expr.kind {
             if call_span == self.target_span
                 && Some(self.target)
                     == self.infcx.in_progress_tables.and_then(|tables| {
@@ -294,7 +294,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             // 3 |     let _ = x.sum() as f64;
             //   |               ^^^ cannot infer type for `S`
             span
-        } else if let Some(ExprKind::MethodCall(_, call_span, _)) =
+        } else if let Some(ExprKind::MethodCall(_, call_span, _, _)) =
             local_visitor.found_method_call.map(|e| &e.kind)
         {
             // Point at the call instead of the whole expression:
@@ -455,7 +455,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             let msg = if let Some(simple_ident) = pattern.simple_ident() {
                 match pattern.span.desugaring_kind() {
                     None => format!("consider giving `{}` {}", simple_ident, suffix),
-                    Some(DesugaringKind::ForLoop) => {
+                    Some(DesugaringKind::ForLoop(_)) => {
                         "the element type for this iterator is not specified".to_string()
                     }
                     _ => format!("this needs {}", suffix),
@@ -550,7 +550,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         let error_code = error_code.into();
         let mut err = self.tcx.sess.struct_span_err_with_code(
             local_visitor.target_span,
-            &format!("type annotations needed"),
+            "type annotations needed",
             error_code,
         );
 
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs
index acaf4746992..a56401ebb90 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs
@@ -84,7 +84,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 rustc_hir::intravisit::walk_ty(&mut v, ty);
 
                 debug!("try_report_named_anon_conflict: ret ty {:?}", ty);
-                if sub == &ty::ReStatic && (matches!(ty.kind, TyKind::Def(_, _)) || v.0.len() == 1)
+                if sub == &ty::ReStatic
+                    && (matches!(ty.kind, TyKind::OpaqueDef(_, _)) || v.0.len() == 1)
                 {
                     debug!("try_report_named_anon_conflict: impl Trait + 'static");
                     // This is an `impl Trait` or `dyn Trait` return that evaluates de need of
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs
index 5f14f799fc7..45aee2b3965 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs
@@ -77,8 +77,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             }
             _ => {}
         }
-        let mut type_param_span: MultiSpan =
-            visitor.types.iter().cloned().collect::<Vec<_>>().into();
+        let mut type_param_span: MultiSpan = visitor.types.to_vec().into();
         for &span in &visitor.types {
             type_param_span.push_span_label(
                 span,
diff --git a/src/librustc_interface/callbacks.rs b/src/librustc_interface/callbacks.rs
index 913c67d045e..7fa1a3eb0f5 100644
--- a/src/librustc_interface/callbacks.rs
+++ b/src/librustc_interface/callbacks.rs
@@ -18,7 +18,7 @@ use std::fmt;
 fn span_debug(span: rustc_span::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     tls::with_opt(|tcx| {
         if let Some(tcx) = tcx {
-            write!(f, "{}", tcx.sess.source_map().span_to_string(span))
+            rustc_span::debug_with_source_map(span, f, tcx.sess.source_map())
         } else {
             rustc_span::default_span_debug(span, f)
         }
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 9a60e74d94d..1ed9bc3f1f5 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -307,16 +307,21 @@ fn configure_and_expand_inner<'a>(
             ecx.check_unused_macros();
         });
 
-        let mut missing_fragment_specifiers: Vec<_> =
-            ecx.parse_sess.missing_fragment_specifiers.borrow().iter().cloned().collect();
-        missing_fragment_specifiers.sort();
+        let mut missing_fragment_specifiers: Vec<_> = ecx
+            .parse_sess
+            .missing_fragment_specifiers
+            .borrow()
+            .iter()
+            .map(|(span, node_id)| (*span, *node_id))
+            .collect();
+        missing_fragment_specifiers.sort_unstable_by_key(|(span, _)| *span);
 
         let recursion_limit_hit = ecx.reduced_recursion_limit.is_some();
 
-        for span in missing_fragment_specifiers {
+        for (span, node_id) in missing_fragment_specifiers {
             let lint = lint::builtin::MISSING_FRAGMENT_SPECIFIER;
             let msg = "missing fragment specifier";
-            resolver.lint_buffer().buffer_lint(lint, ast::CRATE_NODE_ID, span, msg);
+            resolver.lint_buffer().buffer_lint(lint, node_id, span, msg);
         }
         if cfg!(windows) {
             env::set_var("PATH", &old_path);
@@ -842,7 +847,11 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
 
     sess.time("MIR_effect_checking", || {
         for def_id in tcx.body_owners() {
-            mir::transform::check_unsafety::check_unsafety(tcx, def_id)
+            mir::transform::check_unsafety::check_unsafety(tcx, def_id);
+
+            if tcx.hir().body_const_context(def_id).is_some() {
+                tcx.ensure().mir_drops_elaborated_and_const_checked(def_id);
+            }
         }
     });
 
diff --git a/src/librustc_lexer/src/lib.rs b/src/librustc_lexer/src/lib.rs
index cf90c6d8386..200e7acf802 100644
--- a/src/librustc_lexer/src/lib.rs
+++ b/src/librustc_lexer/src/lib.rs
@@ -187,9 +187,9 @@ pub fn strip_shebang(input: &str) -> Option<usize> {
             // Ok, this is a shebang but if the next non-whitespace token is `[` or maybe
             // a doc comment (due to `TokenKind::(Line,Block)Comment` ambiguity at lexer level),
             // then it may be valid Rust code, so consider it Rust code.
-            let next_non_whitespace_token = tokenize(input_tail).map(|tok| tok.kind).filter(|tok|
+            let next_non_whitespace_token = tokenize(input_tail).map(|tok| tok.kind).find(|tok|
                 !matches!(tok, TokenKind::Whitespace | TokenKind::LineComment | TokenKind::BlockComment { .. })
-            ).next();
+            );
             if next_non_whitespace_token != Some(TokenKind::OpenBracket) {
                 // No other choice than to consider this a shebang.
                 return Some(2 + first_line_tail.len());
diff --git a/src/librustc_lexer/src/unescape.rs b/src/librustc_lexer/src/unescape.rs
index 2a9e1b7cbc3..697d25fdb58 100644
--- a/src/librustc_lexer/src/unescape.rs
+++ b/src/librustc_lexer/src/unescape.rs
@@ -335,7 +335,7 @@ where
 
 fn byte_from_char(c: char) -> u8 {
     let res = c as u32;
-    assert!(res <= u8::max_value() as u32, "guaranteed because of Mode::ByteStr");
+    assert!(res <= u8::MAX as u32, "guaranteed because of Mode::ByteStr");
     res as u8
 }
 
diff --git a/src/librustc_lint/array_into_iter.rs b/src/librustc_lint/array_into_iter.rs
index 3eb587c016a..5b282c42034 100644
--- a/src/librustc_lint/array_into_iter.rs
+++ b/src/librustc_lint/array_into_iter.rs
@@ -24,7 +24,7 @@ declare_lint_pass!(
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIntoIter {
     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'tcx>) {
         // We only care about method call expressions.
-        if let hir::ExprKind::MethodCall(call, span, args) = &expr.kind {
+        if let hir::ExprKind::MethodCall(call, span, args, _) = &expr.kind {
             if call.ident.name != sym::into_iter {
                 return;
             }
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index e17e8b7b964..efe60ce1b88 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -1102,6 +1102,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds {
             hir::ItemKind::TyAlias(ref ty, ref generics) => (&*ty, generics),
             _ => return,
         };
+        if let hir::TyKind::OpaqueDef(..) = ty.kind {
+            // Bounds are respected for `type X = impl Trait`
+            return;
+        }
         let mut suggested_changing_assoc_types = false;
         // There must not be a where clause
         if !type_alias_generics.where_clause.predicates.is_empty() {
@@ -1899,7 +1903,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue {
                         }
                     }
                 }
-            } else if let hir::ExprKind::MethodCall(_, _, ref args) = expr.kind {
+            } else if let hir::ExprKind::MethodCall(_, _, ref args, _) = expr.kind {
                 // Find problematic calls to `MaybeUninit::assume_init`.
                 let def_id = cx.tables.type_dependent_def_id(expr.hir_id)?;
                 if cx.tcx.is_diagnostic_item(sym::assume_init, def_id) {
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 703c2a7a443..a8ecfdd0f3d 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -6,7 +6,6 @@ use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
 use rustc_hir::{is_range_literal, ExprKind, Node};
 use rustc_index::vec::Idx;
 use rustc_middle::mir::interpret::{sign_extend, truncate};
@@ -108,23 +107,23 @@ fn lint_overflowing_range_endpoint<'a, 'tcx>(
 // warnings are consistent between 32- and 64-bit platforms.
 fn int_ty_range(int_ty: ast::IntTy) -> (i128, i128) {
     match int_ty {
-        ast::IntTy::Isize => (i64::min_value() as i128, i64::max_value() as i128),
-        ast::IntTy::I8 => (i8::min_value() as i64 as i128, i8::max_value() as i128),
-        ast::IntTy::I16 => (i16::min_value() as i64 as i128, i16::max_value() as i128),
-        ast::IntTy::I32 => (i32::min_value() as i64 as i128, i32::max_value() as i128),
-        ast::IntTy::I64 => (i64::min_value() as i128, i64::max_value() as i128),
-        ast::IntTy::I128 => (i128::min_value() as i128, i128::max_value()),
+        ast::IntTy::Isize => (i64::MIN as i128, i64::MAX as i128),
+        ast::IntTy::I8 => (i8::MIN as i64 as i128, i8::MAX as i128),
+        ast::IntTy::I16 => (i16::MIN as i64 as i128, i16::MAX as i128),
+        ast::IntTy::I32 => (i32::MIN as i64 as i128, i32::MAX as i128),
+        ast::IntTy::I64 => (i64::MIN as i128, i64::MAX as i128),
+        ast::IntTy::I128 => (i128::MIN as i128, i128::MAX),
     }
 }
 
 fn uint_ty_range(uint_ty: ast::UintTy) -> (u128, u128) {
     match uint_ty {
-        ast::UintTy::Usize => (u64::min_value() as u128, u64::max_value() as u128),
-        ast::UintTy::U8 => (u8::min_value() as u128, u8::max_value() as u128),
-        ast::UintTy::U16 => (u16::min_value() as u128, u16::max_value() as u128),
-        ast::UintTy::U32 => (u32::min_value() as u128, u32::max_value() as u128),
-        ast::UintTy::U64 => (u64::min_value() as u128, u64::max_value() as u128),
-        ast::UintTy::U128 => (u128::min_value(), u128::max_value()),
+        ast::UintTy::Usize => (u64::MIN as u128, u64::MAX as u128),
+        ast::UintTy::U8 => (u8::MIN as u128, u8::MAX as u128),
+        ast::UintTy::U16 => (u16::MIN as u128, u16::MAX as u128),
+        ast::UintTy::U32 => (u32::MIN as u128, u32::MAX as u128),
+        ast::UintTy::U64 => (u64::MIN as u128, u64::MAX as u128),
+        ast::UintTy::U128 => (u128::MIN, u128::MAX),
     }
 }
 
@@ -511,10 +510,6 @@ enum FfiResult<'tcx> {
     FfiUnsafe { ty: Ty<'tcx>, reason: &'static str, help: Option<&'static str> },
 }
 
-fn is_zst<'tcx>(tcx: TyCtxt<'tcx>, did: DefId, ty: Ty<'tcx>) -> bool {
-    tcx.layout_of(tcx.param_env(did).and(ty)).map(|layout| layout.is_zst()).unwrap_or(false)
-}
-
 fn ty_is_known_nonnull<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
     match ty.kind {
         ty::FnPtr(_) => true,
@@ -523,7 +518,7 @@ fn ty_is_known_nonnull<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
             for field in field_def.all_fields() {
                 let field_ty =
                     tcx.normalize_erasing_regions(ParamEnv::reveal_all(), field.ty(tcx, substs));
-                if is_zst(tcx, field.did, field_ty) {
+                if field_ty.is_zst(tcx, field.did) {
                     continue;
                 }
 
@@ -653,32 +648,43 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                             };
                         }
 
-                        // We can't completely trust repr(C) and repr(transparent) markings;
-                        // make sure the fields are actually safe.
-                        let mut all_phantom = true;
-                        for field in &def.non_enum_variant().fields {
-                            let field_ty = cx.normalize_erasing_regions(
-                                ParamEnv::reveal_all(),
-                                field.ty(cx, substs),
-                            );
-                            // repr(transparent) types are allowed to have arbitrary ZSTs, not just
-                            // PhantomData -- skip checking all ZST fields
-                            if def.repr.transparent() && is_zst(cx, field.did, field_ty) {
-                                continue;
+                        if def.repr.transparent() {
+                            // Can assume that only one field is not a ZST, so only check
+                            // that field's type for FFI-safety.
+                            if let Some(field) =
+                                def.transparent_newtype_field(cx, self.cx.param_env)
+                            {
+                                let field_ty = cx.normalize_erasing_regions(
+                                    self.cx.param_env,
+                                    field.ty(cx, substs),
+                                );
+                                self.check_type_for_ffi(cache, field_ty)
+                            } else {
+                                FfiSafe
                             }
-                            let r = self.check_type_for_ffi(cache, field_ty);
-                            match r {
-                                FfiSafe => {
-                                    all_phantom = false;
-                                }
-                                FfiPhantom(..) => {}
-                                FfiUnsafe { .. } => {
-                                    return r;
+                        } else {
+                            // We can't completely trust repr(C) markings; make sure the fields are
+                            // actually safe.
+                            let mut all_phantom = true;
+                            for field in &def.non_enum_variant().fields {
+                                let field_ty = cx.normalize_erasing_regions(
+                                    self.cx.param_env,
+                                    field.ty(cx, substs),
+                                );
+                                let r = self.check_type_for_ffi(cache, field_ty);
+                                match r {
+                                    FfiSafe => {
+                                        all_phantom = false;
+                                    }
+                                    FfiPhantom(..) => {}
+                                    FfiUnsafe { .. } => {
+                                        return r;
+                                    }
                                 }
                             }
-                        }
 
-                        if all_phantom { FfiPhantom(ty) } else { FfiSafe }
+                            if all_phantom { FfiPhantom(ty) } else { FfiSafe }
+                        }
                     }
                     AdtKind::Union => {
                         if !def.repr.c() && !def.repr.transparent() {
@@ -708,7 +714,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                             );
                             // repr(transparent) types are allowed to have arbitrary ZSTs, not just
                             // PhantomData -- skip checking all ZST fields.
-                            if def.repr.transparent() && is_zst(cx, field.did, field_ty) {
+                            if def.repr.transparent() && field_ty.is_zst(cx, field.did) {
                                 continue;
                             }
                             let r = self.check_type_for_ffi(cache, field_ty);
@@ -774,7 +780,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                                 );
                                 // repr(transparent) types are allowed to have arbitrary ZSTs, not
                                 // just PhantomData -- skip checking all ZST fields.
-                                if def.repr.transparent() && is_zst(cx, field.did, field_ty) {
+                                if def.repr.transparent() && field_ty.is_zst(cx, field.did) {
                                     continue;
                                 }
                                 let r = self.check_type_for_ffi(cache, field_ty);
@@ -946,7 +952,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         }
     }
 
-    fn check_type_for_ffi_and_report_errors(&mut self, sp: Span, ty: Ty<'tcx>, is_static: bool) {
+    fn check_type_for_ffi_and_report_errors(
+        &mut self,
+        sp: Span,
+        ty: Ty<'tcx>,
+        is_static: bool,
+        is_return_type: bool,
+    ) {
         // We have to check for opaque types before `normalize_erasing_regions`,
         // which will replace opaque types with their underlying concrete type.
         if self.check_for_opaque_ty(sp, ty) {
@@ -957,19 +969,29 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         // it is only OK to use this function because extern fns cannot have
         // any generic types right now:
         let ty = self.cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
-        // C doesn't really support passing arrays by value.
-        // The only way to pass an array by value is through a struct.
-        // So we first test that the top level isn't an array,
-        // and then recursively check the types inside.
+
+        // C doesn't really support passing arrays by value - the only way to pass an array by value
+        // is through a struct. So, first test that the top level isn't an array, and then
+        // recursively check the types inside.
         if !is_static && self.check_for_array_ty(sp, ty) {
             return;
         }
 
+        // Don't report FFI errors for unit return types. This check exists here, and not in
+        // `check_foreign_fn` (where it would make more sense) so that normalization has definitely
+        // happened.
+        if is_return_type && ty.is_unit() {
+            return;
+        }
+
         match self.check_type_for_ffi(&mut FxHashSet::default(), ty) {
             FfiResult::FfiSafe => {}
             FfiResult::FfiPhantom(ty) => {
                 self.emit_ffi_unsafe_type_lint(ty, sp, "composed only of `PhantomData`", None);
             }
+            // If `ty` is a `repr(transparent)` newtype, and the non-zero-sized type is a generic
+            // argument, which after substitution, is `()`, then this branch can be hit.
+            FfiResult::FfiUnsafe { ty, .. } if is_return_type && ty.is_unit() => return,
             FfiResult::FfiUnsafe { ty, reason, help } => {
                 self.emit_ffi_unsafe_type_lint(ty, sp, reason, help);
             }
@@ -982,21 +1004,19 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         let sig = self.cx.tcx.erase_late_bound_regions(&sig);
 
         for (input_ty, input_hir) in sig.inputs().iter().zip(decl.inputs) {
-            self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty, false);
+            self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty, false, false);
         }
 
         if let hir::FnRetTy::Return(ref ret_hir) = decl.output {
             let ret_ty = sig.output();
-            if !ret_ty.is_unit() {
-                self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty, false);
-            }
+            self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty, false, true);
         }
     }
 
     fn check_foreign_static(&mut self, id: hir::HirId, span: Span) {
         let def_id = self.cx.tcx.hir().local_def_id(id);
         let ty = self.cx.tcx.type_of(def_id);
-        self.check_type_for_ffi_and_report_errors(span, ty, true);
+        self.check_type_for_ffi_and_report_errors(span, ty, true, false);
     }
 }
 
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index dea82934313..8196b37391b 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -526,7 +526,7 @@ trait UnusedDelimLint {
                 let (args_to_check, ctx) = match *call_or_other {
                     Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg),
                     // first "argument" is self (which sometimes needs delims)
-                    MethodCall(_, ref args) => (&args[1..], UnusedDelimsCtx::MethodArg),
+                    MethodCall(_, ref args, _) => (&args[1..], UnusedDelimsCtx::MethodArg),
                     // actual catch-all arm
                     _ => {
                         return;
diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs
index e97fa4345fe..ada48bc147e 100644
--- a/src/librustc_llvm/build.rs
+++ b/src/librustc_llvm/build.rs
@@ -78,6 +78,7 @@ fn main() {
         "arm",
         "aarch64",
         "amdgpu",
+        "avr",
         "mips",
         "powerpc",
         "systemz",
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index eca1808de3f..79e1a6cc5dc 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -77,6 +77,14 @@ pub fn initialize_available_targets() {
         LLVMInitializeAMDGPUAsmParser
     );
     init_target!(
+        llvm_component = "avr",
+        LLVMInitializeAVRTargetInfo,
+        LLVMInitializeAVRTarget,
+        LLVMInitializeAVRTargetMC,
+        LLVMInitializeAVRAsmPrinter,
+        LLVMInitializeAVRAsmParser
+    );
+    init_target!(
         llvm_component = "mips",
         LLVMInitializeMipsTargetInfo,
         LLVMInitializeMipsTarget,
diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs
index 41a49a38a19..c17d5311e8f 100644
--- a/src/librustc_macros/src/query.rs
+++ b/src/librustc_macros/src/query.rs
@@ -433,7 +433,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
 
                 try_load_from_on_disk_cache_stream.extend(quote! {
                     ::rustc_middle::dep_graph::DepKind::#name => {
-                        if <#arg as DepNodeParams<TyCtxt<'_>>>::CAN_RECONSTRUCT_QUERY_KEY {
+                        if <#arg as DepNodeParams<TyCtxt<'_>>>::can_reconstruct_query_key() {
                             debug_assert!($tcx.dep_graph
                                             .node_color($dep_node)
                                             .map(|c| c.is_green())
@@ -490,7 +490,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
             // Add a match arm to force the query given the dep node
             dep_node_force_stream.extend(quote! {
                 ::rustc_middle::dep_graph::DepKind::#name => {
-                    if <#arg as DepNodeParams<TyCtxt<'_>>>::CAN_RECONSTRUCT_QUERY_KEY {
+                    if <#arg as DepNodeParams<TyCtxt<'_>>>::can_reconstruct_query_key() {
                         if let Some(key) = <#arg as DepNodeParams<TyCtxt<'_>>>::recover($tcx, $dep_node) {
                             force_query::<crate::ty::query::queries::#name<'_>, _>(
                                 $tcx,
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 7e902f0ade2..b8ebcd6c8a8 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -934,7 +934,7 @@ impl<'a> CrateLoader<'a> {
                 src: ExternCrateSource::Path,
                 span,
                 // to have the least priority in `update_extern_crate`
-                path_len: usize::max_value(),
+                path_len: usize::MAX,
                 dependency_of: LOCAL_CRATE,
             },
         );
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index 2a2169880a5..76e39a476c6 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -7,7 +7,7 @@
 #![feature(nll)]
 #![feature(or_patterns)]
 #![feature(proc_macro_internals)]
-#![feature(specialization)] // FIXME: min_specialization ICEs
+#![feature(min_specialization)]
 #![feature(stmt_expr_attributes)]
 #![recursion_limit = "256"]
 
diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs
index f5a9dceb782..0335aa8358c 100644
--- a/src/librustc_metadata/rmeta/decoder.rs
+++ b/src/librustc_metadata/rmeta/decoder.rs
@@ -30,7 +30,7 @@ use rustc_middle::mir::{self, interpret, Body, Promoted};
 use rustc_middle::ty::codec::TyDecoder;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::util::common::record_time;
-use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder};
+use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder, UseSpecializedDecodable};
 use rustc_session::Session;
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{sym, Ident, Symbol};
@@ -218,7 +218,7 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, TyCtxt<'tcx>) {
     }
 }
 
-impl<'a, 'tcx, T: Decodable> Lazy<T> {
+impl<'a, 'tcx, T: Decodable> Lazy<T, ()> {
     fn decode<M: Metadata<'a, 'tcx>>(self, metadata: M) -> T {
         let mut dcx = metadata.decoder(self.position.get());
         dcx.lazy_state = LazyState::NodeStart(self.position);
@@ -226,7 +226,7 @@ impl<'a, 'tcx, T: Decodable> Lazy<T> {
     }
 }
 
-impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T]> {
+impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T], usize> {
     fn decode<M: Metadata<'a, 'tcx>>(
         self,
         metadata: M,
@@ -321,20 +321,20 @@ impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx, T> SpecializedDecoder<Lazy<T>> for DecodeContext<'a, 'tcx> {
+impl<'a, 'tcx, T> SpecializedDecoder<Lazy<T, ()>> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<Lazy<T>, Self::Error> {
         self.read_lazy_with_meta(())
     }
 }
 
-impl<'a, 'tcx, T> SpecializedDecoder<Lazy<[T]>> for DecodeContext<'a, 'tcx> {
+impl<'a, 'tcx, T> SpecializedDecoder<Lazy<[T], usize>> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<Lazy<[T]>, Self::Error> {
         let len = self.read_usize()?;
         if len == 0 { Ok(Lazy::empty()) } else { self.read_lazy_with_meta(len) }
     }
 }
 
-impl<'a, 'tcx, I: Idx, T> SpecializedDecoder<Lazy<Table<I, T>>> for DecodeContext<'a, 'tcx>
+impl<'a, 'tcx, I: Idx, T> SpecializedDecoder<Lazy<Table<I, T>, usize>> for DecodeContext<'a, 'tcx>
 where
     Option<T>: FixedSizeEncoding,
 {
@@ -515,8 +515,9 @@ impl<'a, 'tcx> SpecializedDecoder<Fingerprint> for DecodeContext<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx, T: Decodable> SpecializedDecoder<mir::ClearCrossCrate<T>>
-    for DecodeContext<'a, 'tcx>
+impl<'a, 'tcx, T> SpecializedDecoder<mir::ClearCrossCrate<T>> for DecodeContext<'a, 'tcx>
+where
+    mir::ClearCrossCrate<T>: UseSpecializedDecodable,
 {
     #[inline]
     fn specialized_decode(&mut self) -> Result<mir::ClearCrossCrate<T>, Self::Error> {
@@ -579,7 +580,6 @@ impl EntryKind {
             EntryKind::ConstParam => DefKind::ConstParam,
             EntryKind::OpaqueTy => DefKind::OpaqueTy,
             EntryKind::AssocType(_) => DefKind::AssocTy,
-            EntryKind::AssocOpaqueTy(_) => DefKind::AssocOpaqueTy,
             EntryKind::Mod(_) => DefKind::Mod,
             EntryKind::Variant(_) => DefKind::Variant,
             EntryKind::Trait(_) => DefKind::Trait,
@@ -1145,7 +1145,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                 (ty::AssocKind::Fn, data.container, data.has_self)
             }
             EntryKind::AssocType(container) => (ty::AssocKind::Type, container, false),
-            EntryKind::AssocOpaqueTy(container) => (ty::AssocKind::OpaqueTy, container, false),
             _ => bug!("cannot get associated-item of `{:?}`", def_key),
         };
 
@@ -1317,13 +1316,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
-    fn get_fn_param_names(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> &'tcx [Symbol] {
+    fn get_fn_param_names(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> &'tcx [Ident] {
         let param_names = match self.kind(id) {
             EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).param_names,
             EntryKind::AssocFn(data) => data.decode(self).fn_data.param_names,
             _ => Lazy::empty(),
         };
-        tcx.arena.alloc_from_iter(param_names.decode(self))
+        tcx.arena.alloc_from_iter(param_names.decode((self, tcx)))
     }
 
     fn exported_symbols(
diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs
index 64ccd46a744..d797e6d4a34 100644
--- a/src/librustc_metadata/rmeta/encoder.rs
+++ b/src/librustc_metadata/rmeta/encoder.rs
@@ -27,10 +27,10 @@ use rustc_middle::mir::{self, interpret};
 use rustc_middle::traits::specialization_graph;
 use rustc_middle::ty::codec::{self as ty_codec, TyEncoder};
 use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
-use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder};
+use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder, UseSpecializedEncodable};
 use rustc_session::config::CrateType;
 use rustc_span::source_map::Spanned;
-use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::{self, ExternalSource, FileName, SourceFile, Span};
 use rustc_target::abi::VariantIdx;
 use std::hash::Hash;
@@ -93,13 +93,13 @@ impl<'tcx> Encoder for EncodeContext<'tcx> {
     }
 }
 
-impl<'tcx, T> SpecializedEncoder<Lazy<T>> for EncodeContext<'tcx> {
+impl<'tcx, T> SpecializedEncoder<Lazy<T, ()>> for EncodeContext<'tcx> {
     fn specialized_encode(&mut self, lazy: &Lazy<T>) -> Result<(), Self::Error> {
         self.emit_lazy_distance(*lazy)
     }
 }
 
-impl<'tcx, T> SpecializedEncoder<Lazy<[T]>> for EncodeContext<'tcx> {
+impl<'tcx, T> SpecializedEncoder<Lazy<[T], usize>> for EncodeContext<'tcx> {
     fn specialized_encode(&mut self, lazy: &Lazy<[T]>) -> Result<(), Self::Error> {
         self.emit_usize(lazy.meta)?;
         if lazy.meta == 0 {
@@ -109,7 +109,7 @@ impl<'tcx, T> SpecializedEncoder<Lazy<[T]>> for EncodeContext<'tcx> {
     }
 }
 
-impl<'tcx, I: Idx, T> SpecializedEncoder<Lazy<Table<I, T>>> for EncodeContext<'tcx>
+impl<'tcx, I: Idx, T> SpecializedEncoder<Lazy<Table<I, T>, usize>> for EncodeContext<'tcx>
 where
     Option<T>: FixedSizeEncoding,
 {
@@ -228,8 +228,13 @@ impl<'tcx> SpecializedEncoder<LocalDefId> for EncodeContext<'tcx> {
     }
 }
 
-impl<'tcx> SpecializedEncoder<Ty<'tcx>> for EncodeContext<'tcx> {
-    fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
+impl<'a, 'b, 'tcx> SpecializedEncoder<&'a ty::TyS<'b>> for EncodeContext<'tcx>
+where
+    &'a ty::TyS<'b>: UseSpecializedEncodable,
+{
+    fn specialized_encode(&mut self, ty: &&'a ty::TyS<'b>) -> Result<(), Self::Error> {
+        debug_assert!(self.tcx.lift(ty).is_some());
+        let ty = unsafe { std::mem::transmute::<&&'a ty::TyS<'b>, &&'tcx ty::TyS<'tcx>>(ty) };
         ty_codec::encode_with_shorthand(self, ty, |ecx| &mut ecx.type_shorthands)
     }
 }
@@ -251,12 +256,19 @@ impl<'tcx> SpecializedEncoder<interpret::AllocId> for EncodeContext<'tcx> {
     }
 }
 
-impl<'tcx> SpecializedEncoder<&'tcx [(ty::Predicate<'tcx>, Span)]> for EncodeContext<'tcx> {
+impl<'a, 'b, 'tcx> SpecializedEncoder<&'a [(ty::Predicate<'b>, Span)]> for EncodeContext<'tcx> {
     fn specialized_encode(
         &mut self,
-        predicates: &&'tcx [(ty::Predicate<'tcx>, Span)],
+        predicates: &&'a [(ty::Predicate<'b>, Span)],
     ) -> Result<(), Self::Error> {
-        ty_codec::encode_spanned_predicates(self, predicates, |ecx| &mut ecx.predicate_shorthands)
+        debug_assert!(self.tcx.lift(*predicates).is_some());
+        let predicates = unsafe {
+            std::mem::transmute::<
+                &&'a [(ty::Predicate<'b>, Span)],
+                &&'tcx [(ty::Predicate<'tcx>, Span)],
+            >(predicates)
+        };
+        ty_codec::encode_spanned_predicates(self, &predicates, |ecx| &mut ecx.predicate_shorthands)
     }
 }
 
@@ -266,7 +278,10 @@ impl<'tcx> SpecializedEncoder<Fingerprint> for EncodeContext<'tcx> {
     }
 }
 
-impl<'tcx, T: Encodable> SpecializedEncoder<mir::ClearCrossCrate<T>> for EncodeContext<'tcx> {
+impl<'tcx, T> SpecializedEncoder<mir::ClearCrossCrate<T>> for EncodeContext<'tcx>
+where
+    mir::ClearCrossCrate<T>: UseSpecializedEncodable,
+{
     fn specialized_encode(&mut self, _: &mir::ClearCrossCrate<T>) -> Result<(), Self::Error> {
         Ok(())
     }
@@ -874,7 +889,6 @@ impl EncodeContext<'tcx> {
                 }))
             }
             ty::AssocKind::Type => EntryKind::AssocType(container),
-            ty::AssocKind::OpaqueTy => span_bug!(ast_item.span, "opaque type in trait"),
         });
         record!(self.tables.visibility[def_id] <- trait_item.vis);
         record!(self.tables.span[def_id] <- ast_item.span);
@@ -892,7 +906,6 @@ impl EncodeContext<'tcx> {
                     self.encode_item_type(def_id);
                 }
             }
-            ty::AssocKind::OpaqueTy => unreachable!(),
         }
         if trait_item.kind == ty::AssocKind::Fn {
             record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
@@ -957,7 +970,6 @@ impl EncodeContext<'tcx> {
                     has_self: impl_item.fn_has_self_parameter,
                 }))
             }
-            ty::AssocKind::OpaqueTy => EntryKind::AssocOpaqueTy(container),
             ty::AssocKind::Type => EntryKind::AssocType(container)
         });
         record!(self.tables.visibility[def_id] <- impl_item.vis);
@@ -989,7 +1001,7 @@ impl EncodeContext<'tcx> {
                 let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
                 needs_inline || is_const_fn || always_encode_mir
             }
-            hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(..) => false,
+            hir::ImplItemKind::TyAlias(..) => false,
         };
         if mir {
             self.encode_optimized_mir(def_id.expect_local());
@@ -997,18 +1009,12 @@ impl EncodeContext<'tcx> {
         }
     }
 
-    fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId) -> Lazy<[Symbol]> {
-        self.tcx.dep_graph.with_ignore(|| {
-            let body = self.tcx.hir().body(body_id);
-            self.lazy(body.params.iter().map(|arg| match arg.pat.kind {
-                hir::PatKind::Binding(_, _, ident, _) => ident.name,
-                _ => kw::Invalid,
-            }))
-        })
+    fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId) -> Lazy<[Ident]> {
+        self.tcx.dep_graph.with_ignore(|| self.lazy(self.tcx.hir().body_param_names(body_id)))
     }
 
-    fn encode_fn_param_names(&mut self, param_names: &[Ident]) -> Lazy<[Symbol]> {
-        self.lazy(param_names.iter().map(|ident| ident.name))
+    fn encode_fn_param_names(&mut self, param_names: &[Ident]) -> Lazy<[Ident]> {
+        self.lazy(param_names.iter())
     }
 
     fn encode_optimized_mir(&mut self, def_id: LocalDefId) {
@@ -1786,7 +1792,7 @@ impl<'tcx, 'v> ParItemLikeVisitor<'v> for PrefetchVisitor<'tcx> {
                     self.prefetch_mir(def_id)
                 }
             }
-            hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(..) => (),
+            hir::ImplItemKind::TyAlias(..) => (),
         }
     }
 }
diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs
index 89d525eb80b..ec80a2b6171 100644
--- a/src/librustc_metadata/rmeta/mod.rs
+++ b/src/librustc_metadata/rmeta/mod.rs
@@ -19,7 +19,7 @@ use rustc_serialize::opaque::Encoder;
 use rustc_session::config::SymbolManglingVersion;
 use rustc_session::CrateDisambiguator;
 use rustc_span::edition::Edition;
-use rustc_span::symbol::Symbol;
+use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::{self, Span};
 use rustc_target::spec::{PanicStrategy, TargetTriple};
 
@@ -308,7 +308,6 @@ enum EntryKind {
     Impl(Lazy<ImplData>),
     AssocFn(Lazy<AssocFnData>),
     AssocType(AssocContainer),
-    AssocOpaqueTy(AssocContainer),
     AssocConst(AssocContainer, mir::ConstQualifs, Lazy<RenderedConst>),
     TraitAlias,
 }
@@ -327,7 +326,7 @@ struct ModData {
 struct FnData {
     asyncness: hir::IsAsync,
     constness: hir::Constness,
-    param_names: Lazy<[Symbol]>,
+    param_names: Lazy<[Ident]>,
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
diff --git a/src/librustc_middle/arena.rs b/src/librustc_middle/arena.rs
index 75228350c6c..f861d63aba0 100644
--- a/src/librustc_middle/arena.rs
+++ b/src/librustc_middle/arena.rs
@@ -11,79 +11,109 @@
 macro_rules! arena_types {
     ($macro:path, $args:tt, $tcx:lifetime) => (
         $macro!($args, [
-            [] layouts: rustc_target::abi::Layout,
+            [] layouts: rustc_target::abi::Layout, rustc_target::abi::Layout;
             // AdtDef are interned and compared by address
-            [] adt_def: rustc_middle::ty::AdtDef,
-            [decode] tables: rustc_middle::ty::TypeckTables<$tcx>,
-            [] const_allocs: rustc_middle::mir::interpret::Allocation,
+            [] adt_def: rustc_middle::ty::AdtDef, rustc_middle::ty::AdtDef;
+            [decode] tables: rustc_middle::ty::TypeckTables<$tcx>, rustc_middle::ty::TypeckTables<'_x>;
+            [] const_allocs: rustc_middle::mir::interpret::Allocation, rustc_middle::mir::interpret::Allocation;
             // Required for the incremental on-disk cache
-            [few, decode] mir_keys: rustc_hir::def_id::DefIdSet,
-            [] region_scope_tree: rustc_middle::middle::region::ScopeTree,
+            [few, decode] mir_keys: rustc_hir::def_id::DefIdSet, rustc_hir::def_id::DefIdSet;
+            [] region_scope_tree: rustc_middle::middle::region::ScopeTree, rustc_middle::middle::region::ScopeTree;
             [] dropck_outlives:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx,
                         rustc_middle::traits::query::DropckOutlivesResult<'tcx>
                     >
                 >,
+                rustc_middle::infer::canonical::Canonical<'_x,
+                    rustc_middle::infer::canonical::QueryResponse<'_y,
+                        rustc_middle::traits::query::DropckOutlivesResult<'_z>
+                    >
+                >;
             [] normalize_projection_ty:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx,
                         rustc_middle::traits::query::NormalizationResult<'tcx>
                     >
                 >,
+                rustc_middle::infer::canonical::Canonical<'_x,
+                    rustc_middle::infer::canonical::QueryResponse<'_y,
+                        rustc_middle::traits::query::NormalizationResult<'_z>
+                    >
+                >;
             [] implied_outlives_bounds:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx,
                         Vec<rustc_middle::traits::query::OutlivesBound<'tcx>>
                     >
                 >,
+                rustc_middle::infer::canonical::Canonical<'_x,
+                    rustc_middle::infer::canonical::QueryResponse<'_y,
+                        Vec<rustc_middle::traits::query::OutlivesBound<'_z>>
+                    >
+                >;
             [] type_op_subtype:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx, ()>
                 >,
+                rustc_middle::infer::canonical::Canonical<'_x,
+                    rustc_middle::infer::canonical::QueryResponse<'_y, ()>
+                >;
             [] type_op_normalize_poly_fn_sig:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::PolyFnSig<'tcx>>
                 >,
+                rustc_middle::infer::canonical::Canonical<'_x,
+                    rustc_middle::infer::canonical::QueryResponse<'_y, rustc_middle::ty::PolyFnSig<'_z>>
+                >;
             [] type_op_normalize_fn_sig:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::FnSig<'tcx>>
                 >,
+                rustc_middle::infer::canonical::Canonical<'_x,
+                    rustc_middle::infer::canonical::QueryResponse<'_y, rustc_middle::ty::FnSig<'_z>>
+                >;
             [] type_op_normalize_predicate:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Predicate<'tcx>>
                 >,
+                rustc_middle::infer::canonical::Canonical<'_x,
+                    rustc_middle::infer::canonical::QueryResponse<'_y, rustc_middle::ty::Predicate<'_z>>
+                >;
             [] type_op_normalize_ty:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Ty<'tcx>>
                 >,
-            [few] all_traits: Vec<rustc_hir::def_id::DefId>,
-            [few] privacy_access_levels: rustc_middle::middle::privacy::AccessLevels,
-            [few] foreign_module: rustc_middle::middle::cstore::ForeignModule,
-            [few] foreign_modules: Vec<rustc_middle::middle::cstore::ForeignModule>,
-            [] upvars_mentioned: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>,
-            [] object_safety_violations: rustc_middle::traits::ObjectSafetyViolation,
-            [] codegen_unit: rustc_middle::mir::mono::CodegenUnit<$tcx>,
-            [] attribute: rustc_ast::ast::Attribute,
-            [] name_set: rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>,
-            [] hir_id_set: rustc_hir::HirIdSet,
+                rustc_middle::infer::canonical::Canonical<'_x,
+                    rustc_middle::infer::canonical::QueryResponse<'_y, &'_z rustc_middle::ty::TyS<'_w>>
+                >;
+            [few] all_traits: Vec<rustc_hir::def_id::DefId>, Vec<rustc_hir::def_id::DefId>;
+            [few] privacy_access_levels: rustc_middle::middle::privacy::AccessLevels, rustc_middle::middle::privacy::AccessLevels;
+            [few] foreign_module: rustc_middle::middle::cstore::ForeignModule, rustc_middle::middle::cstore::ForeignModule;
+            [few] foreign_modules: Vec<rustc_middle::middle::cstore::ForeignModule>, Vec<rustc_middle::middle::cstore::ForeignModule>;
+            [] upvars_mentioned: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>, rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>;
+            [] object_safety_violations: rustc_middle::traits::ObjectSafetyViolation, rustc_middle::traits::ObjectSafetyViolation;
+            [] codegen_unit: rustc_middle::mir::mono::CodegenUnit<$tcx>, rustc_middle::mir::mono::CodegenUnit<'_x>;
+            [] attribute: rustc_ast::ast::Attribute, rustc_ast::ast::Attribute;
+            [] name_set: rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>, rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>;
+            [] hir_id_set: rustc_hir::HirIdSet, rustc_hir::HirIdSet;
 
             // Interned types
-            [] tys: rustc_middle::ty::TyS<$tcx>,
+            [] tys: rustc_middle::ty::TyS<$tcx>, rustc_middle::ty::TyS<'_x>;
 
             // HIR query types
-            [few] indexed_hir: rustc_middle::hir::map::IndexedHir<$tcx>,
-            [few] hir_definitions: rustc_hir::definitions::Definitions,
-            [] hir_owner: rustc_middle::hir::Owner<$tcx>,
-            [] hir_owner_nodes: rustc_middle::hir::OwnerNodes<$tcx>,
+            [few] indexed_hir: rustc_middle::hir::map::IndexedHir<$tcx>, rustc_middle::hir::map::IndexedHir<'_x>;
+            [few] hir_definitions: rustc_hir::definitions::Definitions, rustc_hir::definitions::Definitions;
+            [] hir_owner: rustc_middle::hir::Owner<$tcx>, rustc_middle::hir::Owner<'_x>;
+            [] hir_owner_nodes: rustc_middle::hir::OwnerNodes<$tcx>, rustc_middle::hir::OwnerNodes<'_x>;
 
             // Note that this deliberately duplicates items in the `rustc_hir::arena`,
             // since we need to allocate this type on both the `rustc_hir` arena
             // (during lowering) and the `librustc_middle` arena (for decoding MIR)
-            [decode] asm_template: rustc_ast::ast::InlineAsmTemplatePiece,
+            [decode] asm_template: rustc_ast::ast::InlineAsmTemplatePiece, rustc_ast::ast::InlineAsmTemplatePiece;
 
             // This is used to decode the &'tcx [Span] for InlineAsm's line_spans.
-            [decode] span: rustc_span::Span,
+            [decode] span: rustc_span::Span, rustc_span::Span;
         ], $tcx);
     )
 }
diff --git a/src/librustc_middle/dep_graph/dep_node.rs b/src/librustc_middle/dep_graph/dep_node.rs
index 2c0524fa991..b14f17dee60 100644
--- a/src/librustc_middle/dep_graph/dep_node.rs
+++ b/src/librustc_middle/dep_graph/dep_node.rs
@@ -128,7 +128,7 @@ macro_rules! define_dep_nodes {
                             // tuple args
                             $({
                                 return <$tuple_arg_ty as DepNodeParams<TyCtxt<'_>>>
-                                    ::CAN_RECONSTRUCT_QUERY_KEY;
+                                    ::can_reconstruct_query_key();
                             })*
 
                             true
@@ -304,7 +304,10 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
 ]);
 
 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for DefId {
-    const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
+    #[inline]
+    fn can_reconstruct_query_key() -> bool {
+        true
+    }
 
     fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
         tcx.def_path_hash(*self).0
@@ -320,7 +323,10 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for DefId {
 }
 
 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalDefId {
-    const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
+    #[inline]
+    fn can_reconstruct_query_key() -> bool {
+        true
+    }
 
     fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
         self.to_def_id().to_fingerprint(tcx)
@@ -336,7 +342,10 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalDefId {
 }
 
 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum {
-    const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
+    #[inline]
+    fn can_reconstruct_query_key() -> bool {
+        true
+    }
 
     fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
         let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX };
@@ -353,7 +362,10 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum {
 }
 
 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) {
-    const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
+    #[inline]
+    fn can_reconstruct_query_key() -> bool {
+        false
+    }
 
     // We actually would not need to specialize the implementation of this
     // method but it's faster to combine the hashes than to instantiate a full
@@ -375,7 +387,10 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) {
 }
 
 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
-    const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
+    #[inline]
+    fn can_reconstruct_query_key() -> bool {
+        false
+    }
 
     // We actually would not need to specialize the implementation of this
     // method but it's faster to combine the hashes than to instantiate a full
diff --git a/src/librustc_middle/hir/map/mod.rs b/src/librustc_middle/hir/map/mod.rs
index 53e88787323..e3e0856ffc5 100644
--- a/src/librustc_middle/hir/map/mod.rs
+++ b/src/librustc_middle/hir/map/mod.rs
@@ -14,7 +14,7 @@ use rustc_hir::*;
 use rustc_index::vec::IndexVec;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::Spanned;
-use rustc_span::symbol::{kw, Symbol};
+use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 
@@ -228,7 +228,6 @@ impl<'hir> Map<'hir> {
                 ImplItemKind::Const(..) => DefKind::AssocConst,
                 ImplItemKind::Fn(..) => DefKind::AssocFn,
                 ImplItemKind::TyAlias(..) => DefKind::AssocTy,
-                ImplItemKind::OpaqueTy(..) => DefKind::AssocOpaqueTy,
             },
             Node::Variant(_) => DefKind::Variant,
             Node::Ctor(variant_data) => {
@@ -335,6 +334,16 @@ impl<'hir> Map<'hir> {
         }
     }
 
+    pub fn enclosing_body_owner(&self, hir_id: HirId) -> HirId {
+        for (parent, _) in self.parent_iter(hir_id) {
+            if let Some(body) = self.maybe_body_owned_by(parent) {
+                return self.body_owner(body);
+            }
+        }
+
+        bug!("no `enclosing_body_owner` for hir_id `{}`", hir_id);
+    }
+
     /// Returns the `HirId` that corresponds to the definition of
     /// which this is the body of, i.e., a `fn`, `const` or `static`
     /// item (possibly associated), a closure, or a `hir::AnonConst`.
@@ -365,6 +374,13 @@ impl<'hir> Map<'hir> {
         })
     }
 
+    pub fn body_param_names(&self, id: BodyId) -> impl Iterator<Item = Ident> + 'hir {
+        self.body(id).params.iter().map(|arg| match arg.pat.kind {
+            PatKind::Binding(_, _, ident, _) => ident,
+            _ => Ident::new(kw::Invalid, rustc_span::DUMMY_SP),
+        })
+    }
+
     /// Returns the `BodyOwnerKind` of this `LocalDefId`.
     ///
     /// Panics if `LocalDefId` does not have an associated body.
@@ -537,18 +553,8 @@ impl<'hir> Map<'hir> {
 
     /// Whether the expression pointed at by `hir_id` belongs to a `const` evaluation context.
     /// Used exclusively for diagnostics, to avoid suggestion function calls.
-    pub fn is_const_context(&self, hir_id: HirId) -> bool {
-        let parent_id = self.get_parent_item(hir_id);
-        match self.get(parent_id) {
-            Node::Item(&Item { kind: ItemKind::Const(..) | ItemKind::Static(..), .. })
-            | Node::TraitItem(&TraitItem { kind: TraitItemKind::Const(..), .. })
-            | Node::ImplItem(&ImplItem { kind: ImplItemKind::Const(..), .. })
-            | Node::AnonConst(_) => true,
-            Node::Item(&Item { kind: ItemKind::Fn(ref sig, ..), .. }) => {
-                sig.header.constness == Constness::Const
-            }
-            _ => false,
-        }
+    pub fn is_inside_const_context(&self, hir_id: HirId) -> bool {
+        self.body_const_context(self.local_def_id(self.enclosing_body_owner(hir_id))).is_some()
     }
 
     /// Whether `hir_id` corresponds to a `mod` or a crate.
@@ -672,6 +678,8 @@ impl<'hir> Map<'hir> {
             if let Node::Item(Item {
                 kind:
                     ItemKind::Fn(..)
+                    | ItemKind::Const(..)
+                    | ItemKind::Static(..)
                     | ItemKind::Mod(..)
                     | ItemKind::Enum(..)
                     | ItemKind::Struct(..)
@@ -700,11 +708,7 @@ impl<'hir> Map<'hir> {
                 return CRATE_HIR_ID;
             }
             match self.get(scope) {
-                Node::Item(Item {
-                    kind: ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }),
-                    ..
-                })
-                | Node::Block(_) => {}
+                Node::Block(_) => {}
                 _ => break,
             }
         }
@@ -1025,9 +1029,6 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String {
             ImplItemKind::TyAlias(_) => {
                 format!("assoc type {} in {}{}", ii.ident, path_str(), id_str)
             }
-            ImplItemKind::OpaqueTy(_) => {
-                format!("assoc opaque type {} in {}{}", ii.ident, path_str(), id_str)
-            }
         },
         Some(Node::TraitItem(ti)) => {
             let kind = match ti.kind {
diff --git a/src/librustc_middle/hir/mod.rs b/src/librustc_middle/hir/mod.rs
index 1e3676496ce..e152d11c081 100644
--- a/src/librustc_middle/hir/mod.rs
+++ b/src/librustc_middle/hir/mod.rs
@@ -12,10 +12,7 @@ use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
-use rustc_hir::Body;
-use rustc_hir::HirId;
-use rustc_hir::ItemLocalId;
-use rustc_hir::Node;
+use rustc_hir::*;
 use rustc_index::vec::IndexVec;
 
 pub struct Owner<'tcx> {
@@ -79,5 +76,20 @@ pub fn provide(providers: &mut Providers<'_>) {
     };
     providers.hir_owner = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].signature;
     providers.hir_owner_nodes = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].with_bodies.as_deref();
+    providers.fn_arg_names = |tcx, id| {
+        let hir = tcx.hir();
+        let hir_id = hir.as_local_hir_id(id.expect_local());
+        if let Some(body_id) = hir.maybe_body_owned_by(hir_id) {
+            tcx.arena.alloc_from_iter(hir.body_param_names(body_id))
+        } else if let Node::TraitItem(&TraitItem {
+            kind: TraitItemKind::Fn(_, TraitFn::Required(idents)),
+            ..
+        }) = hir.get(hir_id)
+        {
+            tcx.arena.alloc_slice(idents)
+        } else {
+            span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", id);
+        }
+    };
     map::provide(providers);
 }
diff --git a/src/librustc_middle/lib.rs b/src/librustc_middle/lib.rs
index 7c433574d18..62c92e988ba 100644
--- a/src/librustc_middle/lib.rs
+++ b/src/librustc_middle/lib.rs
@@ -42,7 +42,7 @@
 #![feature(option_expect_none)]
 #![feature(or_patterns)]
 #![feature(range_is_empty)]
-#![feature(specialization)] // FIXME: min_specialization does not work
+#![feature(min_specialization)]
 #![feature(track_caller)]
 #![feature(trusted_len)]
 #![feature(vec_remove_item)]
diff --git a/src/librustc_middle/lint.rs b/src/librustc_middle/lint.rs
index 27239b4ad2e..923119e359c 100644
--- a/src/librustc_middle/lint.rs
+++ b/src/librustc_middle/lint.rs
@@ -339,7 +339,9 @@ pub fn struct_lint_level<'s, 'd>(
 pub fn in_external_macro(sess: &Session, span: Span) -> bool {
     let expn_data = span.ctxt().outer_expn_data();
     match expn_data.kind {
-        ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false,
+        ExpnKind::Root
+        | ExpnKind::Desugaring(DesugaringKind::ForLoop(_))
+        | ExpnKind::Desugaring(DesugaringKind::Operator) => false,
         ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
         ExpnKind::Macro(MacroKind::Bang, _) => {
             // Dummy span for the `def_site` means it's an external macro.
diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs
index 98973f1b6fb..27848684706 100644
--- a/src/librustc_middle/mir/mod.rs
+++ b/src/librustc_middle/mir/mod.rs
@@ -76,7 +76,8 @@ pub enum MirPhase {
     Build = 0,
     Const = 1,
     Validated = 2,
-    Optimized = 3,
+    DropElab = 3,
+    Optimized = 4,
 }
 
 impl MirPhase {
@@ -457,8 +458,39 @@ impl<T> ClearCrossCrate<T> {
     }
 }
 
-impl<T: Encodable> rustc_serialize::UseSpecializedEncodable for ClearCrossCrate<T> {}
-impl<T: Decodable> rustc_serialize::UseSpecializedDecodable for ClearCrossCrate<T> {}
+const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0;
+const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1;
+
+impl<T: Encodable> rustc_serialize::UseSpecializedEncodable for ClearCrossCrate<T> {
+    #[inline]
+    fn default_encode<E: rustc_serialize::Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
+        match *self {
+            ClearCrossCrate::Clear => TAG_CLEAR_CROSS_CRATE_CLEAR.encode(e),
+            ClearCrossCrate::Set(ref val) => {
+                TAG_CLEAR_CROSS_CRATE_SET.encode(e)?;
+                val.encode(e)
+            }
+        }
+    }
+}
+impl<T: Decodable> rustc_serialize::UseSpecializedDecodable for ClearCrossCrate<T> {
+    #[inline]
+    fn default_decode<D>(d: &mut D) -> Result<ClearCrossCrate<T>, D::Error>
+    where
+        D: rustc_serialize::Decoder,
+    {
+        let discr = u8::decode(d)?;
+
+        match discr {
+            TAG_CLEAR_CROSS_CRATE_CLEAR => Ok(ClearCrossCrate::Clear),
+            TAG_CLEAR_CROSS_CRATE_SET => {
+                let val = T::decode(d)?;
+                Ok(ClearCrossCrate::Set(val))
+            }
+            _ => unreachable!(),
+        }
+    }
+}
 
 /// Grouped information about the source code origin of a MIR entity.
 /// Intended to be inspected by diagnostics and debuginfo.
@@ -1131,6 +1163,9 @@ pub enum TerminatorKind<'tcx> {
         /// `true` if this is from a call in HIR rather than from an overloaded
         /// operator. True for overloaded function call.
         from_hir_call: bool,
+        /// This `Span` is the span of the function, without the dot and receiver
+        /// (e.g. `foo(a, b)` in `x.foo(a, b)`
+        fn_span: Span,
     },
 
     /// Jump to the target if the condition has the expected value,
@@ -1240,7 +1275,7 @@ pub enum InlineAsmOperand<'tcx> {
         value: Box<Constant<'tcx>>,
     },
     SymStatic {
-        value: Box<Constant<'tcx>>,
+        def_id: DefId,
     },
 }
 
@@ -1636,9 +1671,11 @@ impl<'tcx> TerminatorKind<'tcx> {
                         InlineAsmOperand::Const { value } => {
                             write!(fmt, "const {:?}", value)?;
                         }
-                        InlineAsmOperand::SymFn { value }
-                        | InlineAsmOperand::SymStatic { value } => {
-                            write!(fmt, "sym {:?}", value)?;
+                        InlineAsmOperand::SymFn { value } => {
+                            write!(fmt, "sym_fn {:?}", value)?;
+                        }
+                        InlineAsmOperand::SymStatic { def_id } => {
+                            write!(fmt, "sym_static {:?}", def_id)?;
                         }
                     }
                 }
@@ -1952,8 +1989,6 @@ impl<V, T> ProjectionElem<V, T> {
 /// and the index is a local.
 pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
 
-impl<'tcx> Copy for PlaceElem<'tcx> {}
-
 // At least on 64 bit systems, `PlaceElem` should not be larger than two pointers.
 #[cfg(target_arch = "x86_64")]
 static_assert_size!(PlaceElem<'_>, 16);
@@ -2449,7 +2484,8 @@ impl<'tcx> Debug for Rvalue<'tcx> {
                                     tcx.def_path_str_with_substs(def_id.to_def_id(), substs),
                                 )
                             } else {
-                                format!("[closure@{:?}]", tcx.hir().span(hir_id))
+                                let span = tcx.hir().span(hir_id);
+                                format!("[closure@{}]", tcx.sess.source_map().span_to_string(span))
                             };
                             let mut struct_fmt = fmt.debug_struct(&name);
 
diff --git a/src/librustc_middle/mir/query.rs b/src/librustc_middle/mir/query.rs
index 99bfb74c243..d82faf3e5fb 100644
--- a/src/librustc_middle/mir/query.rs
+++ b/src/librustc_middle/mir/query.rs
@@ -183,7 +183,7 @@ pub struct ClosureOutlivesRequirement<'tcx> {
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
 #[derive(RustcEncodable, RustcDecodable, HashStable)]
 pub enum ConstraintCategory {
-    Return,
+    Return(ReturnConstraint),
     Yield,
     UseAsConst,
     UseAsStatic,
@@ -199,6 +199,7 @@ pub enum ConstraintCategory {
     SizedBound,
     Assignment,
     OpaqueType,
+    ClosureUpvar(hir::HirId),
 
     /// A "boring" constraint (caused by the given location) is one that
     /// the user probably doesn't want to see described in diagnostics,
@@ -216,6 +217,13 @@ pub enum ConstraintCategory {
     Internal,
 }
 
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
+#[derive(RustcEncodable, RustcDecodable, HashStable)]
+pub enum ReturnConstraint {
+    Normal,
+    ClosureUpvar(hir::HirId),
+}
+
 /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
 /// that must outlive some region.
 #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
diff --git a/src/librustc_middle/mir/type_foldable.rs b/src/librustc_middle/mir/type_foldable.rs
index 97c6d6bf5f4..3f5d528d9e7 100644
--- a/src/librustc_middle/mir/type_foldable.rs
+++ b/src/librustc_middle/mir/type_foldable.rs
@@ -42,7 +42,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
                 resume_arg: resume_arg.fold_with(folder),
                 drop,
             },
-            Call { ref func, ref args, ref destination, cleanup, from_hir_call } => {
+            Call { ref func, ref args, ref destination, cleanup, from_hir_call, fn_span } => {
                 let dest =
                     destination.as_ref().map(|&(ref loc, dest)| (loc.fold_with(folder), dest));
 
@@ -52,6 +52,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
                     destination: dest,
                     cleanup,
                     from_hir_call,
+                    fn_span,
                 }
             }
             Assert { ref cond, expected, ref msg, target, cleanup } => {
diff --git a/src/librustc_middle/mir/visit.rs b/src/librustc_middle/mir/visit.rs
index 9f886cbc9fb..5f9fcdca516 100644
--- a/src/librustc_middle/mir/visit.rs
+++ b/src/librustc_middle/mir/visit.rs
@@ -492,6 +492,7 @@ macro_rules! make_mir_visitor {
                         destination,
                         cleanup: _,
                         from_hir_call: _,
+                        fn_span: _
                     } => {
                         self.visit_operand(func, source_location);
                         for arg in args {
@@ -563,10 +564,10 @@ macro_rules! make_mir_visitor {
                                         );
                                     }
                                 }
-                                InlineAsmOperand::SymFn { value }
-                                | InlineAsmOperand::SymStatic { value } => {
+                                InlineAsmOperand::SymFn { value } => {
                                     self.visit_constant(value, source_location);
                                 }
+                                InlineAsmOperand::SymStatic { def_id: _ } => {}
                             }
                         }
                     }
diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs
index 4d7e7882e42..3b6d54a1bc1 100644
--- a/src/librustc_middle/query/mod.rs
+++ b/src/librustc_middle/query/mod.rs
@@ -190,6 +190,12 @@ rustc_queries! {
             no_hash
         }
 
+        query mir_drops_elaborated_and_const_checked(key: LocalDefId) -> Steal<mir::Body<'tcx>> {
+            storage(ArenaCacheSelector<'tcx>)
+            no_hash
+            desc { |tcx| "elaborating drops for `{}`", tcx.def_path_str(key.to_def_id()) }
+        }
+
         query mir_validated(key: LocalDefId) ->
             (
                 Steal<mir::Body<'tcx>>,
@@ -700,7 +706,7 @@ rustc_queries! {
     }
 
     Other {
-        query fn_arg_names(def_id: DefId) -> &'tcx [Symbol] {
+        query fn_arg_names(def_id: DefId) -> &'tcx [rustc_span::symbol::Ident] {
             desc { |tcx| "looking up function parameter names for `{}`", tcx.def_path_str(def_id) }
         }
         /// Gets the rendered value of the specified constant or associated constant.
@@ -789,6 +795,17 @@ rustc_queries! {
             desc { "computing whether `{}` needs drop", env.value }
         }
 
+        /// Query backing `TyS::is_structural_eq_shallow`.
+        ///
+        /// This is only correct for ADTs. Call `is_structural_eq_shallow` to handle all types
+        /// correctly.
+        query has_structural_eq_impls(ty: Ty<'tcx>) -> bool {
+            desc {
+                "computing whether `{:?}` implements `PartialStructuralEq` and `StructuralEq`",
+                ty
+            }
+        }
+
         /// A list of types where the ADT requires drop if and only if any of
         /// those types require drop. If the ADT is known to always need drop
         /// then `Err(AlwaysRequiresDrop)` is returned.
diff --git a/src/librustc_middle/traits/specialization_graph.rs b/src/librustc_middle/traits/specialization_graph.rs
index 4f02aaa96ac..f4961617b81 100644
--- a/src/librustc_middle/traits/specialization_graph.rs
+++ b/src/librustc_middle/traits/specialization_graph.rs
@@ -100,24 +100,11 @@ impl<'tcx> Node {
         trait_item_kind: ty::AssocKind,
         trait_def_id: DefId,
     ) -> Option<ty::AssocItem> {
-        use crate::ty::AssocKind::*;
-
         tcx.associated_items(self.def_id())
             .filter_by_name_unhygienic(trait_item_name.name)
             .find(move |impl_item| {
-                match (trait_item_kind, impl_item.kind) {
-                | (Const, Const)
-                | (Fn, Fn)
-                | (Type, Type)
-                | (Type, OpaqueTy)  // assoc. types can be made opaque in impls
-                => tcx.hygienic_eq(impl_item.ident, trait_item_name, trait_def_id),
-
-                | (Const, _)
-                | (Fn, _)
-                | (Type, _)
-                | (OpaqueTy, _)
-                => false,
-            }
+                trait_item_kind == impl_item.kind
+                    && tcx.hygienic_eq(impl_item.ident, trait_item_name, trait_def_id)
             })
             .copied()
     }
diff --git a/src/librustc_middle/ty/codec.rs b/src/librustc_middle/ty/codec.rs
index 8bc69a9d123..1a8e5c45dd2 100644
--- a/src/librustc_middle/ty/codec.rs
+++ b/src/librustc_middle/ty/codec.rs
@@ -97,7 +97,7 @@ where
 
 pub fn encode_spanned_predicates<'tcx, E, C>(
     encoder: &mut E,
-    predicates: &'tcx [(ty::Predicate<'tcx>, Span)],
+    predicates: &[(ty::Predicate<'tcx>, Span)],
     cache: C,
 ) -> Result<(), E::Error>
 where
@@ -139,7 +139,7 @@ pub trait TyDecoder<'tcx>: Decoder {
 }
 
 #[inline]
-pub fn decode_arena_allocable<D, T: ArenaAllocatable + Decodable>(
+pub fn decode_arena_allocable<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>(
     decoder: &mut D,
 ) -> Result<&'tcx T, D::Error>
 where
@@ -149,7 +149,7 @@ where
 }
 
 #[inline]
-pub fn decode_arena_allocable_slice<D, T: ArenaAllocatable + Decodable>(
+pub fn decode_arena_allocable_slice<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>(
     decoder: &mut D,
 ) -> Result<&'tcx [T], D::Error>
 where
@@ -318,18 +318,38 @@ macro_rules! __impl_decoder_methods {
 macro_rules! impl_arena_allocatable_decoder {
     ([]$args:tt) => {};
     ([decode $(, $attrs:ident)*]
-     [[$DecoderName:ident [$($typaram:tt),*]], [$name:ident: $ty:ty], $tcx:lifetime]) => {
-        impl<$($typaram),*> SpecializedDecoder<&$tcx $ty> for $DecoderName<$($typaram),*> {
+     [[$DecoderName:ident [$($typaram:tt),*]], [$name:ident: $ty:ty, $gen_ty:ty], $tcx:lifetime]) => {
+         // FIXME(#36588): These impls are horribly unsound as they allow
+         // the caller to pick any lifetime for `'tcx`, including `'static`.
+        #[allow(unused_lifetimes)]
+        impl<'_x, '_y, '_z, '_w, '_a, $($typaram),*> SpecializedDecoder<&'_a $gen_ty>
+        for $DecoderName<$($typaram),*>
+        where &'_a $gen_ty: UseSpecializedDecodable
+        {
             #[inline]
-            fn specialized_decode(&mut self) -> Result<&$tcx $ty, Self::Error> {
-                decode_arena_allocable(self)
+            fn specialized_decode(&mut self) -> Result<&'_a $gen_ty, Self::Error> {
+                unsafe {
+                    std::mem::transmute::<
+                        Result<&$tcx $ty, Self::Error>,
+                        Result<&'_a $gen_ty, Self::Error>,
+                    >(decode_arena_allocable(self))
+                }
             }
         }
 
-        impl<$($typaram),*> SpecializedDecoder<&$tcx [$ty]> for $DecoderName<$($typaram),*> {
+        #[allow(unused_lifetimes)]
+        impl<'_x, '_y, '_z, '_w, '_a, $($typaram),*> SpecializedDecoder<&'_a [$gen_ty]>
+        for $DecoderName<$($typaram),*>
+        where &'_a [$gen_ty]: UseSpecializedDecodable
+        {
             #[inline]
-            fn specialized_decode(&mut self) -> Result<&$tcx [$ty], Self::Error> {
-                decode_arena_allocable_slice(self)
+            fn specialized_decode(&mut self) -> Result<&'_a [$gen_ty], Self::Error> {
+                unsafe {
+                    std::mem::transmute::<
+                        Result<&$tcx [$ty], Self::Error>,
+                        Result<&'_a [$gen_ty], Self::Error>,
+                    >(decode_arena_allocable_slice(self))
+                }
             }
         }
     };
@@ -340,9 +360,9 @@ macro_rules! impl_arena_allocatable_decoder {
 
 #[macro_export]
 macro_rules! impl_arena_allocatable_decoders {
-    ($args:tt, [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
+    ($args:tt, [$($a:tt $name:ident: $ty:ty, $gen_ty:ty;)*], $tcx:lifetime) => {
         $(
-            impl_arena_allocatable_decoder!($a [$args, [$name: $ty], $tcx]);
+            impl_arena_allocatable_decoder!($a [$args, [$name: $ty, $gen_ty], $tcx]);
         )*
     }
 }
@@ -352,14 +372,15 @@ macro_rules! implement_ty_decoder {
     ($DecoderName:ident <$($typaram:tt),*>) => {
         mod __ty_decoder_impl {
             use std::borrow::Cow;
+            use std::mem::transmute;
 
-            use rustc_serialize::{Decoder, SpecializedDecoder};
+            use rustc_serialize::{Decoder, SpecializedDecoder, UseSpecializedDecodable};
 
             use $crate::infer::canonical::CanonicalVarInfos;
             use $crate::ty;
             use $crate::ty::codec::*;
-            use $crate::ty::subst::SubstsRef;
-            use rustc_hir::def_id::{CrateNum};
+            use $crate::ty::subst::InternalSubsts;
+            use rustc_hir::def_id::CrateNum;
 
             use rustc_span::Span;
 
@@ -398,8 +419,7 @@ macro_rules! implement_ty_decoder {
             }
 
             // FIXME(#36588): These impls are horribly unsound as they allow
-            // the caller to pick any lifetime for `'tcx`, including `'static`,
-            // by using the unspecialized proxies to them.
+            // the caller to pick any lifetime for `'tcx`, including `'static`.
 
             rustc_hir::arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx);
             arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx);
@@ -411,90 +431,98 @@ macro_rules! implement_ty_decoder {
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<ty::Ty<'tcx>>
-            for $DecoderName<$($typaram),*> {
-                fn specialized_decode(&mut self) -> Result<ty::Ty<'tcx>, Self::Error> {
-                    decode_ty(self)
+            impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x ty::TyS<'_y>>
+            for $DecoderName<$($typaram),*>
+            where &'_x ty::TyS<'_y>: UseSpecializedDecodable
+            {
+                fn specialized_decode(&mut self) -> Result<&'_x ty::TyS<'_y>, Self::Error> {
+                    unsafe { transmute::<Result<ty::Ty<'tcx>, Self::Error>, Result<&'_x ty::TyS<'_y>, Self::Error>>(decode_ty(self)) }
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<&'tcx [(ty::Predicate<'tcx>, Span)]>
-            for $DecoderName<$($typaram),*> {
+            impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x [(ty::Predicate<'_y>, Span)]>
+            for $DecoderName<$($typaram),*>
+            where &'_x [(ty::Predicate<'_y>, Span)]: UseSpecializedDecodable {
                 fn specialized_decode(&mut self)
-                                      -> Result<&'tcx [(ty::Predicate<'tcx>, Span)], Self::Error> {
-                    decode_spanned_predicates(self)
+                                      -> Result<&'_x [(ty::Predicate<'_y>, Span)], Self::Error>
+                {
+                    unsafe { transmute(decode_spanned_predicates(self)) }
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<SubstsRef<'tcx>>
-            for $DecoderName<$($typaram),*> {
-                fn specialized_decode(&mut self) -> Result<SubstsRef<'tcx>, Self::Error> {
-                    decode_substs(self)
+            impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x InternalSubsts<'_y>>
+            for $DecoderName<$($typaram),*>
+            where &'_x InternalSubsts<'_y>: UseSpecializedDecodable {
+                fn specialized_decode(&mut self) -> Result<&'_x InternalSubsts<'_y>, Self::Error> {
+                    unsafe { transmute(decode_substs(self)) }
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<$crate::mir::Place<'tcx>>
+            impl<'_x, $($typaram),*> SpecializedDecoder<$crate::mir::Place<'_x>>
             for $DecoderName<$($typaram),*> {
                 fn specialized_decode(
                     &mut self
-                ) -> Result<$crate::mir::Place<'tcx>, Self::Error> {
-                    decode_place(self)
+                ) -> Result<$crate::mir::Place<'_x>, Self::Error> {
+                    unsafe { transmute(decode_place(self)) }
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<ty::Region<'tcx>>
+            impl<'_x, $($typaram),*> SpecializedDecoder<ty::Region<'_x>>
             for $DecoderName<$($typaram),*> {
-                fn specialized_decode(&mut self) -> Result<ty::Region<'tcx>, Self::Error> {
-                    decode_region(self)
+                fn specialized_decode(&mut self) -> Result<ty::Region<'_x>, Self::Error> {
+                    unsafe { transmute(decode_region(self)) }
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<&'tcx ty::List<ty::Ty<'tcx>>>
-            for $DecoderName<$($typaram),*> {
+            impl<'_x, '_y, '_z, $($typaram),*> SpecializedDecoder<&'_x ty::List<&'_y ty::TyS<'_z>>>
+            for $DecoderName<$($typaram),*>
+            where &'_x ty::List<&'_y ty::TyS<'_z>>: UseSpecializedDecodable {
                 fn specialized_decode(&mut self)
-                                      -> Result<&'tcx ty::List<ty::Ty<'tcx>>, Self::Error> {
-                    decode_ty_slice(self)
+                                      -> Result<&'_x ty::List<&'_y ty::TyS<'_z>>, Self::Error> {
+                    unsafe { transmute(decode_ty_slice(self)) }
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<&'tcx ty::AdtDef>
+            impl<'_x, $($typaram),*> SpecializedDecoder<&'_x ty::AdtDef>
             for $DecoderName<$($typaram),*> {
-                fn specialized_decode(&mut self) -> Result<&'tcx ty::AdtDef, Self::Error> {
-                    decode_adt_def(self)
+                fn specialized_decode(&mut self) -> Result<&'_x ty::AdtDef, Self::Error> {
+                    unsafe { transmute(decode_adt_def(self)) }
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>
-                for $DecoderName<$($typaram),*> {
+            impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x ty::List<ty::ExistentialPredicate<'_y>>>
+            for $DecoderName<$($typaram),*>
+            where &'_x ty::List<ty::ExistentialPredicate<'_y>>: UseSpecializedDecodable {
                 fn specialized_decode(&mut self)
-                    -> Result<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>, Self::Error> {
-                    decode_existential_predicate_slice(self)
+                    -> Result<&'_x ty::List<ty::ExistentialPredicate<'_y>>, Self::Error> {
+                        unsafe { transmute(decode_existential_predicate_slice(self)) }
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<CanonicalVarInfos<'tcx>>
+            impl<'_x, $($typaram),*> SpecializedDecoder<CanonicalVarInfos<'_x>>
                 for $DecoderName<$($typaram),*> {
                 fn specialized_decode(&mut self)
-                    -> Result<CanonicalVarInfos<'tcx>, Self::Error> {
-                    decode_canonical_var_infos(self)
+                    -> Result<CanonicalVarInfos<'_x>, Self::Error> {
+                        unsafe { transmute(decode_canonical_var_infos(self)) }
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::Const<'tcx>>
-            for $DecoderName<$($typaram),*> {
-                fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
-                    decode_const(self)
+            impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x $crate::ty::Const<'_y>>
+            for $DecoderName<$($typaram),*>
+            where &'_x $crate::ty::Const<'_y>: UseSpecializedDecodable {
+                fn specialized_decode(&mut self) -> Result<&'_x ty::Const<'_y>, Self::Error> {
+                    unsafe { transmute(decode_const(self)) }
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::mir::interpret::Allocation>
+            impl<'_x, $($typaram),*> SpecializedDecoder<&'_x $crate::mir::interpret::Allocation>
             for $DecoderName<$($typaram),*> {
                 fn specialized_decode(
                     &mut self
-                ) -> Result<&'tcx $crate::mir::interpret::Allocation, Self::Error> {
-                    decode_allocation(self)
+                ) -> Result<&'_x $crate::mir::interpret::Allocation, Self::Error> {
+                    unsafe { transmute(decode_allocation(self)) }
                 }
             }
         }
-    }
+    };
 }
diff --git a/src/librustc_middle/ty/error.rs b/src/librustc_middle/ty/error.rs
index 480420dfdcf..be3bf748225 100644
--- a/src/librustc_middle/ty/error.rs
+++ b/src/librustc_middle/ty/error.rs
@@ -814,7 +814,7 @@ fn foo(&self) -> Self::T { String::new() }
                 // FIXME: account for `#![feature(specialization)]`
                 for item in &items[..] {
                     match item.kind {
-                        hir::AssocItemKind::Type | hir::AssocItemKind::OpaqueTy => {
+                        hir::AssocItemKind::Type => {
                             // FIXME: account for returning some type in a trait fn impl that has
                             // an assoc type as a return type (#72076).
                             if let hir::Defaultness::Default { has_value: true } = item.defaultness
@@ -838,7 +838,7 @@ fn foo(&self) -> Self::T { String::new() }
             })) => {
                 for item in &items[..] {
                     match item.kind {
-                        hir::AssocItemKind::Type | hir::AssocItemKind::OpaqueTy => {
+                        hir::AssocItemKind::Type => {
                             if self.type_of(self.hir().local_def_id(item.id.hir_id)) == found {
                                 db.span_label(item.span, "expected this associated type");
                                 return true;
diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs
index e93abd3390a..f5bca90c2bd 100644
--- a/src/librustc_middle/ty/layout.rs
+++ b/src/librustc_middle/ty/layout.rs
@@ -2529,6 +2529,8 @@ where
             Msp430Interrupt => Conv::Msp430Intr,
             X86Interrupt => Conv::X86Intr,
             AmdGpuKernel => Conv::AmdGpuKernel,
+            AvrInterrupt => Conv::AvrInterrupt,
+            AvrNonBlockingInterrupt => Conv::AvrNonBlockingInterrupt,
 
             // These API constants ought to be more specific...
             Cdecl => Conv::C,
diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs
index ffbe3a40297..93ef7317199 100644
--- a/src/librustc_middle/ty/mod.rs
+++ b/src/librustc_middle/ty/mod.rs
@@ -198,14 +198,13 @@ pub struct AssocItem {
 pub enum AssocKind {
     Const,
     Fn,
-    OpaqueTy,
     Type,
 }
 
 impl AssocKind {
     pub fn namespace(&self) -> Namespace {
         match *self {
-            ty::AssocKind::OpaqueTy | ty::AssocKind::Type => Namespace::TypeNS,
+            ty::AssocKind::Type => Namespace::TypeNS,
             ty::AssocKind::Const | ty::AssocKind::Fn => Namespace::ValueNS,
         }
     }
@@ -215,22 +214,11 @@ impl AssocKind {
             AssocKind::Const => DefKind::AssocConst,
             AssocKind::Fn => DefKind::AssocFn,
             AssocKind::Type => DefKind::AssocTy,
-            AssocKind::OpaqueTy => DefKind::AssocOpaqueTy,
         }
     }
 }
 
 impl AssocItem {
-    /// Tests whether the associated item admits a non-trivial implementation
-    /// for !
-    pub fn relevant_for_never(&self) -> bool {
-        match self.kind {
-            AssocKind::OpaqueTy | AssocKind::Const | AssocKind::Type => true,
-            // FIXME(canndrew): Be more thorough here, check if any argument is uninhabited.
-            AssocKind::Fn => !self.fn_has_self_parameter,
-        }
-    }
-
     pub fn signature(&self, tcx: TyCtxt<'_>) -> String {
         match self.kind {
             ty::AssocKind::Fn => {
@@ -241,8 +229,6 @@ impl AssocItem {
                 tcx.fn_sig(self.def_id).skip_binder().to_string()
             }
             ty::AssocKind::Type => format!("type {};", self.ident),
-            // FIXME(type_alias_impl_trait): we should print bounds here too.
-            ty::AssocKind::OpaqueTy => format!("type {};", self.ident),
             ty::AssocKind::Const => {
                 format!("const {}: {:?};", self.ident, tcx.type_of(self.def_id))
             }
@@ -2390,6 +2376,29 @@ impl<'tcx> AdtDef {
     pub fn sized_constraint(&self, tcx: TyCtxt<'tcx>) -> &'tcx [Ty<'tcx>] {
         tcx.adt_sized_constraint(self.did).0
     }
+
+    /// `repr(transparent)` structs can have a single non-ZST field, this function returns that
+    /// field.
+    pub fn transparent_newtype_field(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ParamEnv<'tcx>,
+    ) -> Option<&FieldDef> {
+        assert!(self.is_struct() && self.repr.transparent());
+
+        for field in &self.non_enum_variant().fields {
+            let field_ty = tcx.normalize_erasing_regions(
+                param_env,
+                field.ty(tcx, InternalSubsts::identity_for_item(tcx, self.did)),
+            );
+
+            if !field_ty.is_zst(tcx, self.did) {
+                return Some(field);
+            }
+        }
+
+        None
+    }
 }
 
 impl<'tcx> FieldDef {
@@ -2558,10 +2567,6 @@ impl<'tcx> TyCtxt<'tcx> {
             .filter(|item| item.kind == AssocKind::Fn && item.defaultness.has_value())
     }
 
-    pub fn trait_relevant_for_never(self, did: DefId) -> bool {
-        self.associated_items(did).in_definition_order().any(|item| item.relevant_for_never())
-    }
-
     pub fn opt_item_name(self, def_id: DefId) -> Option<Ident> {
         def_id
             .as_local()
diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs
index 90fb1981617..d782dd07a65 100644
--- a/src/librustc_middle/ty/print/pretty.rs
+++ b/src/librustc_middle/ty/print/pretty.rs
@@ -605,7 +605,8 @@ pub trait PrettyPrinter<'tcx>:
                 // FIXME(eddyb) should use `def_span`.
                 if let Some(did) = did.as_local() {
                     let hir_id = self.tcx().hir().as_local_hir_id(did);
-                    p!(write("@{:?}", self.tcx().hir().span(hir_id)));
+                    let span = self.tcx().hir().span(hir_id);
+                    p!(write("@{}", self.tcx().sess.source_map().span_to_string(span)));
 
                     if substs.as_generator().is_valid() {
                         let upvar_tys = substs.as_generator().upvar_tys();
@@ -653,7 +654,8 @@ pub trait PrettyPrinter<'tcx>:
                     if self.tcx().sess.opts.debugging_opts.span_free_formats {
                         p!(write("@"), print_def_path(did.to_def_id(), substs));
                     } else {
-                        p!(write("@{:?}", self.tcx().hir().span(hir_id)));
+                        let span = self.tcx().hir().span(hir_id);
+                        p!(write("@{}", self.tcx().sess.source_map().span_to_string(span)));
                     }
 
                     if substs.as_closure().is_valid() {
@@ -984,7 +986,7 @@ pub trait PrettyPrinter<'tcx>:
 
                 let ui_str = ui.name_str();
                 if data == max {
-                    p!(write("std::{}::MAX", ui_str))
+                    p!(write("{}::MAX", ui_str))
                 } else {
                     if print_ty { p!(write("{}{}", data, ui_str)) } else { p!(write("{}", data)) }
                 };
@@ -997,8 +999,8 @@ pub trait PrettyPrinter<'tcx>:
 
                 let i_str = i.name_str();
                 match data {
-                    d if d == min => p!(write("std::{}::MIN", i_str)),
-                    d if d == max => p!(write("std::{}::MAX", i_str)),
+                    d if d == min => p!(write("{}::MIN", i_str)),
+                    d if d == max => p!(write("{}::MAX", i_str)),
                     _ => {
                         let data = sign_extend(data, size) as i128;
                         if print_ty {
@@ -1362,7 +1364,7 @@ impl<F: fmt::Write> Printer<'tcx> for FmtPrinter<'_, 'tcx, F> {
                 if !self.empty_path {
                     write!(self, "::")?;
                 }
-                write!(self, "<impl at {:?}>", span)?;
+                write!(self, "<impl at {}>", self.tcx.sess.source_map().span_to_string(span))?;
                 self.empty_path = false;
 
                 return Ok(self);
diff --git a/src/librustc_middle/ty/query/on_disk_cache.rs b/src/librustc_middle/ty/query/on_disk_cache.rs
index 4eae06742d9..5374dff4224 100644
--- a/src/librustc_middle/ty/query/on_disk_cache.rs
+++ b/src/librustc_middle/ty/query/on_disk_cache.rs
@@ -1,6 +1,6 @@
 use crate::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
+use crate::mir::interpret;
 use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState};
-use crate::mir::{self, interpret};
 use crate::ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
 use crate::ty::context::TyCtxt;
 use crate::ty::{self, Ty};
@@ -26,9 +26,6 @@ use std::mem;
 
 const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
 
-const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0;
-const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1;
-
 const TAG_NO_EXPN_DATA: u8 = 0;
 const TAG_EXPN_DATA_SHORTHAND: u8 = 1;
 const TAG_EXPN_DATA_INLINE: u8 = 2;
@@ -667,24 +664,6 @@ impl<'a, 'tcx> SpecializedDecoder<Fingerprint> for CacheDecoder<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx, T: Decodable> SpecializedDecoder<mir::ClearCrossCrate<T>>
-    for CacheDecoder<'a, 'tcx>
-{
-    #[inline]
-    fn specialized_decode(&mut self) -> Result<mir::ClearCrossCrate<T>, Self::Error> {
-        let discr = u8::decode(self)?;
-
-        match discr {
-            TAG_CLEAR_CROSS_CRATE_CLEAR => Ok(mir::ClearCrossCrate::Clear),
-            TAG_CLEAR_CROSS_CRATE_SET => {
-                let val = T::decode(self)?;
-                Ok(mir::ClearCrossCrate::Set(val))
-            }
-            _ => unreachable!(),
-        }
-    }
-}
-
 //- ENCODING -------------------------------------------------------------------
 
 /// An encoder that can write the incr. comp. cache.
@@ -828,17 +807,20 @@ where
     }
 }
 
-impl<'a, 'tcx, E> SpecializedEncoder<Ty<'tcx>> for CacheEncoder<'a, 'tcx, E>
+impl<'a, 'b, 'c, 'tcx, E> SpecializedEncoder<&'b ty::TyS<'c>> for CacheEncoder<'a, 'tcx, E>
 where
     E: 'a + TyEncoder,
+    &'b ty::TyS<'c>: UseSpecializedEncodable,
 {
     #[inline]
-    fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
+    fn specialized_encode(&mut self, ty: &&'b ty::TyS<'c>) -> Result<(), Self::Error> {
+        debug_assert!(self.tcx.lift(ty).is_some());
+        let ty = unsafe { std::mem::transmute::<&&'b ty::TyS<'c>, &&'tcx ty::TyS<'tcx>>(ty) };
         ty_codec::encode_with_shorthand(self, ty, |encoder| &mut encoder.type_shorthands)
     }
 }
 
-impl<'a, 'tcx, E> SpecializedEncoder<&'tcx [(ty::Predicate<'tcx>, Span)]>
+impl<'a, 'b, 'c, 'tcx, E> SpecializedEncoder<&'b [(ty::Predicate<'c>, Span)]>
     for CacheEncoder<'a, 'tcx, E>
 where
     E: 'a + TyEncoder,
@@ -846,8 +828,15 @@ where
     #[inline]
     fn specialized_encode(
         &mut self,
-        predicates: &&'tcx [(ty::Predicate<'tcx>, Span)],
+        predicates: &&'b [(ty::Predicate<'c>, Span)],
     ) -> Result<(), Self::Error> {
+        debug_assert!(self.tcx.lift(*predicates).is_some());
+        let predicates = unsafe {
+            std::mem::transmute::<
+                &&'b [(ty::Predicate<'c>, Span)],
+                &&'tcx [(ty::Predicate<'tcx>, Span)],
+            >(predicates)
+        };
         ty_codec::encode_spanned_predicates(self, predicates, |encoder| {
             &mut encoder.predicate_shorthands
         })
@@ -890,23 +879,6 @@ impl<'a, 'tcx> SpecializedEncoder<Fingerprint> for CacheEncoder<'a, 'tcx, opaque
     }
 }
 
-impl<'a, 'tcx, E, T> SpecializedEncoder<mir::ClearCrossCrate<T>> for CacheEncoder<'a, 'tcx, E>
-where
-    E: 'a + TyEncoder,
-    T: Encodable,
-{
-    #[inline]
-    fn specialized_encode(&mut self, val: &mir::ClearCrossCrate<T>) -> Result<(), Self::Error> {
-        match *val {
-            mir::ClearCrossCrate::Clear => TAG_CLEAR_CROSS_CRATE_CLEAR.encode(self),
-            mir::ClearCrossCrate::Set(ref val) => {
-                TAG_CLEAR_CROSS_CRATE_SET.encode(self)?;
-                val.encode(self)
-            }
-        }
-    }
-}
-
 macro_rules! encoder_methods {
     ($($name:ident($ty:ty);)*) => {
         #[inline]
@@ -995,7 +967,7 @@ fn encode_query_results<'a, 'tcx, Q, E>(
     query_result_index: &mut EncodedQueryResultIndex,
 ) -> Result<(), E::Error>
 where
-    Q: super::QueryDescription<TyCtxt<'tcx>>,
+    Q: super::QueryDescription<TyCtxt<'tcx>> + super::QueryAccessors<TyCtxt<'tcx>>,
     Q::Value: Encodable,
     E: 'a + TyEncoder,
 {
diff --git a/src/librustc_middle/ty/query/profiling_support.rs b/src/librustc_middle/ty/query/profiling_support.rs
index e0d3e764dad..3c446624418 100644
--- a/src/librustc_middle/ty/query/profiling_support.rs
+++ b/src/librustc_middle/ty/query/profiling_support.rs
@@ -112,30 +112,53 @@ impl<T: Debug> IntoSelfProfilingString for T {
     }
 }
 
-impl IntoSelfProfilingString for DefId {
+impl<T: SpecIntoSelfProfilingString> IntoSelfProfilingString for T {
     fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
+        self.spec_to_self_profile_string(builder)
+    }
+}
+
+#[rustc_specialization_trait]
+pub trait SpecIntoSelfProfilingString: Debug {
+    fn spec_to_self_profile_string(
+        &self,
+        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
+    ) -> StringId;
+}
+
+impl SpecIntoSelfProfilingString for DefId {
+    fn spec_to_self_profile_string(
+        &self,
+        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
+    ) -> StringId {
         builder.def_id_to_string_id(*self)
     }
 }
 
-impl IntoSelfProfilingString for CrateNum {
-    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
+impl SpecIntoSelfProfilingString for CrateNum {
+    fn spec_to_self_profile_string(
+        &self,
+        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
+    ) -> StringId {
         builder.def_id_to_string_id(DefId { krate: *self, index: CRATE_DEF_INDEX })
     }
 }
 
-impl IntoSelfProfilingString for DefIndex {
-    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
+impl SpecIntoSelfProfilingString for DefIndex {
+    fn spec_to_self_profile_string(
+        &self,
+        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
+    ) -> StringId {
         builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: *self })
     }
 }
 
-impl<T0, T1> IntoSelfProfilingString for (T0, T1)
+impl<T0, T1> SpecIntoSelfProfilingString for (T0, T1)
 where
-    T0: IntoSelfProfilingString + Debug,
-    T1: IntoSelfProfilingString + Debug,
+    T0: SpecIntoSelfProfilingString,
+    T1: SpecIntoSelfProfilingString,
 {
-    default fn to_self_profile_string(
+    fn spec_to_self_profile_string(
         &self,
         builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
     ) -> StringId {
diff --git a/src/librustc_middle/ty/query/values.rs b/src/librustc_middle/ty/query/values.rs
index b01d15c29b2..b1f76ff6a03 100644
--- a/src/librustc_middle/ty/query/values.rs
+++ b/src/librustc_middle/ty/query/values.rs
@@ -1,4 +1,4 @@
-use crate::ty::{self, AdtSizedConstraint, Ty, TyCtxt};
+use crate::ty::{self, AdtSizedConstraint, Ty, TyCtxt, TyS};
 
 use rustc_span::symbol::Symbol;
 
@@ -13,9 +13,11 @@ impl<'tcx, T> Value<'tcx> for T {
     }
 }
 
-impl<'tcx> Value<'tcx> for Ty<'tcx> {
-    fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
-        tcx.types.err
+impl<'tcx> Value<'tcx> for &'_ TyS<'_> {
+    fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self {
+        // SAFETY: This is never called when `Self` is not `Ty<'tcx>`.
+        // FIXME: Represent the above fact in the trait system somehow.
+        unsafe { std::mem::transmute::<Ty<'tcx>, Ty<'_>>(tcx.types.err) }
     }
 }
 
@@ -25,8 +27,14 @@ impl<'tcx> Value<'tcx> for ty::SymbolName {
     }
 }
 
-impl<'tcx> Value<'tcx> for AdtSizedConstraint<'tcx> {
+impl<'tcx> Value<'tcx> for AdtSizedConstraint<'_> {
     fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self {
-        AdtSizedConstraint(tcx.intern_type_list(&[tcx.types.err]))
+        // SAFETY: This is never called when `Self` is not `AdtSizedConstraint<'tcx>`.
+        // FIXME: Represent the above fact in the trait system somehow.
+        unsafe {
+            std::mem::transmute::<AdtSizedConstraint<'tcx>, AdtSizedConstraint<'_>>(
+                AdtSizedConstraint(tcx.intern_type_list(&[tcx.types.err])),
+            )
+        }
     }
 }
diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs
index d507fcbc194..cddd7081ca3 100644
--- a/src/librustc_middle/ty/relate.rs
+++ b/src/librustc_middle/ty/relate.rs
@@ -250,8 +250,8 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
                 &b.item_def_id,
             )))
         } else {
-            let ty = relation.relate(&a.ty, &b.ty)?;
-            let substs = relation.relate(&a.substs, &b.substs)?;
+            let ty = relation.relate_with_variance(ty::Invariant, &a.ty, &b.ty)?;
+            let substs = relation.relate_with_variance(ty::Invariant, &a.substs, &b.substs)?;
             Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, ty })
         }
     }
@@ -508,16 +508,7 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
     debug!("{}.super_relate_consts(a = {:?}, b = {:?})", relation.tag(), a, b);
     let tcx = relation.tcx();
 
-    let eagerly_eval = |x: &'tcx ty::Const<'tcx>| {
-        // FIXME(eddyb) this doesn't account for lifetime inference variables
-        // being erased by `eval`, *nor* for the polymorphic aspect of `eval`.
-        // That is, we could always use `eval` and it will just return the
-        // old value back if it doesn't succeed.
-        if !x.val.needs_infer() {
-            return x.eval(tcx, relation.param_env()).val;
-        }
-        x.val
-    };
+    let eagerly_eval = |x: &'tcx ty::Const<'tcx>| x.eval(tcx, relation.param_env()).val;
 
     // FIXME(eddyb) doesn't look like everything below checks that `a.ty == b.ty`.
     // We could probably always assert it early, as `const` generic parameters
diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs
index 5d4c2a54267..fad96aa86cc 100644
--- a/src/librustc_middle/ty/sty.rs
+++ b/src/librustc_middle/ty/sty.rs
@@ -2186,6 +2186,11 @@ impl<'tcx> TyS<'tcx> {
             }
         }
     }
+
+    /// Is this a zero-sized type?
+    pub fn is_zst(&'tcx self, tcx: TyCtxt<'tcx>, did: DefId) -> bool {
+        tcx.layout_of(tcx.param_env(did).and(self)).map(|layout| layout.is_zst()).unwrap_or(false)
+    }
 }
 
 /// Typed constant value.
@@ -2404,8 +2409,6 @@ impl<'tcx> Const<'tcx> {
     }
 }
 
-impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx Const<'tcx> {}
-
 /// Represents a constant in Rust.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
 #[derive(HashStable)]
diff --git a/src/librustc_middle/ty/util.rs b/src/librustc_middle/ty/util.rs
index c2b794ca4bd..ff284b709c2 100644
--- a/src/librustc_middle/ty/util.rs
+++ b/src/librustc_middle/ty/util.rs
@@ -705,6 +705,7 @@ impl<'tcx> ty::TyS<'tcx> {
     /// optimization as well as the rules around static values. Note
     /// that the `Freeze` trait is not exposed to end users and is
     /// effectively an implementation detail.
+    // FIXME: use `TyCtxtAt` instead of separate `Span`.
     pub fn is_freeze(
         &'tcx self,
         tcx: TyCtxt<'tcx>,
@@ -778,6 +779,57 @@ impl<'tcx> ty::TyS<'tcx> {
         }
     }
 
+    /// Returns `true` if equality for this type is both reflexive and structural.
+    ///
+    /// Reflexive equality for a type is indicated by an `Eq` impl for that type.
+    ///
+    /// Primitive types (`u32`, `str`) have structural equality by definition. For composite data
+    /// types, equality for the type as a whole is structural when it is the same as equality
+    /// between all components (fields, array elements, etc.) of that type. For ADTs, structural
+    /// equality is indicated by an implementation of `PartialStructuralEq` and `StructuralEq` for
+    /// that type.
+    ///
+    /// This function is "shallow" because it may return `true` for a composite type whose fields
+    /// are not `StructuralEq`. For example, `[T; 4]` has structural equality regardless of `T`
+    /// because equality for arrays is determined by the equality of each array element. If you
+    /// want to know whether a given call to `PartialEq::eq` will proceed structurally all the way
+    /// down, you will need to use a type visitor.
+    #[inline]
+    pub fn is_structural_eq_shallow(&'tcx self, tcx: TyCtxt<'tcx>) -> bool {
+        match self.kind {
+            // Look for an impl of both `PartialStructuralEq` and `StructuralEq`.
+            Adt(..) => tcx.has_structural_eq_impls(self),
+
+            // Primitive types that satisfy `Eq`.
+            Bool | Char | Int(_) | Uint(_) | Str | Never => true,
+
+            // Composite types that satisfy `Eq` when all of their fields do.
+            //
+            // Because this function is "shallow", we return `true` for these composites regardless
+            // of the type(s) contained within.
+            Ref(..) | Array(..) | Slice(_) | Tuple(..) => true,
+
+            // Raw pointers use bitwise comparison.
+            RawPtr(_) | FnPtr(_) => true,
+
+            // Floating point numbers are not `Eq`.
+            Float(_) => false,
+
+            // Conservatively return `false` for all others...
+
+            // Anonymous function types
+            FnDef(..) | Closure(..) | Dynamic(..) | Generator(..) => false,
+
+            // Generic or inferred types
+            //
+            // FIXME(ecstaticmorse): Maybe we should `bug` here? This should probably only be
+            // called for known, fully-monomorphized types.
+            Projection(_) | Opaque(..) | Param(_) | Bound(..) | Placeholder(_) | Infer(_) => false,
+
+            Foreign(_) | GeneratorWitness(..) | Error => false,
+        }
+    }
+
     pub fn same_type(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
         match (&a.kind, &b.kind) {
             (&Adt(did_a, substs_a), &Adt(did_b, substs_b)) => {
@@ -827,7 +879,15 @@ impl<'tcx> ty::TyS<'tcx> {
                     // Find non representable fields with their spans
                     fold_repr(def.all_fields().map(|field| {
                         let ty = field.ty(tcx, substs);
-                        let span = tcx.hir().span_if_local(field.did).unwrap_or(sp);
+                        let span = match field
+                            .did
+                            .as_local()
+                            .map(|id| tcx.hir().as_local_hir_id(id))
+                            .and_then(|id| tcx.hir().find(id))
+                        {
+                            Some(hir::Node::Field(field)) => field.ty.span,
+                            _ => sp,
+                        };
                         match is_type_structurally_recursive(
                             tcx,
                             span,
diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
index d0050f801fc..2e897647a3b 100644
--- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
@@ -24,7 +24,8 @@ use crate::borrow_check::{
 };
 
 use super::{
-    explain_borrow::BorrowExplanation, IncludingDowncast, RegionName, RegionNameSource, UseSpans,
+    explain_borrow::BorrowExplanation, FnSelfUseKind, IncludingDowncast, RegionName,
+    RegionNameSource, UseSpans,
 };
 
 #[derive(Debug)]
@@ -150,13 +151,70 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         format!("value moved{} here, in previous iteration of loop", move_msg),
                     );
                 } else {
-                    err.span_label(move_span, format!("value moved{} here", move_msg));
-                    move_spans.var_span_label(
-                        &mut err,
-                        format!("variable moved due to use{}", move_spans.describe()),
-                    );
+                    if let UseSpans::FnSelfUse { var_span, fn_call_span, fn_span, kind } =
+                        move_spans
+                    {
+                        let place_name = self
+                            .describe_place(moved_place.as_ref())
+                            .map(|n| format!("`{}`", n))
+                            .unwrap_or_else(|| "value".to_owned());
+                        match kind {
+                            FnSelfUseKind::FnOnceCall => {
+                                err.span_label(
+                                    fn_call_span,
+                                    &format!("{} moved due to this call", place_name),
+                                );
+                                err.span_note(
+                                    var_span,
+                                    "this value implements `FnOnce`, which causes it to be moved when called",
+                                );
+                            }
+                            FnSelfUseKind::Operator { self_arg } => {
+                                err.span_label(
+                                    fn_call_span,
+                                    &format!("{} moved due to usage in operator", place_name),
+                                );
+                                if self.fn_self_span_reported.insert(fn_span) {
+                                    err.span_note(
+                                        self_arg.span,
+                                        "calling this operator moves the left-hand side",
+                                    );
+                                }
+                            }
+                            FnSelfUseKind::Normal { self_arg, implicit_into_iter } => {
+                                if implicit_into_iter {
+                                    err.span_label(
+                                        fn_call_span,
+                                        &format!(
+                                            "{} moved due to this implicit call to `.into_iter()`",
+                                            place_name
+                                        ),
+                                    );
+                                } else {
+                                    err.span_label(
+                                        fn_call_span,
+                                        &format!("{} moved due to this method call", place_name),
+                                    );
+                                }
+                                // Avoid pointing to the same function in multiple different
+                                // error messages
+                                if self.fn_self_span_reported.insert(self_arg.span) {
+                                    err.span_note(
+                                        self_arg.span,
+                                        &format!("this function consumes the receiver `self` by taking ownership of it, which moves {}", place_name)
+                                    );
+                                }
+                            }
+                        }
+                    } else {
+                        err.span_label(move_span, format!("value moved{} here", move_msg));
+                        move_spans.var_span_label(
+                            &mut err,
+                            format!("variable moved due to use{}", move_spans.describe()),
+                        );
+                    }
                 }
-                if Some(DesugaringKind::ForLoop) == move_span.desugaring_kind() {
+                if let Some(DesugaringKind::ForLoop(_)) = move_span.desugaring_kind() {
                     let sess = self.infcx.tcx.sess;
                     if let Ok(snippet) = sess.source_map().span_to_snippet(move_span) {
                         err.span_suggestion(
@@ -766,7 +824,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     category:
                         category
                         @
-                        (ConstraintCategory::Return
+                        (ConstraintCategory::Return(_)
                         | ConstraintCategory::CallArgument
                         | ConstraintCategory::OpaqueType),
                     from_closure: false,
@@ -1089,7 +1147,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         opt_place_desc: Option<&String>,
     ) -> Option<DiagnosticBuilder<'cx>> {
         let return_kind = match category {
-            ConstraintCategory::Return => "return",
+            ConstraintCategory::Return(_) => "return",
             ConstraintCategory::Yield => "yield",
             _ => return None,
         };
@@ -1203,7 +1261,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         );
 
         let msg = match category {
-            ConstraintCategory::Return | ConstraintCategory::OpaqueType => {
+            ConstraintCategory::Return(_) | ConstraintCategory::OpaqueType => {
                 format!("{} is returned here", kind)
             }
             ConstraintCategory::CallArgument => {
diff --git a/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
index 5253acbba7f..d04059ff0fc 100644
--- a/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs
@@ -509,7 +509,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 // Used in a closure.
                 (LaterUseKind::ClosureCapture, var_span)
             }
-            UseSpans::OtherUse(span) => {
+            UseSpans::OtherUse(span) | UseSpans::FnSelfUse { var_span: span, .. } => {
                 let block = &self.body.basic_blocks()[location.block];
 
                 let kind = if let Some(&Statement {
diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs
index ca8e54ea286..04f48cd6582 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mod.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs
@@ -11,7 +11,11 @@ use rustc_middle::mir::{
 };
 use rustc_middle::ty::print::Print;
 use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
-use rustc_span::{symbol::sym, Span};
+use rustc_span::{
+    hygiene::{DesugaringKind, ForLoopLoc},
+    symbol::sym,
+    Span,
+};
 use rustc_target::abi::VariantIdx;
 
 use super::borrow_set::BorrowData;
@@ -33,6 +37,7 @@ crate use mutability_errors::AccessKind;
 crate use outlives_suggestion::OutlivesSuggestionBuilder;
 crate use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors};
 crate use region_name::{RegionName, RegionNameSource};
+use rustc_span::symbol::Ident;
 
 pub(super) struct IncludingDowncast(pub(super) bool);
 
@@ -529,33 +534,58 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     }
 }
 
-// The span(s) associated to a use of a place.
+/// The span(s) associated to a use of a place.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub(super) enum UseSpans {
-    // The access is caused by capturing a variable for a closure.
+    /// The access is caused by capturing a variable for a closure.
     ClosureUse {
-        // This is true if the captured variable was from a generator.
+        /// This is true if the captured variable was from a generator.
         generator_kind: Option<GeneratorKind>,
-        // The span of the args of the closure, including the `move` keyword if
-        // it's present.
+        /// The span of the args of the closure, including the `move` keyword if
+        /// it's present.
         args_span: Span,
-        // The span of the first use of the captured variable inside the closure.
+        /// The span of the first use of the captured variable inside the closure.
+        var_span: Span,
+    },
+    /// The access is caused by using a variable as the receiver of a method
+    /// that takes 'self'
+    FnSelfUse {
+        /// The span of the variable being moved
         var_span: Span,
+        /// The span of the method call on the variable
+        fn_call_span: Span,
+        /// The definition span of the method being called
+        fn_span: Span,
+        kind: FnSelfUseKind,
     },
     // This access has a single span associated to it: common case.
     OtherUse(Span),
 }
 
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub(super) enum FnSelfUseKind {
+    /// A normal method call of the form `receiver.foo(a, b, c)`
+    Normal { self_arg: Ident, implicit_into_iter: bool },
+    /// A call to `FnOnce::call_once`, desugared from `my_closure(a, b, c)`
+    FnOnceCall,
+    /// A call to an operator trait, desuraged from operator syntax (e.g. `a << b`)
+    Operator { self_arg: Ident },
+}
+
 impl UseSpans {
     pub(super) fn args_or_use(self) -> Span {
         match self {
-            UseSpans::ClosureUse { args_span: span, .. } | UseSpans::OtherUse(span) => span,
+            UseSpans::ClosureUse { args_span: span, .. }
+            | UseSpans::FnSelfUse { var_span: span, .. }
+            | UseSpans::OtherUse(span) => span,
         }
     }
 
     pub(super) fn var_or_use(self) -> Span {
         match self {
-            UseSpans::ClosureUse { var_span: span, .. } | UseSpans::OtherUse(span) => span,
+            UseSpans::ClosureUse { var_span: span, .. }
+            | UseSpans::FnSelfUse { var_span: span, .. }
+            | UseSpans::OtherUse(span) => span,
         }
     }
 
@@ -624,6 +654,7 @@ impl UseSpans {
     {
         match self {
             closure @ UseSpans::ClosureUse { .. } => closure,
+            fn_self @ UseSpans::FnSelfUse { .. } => fn_self,
             UseSpans::OtherUse(_) => if_other(),
         }
     }
@@ -727,21 +758,100 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
         debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt);
         if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) = stmt.kind {
-            let def_id = match kind {
+            match kind {
                 box AggregateKind::Closure(def_id, _)
-                | box AggregateKind::Generator(def_id, _, _) => def_id,
-                _ => return OtherUse(stmt.source_info.span),
-            };
-
-            debug!("move_spans: def_id={:?} places={:?}", def_id, places);
-            if let Some((args_span, generator_kind, var_span)) =
-                self.closure_span(*def_id, moved_place, places)
-            {
-                return ClosureUse { generator_kind, args_span, var_span };
+                | box AggregateKind::Generator(def_id, _, _) => {
+                    debug!("move_spans: def_id={:?} places={:?}", def_id, places);
+                    if let Some((args_span, generator_kind, var_span)) =
+                        self.closure_span(*def_id, moved_place, places)
+                    {
+                        return ClosureUse { generator_kind, args_span, var_span };
+                    }
+                }
+                _ => {}
             }
         }
 
-        OtherUse(stmt.source_info.span)
+        let normal_ret = OtherUse(stmt.source_info.span);
+
+        // We are trying to find MIR of the form:
+        // ```
+        // _temp = _moved_val;
+        // ...
+        // FnSelfCall(_temp, ...)
+        // ```
+        //
+        // where `_moved_val` is the place we generated the move error for,
+        // `_temp` is some other local, and `FnSelfCall` is a function
+        // that has a `self` parameter.
+
+        let target_temp = match stmt.kind {
+            StatementKind::Assign(box (temp, _)) if temp.as_local().is_some() => {
+                temp.as_local().unwrap()
+            }
+            _ => return normal_ret,
+        };
+
+        debug!("move_spans: target_temp = {:?}", target_temp);
+
+        if let Some(Terminator { kind: TerminatorKind::Call { func, args, fn_span, .. }, .. }) =
+            &self.body[location.block].terminator
+        {
+            let mut method_did = None;
+            if let Operand::Constant(box Constant { literal: ty::Const { ty, .. }, .. }) = func {
+                if let ty::FnDef(def_id, _) = ty.kind {
+                    debug!("move_spans: fn = {:?}", def_id);
+                    if let Some(ty::AssocItem { fn_has_self_parameter, .. }) =
+                        self.infcx.tcx.opt_associated_item(def_id)
+                    {
+                        if *fn_has_self_parameter {
+                            method_did = Some(def_id);
+                        }
+                    }
+                }
+            }
+
+            let tcx = self.infcx.tcx;
+            let method_did = if let Some(did) = method_did { did } else { return normal_ret };
+
+            if let [Operand::Move(self_place), ..] = **args {
+                if self_place.as_local() == Some(target_temp) {
+                    let is_fn_once = tcx.parent(method_did) == tcx.lang_items().fn_once_trait();
+                    let fn_call_span = *fn_span;
+
+                    let self_arg = tcx.fn_arg_names(method_did)[0];
+
+                    let kind = if is_fn_once {
+                        FnSelfUseKind::FnOnceCall
+                    } else if fn_call_span.is_desugaring(DesugaringKind::Operator) {
+                        FnSelfUseKind::Operator { self_arg }
+                    } else {
+                        debug!(
+                            "move_spans: method_did={:?}, fn_call_span={:?}",
+                            method_did, fn_call_span
+                        );
+                        let implicit_into_iter = matches!(
+                            fn_call_span.desugaring_kind(),
+                            Some(DesugaringKind::ForLoop(ForLoopLoc::IntoIter))
+                        );
+                        FnSelfUseKind::Normal { self_arg, implicit_into_iter }
+                    };
+
+                    return FnSelfUse {
+                        var_span: stmt.source_info.span,
+                        fn_call_span,
+                        fn_span: self
+                            .infcx
+                            .tcx
+                            .sess
+                            .source_map()
+                            .guess_head_span(self.infcx.tcx.def_span(method_did)),
+                        kind,
+                    };
+                }
+            }
+        }
+        return normal_ret;
     }
 
     /// Finds the span of arguments of a closure (within `maybe_closure_span`)
diff --git a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
index b49e4187fb8..4883b08e424 100644
--- a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
@@ -408,7 +408,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     format!("{}.as_ref()", snippet),
                     Applicability::MaybeIncorrect,
                 );
-            } else if span.is_desugaring(DesugaringKind::ForLoop)
+            } else if matches!(span.desugaring_kind(), Some(DesugaringKind::ForLoop(_)))
                 && self.infcx.tcx.is_diagnostic_item(Symbol::intern("vec_type"), def_id)
             {
                 // FIXME: suggest for anything that implements `IntoIterator`.
diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
index e04ed8b83de..b4bc89e827d 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
@@ -365,7 +365,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                                     opt_assignment_rhs_span.and_then(|span| span.desugaring_kind());
                                 match opt_desugaring_kind {
                                     // on for loops, RHS points to the iterator part
-                                    Some(DesugaringKind::ForLoop) => Some((
+                                    Some(DesugaringKind::ForLoop(_)) => Some((
                                         false,
                                         opt_assignment_rhs_span.unwrap(),
                                         format!(
@@ -495,7 +495,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         let closure_id = hir.as_local_hir_id(self.mir_def_id);
         let fn_call_id = hir.get_parent_node(closure_id);
         let node = hir.get(fn_call_id);
-        let item_id = hir.get_parent_item(fn_call_id);
+        let item_id = hir.enclosing_body_owner(fn_call_id);
         let mut look_at_return = true;
         // If we can detect the expression to be an `fn` call where the closure was an argument,
         // we point at the `fn` definition argument...
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
index 727c4d0605e..f1923b9e81c 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
@@ -5,9 +5,9 @@ use rustc_infer::infer::{
     error_reporting::nice_region_error::NiceRegionError,
     error_reporting::unexpected_hidden_region_diagnostic, NLLRegionVariableOrigin,
 };
-use rustc_middle::mir::ConstraintCategory;
+use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
 use rustc_middle::ty::{self, RegionVid, Ty};
-use rustc_span::symbol::kw;
+use rustc_span::symbol::{kw, sym};
 use rustc_span::Span;
 
 use crate::util::borrowck_errors;
@@ -26,7 +26,7 @@ impl ConstraintDescription for ConstraintCategory {
         // Must end with a space. Allows for empty names to be provided.
         match self {
             ConstraintCategory::Assignment => "assignment ",
-            ConstraintCategory::Return => "returning this value ",
+            ConstraintCategory::Return(_) => "returning this value ",
             ConstraintCategory::Yield => "yielding this value ",
             ConstraintCategory::UseAsConst => "using this value as a constant ",
             ConstraintCategory::UseAsStatic => "using this value as a static ",
@@ -37,6 +37,7 @@ impl ConstraintDescription for ConstraintCategory {
             ConstraintCategory::SizedBound => "proving this value is `Sized` ",
             ConstraintCategory::CopyBound => "copying this value ",
             ConstraintCategory::OpaqueType => "opaque type ",
+            ConstraintCategory::ClosureUpvar(_) => "closure capture ",
             ConstraintCategory::Boring
             | ConstraintCategory::BoringNoLocation
             | ConstraintCategory::Internal => "",
@@ -306,8 +307,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         };
 
         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::Return(kind), true, false) if self.is_closure_fn_mut(fr) => {
+                self.report_fnmut_error(&errci, kind)
             }
             (ConstraintCategory::Assignment, true, false)
             | (ConstraintCategory::CallArgument, true, false) => {
@@ -347,7 +348,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     ///            executing...
     ///    = note: ...therefore, returned references to captured variables will escape the closure
     /// ```
-    fn report_fnmut_error(&self, errci: &ErrorConstraintInfo) -> DiagnosticBuilder<'tcx> {
+    fn report_fnmut_error(
+        &self,
+        errci: &ErrorConstraintInfo,
+        kind: ReturnConstraint,
+    ) -> DiagnosticBuilder<'tcx> {
         let ErrorConstraintInfo { outlived_fr, span, .. } = errci;
 
         let mut diag = self
@@ -356,19 +361,39 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             .sess
             .struct_span_err(*span, "captured variable cannot escape `FnMut` closure body");
 
-        // 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.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"
-        } else {
-            "returns a reference to a captured variable which escapes the closure body"
+        let mut output_ty = self.regioncx.universal_regions().unnormalized_output_ty;
+        if let ty::Opaque(def_id, _) = output_ty.kind {
+            output_ty = self.infcx.tcx.type_of(def_id)
+        };
+
+        debug!("report_fnmut_error: output_ty={:?}", output_ty);
+
+        let message = match output_ty.kind {
+            ty::Closure(_, _) => {
+                "returns a closure that contains a reference to a captured variable, which then \
+                 escapes the closure body"
+            }
+            ty::Adt(def, _) if self.infcx.tcx.is_diagnostic_item(sym::gen_future, def.did) => {
+                "returns an `async` block that contains a reference to a captured variable, which then \
+                 escapes the closure body"
+            }
+            _ => "returns a reference to a captured variable which escapes the closure body",
         };
 
         diag.span_label(*span, message);
 
+        if let ReturnConstraint::ClosureUpvar(upvar) = kind {
+            let def_id = match self.regioncx.universal_regions().defining_ty {
+                DefiningTy::Closure(def_id, _) => def_id,
+                ty @ _ => bug!("unexpected DefiningTy {:?}", ty),
+            };
+
+            let upvar_def_span = self.infcx.tcx.hir().span(upvar);
+            let upvar_span = self.infcx.tcx.upvars_mentioned(def_id).unwrap()[&upvar].span;
+            diag.span_label(upvar_def_span, "variable defined here");
+            diag.span_label(upvar_span, "variable captured here");
+        }
+
         match self.give_region_a_name(*outlived_fr).unwrap().source {
             RegionNameSource::NamedEarlyBoundRegion(fr_span)
             | RegionNameSource::NamedFreeRegion(fr_span)
@@ -506,7 +531,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         outlived_fr_name.highlight_region_name(&mut diag);
 
         match (category, outlived_fr_is_local, fr_is_local) {
-            (ConstraintCategory::Return, true, _) => {
+            (ConstraintCategory::Return(_), true, _) => {
                 diag.span_label(
                     *span,
                     format!(
diff --git a/src/librustc_mir/borrow_check/invalidation.rs b/src/librustc_mir/borrow_check/invalidation.rs
index 77d16458383..17fa641ae6c 100644
--- a/src/librustc_mir/borrow_check/invalidation.rs
+++ b/src/librustc_mir/borrow_check/invalidation.rs
@@ -142,6 +142,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
                 destination,
                 cleanup: _,
                 from_hir_call: _,
+                fn_span: _,
             } => {
                 self.consume_operand(location, func);
                 for arg in args {
@@ -208,7 +209,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
                             }
                         }
                         InlineAsmOperand::SymFn { value: _ }
-                        | InlineAsmOperand::SymStatic { value: _ } => {}
+                        | InlineAsmOperand::SymStatic { def_id: _ } => {}
                     }
                 }
             }
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 736cda83ca5..d099f48adc5 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -216,6 +216,7 @@ fn do_mir_borrowck<'a, 'tcx>(
         &mut flow_inits,
         &mdpe.move_data,
         &borrow_set,
+        &upvars,
     );
 
     // Dump MIR results into a file, if that is enabled. This let us
@@ -277,6 +278,7 @@ fn do_mir_borrowck<'a, 'tcx>(
                 move_data: &move_data,
                 location_table: &LocationTable::new(promoted_body),
                 movable_generator,
+                fn_self_span_reported: Default::default(),
                 locals_are_invalidated_at_exit,
                 access_place_error_reported: Default::default(),
                 reservation_error_reported: Default::default(),
@@ -310,6 +312,7 @@ fn do_mir_borrowck<'a, 'tcx>(
         location_table,
         movable_generator,
         locals_are_invalidated_at_exit,
+        fn_self_span_reported: Default::default(),
         access_place_error_reported: Default::default(),
         reservation_error_reported: Default::default(),
         reservation_warnings: Default::default(),
@@ -486,6 +489,10 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> {
     // but it is currently inconvenient to track down the `BorrowIndex`
     // at the time we detect and report a reservation error.
     reservation_error_reported: FxHashSet<Place<'tcx>>,
+    /// This fields keeps track of the `Span`s that we have
+    /// used to report extra information for `FnSelfUse`, to avoid
+    /// unnecessarily verbose errors.
+    fn_self_span_reported: FxHashSet<Span>,
     /// Migration warnings to be reported for #56254. We delay reporting these
     /// so that we can suppress the warning if there's a corresponding error
     /// for the activation of the borrow.
@@ -699,6 +706,7 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc
                 ref destination,
                 cleanup: _,
                 from_hir_call: _,
+                fn_span: _,
             } => {
                 self.consume_operand(loc, (func, span), flow_state);
                 for arg in args {
@@ -759,7 +767,7 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc
                             }
                         }
                         InlineAsmOperand::SymFn { value: _ }
-                        | InlineAsmOperand::SymStatic { value: _ } => {}
+                        | InlineAsmOperand::SymStatic { def_id: _ } => {}
                     }
                 }
             }
@@ -2307,30 +2315,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// be `self` in the current MIR, because that is the only time we directly access the fields
     /// of a closure type.
     pub fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option<Field> {
-        let mut place_projection = place_ref.projection;
-        let mut by_ref = false;
-
-        if let [proj_base @ .., ProjectionElem::Deref] = place_projection {
-            place_projection = proj_base;
-            by_ref = true;
-        }
-
-        match place_projection {
-            [base @ .., ProjectionElem::Field(field, _ty)] => {
-                let tcx = self.infcx.tcx;
-                let base_ty = Place::ty_from(place_ref.local, base, self.body(), tcx).ty;
-
-                if (base_ty.is_closure() || base_ty.is_generator())
-                    && (!by_ref || self.upvars[field.index()].by_ref)
-                {
-                    Some(*field)
-                } else {
-                    None
-                }
-            }
-
-            _ => None,
-        }
+        path_utils::is_upvar_field_projection(self.infcx.tcx, &self.upvars, place_ref, self.body())
     }
 }
 
diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs
index 1d373337147..ea68364be37 100644
--- a/src/librustc_mir/borrow_check/nll.rs
+++ b/src/librustc_mir/borrow_check/nll.rs
@@ -39,6 +39,7 @@ use crate::borrow_check::{
     renumber,
     type_check::{self, MirTypeckRegionConstraints, MirTypeckResults},
     universal_regions::UniversalRegions,
+    Upvar,
 };
 
 crate type PoloniusOutput = Output<RustcFacts>;
@@ -166,6 +167,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
     flow_inits: &mut ResultsCursor<'cx, 'tcx, MaybeInitializedPlaces<'cx, 'tcx>>,
     move_data: &MoveData<'tcx>,
     borrow_set: &BorrowSet<'tcx>,
+    upvars: &[Upvar],
 ) -> NllOutput<'tcx> {
     let mut all_facts = AllFacts::enabled(infcx.tcx).then_some(AllFacts::default());
 
@@ -188,6 +190,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
             flow_inits,
             move_data,
             elements,
+            upvars,
         );
 
     if let Some(all_facts) = &mut all_facts {
@@ -314,7 +317,7 @@ pub(super) fn dump_mir_results<'a, 'tcx>(
     infcx: &InferCtxt<'a, 'tcx>,
     source: MirSource<'tcx>,
     body: &Body<'tcx>,
-    regioncx: &RegionInferenceContext<'_>,
+    regioncx: &RegionInferenceContext<'tcx>,
     closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
 ) {
     if !mir_util::dump_enabled(infcx.tcx, "nll", source.def_id()) {
@@ -325,7 +328,7 @@ pub(super) fn dump_mir_results<'a, 'tcx>(
         match pass_where {
             // Before the CFG, dump out the values for each region variable.
             PassWhere::BeforeCFG => {
-                regioncx.dump_mir(out)?;
+                regioncx.dump_mir(infcx.tcx, out)?;
                 writeln!(out, "|")?;
 
                 if let Some(closure_region_requirements) = closure_region_requirements {
diff --git a/src/librustc_mir/borrow_check/path_utils.rs b/src/librustc_mir/borrow_check/path_utils.rs
index f5238e7b7be..934729553a7 100644
--- a/src/librustc_mir/borrow_check/path_utils.rs
+++ b/src/librustc_mir/borrow_check/path_utils.rs
@@ -1,10 +1,11 @@
 use crate::borrow_check::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation};
 use crate::borrow_check::places_conflict;
 use crate::borrow_check::AccessDepth;
+use crate::borrow_check::Upvar;
 use crate::dataflow::indexes::BorrowIndex;
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_middle::mir::BorrowKind;
-use rustc_middle::mir::{BasicBlock, Body, Location, Place};
+use rustc_middle::mir::{BasicBlock, Body, Field, Location, Place, PlaceRef, ProjectionElem};
 use rustc_middle::ty::TyCtxt;
 
 /// Returns `true` if the borrow represented by `kind` is
@@ -135,3 +136,38 @@ pub(super) fn borrow_of_local_data(place: Place<'_>) -> bool {
     // Any errors will be caught on the initial borrow
     !place.is_indirect()
 }
+
+/// If `place` is a field projection, and the field is being projected from a closure type,
+/// then returns the index of the field being projected. Note that this closure will always
+/// be `self` in the current MIR, because that is the only time we directly access the fields
+/// of a closure type.
+pub(crate) fn is_upvar_field_projection(
+    tcx: TyCtxt<'tcx>,
+    upvars: &[Upvar],
+    place_ref: PlaceRef<'tcx>,
+    body: &Body<'tcx>,
+) -> Option<Field> {
+    let mut place_projection = place_ref.projection;
+    let mut by_ref = false;
+
+    if let [proj_base @ .., ProjectionElem::Deref] = place_projection {
+        place_projection = proj_base;
+        by_ref = true;
+    }
+
+    match place_projection {
+        [base @ .., ProjectionElem::Field(field, _ty)] => {
+            let base_ty = Place::ty_from(place_ref.local, base, body, tcx).ty;
+
+            if (base_ty.is_closure() || base_ty.is_generator())
+                && (!by_ref || upvars[field.index()].by_ref)
+            {
+                Some(*field)
+            } else {
+                None
+            }
+        }
+
+        _ => None,
+    }
+}
diff --git a/src/librustc_mir/borrow_check/region_infer/dump_mir.rs b/src/librustc_mir/borrow_check/region_infer/dump_mir.rs
index 369e5402311..d6e48deb031 100644
--- a/src/librustc_mir/borrow_check/region_infer/dump_mir.rs
+++ b/src/librustc_mir/borrow_check/region_infer/dump_mir.rs
@@ -4,7 +4,9 @@
 //! context internal state.
 
 use super::{OutlivesConstraint, RegionInferenceContext};
+use crate::borrow_check::type_check::Locations;
 use rustc_infer::infer::NLLRegionVariableOrigin;
+use rustc_middle::ty::TyCtxt;
 use std::io::{self, Write};
 
 // Room for "'_#NNNNr" before things get misaligned.
@@ -14,7 +16,7 @@ const REGION_WIDTH: usize = 8;
 
 impl<'tcx> RegionInferenceContext<'tcx> {
     /// Write out our state into the `.mir` files.
-    pub(crate) fn dump_mir(&self, out: &mut dyn Write) -> io::Result<()> {
+    pub(crate) fn dump_mir(&self, tcx: TyCtxt<'tcx>, out: &mut dyn Write) -> io::Result<()> {
         writeln!(out, "| Free Region Mapping")?;
 
         for region in self.regions() {
@@ -48,7 +50,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         writeln!(out, "|")?;
         writeln!(out, "| Inference Constraints")?;
-        self.for_each_constraint(&mut |msg| writeln!(out, "| {}", msg))?;
+        self.for_each_constraint(tcx, &mut |msg| writeln!(out, "| {}", msg))?;
 
         Ok(())
     }
@@ -59,6 +61,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// inference resulted in the values that it did when debugging.
     fn for_each_constraint(
         &self,
+        tcx: TyCtxt<'tcx>,
         with_msg: &mut dyn FnMut(&str) -> io::Result<()>,
     ) -> io::Result<()> {
         for region in self.definitions.indices() {
@@ -72,7 +75,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         constraints.sort();
         for constraint in &constraints {
             let OutlivesConstraint { sup, sub, locations, category } = constraint;
-            with_msg(&format!("{:?}: {:?} due to {:?} at {:?}", sup, sub, category, locations,))?;
+            let (name, arg) = match locations {
+                Locations::All(span) => ("All", tcx.sess.source_map().span_to_string(*span)),
+                Locations::Single(loc) => ("Single", format!("{:?}", loc)),
+            };
+            with_msg(&format!("{:?}: {:?} due to {:?} at {}({})", sup, sub, category, name, arg))?;
         }
 
         Ok(())
diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs
index fe113843800..3e459bd52f7 100644
--- a/src/librustc_mir/borrow_check/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/region_infer/mod.rs
@@ -12,7 +12,7 @@ use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound}
 use rustc_infer::infer::{InferCtxt, NLLRegionVariableOrigin, RegionVariableOrigin};
 use rustc_middle::mir::{
     Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
-    ConstraintCategory, Local, Location,
+    ConstraintCategory, Local, Location, ReturnConstraint,
 };
 use rustc_middle::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable};
 use rustc_span::Span;
@@ -2017,7 +2017,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     | ConstraintCategory::BoringNoLocation
                     | ConstraintCategory::Internal => false,
                     ConstraintCategory::TypeAnnotation
-                    | ConstraintCategory::Return
+                    | ConstraintCategory::Return(_)
                     | ConstraintCategory::Yield => true,
                     _ => constraint_sup_scc != target_scc,
                 }
@@ -2042,7 +2042,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         if let Some(i) = best_choice {
             if let Some(next) = categorized_path.get(i + 1) {
-                if categorized_path[i].0 == ConstraintCategory::Return
+                if matches!(categorized_path[i].0, ConstraintCategory::Return(_))
                     && next.0 == ConstraintCategory::OpaqueType
                 {
                     // The return expression is being influenced by the return type being
@@ -2050,6 +2050,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     return *next;
                 }
             }
+
+            if categorized_path[i].0 == ConstraintCategory::Return(ReturnConstraint::Normal) {
+                let field = categorized_path.iter().find_map(|p| {
+                    if let ConstraintCategory::ClosureUpvar(f) = p.0 { Some(f) } else { None }
+                });
+
+                if let Some(field) = field {
+                    categorized_path[i].0 =
+                        ConstraintCategory::Return(ReturnConstraint::ClosureUpvar(field));
+                }
+            }
+
             return categorized_path[i];
         }
 
diff --git a/src/librustc_mir/borrow_check/type_check/free_region_relations.rs b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
index f97dff14645..5707127340d 100644
--- a/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
+++ b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs
@@ -259,7 +259,13 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
                     .param_env
                     .and(type_op::normalize::Normalize::new(ty))
                     .fully_perform(self.infcx)
-                    .unwrap_or_else(|_| bug!("failed to normalize {:?}", ty));
+                    .unwrap_or_else(|_| {
+                        self.infcx
+                            .tcx
+                            .sess
+                            .delay_span_bug(DUMMY_SP, &format!("failed to normalize {:?}", ty));
+                        (self.infcx.tcx.types.err, None)
+                    });
                 let constraints2 = self.add_implied_bounds(ty);
                 normalized_inputs_and_output.push(ty);
                 constraints1.into_iter().chain(constraints2)
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
index e2255d170f9..168612f9bee 100644
--- a/src/librustc_mir/borrow_check/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -55,6 +55,7 @@ use crate::borrow_check::{
     location::LocationTable,
     member_constraints::MemberConstraintSet,
     nll::ToRegionVid,
+    path_utils,
     region_infer::values::{
         LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements,
     },
@@ -62,6 +63,7 @@ use crate::borrow_check::{
     renumber,
     type_check::free_region_relations::{CreateResult, UniversalRegionRelations},
     universal_regions::{DefiningTy, UniversalRegions},
+    Upvar,
 };
 
 macro_rules! span_mirbug {
@@ -132,6 +134,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
     flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
     move_data: &MoveData<'tcx>,
     elements: &Rc<RegionValueElements>,
+    upvars: &[Upvar],
 ) -> MirTypeckResults<'tcx> {
     let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
     let mut constraints = MirTypeckRegionConstraints {
@@ -162,6 +165,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
         borrow_set,
         all_facts,
         constraints: &mut constraints,
+        upvars,
     };
 
     let opaque_type_values = type_check_internal(
@@ -577,7 +581,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         for constraint in constraints.outlives().iter() {
             let mut constraint = *constraint;
             constraint.locations = locations;
-            if let ConstraintCategory::Return
+            if let ConstraintCategory::Return(_)
             | ConstraintCategory::UseAsConst
             | ConstraintCategory::UseAsStatic = constraint.category
             {
@@ -827,6 +831,7 @@ struct BorrowCheckContext<'a, 'tcx> {
     all_facts: &'a mut Option<AllFacts>,
     borrow_set: &'a BorrowSet<'tcx>,
     constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
+    upvars: &'a [Upvar],
 }
 
 crate struct MirTypeckResults<'tcx> {
@@ -1420,7 +1425,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                                 ConstraintCategory::UseAsConst
                             }
                         } else {
-                            ConstraintCategory::Return
+                            ConstraintCategory::Return(ReturnConstraint::Normal)
                         }
                     }
                     Some(l) if !body.local_decls[l].is_user_variable() => {
@@ -1703,7 +1708,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                                 ConstraintCategory::UseAsConst
                             }
                         } else {
-                            ConstraintCategory::Return
+                            ConstraintCategory::Return(ReturnConstraint::Normal)
                         }
                     }
                     Some(l) if !body.local_decls[l].is_user_variable() => {
@@ -2489,6 +2494,19 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         );
 
         let mut cursor = borrowed_place.projection.as_ref();
+        let tcx = self.infcx.tcx;
+        let field = path_utils::is_upvar_field_projection(
+            tcx,
+            &self.borrowck_context.upvars,
+            borrowed_place.as_ref(),
+            body,
+        );
+        let category = if let Some(field) = field {
+            ConstraintCategory::ClosureUpvar(self.borrowck_context.upvars[field.index()].var_hir_id)
+        } else {
+            ConstraintCategory::Boring
+        };
+
         while let [proj_base @ .., elem] = cursor {
             cursor = proj_base;
 
@@ -2496,7 +2514,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
             match elem {
                 ProjectionElem::Deref => {
-                    let tcx = self.infcx.tcx;
                     let base_ty = Place::ty_from(borrowed_place.local, proj_base, body, tcx).ty;
 
                     debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
@@ -2506,7 +2523,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                                 sup: ref_region.to_region_vid(),
                                 sub: borrow_region.to_region_vid(),
                                 locations: location.to_locations(),
-                                category: ConstraintCategory::Boring,
+                                category,
                             });
 
                             match mutbl {
diff --git a/src/librustc_mir/const_eval/error.rs b/src/librustc_mir/const_eval/error.rs
index b165a69433d..5deae94fe0c 100644
--- a/src/librustc_mir/const_eval/error.rs
+++ b/src/librustc_mir/const_eval/error.rs
@@ -2,7 +2,7 @@ use std::error::Error;
 use std::fmt;
 
 use rustc_middle::mir::AssertKind;
-use rustc_span::Symbol;
+use rustc_span::{Span, Symbol};
 
 use super::InterpCx;
 use crate::interpret::{ConstEvalErr, InterpErrorInfo, Machine};
@@ -53,8 +53,9 @@ impl Error for ConstEvalErrKind {}
 pub fn error_to_const_error<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>(
     ecx: &InterpCx<'mir, 'tcx, M>,
     error: InterpErrorInfo<'tcx>,
+    span: Option<Span>,
 ) -> ConstEvalErr<'tcx> {
     error.print_backtrace();
     let stacktrace = ecx.generate_stacktrace();
-    ConstEvalErr { error: error.kind, stacktrace, span: ecx.tcx.span }
+    ConstEvalErr { error: error.kind, stacktrace, span: span.unwrap_or_else(|| ecx.cur_span()) }
 }
diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs
index 695e0741e35..d62300b3f55 100644
--- a/src/librustc_mir/const_eval/eval_queries.rs
+++ b/src/librustc_mir/const_eval/eval_queries.rs
@@ -27,7 +27,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
     body: &'mir mir::Body<'tcx>,
 ) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
     debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env);
-    let tcx = ecx.tcx.tcx;
+    let tcx = *ecx.tcx;
     let layout = ecx.layout_of(body.return_ty().subst(tcx, cid.instance.substs))?;
     assert!(!layout.is_unsized());
     let ret = ecx.allocate(layout, MemoryKind::Stack);
@@ -81,13 +81,14 @@ fn eval_body_using_ecx<'mir, 'tcx>(
 /// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
 pub(super) fn mk_eval_cx<'mir, 'tcx>(
     tcx: TyCtxt<'tcx>,
-    span: Span,
+    root_span: Span,
     param_env: ty::ParamEnv<'tcx>,
     can_access_statics: bool,
 ) -> CompileTimeEvalContext<'mir, 'tcx> {
     debug!("mk_eval_cx: {:?}", param_env);
     InterpCx::new(
-        tcx.at(span),
+        tcx,
+        root_span,
         param_env,
         CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
         MemoryExtra { can_access_statics },
@@ -163,7 +164,7 @@ pub(super) fn op_to_const<'tcx>(
                         0,
                     ),
                 };
-                let len = b.to_machine_usize(&ecx.tcx.tcx).unwrap();
+                let len = b.to_machine_usize(ecx).unwrap();
                 let start = start.try_into().unwrap();
                 let len: usize = len.try_into().unwrap();
                 ConstValue::Slice { data, start, end: start + len }
@@ -212,7 +213,7 @@ fn validate_and_turn_into_const<'tcx>(
     })();
 
     val.map_err(|error| {
-        let err = error_to_const_error(&ecx, error);
+        let err = error_to_const_error(&ecx, error, None);
         err.struct_error(ecx.tcx, "it is undefined behavior to use this value", |mut diag| {
             diag.note(note_on_undefined_behavior_error());
             diag.emit();
@@ -299,9 +300,9 @@ pub fn const_eval_raw_provider<'tcx>(
 
     let is_static = tcx.is_static(def_id);
 
-    let span = tcx.def_span(cid.instance.def_id());
     let mut ecx = InterpCx::new(
-        tcx.at(span),
+        tcx,
+        tcx.def_span(cid.instance.def_id()),
         key.param_env,
         CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
         MemoryExtra { can_access_statics: is_static },
@@ -309,16 +310,17 @@ pub fn const_eval_raw_provider<'tcx>(
 
     let res = ecx.load_mir(cid.instance.def, cid.promoted);
     res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body))
-        .and_then(|place| {
-            Ok(RawConst { alloc_id: place.ptr.assert_ptr().alloc_id, ty: place.layout.ty })
-        })
+        .map(|place| RawConst { alloc_id: place.ptr.assert_ptr().alloc_id, ty: place.layout.ty })
         .map_err(|error| {
-            let err = error_to_const_error(&ecx, error);
+            let err = error_to_const_error(&ecx, error, None);
             // errors in statics are always emitted as fatal errors
             if is_static {
                 // Ensure that if the above error was either `TooGeneric` or `Reported`
                 // an error must be reported.
-                let v = err.report_as_error(ecx.tcx, "could not evaluate static initializer");
+                let v = err.report_as_error(
+                    ecx.tcx.at(ecx.cur_span()),
+                    "could not evaluate static initializer",
+                );
 
                 // If this is `Reveal:All`, then we need to make sure an error is reported but if
                 // this is `Reveal::UserFacing`, then it's expected that we could get a
@@ -374,13 +376,16 @@ pub fn const_eval_raw_provider<'tcx>(
                         // anything else (array lengths, enum initializers, constant patterns) are
                         // reported as hard errors
                         } else {
-                            err.report_as_error(ecx.tcx, "evaluation of constant value failed")
+                            err.report_as_error(
+                                ecx.tcx.at(ecx.cur_span()),
+                                "evaluation of constant value failed",
+                            )
                         }
                     }
                 }
             } else {
                 // use of broken constant from other crate
-                err.report_as_error(ecx.tcx, "could not evaluate constant")
+                err.report_as_error(ecx.tcx.at(ecx.cur_span()), "could not evaluate constant")
             }
         })
 }
diff --git a/src/librustc_mir/dataflow/framework/direction.rs b/src/librustc_mir/dataflow/framework/direction.rs
index da4ad9b6168..6c9cb529dc2 100644
--- a/src/librustc_mir/dataflow/framework/direction.rs
+++ b/src/librustc_mir/dataflow/framework/direction.rs
@@ -467,7 +467,7 @@ impl Direction for Forward {
                 propagate(target, exit_state);
             }
 
-            Call { cleanup, destination, ref func, ref args, from_hir_call: _ } => {
+            Call { cleanup, destination, ref func, ref args, from_hir_call: _, fn_span: _ } => {
                 if let Some(unwind) = cleanup {
                     if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) {
                         propagate(unwind, exit_state);
diff --git a/src/librustc_mir/dataflow/framework/tests.rs b/src/librustc_mir/dataflow/framework/tests.rs
index 3ed0a9594e7..9349f5133a5 100644
--- a/src/librustc_mir/dataflow/framework/tests.rs
+++ b/src/librustc_mir/dataflow/framework/tests.rs
@@ -41,6 +41,7 @@ fn mock_body() -> mir::Body<'static> {
             destination: Some((dummy_place.clone(), mir::START_BLOCK)),
             cleanup: None,
             from_hir_call: false,
+            fn_span: DUMMY_SP,
         },
     );
     block(3, mir::TerminatorKind::Return);
@@ -53,6 +54,7 @@ fn mock_body() -> mir::Body<'static> {
             destination: Some((dummy_place.clone(), mir::START_BLOCK)),
             cleanup: None,
             from_hir_call: false,
+            fn_span: DUMMY_SP,
         },
     );
 
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index c0ab356756a..41c7bd95a96 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -401,6 +401,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
                 ref destination,
                 cleanup: _,
                 from_hir_call: _,
+                fn_span: _,
             } => {
                 self.gather_operand(func);
                 for arg in args {
@@ -438,7 +439,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
                             }
                         }
                         InlineAsmOperand::SymFn { value: _ }
-                        | InlineAsmOperand::SymStatic { value: _ } => {}
+                        | InlineAsmOperand::SymStatic { def_id: _ } => {}
                     }
                 }
             }
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index 0fd695586eb..cfe856abe36 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -268,11 +268,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             (&ty::Array(_, length), &ty::Slice(_)) => {
                 let ptr = self.read_immediate(src)?.to_scalar()?;
                 // u64 cast is from usize to u64, which is always good
-                let val = Immediate::new_slice(
-                    ptr,
-                    length.eval_usize(self.tcx.tcx, self.param_env),
-                    self,
-                );
+                let val =
+                    Immediate::new_slice(ptr, length.eval_usize(*self.tcx, self.param_env), self);
                 self.write_immediate(val, dest)
             }
             (&ty::Dynamic(..), &ty::Dynamic(..)) => {
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 6497e211de3..22f4691c22b 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -33,6 +33,8 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
     pub machine: M,
 
     /// The results of the type checker, from rustc.
+    /// The span in this is the "root" of the evaluation, i.e., the const
+    /// we are evaluating (if this is CTFE).
     pub tcx: TyCtxtAt<'tcx>,
 
     /// Bounds in scope for polymorphic evaluations.
@@ -171,15 +173,8 @@ impl<'mir, 'tcx, Tag> Frame<'mir, 'tcx, Tag> {
 
 impl<'mir, 'tcx, Tag, Extra> Frame<'mir, 'tcx, Tag, Extra> {
     /// Return the `SourceInfo` of the current instruction.
-    pub fn current_source_info(&self) -> Option<mir::SourceInfo> {
-        self.loc.map(|loc| {
-            let block = &self.body.basic_blocks()[loc.block];
-            if loc.statement_index < block.statements.len() {
-                block.statements[loc.statement_index].source_info
-            } else {
-                block.terminator().source_info
-            }
-        })
+    pub fn current_source_info(&self) -> Option<&mir::SourceInfo> {
+        self.loc.map(|loc| self.body.source_info(loc))
     }
 }
 
@@ -209,7 +204,7 @@ where
     }
 }
 
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf for InterpCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOf for InterpCx<'mir, 'tcx, M> {
     type Ty = Ty<'tcx>;
     type TyAndLayout = InterpResult<'tcx, TyAndLayout<'tcx>>;
 
@@ -292,14 +287,15 @@ pub(super) fn from_known_layout<'tcx>(
 
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     pub fn new(
-        tcx: TyCtxtAt<'tcx>,
+        tcx: TyCtxt<'tcx>,
+        root_span: Span,
         param_env: ty::ParamEnv<'tcx>,
         machine: M,
         memory_extra: M::MemoryExtra,
     ) -> Self {
         InterpCx {
             machine,
-            tcx,
+            tcx: tcx.at(root_span),
             param_env,
             memory: Memory::new(tcx, memory_extra),
             vtables: FxHashMap::default(),
@@ -307,9 +303,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     }
 
     #[inline(always)]
-    pub fn set_span(&mut self, span: Span) {
-        self.tcx.span = span;
-        self.memory.tcx.span = span;
+    pub fn cur_span(&self) -> Span {
+        self.stack()
+            .last()
+            .and_then(|f| f.current_source_info())
+            .map(|si| si.span)
+            .unwrap_or(self.tcx.span)
     }
 
     #[inline(always)]
@@ -392,7 +391,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
     #[inline]
     pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
-        ty.is_freeze(*self.tcx, self.param_env, DUMMY_SP)
+        ty.is_freeze(*self.tcx, self.param_env, self.tcx.span)
     }
 
     pub fn load_mir(
@@ -561,7 +560,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let size = size.align_to(align);
 
                 // Check if this brought us over the size limit.
-                if size.bytes() >= self.tcx.data_layout().obj_size_bound() {
+                if size.bytes() >= self.tcx.data_layout.obj_size_bound() {
                     throw_ub!(InvalidMeta("total size is bigger than largest supported object"));
                 }
                 Ok(Some((size, align)))
@@ -577,7 +576,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let elem = layout.field(self, 0)?;
 
                 // Make sure the slice is not too big.
-                let size = elem.size.checked_mul(len, &*self.tcx).ok_or_else(|| {
+                let size = elem.size.checked_mul(len, self).ok_or_else(|| {
                     err_ub!(InvalidMeta("slice is bigger than largest supported object"))
                 })?;
                 Ok(Some((size, elem.align.abi)))
diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs
index 02a7f24a1e3..3c724c79b40 100644
--- a/src/librustc_mir/interpret/intern.rs
+++ b/src/librustc_mir/interpret/intern.rs
@@ -111,7 +111,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
     if let InternMode::Static(mutability) = mode {
         // For this, we need to take into account `UnsafeCell`. When `ty` is `None`, we assume
         // no interior mutability.
-        let frozen = ty.map_or(true, |ty| ty.is_freeze(ecx.tcx.tcx, ecx.param_env, ecx.tcx.span));
+        let frozen = ty.map_or(true, |ty| ty.is_freeze(*ecx.tcx, ecx.param_env, ecx.tcx.span));
         // For statics, allocation mutability is the combination of the place mutability and
         // the type mutability.
         // The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere.
@@ -253,8 +253,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
                         // caused (by somehow getting a mutable reference in a `const`).
                         if ref_mutability == Mutability::Mut {
                             match referenced_ty.kind {
-                                ty::Array(_, n)
-                                    if n.eval_usize(tcx.tcx, self.ecx.param_env) == 0 => {}
+                                ty::Array(_, n) if n.eval_usize(*tcx, self.ecx.param_env) == 0 => {}
                                 ty::Slice(_)
                                     if mplace.meta.unwrap_meta().to_machine_usize(self.ecx)?
                                         == 0 => {}
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 115a472cabe..47e5b8b4fce 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -347,7 +347,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let index = u64::from(self.read_scalar(args[1])?.to_u32()?);
                 let elem = args[2];
                 let input = args[0];
-                let (len, e_ty) = input.layout.ty.simd_size_and_type(self.tcx.tcx);
+                let (len, e_ty) = input.layout.ty.simd_size_and_type(*self.tcx);
                 assert!(
                     index < len,
                     "Index `{}` must be in bounds of vector type `{}`: `[0, {})`",
@@ -374,7 +374,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
             sym::simd_extract => {
                 let index = u64::from(self.read_scalar(args[1])?.to_u32()?);
-                let (len, e_ty) = args[0].layout.ty.simd_size_and_type(self.tcx.tcx);
+                let (len, e_ty) = args[0].layout.ty.simd_size_and_type(*self.tcx);
                 assert!(
                     index < len,
                     "index `{}` is out-of-bounds of vector type `{}` with length `{}`",
diff --git a/src/librustc_mir/interpret/intrinsics/caller_location.rs b/src/librustc_mir/interpret/intrinsics/caller_location.rs
index 91b046d7bb2..9adef8c43c7 100644
--- a/src/librustc_mir/interpret/intrinsics/caller_location.rs
+++ b/src/librustc_mir/interpret/intrinsics/caller_location.rs
@@ -1,6 +1,7 @@
 use std::convert::TryFrom;
 
 use rustc_hir::lang_items::PanicLocationLangItem;
+use rustc_middle::mir::TerminatorKind;
 use rustc_middle::ty::subst::Subst;
 use rustc_span::{Span, Symbol};
 use rustc_target::abi::LayoutOf;
@@ -14,19 +15,39 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
     /// frame which is not `#[track_caller]`.
     crate fn find_closest_untracked_caller_location(&self) -> Span {
-        self.stack()
+        let frame = self
+            .stack()
             .iter()
             .rev()
             // Find first non-`#[track_caller]` frame.
-            .find(|frame| !frame.instance.def.requires_caller_location(*self.tcx))
+            .find(|frame| {
+                debug!(
+                    "find_closest_untracked_caller_location: checking frame {:?}",
+                    frame.instance
+                );
+                !frame.instance.def.requires_caller_location(*self.tcx)
+            })
             // Assert that there is always such a frame.
-            .unwrap()
-            .current_source_info()
-            // Assert that the frame we look at is actually executing code currently
-            // (`current_source_info` is None when we are unwinding and the frame does
-            // not require cleanup).
-            .unwrap()
-            .span
+            .unwrap();
+        // Assert that the frame we look at is actually executing code currently
+        // (`current_source_info` is None when we are unwinding and the frame does
+        // not require cleanup).
+        let loc = frame.loc.unwrap();
+        // If this is a `Call` terminator, use the `fn_span` instead.
+        let block = &frame.body.basic_blocks()[loc.block];
+        if loc.statement_index == block.statements.len() {
+            debug!(
+                "find_closest_untracked_caller_location:: got terminator {:?} ({:?})",
+                block.terminator(),
+                block.terminator().kind
+            );
+            if let TerminatorKind::Call { fn_span, .. } = block.terminator().kind {
+                return fn_span;
+            }
+        }
+        // This is a different terminator (such as `Drop`) or not a terminator at all
+        // (such as `box`). Use the normal span.
+        frame.body.source_info(loc).span
     }
 
     /// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index d7f64542aa7..8af1a8ac608 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -14,7 +14,7 @@ use std::ptr;
 
 use rustc_ast::ast::Mutability;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_middle::ty::{self, query::TyCtxtAt, Instance, ParamEnv};
+use rustc_middle::ty::{self, Instance, ParamEnv, TyCtxt};
 use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
 
 use super::{
@@ -115,7 +115,7 @@ pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
     pub extra: M::MemoryExtra,
 
     /// Lets us implement `HasDataLayout`, which is awfully convenient.
-    pub tcx: TyCtxtAt<'tcx>,
+    pub tcx: TyCtxt<'tcx>,
 }
 
 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for Memory<'mir, 'tcx, M> {
@@ -126,7 +126,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for Memory<'mir, 'tcx, M>
 }
 
 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
-    pub fn new(tcx: TyCtxtAt<'tcx>, extra: M::MemoryExtra) -> Self {
+    pub fn new(tcx: TyCtxt<'tcx>, extra: M::MemoryExtra) -> Self {
         Memory {
             alloc_map: M::MemoryMap::default(),
             extra_fn_ptr_map: FxHashMap::default(),
@@ -425,7 +425,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     /// `M::tag_allocation`.
     fn get_global_alloc(
         memory_extra: &M::MemoryExtra,
-        tcx: TyCtxtAt<'tcx>,
+        tcx: TyCtxt<'tcx>,
         id: AllocId,
         is_write: bool,
     ) -> InterpResult<'tcx, Cow<'tcx, Allocation<M::PointerTag, M::AllocExtra>>> {
@@ -455,7 +455,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
                     throw_unsup!(ReadForeignStatic(def_id))
                 }
                 trace!("get_global_alloc: Need to compute {:?}", def_id);
-                let instance = Instance::mono(tcx.tcx, def_id);
+                let instance = Instance::mono(tcx, def_id);
                 let gid = GlobalId { instance, promoted: None };
                 // Use the raw query here to break validation cycles. Later uses of the static
                 // will call the full query anyway.
@@ -664,14 +664,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     pub fn dump_allocs(&self, mut allocs: Vec<AllocId>) {
         // Cannot be a closure because it is generic in `Tag`, `Extra`.
         fn write_allocation_track_relocs<'tcx, Tag: Copy + fmt::Debug, Extra>(
-            tcx: TyCtxtAt<'tcx>,
+            tcx: TyCtxt<'tcx>,
             allocs_to_print: &mut VecDeque<AllocId>,
             alloc: &Allocation<Tag, Extra>,
         ) {
             for &(_, target_id) in alloc.relocations().values() {
                 allocs_to_print.push_back(target_id);
             }
-            pretty::write_allocation(tcx.tcx, alloc, &mut std::io::stderr()).unwrap();
+            pretty::write_allocation(tcx, alloc, &mut std::io::stderr()).unwrap();
         }
 
         allocs.sort();
@@ -820,7 +820,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
                 return Ok(());
             }
         };
-        let tcx = self.tcx.tcx;
+        let tcx = self.tcx;
         self.get_raw_mut(ptr.alloc_id)?.write_bytes(&tcx, ptr, src)
     }
 
@@ -846,7 +846,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
                 return Ok(());
             }
         };
-        let tcx = self.tcx.tcx;
+        let tcx = self.tcx;
         let allocation = self.get_raw_mut(ptr.alloc_id)?;
 
         for idx in 0..len {
@@ -888,7 +888,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         let relocations =
             self.get_raw(src.alloc_id)?.prepare_relocation_copy(self, src, size, dest, length);
 
-        let tcx = self.tcx.tcx;
+        let tcx = self.tcx;
 
         // This checks relocation edges on the src.
         let src_bytes =
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index db4473154c4..38f5988d0eb 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -651,12 +651,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 // Convert discriminant to variant index, and catch invalid discriminants.
                 let index = match op.layout.ty.kind {
                     ty::Adt(adt, _) => {
-                        adt.discriminants(self.tcx.tcx).find(|(_, var)| var.val == discr_bits)
+                        adt.discriminants(*self.tcx).find(|(_, var)| var.val == discr_bits)
                     }
                     ty::Generator(def_id, substs, _) => {
                         let substs = substs.as_generator();
                         substs
-                            .discriminants(def_id, self.tcx.tcx)
+                            .discriminants(def_id, *self.tcx)
                             .find(|(_, var)| var.val == discr_bits)
                     }
                     _ => bug!("tagged layout for non-adt non-generator"),
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 3f0800b12b5..24b191e9b53 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -404,7 +404,10 @@ where
                     // 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"),
+                None => span_bug!(
+                    self.cur_span(),
+                    "cannot compute offset for extern type field at non-0 offset"
+                ),
             };
             (base.meta, offset.align_to(align))
         } else {
@@ -440,7 +443,11 @@ where
                 assert!(!field_layout.is_unsized());
                 base.offset(offset, MemPlaceMeta::None, field_layout, self)
             }
-            _ => bug!("`mplace_index` called on non-array type {:?}", base.layout.ty),
+            _ => span_bug!(
+                self.cur_span(),
+                "`mplace_index` called on non-array type {:?}",
+                base.layout.ty
+            ),
         }
     }
 
@@ -454,7 +461,7 @@ where
         let len = base.len(self)?; // also asserts that we have a type where this makes sense
         let stride = match base.layout.fields {
             FieldsShape::Array { stride, .. } => stride,
-            _ => bug!("mplace_array_fields: expected an array layout"),
+            _ => span_bug!(self.cur_span(), "mplace_array_fields: expected an array layout"),
         };
         let layout = base.layout.field(self, 0)?;
         let dl = &self.tcx.data_layout;
@@ -484,7 +491,9 @@ where
         // (that have count 0 in their layout).
         let from_offset = match base.layout.fields {
             FieldsShape::Array { stride, .. } => stride * from, // `Size` multiplication is checked
-            _ => bug!("Unexpected layout of index access: {:#?}", base.layout),
+            _ => {
+                span_bug!(self.cur_span(), "unexpected layout of index access: {:#?}", base.layout)
+            }
         };
 
         // Compute meta and new layout
@@ -497,7 +506,9 @@ where
                 let len = Scalar::from_machine_usize(inner_len, self);
                 (MemPlaceMeta::Meta(len), base.layout.ty)
             }
-            _ => bug!("cannot subslice non-array type: `{:?}`", base.layout.ty),
+            _ => {
+                span_bug!(self.cur_span(), "cannot subslice non-array type: `{:?}`", base.layout.ty)
+            }
         };
         let layout = self.layout_of(ty)?;
         base.offset(from_offset, meta, layout, self)
@@ -768,7 +779,7 @@ where
             None => return Ok(()), // zero-sized access
         };
 
-        let tcx = &*self.tcx;
+        let tcx = *self.tcx;
         // FIXME: We should check that there are dest.layout.size many bytes available in
         // memory.  The code below is not sufficient, with enough padding it might not
         // cover all the bytes!
@@ -776,12 +787,14 @@ where
             Immediate::Scalar(scalar) => {
                 match dest.layout.abi {
                     Abi::Scalar(_) => {} // fine
-                    _ => {
-                        bug!("write_immediate_to_mplace: invalid Scalar layout: {:#?}", dest.layout)
-                    }
+                    _ => span_bug!(
+                        self.cur_span(),
+                        "write_immediate_to_mplace: invalid Scalar layout: {:#?}",
+                        dest.layout
+                    ),
                 }
                 self.memory.get_raw_mut(ptr.alloc_id)?.write_scalar(
-                    tcx,
+                    &tcx,
                     ptr,
                     scalar,
                     dest.layout.size,
@@ -793,7 +806,8 @@ where
                 // which `ptr.offset(b_offset)` cannot possibly fail to satisfy.
                 let (a, b) = match dest.layout.abi {
                     Abi::ScalarPair(ref a, ref b) => (&a.value, &b.value),
-                    _ => bug!(
+                    _ => span_bug!(
+                        self.cur_span(),
                         "write_immediate_to_mplace: invalid ScalarPair layout: {:#?}",
                         dest.layout
                     ),
@@ -806,8 +820,8 @@ where
                 // but that does not work: We could be a newtype around a pair, then the
                 // fields do not match the `ScalarPair` components.
 
-                self.memory.get_raw_mut(ptr.alloc_id)?.write_scalar(tcx, ptr, a_val, a_size)?;
-                self.memory.get_raw_mut(b_ptr.alloc_id)?.write_scalar(tcx, b_ptr, b_val, b_size)
+                self.memory.get_raw_mut(ptr.alloc_id)?.write_scalar(&tcx, ptr, a_val, a_size)?;
+                self.memory.get_raw_mut(b_ptr.alloc_id)?.write_scalar(&tcx, b_ptr, b_val, b_size)
             }
         }
     }
@@ -841,9 +855,9 @@ where
     ) -> InterpResult<'tcx> {
         // We do NOT compare the types for equality, because well-typed code can
         // actually "transmute" `&mut T` to `&T` in an assignment without a cast.
-        if !mir_assign_valid_types(self.tcx.tcx, src.layout, dest.layout) {
+        if !mir_assign_valid_types(*self.tcx, src.layout, dest.layout) {
             span_bug!(
-                self.tcx.span,
+                self.cur_span(),
                 "type mismatch when copying!\nsrc: {:?},\ndest: {:?}",
                 src.layout.ty,
                 dest.layout.ty,
@@ -898,7 +912,7 @@ where
         src: OpTy<'tcx, M::PointerTag>,
         dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx> {
-        if mir_assign_valid_types(self.tcx.tcx, src.layout, dest.layout) {
+        if mir_assign_valid_types(*self.tcx, src.layout, dest.layout) {
             // Fast path: Just use normal `copy_op`
             return self.copy_op(src, dest);
         }
@@ -910,7 +924,7 @@ where
             // on `typeck_tables().has_errors` at all const eval entry points.
             debug!("Size mismatch when transmuting!\nsrc: {:#?}\ndest: {:#?}", src, dest);
             self.tcx.sess.delay_span_bug(
-                self.tcx.span,
+                self.cur_span(),
                 "size-changing transmute, should have been caught by transmute checking",
             );
             throw_inval!(TransmuteSizeDiff(src.layout.ty, dest.layout.ty));
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index 02a709ab1a1..16c6396799e 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -76,7 +76,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
     fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> {
         info!("{:?}", stmt);
-        self.set_span(stmt.source_info.span);
 
         use rustc_middle::mir::StatementKind::*;
 
@@ -279,7 +278,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
     fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> InterpResult<'tcx> {
         info!("{:?}", terminator.kind);
-        self.set_span(terminator.source_info.span);
 
         self.eval_terminator(terminator)?;
         if !self.stack().is_empty() {
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index 4a63884be4c..cd7621ea975 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -56,6 +56,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 destination,
                 ref cleanup,
                 from_hir_call: _from_hir_call,
+                fn_span: _,
             } => {
                 let old_stack = self.frame_idx();
                 let old_loc = self.frame().loc;
diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs
index b9f9d37df76..a1d124bb760 100644
--- a/src/librustc_mir/interpret/traits.rs
+++ b/src/librustc_mir/interpret/traits.rs
@@ -2,7 +2,7 @@ use std::convert::TryFrom;
 
 use rustc_middle::mir::interpret::{InterpResult, Pointer, PointerArithmetic, Scalar};
 use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
-use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size};
+use rustc_target::abi::{Align, LayoutOf, Size};
 
 use super::{FnVal, InterpCx, Machine, MemoryKind};
 
@@ -49,8 +49,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let size = layout.size.bytes();
         let align = layout.align.abi.bytes();
 
+        let tcx = *self.tcx;
         let ptr_size = self.pointer_size();
-        let ptr_align = self.tcx.data_layout.pointer_align.abi;
+        let ptr_align = tcx.data_layout.pointer_align.abi;
         // /////////////////////////////////////////////////////////////////////////////////////////
         // If you touch this code, be sure to also make the corresponding changes to
         // `get_vtable` in `rust_codegen_llvm/meth.rs`.
@@ -60,33 +61,32 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             ptr_align,
             MemoryKind::Vtable,
         );
-        let tcx = &*self.tcx;
 
-        let drop = Instance::resolve_drop_in_place(*tcx, ty);
+        let drop = Instance::resolve_drop_in_place(tcx, ty);
         let drop = self.memory.create_fn_alloc(FnVal::Instance(drop));
 
         // No need to do any alignment checks on the memory accesses below, because we know the
         // allocation is correctly aligned as we created it above. Also we're only offsetting by
         // multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`.
         let vtable_alloc = self.memory.get_raw_mut(vtable.alloc_id)?;
-        vtable_alloc.write_ptr_sized(tcx, vtable, drop.into())?;
+        vtable_alloc.write_ptr_sized(&tcx, vtable, drop.into())?;
 
-        let size_ptr = vtable.offset(ptr_size, tcx)?;
-        vtable_alloc.write_ptr_sized(tcx, size_ptr, Scalar::from_uint(size, ptr_size).into())?;
-        let align_ptr = vtable.offset(ptr_size * 2, tcx)?;
-        vtable_alloc.write_ptr_sized(tcx, align_ptr, Scalar::from_uint(align, ptr_size).into())?;
+        let size_ptr = vtable.offset(ptr_size, &tcx)?;
+        vtable_alloc.write_ptr_sized(&tcx, size_ptr, Scalar::from_uint(size, ptr_size).into())?;
+        let align_ptr = vtable.offset(ptr_size * 2, &tcx)?;
+        vtable_alloc.write_ptr_sized(&tcx, align_ptr, Scalar::from_uint(align, ptr_size).into())?;
 
         for (i, method) in methods.iter().enumerate() {
             if let Some((def_id, substs)) = *method {
                 // resolve for vtable: insert shims where needed
                 let instance =
-                    ty::Instance::resolve_for_vtable(*tcx, self.param_env, def_id, substs)
+                    ty::Instance::resolve_for_vtable(tcx, self.param_env, def_id, substs)
                         .ok_or_else(|| err_inval!(TooGeneric))?;
                 let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance));
                 // We cannot use `vtable_allic` as we are creating fn ptrs in this loop.
-                let method_ptr = vtable.offset(ptr_size * (3 + i as u64), tcx)?;
+                let method_ptr = vtable.offset(ptr_size * (3 + i as u64), &tcx)?;
                 self.memory.get_raw_mut(vtable.alloc_id)?.write_ptr_sized(
-                    tcx,
+                    &tcx,
                     method_ptr,
                     fn_ptr.into(),
                 )?;
@@ -171,7 +171,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             alloc.read_ptr_sized(self, vtable.offset(pointer_size * 2, self)?)?.not_undef()?;
         let align = u64::try_from(self.force_bits(align, pointer_size)?).unwrap();
 
-        if size >= self.tcx.data_layout().obj_size_bound() {
+        if size >= self.tcx.data_layout.obj_size_bound() {
             throw_ub_format!(
                 "invalid vtable: \
                 size is bigger than largest supported object"
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index f3d3666b99f..994d1e69f2e 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -634,9 +634,19 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
             }
             mir::TerminatorKind::InlineAsm { ref operands, .. } => {
                 for op in operands {
-                    if let mir::InlineAsmOperand::SymFn { value } = op {
-                        let fn_ty = self.monomorphize(value.literal.ty);
-                        visit_fn_use(self.tcx, fn_ty, false, &mut self.output);
+                    match *op {
+                        mir::InlineAsmOperand::SymFn { ref value } => {
+                            let fn_ty = self.monomorphize(value.literal.ty);
+                            visit_fn_use(self.tcx, fn_ty, false, &mut self.output);
+                        }
+                        mir::InlineAsmOperand::SymStatic { def_id } => {
+                            let instance = Instance::mono(self.tcx, def_id);
+                            if should_monomorphize_locally(self.tcx, &instance) {
+                                trace!("collecting asm sym static {:?}", def_id);
+                                self.output.push(MonoItem::Static(def_id));
+                            }
+                        }
+                        _ => {}
                     }
                 }
             }
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index b439e919050..f95fd9b9e90 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -460,6 +460,7 @@ impl CloneShimBuilder<'tcx> {
                 destination: Some((dest, next)),
                 cleanup: Some(cleanup),
                 from_hir_call: true,
+                fn_span: self.span,
             },
             false,
         );
@@ -788,6 +789,7 @@ fn build_call_shim<'tcx>(
                 None
             },
             from_hir_call: true,
+            fn_span: span,
         },
         false,
     );
diff --git a/src/librustc_mir/transform/check_consts/mod.rs b/src/librustc_mir/transform/check_consts/mod.rs
index 7c439f80ef6..e4aa88e3c20 100644
--- a/src/librustc_mir/transform/check_consts/mod.rs
+++ b/src/librustc_mir/transform/check_consts/mod.rs
@@ -12,6 +12,7 @@ use rustc_middle::ty::{self, TyCtxt};
 pub use self::qualifs::Qualif;
 
 mod ops;
+pub mod post_drop_elaboration;
 pub mod qualifs;
 mod resolver;
 pub mod validation;
diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs
index 92bd740e27a..d5059c98c95 100644
--- a/src/librustc_mir/transform/check_consts/ops.rs
+++ b/src/librustc_mir/transform/check_consts/ops.rs
@@ -10,6 +10,22 @@ use rustc_span::{Span, Symbol};
 
 use super::ConstCx;
 
+/// Emits an error if `op` is not allowed in the given const context.
+pub fn non_const<O: NonConstOp>(ccx: &ConstCx<'_, '_>, op: O, span: Span) {
+    debug!("illegal_op: op={:?}", op);
+
+    if op.is_allowed_in_item(ccx) {
+        return;
+    }
+
+    if ccx.tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you {
+        ccx.tcx.sess.miri_unleashed_feature(span, O::feature_gate());
+        return;
+    }
+
+    op.emit_error(ccx, span);
+}
+
 /// An operation that is not *always* allowed in a const context.
 pub trait NonConstOp: std::fmt::Debug {
     /// Returns the `Symbol` corresponding to the feature gate that would enable this operation,
diff --git a/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs b/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs
new file mode 100644
index 00000000000..226e0e2049e
--- /dev/null
+++ b/src/librustc_mir/transform/check_consts/post_drop_elaboration.rs
@@ -0,0 +1,119 @@
+use rustc_hir::def_id::LocalDefId;
+use rustc_middle::mir::visit::Visitor;
+use rustc_middle::mir::{self, BasicBlock, Location};
+use rustc_middle::ty::TyCtxt;
+use rustc_span::Span;
+
+use super::ops;
+use super::qualifs::{NeedsDrop, Qualif};
+use super::validation::Qualifs;
+use super::ConstCx;
+
+/// Returns `true` if we should use the more precise live drop checker that runs after drop
+/// elaboration.
+pub fn checking_enabled(tcx: TyCtxt<'tcx>) -> bool {
+    tcx.features().const_precise_live_drops
+}
+
+/// Look for live drops in a const context.
+///
+/// This is separate from the rest of the const checking logic because it must run after drop
+/// elaboration.
+pub fn check_live_drops(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &mir::Body<'tcx>) {
+    let const_kind = tcx.hir().body_const_context(def_id);
+    if const_kind.is_none() {
+        return;
+    }
+
+    if !checking_enabled(tcx) {
+        return;
+    }
+
+    let ccx = ConstCx {
+        body,
+        tcx,
+        def_id: def_id.to_def_id(),
+        const_kind,
+        param_env: tcx.param_env(def_id),
+    };
+
+    let mut visitor = CheckLiveDrops { ccx: &ccx, qualifs: Qualifs::default() };
+
+    visitor.visit_body(body);
+}
+
+struct CheckLiveDrops<'mir, 'tcx> {
+    ccx: &'mir ConstCx<'mir, 'tcx>,
+    qualifs: Qualifs<'mir, 'tcx>,
+}
+
+// So we can access `body` and `tcx`.
+impl std::ops::Deref for CheckLiveDrops<'mir, 'tcx> {
+    type Target = ConstCx<'mir, 'tcx>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.ccx
+    }
+}
+
+impl CheckLiveDrops<'mir, 'tcx> {
+    fn check_live_drop(&self, span: Span) {
+        ops::non_const(self.ccx, ops::LiveDrop, span);
+    }
+}
+
+impl Visitor<'tcx> for CheckLiveDrops<'mir, 'tcx> {
+    fn visit_basic_block_data(&mut self, bb: BasicBlock, block: &mir::BasicBlockData<'tcx>) {
+        trace!("visit_basic_block_data: bb={:?} is_cleanup={:?}", bb, block.is_cleanup);
+
+        // Ignore drop terminators in cleanup blocks.
+        if block.is_cleanup {
+            return;
+        }
+
+        self.super_basic_block_data(bb, block);
+    }
+
+    fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) {
+        trace!("visit_terminator: terminator={:?} location={:?}", terminator, location);
+
+        match &terminator.kind {
+            mir::TerminatorKind::Drop { location: dropped_place, .. } => {
+                let dropped_ty = dropped_place.ty(self.body, self.tcx).ty;
+                if !NeedsDrop::in_any_value_of_ty(self.ccx, dropped_ty) {
+                    return;
+                }
+
+                if dropped_place.is_indirect() {
+                    self.check_live_drop(terminator.source_info.span);
+                    return;
+                }
+
+                if self.qualifs.needs_drop(self.ccx, dropped_place.local, location) {
+                    // Use the span where the dropped local was declared for the error.
+                    let span = self.body.local_decls[dropped_place.local].source_info.span;
+                    self.check_live_drop(span);
+                }
+            }
+
+            mir::TerminatorKind::DropAndReplace { .. } => span_bug!(
+                terminator.source_info.span,
+                "`DropAndReplace` should be removed by drop elaboration",
+            ),
+
+            mir::TerminatorKind::Abort
+            | mir::TerminatorKind::Call { .. }
+            | mir::TerminatorKind::Assert { .. }
+            | mir::TerminatorKind::FalseEdge { .. }
+            | mir::TerminatorKind::FalseUnwind { .. }
+            | mir::TerminatorKind::GeneratorDrop
+            | mir::TerminatorKind::Goto { .. }
+            | mir::TerminatorKind::InlineAsm { .. }
+            | mir::TerminatorKind::Resume
+            | mir::TerminatorKind::Return
+            | mir::TerminatorKind::SwitchInt { .. }
+            | mir::TerminatorKind::Unreachable
+            | mir::TerminatorKind::Yield { .. } => {}
+        }
+    }
+}
diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs
index 5d604d8e3d7..936c1a84e14 100644
--- a/src/librustc_mir/transform/check_consts/qualifs.rs
+++ b/src/librustc_mir/transform/check_consts/qualifs.rs
@@ -2,7 +2,6 @@
 //!
 //! See the `Qualif` trait for more info.
 
-use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
 use rustc_span::DUMMY_SP;
@@ -137,10 +136,7 @@ impl Qualif for CustomEq {
         substs: SubstsRef<'tcx>,
     ) -> bool {
         let ty = cx.tcx.mk_ty(ty::Adt(adt, substs));
-        let id = cx.tcx.hir().local_def_id_to_hir_id(cx.def_id.as_local().unwrap());
-        cx.tcx
-            .infer_ctxt()
-            .enter(|infcx| !traits::type_marked_structural(id, cx.body.span, &infcx, ty))
+        !ty.is_structural_eq_shallow(cx.tcx)
     }
 }
 
diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs
index ab87d70da7d..428a74bcdcb 100644
--- a/src/librustc_mir/transform/check_consts/validation.rs
+++ b/src/librustc_mir/transform/check_consts/validation.rs
@@ -40,7 +40,7 @@ pub struct Qualifs<'mir, 'tcx> {
 }
 
 impl Qualifs<'mir, 'tcx> {
-    fn indirectly_mutable(
+    pub fn indirectly_mutable(
         &mut self,
         ccx: &'mir ConstCx<'mir, 'tcx>,
         local: Local,
@@ -68,7 +68,7 @@ impl Qualifs<'mir, 'tcx> {
     /// Returns `true` if `local` is `NeedsDrop` at the given `Location`.
     ///
     /// Only updates the cursor if absolutely necessary
-    fn needs_drop(
+    pub fn needs_drop(
         &mut self,
         ccx: &'mir ConstCx<'mir, 'tcx>,
         local: Local,
@@ -95,7 +95,7 @@ impl Qualifs<'mir, 'tcx> {
     /// Returns `true` if `local` is `HasMutInterior` at the given `Location`.
     ///
     /// Only updates the cursor if absolutely necessary.
-    fn has_mut_interior(
+    pub fn has_mut_interior(
         &mut self,
         ccx: &'mir ConstCx<'mir, 'tcx>,
         local: Local,
@@ -232,30 +232,15 @@ impl Validator<'mir, 'tcx> {
         self.qualifs.in_return_place(self.ccx)
     }
 
-    /// Emits an error at the given `span` if an expression cannot be evaluated in the current
-    /// context.
-    pub fn check_op_spanned<O>(&mut self, op: O, span: Span)
-    where
-        O: NonConstOp,
-    {
-        debug!("check_op: op={:?}", op);
-
-        if op.is_allowed_in_item(self) {
-            return;
-        }
-
-        if self.tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you {
-            self.tcx.sess.miri_unleashed_feature(span, O::feature_gate());
-            return;
-        }
-
-        op.emit_error(self, span);
-    }
-
     /// Emits an error if an expression cannot be evaluated in the current context.
     pub fn check_op(&mut self, op: impl NonConstOp) {
-        let span = self.span;
-        self.check_op_spanned(op, span)
+        ops::non_const(self.ccx, op, self.span);
+    }
+
+    /// Emits an error at the given `span` if an expression cannot be evaluated in the current
+    /// context.
+    pub fn check_op_spanned(&mut self, op: impl NonConstOp, span: Span) {
+        ops::non_const(self.ccx, op, span);
     }
 
     fn check_static(&mut self, def_id: DefId, span: Span) {
@@ -577,6 +562,12 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
             // projections that cannot be `NeedsDrop`.
             TerminatorKind::Drop { location: dropped_place, .. }
             | TerminatorKind::DropAndReplace { location: dropped_place, .. } => {
+                // If we are checking live drops after drop-elaboration, don't emit duplicate
+                // errors here.
+                if super::post_drop_elaboration::checking_enabled(self.tcx) {
+                    return;
+                }
+
                 let mut err_span = self.span;
 
                 // Check to see if the type of this place can ever have a drop impl. If not, this
diff --git a/src/librustc_mir/transform/check_packed_ref.rs b/src/librustc_mir/transform/check_packed_ref.rs
index faad1a72327..043b2d0d170 100644
--- a/src/librustc_mir/transform/check_packed_ref.rs
+++ b/src/librustc_mir/transform/check_packed_ref.rs
@@ -51,7 +51,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PackedRefChecker<'a, 'tcx> {
                     lint_root,
                     source_info.span,
                     |lint| {
-                        lint.build(&format!("reference to packed field is unaligned",))
+                        lint.build("reference to packed field is unaligned")
                             .note(
                                 "fields of packed structs are not properly aligned, and creating \
                                 a misaligned reference is undefined behavior (even if that \
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 0ff60cbd55d..83ed2fc2d43 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -313,7 +313,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         let param_env = tcx.param_env(def_id).with_reveal_all();
 
         let span = tcx.def_span(def_id);
-        let mut ecx = InterpCx::new(tcx.at(span), param_env, ConstPropMachine::new(), ());
+        let mut ecx = InterpCx::new(tcx, span, param_env, ConstPropMachine::new(), ());
         let can_const_prop = CanConstProp::check(body);
 
         let ret = ecx
@@ -404,9 +404,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         match self.ecx.eval_const_to_op(c.literal, None) {
             Ok(op) => Some(op),
             Err(error) => {
-                // Make sure errors point at the constant.
-                self.ecx.set_span(c.span);
-                let err = error_to_const_error(&self.ecx, error);
+                let tcx = self.ecx.tcx.at(c.span);
+                let err = error_to_const_error(&self.ecx, error, Some(c.span));
                 if let Some(lint_root) = self.lint_root(source_info) {
                     let lint_only = match c.literal.val {
                         // Promoteds must lint and not error as the user didn't ask for them
@@ -418,17 +417,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                     if lint_only {
                         // Out of backwards compatibility we cannot report hard errors in unused
                         // generic functions using associated constants of the generic parameters.
-                        err.report_as_lint(
-                            self.ecx.tcx,
-                            "erroneous constant used",
-                            lint_root,
-                            Some(c.span),
-                        );
+                        err.report_as_lint(tcx, "erroneous constant used", lint_root, Some(c.span));
                     } else {
-                        err.report_as_error(self.ecx.tcx, "erroneous constant used");
+                        err.report_as_error(tcx, "erroneous constant used");
                     }
                 } else {
-                    err.report_as_error(self.ecx.tcx, "erroneous constant used");
+                    err.report_as_error(tcx, "erroneous constant used");
                 }
                 None
             }
@@ -511,6 +505,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
             // This is basically `force_bits`.
             let r_bits = r_bits.and_then(|r| r.to_bits_or_ptr(right_size, &self.tcx).ok());
             if r_bits.map_or(false, |b| b >= left_size_bits as u128) {
+                debug!("check_binary_op: reporting assert for {:?}", source_info);
                 self.report_assert_as_lint(
                     lint::builtin::ARITHMETIC_OVERFLOW,
                     source_info,
@@ -851,7 +846,6 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
     fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) {
         trace!("visit_statement: {:?}", statement);
         let source_info = statement.source_info;
-        self.ecx.set_span(source_info.span);
         self.source_info = Some(source_info);
         if let StatementKind::Assign(box (place, ref mut rval)) = statement.kind {
             let place_ty: Ty<'tcx> = place.ty(&self.local_decls, self.tcx).ty;
@@ -864,7 +858,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
                         if let Some(value) = self.get_const(place) {
                             if self.should_const_prop(value) {
                                 trace!("replacing {:?} with {:?}", rval, value);
-                                self.replace_with_const(rval, value, statement.source_info);
+                                self.replace_with_const(rval, value, source_info);
                                 if can_const_prop == ConstPropMode::FullConstProp
                                     || can_const_prop == ConstPropMode::OnlyInsideOwnBlock
                                 {
@@ -927,7 +921,6 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
 
     fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) {
         let source_info = terminator.source_info;
-        self.ecx.set_span(source_info.span);
         self.source_info = Some(source_info);
         self.super_terminator(terminator, location);
         match &mut terminator.kind {
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 26725a2ac02..4240b528a61 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -49,6 +49,7 @@ pub(crate) fn provide(providers: &mut Providers<'_>) {
         mir_const,
         mir_const_qualif,
         mir_validated,
+        mir_drops_elaborated_and_const_checked,
         optimized_mir,
         is_mir_available,
         promoted_mir,
@@ -294,12 +295,31 @@ fn mir_validated(
     (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted))
 }
 
-fn run_optimization_passes<'tcx>(
+fn mir_drops_elaborated_and_const_checked<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: LocalDefId,
+) -> Steal<Body<'tcx>> {
+    // (Mir-)Borrowck uses `mir_validated`, so we have to force it to
+    // execute before we can steal.
+    tcx.ensure().mir_borrowck(def_id);
+
+    let (body, _) = tcx.mir_validated(def_id);
+    let mut body = body.steal();
+
+    run_post_borrowck_cleanup_passes(tcx, &mut body, def_id, None);
+    check_consts::post_drop_elaboration::check_live_drops(tcx, def_id, &body);
+    tcx.alloc_steal_mir(body)
+}
+
+/// After this series of passes, no lifetime analysis based on borrowing can be done.
+fn run_post_borrowck_cleanup_passes<'tcx>(
     tcx: TyCtxt<'tcx>,
     body: &mut Body<'tcx>,
     def_id: LocalDefId,
     promoted: Option<Promoted>,
 ) {
+    debug!("post_borrowck_cleanup({:?})", def_id);
+
     let post_borrowck_cleanup: &[&dyn MirPass<'tcx>] = &[
         // Remove all things only needed by analysis
         &no_landing_pads::NoLandingPads::new(tcx),
@@ -318,9 +338,24 @@ fn run_optimization_passes<'tcx>(
         // but before optimizations begin.
         &add_retag::AddRetag,
         &simplify::SimplifyCfg::new("elaborate-drops"),
-        // No lifetime analysis based on borrowing can be done from here on out.
     ];
 
+    run_passes(
+        tcx,
+        body,
+        InstanceDef::Item(def_id.to_def_id()),
+        promoted,
+        MirPhase::DropElab,
+        &[post_borrowck_cleanup],
+    );
+}
+
+fn run_optimization_passes<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    body: &mut Body<'tcx>,
+    def_id: LocalDefId,
+    promoted: Option<Promoted>,
+) {
     let optimizations: &[&dyn MirPass<'tcx>] = &[
         &unreachable_prop::UnreachablePropagation,
         &uninhabited_enum_branching::UninhabitedEnumBranching,
@@ -368,6 +403,7 @@ fn run_optimization_passes<'tcx>(
 
     let mir_opt_level = tcx.sess.opts.debugging_opts.mir_opt_level;
 
+    #[rustfmt::skip]
     run_passes(
         tcx,
         body,
@@ -375,7 +411,6 @@ fn run_optimization_passes<'tcx>(
         promoted,
         MirPhase::Optimized,
         &[
-            post_borrowck_cleanup,
             if mir_opt_level > 0 { optimizations } else { no_optimizations },
             pre_codegen_cleanup,
         ],
@@ -393,12 +428,7 @@ fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> {
 
     let def_id = def_id.expect_local();
 
-    // (Mir-)Borrowck uses `mir_validated`, so we have to force it to
-    // execute before we can steal.
-    tcx.ensure().mir_borrowck(def_id);
-
-    let (body, _) = tcx.mir_validated(def_id);
-    let mut body = body.steal();
+    let mut body = tcx.mir_drops_elaborated_and_const_checked(def_id).steal();
     run_optimization_passes(tcx, &mut body, def_id, None);
 
     debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR");
@@ -418,6 +448,7 @@ fn promoted_mir(tcx: TyCtxt<'_>, def_id: DefId) -> IndexVec<Promoted, Body<'_>>
     let mut promoted = promoted.steal();
 
     for (p, mut body) in promoted.iter_enumerated_mut() {
+        run_post_borrowck_cleanup_passes(tcx, &mut body, def_id, Some(p));
         run_optimization_passes(tcx, &mut body, def_id, Some(p));
     }
 
diff --git a/src/librustc_mir/transform/nrvo.rs b/src/librustc_mir/transform/nrvo.rs
index ffad1ebea00..1f3d7bb7cc6 100644
--- a/src/librustc_mir/transform/nrvo.rs
+++ b/src/librustc_mir/transform/nrvo.rs
@@ -111,7 +111,7 @@ fn local_eligible_for_nrvo(body: &mut mir::Body<'_>) -> Option<Local> {
         copied_to_return_place = Some(returned_local);
     }
 
-    return copied_to_return_place;
+    copied_to_return_place
 }
 
 fn find_local_assigned_to_return_place(
@@ -136,7 +136,7 @@ fn find_local_assigned_to_return_place(
         }
     }
 
-    return None;
+    None
 }
 
 // If this statement is an assignment of an unprojected local to the return place,
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index 2c8ad00fd06..e1311ccd374 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -909,7 +909,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
             };
 
             match terminator.kind {
-                TerminatorKind::Call { mut func, mut args, from_hir_call, .. } => {
+                TerminatorKind::Call { mut func, mut args, from_hir_call, fn_span, .. } => {
                     self.visit_operand(&mut func, loc);
                     for arg in &mut args {
                         self.visit_operand(arg, loc);
@@ -925,6 +925,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                             cleanup: None,
                             destination: Some((Place::from(new_temp), new_target)),
                             from_hir_call,
+                            fn_span,
                         },
                         ..terminator
                     };
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 5c78307d882..4c8fc49099b 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -368,7 +368,14 @@ fn check_terminator(
             Err((span, "const fn generators are unstable".into()))
         }
 
-        TerminatorKind::Call { func, args, from_hir_call: _, destination: _, cleanup: _ } => {
+        TerminatorKind::Call {
+            func,
+            args,
+            from_hir_call: _,
+            destination: _,
+            cleanup: _,
+            fn_span: _,
+        } => {
             let fn_ty = func.ty(body, tcx);
             if let ty::FnDef(def_id, _) = fn_ty.kind {
                 if !crate::const_eval::is_min_const_fn(tcx, def_id) {
diff --git a/src/librustc_mir/transform/simplify_try.rs b/src/librustc_mir/transform/simplify_try.rs
index 41ffa659441..50136ac3bec 100644
--- a/src/librustc_mir/transform/simplify_try.rs
+++ b/src/librustc_mir/transform/simplify_try.rs
@@ -99,7 +99,7 @@ fn get_arm_identity_info<'a, 'tcx>(stmts: &'a [Statement<'tcx>]) -> Option<ArmId
     fn try_eat<'a, 'tcx>(
         stmt_iter: &mut StmtIter<'a, 'tcx>,
         test: impl Fn(&'a Statement<'tcx>) -> bool,
-        mut action: impl FnMut(usize, &'a Statement<'tcx>) -> (),
+        mut action: impl FnMut(usize, &'a Statement<'tcx>),
     ) {
         while stmt_iter.peek().map(|(_, stmt)| test(stmt)).unwrap_or(false) {
             let (idx, stmt) = stmt_iter.next().unwrap();
@@ -271,7 +271,7 @@ fn optimization_applies<'tcx>(
     }
 
     // Verify the assigment chain consists of the form b = a; c = b; d = c; etc...
-    if opt_info.field_tmp_assignments.len() == 0 {
+    if opt_info.field_tmp_assignments.is_empty() {
         trace!("NO: no assignments found");
     }
     let mut last_assigned_to = opt_info.field_tmp_assignments[0].1;
@@ -306,7 +306,11 @@ fn optimization_applies<'tcx>(
 }
 
 impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity {
-    fn run_pass(&self, _: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
+        if tcx.sess.opts.debugging_opts.mir_opt_level < 2 {
+            return;
+        }
+
         trace!("running SimplifyArmIdentity on {:?}", source);
         let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
         for bb in basic_blocks {
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index 8f27247bfb4..a1345452ca9 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -644,6 +644,7 @@ where
                     destination: Some((unit_temp, succ)),
                     cleanup: unwind.into_option(),
                     from_hir_call: true,
+                    fn_span: self.source_info.span,
                 },
                 source_info: self.source_info,
             }),
@@ -988,6 +989,7 @@ where
             destination: Some((unit_temp, target)),
             cleanup: None,
             from_hir_call: false,
+            fn_span: self.source_info.span,
         }; // FIXME(#43234)
         let free_block = self.new_block(unwind, call);
 
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index ff386cb2183..02614044063 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -135,7 +135,7 @@ fn dump_matched_mir_node<'tcx, F>(
         }
         writeln!(file)?;
         extra_data(PassWhere::BeforeCFG, &mut file)?;
-        write_user_type_annotations(body, &mut file)?;
+        write_user_type_annotations(tcx, body, &mut file)?;
         write_mir_fn(tcx, source, body, &mut extra_data, &mut file)?;
         extra_data(PassWhere::AfterCFG, &mut file)?;
     };
@@ -351,7 +351,7 @@ fn write_extra<'tcx, F>(tcx: TyCtxt<'tcx>, write: &mut dyn Write, mut visit_op:
 where
     F: FnMut(&mut ExtraComments<'tcx>),
 {
-    let mut extra_comments = ExtraComments { _tcx: tcx, comments: vec![] };
+    let mut extra_comments = ExtraComments { tcx, comments: vec![] };
     visit_op(&mut extra_comments);
     for comment in extra_comments.comments {
         writeln!(write, "{:A$} // {}", "", comment, A = ALIGN)?;
@@ -360,7 +360,7 @@ where
 }
 
 struct ExtraComments<'tcx> {
-    _tcx: TyCtxt<'tcx>, // don't need it now, but bet we will soon
+    tcx: TyCtxt<'tcx>,
     comments: Vec<String>,
 }
 
@@ -377,7 +377,7 @@ impl Visitor<'tcx> for ExtraComments<'tcx> {
         self.super_constant(constant, location);
         let Constant { span, user_ty, literal } = constant;
         self.push("mir::Constant");
-        self.push(&format!("+ span: {:?}", span));
+        self.push(&format!("+ span: {}", self.tcx.sess.source_map().span_to_string(*span)));
         if let Some(user_ty) = user_ty {
             self.push(&format!("+ user_ty: {:?}", user_ty));
         }
@@ -862,12 +862,22 @@ fn write_mir_sig(
     Ok(())
 }
 
-fn write_user_type_annotations(body: &Body<'_>, w: &mut dyn Write) -> io::Result<()> {
+fn write_user_type_annotations(
+    tcx: TyCtxt<'_>,
+    body: &Body<'_>,
+    w: &mut dyn Write,
+) -> io::Result<()> {
     if !body.user_type_annotations.is_empty() {
         writeln!(w, "| User Type Annotations")?;
     }
     for (index, annotation) in body.user_type_annotations.iter_enumerated() {
-        writeln!(w, "| {:?}: {:?} at {:?}", index.index(), annotation.user_ty, annotation.span)?;
+        writeln!(
+            w,
+            "| {:?}: {:?} at {}",
+            index.index(),
+            annotation.user_ty,
+            tcx.sess.source_map().span_to_string(annotation.span)
+        )?;
     }
     if !body.user_type_annotations.is_empty() {
         writeln!(w, "|")?;
diff --git a/src/librustc_mir_build/build/expr/into.rs b/src/librustc_mir_build/build/expr/into.rs
index e402b2d1596..0d5bd4c7e61 100644
--- a/src/librustc_mir_build/build/expr/into.rs
+++ b/src/librustc_mir_build/build/expr/into.rs
@@ -162,7 +162,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 });
                 exit_block.unit()
             }
-            ExprKind::Call { ty, fun, args, from_hir_call } => {
+            ExprKind::Call { ty, fun, args, from_hir_call, fn_span } => {
                 let intrinsic = match ty.kind {
                     ty::FnDef(def_id, _) => {
                         let f = ty.fn_sig(this.hir.tcx());
@@ -206,6 +206,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                     this.record_operands_moved(&args);
 
+                    debug!("into_expr: fn_span={:?}", fn_span);
+
                     this.cfg.terminate(
                         block,
                         source_info,
@@ -222,6 +224,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                 Some((destination, success))
                             },
                             from_hir_call,
+                            fn_span
                         },
                     );
                     success.unit()
@@ -355,8 +358,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         hair::InlineAsmOperand::SymFn { expr } => {
                             mir::InlineAsmOperand::SymFn { value: box this.as_constant(expr) }
                         }
-                        hair::InlineAsmOperand::SymStatic { expr } => {
-                            mir::InlineAsmOperand::SymStatic { value: box this.as_constant(expr) }
+                        hair::InlineAsmOperand::SymStatic { def_id } => {
+                            mir::InlineAsmOperand::SymStatic { def_id }
                         }
                     })
                     .collect();
diff --git a/src/librustc_mir_build/build/matches/mod.rs b/src/librustc_mir_build/build/matches/mod.rs
index 3b448b0cf27..19948196f25 100644
--- a/src/librustc_mir_build/build/matches/mod.rs
+++ b/src/librustc_mir_build/build/matches/mod.rs
@@ -10,7 +10,7 @@ use crate::build::ForGuard::{self, OutsideGuard, RefWithinGuard};
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
 use crate::build::{GuardFrame, GuardFrameLocal, LocalsForNode};
 use crate::hair::{self, *};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::{fx::{FxHashMap, FxHashSet}, stack::ensure_sufficient_stack};
 use rustc_hir::HirId;
 use rustc_index::bit_set::BitSet;
 use rustc_middle::middle::region;
@@ -909,30 +909,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             split_or_candidate |= self.simplify_candidate(candidate);
         }
 
-        if split_or_candidate {
-            // At least one of the candidates has been split into subcandidates.
-            // We need to change the candidate list to include those.
-            let mut new_candidates = Vec::new();
+        ensure_sufficient_stack(|| {
+            if split_or_candidate {
+                // At least one of the candidates has been split into subcandidates.
+                // We need to change the candidate list to include those.
+                let mut new_candidates = Vec::new();
 
-            for candidate in candidates {
-                candidate.visit_leaves(|leaf_candidate| new_candidates.push(leaf_candidate));
+                for candidate in candidates {
+                    candidate.visit_leaves(|leaf_candidate| new_candidates.push(leaf_candidate));
+                }
+                self.match_simplified_candidates(
+                    span,
+                    start_block,
+                    otherwise_block,
+                    &mut *new_candidates,
+                    fake_borrows,
+                );
+            } else {
+                self.match_simplified_candidates(
+                    span,
+                    start_block,
+                    otherwise_block,
+                    candidates,
+                    fake_borrows,
+                );
             }
-            self.match_simplified_candidates(
-                span,
-                start_block,
-                otherwise_block,
-                &mut *new_candidates,
-                fake_borrows,
-            );
-        } else {
-            self.match_simplified_candidates(
-                span,
-                start_block,
-                otherwise_block,
-                candidates,
-                fake_borrows,
-            );
-        };
+        });
     }
 
     fn match_simplified_candidates(
diff --git a/src/librustc_mir_build/build/matches/simplify.rs b/src/librustc_mir_build/build/matches/simplify.rs
index 09543cd1ce4..2917a771a2c 100644
--- a/src/librustc_mir_build/build/matches/simplify.rs
+++ b/src/librustc_mir_build/build/matches/simplify.rs
@@ -160,13 +160,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     }
                     ty::Int(ity) => {
                         let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
-                        let max = truncate(u128::max_value(), size);
+                        let max = truncate(u128::MAX, size);
                         let bias = 1u128 << (size.bits() - 1);
                         (Some((0, max, size)), bias)
                     }
                     ty::Uint(uty) => {
                         let size = Integer::from_attr(&tcx, UnsignedInt(uty)).size();
-                        let max = truncate(u128::max_value(), size);
+                        let max = truncate(u128::MAX, size);
                         (Some((0, max, size)), 0)
                     }
                     _ => (None, 0),
diff --git a/src/librustc_mir_build/build/matches/test.rs b/src/librustc_mir_build/build/matches/test.rs
index 74398ca8a40..3e7bfc7d59b 100644
--- a/src/librustc_mir_build/build/matches/test.rs
+++ b/src/librustc_mir_build/build/matches/test.rs
@@ -443,6 +443,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 destination: Some((eq_result, eq_block)),
                 cleanup: Some(cleanup),
                 from_hir_call: false,
+                fn_span: source_info.span
             },
         );
 
diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs
index d0b35f32122..703f6ef8dc4 100644
--- a/src/librustc_mir_build/hair/cx/expr.rs
+++ b/src/librustc_mir_build/hair/cx/expr.rs
@@ -139,11 +139,11 @@ fn make_mirror_unadjusted<'a, 'tcx>(
 
     let kind = match expr.kind {
         // Here comes the interesting stuff:
-        hir::ExprKind::MethodCall(_, method_span, ref args) => {
+        hir::ExprKind::MethodCall(_, method_span, ref args, fn_span) => {
             // Rewrite a.b(c) into UFCS form like Trait::b(a, c)
             let expr = method_callee(cx, expr, method_span, None);
             let args = args.iter().map(|e| e.to_ref()).collect();
-            ExprKind::Call { ty: expr.ty, fun: expr.to_ref(), args, from_hir_call: true }
+            ExprKind::Call { ty: expr.ty, fun: expr.to_ref(), args, from_hir_call: true, fn_span }
         }
 
         hir::ExprKind::Call(ref fun, ref args) => {
@@ -170,6 +170,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
                     fun: method.to_ref(),
                     args: vec![fun.to_ref(), tupled_args.to_ref()],
                     from_hir_call: true,
+                    fn_span: expr.span,
                 }
             } else {
                 let adt_data =
@@ -215,6 +216,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
                         fun: fun.to_ref(),
                         args: args.to_ref(),
                         from_hir_call: true,
+                        fn_span: expr.span,
                     }
                 }
             }
@@ -465,25 +467,8 @@ fn make_mirror_unadjusted<'a, 'tcx>(
                                     }
                                 }
 
-                                Res::Def(DefKind::Static, id) => {
-                                    ty = cx.tcx.static_ptr_ty(id);
-                                    let ptr = cx.tcx.create_static_alloc(id);
-                                    InlineAsmOperand::SymStatic {
-                                        expr: Expr {
-                                            ty,
-                                            temp_lifetime,
-                                            span: expr.span,
-                                            kind: ExprKind::StaticRef {
-                                                literal: ty::Const::from_scalar(
-                                                    cx.tcx,
-                                                    Scalar::Ptr(ptr.into()),
-                                                    ty,
-                                                ),
-                                                def_id: id,
-                                            },
-                                        }
-                                        .to_ref(),
-                                    }
+                                Res::Def(DefKind::Static, def_id) => {
+                                    InlineAsmOperand::SymStatic { def_id }
                                 }
 
                                 _ => {
@@ -1024,7 +1009,7 @@ fn overloaded_operator<'a, 'tcx>(
     args: Vec<ExprRef<'tcx>>,
 ) -> ExprKind<'tcx> {
     let fun = method_callee(cx, expr, expr.span, None);
-    ExprKind::Call { ty: fun.ty, fun: fun.to_ref(), args, from_hir_call: false }
+    ExprKind::Call { ty: fun.ty, fun: fun.to_ref(), args, from_hir_call: false, fn_span: expr.span }
 }
 
 fn overloaded_place<'a, 'tcx>(
@@ -1060,7 +1045,13 @@ fn overloaded_place<'a, 'tcx>(
         temp_lifetime,
         ty: ref_ty,
         span: expr.span,
-        kind: ExprKind::Call { ty: fun.ty, fun: fun.to_ref(), args, from_hir_call: false },
+        kind: ExprKind::Call {
+            ty: fun.ty,
+            fun: fun.to_ref(),
+            args,
+            from_hir_call: false,
+            fn_span: expr.span,
+        },
     };
 
     // construct and return a deref wrapper `*foo()`
diff --git a/src/librustc_mir_build/hair/mod.rs b/src/librustc_mir_build/hair/mod.rs
index c869699bb20..ccff510f2d4 100644
--- a/src/librustc_mir_build/hair/mod.rs
+++ b/src/librustc_mir_build/hair/mod.rs
@@ -146,6 +146,9 @@ crate enum ExprKind<'tcx> {
         // Whether this is from a call in HIR, rather than from an overloaded
         // operator. True for overloaded function call.
         from_hir_call: bool,
+        /// This `Span` is the span of the function, without the dot and receiver
+        /// (e.g. `foo(a, b)` in `x.foo(a, b)`
+        fn_span: Span,
     },
     Deref {
         arg: ExprRef<'tcx>,
@@ -374,7 +377,7 @@ crate enum InlineAsmOperand<'tcx> {
         expr: ExprRef<'tcx>,
     },
     SymStatic {
-        expr: ExprRef<'tcx>,
+        def_id: DefId,
     },
 }
 
diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs
index 2de6d9fe3d4..4a4de6c420b 100644
--- a/src/librustc_mir_build/hair/pattern/_match.rs
+++ b/src/librustc_mir_build/hair/pattern/_match.rs
@@ -1,274 +1,274 @@
-/// Note: most of the tests relevant to this file can be found (at the time of writing) in
-/// src/tests/ui/pattern/usefulness.
-///
-/// This file includes the logic for exhaustiveness and usefulness checking for
-/// pattern-matching. Specifically, given a list of patterns for a type, we can
-/// tell whether:
-/// (a) the patterns cover every possible constructor for the type [exhaustiveness]
-/// (b) each pattern is necessary [usefulness]
-///
-/// The algorithm implemented here is a modified version of the one described in:
-/// http://moscova.inria.fr/~maranget/papers/warn/index.html
-/// However, to save future implementors from reading the original paper, we
-/// summarise the algorithm here to hopefully save time and be a little clearer
-/// (without being so rigorous).
-///
-/// # Premise
-///
-/// The core of the algorithm revolves about a "usefulness" check. In particular, we
-/// are trying to compute a predicate `U(P, p)` where `P` is a list of patterns (we refer to this as
-/// a matrix). `U(P, p)` represents whether, given an existing list of patterns
-/// `P_1 ..= P_m`, adding a new pattern `p` will be "useful" (that is, cover previously-
-/// uncovered values of the type).
-///
-/// If we have this predicate, then we can easily compute both exhaustiveness of an
-/// entire set of patterns and the individual usefulness of each one.
-/// (a) the set of patterns is exhaustive iff `U(P, _)` is false (i.e., adding a wildcard
-/// match doesn't increase the number of values we're matching)
-/// (b) a pattern `P_i` is not useful if `U(P[0..=(i-1), P_i)` is false (i.e., adding a
-/// pattern to those that have come before it doesn't increase the number of values
-/// we're matching).
-///
-/// # Core concept
-///
-/// The idea that powers everything that is done in this file is the following: a value is made
-/// from a constructor applied to some fields. Examples of constructors are `Some`, `None`, `(,)`
-/// (the 2-tuple constructor), `Foo {..}` (the constructor for a struct `Foo`), and `2` (the
-/// constructor for the number `2`). Fields are just a (possibly empty) list of values.
-///
-/// Some of the constructors listed above might feel weird: `None` and `2` don't take any
-/// arguments. This is part of what makes constructors so general: we will consider plain values
-/// like numbers and string literals to be constructors that take no arguments, also called "0-ary
-/// constructors"; they are the simplest case of constructors. This allows us to see any value as
-/// made up from a tree of constructors, each having a given number of children. For example:
-/// `(None, Ok(0))` is made from 4 different constructors.
-///
-/// This idea can be extended to patterns: a pattern captures a set of possible values, and we can
-/// describe this set using constructors. For example, `Err(_)` captures all values of the type
-/// `Result<T, E>` that start with the `Err` constructor (for some choice of `T` and `E`). The
-/// wildcard `_` captures all values of the given type starting with any of the constructors for
-/// that type.
-///
-/// We use this to compute whether different patterns might capture a same value. Do the patterns
-/// `Ok("foo")` and `Err(_)` capture a common value? The answer is no, because the first pattern
-/// captures only values starting with the `Ok` constructor and the second only values starting
-/// with the `Err` constructor. Do the patterns `Some(42)` and `Some(1..10)` intersect? They might,
-/// since they both capture values starting with `Some`. To be certain, we need to dig under the
-/// `Some` constructor and continue asking the question. This is the main idea behind the
-/// exhaustiveness algorithm: by looking at patterns constructor-by-constructor, we can efficiently
-/// figure out if some new pattern might capture a value that hadn't been captured by previous
-/// patterns.
-///
-/// Constructors are represented by the `Constructor` enum, and its fields by the `Fields` enum.
-/// Most of the complexity of this file resides in transforming between patterns and
-/// (`Constructor`, `Fields`) pairs, handling all the special cases correctly.
-///
-/// Caveat: this constructors/fields distinction doesn't quite cover every Rust value. For example
-/// a value of type `Rc<u64>` doesn't fit this idea very well, nor do various other things.
-/// However, this idea covers most of the cases that are relevant to exhaustiveness checking.
-///
-///
-/// # Algorithm
-///
-/// Recall that `U(P, p)` represents whether, given an existing list of patterns (aka matrix) `P`,
-/// adding a new pattern `p` will cover previously-uncovered values of the type.
-/// During the course of the algorithm, the rows of the matrix won't just be individual patterns,
-/// but rather partially-deconstructed patterns in the form of a list of fields. The paper
-/// calls those pattern-vectors, and we will call them pattern-stacks. The same holds for the
-/// new pattern `p`.
-///
-/// For example, say we have the following:
-/// ```
-///     // x: (Option<bool>, Result<()>)
-///     match x {
-///         (Some(true), _) => {}
-///         (None, Err(())) => {}
-///         (None, Err(_)) => {}
-///     }
-/// ```
-/// Here, the matrix `P` starts as:
-/// [
-///     [(Some(true), _)],
-///     [(None, Err(()))],
-///     [(None, Err(_))],
-/// ]
-/// We can tell it's not exhaustive, because `U(P, _)` is true (we're not covering
-/// `[(Some(false), _)]`, for instance). In addition, row 3 is not useful, because
-/// all the values it covers are already covered by row 2.
-///
-/// A list of patterns can be thought of as a stack, because we are mainly interested in the top of
-/// the stack at any given point, and we can pop or apply constructors to get new pattern-stacks.
-/// To match the paper, the top of the stack is at the beginning / on the left.
-///
-/// There are two important operations on pattern-stacks necessary to understand the algorithm:
-///     1. We can pop a given constructor off the top of a stack. This operation is called
-///        `specialize`, and is denoted `S(c, p)` where `c` is a constructor (like `Some` or
-///        `None`) and `p` a pattern-stack.
-///        If the pattern on top of the stack can cover `c`, this removes the constructor and
-///        pushes its arguments onto the stack. It also expands OR-patterns into distinct patterns.
-///        Otherwise the pattern-stack is discarded.
-///        This essentially filters those pattern-stacks whose top covers the constructor `c` and
-///        discards the others.
-///
-///        For example, the first pattern above initially gives a stack `[(Some(true), _)]`. If we
-///        pop the tuple constructor, we are left with `[Some(true), _]`, and if we then pop the
-///        `Some` constructor we get `[true, _]`. If we had popped `None` instead, we would get
-///        nothing back.
-///
-///        This returns zero or more new pattern-stacks, as follows. We look at the pattern `p_1`
-///        on top of the stack, and we have four cases:
-///             1.1. `p_1 = c(r_1, .., r_a)`, i.e. the top of the stack has constructor `c`. We
-///                  push onto the stack the arguments of this constructor, and return the result:
-///                     r_1, .., r_a, p_2, .., p_n
-///             1.2. `p_1 = c'(r_1, .., r_a')` where `c ≠ c'`. We discard the current stack and
-///                  return nothing.
-///             1.3. `p_1 = _`. We push onto the stack as many wildcards as the constructor `c` has
-///                  arguments (its arity), and return the resulting stack:
-///                     _, .., _, p_2, .., p_n
-///             1.4. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting
-///                  stack:
-///                     S(c, (r_1, p_2, .., p_n))
-///                     S(c, (r_2, p_2, .., p_n))
-///
-///     2. We can pop a wildcard off the top of the stack. This is called `D(p)`, where `p` is
-///        a pattern-stack.
-///        This is used when we know there are missing constructor cases, but there might be
-///        existing wildcard patterns, so to check the usefulness of the matrix, we have to check
-///        all its *other* components.
-///
-///        It is computed as follows. We look at the pattern `p_1` on top of the stack,
-///        and we have three cases:
-///             1.1. `p_1 = c(r_1, .., r_a)`. We discard the current stack and return nothing.
-///             1.2. `p_1 = _`. We return the rest of the stack:
-///                     p_2, .., p_n
-///             1.3. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting
-///               stack.
-///                     D((r_1, p_2, .., p_n))
-///                     D((r_2, p_2, .., p_n))
-///
-///     Note that the OR-patterns are not always used directly in Rust, but are used to derive the
-///     exhaustive integer matching rules, so they're written here for posterity.
-///
-/// Both those operations extend straightforwardly to a list or pattern-stacks, i.e. a matrix, by
-/// working row-by-row. Popping a constructor ends up keeping only the matrix rows that start with
-/// the given constructor, and popping a wildcard keeps those rows that start with a wildcard.
-///
-///
-/// The algorithm for computing `U`
-/// -------------------------------
-/// The algorithm is inductive (on the number of columns: i.e., components of tuple patterns).
-/// That means we're going to check the components from left-to-right, so the algorithm
-/// operates principally on the first component of the matrix and new pattern-stack `p`.
-/// This algorithm is realised in the `is_useful` function.
-///
-/// Base case. (`n = 0`, i.e., an empty tuple pattern)
-///     - If `P` already contains an empty pattern (i.e., if the number of patterns `m > 0`),
-///       then `U(P, p)` is false.
-///     - Otherwise, `P` must be empty, so `U(P, p)` is true.
-///
-/// Inductive step. (`n > 0`, i.e., whether there's at least one column
-///                  [which may then be expanded into further columns later])
-///     We're going to match on the top of the new pattern-stack, `p_1`.
-///         - If `p_1 == c(r_1, .., r_a)`, i.e. we have a constructor pattern.
-///           Then, the usefulness of `p_1` can be reduced to whether it is useful when
-///           we ignore all the patterns in the first column of `P` that involve other constructors.
-///           This is where `S(c, P)` comes in:
-///           `U(P, p) := U(S(c, P), S(c, p))`
-///           This special case is handled in `is_useful_specialized`.
-///
-///           For example, if `P` is:
-///           [
-///               [Some(true), _],
-///               [None, 0],
-///           ]
-///           and `p` is [Some(false), 0], then we don't care about row 2 since we know `p` only
-///           matches values that row 2 doesn't. For row 1 however, we need to dig into the
-///           arguments of `Some` to know whether some new value is covered. So we compute
-///           `U([[true, _]], [false, 0])`.
-///
-///         - If `p_1 == _`, then we look at the list of constructors that appear in the first
-///               component of the rows of `P`:
-///             + If there are some constructors that aren't present, then we might think that the
-///               wildcard `_` is useful, since it covers those constructors that weren't covered
-///               before.
-///               That's almost correct, but only works if there were no wildcards in those first
-///               components. So we need to check that `p` is useful with respect to the rows that
-///               start with a wildcard, if there are any. This is where `D` comes in:
-///               `U(P, p) := U(D(P), D(p))`
-///
-///               For example, if `P` is:
-///               [
-///                   [_, true, _],
-///                   [None, false, 1],
-///               ]
-///               and `p` is [_, false, _], the `Some` constructor doesn't appear in `P`. So if we
-///               only had row 2, we'd know that `p` is useful. However row 1 starts with a
-///               wildcard, so we need to check whether `U([[true, _]], [false, 1])`.
-///
-///             + Otherwise, all possible constructors (for the relevant type) are present. In this
-///               case we must check whether the wildcard pattern covers any unmatched value. For
-///               that, we can think of the `_` pattern as a big OR-pattern that covers all
-///               possible constructors. For `Option`, that would mean `_ = None | Some(_)` for
-///               example. The wildcard pattern is useful in this case if it is useful when
-///               specialized to one of the possible constructors. So we compute:
-///               `U(P, p) := ∃(k ϵ constructors) U(S(k, P), S(k, p))`
-///
-///               For example, if `P` is:
-///               [
-///                   [Some(true), _],
-///                   [None, false],
-///               ]
-///               and `p` is [_, false], both `None` and `Some` constructors appear in the first
-///               components of `P`. We will therefore try popping both constructors in turn: we
-///               compute U([[true, _]], [_, false]) for the `Some` constructor, and U([[false]],
-///               [false]) for the `None` constructor. The first case returns true, so we know that
-///               `p` is useful for `P`. Indeed, it matches `[Some(false), _]` that wasn't matched
-///               before.
-///
-///         - If `p_1 == r_1 | r_2`, then the usefulness depends on each `r_i` separately:
-///           `U(P, p) := U(P, (r_1, p_2, .., p_n))
-///                    || U(P, (r_2, p_2, .., p_n))`
-///
-/// Modifications to the algorithm
-/// ------------------------------
-/// The algorithm in the paper doesn't cover some of the special cases that arise in Rust, for
-/// example uninhabited types and variable-length slice patterns. These are drawn attention to
-/// throughout the code below. I'll make a quick note here about how exhaustive integer matching is
-/// accounted for, though.
-///
-/// Exhaustive integer matching
-/// ---------------------------
-/// An integer type can be thought of as a (huge) sum type: 1 | 2 | 3 | ...
-/// So to support exhaustive integer matching, we can make use of the logic in the paper for
-/// OR-patterns. However, we obviously can't just treat ranges x..=y as individual sums, because
-/// they are likely gigantic. So we instead treat ranges as constructors of the integers. This means
-/// that we have a constructor *of* constructors (the integers themselves). We then need to work
-/// through all the inductive step rules above, deriving how the ranges would be treated as
-/// OR-patterns, and making sure that they're treated in the same way even when they're ranges.
-/// There are really only four special cases here:
-/// - When we match on a constructor that's actually a range, we have to treat it as if we would
-///   an OR-pattern.
-///     + It turns out that we can simply extend the case for single-value patterns in
-///      `specialize` to either be *equal* to a value constructor, or *contained within* a range
-///      constructor.
-///     + When the pattern itself is a range, you just want to tell whether any of the values in
-///       the pattern range coincide with values in the constructor range, which is precisely
-///       intersection.
-///   Since when encountering a range pattern for a value constructor, we also use inclusion, it
-///   means that whenever the constructor is a value/range and the pattern is also a value/range,
-///   we can simply use intersection to test usefulness.
-/// - When we're testing for usefulness of a pattern and the pattern's first component is a
-///   wildcard.
-///     + If all the constructors appear in the matrix, we have a slight complication. By default,
-///       the behaviour (i.e., a disjunction over specialised matrices for each constructor) is
-///       invalid, because we want a disjunction over every *integer* in each range, not just a
-///       disjunction over every range. This is a bit more tricky to deal with: essentially we need
-///       to form equivalence classes of subranges of the constructor range for which the behaviour
-///       of the matrix `P` and new pattern `p` are the same. This is described in more
-///       detail in `split_grouped_constructors`.
-///     + If some constructors are missing from the matrix, it turns out we don't need to do
-///       anything special (because we know none of the integers are actually wildcards: i.e., we
-///       can't span wildcards using ranges).
+//! Note: most of the tests relevant to this file can be found (at the time of writing) in
+//! src/tests/ui/pattern/usefulness.
+//!
+//! This file includes the logic for exhaustiveness and usefulness checking for
+//! pattern-matching. Specifically, given a list of patterns for a type, we can
+//! tell whether:
+//! (a) the patterns cover every possible constructor for the type [exhaustiveness]
+//! (b) each pattern is necessary [usefulness]
+//!
+//! The algorithm implemented here is a modified version of the one described in:
+//! http://moscova.inria.fr/~maranget/papers/warn/index.html
+//! However, to save future implementors from reading the original paper, we
+//! summarise the algorithm here to hopefully save time and be a little clearer
+//! (without being so rigorous).
+//!
+//! # Premise
+//!
+//! The core of the algorithm revolves about a "usefulness" check. In particular, we
+//! are trying to compute a predicate `U(P, p)` where `P` is a list of patterns (we refer to this as
+//! a matrix). `U(P, p)` represents whether, given an existing list of patterns
+//! `P_1 ..= P_m`, adding a new pattern `p` will be "useful" (that is, cover previously-
+//! uncovered values of the type).
+//!
+//! If we have this predicate, then we can easily compute both exhaustiveness of an
+//! entire set of patterns and the individual usefulness of each one.
+//! (a) the set of patterns is exhaustive iff `U(P, _)` is false (i.e., adding a wildcard
+//! match doesn't increase the number of values we're matching)
+//! (b) a pattern `P_i` is not useful if `U(P[0..=(i-1), P_i)` is false (i.e., adding a
+//! pattern to those that have come before it doesn't increase the number of values
+//! we're matching).
+//!
+//! # Core concept
+//!
+//! The idea that powers everything that is done in this file is the following: a value is made
+//! from a constructor applied to some fields. Examples of constructors are `Some`, `None`, `(,)`
+//! (the 2-tuple constructor), `Foo {..}` (the constructor for a struct `Foo`), and `2` (the
+//! constructor for the number `2`). Fields are just a (possibly empty) list of values.
+//!
+//! Some of the constructors listed above might feel weird: `None` and `2` don't take any
+//! arguments. This is part of what makes constructors so general: we will consider plain values
+//! like numbers and string literals to be constructors that take no arguments, also called "0-ary
+//! constructors"; they are the simplest case of constructors. This allows us to see any value as
+//! made up from a tree of constructors, each having a given number of children. For example:
+//! `(None, Ok(0))` is made from 4 different constructors.
+//!
+//! This idea can be extended to patterns: a pattern captures a set of possible values, and we can
+//! describe this set using constructors. For example, `Err(_)` captures all values of the type
+//! `Result<T, E>` that start with the `Err` constructor (for some choice of `T` and `E`). The
+//! wildcard `_` captures all values of the given type starting with any of the constructors for
+//! that type.
+//!
+//! We use this to compute whether different patterns might capture a same value. Do the patterns
+//! `Ok("foo")` and `Err(_)` capture a common value? The answer is no, because the first pattern
+//! captures only values starting with the `Ok` constructor and the second only values starting
+//! with the `Err` constructor. Do the patterns `Some(42)` and `Some(1..10)` intersect? They might,
+//! since they both capture values starting with `Some`. To be certain, we need to dig under the
+//! `Some` constructor and continue asking the question. This is the main idea behind the
+//! exhaustiveness algorithm: by looking at patterns constructor-by-constructor, we can efficiently
+//! figure out if some new pattern might capture a value that hadn't been captured by previous
+//! patterns.
+//!
+//! Constructors are represented by the `Constructor` enum, and its fields by the `Fields` enum.
+//! Most of the complexity of this file resides in transforming between patterns and
+//! (`Constructor`, `Fields`) pairs, handling all the special cases correctly.
+//!
+//! Caveat: this constructors/fields distinction doesn't quite cover every Rust value. For example
+//! a value of type `Rc<u64>` doesn't fit this idea very well, nor do various other things.
+//! However, this idea covers most of the cases that are relevant to exhaustiveness checking.
+//!
+//!
+//! # Algorithm
+//!
+//! Recall that `U(P, p)` represents whether, given an existing list of patterns (aka matrix) `P`,
+//! adding a new pattern `p` will cover previously-uncovered values of the type.
+//! During the course of the algorithm, the rows of the matrix won't just be individual patterns,
+//! but rather partially-deconstructed patterns in the form of a list of fields. The paper
+//! calls those pattern-vectors, and we will call them pattern-stacks. The same holds for the
+//! new pattern `p`.
+//!
+//! For example, say we have the following:
+//! ```
+//!     // x: (Option<bool>, Result<()>)
+//!     match x {
+//!         (Some(true), _) => {}
+//!         (None, Err(())) => {}
+//!         (None, Err(_)) => {}
+//!     }
+//! ```
+//! Here, the matrix `P` starts as:
+//! [
+//!     [(Some(true), _)],
+//!     [(None, Err(()))],
+//!     [(None, Err(_))],
+//! ]
+//! We can tell it's not exhaustive, because `U(P, _)` is true (we're not covering
+//! `[(Some(false), _)]`, for instance). In addition, row 3 is not useful, because
+//! all the values it covers are already covered by row 2.
+//!
+//! A list of patterns can be thought of as a stack, because we are mainly interested in the top of
+//! the stack at any given point, and we can pop or apply constructors to get new pattern-stacks.
+//! To match the paper, the top of the stack is at the beginning / on the left.
+//!
+//! There are two important operations on pattern-stacks necessary to understand the algorithm:
+//!     1. We can pop a given constructor off the top of a stack. This operation is called
+//!        `specialize`, and is denoted `S(c, p)` where `c` is a constructor (like `Some` or
+//!        `None`) and `p` a pattern-stack.
+//!        If the pattern on top of the stack can cover `c`, this removes the constructor and
+//!        pushes its arguments onto the stack. It also expands OR-patterns into distinct patterns.
+//!        Otherwise the pattern-stack is discarded.
+//!        This essentially filters those pattern-stacks whose top covers the constructor `c` and
+//!        discards the others.
+//!
+//!        For example, the first pattern above initially gives a stack `[(Some(true), _)]`. If we
+//!        pop the tuple constructor, we are left with `[Some(true), _]`, and if we then pop the
+//!        `Some` constructor we get `[true, _]`. If we had popped `None` instead, we would get
+//!        nothing back.
+//!
+//!        This returns zero or more new pattern-stacks, as follows. We look at the pattern `p_1`
+//!        on top of the stack, and we have four cases:
+//!             1.1. `p_1 = c(r_1, .., r_a)`, i.e. the top of the stack has constructor `c`. We
+//!                  push onto the stack the arguments of this constructor, and return the result:
+//!                     r_1, .., r_a, p_2, .., p_n
+//!             1.2. `p_1 = c'(r_1, .., r_a')` where `c ≠ c'`. We discard the current stack and
+//!                  return nothing.
+//!             1.3. `p_1 = _`. We push onto the stack as many wildcards as the constructor `c` has
+//!                  arguments (its arity), and return the resulting stack:
+//!                     _, .., _, p_2, .., p_n
+//!             1.4. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting
+//!                  stack:
+//!                     S(c, (r_1, p_2, .., p_n))
+//!                     S(c, (r_2, p_2, .., p_n))
+//!
+//!     2. We can pop a wildcard off the top of the stack. This is called `D(p)`, where `p` is
+//!        a pattern-stack.
+//!        This is used when we know there are missing constructor cases, but there might be
+//!        existing wildcard patterns, so to check the usefulness of the matrix, we have to check
+//!        all its *other* components.
+//!
+//!        It is computed as follows. We look at the pattern `p_1` on top of the stack,
+//!        and we have three cases:
+//!             1.1. `p_1 = c(r_1, .., r_a)`. We discard the current stack and return nothing.
+//!             1.2. `p_1 = _`. We return the rest of the stack:
+//!                     p_2, .., p_n
+//!             1.3. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting
+//!               stack.
+//!                     D((r_1, p_2, .., p_n))
+//!                     D((r_2, p_2, .., p_n))
+//!
+//!     Note that the OR-patterns are not always used directly in Rust, but are used to derive the
+//!     exhaustive integer matching rules, so they're written here for posterity.
+//!
+//! Both those operations extend straightforwardly to a list or pattern-stacks, i.e. a matrix, by
+//! working row-by-row. Popping a constructor ends up keeping only the matrix rows that start with
+//! the given constructor, and popping a wildcard keeps those rows that start with a wildcard.
+//!
+//!
+//! The algorithm for computing `U`
+//! -------------------------------
+//! The algorithm is inductive (on the number of columns: i.e., components of tuple patterns).
+//! That means we're going to check the components from left-to-right, so the algorithm
+//! operates principally on the first component of the matrix and new pattern-stack `p`.
+//! This algorithm is realised in the `is_useful` function.
+//!
+//! Base case. (`n = 0`, i.e., an empty tuple pattern)
+//!     - If `P` already contains an empty pattern (i.e., if the number of patterns `m > 0`),
+//!       then `U(P, p)` is false.
+//!     - Otherwise, `P` must be empty, so `U(P, p)` is true.
+//!
+//! Inductive step. (`n > 0`, i.e., whether there's at least one column
+//!                  [which may then be expanded into further columns later])
+//!     We're going to match on the top of the new pattern-stack, `p_1`.
+//!         - If `p_1 == c(r_1, .., r_a)`, i.e. we have a constructor pattern.
+//!           Then, the usefulness of `p_1` can be reduced to whether it is useful when
+//!           we ignore all the patterns in the first column of `P` that involve other constructors.
+//!           This is where `S(c, P)` comes in:
+//!           `U(P, p) := U(S(c, P), S(c, p))`
+//!           This special case is handled in `is_useful_specialized`.
+//!
+//!           For example, if `P` is:
+//!           [
+//!               [Some(true), _],
+//!               [None, 0],
+//!           ]
+//!           and `p` is [Some(false), 0], then we don't care about row 2 since we know `p` only
+//!           matches values that row 2 doesn't. For row 1 however, we need to dig into the
+//!           arguments of `Some` to know whether some new value is covered. So we compute
+//!           `U([[true, _]], [false, 0])`.
+//!
+//!         - If `p_1 == _`, then we look at the list of constructors that appear in the first
+//!               component of the rows of `P`:
+//!             + If there are some constructors that aren't present, then we might think that the
+//!               wildcard `_` is useful, since it covers those constructors that weren't covered
+//!               before.
+//!               That's almost correct, but only works if there were no wildcards in those first
+//!               components. So we need to check that `p` is useful with respect to the rows that
+//!               start with a wildcard, if there are any. This is where `D` comes in:
+//!               `U(P, p) := U(D(P), D(p))`
+//!
+//!               For example, if `P` is:
+//!               [
+//!                   [_, true, _],
+//!                   [None, false, 1],
+//!               ]
+//!               and `p` is [_, false, _], the `Some` constructor doesn't appear in `P`. So if we
+//!               only had row 2, we'd know that `p` is useful. However row 1 starts with a
+//!               wildcard, so we need to check whether `U([[true, _]], [false, 1])`.
+//!
+//!             + Otherwise, all possible constructors (for the relevant type) are present. In this
+//!               case we must check whether the wildcard pattern covers any unmatched value. For
+//!               that, we can think of the `_` pattern as a big OR-pattern that covers all
+//!               possible constructors. For `Option`, that would mean `_ = None | Some(_)` for
+//!               example. The wildcard pattern is useful in this case if it is useful when
+//!               specialized to one of the possible constructors. So we compute:
+//!               `U(P, p) := ∃(k ϵ constructors) U(S(k, P), S(k, p))`
+//!
+//!               For example, if `P` is:
+//!               [
+//!                   [Some(true), _],
+//!                   [None, false],
+//!               ]
+//!               and `p` is [_, false], both `None` and `Some` constructors appear in the first
+//!               components of `P`. We will therefore try popping both constructors in turn: we
+//!               compute U([[true, _]], [_, false]) for the `Some` constructor, and U([[false]],
+//!               [false]) for the `None` constructor. The first case returns true, so we know that
+//!               `p` is useful for `P`. Indeed, it matches `[Some(false), _]` that wasn't matched
+//!               before.
+//!
+//!         - If `p_1 == r_1 | r_2`, then the usefulness depends on each `r_i` separately:
+//!           `U(P, p) := U(P, (r_1, p_2, .., p_n))
+//!                    || U(P, (r_2, p_2, .., p_n))`
+//!
+//! Modifications to the algorithm
+//! ------------------------------
+//! The algorithm in the paper doesn't cover some of the special cases that arise in Rust, for
+//! example uninhabited types and variable-length slice patterns. These are drawn attention to
+//! throughout the code below. I'll make a quick note here about how exhaustive integer matching is
+//! accounted for, though.
+//!
+//! Exhaustive integer matching
+//! ---------------------------
+//! An integer type can be thought of as a (huge) sum type: 1 | 2 | 3 | ...
+//! So to support exhaustive integer matching, we can make use of the logic in the paper for
+//! OR-patterns. However, we obviously can't just treat ranges x..=y as individual sums, because
+//! they are likely gigantic. So we instead treat ranges as constructors of the integers. This means
+//! that we have a constructor *of* constructors (the integers themselves). We then need to work
+//! through all the inductive step rules above, deriving how the ranges would be treated as
+//! OR-patterns, and making sure that they're treated in the same way even when they're ranges.
+//! There are really only four special cases here:
+//! - When we match on a constructor that's actually a range, we have to treat it as if we would
+//!   an OR-pattern.
+//!     + It turns out that we can simply extend the case for single-value patterns in
+//!      `specialize` to either be *equal* to a value constructor, or *contained within* a range
+//!      constructor.
+//!     + When the pattern itself is a range, you just want to tell whether any of the values in
+//!       the pattern range coincide with values in the constructor range, which is precisely
+//!       intersection.
+//!   Since when encountering a range pattern for a value constructor, we also use inclusion, it
+//!   means that whenever the constructor is a value/range and the pattern is also a value/range,
+//!   we can simply use intersection to test usefulness.
+//! - When we're testing for usefulness of a pattern and the pattern's first component is a
+//!   wildcard.
+//!     + If all the constructors appear in the matrix, we have a slight complication. By default,
+//!       the behaviour (i.e., a disjunction over specialised matrices for each constructor) is
+//!       invalid, because we want a disjunction over every *integer* in each range, not just a
+//!       disjunction over every range. This is a bit more tricky to deal with: essentially we need
+//!       to form equivalence classes of subranges of the constructor range for which the behaviour
+//!       of the matrix `P` and new pattern `p` are the same. This is described in more
+//!       detail in `split_grouped_constructors`.
+//!     + If some constructors are missing from the matrix, it turns out we don't need to do
+//!       anything special (because we know none of the integers are actually wildcards: i.e., we
+//!       can't span wildcards using ranges).
 use self::Constructor::*;
 use self::SliceKind::*;
 use self::Usefulness::*;
@@ -1519,7 +1519,7 @@ fn all_constructors<'a, 'tcx>(
         }
         ty::Uint(uty) => {
             let size = Integer::from_attr(&cx.tcx, UnsignedInt(uty)).size();
-            let max = truncate(u128::max_value(), size);
+            let max = truncate(u128::MAX, size);
             vec![make_range(0, max)]
         }
         _ => {
diff --git a/src/librustc_mir_build/hair/pattern/const_to_pat.rs b/src/librustc_mir_build/hair/pattern/const_to_pat.rs
index 9e3f75fdc07..087c2c064cf 100644
--- a/src/librustc_mir_build/hair/pattern/const_to_pat.rs
+++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs
@@ -80,7 +80,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
     }
 
     fn type_marked_structural(&self, ty: Ty<'tcx>) -> bool {
-        traits::type_marked_structural(self.id, self.span, &self.infcx, ty)
+        ty.is_structural_eq_shallow(self.infcx.tcx)
     }
 
     fn to_pat(
@@ -130,6 +130,9 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
                     traits::NonStructuralMatchTy::Generator => {
                         "generators cannot be used in patterns".to_string()
                     }
+                    traits::NonStructuralMatchTy::Closure => {
+                        "closures cannot be used in patterns".to_string()
+                    }
                     traits::NonStructuralMatchTy::Param => {
                         bug!("use of a constant whose type is a parameter inside a pattern")
                     }
diff --git a/src/librustc_parse/lexer/mod.rs b/src/librustc_parse/lexer/mod.rs
index 9bc6a50acad..84b3335a0f6 100644
--- a/src/librustc_parse/lexer/mod.rs
+++ b/src/librustc_parse/lexer/mod.rs
@@ -325,7 +325,15 @@ impl<'a> StringReader<'a> {
         let (lit_kind, mode, prefix_len, postfix_len) = match kind {
             rustc_lexer::LiteralKind::Char { terminated } => {
                 if !terminated {
-                    self.fatal_span_(start, suffix_start, "unterminated character literal").raise()
+                    self.sess
+                        .span_diagnostic
+                        .struct_span_fatal_with_code(
+                            self.mk_sp(start, suffix_start),
+                            "unterminated character literal",
+                            error_code!(E0762),
+                        )
+                        .emit();
+                    FatalError.raise();
                 }
                 (token::Char, Mode::Char, 1, 1) // ' '
             }
@@ -401,7 +409,7 @@ impl<'a> StringReader<'a> {
         let content_end = suffix_start - BytePos(postfix_len);
         let id = self.symbol_from_to(content_start, content_end);
         self.validate_literal_escape(mode, content_start, content_end);
-        return (lit_kind, id);
+        (lit_kind, id)
     }
 
     pub fn pos(&self) -> BytePos {
diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs
index 660a63841bc..8792605c08d 100644
--- a/src/librustc_parse/parser/diagnostics.rs
+++ b/src/librustc_parse/parser/diagnostics.rs
@@ -936,7 +936,7 @@ impl<'a> Parser<'a> {
         } else if !sm.is_multiline(self.prev_token.span.until(self.token.span)) {
             // The current token is in the same line as the prior token, not recoverable.
         } else if [token::Comma, token::Colon].contains(&self.token.kind)
-            && &self.prev_token.kind == &token::CloseDelim(token::Paren)
+            && self.prev_token.kind == token::CloseDelim(token::Paren)
         {
             // Likely typo: The current token is on a new line and is expected to be
             // `.`, `;`, `?`, or an operator after a close delimiter token.
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs
index e0c37284839..49a5c880176 100644
--- a/src/librustc_parse/parser/expr.rs
+++ b/src/librustc_parse/parser/expr.rs
@@ -639,7 +639,7 @@ impl<'a> Parser<'a> {
                     ExprKind::Index(_, _) => "indexing",
                     ExprKind::Try(_) => "?",
                     ExprKind::Field(_, _) => "a field access",
-                    ExprKind::MethodCall(_, _) => "a method call",
+                    ExprKind::MethodCall(_, _, _) => "a method call",
                     ExprKind::Call(_, _) => "a function call",
                     ExprKind::Await(_) => "`.await`",
                     ExprKind::Err => return Ok(with_postfix),
@@ -865,6 +865,7 @@ impl<'a> Parser<'a> {
             return self.mk_await_expr(self_arg, lo);
         }
 
+        let fn_span_lo = self.token.span;
         let segment = self.parse_path_segment(PathStyle::Expr)?;
         self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren));
 
@@ -873,8 +874,9 @@ impl<'a> Parser<'a> {
             let mut args = self.parse_paren_expr_seq()?;
             args.insert(0, self_arg);
 
+            let fn_span = fn_span_lo.to(self.prev_token.span);
             let span = lo.to(self.prev_token.span);
-            Ok(self.mk_expr(span, ExprKind::MethodCall(segment, args), AttrVec::new()))
+            Ok(self.mk_expr(span, ExprKind::MethodCall(segment, args, fn_span), AttrVec::new()))
         } else {
             // Field access `expr.f`
             if let Some(args) = segment.args {
diff --git a/src/librustc_parse/parser/generics.rs b/src/librustc_parse/parser/generics.rs
index 8e8f864728c..04b64d93c70 100644
--- a/src/librustc_parse/parser/generics.rs
+++ b/src/librustc_parse/parser/generics.rs
@@ -157,6 +157,7 @@ impl<'a> Parser<'a> {
         Ok(ast::Generics {
             params,
             where_clause: WhereClause {
+                has_where_token: false,
                 predicates: Vec::new(),
                 span: self.prev_token.span.shrink_to_hi(),
             },
@@ -170,12 +171,16 @@ impl<'a> Parser<'a> {
     /// where T : Trait<U, V> + 'b, 'a : 'b
     /// ```
     pub(super) fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
-        let mut where_clause =
-            WhereClause { predicates: Vec::new(), span: self.prev_token.span.shrink_to_hi() };
+        let mut where_clause = WhereClause {
+            has_where_token: false,
+            predicates: Vec::new(),
+            span: self.prev_token.span.shrink_to_hi(),
+        };
 
         if !self.eat_keyword(kw::Where) {
             return Ok(where_clause);
         }
+        where_clause.has_where_token = true;
         let lo = self.prev_token.span;
 
         // We are considering adding generics to the `where` keyword as an alternative higher-rank
diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs
index c00b6084829..47ae92c48bd 100644
--- a/src/librustc_parse/parser/mod.rs
+++ b/src/librustc_parse/parser/mod.rs
@@ -193,7 +193,7 @@ impl TokenCursor {
                         tree,
                         self.stack.len()
                     );
-                    collecting.buf.push(tree.clone().into())
+                    collecting.buf.push(tree.clone())
                 }
             }
 
@@ -675,7 +675,7 @@ impl<'a> Parser<'a> {
                             // If this was a missing `@` in a binding pattern
                             // bail with a suggestion
                             // https://github.com/rust-lang/rust/issues/72373
-                            if self.prev_token.is_ident() && &self.token.kind == &token::DotDot {
+                            if self.prev_token.is_ident() && self.token.kind == token::DotDot {
                                 let msg = format!(
                                     "if you meant to bind the contents of \
                                     the rest of the array pattern into `{}`, use `@`",
@@ -1193,7 +1193,7 @@ impl<'a> Parser<'a> {
         let mut collected_tokens = if let Some(collecting) = self.token_cursor.collecting.take() {
             collecting.buf
         } else {
-            let msg = format!("our vector went away?");
+            let msg = "our vector went away?";
             debug!("collect_tokens: {}", msg);
             self.sess.span_diagnostic.delay_span_bug(self.token.span, &msg);
             // This can happen due to a bad interaction of two unrelated recovery mechanisms
diff --git a/src/librustc_passes/check_attr.rs b/src/librustc_passes/check_attr.rs
index b54731d8881..80681c14375 100644
--- a/src/librustc_passes/check_attr.rs
+++ b/src/librustc_passes/check_attr.rs
@@ -37,7 +37,7 @@ fn target_from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem<'_>)
                 Target::Method(MethodKind::Inherent)
             }
         }
-        hir::ImplItemKind::TyAlias(..) | hir::ImplItemKind::OpaqueTy(..) => Target::AssocTy,
+        hir::ImplItemKind::TyAlias(..) => Target::AssocTy,
     }
 }
 
diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs
index 1dcf0e7c7a9..503fbb64db8 100644
--- a/src/librustc_passes/dead.rs
+++ b/src/librustc_passes/dead.rs
@@ -304,7 +304,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> {
     }
 
     fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
-        if let TyKind::Def(item_id, _) = ty.kind {
+        if let TyKind::OpaqueDef(item_id, _) = ty.kind {
             let item = self.tcx.hir().expect_item(item_id.id);
             intravisit::walk_item(self, item);
         }
@@ -668,7 +668,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> {
                 }
                 self.visit_nested_body(body_id)
             }
-            hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(..) => {}
+            hir::ImplItemKind::TyAlias(..) => {}
         }
     }
 
diff --git a/src/librustc_passes/intrinsicck.rs b/src/librustc_passes/intrinsicck.rs
index 93344e907c3..e2bfcf18edb 100644
--- a/src/librustc_passes/intrinsicck.rs
+++ b/src/librustc_passes/intrinsicck.rs
@@ -232,7 +232,7 @@ impl ExprVisitor<'tcx> {
         // size).
         if let Some((in_expr, Some(in_asm_ty))) = tied_input {
             if in_asm_ty != asm_ty {
-                let msg = &format!("incompatible types for asm inout argument");
+                let msg = "incompatible types for asm inout argument";
                 let mut err = self.tcx.sess.struct_span_err(vec![in_expr.span, expr.span], msg);
                 err.span_label(
                     in_expr.span,
diff --git a/src/librustc_passes/layout_test.rs b/src/librustc_passes/layout_test.rs
index c0826f8cc60..2419e696596 100644
--- a/src/librustc_passes/layout_test.rs
+++ b/src/librustc_passes/layout_test.rs
@@ -27,8 +27,7 @@ impl ItemLikeVisitor<'tcx> for LayoutTest<'tcx> {
             ItemKind::TyAlias(..)
             | ItemKind::Enum(..)
             | ItemKind::Struct(..)
-            | ItemKind::Union(..)
-            | ItemKind::OpaqueTy(..) => {
+            | ItemKind::Union(..) => {
                 for attr in self.tcx.get_attrs(item_def_id.to_def_id()).iter() {
                     if attr.check_name(sym::rustc_layout) {
                         self.dump_layout_of(item_def_id, item, attr);
@@ -83,9 +82,11 @@ impl LayoutTest<'tcx> {
                         }
 
                         sym::debug => {
+                            let normalized_ty =
+                                self.tcx.normalize_erasing_regions(param_env.with_reveal_all(), ty);
                             self.tcx.sess.span_err(
                                 item.span,
-                                &format!("layout_of({:?}) = {:#?}", ty, *ty_layout),
+                                &format!("layout_of({:?}) = {:#?}", normalized_ty, *ty_layout),
                             );
                         }
 
diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs
index 55978afc594..ff5dabd5418 100644
--- a/src/librustc_passes/liveness.rs
+++ b/src/librustc_passes/liveness.rs
@@ -1198,7 +1198,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                 self.propagate_through_expr(&f, succ)
             }
 
-            hir::ExprKind::MethodCall(.., ref args) => {
+            hir::ExprKind::MethodCall(.., ref args, _) => {
                 let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id();
                 let succ = if self.ir.tcx.is_ty_uninhabited_from(
                     m,
diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs
index cac71b3836c..c9a4428c007 100644
--- a/src/librustc_passes/reachable.rs
+++ b/src/librustc_passes/reachable.rs
@@ -180,7 +180,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
                             }
                         }
                     }
-                    hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(_) => false,
+                    hir::ImplItemKind::TyAlias(_) => false,
                 }
             }
             Some(_) => false,
@@ -289,7 +289,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
                         self.visit_nested_body(body)
                     }
                 }
-                hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(_) => {}
+                hir::ImplItemKind::TyAlias(_) => {}
             },
             Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(.., body, _, _), .. }) => {
                 self.visit_nested_body(body);
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index cb896810951..3c1b56a9ef4 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -615,7 +615,6 @@ impl EmbargoVisitor<'tcx> {
             // public, or are not namespaced at all.
             DefKind::AssocConst
             | DefKind::AssocTy
-            | DefKind::AssocOpaqueTy
             | DefKind::ConstParam
             | DefKind::Ctor(_, _)
             | DefKind::Enum
@@ -1302,7 +1301,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
                     return;
                 }
             }
-            hir::ExprKind::MethodCall(_, span, _) => {
+            hir::ExprKind::MethodCall(_, span, _, _) => {
                 // Method calls have to be checked specially.
                 self.span = span;
                 if let Some(def_id) = self.tables.type_dependent_def_id(expr.hir_id) {
@@ -1333,11 +1332,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
             _ => None,
         };
         let def = def.filter(|(kind, _)| match kind {
-            DefKind::AssocFn
-            | DefKind::AssocConst
-            | DefKind::AssocTy
-            | DefKind::AssocOpaqueTy
-            | DefKind::Static => true,
+            DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::Static => true,
             _ => false,
         });
         if let Some((kind, def_id)) = def {
@@ -1602,9 +1597,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
                             hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) => {
                                 self.access_levels.is_reachable(impl_item_ref.id.hir_id)
                             }
-                            hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(_) => {
-                                false
-                            }
+                            hir::ImplItemKind::TyAlias(_) => false,
                         }
                     });
 
@@ -1952,9 +1945,6 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
         let (check_ty, is_assoc_ty) = match assoc_item_kind {
             AssocItemKind::Const | AssocItemKind::Fn { .. } => (true, false),
             AssocItemKind::Type => (defaultness.has_value(), true),
-            // `ty()` for opaque types is the underlying type,
-            // it's not a part of interface, so we skip it.
-            AssocItemKind::OpaqueTy => (false, true),
         };
         check.in_assoc_ty = is_assoc_ty;
         check.generics().predicates();
diff --git a/src/librustc_query_system/dep_graph/dep_node.rs b/src/librustc_query_system/dep_graph/dep_node.rs
index d8875f8ac64..002b0f9c165 100644
--- a/src/librustc_query_system/dep_graph/dep_node.rs
+++ b/src/librustc_query_system/dep_graph/dep_node.rs
@@ -91,7 +91,7 @@ impl<K: DepKind> fmt::Debug for DepNode<K> {
 }
 
 pub trait DepNodeParams<Ctxt: DepContext>: fmt::Debug + Sized {
-    const CAN_RECONSTRUCT_QUERY_KEY: bool;
+    fn can_reconstruct_query_key() -> bool;
 
     /// This method turns the parameters of a DepNodeConstructor into an opaque
     /// Fingerprint to be used in DepNode.
@@ -108,7 +108,7 @@ pub trait DepNodeParams<Ctxt: DepContext>: fmt::Debug + Sized {
     /// This method tries to recover the query key from the given `DepNode`,
     /// something which is needed when forcing `DepNode`s during red-green
     /// evaluation. The query system will only call this method if
-    /// `CAN_RECONSTRUCT_QUERY_KEY` is `true`.
+    /// `can_reconstruct_query_key()` is `true`.
     /// It is always valid to return `None` here, in which case incremental
     /// compilation will treat the query as having changed instead of forcing it.
     fn recover(tcx: Ctxt, dep_node: &DepNode<Ctxt::DepKind>) -> Option<Self>;
@@ -118,7 +118,10 @@ impl<Ctxt: DepContext, T> DepNodeParams<Ctxt> for T
 where
     T: HashStable<Ctxt::StableHashingContext> + fmt::Debug,
 {
-    default const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
+    #[inline]
+    default fn can_reconstruct_query_key() -> bool {
+        false
+    }
 
     default fn to_fingerprint(&self, tcx: Ctxt) -> Fingerprint {
         let mut hcx = tcx.create_stable_hashing_context();
diff --git a/src/librustc_query_system/lib.rs b/src/librustc_query_system/lib.rs
index 8e350d3ba26..12450a4ccd3 100644
--- a/src/librustc_query_system/lib.rs
+++ b/src/librustc_query_system/lib.rs
@@ -4,7 +4,7 @@
 #![feature(const_panic)]
 #![feature(core_intrinsics)]
 #![feature(hash_raw_entry)]
-#![feature(specialization)] // FIXME: min_specialization rejects `default const`
+#![feature(min_specialization)]
 #![feature(stmt_expr_attributes)]
 #![feature(vec_remove_item)]
 
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 2ae063660e3..e633bd1843e 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -746,12 +746,11 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
             }
 
             // These items live in the type namespace.
-            ItemKind::TyAlias(_, _, _, ref ty) => {
-                let def_kind = match ty.as_deref().and_then(|ty| ty.kind.opaque_top_hack()) {
-                    None => DefKind::TyAlias,
-                    Some(_) => DefKind::OpaqueTy,
-                };
-                let res = Res::Def(def_kind, self.r.definitions.local_def_id(item.id).to_def_id());
+            ItemKind::TyAlias(..) => {
+                let res = Res::Def(
+                    DefKind::TyAlias,
+                    self.r.definitions.local_def_id(item.id).to_def_id(),
+                );
                 self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
             }
 
@@ -917,8 +916,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 | DefKind::ForeignTy
                 | DefKind::OpaqueTy
                 | DefKind::TraitAlias
-                | DefKind::AssocTy
-                | DefKind::AssocOpaqueTy,
+                | DefKind::AssocTy,
                 _,
             )
             | Res::PrimTy(..)
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index cbb2878011c..bd2ce5a72e8 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -629,6 +629,7 @@ impl<'a> Resolver<'a> {
         &mut self,
         lookup_ident: Ident,
         namespace: Namespace,
+        parent_scope: &ParentScope<'a>,
         start_module: Module<'a>,
         crate_name: Ident,
         filter_fn: FilterFn,
@@ -655,7 +656,11 @@ impl<'a> Resolver<'a> {
                 }
 
                 // collect results based on the filter function
-                if ident.name == lookup_ident.name && ns == namespace {
+                // avoid suggesting anything from the same module in which we are resolving
+                if ident.name == lookup_ident.name
+                    && ns == namespace
+                    && !ptr::eq(in_module, parent_scope.module)
+                {
                     let res = name_binding.res();
                     if filter_fn(res) {
                         // create the path
@@ -680,7 +685,9 @@ impl<'a> Resolver<'a> {
                                 Res::Def(DefKind::Ctor(..), did) => this.parent(did),
                                 _ => res.opt_def_id(),
                             };
-                            candidates.push(ImportSuggestion { did, descr: res.descr(), path });
+                            if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
+                                candidates.push(ImportSuggestion { did, descr: res.descr(), path });
+                            }
                         }
                     }
                 }
@@ -722,6 +729,7 @@ impl<'a> Resolver<'a> {
         &mut self,
         lookup_ident: Ident,
         namespace: Namespace,
+        parent_scope: &ParentScope<'a>,
         filter_fn: FilterFn,
     ) -> Vec<ImportSuggestion>
     where
@@ -730,6 +738,7 @@ impl<'a> Resolver<'a> {
         let mut suggestions = self.lookup_import_candidates_from_module(
             lookup_ident,
             namespace,
+            parent_scope,
             self.graph_root,
             Ident::with_dummy_span(kw::Crate),
             &filter_fn,
@@ -754,6 +763,7 @@ impl<'a> Resolver<'a> {
                     suggestions.extend(self.lookup_import_candidates_from_module(
                         lookup_ident,
                         namespace,
+                        parent_scope,
                         crate_root,
                         ident,
                         &filter_fn,
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index 49177906647..7166fef2d13 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -2117,7 +2117,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
             ExprKind::Field(ref subexpression, _) => {
                 self.resolve_expr(subexpression, Some(expr));
             }
-            ExprKind::MethodCall(ref segment, ref arguments) => {
+            ExprKind::MethodCall(ref segment, ref arguments, _) => {
                 let mut arguments = arguments.iter();
                 self.resolve_expr(arguments.next().unwrap(), Some(expr));
                 for argument in arguments {
diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs
index b1a1f8725a1..ed7adefcb8c 100644
--- a/src/librustc_resolve/late/diagnostics.rs
+++ b/src/librustc_resolve/late/diagnostics.rs
@@ -212,7 +212,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
         let ident = path.last().unwrap().ident;
         let candidates = self
             .r
-            .lookup_import_candidates(ident, ns, is_expected)
+            .lookup_import_candidates(ident, ns, &self.parent_scope, is_expected)
             .drain(..)
             .filter(|ImportSuggestion { did, .. }| {
                 match (did, res.and_then(|res| res.opt_def_id())) {
@@ -223,7 +223,8 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> {
             .collect::<Vec<_>>();
         let crate_def_id = DefId::local(CRATE_DEF_INDEX);
         if candidates.is_empty() && is_expected(Res::Def(DefKind::Enum, crate_def_id)) {
-            let enum_candidates = self.r.lookup_import_candidates(ident, ns, is_enum_variant);
+            let enum_candidates =
+                self.r.lookup_import_candidates(ident, ns, &self.parent_scope, is_enum_variant);
             let mut enum_candidates = enum_candidates
                 .iter()
                 .map(|suggestion| import_candidate_to_enum_paths(&suggestion))
diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs
index a3fbb28f22a..5bbf8703f0b 100644
--- a/src/librustc_resolve/late/lifetimes.rs
+++ b/src/librustc_resolve/late/lifetimes.rs
@@ -258,6 +258,9 @@ enum Elide {
     Exact(Region),
     /// Less or more than one lifetime were found, error on unspecified.
     Error(Vec<ElisionFailureInfo>),
+    /// Forbid lifetime elision inside of a larger scope where it would be
+    /// permitted. For example, in let position impl trait.
+    Forbid,
 }
 
 #[derive(Clone, Debug)]
@@ -396,15 +399,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 let scope = Scope::Elision { elide: Elide::Exact(Region::Static), s: ROOT_SCOPE };
                 self.with(scope, |_, this| intravisit::walk_item(this, item));
             }
-            hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(_), .. }) => {
-                // Currently opaque type declarations are just generated from `impl Trait`
-                // items. Doing anything on this node is irrelevant, as we currently don't need
-                // it.
+            hir::ItemKind::OpaqueTy(hir::OpaqueTy { .. }) => {
+                // Opaque types are visited when we visit the
+                // `TyKind::OpaqueDef`, so that they have the lifetimes from
+                // their parent opaque_ty in scope.
             }
             hir::ItemKind::TyAlias(_, ref generics)
-            | hir::ItemKind::OpaqueTy(hir::OpaqueTy {
-                impl_trait_fn: None, ref generics, ..
-            })
             | hir::ItemKind::Enum(_, ref generics)
             | hir::ItemKind::Struct(_, ref generics)
             | hir::ItemKind::Union(_, ref generics)
@@ -557,23 +557,35 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                 };
                 self.with(scope, |_, this| this.visit_ty(&mt.ty));
             }
-            hir::TyKind::Def(item_id, lifetimes) => {
+            hir::TyKind::OpaqueDef(item_id, lifetimes) => {
                 // Resolve the lifetimes in the bounds to the lifetime defs in the generics.
                 // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
                 // `type MyAnonTy<'b> = impl MyTrait<'b>;`
                 //                 ^                  ^ this gets resolved in the scope of
                 //                                      the opaque_ty generics
-                let (generics, bounds) = match self.tcx.hir().expect_item(item_id.id).kind {
+                let opaque_ty = self.tcx.hir().expect_item(item_id.id);
+                let (generics, bounds) = match opaque_ty.kind {
                     // Named opaque `impl Trait` types are reached via `TyKind::Path`.
                     // This arm is for `impl Trait` in the types of statics, constants and locals.
                     hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: None, .. }) => {
                         intravisit::walk_ty(self, ty);
+
+                        // Elided lifetimes are not allowed in non-return
+                        // position impl Trait
+                        let scope = Scope::Elision { elide: Elide::Forbid, s: self.scope };
+                        self.with(scope, |_, this| {
+                            intravisit::walk_item(this, opaque_ty);
+                        });
+
                         return;
                     }
                     // RPIT (return position impl trait)
-                    hir::ItemKind::OpaqueTy(hir::OpaqueTy { ref generics, bounds, .. }) => {
-                        (generics, bounds)
-                    }
+                    hir::ItemKind::OpaqueTy(hir::OpaqueTy {
+                        impl_trait_fn: Some(_),
+                        ref generics,
+                        bounds,
+                        ..
+                    }) => (generics, bounds),
                     ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
                 };
 
@@ -797,43 +809,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     this.visit_ty(ty);
                 });
             }
-            OpaqueTy(bounds) => {
-                let generics = &impl_item.generics;
-                let mut index = self.next_early_index();
-                let mut next_early_index = index;
-                debug!("visit_ty: index = {}", index);
-                let lifetimes = generics
-                    .params
-                    .iter()
-                    .filter_map(|param| match param.kind {
-                        GenericParamKind::Lifetime { .. } => {
-                            Some(Region::early(&self.tcx.hir(), &mut index, param))
-                        }
-                        GenericParamKind::Type { .. } => {
-                            next_early_index += 1;
-                            None
-                        }
-                        GenericParamKind::Const { .. } => {
-                            next_early_index += 1;
-                            None
-                        }
-                    })
-                    .collect();
-
-                let scope = Scope::Binder {
-                    lifetimes,
-                    next_early_index,
-                    s: self.scope,
-                    track_lifetime_uses: true,
-                    opaque_type_parent: true,
-                };
-                self.with(scope, |_old_scope, this| {
-                    this.visit_generics(generics);
-                    for bound in bounds {
-                        this.visit_param_bound(bound);
-                    }
-                });
-            }
             Const(_, _) => {
                 // Only methods and types support generics.
                 assert!(impl_item.generics.params.is_empty());
@@ -2367,6 +2342,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                             }
                             break Some(e);
                         }
+                        Elide::Forbid => break None,
                     };
                     for lifetime_ref in lifetime_refs {
                         self.insert_lifetime(lifetime_ref, lifetime);
@@ -2667,8 +2643,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
                 // going to make a fresh name, so we cannot
                 // necessarily replace a single-use lifetime with
                 // `'_`.
-                Scope::Elision { elide: Elide::Exact(_), .. } => break false,
-                Scope::Elision { elide: Elide::Error(_), .. } => break false,
+                Scope::Elision {
+                    elide: Elide::Exact(_) | Elide::Error(_) | Elide::Forbid, ..
+                } => break false,
 
                 Scope::ObjectLifetimeDefault { s, .. } => scope = s,
             }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 6bd73877fab..61792e039c7 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -2235,7 +2235,8 @@ impl<'a> Resolver<'a> {
                             Res::Def(DefKind::Mod, _) => true,
                             _ => false,
                         };
-                        let mut candidates = self.lookup_import_candidates(ident, TypeNS, is_mod);
+                        let mut candidates =
+                            self.lookup_import_candidates(ident, TypeNS, parent_scope, is_mod);
                         candidates.sort_by_cached_key(|c| {
                             (c.path.segments.len(), pprust::path_to_string(&c.path))
                         });
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 394d8dc4e11..1b49722355e 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -288,7 +288,8 @@ impl<'a> base::Resolver for Resolver<'a> {
 
         // Derives are not included when `invocations` are collected, so we have to add them here.
         let parent_scope = &ParentScope { derives, ..parent_scope };
-        let (ext, res) = self.smart_resolve_macro_path(path, kind, parent_scope, force)?;
+        let node_id = self.lint_node_id(eager_expansion_root);
+        let (ext, res) = self.smart_resolve_macro_path(path, kind, parent_scope, node_id, force)?;
 
         let span = invoc.span();
         invoc_id.set_expn_data(ext.expn_data(
@@ -338,6 +339,10 @@ impl<'a> base::Resolver for Resolver<'a> {
         }
     }
 
+    fn lint_node_id(&mut self, expn_id: ExpnId) -> NodeId {
+        self.definitions.lint_node_id(expn_id)
+    }
+
     fn has_derive_copy(&self, expn_id: ExpnId) -> bool {
         self.containers_deriving_copy.contains(&expn_id)
     }
@@ -390,6 +395,7 @@ impl<'a> Resolver<'a> {
         path: &ast::Path,
         kind: MacroKind,
         parent_scope: &ParentScope<'a>,
+        node_id: NodeId,
         force: bool,
     ) -> Result<(Lrc<SyntaxExtension>, Res), Indeterminate> {
         let (ext, res) = match self.resolve_macro_path(path, Some(kind), parent_scope, true, force)
@@ -430,7 +436,7 @@ impl<'a> Resolver<'a> {
             _ => panic!("expected `DefKind::Macro` or `Res::NonMacroAttr`"),
         };
 
-        self.check_stability_and_deprecation(&ext, path);
+        self.check_stability_and_deprecation(&ext, path, node_id);
 
         Ok(if ext.macro_kind() != kind {
             let expected = kind.descr_expected();
@@ -984,13 +990,17 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    fn check_stability_and_deprecation(&mut self, ext: &SyntaxExtension, path: &ast::Path) {
+    fn check_stability_and_deprecation(
+        &mut self,
+        ext: &SyntaxExtension,
+        path: &ast::Path,
+        node_id: NodeId,
+    ) {
         let span = path.span;
         if let Some(stability) = &ext.stability {
             if let StabilityLevel::Unstable { reason, issue, is_soft } = stability.level {
                 let feature = stability.feature;
                 if !self.active_features.contains(&feature) && !span.allows_unstable(feature) {
-                    let node_id = ast::CRATE_NODE_ID;
                     let lint_buffer = &mut self.lint_buffer;
                     let soft_handler =
                         |lint, span, msg: &_| lint_buffer.buffer_lint(lint, node_id, span, msg);
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 489d38b00df..e63e31e03c9 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -20,7 +20,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind as HirDefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir_pretty::{bounds_to_string, generic_params_to_string, ty_to_string};
+use rustc_hir_pretty::{bounds_to_string, fn_to_string, generic_params_to_string, ty_to_string};
 use rustc_middle::hir::map::Map;
 use rustc_middle::span_bug;
 use rustc_middle::ty::{self, DefIdTree, TyCtxt};
@@ -199,23 +199,23 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         self.dumper.compilation_opts(data);
     }
 
-    fn write_sub_paths(&mut self, path: &'tcx hir::Path<'tcx>) {
-        for seg in path.segments {
+    fn write_segments(&mut self, segments: impl IntoIterator<Item = &'tcx hir::PathSegment<'tcx>>) {
+        for seg in segments {
             if let Some(data) = self.save_ctxt.get_path_segment_data(seg) {
                 self.dumper.dump_ref(data);
             }
         }
     }
 
+    fn write_sub_paths(&mut self, path: &'tcx hir::Path<'tcx>) {
+        self.write_segments(path.segments)
+    }
+
     // As write_sub_paths, but does not process the last ident in the path (assuming it
     // will be processed elsewhere). See note on write_sub_paths about global.
     fn write_sub_paths_truncated(&mut self, path: &'tcx hir::Path<'tcx>) {
         if let [segments @ .., _] = path.segments {
-            for seg in segments {
-                if let Some(data) = self.save_ctxt.get_path_segment_data(seg) {
-                    self.dumper.dump_ref(data);
-                }
-            }
+            self.write_segments(segments)
         }
     }
 
@@ -276,7 +276,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                 }
                 v.process_generic_params(&generics, &method_data.qualname, hir_id);
 
-                method_data.value = crate::make_signature(&sig.decl, &generics);
+                method_data.value =
+                    fn_to_string(sig.decl, sig.header, Some(ident.name), generics, vis, &[], None);
                 method_data.sig = sig::method_signature(hir_id, ident, generics, sig, &v.save_ctxt);
 
                 v.dumper.dump_def(&access_from_vis!(v.save_ctxt, vis, hir_id), method_data);
@@ -643,7 +644,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         self.nest_tables(map.local_def_id(item.hir_id), |v| {
             v.visit_ty(&typ);
             if let &Some(ref trait_ref) = trait_ref {
-                v.process_path(trait_ref.hir_ref_id, &trait_ref.path);
+                v.process_path(trait_ref.hir_ref_id, &hir::QPath::Resolved(None, &trait_ref.path));
             }
             v.process_generic_params(generics, "", item.hir_id);
             for impl_item in impl_items {
@@ -746,7 +747,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         }
     }
 
-    fn dump_path_ref(&mut self, id: hir::HirId, path: &hir::Path<'tcx>) {
+    fn dump_path_ref(&mut self, id: hir::HirId, path: &hir::QPath<'tcx>) {
         let path_data = self.save_ctxt.get_path_data(id, path);
         if let Some(path_data) = path_data {
             self.dumper.dump_ref(path_data);
@@ -760,14 +761,30 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         }
     }
 
-    fn process_path(&mut self, id: hir::HirId, path: &'tcx hir::Path<'tcx>) {
-        if self.span.filter_generated(path.span) {
+    fn process_path(&mut self, id: hir::HirId, path: &hir::QPath<'tcx>) {
+        let span = match path {
+            hir::QPath::Resolved(_, path) => path.span,
+            hir::QPath::TypeRelative(_, segment) => segment.ident.span,
+        };
+        if self.span.filter_generated(span) {
             return;
         }
         self.dump_path_ref(id, path);
 
         // Type arguments
-        for seg in path.segments {
+        let segments = match path {
+            hir::QPath::Resolved(ty, path) => {
+                if let Some(ty) = ty {
+                    self.visit_ty(ty);
+                }
+                path.segments
+            }
+            hir::QPath::TypeRelative(ty, segment) => {
+                self.visit_ty(ty);
+                std::slice::from_ref(*segment)
+            }
+        };
+        for seg in segments {
             if let Some(ref generic_args) = seg.args {
                 for arg in generic_args.args {
                     if let hir::GenericArg::Type(ref ty) = arg {
@@ -777,7 +794,9 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
             }
         }
 
-        self.write_sub_paths_truncated(path);
+        if let hir::QPath::Resolved(_, path) = path {
+            self.write_sub_paths_truncated(path);
+        }
     }
 
     fn process_struct_lit(
@@ -931,9 +950,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
         }
 
         for (id, ref path) in collector.collected_paths {
-            if let hir::QPath::Resolved(_, path) = path {
-                self.process_path(id, path);
-            }
+            self.process_path(id, path);
         }
     }
 
@@ -1085,7 +1102,6 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
                     impl_item.span,
                 );
             }
-            hir::ImplItemKind::OpaqueTy(..) => {}
             hir::ImplItemKind::TyAlias(ref ty) => {
                 // FIXME: uses of the assoc type should ideally point to this
                 // 'def' and the name here should be a ref to the def in the
@@ -1135,7 +1151,10 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> {
     fn process_bounds(&mut self, bounds: hir::GenericBounds<'tcx>) {
         for bound in bounds {
             if let hir::GenericBound::Trait(ref trait_ref, _) = *bound {
-                self.process_path(trait_ref.trait_ref.hir_ref_id, &trait_ref.trait_ref.path)
+                self.process_path(
+                    trait_ref.trait_ref.hir_ref_id,
+                    &hir::QPath::Resolved(None, &trait_ref.trait_ref.path),
+                )
             }
         }
     }
@@ -1330,13 +1349,16 @@ impl<'l, 'tcx> Visitor<'tcx> for DumpVisitor<'l, 'tcx> {
     fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
         self.process_macro_use(t.span);
         match t.kind {
-            hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
+            hir::TyKind::Path(ref path) => {
                 if generated_code(t.span) {
                     return;
                 }
 
                 if let Some(id) = self.lookup_def_id(t.hir_id) {
-                    let sub_span = path.segments.last().unwrap().ident.span;
+                    let sub_span = match path {
+                        hir::QPath::Resolved(_, path) => path.segments.last().unwrap().ident.span,
+                        hir::QPath::TypeRelative(_, segment) => segment.ident.span,
+                    };
                     let span = self.span_from_span(sub_span);
                     self.dumper.dump_ref(Ref {
                         kind: RefKind::Type,
@@ -1345,8 +1367,10 @@ impl<'l, 'tcx> Visitor<'tcx> for DumpVisitor<'l, 'tcx> {
                     });
                 }
 
-                self.write_sub_paths_truncated(path);
-                intravisit::walk_path(self, path);
+                if let hir::QPath::Resolved(_, path) = path {
+                    self.write_sub_paths_truncated(path);
+                }
+                intravisit::walk_qpath(self, path, t.hir_id, t.span);
             }
             hir::TyKind::Array(ref ty, ref anon_const) => {
                 self.visit_ty(ty);
@@ -1355,6 +1379,10 @@ impl<'l, 'tcx> Visitor<'tcx> for DumpVisitor<'l, 'tcx> {
                     v.visit_expr(&map.body(anon_const.body).value)
                 });
             }
+            hir::TyKind::OpaqueDef(item_id, _) => {
+                let item = self.tcx.hir().item(item_id.id);
+                self.nest_tables(self.tcx.hir().local_def_id(item_id.id), |v| v.visit_item(item));
+            }
             _ => intravisit::walk_ty(self, t),
         }
     }
@@ -1375,7 +1403,9 @@ impl<'l, 'tcx> Visitor<'tcx> for DumpVisitor<'l, 'tcx> {
                 let res = self.save_ctxt.get_path_res(hir_expr.hir_id);
                 self.process_struct_lit(ex, path, fields, adt.variant_of_res(res), *base)
             }
-            hir::ExprKind::MethodCall(ref seg, _, args) => self.process_method_call(ex, seg, args),
+            hir::ExprKind::MethodCall(ref seg, _, args, _) => {
+                self.process_method_call(ex, seg, args)
+            }
             hir::ExprKind::Field(ref sub_ex, _) => {
                 self.visit_expr(&sub_ex);
 
@@ -1432,8 +1462,8 @@ impl<'l, 'tcx> Visitor<'tcx> for DumpVisitor<'l, 'tcx> {
         self.visit_expr(&arm.body);
     }
 
-    fn visit_path(&mut self, p: &'tcx hir::Path<'tcx>, id: hir::HirId) {
-        self.process_path(id, p);
+    fn visit_qpath(&mut self, path: &'tcx hir::QPath<'tcx>, id: hir::HirId, _: Span) {
+        self.process_path(id, path);
     }
 
     fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) {
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 0341b542526..12d2c8c7eb9 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -13,11 +13,11 @@ use rustc_ast::ast::{self};
 use rustc_ast::util::comments::strip_doc_comment_decoration;
 use rustc_ast_pretty::pprust::attribute_to_string;
 use rustc_hir as hir;
-use rustc_hir::def::{CtorOf, DefKind as HirDefKind, Res};
+use rustc_hir::def::{DefKind as HirDefKind, Res};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::Node;
-use rustc_hir_pretty::ty_to_string;
+use rustc_hir_pretty::{enum_def_to_string, fn_to_string, ty_to_string};
 use rustc_middle::hir::map::Map;
 use rustc_middle::middle::cstore::ExternCrate;
 use rustc_middle::middle::privacy::AccessLevels;
@@ -135,7 +135,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
         let def_id = self.tcx.hir().local_def_id(item.hir_id).to_def_id();
         let qualname = format!("::{}", self.tcx.def_path_str(def_id));
         match item.kind {
-            hir::ForeignItemKind::Fn(ref decl, _, ref generics) => {
+            hir::ForeignItemKind::Fn(ref decl, arg_names, ref generics) => {
                 filter!(self.span_utils, item.ident.span);
 
                 Some(Data::DefData(Def {
@@ -144,7 +144,23 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                     span: self.span_from_span(item.ident.span),
                     name: item.ident.to_string(),
                     qualname,
-                    value: make_signature(decl, generics),
+                    value: fn_to_string(
+                        decl,
+                        hir::FnHeader {
+                            // functions in extern block are implicitly unsafe
+                            unsafety: hir::Unsafety::Unsafe,
+                            // functions in extern block cannot be const
+                            constness: hir::Constness::NotConst,
+                            abi: self.tcx.hir().get_foreign_abi(item.hir_id),
+                            // functions in extern block cannot be async
+                            asyncness: hir::IsAsync::NotAsync,
+                        },
+                        Some(item.ident.name),
+                        generics,
+                        &item.vis,
+                        arg_names,
+                        None,
+                    ),
                     parent: None,
                     children: vec![],
                     decl_id: None,
@@ -191,7 +207,15 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                     span: self.span_from_span(item.ident.span),
                     name: item.ident.to_string(),
                     qualname,
-                    value: make_signature(&sig.decl, generics),
+                    value: fn_to_string(
+                        sig.decl,
+                        sig.header,
+                        Some(item.ident.name),
+                        generics,
+                        &item.vis,
+                        &[],
+                        None,
+                    ),
                     parent: None,
                     children: vec![],
                     decl_id: None,
@@ -268,13 +292,12 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                     attributes: lower_attributes(item.attrs.to_vec(), self),
                 }))
             }
-            hir::ItemKind::Enum(ref def, _) => {
+            hir::ItemKind::Enum(ref def, ref generics) => {
                 let name = item.ident.to_string();
                 let qualname = format!("::{}", self.tcx.def_path_str(def_id));
                 filter!(self.span_utils, item.ident.span);
-                let variants_str =
-                    def.variants.iter().map(|v| v.ident.to_string()).collect::<Vec<_>>().join(", ");
-                let value = format!("{}::{{{}}}", name, variants_str);
+                let value =
+                    enum_def_to_string(def, generics, item.ident.name, item.span, &item.vis);
                 Some(Data::DefData(Def {
                     kind: DefKind::Enum,
                     id: id_from_def_id(def_id),
@@ -579,7 +602,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                     ref_id: def_id.or(decl_id).map(id_from_def_id).unwrap_or_else(null_id),
                 }))
             }
-            hir::ExprKind::Path(hir::QPath::Resolved(_, path)) => {
+            hir::ExprKind::Path(ref path) => {
                 self.get_path_data(expr.hir_id, path).map(Data::RefData)
             }
             _ => {
@@ -631,8 +654,12 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
         }
     }
 
-    pub fn get_path_data(&self, id: hir::HirId, path: &hir::Path<'_>) -> Option<Ref> {
-        path.segments.last().and_then(|seg| {
+    pub fn get_path_data(&self, id: hir::HirId, path: &hir::QPath<'_>) -> Option<Ref> {
+        let segment = match path {
+            hir::QPath::Resolved(_, path) => path.segments.last(),
+            hir::QPath::TypeRelative(_, segment) => Some(*segment),
+        };
+        segment.and_then(|seg| {
             self.get_path_segment_data(seg).or_else(|| self.get_path_segment_data_with_id(seg, id))
         })
     }
@@ -671,7 +698,6 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
                 | HirDefKind::TyAlias
                 | HirDefKind::ForeignTy
                 | HirDefKind::TraitAlias
-                | HirDefKind::AssocOpaqueTy
                 | HirDefKind::AssocTy
                 | HirDefKind::Trait
                 | HirDefKind::OpaqueTy
@@ -681,20 +707,16 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
             Res::Def(HirDefKind::ConstParam, def_id) => {
                 Some(Ref { kind: RefKind::Variable, span, ref_id: id_from_def_id(def_id) })
             }
-            Res::Def(HirDefKind::Ctor(CtorOf::Struct, ..), def_id) => {
-                // This is a reference to a tuple struct where the def_id points
+            Res::Def(HirDefKind::Ctor(_, ..), def_id) => {
+                // This is a reference to a tuple struct or an enum variant where the def_id points
                 // to an invisible constructor function. That is not a very useful
-                // def, so adjust to point to the tuple struct itself.
+                // def, so adjust to point to the tuple struct or enum variant itself.
                 let parent_def_id = self.tcx.parent(def_id).unwrap();
                 Some(Ref { kind: RefKind::Type, span, ref_id: id_from_def_id(parent_def_id) })
             }
-            Res::Def(
-                HirDefKind::Static
-                | HirDefKind::Const
-                | HirDefKind::AssocConst
-                | HirDefKind::Ctor(..),
-                _,
-            ) => Some(Ref { kind: RefKind::Variable, span, ref_id: id_from_def_id(res.def_id()) }),
+            Res::Def(HirDefKind::Static | HirDefKind::Const | HirDefKind::AssocConst, _) => {
+                Some(Ref { kind: RefKind::Variable, span, ref_id: id_from_def_id(res.def_id()) })
+            }
             Res::Def(HirDefKind::AssocFn, decl_id) => {
                 let def_id = if decl_id.is_local() {
                     let ti = self.tcx.associated_item(decl_id);
@@ -844,31 +866,6 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> {
     }
 }
 
-fn make_signature(decl: &hir::FnDecl<'_>, generics: &hir::Generics<'_>) -> String {
-    let mut sig = "fn ".to_owned();
-    if !generics.params.is_empty() {
-        sig.push('<');
-        sig.push_str(
-            &generics
-                .params
-                .iter()
-                .map(|param| param.name.ident().to_string())
-                .collect::<Vec<_>>()
-                .join(", "),
-        );
-        sig.push_str("> ");
-    }
-    sig.push('(');
-    sig.push_str(&decl.inputs.iter().map(ty_to_string).collect::<Vec<_>>().join(", "));
-    sig.push(')');
-    match decl.output {
-        hir::FnRetTy::DefaultReturn(_) => sig.push_str(" -> ()"),
-        hir::FnRetTy::Return(ref t) => sig.push_str(&format!(" -> {}", ty_to_string(t))),
-    }
-
-    sig
-}
-
 // An AST visitor for collecting paths (e.g., the names of structs) and formal
 // variables (idents) from patterns.
 struct PathCollector<'l> {
@@ -1088,7 +1085,7 @@ fn id_from_hir_id(id: hir::HirId, scx: &SaveContext<'_, '_>) -> rls_data::Id {
 }
 
 fn null_id() -> rls_data::Id {
-    rls_data::Id { krate: u32::max_value(), index: u32::max_value() }
+    rls_data::Id { krate: u32::MAX, index: u32::MAX }
 }
 
 fn lower_attributes(
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index 6fec5cdba8b..cd2a5deeb2d 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -281,6 +281,22 @@ impl<'hir> Sig for hir::Ty<'hir> {
                     })
                 }
             }
+            hir::TyKind::Path(hir::QPath::TypeRelative(ty, segment)) => {
+                let nested_ty = ty.make(offset + 1, id, scx)?;
+                let prefix = format!("<{}>::", nested_ty.text,);
+
+                let name = path_segment_to_string(segment);
+                let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
+                let id = id_from_def_id(res.def_id());
+
+                let start = offset + prefix.len();
+                let end = start + name.len();
+                Ok(Signature {
+                    text: prefix + &name,
+                    defs: vec![],
+                    refs: vec![SigElement { id, start, end }],
+                })
+            }
             hir::TyKind::TraitObject(bounds, ..) => {
                 // FIXME recurse into bounds
                 let bounds: Vec<hir::GenericBound<'_>> = bounds
@@ -308,11 +324,11 @@ impl<'hir> Sig for hir::Ty<'hir> {
                 let text = format!("[{}; {}]", nested_ty.text, expr);
                 Ok(replace_text(nested_ty, text))
             }
-            hir::TyKind::Typeof(_)
-            | hir::TyKind::Infer
-            | hir::TyKind::Def(..)
-            | hir::TyKind::Path(..)
-            | hir::TyKind::Err => Err("Ty"),
+            hir::TyKind::OpaqueDef(item_id, _) => {
+                let item = scx.tcx.hir().item(item_id.id);
+                item.make(offset, Some(item_id.id), scx)
+            }
+            hir::TyKind::Typeof(_) | hir::TyKind::Infer | hir::TyKind::Err => Err("Ty"),
         }
     }
 }
diff --git a/src/librustc_serialize/lib.rs b/src/librustc_serialize/lib.rs
index 7261d631a6f..3dc3e783820 100644
--- a/src/librustc_serialize/lib.rs
+++ b/src/librustc_serialize/lib.rs
@@ -10,7 +10,7 @@ Core encoding and decoding interfaces.
     test(attr(allow(unused_variables), deny(warnings)))
 )]
 #![feature(box_syntax)]
-#![feature(specialization)] // FIXME: min_specialization does not work
+#![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(nll)]
 #![feature(associated_type_bounds)]
diff --git a/src/librustc_serialize/serialize.rs b/src/librustc_serialize/serialize.rs
index e80d16bb0c7..29c5737ad89 100644
--- a/src/librustc_serialize/serialize.rs
+++ b/src/librustc_serialize/serialize.rs
@@ -635,24 +635,6 @@ impl<T> Decodable for PhantomData<T> {
     }
 }
 
-impl<'a, T: ?Sized + Encodable> Encodable for &'a T {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        (**self).encode(s)
-    }
-}
-
-impl<T: ?Sized + Encodable> Encodable for Box<T> {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        (**self).encode(s)
-    }
-}
-
-impl<T: Decodable> Decodable for Box<T> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<Box<T>, D::Error> {
-        Ok(box Decodable::decode(d)?)
-    }
-}
-
 impl<T: Decodable> Decodable for Box<[T]> {
     fn decode<D: Decoder>(d: &mut D) -> Result<Box<[T]>, D::Error> {
         let v: Vec<T> = Decodable::decode(d)?;
@@ -1008,8 +990,20 @@ impl<T: UseSpecializedDecodable> Decodable for T {
 // for this exact reason.
 // May be fixable in a simpler fashion via the
 // more complex lattice model for specialization.
-impl<'a, T: ?Sized + Encodable> UseSpecializedEncodable for &'a T {}
-impl<T: ?Sized + Encodable> UseSpecializedEncodable for Box<T> {}
-impl<T: Decodable> UseSpecializedDecodable for Box<T> {}
+impl<'a, T: ?Sized + Encodable> UseSpecializedEncodable for &'a T {
+    fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        (**self).encode(s)
+    }
+}
+impl<T: ?Sized + Encodable> UseSpecializedEncodable for Box<T> {
+    fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        (**self).encode(s)
+    }
+}
+impl<T: Decodable> UseSpecializedDecodable for Box<T> {
+    fn default_decode<D: Decoder>(d: &mut D) -> Result<Box<T>, D::Error> {
+        Ok(box Decodable::decode(d)?)
+    }
+}
 impl<'a, T: Decodable> UseSpecializedDecodable for &'a T {}
 impl<'a, T: Decodable> UseSpecializedDecodable for &'a [T] {}
diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs
index 5bdd7b67723..411a6eecbba 100644
--- a/src/librustc_session/config.rs
+++ b/src/librustc_session/config.rs
@@ -1031,7 +1031,7 @@ pub fn get_cmd_lint_options(
                 // HACK: forbid is always specified last, so it can't be overridden.
                 // FIXME: remove this once <https://github.com/rust-lang/rust/issues/70819> is
                 // fixed and `forbid` works as expected.
-                usize::max_value()
+                usize::MAX
             } else {
                 passed_arg_pos
             };
diff --git a/src/librustc_session/lint/builtin.rs b/src/librustc_session/lint/builtin.rs
index bb0d6e1a47e..58388bafbed 100644
--- a/src/librustc_session/lint/builtin.rs
+++ b/src/librustc_session/lint/builtin.rs
@@ -606,6 +606,7 @@ declare_lint_pass! {
         INLINE_NO_SANITIZE,
         ASM_SUB_REGISTER,
         UNSAFE_OP_IN_UNSAFE_FN,
+        INCOMPLETE_INCLUDE,
     ]
 }
 
diff --git a/src/librustc_session/parse.rs b/src/librustc_session/parse.rs
index 233761dbed7..ddbc95fb1b0 100644
--- a/src/librustc_session/parse.rs
+++ b/src/librustc_session/parse.rs
@@ -119,7 +119,7 @@ pub struct ParseSess {
     pub unstable_features: UnstableFeatures,
     pub config: CrateConfig,
     pub edition: Edition,
-    pub missing_fragment_specifiers: Lock<FxHashSet<Span>>,
+    pub missing_fragment_specifiers: Lock<FxHashMap<Span, NodeId>>,
     /// Places where raw identifiers were used. This is used for feature-gating raw identifiers.
     pub raw_identifier_spans: Lock<Vec<Span>>,
     /// Used to determine and report recursive module inclusions.
@@ -150,7 +150,7 @@ impl ParseSess {
             unstable_features: UnstableFeatures::from_environment(),
             config: FxHashSet::default(),
             edition: ExpnId::root().expn_data().edition,
-            missing_fragment_specifiers: Lock::new(FxHashSet::default()),
+            missing_fragment_specifiers: Default::default(),
             raw_identifier_spans: Lock::new(Vec::new()),
             included_mod_stack: Lock::new(vec![]),
             source_map,
diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs
index 048033846a1..06d7d4f14d8 100644
--- a/src/librustc_session/session.rs
+++ b/src/librustc_session/session.rs
@@ -441,6 +441,9 @@ impl Session {
     pub fn span_note_without_error<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.diagnostic().span_note_without_error(sp, msg)
     }
+    pub fn struct_note_without_error(&self, msg: &str) -> DiagnosticBuilder<'_> {
+        self.diagnostic().struct_note_without_error(msg)
+    }
 
     pub fn diagnostic(&self) -> &rustc_errors::Handler {
         &self.parse_sess.span_diagnostic
diff --git a/src/librustc_span/def_id.rs b/src/librustc_span/def_id.rs
index fad9f2f6130..0a70be1f152 100644
--- a/src/librustc_span/def_id.rs
+++ b/src/librustc_span/def_id.rs
@@ -133,6 +133,8 @@ impl rustc_serialize::UseSpecializedDecodable for DefIndex {}
 
 /// A `DefId` identifies a particular *definition*, by combining a crate
 /// index and a def index.
+///
+/// You can create a `DefId` from a `LocalDefId` using `local_def_id.to_def_id()`.
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
 pub struct DefId {
     pub krate: CrateNum,
diff --git a/src/librustc_span/hygiene.rs b/src/librustc_span/hygiene.rs
index c0fb84e741f..f2c9f8055b9 100644
--- a/src/librustc_span/hygiene.rs
+++ b/src/librustc_span/hygiene.rs
@@ -822,7 +822,15 @@ pub enum DesugaringKind {
     OpaqueTy,
     Async,
     Await,
-    ForLoop,
+    ForLoop(ForLoopLoc),
+    Operator,
+}
+
+/// A location in the desugaring of a `for` loop
+#[derive(Clone, Copy, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable_Generic)]
+pub enum ForLoopLoc {
+    Head,
+    IntoIter,
 }
 
 impl DesugaringKind {
@@ -835,7 +843,8 @@ impl DesugaringKind {
             DesugaringKind::QuestionMark => "operator `?`",
             DesugaringKind::TryBlock => "`try` block",
             DesugaringKind::OpaqueTy => "`impl Trait`",
-            DesugaringKind::ForLoop => "`for` loop",
+            DesugaringKind::ForLoop(_) => "`for` loop",
+            DesugaringKind::Operator => "operator",
         }
     }
 }
diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs
index fbab99b2f8f..af9b5a264e3 100644
--- a/src/librustc_span/lib.rs
+++ b/src/librustc_span/lib.rs
@@ -31,7 +31,9 @@ pub mod edition;
 use edition::Edition;
 pub mod hygiene;
 use hygiene::Transparency;
-pub use hygiene::{DesugaringKind, ExpnData, ExpnId, ExpnKind, MacroKind, SyntaxContext};
+pub use hygiene::{
+    DesugaringKind, ExpnData, ExpnId, ExpnKind, ForLoopLoc, MacroKind, SyntaxContext,
+};
 pub mod def_id;
 use def_id::{CrateNum, DefId, LOCAL_CRATE};
 mod span_encoding;
@@ -726,10 +728,18 @@ pub fn with_source_map<T, F: FnOnce() -> T>(source_map: Lrc<SourceMap>, f: F) ->
     f()
 }
 
+pub fn debug_with_source_map(
+    span: Span,
+    f: &mut fmt::Formatter<'_>,
+    source_map: &SourceMap,
+) -> fmt::Result {
+    write!(f, "{} ({:?})", source_map.span_to_string(span), span.ctxt())
+}
+
 pub fn default_span_debug(span: Span, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     GLOBALS.with(|globals| {
         if let Some(source_map) = &*globals.source_map.borrow() {
-            write!(f, "{}", source_map.span_to_string(span))
+            debug_with_source_map(span, f, source_map)
         } else {
             f.debug_struct("Span")
                 .field("lo", &span.lo())
@@ -1250,7 +1260,7 @@ impl SourceFile {
             hasher.finish::<u128>()
         };
         let end_pos = start_pos.to_usize() + src.len();
-        assert!(end_pos <= u32::max_value() as usize);
+        assert!(end_pos <= u32::MAX as usize);
 
         let (lines, multibyte_chars, non_narrow_chars) =
             analyze_source_file::analyze_source_file(&src[..], start_pos);
diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs
index c33c1dd29cb..4b5bce1db26 100644
--- a/src/librustc_span/source_map.rs
+++ b/src/librustc_span/source_map.rs
@@ -819,9 +819,7 @@ impl SourceMap {
 
         // Disregard indexes that are at the start or end of their spans, they can't fit bigger
         // characters.
-        if (!forwards && end_index == usize::min_value())
-            || (forwards && start_index == usize::max_value())
-        {
+        if (!forwards && end_index == usize::MIN) || (forwards && start_index == usize::MAX) {
             debug!("find_width_of_character_at_span: start or end of span, cannot be multibyte");
             return 1;
         }
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index d165409696e..fdeb58b7b7a 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -120,6 +120,7 @@ symbols! {
         abi_unadjusted,
         abi_vectorcall,
         abi_x86_interrupt,
+        abi_avr_interrupt,
         abort,
         aborts,
         address,
@@ -226,6 +227,7 @@ symbols! {
         const_loop,
         const_mut_refs,
         const_panic,
+        const_precise_live_drops,
         const_raw_ptr_deref,
         const_raw_ptr_to_usize_cast,
         const_transmute,
diff --git a/src/librustc_target/abi/call/avr.rs b/src/librustc_target/abi/call/avr.rs
new file mode 100644
index 00000000000..c1f7a1e3af5
--- /dev/null
+++ b/src/librustc_target/abi/call/avr.rs
@@ -0,0 +1,59 @@
+//! LLVM-frontend specific AVR calling convention implementation.
+//!
+//! # Current calling convention ABI
+//!
+//! Inherited from Clang's `clang::DefaultABIInfo` implementation - self described
+//! as
+//!
+//! > the default implementation for ABI specific details. This implementation
+//! > provides information which results in
+//! > self-consistent and sensible LLVM IR generation, but does not
+//! > conform to any particular ABI.
+//! >
+//! > - Doxygen Doxumentation of `clang::DefaultABIInfo`
+//!
+//! This calling convention may not match AVR-GCC in all cases.
+//!
+//! In the future, an AVR-GCC compatible argument classification ABI should be
+//! adopted in both Rust and Clang.
+//!
+//! *NOTE*: Currently, this module implements the same calling convention
+//! that clang with AVR currently does - the default, simple, unspecialized
+//! ABI implementation available to all targets. This ABI is not
+//! binary-compatible with AVR-GCC. Once LLVM [PR46140](https://bugs.llvm.org/show_bug.cgi?id=46140)
+//! is completed, this module should be updated to match so that both Clang
+//! and Rust emit code to the same AVR-GCC compatible ABI.
+//!
+//! In particular, both Clang and Rust may not have the same semantics
+//! when promoting arguments to indirect references as AVR-GCC. It is important
+//! to note that the core AVR ABI implementation within LLVM itself is ABI
+//! compatible with AVR-GCC - Rust and AVR-GCC only differ in the small amount
+//! of compiler frontend specific calling convention logic implemented here.
+
+use crate::abi::call::{ArgAbi, FnAbi};
+
+fn classify_ret_ty<Ty>(ret: &mut ArgAbi<'_, Ty>) {
+    if ret.layout.is_aggregate() {
+        ret.make_indirect();
+    }
+}
+
+fn classify_arg_ty<Ty>(arg: &mut ArgAbi<'_, Ty>) {
+    if arg.layout.is_aggregate() {
+        arg.make_indirect();
+    }
+}
+
+pub fn compute_abi_info<Ty>(fty: &mut FnAbi<'_, Ty>) {
+    if !fty.ret.is_ignore() {
+        classify_ret_ty(&mut fty.ret);
+    }
+
+    for arg in &mut fty.args {
+        if arg.is_ignore() {
+            continue;
+        }
+
+        classify_arg_ty(arg);
+    }
+}
diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs
index 0303312d057..8f7e2bba5aa 100644
--- a/src/librustc_target/abi/call/mod.rs
+++ b/src/librustc_target/abi/call/mod.rs
@@ -5,6 +5,7 @@ use crate::spec::{self, HasTargetSpec};
 mod aarch64;
 mod amdgpu;
 mod arm;
+mod avr;
 mod hexagon;
 mod mips;
 mod mips64;
@@ -525,6 +526,8 @@ pub enum Conv {
     X86_64Win64,
 
     AmdGpuKernel,
+    AvrInterrupt,
+    AvrNonBlockingInterrupt,
 }
 
 /// Metadata describing how the arguments to a native function
@@ -580,6 +583,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
             "aarch64" => aarch64::compute_abi_info(cx, self),
             "amdgpu" => amdgpu::compute_abi_info(cx, self),
             "arm" => arm::compute_abi_info(cx, self),
+            "avr" => avr::compute_abi_info(self),
             "mips" => mips::compute_abi_info(cx, self),
             "mips64" => mips64::compute_abi_info(cx, self),
             "powerpc" => powerpc::compute_abi_info(self),
diff --git a/src/librustc_target/spec/aarch64_apple_ios.rs b/src/librustc_target/spec/aarch64_apple_ios.rs
index eac2c3e6aa4..1447716ca84 100644
--- a/src/librustc_target/spec/aarch64_apple_ios.rs
+++ b/src/librustc_target/spec/aarch64_apple_ios.rs
@@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
         target_vendor: "apple".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
-            features: "+neon,+fp-armv8,+cyclone".to_string(),
+            features: "+neon,+fp-armv8,+apple-a7".to_string(),
             eliminate_frame_pointer: false,
             max_atomic_width: Some(128),
             abi_blacklist: super::arm_base::abi_blacklist(),
diff --git a/src/librustc_target/spec/aarch64_apple_tvos.rs b/src/librustc_target/spec/aarch64_apple_tvos.rs
index f1cd14ffd11..21f660ac8b8 100644
--- a/src/librustc_target/spec/aarch64_apple_tvos.rs
+++ b/src/librustc_target/spec/aarch64_apple_tvos.rs
@@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
         target_vendor: "apple".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
-            features: "+neon,+fp-armv8,+cyclone".to_string(),
+            features: "+neon,+fp-armv8,+apple-a7".to_string(),
             eliminate_frame_pointer: false,
             max_atomic_width: Some(128),
             abi_blacklist: super::arm_base::abi_blacklist(),
diff --git a/src/librustc_target/spec/abi.rs b/src/librustc_target/spec/abi.rs
index 226fe0b8bc6..a5c874bb4ac 100644
--- a/src/librustc_target/spec/abi.rs
+++ b/src/librustc_target/spec/abi.rs
@@ -34,6 +34,8 @@ pub enum Abi {
     X86Interrupt,
     AmdGpuKernel,
     EfiApi,
+    AvrInterrupt,
+    AvrNonBlockingInterrupt,
 
     // Multiplatform / generic ABIs
     System,
@@ -73,6 +75,12 @@ const AbiDatas: &[AbiData] = &[
     AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt", generic: false },
     AbiData { abi: Abi::AmdGpuKernel, name: "amdgpu-kernel", generic: false },
     AbiData { abi: Abi::EfiApi, name: "efiapi", generic: false },
+    AbiData { abi: Abi::AvrInterrupt, name: "avr-interrupt", generic: false },
+    AbiData {
+        abi: Abi::AvrNonBlockingInterrupt,
+        name: "avr-non-blocking-interrupt",
+        generic: false,
+    },
     // Cross-platform ABIs
     AbiData { abi: Abi::System, name: "system", generic: true },
     AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic", generic: true },
diff --git a/src/librustc_target/spec/apple_sdk_base.rs b/src/librustc_target/spec/apple_sdk_base.rs
index c7cff17b154..b07c2aef1ca 100644
--- a/src/librustc_target/spec/apple_sdk_base.rs
+++ b/src/librustc_target/spec/apple_sdk_base.rs
@@ -122,7 +122,7 @@ fn target_cpu(arch: Arch) -> String {
     match arch {
         Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
         Armv7s => "cortex-a9",
-        Arm64 => "cyclone",
+        Arm64 => "apple-a7",
         I386 => "yonah",
         X86_64 => "core2",
         X86_64_macabi => "core2",
diff --git a/src/librustc_target/spec/avr_unknown_unknown.rs b/src/librustc_target/spec/avr_unknown_unknown.rs
new file mode 100644
index 00000000000..f90a8def0aa
--- /dev/null
+++ b/src/librustc_target/spec/avr_unknown_unknown.rs
@@ -0,0 +1,17 @@
+use crate::spec::{LinkerFlavor, Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    Ok(Target {
+        llvm_target: "avr-unknown-unknown".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "16".to_string(),
+        data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".to_string(),
+        arch: "avr".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        target_os: "unknown".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
+        target_c_int_width: 16.to_string(),
+        options: super::freestanding_base::opts(),
+    })
+}
diff --git a/src/librustc_target/spec/freestanding_base.rs b/src/librustc_target/spec/freestanding_base.rs
new file mode 100644
index 00000000000..5402ea074fa
--- /dev/null
+++ b/src/librustc_target/spec/freestanding_base.rs
@@ -0,0 +1,30 @@
+use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
+use std::default::Default;
+
+pub fn opts() -> TargetOptions {
+    let mut args = LinkArgs::new();
+
+    args.insert(
+        LinkerFlavor::Gcc,
+        vec![
+            // We want to be able to strip as much executable code as possible
+            // from the linker command line, and this flag indicates to the
+            // linker that it can avoid linking in dynamic libraries that don't
+            // actually satisfy any symbols up to that point (as with many other
+            // resolutions the linker does). This option only applies to all
+            // following libraries so we're sure to pass it as one of the first
+            // arguments.
+            "-Wl,--as-needed".to_string(),
+        ],
+    );
+
+    TargetOptions {
+        dynamic_linking: false,
+        executables: true,
+        linker_is_gnu: true,
+        has_rpath: false,
+        pre_link_args: args,
+        position_independent_executables: false,
+        ..Default::default()
+    }
+}
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index f329c8c06cc..29250f21383 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -54,6 +54,7 @@ mod arm_base;
 mod cloudabi_base;
 mod dragonfly_base;
 mod freebsd_base;
+mod freestanding_base;
 mod fuchsia_base;
 mod haiku_base;
 mod hermit_base;
@@ -579,6 +580,8 @@ supported_targets! {
     ("aarch64-fuchsia", aarch64_fuchsia),
     ("x86_64-fuchsia", x86_64_fuchsia),
 
+    ("avr-unknown-unknown", avr_unknown_unknown),
+
     ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc),
 
     ("aarch64-unknown-redox", aarch64_unknown_redox),
diff --git a/src/librustc_target/spec/windows_gnu_base.rs b/src/librustc_target/spec/windows_gnu_base.rs
index f556bf03f02..680dbbad4b0 100644
--- a/src/librustc_target/spec/windows_gnu_base.rs
+++ b/src/librustc_target/spec/windows_gnu_base.rs
@@ -17,20 +17,21 @@ pub fn opts() -> TargetOptions {
     let mut late_link_args = LinkArgs::new();
     let mut late_link_args_dynamic = LinkArgs::new();
     let mut late_link_args_static = LinkArgs::new();
+    // Order of `late_link_args*` was found through trial and error to work with various
+    // mingw-w64 versions (not tested on the CI). It's expected to change from time to time.
     late_link_args.insert(
         LinkerFlavor::Gcc,
         vec![
+            "-lmsvcrt".to_string(),
             "-lmingwex".to_string(),
             "-lmingw32".to_string(),
-            "-lmsvcrt".to_string(),
             // mingw's msvcrt is a weird hybrid import library and static library.
             // And it seems that the linker fails to use import symbols from msvcrt
             // that are required from functions in msvcrt in certain cases. For example
             // `_fmode` that is used by an implementation of `__p__fmode` in x86_64.
-            // Listing the library twice seems to fix that, and seems to also be done
-            // by mingw's gcc (Though not sure if it's done on purpose, or by mistake).
+            // The library is purposely listed twice to fix that.
             //
-            // See https://github.com/rust-lang/rust/pull/47483
+            // See https://github.com/rust-lang/rust/pull/47483 for some more details.
             "-lmsvcrt".to_string(),
             "-luser32".to_string(),
             "-lkernel32".to_string(),
diff --git a/src/librustc_trait_selection/infer.rs b/src/librustc_trait_selection/infer.rs
index 66df4fe9511..f244785b49d 100644
--- a/src/librustc_trait_selection/infer.rs
+++ b/src/librustc_trait_selection/infer.rs
@@ -90,7 +90,7 @@ pub trait InferCtxtBuilderExt<'tcx> {
     where
         K: TypeFoldable<'tcx>,
         R: Debug + TypeFoldable<'tcx>,
-        Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable;
+        Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>;
 }
 
 impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
@@ -118,7 +118,7 @@ impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
     where
         K: TypeFoldable<'tcx>,
         R: Debug + TypeFoldable<'tcx>,
-        Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable,
+        Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>,
     {
         self.enter_with_canonical(
             DUMMY_SP,
diff --git a/src/librustc_trait_selection/lib.rs b/src/librustc_trait_selection/lib.rs
index 044239b047a..ea886cd1f9e 100644
--- a/src/librustc_trait_selection/lib.rs
+++ b/src/librustc_trait_selection/lib.rs
@@ -16,7 +16,6 @@
 #![feature(in_band_lifetimes)]
 #![feature(crate_visibility_modifier)]
 #![feature(or_patterns)]
-#![feature(option_zip)]
 #![recursion_limit = "512"] // For rustdoc
 
 #[macro_use]
diff --git a/src/librustc_trait_selection/opaque_types.rs b/src/librustc_trait_selection/opaque_types.rs
index 19caf64c63f..d53a0ec9ef8 100644
--- a/src/librustc_trait_selection/opaque_types.rs
+++ b/src/librustc_trait_selection/opaque_types.rs
@@ -11,7 +11,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
 use rustc_infer::infer::{self, InferCtxt, InferOk};
 use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
-use rustc_middle::ty::{self, GenericParamDefKind, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::config::nightly_options;
 use rustc_span::Span;
 
@@ -133,9 +133,9 @@ pub trait InferCtxtExt<'tcx> {
     fn generate_member_constraint(
         &self,
         concrete_ty: Ty<'tcx>,
-        opaque_type_generics: &ty::Generics,
         opaque_defn: &OpaqueTypeDecl<'tcx>,
         opaque_type_def_id: DefId,
+        first_own_region_index: usize,
     );
 
     /*private*/
@@ -405,7 +405,24 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
 
         debug!("constrain_opaque_type: concrete_ty={:?}", concrete_ty);
 
-        let opaque_type_generics = tcx.generics_of(def_id);
+        let first_own_region = match opaque_defn.origin {
+            hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => {
+                // We lower
+                //
+                // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
+                //
+                // into
+                //
+                // type foo::<'p0..'pn>::Foo<'q0..'qm>
+                // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
+                //
+                // For these types we onlt iterate over `'l0..lm` below.
+                tcx.generics_of(def_id).parent_count
+            }
+            // These opaque type inherit all lifetime parameters from their
+            // parent, so we have to check them all.
+            hir::OpaqueTyOrigin::Binding | hir::OpaqueTyOrigin::Misc => 0,
+        };
 
         let span = tcx.def_span(def_id);
 
@@ -427,12 +444,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 });
             }
             if let GenerateMemberConstraints::IfNoStaticBound = mode {
-                self.generate_member_constraint(
-                    concrete_ty,
-                    opaque_type_generics,
-                    opaque_defn,
-                    def_id,
-                );
+                self.generate_member_constraint(concrete_ty, opaque_defn, def_id, first_own_region);
             }
             return;
         }
@@ -445,29 +457,27 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         // `['a]` for the first impl trait and `'b` for the
         // second.
         let mut least_region = None;
-        for param in &opaque_type_generics.params {
-            match param.kind {
-                GenericParamDefKind::Lifetime => {}
-                _ => continue,
-            }
 
-            // Get the value supplied for this region from the substs.
-            let subst_arg = opaque_defn.substs.region_at(param.index as usize);
+        for subst_arg in &opaque_defn.substs[first_own_region..] {
+            let subst_region = match subst_arg.unpack() {
+                GenericArgKind::Lifetime(r) => r,
+                GenericArgKind::Type(_) | GenericArgKind::Const(_) => continue,
+            };
 
             // Compute the least upper bound of it with the other regions.
             debug!("constrain_opaque_types: least_region={:?}", least_region);
-            debug!("constrain_opaque_types: subst_arg={:?}", subst_arg);
+            debug!("constrain_opaque_types: subst_region={:?}", subst_region);
             match least_region {
-                None => least_region = Some(subst_arg),
+                None => least_region = Some(subst_region),
                 Some(lr) => {
-                    if free_region_relations.sub_free_regions(self.tcx, lr, subst_arg) {
+                    if free_region_relations.sub_free_regions(self.tcx, lr, subst_region) {
                         // keep the current least region
-                    } else if free_region_relations.sub_free_regions(self.tcx, subst_arg, lr) {
-                        // switch to `subst_arg`
-                        least_region = Some(subst_arg);
+                    } else if free_region_relations.sub_free_regions(self.tcx, subst_region, lr) {
+                        // switch to `subst_region`
+                        least_region = Some(subst_region);
                     } else {
                         // There are two regions (`lr` and
-                        // `subst_arg`) which are not relatable. We
+                        // `subst_region`) which are not relatable. We
                         // can't find a best choice. Therefore,
                         // instead of creating a single bound like
                         // `'r: 'a` (which is our preferred choice),
@@ -476,13 +486,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         // regions that appear in the impl trait.
 
                         // For now, enforce a feature gate outside of async functions.
-                        self.member_constraint_feature_gate(opaque_defn, def_id, lr, subst_arg);
+                        self.member_constraint_feature_gate(opaque_defn, def_id, lr, subst_region);
 
                         return self.generate_member_constraint(
                             concrete_ty,
-                            opaque_type_generics,
                             opaque_defn,
                             def_id,
+                            first_own_region,
                         );
                     }
                 }
@@ -494,12 +504,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
 
         if let GenerateMemberConstraints::IfNoStaticBound = mode {
             if least_region != tcx.lifetimes.re_static {
-                self.generate_member_constraint(
-                    concrete_ty,
-                    opaque_type_generics,
-                    opaque_defn,
-                    def_id,
-                );
+                self.generate_member_constraint(concrete_ty, opaque_defn, def_id, first_own_region);
             }
         }
         concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
@@ -518,22 +523,20 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
     fn generate_member_constraint(
         &self,
         concrete_ty: Ty<'tcx>,
-        opaque_type_generics: &ty::Generics,
         opaque_defn: &OpaqueTypeDecl<'tcx>,
         opaque_type_def_id: DefId,
+        first_own_region: usize,
     ) {
         // Create the set of choice regions: each region in the hidden
         // type can be equal to any of the region parameters of the
         // opaque type definition.
         let choice_regions: Lrc<Vec<ty::Region<'tcx>>> = Lrc::new(
-            opaque_type_generics
-                .params
+            opaque_defn.substs[first_own_region..]
                 .iter()
-                .filter(|param| match param.kind {
-                    GenericParamDefKind::Lifetime => true,
-                    GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => false,
+                .filter_map(|arg| match arg.unpack() {
+                    GenericArgKind::Lifetime(r) => Some(r),
+                    GenericArgKind::Type(_) | GenericArgKind::Const(_) => None,
                 })
-                .map(|param| opaque_defn.substs.region_at(param.index as usize))
                 .chain(std::iter::once(self.tcx.lifetimes.re_static))
                 .collect(),
         );
@@ -574,7 +577,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             hir::OpaqueTyOrigin::AsyncFn => return false,
 
             // Otherwise, generate the label we'll use in the error message.
-            hir::OpaqueTyOrigin::TypeAlias
+            hir::OpaqueTyOrigin::Binding
             | hir::OpaqueTyOrigin::FnReturn
             | hir::OpaqueTyOrigin::Misc => "impl Trait",
         };
@@ -1064,21 +1067,10 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
                                     ),
                                     origin,
                                 ),
-                                _ => (def_scope_default(), hir::OpaqueTyOrigin::TypeAlias),
-                            },
-                            Some(Node::ImplItem(item)) => match item.kind {
-                                hir::ImplItemKind::OpaqueTy(_) => (
-                                    may_define_opaque_type(
-                                        tcx,
-                                        self.parent_def_id.expect_local(),
-                                        opaque_hir_id,
-                                    ),
-                                    hir::OpaqueTyOrigin::TypeAlias,
-                                ),
-                                _ => (def_scope_default(), hir::OpaqueTyOrigin::TypeAlias),
+                                _ => (def_scope_default(), hir::OpaqueTyOrigin::Misc),
                             },
                             _ => bug!(
-                                "expected (impl) item, found {}",
+                                "expected item, found {}",
                                 tcx.hir().node_to_string(opaque_hir_id),
                             ),
                         };
diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs
index 1b72a4bf84f..d31e04cffd5 100644
--- a/src/librustc_trait_selection/traits/error_reporting/mod.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs
@@ -1747,24 +1747,41 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
 pub fn recursive_type_with_infinite_size_error(
     tcx: TyCtxt<'tcx>,
     type_def_id: DefId,
-) -> DiagnosticBuilder<'tcx> {
+    spans: Vec<Span>,
+) {
     assert!(type_def_id.is_local());
     let span = tcx.hir().span_if_local(type_def_id).unwrap();
     let span = tcx.sess.source_map().guess_head_span(span);
-    let mut err = struct_span_err!(
-        tcx.sess,
-        span,
-        E0072,
-        "recursive type `{}` has infinite size",
-        tcx.def_path_str(type_def_id)
-    );
+    let path = tcx.def_path_str(type_def_id);
+    let mut err =
+        struct_span_err!(tcx.sess, span, E0072, "recursive type `{}` has infinite size", path);
     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
+    for &span in &spans {
+        err.span_label(span, "recursive without indirection");
+    }
+    let msg = format!(
+        "insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `{}` representable",
+        path,
+    );
+    if spans.len() <= 4 {
+        err.multipart_suggestion(
+            &msg,
+            spans
+                .iter()
+                .flat_map(|&span| {
+                    vec![
+                        (span.shrink_to_lo(), "Box<".to_string()),
+                        (span.shrink_to_hi(), ">".to_string()),
+                    ]
+                    .into_iter()
+                })
+                .collect(),
+            Applicability::HasPlaceholders,
+        );
+    } else {
+        err.help(&msg);
+    }
+    err.emit();
 }
 
 /// Summarizes information
diff --git a/src/librustc_trait_selection/traits/mod.rs b/src/librustc_trait_selection/traits/mod.rs
index 6abea18ee29..9ab87e6b6ca 100644
--- a/src/librustc_trait_selection/traits/mod.rs
+++ b/src/librustc_trait_selection/traits/mod.rs
@@ -60,7 +60,6 @@ pub use self::specialize::specialization_graph::FutureCompatOverlapError;
 pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
 pub use self::specialize::{specialization_graph, translate_substs, OverlapError};
 pub use self::structural_match::search_for_structural_match_violation;
-pub use self::structural_match::type_marked_structural;
 pub use self::structural_match::NonStructuralMatchTy;
 pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
 pub use self::util::{expand_trait_aliases, TraitAliasExpander};
@@ -553,6 +552,7 @@ fn type_implements_trait<'tcx>(
 
 pub fn provide(providers: &mut ty::query::Providers<'_>) {
     object_safety::provide(providers);
+    structural_match::provide(providers);
     *providers = ty::query::Providers {
         specialization_graph_of: specialize::specialization_graph_provider,
         specializes: specialize::specializes,
diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs
index d6c79d1973a..9492c3c3409 100644
--- a/src/librustc_trait_selection/traits/project.rs
+++ b/src/librustc_trait_selection/traits/project.rs
@@ -25,7 +25,7 @@ use rustc_errors::ErrorReported;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::{FnOnceTraitLangItem, GeneratorTraitLangItem};
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
 use rustc_span::symbol::{sym, Ident};
@@ -1477,12 +1477,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
     let substs =
         translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.defining_node);
-    let ty = if let ty::AssocKind::OpaqueTy = assoc_ty.item.kind {
-        let item_substs = InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
-        tcx.mk_opaque(assoc_ty.item.def_id, item_substs)
-    } else {
-        tcx.type_of(assoc_ty.item.def_id)
-    };
+    let ty = tcx.type_of(assoc_ty.item.def_id);
     if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() {
         tcx.sess
             .delay_span_bug(DUMMY_SP, "impl item and trait item have different parameter counts");
@@ -1515,7 +1510,7 @@ fn assoc_ty_def(
     // cycle error if the specialization graph is currently being built.
     let impl_node = specialization_graph::Node::Impl(impl_def_id);
     for item in impl_node.items(tcx) {
-        if matches!(item.kind, ty::AssocKind::Type | ty::AssocKind::OpaqueTy)
+        if matches!(item.kind, ty::AssocKind::Type)
             && tcx.hygienic_eq(item.ident, assoc_ty_name, trait_def_id)
         {
             return Ok(specialization_graph::LeafDef {
diff --git a/src/librustc_trait_selection/traits/select/candidate_assembly.rs b/src/librustc_trait_selection/traits/select/candidate_assembly.rs
index d42c31a5474..9045451056b 100644
--- a/src/librustc_trait_selection/traits/select/candidate_assembly.rs
+++ b/src/librustc_trait_selection/traits/select/candidate_assembly.rs
@@ -331,6 +331,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     ) -> Result<(), SelectionError<'tcx>> {
         debug!("assemble_candidates_from_impls(obligation={:?})", obligation);
 
+        // Essentially any user-written impl will match with an error type,
+        // so creating `ImplCandidates` isn't useful. However, we might
+        // end up finding a candidate elsewhere (e.g. a `BuiltinCandidate` for `Sized)
+        // This helps us avoid overflow: see issue #72839
+        // Since compilation is already guaranteed to fail, this is just
+        // to try to show the 'nicest' possible errors to the user.
+        if obligation.references_error() {
+            return Ok(());
+        }
+
         self.tcx().for_each_relevant_impl(
             obligation.predicate.def_id(),
             obligation.predicate.skip_binder().trait_ref.self_ty(),
diff --git a/src/librustc_trait_selection/traits/select/mod.rs b/src/librustc_trait_selection/traits/select/mod.rs
index def99a7b5b5..7ebf30f61c0 100644
--- a/src/librustc_trait_selection/traits/select/mod.rs
+++ b/src/librustc_trait_selection/traits/select/mod.rs
@@ -1104,6 +1104,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // who might care about this case, like coherence, should use
         // that function).
         if candidates.is_empty() {
+            // If there's an error type, 'downgrade' our result from
+            // `Err(Unimplemented)` to `Ok(None)`. This helps us avoid
+            // emitting additional spurious errors, since we're guaranteed
+            // to have emitted at least one.
+            if stack.obligation.references_error() {
+                debug!("no results for error type, treating as ambiguous");
+                return Ok(None);
+            }
             return Err(Unimplemented);
         }
 
diff --git a/src/librustc_trait_selection/traits/structural_match.rs b/src/librustc_trait_selection/traits/structural_match.rs
index b877049fcf6..c4deb639140 100644
--- a/src/librustc_trait_selection/traits/structural_match.rs
+++ b/src/librustc_trait_selection/traits/structural_match.rs
@@ -1,10 +1,11 @@
 use crate::infer::{InferCtxt, TyCtxtInferExt};
 use crate::traits::ObligationCause;
-use crate::traits::{self, ConstPatternStructural, TraitEngine};
+use crate::traits::{self, TraitEngine};
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::lang_items::{StructuralPeqTraitLangItem, StructuralTeqTraitLangItem};
+use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeFoldable, TypeVisitor};
 use rustc_span::Span;
 
@@ -17,6 +18,7 @@ pub enum NonStructuralMatchTy<'tcx> {
     Opaque,
     Generator,
     Projection,
+    Closure,
 }
 
 /// This method traverses the structure of `ty`, trying to find an
@@ -45,14 +47,14 @@ pub enum NonStructuralMatchTy<'tcx> {
 /// that arose when the requirement was not enforced completely, see
 /// Rust RFC 1445, rust-lang/rust#61188, and rust-lang/rust#62307.
 pub fn search_for_structural_match_violation<'tcx>(
-    id: hir::HirId,
+    _id: hir::HirId,
     span: Span,
     tcx: TyCtxt<'tcx>,
     ty: Ty<'tcx>,
 ) -> Option<NonStructuralMatchTy<'tcx>> {
     // FIXME: we should instead pass in an `infcx` from the outside.
     tcx.infer_ctxt().enter(|infcx| {
-        let mut search = Search { id, span, infcx, found: None, seen: FxHashSet::default() };
+        let mut search = Search { infcx, span, found: None, seen: FxHashSet::default() };
         ty.visit_with(&mut search);
         search.found
     })
@@ -65,27 +67,26 @@ pub fn search_for_structural_match_violation<'tcx>(
 ///
 /// Note that this does *not* recursively check if the substructure of `adt_ty`
 /// implements the traits.
-pub fn type_marked_structural(
-    id: hir::HirId,
-    span: Span,
+fn type_marked_structural(
     infcx: &InferCtxt<'_, 'tcx>,
     adt_ty: Ty<'tcx>,
+    cause: ObligationCause<'tcx>,
 ) -> bool {
     let mut fulfillment_cx = traits::FulfillmentContext::new();
-    let cause = ObligationCause::new(span, id, ConstPatternStructural);
     // require `#[derive(PartialEq)]`
-    let structural_peq_def_id = infcx.tcx.require_lang_item(StructuralPeqTraitLangItem, Some(span));
+    let structural_peq_def_id =
+        infcx.tcx.require_lang_item(StructuralPeqTraitLangItem, Some(cause.span));
     fulfillment_cx.register_bound(
         infcx,
         ty::ParamEnv::empty(),
         adt_ty,
         structural_peq_def_id,
-        cause,
+        cause.clone(),
     );
     // for now, require `#[derive(Eq)]`. (Doing so is a hack to work around
     // the type `for<'a> fn(&'a ())` failing to implement `Eq` itself.)
-    let cause = ObligationCause::new(span, id, ConstPatternStructural);
-    let structural_teq_def_id = infcx.tcx.require_lang_item(StructuralTeqTraitLangItem, Some(span));
+    let structural_teq_def_id =
+        infcx.tcx.require_lang_item(StructuralTeqTraitLangItem, Some(cause.span));
     fulfillment_cx.register_bound(
         infcx,
         ty::ParamEnv::empty(),
@@ -110,7 +111,6 @@ pub fn type_marked_structural(
 /// find instances of ADTs (specifically structs or enums) that do not implement
 /// the structural-match traits (`StructuralPartialEq` and `StructuralEq`).
 struct Search<'a, 'tcx> {
-    id: hir::HirId,
     span: Span,
 
     infcx: InferCtxt<'a, 'tcx>,
@@ -129,7 +129,7 @@ impl Search<'a, 'tcx> {
     }
 
     fn type_marked_structural(&self, adt_ty: Ty<'tcx>) -> bool {
-        type_marked_structural(self.id, self.span, &self.infcx, adt_ty)
+        adt_ty.is_structural_eq_shallow(self.tcx())
     }
 }
 
@@ -163,6 +163,10 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
                 self.found = Some(NonStructuralMatchTy::Generator);
                 return true; // Stop visiting.
             }
+            ty::Closure(..) => {
+                self.found = Some(NonStructuralMatchTy::Closure);
+                return true; // Stop visiting.
+            }
             ty::RawPtr(..) => {
                 // structural-match ignores substructure of
                 // `*const _`/`*mut _`, so skip `super_visit_with`.
@@ -212,7 +216,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
                 ty.super_visit_with(self);
                 return false;
             }
-            ty::Closure(..) | ty::Infer(_) | ty::Placeholder(_) | ty::Bound(..) => {
+            ty::Infer(_) | ty::Placeholder(_) | ty::Bound(..) => {
                 bug!("unexpected type during structural-match checking: {:?}", ty);
             }
             ty::Error => {
@@ -251,7 +255,10 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
         // fields of ADT.
         let tcx = self.tcx();
         for field_ty in adt_def.all_fields().map(|field| field.ty(tcx, substs)) {
-            if field_ty.visit_with(self) {
+            let ty = self.tcx().normalize_erasing_regions(ty::ParamEnv::empty(), field_ty);
+            debug!("structural-match ADT: field_ty={:?}, ty={:?}", field_ty, ty);
+
+            if ty.visit_with(self) {
                 // found an ADT without structural-match; halt visiting!
                 assert!(self.found.is_some());
                 return true;
@@ -263,3 +270,12 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
         false
     }
 }
+
+pub fn provide(providers: &mut Providers<'_>) {
+    providers.has_structural_eq_impls = |tcx, ty| {
+        tcx.infer_ctxt().enter(|infcx| {
+            let cause = ObligationCause::dummy();
+            type_marked_structural(&infcx, ty, cause)
+        })
+    };
+}
diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs
index 3da5da2d9ef..99094246a63 100644
--- a/src/librustc_ty/ty.rs
+++ b/src/librustc_ty/ty.rs
@@ -85,7 +85,6 @@ fn associated_item_from_trait_item_ref(
         hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
         hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
         hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
-        hir::AssocItemKind::OpaqueTy => bug!("only impls can have opaque types"),
     };
 
     ty::AssocItem {
@@ -110,7 +109,6 @@ fn associated_item_from_impl_item_ref(
         hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
         hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
         hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
-        hir::AssocItemKind::OpaqueTy => (ty::AssocKind::OpaqueTy, false),
     };
 
     ty::AssocItem {
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index f1dc7e53906..267f3d9f3ef 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -2838,9 +2838,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 let opt_self_ty = maybe_qself.as_ref().map(|qself| self.ast_ty_to_ty(qself));
                 self.res_to_ty(opt_self_ty, path, false)
             }
-            hir::TyKind::Def(item_id, ref lifetimes) => {
-                let did = tcx.hir().local_def_id(item_id.id);
-                self.impl_trait_ty_to_ty(did.to_def_id(), lifetimes)
+            hir::TyKind::OpaqueDef(item_id, ref lifetimes) => {
+                let opaque_ty = tcx.hir().expect_item(item_id.id);
+                let def_id = tcx.hir().local_def_id(item_id.id).to_def_id();
+
+                match opaque_ty.kind {
+                    hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => {
+                        self.impl_trait_ty_to_ty(def_id, lifetimes, impl_trait_fn.is_some())
+                    }
+                    ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
+                }
             }
             hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
                 debug!("ast_ty_to_ty: qself={:?} segment={:?}", qself, segment);
@@ -2893,6 +2900,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         &self,
         def_id: DefId,
         lifetimes: &[hir::GenericArg<'_>],
+        replace_parent_lifetimes: bool,
     ) -> Ty<'tcx> {
         debug!("impl_trait_ty_to_ty(def_id={:?}, lifetimes={:?})", def_id, lifetimes);
         let tcx = self.tcx();
@@ -2914,9 +2922,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     _ => bug!(),
                 }
             } else {
-                // Replace all parent lifetimes with `'static`.
                 match param.kind {
-                    GenericParamDefKind::Lifetime => tcx.lifetimes.re_static.into(),
+                    // For RPIT (return position impl trait), only lifetimes
+                    // mentioned in the impl Trait predicate are captured by
+                    // the opaque type, so the lifetime parameters from the
+                    // parent item need to be replaced with `'static`.
+                    //
+                    // For `impl Trait` in the types of statics, constants,
+                    // locals and type aliases. These capture all parent
+                    // lifetimes, so they can use their identity subst.
+                    GenericParamDefKind::Lifetime if replace_parent_lifetimes => {
+                        tcx.lifetimes.re_static.into()
+                    }
                     _ => tcx.mk_param_from_def(param),
                 }
             }
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index efafb05c040..15ec92568fb 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -1377,7 +1377,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                 }
 
                 if let Some(expr) = expression {
-                    fcx.emit_coerce_suggestions(&mut err, expr, found, expected);
+                    fcx.emit_coerce_suggestions(&mut err, expr, found, expected, None);
                 }
 
                 // Error possibly reported in `check_assign` so avoid emitting error again.
@@ -1494,7 +1494,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
         let mut is_object_safe = false;
         if let hir::FnRetTy::Return(ty) = fn_output {
             // Get the return type.
-            if let hir::TyKind::Def(..) = ty.kind {
+            if let hir::TyKind::OpaqueDef(..) = 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 {
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 29cd9681295..5f8fcaadfdb 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -1165,6 +1165,6 @@ fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
     match impl_item.kind {
         ty::AssocKind::Const => "const",
         ty::AssocKind::Fn => "method",
-        ty::AssocKind::Type | ty::AssocKind::OpaqueTy => "type",
+        ty::AssocKind::Type => "type",
     }
 }
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 700b9359d06..019b4ca6606 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -15,6 +15,8 @@ use rustc_span::Span;
 
 use super::method::probe;
 
+use std::fmt;
+
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn emit_coerce_suggestions(
         &self,
@@ -22,10 +24,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &hir::Expr<'_>,
         expr_ty: Ty<'tcx>,
         expected: Ty<'tcx>,
+        expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
     ) {
         self.annotate_expected_due_to_let_ty(err, expr);
         self.suggest_compatible_variants(err, expr, expected, expr_ty);
-        self.suggest_deref_ref_or_into(err, expr, expected, expr_ty);
+        self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr);
         if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) {
             return;
         }
@@ -100,9 +103,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &hir::Expr<'_>,
         checked_ty: Ty<'tcx>,
         expected: Ty<'tcx>,
+        expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
         allow_two_phase: AllowTwoPhase,
     ) -> Ty<'tcx> {
-        let (ty, err) = self.demand_coerce_diag(expr, checked_ty, expected, allow_two_phase);
+        let (ty, err) =
+            self.demand_coerce_diag(expr, checked_ty, expected, expected_ty_expr, allow_two_phase);
         if let Some(mut err) = err {
             err.emit();
         }
@@ -119,6 +124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &hir::Expr<'_>,
         checked_ty: Ty<'tcx>,
         expected: Ty<'tcx>,
+        expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
         allow_two_phase: AllowTwoPhase,
     ) -> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx>>) {
         let expected = self.resolve_vars_with_obligations(expected);
@@ -139,7 +145,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return (expected, None);
         }
 
-        self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected);
+        self.emit_coerce_suggestions(&mut err, expr, expr_ty, expected, expected_ty_expr);
 
         (expected, Some(err))
     }
@@ -305,7 +311,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let (method_path, method_span, method_expr) = match (hir, closure_params_len) {
             (
                 Some(Node::Expr(hir::Expr {
-                    kind: hir::ExprKind::MethodCall(path, span, expr),
+                    kind: hir::ExprKind::MethodCall(path, span, expr, _),
                     ..
                 })),
                 1,
@@ -455,7 +461,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 };
                 if self.can_coerce(ref_ty, expected) {
                     let mut sugg_sp = sp;
-                    if let hir::ExprKind::MethodCall(ref segment, sp, ref args) = expr.kind {
+                    if let hir::ExprKind::MethodCall(ref segment, sp, ref args, _) = expr.kind {
                         let clone_trait = self.tcx.require_lang_item(CloneTraitLangItem, Some(sp));
                         if let ([arg], Some(true), sym::clone) = (
                             &args[..],
@@ -669,17 +675,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &hir::Expr<'_>,
         checked_ty: Ty<'tcx>,
         expected_ty: Ty<'tcx>,
+        expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
     ) -> bool {
-        if self.tcx.hir().is_const_context(expr.hir_id) {
-            // Shouldn't suggest `.into()` on `const`s.
-            // FIXME(estebank): modify once we decide to suggest `as` casts
-            return false;
-        }
         if self.tcx.sess.source_map().is_imported(expr.span) {
             // Ignore if span is from within a macro.
             return false;
         }
 
+        let src = if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
+            src
+        } else {
+            return false;
+        };
+
         // If casting this expression to a given numeric type would be appropriate in case of a type
         // mismatch.
         //
@@ -708,6 +716,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         } else {
             String::new()
         };
+
         if let hir::ExprKind::Call(path, args) = &expr.kind {
             if let (hir::ExprKind::Path(hir::QPath::TypeRelative(base_ty, path_segment)), 1) =
                 (&path.kind, args.len())
@@ -743,228 +752,250 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let msg = format!("you can convert an `{}` to `{}`", checked_ty, expected_ty);
         let cast_msg = format!("you can cast an `{} to `{}`", checked_ty, expected_ty);
-        let try_msg = format!("{} and panic if the converted value wouldn't fit", msg);
         let lit_msg = format!(
             "change the type of the numeric literal from `{}` to `{}`",
             checked_ty, expected_ty,
         );
 
-        let needs_paren = expr.precedence().order() < (PREC_POSTFIX as i8);
-
-        if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
-            let cast_suggestion = format!(
-                "{}{}{}{} as {}",
-                prefix,
-                if needs_paren { "(" } else { "" },
-                src,
-                if needs_paren { ")" } else { "" },
-                expected_ty,
-            );
-            let try_into_suggestion = format!(
-                "{}{}{}{}.try_into().unwrap()",
-                prefix,
-                if needs_paren { "(" } else { "" },
-                src,
-                if needs_paren { ")" } else { "" },
-            );
-            let into_suggestion = format!(
-                "{}{}{}{}.into()",
-                prefix,
-                if needs_paren { "(" } else { "" },
-                src,
-                if needs_paren { ")" } else { "" },
-            );
-            let suffix_suggestion = format!(
-                "{}{}{}{}",
-                if needs_paren { "(" } else { "" },
-                if let (ty::Int(_) | ty::Uint(_), ty::Float(_)) =
-                    (&expected_ty.kind, &checked_ty.kind,)
+        let with_opt_paren: fn(&dyn fmt::Display) -> String =
+            if expr.precedence().order() < PREC_POSTFIX {
+                |s| format!("({})", s)
+            } else {
+                |s| s.to_string()
+            };
+
+        let cast_suggestion = format!("{}{} as {}", prefix, with_opt_paren(&src), expected_ty);
+        let into_suggestion = format!("{}{}.into()", prefix, with_opt_paren(&src));
+        let suffix_suggestion = with_opt_paren(&format_args!(
+            "{}{}",
+            if matches!(
+                (&expected_ty.kind, &checked_ty.kind),
+                (ty::Int(_) | ty::Uint(_), ty::Float(_))
+            ) {
+                // Remove fractional part from literal, for example `42.0f32` into `42`
+                let src = src.trim_end_matches(&checked_ty.to_string());
+                src.split('.').next().unwrap()
+            } else {
+                src.trim_end_matches(&checked_ty.to_string())
+            },
+            expected_ty,
+        ));
+        let literal_is_ty_suffixed = |expr: &hir::Expr<'_>| {
+            if let hir::ExprKind::Lit(lit) = &expr.kind { lit.node.is_suffixed() } else { false }
+        };
+
+        let in_const_context = self.tcx.hir().is_inside_const_context(expr.hir_id);
+
+        let suggest_fallible_into_or_lhs_from =
+            |err: &mut DiagnosticBuilder<'_>, exp_to_found_is_fallible: bool| {
+                // If we know the expression the expected type is derived from, we might be able
+                // to suggest a widening conversion rather than a narrowing one (which may
+                // panic). For example, given x: u8 and y: u32, if we know the span of "x",
+                //   x > y
+                // can be given the suggestion "u32::from(x) > y" rather than
+                // "x > y.try_into().unwrap()".
+                let lhs_expr_and_src = expected_ty_expr.and_then(|expr| {
+                    match self.tcx.sess.source_map().span_to_snippet(expr.span).ok() {
+                        Some(src) => Some((expr, src)),
+                        None => None,
+                    }
+                });
+                let (span, msg, suggestion) = if let (Some((lhs_expr, lhs_src)), false) =
+                    (lhs_expr_and_src, exp_to_found_is_fallible)
                 {
-                    // Remove fractional part from literal, for example `42.0f32` into `42`
-                    let src = src.trim_end_matches(&checked_ty.to_string());
-                    src.split('.').next().unwrap()
+                    let msg = format!(
+                        "you can convert `{}` from `{}` to `{}`, matching the type of `{}`",
+                        lhs_src, expected_ty, checked_ty, src
+                    );
+                    let suggestion = format!("{}::from({})", checked_ty, lhs_src,);
+                    (lhs_expr.span, msg, suggestion)
                 } else {
-                    src.trim_end_matches(&checked_ty.to_string())
-                },
-                expected_ty,
-                if needs_paren { ")" } else { "" },
-            );
-            let literal_is_ty_suffixed = |expr: &hir::Expr<'_>| {
-                if let hir::ExprKind::Lit(lit) = &expr.kind {
-                    lit.node.is_suffixed()
+                    let msg = format!("{} and panic if the converted value wouldn't fit", msg);
+                    let suggestion =
+                        format!("{}{}.try_into().unwrap()", prefix, with_opt_paren(&src));
+                    (expr.span, msg, suggestion)
+                };
+                err.span_suggestion(span, &msg, suggestion, Applicability::MachineApplicable);
+            };
+
+        let suggest_to_change_suffix_or_into =
+            |err: &mut DiagnosticBuilder<'_>,
+             found_to_exp_is_fallible: bool,
+             exp_to_found_is_fallible: bool| {
+                let msg = if literal_is_ty_suffixed(expr) {
+                    &lit_msg
+                } else if in_const_context {
+                    // Do not recommend `into` or `try_into` in const contexts.
+                    return;
+                } else if found_to_exp_is_fallible {
+                    return suggest_fallible_into_or_lhs_from(err, exp_to_found_is_fallible);
                 } else {
-                    false
-                }
+                    &msg
+                };
+                let suggestion = if literal_is_ty_suffixed(expr) {
+                    suffix_suggestion.clone()
+                } else {
+                    into_suggestion.clone()
+                };
+                err.span_suggestion(expr.span, msg, suggestion, Applicability::MachineApplicable);
             };
 
-            let suggest_to_change_suffix_or_into =
-                |err: &mut DiagnosticBuilder<'_>, is_fallible: bool| {
+        match (&expected_ty.kind, &checked_ty.kind) {
+            (&ty::Int(ref exp), &ty::Int(ref found)) => {
+                let (f2e_is_fallible, e2f_is_fallible) = match (exp.bit_width(), found.bit_width())
+                {
+                    (Some(exp), Some(found)) if exp < found => (true, false),
+                    (Some(exp), Some(found)) if exp > found => (false, true),
+                    (None, Some(8 | 16)) => (false, true),
+                    (Some(8 | 16), None) => (true, false),
+                    (None, _) | (_, None) => (true, true),
+                    _ => (false, false),
+                };
+                suggest_to_change_suffix_or_into(err, f2e_is_fallible, e2f_is_fallible);
+                true
+            }
+            (&ty::Uint(ref exp), &ty::Uint(ref found)) => {
+                let (f2e_is_fallible, e2f_is_fallible) = match (exp.bit_width(), found.bit_width())
+                {
+                    (Some(exp), Some(found)) if exp < found => (true, false),
+                    (Some(exp), Some(found)) if exp > found => (false, true),
+                    (None, Some(8 | 16)) => (false, true),
+                    (Some(8 | 16), None) => (true, false),
+                    (None, _) | (_, None) => (true, true),
+                    _ => (false, false),
+                };
+                suggest_to_change_suffix_or_into(err, f2e_is_fallible, e2f_is_fallible);
+                true
+            }
+            (&ty::Int(exp), &ty::Uint(found)) => {
+                let (f2e_is_fallible, e2f_is_fallible) = match (exp.bit_width(), found.bit_width())
+                {
+                    (Some(exp), Some(found)) if found < exp => (false, true),
+                    (None, Some(8)) => (false, true),
+                    _ => (true, true),
+                };
+                suggest_to_change_suffix_or_into(err, f2e_is_fallible, e2f_is_fallible);
+                true
+            }
+            (&ty::Uint(exp), &ty::Int(found)) => {
+                let (f2e_is_fallible, e2f_is_fallible) = match (exp.bit_width(), found.bit_width())
+                {
+                    (Some(exp), Some(found)) if found > exp => (true, false),
+                    (Some(8), None) => (true, false),
+                    _ => (true, true),
+                };
+                suggest_to_change_suffix_or_into(err, f2e_is_fallible, e2f_is_fallible);
+                true
+            }
+            (&ty::Float(ref exp), &ty::Float(ref found)) => {
+                if found.bit_width() < exp.bit_width() {
+                    suggest_to_change_suffix_or_into(err, false, true);
+                } else if literal_is_ty_suffixed(expr) {
                     err.span_suggestion(
                         expr.span,
-                        if literal_is_ty_suffixed(expr) {
-                            &lit_msg
-                        } else if is_fallible {
-                            &try_msg
-                        } else {
-                            &msg
-                        },
-                        if literal_is_ty_suffixed(expr) {
-                            suffix_suggestion.clone()
-                        } else if is_fallible {
-                            try_into_suggestion
-                        } else {
-                            into_suggestion.clone()
-                        },
+                        &lit_msg,
+                        suffix_suggestion,
                         Applicability::MachineApplicable,
                     );
-                };
-
-            match (&expected_ty.kind, &checked_ty.kind) {
-                (&ty::Int(ref exp), &ty::Int(ref found)) => {
-                    let is_fallible = match (exp.bit_width(), found.bit_width()) {
-                        (Some(exp), Some(found)) if exp < found => true,
-                        (None, Some(8 | 16)) => false,
-                        (None, _) | (_, None) => true,
-                        _ => false,
-                    };
-                    suggest_to_change_suffix_or_into(err, is_fallible);
-                    true
-                }
-                (&ty::Uint(ref exp), &ty::Uint(ref found)) => {
-                    let is_fallible = match (exp.bit_width(), found.bit_width()) {
-                        (Some(exp), Some(found)) if exp < found => true,
-                        (None, Some(8 | 16)) => false,
-                        (None, _) | (_, None) => true,
-                        _ => false,
-                    };
-                    suggest_to_change_suffix_or_into(err, is_fallible);
-                    true
-                }
-                (&ty::Int(exp), &ty::Uint(found)) => {
-                    let is_fallible = match (exp.bit_width(), found.bit_width()) {
-                        (Some(exp), Some(found)) if found < exp => false,
-                        (None, Some(8)) => false,
-                        _ => true,
-                    };
-                    suggest_to_change_suffix_or_into(err, is_fallible);
-                    true
-                }
-                (&ty::Uint(_), &ty::Int(_)) => {
-                    suggest_to_change_suffix_or_into(err, true);
-                    true
-                }
-                (&ty::Float(ref exp), &ty::Float(ref found)) => {
-                    if found.bit_width() < exp.bit_width() {
-                        suggest_to_change_suffix_or_into(err, false);
-                    } else if literal_is_ty_suffixed(expr) {
-                        err.span_suggestion(
-                            expr.span,
-                            &lit_msg,
-                            suffix_suggestion,
-                            Applicability::MachineApplicable,
-                        );
-                    } else if can_cast {
-                        // Missing try_into implementation for `f64` to `f32`
-                        err.span_suggestion(
-                            expr.span,
-                            &format!("{}, producing the closest possible value", cast_msg),
-                            cast_suggestion,
-                            Applicability::MaybeIncorrect, // lossy conversion
-                        );
-                    }
-                    true
+                } else if can_cast {
+                    // Missing try_into implementation for `f64` to `f32`
+                    err.span_suggestion(
+                        expr.span,
+                        &format!("{}, producing the closest possible value", cast_msg),
+                        cast_suggestion,
+                        Applicability::MaybeIncorrect, // lossy conversion
+                    );
                 }
-                (&ty::Uint(_) | &ty::Int(_), &ty::Float(_)) => {
-                    if literal_is_ty_suffixed(expr) {
-                        err.span_suggestion(
-                            expr.span,
-                            &lit_msg,
-                            suffix_suggestion,
-                            Applicability::MachineApplicable,
-                        );
-                    } else if can_cast {
-                        // Missing try_into implementation for `{float}` to `{integer}`
-                        err.span_suggestion(
-                            expr.span,
-                            &format!("{}, rounding the float towards zero", msg),
-                            cast_suggestion,
-                            Applicability::MaybeIncorrect, // lossy conversion
-                        );
-                    }
-                    true
+                true
+            }
+            (&ty::Uint(_) | &ty::Int(_), &ty::Float(_)) => {
+                if literal_is_ty_suffixed(expr) {
+                    err.span_suggestion(
+                        expr.span,
+                        &lit_msg,
+                        suffix_suggestion,
+                        Applicability::MachineApplicable,
+                    );
+                } else if can_cast {
+                    // Missing try_into implementation for `{float}` to `{integer}`
+                    err.span_suggestion(
+                        expr.span,
+                        &format!("{}, rounding the float towards zero", msg),
+                        cast_suggestion,
+                        Applicability::MaybeIncorrect, // lossy conversion
+                    );
                 }
-                (&ty::Float(ref exp), &ty::Uint(ref found)) => {
-                    // if `found` is `None` (meaning found is `usize`), don't suggest `.into()`
-                    if exp.bit_width() > found.bit_width().unwrap_or(256) {
-                        err.span_suggestion(
-                            expr.span,
-                            &format!(
-                                "{}, producing the floating point representation of the integer",
-                                msg,
-                            ),
-                            into_suggestion,
-                            Applicability::MachineApplicable,
-                        );
-                    } else if literal_is_ty_suffixed(expr) {
-                        err.span_suggestion(
-                            expr.span,
-                            &lit_msg,
-                            suffix_suggestion,
-                            Applicability::MachineApplicable,
-                        );
-                    } else {
-                        // Missing try_into implementation for `{integer}` to `{float}`
-                        err.span_suggestion(
-                            expr.span,
-                            &format!(
-                                "{}, producing the floating point representation of the integer,
+                true
+            }
+            (&ty::Float(ref exp), &ty::Uint(ref found)) => {
+                // if `found` is `None` (meaning found is `usize`), don't suggest `.into()`
+                if exp.bit_width() > found.bit_width().unwrap_or(256) {
+                    err.span_suggestion(
+                        expr.span,
+                        &format!(
+                            "{}, producing the floating point representation of the integer",
+                            msg,
+                        ),
+                        into_suggestion,
+                        Applicability::MachineApplicable,
+                    );
+                } else if literal_is_ty_suffixed(expr) {
+                    err.span_suggestion(
+                        expr.span,
+                        &lit_msg,
+                        suffix_suggestion,
+                        Applicability::MachineApplicable,
+                    );
+                } else {
+                    // Missing try_into implementation for `{integer}` to `{float}`
+                    err.span_suggestion(
+                        expr.span,
+                        &format!(
+                            "{}, producing the floating point representation of the integer,
                                  rounded if necessary",
-                                cast_msg,
-                            ),
-                            cast_suggestion,
-                            Applicability::MaybeIncorrect, // lossy conversion
-                        );
-                    }
-                    true
+                            cast_msg,
+                        ),
+                        cast_suggestion,
+                        Applicability::MaybeIncorrect, // lossy conversion
+                    );
                 }
-                (&ty::Float(ref exp), &ty::Int(ref found)) => {
-                    // if `found` is `None` (meaning found is `isize`), don't suggest `.into()`
-                    if exp.bit_width() > found.bit_width().unwrap_or(256) {
-                        err.span_suggestion(
-                            expr.span,
-                            &format!(
-                                "{}, producing the floating point representation of the integer",
-                                &msg,
-                            ),
-                            into_suggestion,
-                            Applicability::MachineApplicable,
-                        );
-                    } else if literal_is_ty_suffixed(expr) {
-                        err.span_suggestion(
-                            expr.span,
-                            &lit_msg,
-                            suffix_suggestion,
-                            Applicability::MachineApplicable,
-                        );
-                    } else {
-                        // Missing try_into implementation for `{integer}` to `{float}`
-                        err.span_suggestion(
-                            expr.span,
-                            &format!(
-                                "{}, producing the floating point representation of the integer, \
-                                 rounded if necessary",
-                                &msg,
-                            ),
-                            cast_suggestion,
-                            Applicability::MaybeIncorrect, // lossy conversion
-                        );
-                    }
-                    true
+                true
+            }
+            (&ty::Float(ref exp), &ty::Int(ref found)) => {
+                // if `found` is `None` (meaning found is `isize`), don't suggest `.into()`
+                if exp.bit_width() > found.bit_width().unwrap_or(256) {
+                    err.span_suggestion(
+                        expr.span,
+                        &format!(
+                            "{}, producing the floating point representation of the integer",
+                            &msg,
+                        ),
+                        into_suggestion,
+                        Applicability::MachineApplicable,
+                    );
+                } else if literal_is_ty_suffixed(expr) {
+                    err.span_suggestion(
+                        expr.span,
+                        &lit_msg,
+                        suffix_suggestion,
+                        Applicability::MachineApplicable,
+                    );
+                } else {
+                    // Missing try_into implementation for `{integer}` to `{float}`
+                    err.span_suggestion(
+                        expr.span,
+                        &format!(
+                            "{}, producing the floating point representation of the integer, \
+                                rounded if necessary",
+                            &msg,
+                        ),
+                        cast_suggestion,
+                        Applicability::MaybeIncorrect, // lossy conversion
+                    );
                 }
-                _ => false,
+                true
             }
-        } else {
-            false
+            _ => false,
         }
     }
 }
diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs
index 266e9b21d69..bc3ef73d851 100644
--- a/src/librustc_typeck/check/expr.rs
+++ b/src/librustc_typeck/check/expr.rs
@@ -86,7 +86,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
             let expr = expr.peel_drop_temps();
-            self.suggest_deref_ref_or_into(&mut err, expr, expected_ty, ty);
+            self.suggest_deref_ref_or_into(&mut err, expr, expected_ty, ty, None);
             extend_err(&mut err);
             // Error possibly reported in `check_assign` so avoid emitting error again.
             err.emit_unless(self.is_assign_to_bool(expr, expected_ty));
@@ -98,10 +98,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         expr: &'tcx hir::Expr<'tcx>,
         expected: Ty<'tcx>,
+        expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
     ) -> Ty<'tcx> {
         let ty = self.check_expr_with_hint(expr, expected);
         // checks don't need two phase
-        self.demand_coerce(expr, ty, expected, AllowTwoPhase::No)
+        self.demand_coerce(expr, ty, expected, expected_ty_expr, AllowTwoPhase::No)
     }
 
     pub(super) fn check_expr_with_hint(
@@ -182,7 +183,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ExprKind::Call(ref callee, _) => {
                 self.warn_if_unreachable(expr.hir_id, callee.span, "call")
             }
-            ExprKind::MethodCall(_, ref span, _) => {
+            ExprKind::MethodCall(_, ref span, _, _) => {
                 self.warn_if_unreachable(expr.hir_id, *span, "call")
             }
             _ => self.warn_if_unreachable(expr.hir_id, expr.span, "expression"),
@@ -262,7 +263,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             ExprKind::Block(ref body, _) => self.check_block_with_expected(&body, expected),
             ExprKind::Call(ref callee, ref args) => self.check_call(expr, &callee, args, expected),
-            ExprKind::MethodCall(ref segment, span, ref args) => {
+            ExprKind::MethodCall(ref segment, span, ref args, _) => {
                 self.check_method_call(expr, segment, span, args, expected, needs)
             }
             ExprKind::Cast(ref e, ref t) => self.check_expr_cast(e, t, expr),
@@ -776,7 +777,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         span: &Span,
     ) -> Ty<'tcx> {
         let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
-        let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty);
+        let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty, Some(lhs));
 
         let expected_ty = expected.coercion_target_type(self, expr.span);
         if expected_ty == self.tcx.types.bool {
@@ -1026,7 +1027,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let (element_ty, t) = match uty {
             Some(uty) => {
-                self.check_expr_coercable_to_type(&element, uty);
+                self.check_expr_coercable_to_type(&element, uty, None);
                 (uty, uty)
             }
             None => {
@@ -1063,7 +1064,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let elt_ts_iter = elts.iter().enumerate().map(|(i, e)| match flds {
             Some(ref fs) if i < fs.len() => {
                 let ety = fs[i].expect_ty();
-                self.check_expr_coercable_to_type(&e, ety);
+                self.check_expr_coercable_to_type(&e, ety, None);
                 ety
             }
             _ => self.check_expr_with_expectation(&e, NoExpectation),
@@ -1237,7 +1238,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             // Make sure to give a type to the field even if there's
             // an error, so we can continue type-checking.
-            self.check_expr_coercable_to_type(&field.expr, field_type);
+            self.check_expr_coercable_to_type(&field.expr, field_type, None);
         }
 
         // Make sure the programmer specified correct number of fields.
@@ -1735,7 +1736,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             match self.lookup_indexing(expr, base, base_t, idx_t, needs) {
                 Some((index_ty, element_ty)) => {
                     // two-phase not needed because index_ty is never mutable
-                    self.demand_coerce(idx, idx_t, index_ty, AllowTwoPhase::No);
+                    self.demand_coerce(idx, idx_t, index_ty, None, AllowTwoPhase::No);
                     element_ty
                 }
                 None => {
@@ -1788,7 +1789,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> Ty<'tcx> {
         match self.resume_yield_tys {
             Some((resume_ty, yield_ty)) => {
-                self.check_expr_coercable_to_type(&value, yield_ty);
+                self.check_expr_coercable_to_type(&value, yield_ty, None);
 
                 resume_ty
             }
@@ -1797,7 +1798,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // information. Hence, we check the source of the yield expression here and check its
             // value's type against `()` (this check should always hold).
             None if src.is_await() => {
-                self.check_expr_coercable_to_type(&value, self.tcx.mk_unit());
+                self.check_expr_coercable_to_type(&value, self.tcx.mk_unit(), None);
                 self.tcx.mk_unit()
             }
             _ => {
@@ -1836,11 +1837,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             match ty.kind {
                 ty::FnDef(..) => {
                     let fnptr_ty = self.tcx.mk_fn_ptr(ty.fn_sig(self.tcx));
-                    self.demand_coerce(expr, ty, fnptr_ty, AllowTwoPhase::No);
+                    self.demand_coerce(expr, ty, fnptr_ty, None, AllowTwoPhase::No);
                 }
                 ty::Ref(_, base_ty, mutbl) => {
                     let ptr_ty = self.tcx.mk_ptr(ty::TypeAndMut { ty: base_ty, mutbl });
-                    self.demand_coerce(expr, ty, ptr_ty, AllowTwoPhase::No);
+                    self.demand_coerce(expr, ty, ptr_ty, None, AllowTwoPhase::No);
                 }
                 _ => {}
             }
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 4095ab5e10f..37652330108 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -795,6 +795,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
 
     fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) {
         // FIXME: do we want to commit to this behavior for param bounds?
+        debug!("assemble_inherent_candidates_from_param(param_ty={:?})", param_ty);
 
         let bounds =
             self.param_env.caller_bounds.iter().filter_map(|predicate| match predicate.kind() {
@@ -952,7 +953,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                         import_ids: import_ids.clone(),
                         kind: TraitCandidate(new_trait_ref),
                     },
-                    true,
+                    false,
                 );
             });
         } else {
@@ -1556,7 +1557,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         match self.mode {
             Mode::MethodCall => item.fn_has_self_parameter,
             Mode::Path => match item.kind {
-                ty::AssocKind::OpaqueTy | ty::AssocKind::Type => false,
+                ty::AssocKind::Type => false,
                 ty::AssocKind::Fn | ty::AssocKind::Const => true,
             },
         }
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 7ca3eb884d8..67bdd04d371 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -158,9 +158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             let path = self.tcx.def_path_str(trait_ref.def_id);
 
                             let ty = match item.kind {
-                                ty::AssocKind::Const
-                                | ty::AssocKind::Type
-                                | ty::AssocKind::OpaqueTy => rcvr_ty,
+                                ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
                                 ty::AssocKind::Fn => self
                                     .tcx
                                     .fn_sig(item.def_id)
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index f2aeed4f1e4..a409e20953d 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1046,7 +1046,7 @@ fn typeck_tables_of_with_fallback<'tcx>(
             // Gather locals in statics (because of block expressions).
             GatherLocalsVisitor { fcx: &fcx, parent_id: id }.visit_body(body);
 
-            fcx.check_expr_coercable_to_type(&body.value, revealed_ty);
+            fcx.check_expr_coercable_to_type(&body.value, revealed_ty, None);
 
             fcx.write_ty(id, revealed_ty);
 
@@ -1943,7 +1943,6 @@ fn check_specialization_validity<'tcx>(
     let kind = match impl_item.kind {
         hir::ImplItemKind::Const(..) => ty::AssocKind::Const,
         hir::ImplItemKind::Fn(..) => ty::AssocKind::Fn,
-        hir::ImplItemKind::OpaqueTy(..) => ty::AssocKind::OpaqueTy,
         hir::ImplItemKind::TyAlias(_) => ty::AssocKind::Type,
     };
 
@@ -2114,7 +2113,7 @@ fn check_impl_items_against_trait<'tcx>(
                         err.emit()
                     }
                 }
-                hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(_) => {
+                hir::ImplItemKind::TyAlias(_) => {
                     let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
                     if ty_trait_item.kind == ty::AssocKind::Type {
                         compare_ty_impl(
@@ -2367,8 +2366,6 @@ fn suggestion_signature(assoc: &ty::AssocItem, tcx: TyCtxt<'_>) -> String {
             )
         }
         ty::AssocKind::Type => format!("type {} = Type;", assoc.ident),
-        // FIXME(type_alias_impl_trait): we should print bounds here too.
-        ty::AssocKind::OpaqueTy => format!("type {} = Type;", assoc.ident),
         ty::AssocKind::Const => {
             let ty = tcx.type_of(assoc.def_id);
             let val = expr::ty_kind_suggestion(ty).unwrap_or("value");
@@ -2390,11 +2387,7 @@ fn check_representable(tcx: TyCtxt<'_>, sp: Span, item_def_id: LocalDefId) -> bo
     // caught by case 1.
     match rty.is_representable(tcx, sp) {
         Representability::SelfRecursive(spans) => {
-            let mut err = recursive_type_with_infinite_size_error(tcx, item_def_id.to_def_id());
-            for span in spans {
-                err.span_label(span, "recursive without indirection");
-            }
-            err.emit();
+            recursive_type_with_infinite_size_error(tcx, item_def_id.to_def_id(), spans);
             return false;
         }
         Representability::Representable | Representability::ContainsRecursive => (),
@@ -3912,7 +3905,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                  sugg_unit: bool| {
             let (span, start_span, args) = match &expr.kind {
                 hir::ExprKind::Call(hir::Expr { span, .. }, args) => (*span, *span, &args[..]),
-                hir::ExprKind::MethodCall(path_segment, span, args) => (
+                hir::ExprKind::MethodCall(path_segment, span, args, _) => (
                     *span,
                     // `sp` doesn't point at the whole `foo.bar()`, only at `bar`.
                     path_segment
@@ -4123,7 +4116,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let coerce_ty = expected.only_has_type(self).unwrap_or(formal_ty);
                 // We're processing function arguments so we definitely want to use
                 // two-phase borrows.
-                self.demand_coerce(&arg, checked_ty, coerce_ty, AllowTwoPhase::Yes);
+                self.demand_coerce(&arg, checked_ty, coerce_ty, None, AllowTwoPhase::Yes);
                 final_arg_types.push((i, checked_ty, coerce_ty));
 
                 // 3. Relate the expected type and the formal one,
@@ -4541,7 +4534,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.demand_eqtype(init.span, local_ty, init_ty);
             init_ty
         } else {
-            self.check_expr_coercable_to_type(init, local_ty)
+            self.check_expr_coercable_to_type(init, local_ty, None)
         }
     }
 
@@ -5027,6 +5020,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &hir::Expr<'_>,
         expected: Ty<'tcx>,
         found: Ty<'tcx>,
+        expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
     ) {
         if let Some((sp, msg, suggestion, applicability)) = self.check_ref(expr, found, expected) {
             err.span_suggestion(sp, msg, suggestion, applicability);
@@ -5037,7 +5031,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let sp = self.sess().source_map().guess_head_span(sp);
                 err.span_label(sp, &format!("{} defined here", found));
             }
-        } else if !self.check_for_cast(err, expr, found, expected) {
+        } else if !self.check_for_cast(err, expr, found, expected, expected_ty_expr) {
             let is_struct_pat_shorthand_field =
                 self.is_hir_id_from_struct_pattern_shorthand_field(expr.hir_id, expr.span);
             let methods = self.get_conversion_methods(expr.span, expected, found, expr.hir_id);
@@ -5091,7 +5085,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Ty<'tcx>,
         found: Ty<'tcx>,
     ) {
-        if self.tcx.hir().is_const_context(expr.hir_id) {
+        if self.tcx.hir().is_inside_const_context(expr.hir_id) {
             // Do not suggest `Box::new` in const context.
             return;
         }
@@ -5128,7 +5122,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> bool {
         // Handle #68197.
 
-        if self.tcx.hir().is_const_context(expr.hir_id) {
+        if self.tcx.hir().is_inside_const_context(expr.hir_id) {
             // Do not suggest `Box::new` in const context.
             return false;
         }
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index d89993e3547..a3a27dc138b 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -57,9 +57,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         match BinOpCategory::from(op) {
             BinOpCategory::Shortcircuit => {
                 // && and || are a simple case.
-                self.check_expr_coercable_to_type(lhs_expr, tcx.types.bool);
+                self.check_expr_coercable_to_type(lhs_expr, tcx.types.bool, None);
                 let lhs_diverges = self.diverges.get();
-                self.check_expr_coercable_to_type(rhs_expr, tcx.types.bool);
+                self.check_expr_coercable_to_type(rhs_expr, tcx.types.bool, None);
 
                 // Depending on the LHS' value, the RHS can never execute.
                 self.diverges.set(lhs_diverges);
@@ -170,7 +170,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     kind: TypeVariableOriginKind::MiscVariable,
                     span: lhs_expr.span,
                 });
-                self.demand_coerce(lhs_expr, lhs_ty, fresh_var, AllowTwoPhase::No)
+                self.demand_coerce(lhs_expr, lhs_ty, fresh_var, Some(rhs_expr), AllowTwoPhase::No)
             }
             IsAssign::Yes => {
                 // rust-lang/rust#52126: We have to use strict
@@ -196,7 +196,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let result = self.lookup_op_method(lhs_ty, &[rhs_ty_var], Op::Binary(op, is_assign));
 
         // see `NB` above
-        let rhs_ty = self.check_expr_coercable_to_type(rhs_expr, rhs_ty_var);
+        let rhs_ty = self.check_expr_coercable_to_type(rhs_expr, rhs_ty_var, Some(lhs_expr));
         let rhs_ty = self.resolve_vars_with_obligations(rhs_ty);
 
         let return_ty = match result {
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 7d9bf975c69..f3297ed6743 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -316,9 +316,6 @@ fn check_associated_item(
                     fcx.register_wf_obligation(ty.into(), span, code.clone());
                 }
             }
-            ty::AssocKind::OpaqueTy => {
-                // Do nothing: opaque types check themselves.
-            }
         }
 
         implied_bounds
@@ -804,14 +801,14 @@ fn check_where_clauses<'tcx, 'fcx>(
             traits::Obligation::new(cause, fcx.param_env, pred)
         });
 
-    let mut predicates = predicates.instantiate_identity(fcx.tcx);
+    let predicates = predicates.instantiate_identity(fcx.tcx);
 
-    if let Some((return_ty, span)) = return_ty {
-        let opaque_types = check_opaque_types(tcx, fcx, def_id.expect_local(), span, return_ty);
-        for _ in 0..opaque_types.len() {
-            predicates.spans.push(span);
+    if let Some((mut return_ty, span)) = return_ty {
+        if return_ty.has_infer_types_or_consts() {
+            fcx.select_obligations_where_possible(false, |_| {});
+            return_ty = fcx.resolve_vars_if_possible(&return_ty);
         }
-        predicates.predicates.extend(opaque_types);
+        check_opaque_types(tcx, fcx, def_id.expect_local(), span, return_ty);
     }
 
     let predicates = fcx.normalize_associated_types_in(span, &predicates);
@@ -883,119 +880,117 @@ fn check_opaque_types<'fcx, 'tcx>(
     fn_def_id: LocalDefId,
     span: Span,
     ty: Ty<'tcx>,
-) -> Vec<ty::Predicate<'tcx>> {
+) {
     trace!("check_opaque_types(ty={:?})", ty);
-    let mut substituted_predicates = Vec::new();
     ty.fold_with(&mut ty::fold::BottomUpFolder {
         tcx: fcx.tcx,
         ty_op: |ty| {
             if let ty::Opaque(def_id, substs) = ty.kind {
                 trace!("check_opaque_types: opaque_ty, {:?}, {:?}", def_id, substs);
                 let generics = tcx.generics_of(def_id);
-                // Only check named `impl Trait` types defined in this crate.
-                // FIXME(eddyb) is  `generics.parent.is_none()` correct? It seems
-                // potentially risky wrt associated types in `impl`s.
-                if generics.parent.is_none() && def_id.is_local() {
-                    let opaque_hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
-                    if may_define_opaque_type(tcx, fn_def_id, opaque_hir_id) {
-                        trace!("check_opaque_types: may define, generics={:#?}", generics);
-                        let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
-                        for (i, arg) in substs.iter().enumerate() {
-                            let arg_is_param = match arg.unpack() {
-                                GenericArgKind::Type(ty) => matches!(ty.kind, ty::Param(_)),
-
-                                GenericArgKind::Lifetime(region) => {
-                                    if let ty::ReStatic = region {
-                                        tcx.sess
-                                            .struct_span_err(
-                                                span,
-                                                "non-defining opaque type use in defining scope",
-                                            )
-                                            .span_label(
-                                                tcx.def_span(generics.param_at(i, tcx).def_id),
-                                                "cannot use static lifetime; use a bound lifetime \
-                                                 instead or remove the lifetime parameter from the \
-                                                 opaque type",
-                                            )
-                                            .emit();
-                                        continue;
-                                    }
-
-                                    true
-                                }
-
-                                GenericArgKind::Const(ct) => {
-                                    matches!(ct.val, ty::ConstKind::Param(_))
-                                }
-                            };
-
-                            if arg_is_param {
-                                seen_params.entry(arg).or_default().push(i);
-                            } else {
-                                // Prevent `fn foo() -> Foo<u32>` from being defining.
-                                let opaque_param = generics.param_at(i, tcx);
+
+                let opaque_hir_id = if let Some(local_id) = def_id.as_local() {
+                    tcx.hir().as_local_hir_id(local_id)
+                } else {
+                    // Opaque types from other crates won't have defining uses in this crate.
+                    return ty;
+                };
+                if let hir::ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(_), .. }) =
+                    tcx.hir().expect_item(opaque_hir_id).kind
+                {
+                    // No need to check return position impl trait (RPIT)
+                    // because for type and const parameters they are correct
+                    // by construction: we convert
+                    //
+                    // fn foo<P0..Pn>() -> impl Trait
+                    //
+                    // into
+                    //
+                    // type Foo<P0...Pn>
+                    // fn foo<P0..Pn>() -> Foo<P0...Pn>.
+                    //
+                    // For lifetime parameters we convert
+                    //
+                    // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm>
+                    //
+                    // into
+                    //
+                    // type foo::<'p0..'pn>::Foo<'q0..'qm>
+                    // fn foo<l0..'ln>() -> foo::<'static..'static>::Foo<'l0..'lm>.
+                    //
+                    // which would error here on all of the `'static` args.
+                    return ty;
+                }
+                if !may_define_opaque_type(tcx, fn_def_id, opaque_hir_id) {
+                    return ty;
+                }
+                trace!("check_opaque_types: may define, generics={:#?}", generics);
+                let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
+                for (i, arg) in substs.iter().enumerate() {
+                    let arg_is_param = match arg.unpack() {
+                        GenericArgKind::Type(ty) => matches!(ty.kind, ty::Param(_)),
+
+                        GenericArgKind::Lifetime(region) => {
+                            if let ty::ReStatic = region {
                                 tcx.sess
                                     .struct_span_err(
                                         span,
                                         "non-defining opaque type use in defining scope",
                                     )
-                                    .span_note(
-                                        tcx.def_span(opaque_param.def_id),
-                                        &format!(
-                                            "used non-generic {} `{}` for generic parameter",
-                                            opaque_param.kind.descr(),
-                                            arg,
-                                        ),
-                                    )
-                                    .emit();
-                            }
-                        } // for (arg, param)
-
-                        for (_, indices) in seen_params {
-                            if indices.len() > 1 {
-                                let descr = generics.param_at(indices[0], tcx).kind.descr();
-                                let spans: Vec<_> = indices
-                                    .into_iter()
-                                    .map(|i| tcx.def_span(generics.param_at(i, tcx).def_id))
-                                    .collect();
-                                tcx.sess
-                                    .struct_span_err(
-                                        span,
-                                        "non-defining opaque type use in defining scope",
+                                    .span_label(
+                                        tcx.def_span(generics.param_at(i, tcx).def_id),
+                                        "cannot use static lifetime; use a bound lifetime \
+                                                 instead or remove the lifetime parameter from the \
+                                                 opaque type",
                                     )
-                                    .span_note(spans, &format!("{} used multiple times", descr))
                                     .emit();
+                                continue;
                             }
-                        }
-                    } // if may_define_opaque_type
 
-                    // Now register the bounds on the parameters of the opaque type
-                    // so the parameters given by the function need to fulfill them.
-                    //
-                    //     type Foo<T: Bar> = impl Baz + 'static;
-                    //     fn foo<U>() -> Foo<U> { .. *}
-                    //
-                    // becomes
-                    //
-                    //     type Foo<T: Bar> = impl Baz + 'static;
-                    //     fn foo<U: Bar>() -> Foo<U> { .. *}
-                    let predicates = tcx.predicates_of(def_id);
-                    trace!("check_opaque_types: may define, predicates={:#?}", predicates,);
-                    for &(pred, _) in predicates.predicates {
-                        let substituted_pred = pred.subst(fcx.tcx, substs);
-                        // Avoid duplication of predicates that contain no parameters, for example.
-                        if !predicates.predicates.iter().any(|&(p, _)| p == substituted_pred) {
-                            substituted_predicates.push(substituted_pred);
+                            true
                         }
+
+                        GenericArgKind::Const(ct) => matches!(ct.val, ty::ConstKind::Param(_)),
+                    };
+
+                    if arg_is_param {
+                        seen_params.entry(arg).or_default().push(i);
+                    } else {
+                        // Prevent `fn foo() -> Foo<u32>` from being defining.
+                        let opaque_param = generics.param_at(i, tcx);
+                        tcx.sess
+                            .struct_span_err(span, "non-defining opaque type use in defining scope")
+                            .span_note(
+                                tcx.def_span(opaque_param.def_id),
+                                &format!(
+                                    "used non-generic {} `{}` for generic parameter",
+                                    opaque_param.kind.descr(),
+                                    arg,
+                                ),
+                            )
+                            .emit();
                     }
-                } // if is_named_opaque_type
+                } // for (arg, param)
+
+                for (_, indices) in seen_params {
+                    if indices.len() > 1 {
+                        let descr = generics.param_at(indices[0], tcx).kind.descr();
+                        let spans: Vec<_> = indices
+                            .into_iter()
+                            .map(|i| tcx.def_span(generics.param_at(i, tcx).def_id))
+                            .collect();
+                        tcx.sess
+                            .struct_span_err(span, "non-defining opaque type use in defining scope")
+                            .span_note(spans, &format!("{} used multiple times", descr))
+                            .emit();
+                    }
+                }
             } // if let Opaque
             ty
         },
         lt_op: |lt| lt,
         ct_op: |ct| ct,
     });
-    substituted_predicates
 }
 
 const HELP_FOR_SELF_TYPE: &str = "consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, \
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 3473dc7a58d..159d3d7a538 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -460,7 +460,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             let mut skip_add = false;
 
             if let ty::Opaque(defin_ty_def_id, _substs) = definition_ty.kind {
-                if let hir::OpaqueTyOrigin::TypeAlias = opaque_defn.origin {
+                if let hir::OpaqueTyOrigin::Misc = opaque_defn.origin {
                     if def_id == defin_ty_def_id {
                         debug!(
                             "skipping adding concrete definition for opaque type {:?} {:?}",
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 355b4fc413f..1d59d749634 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -742,7 +742,7 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::HirId) {
         hir::ImplItemKind::Fn(..) => {
             tcx.ensure().fn_sig(def_id);
         }
-        hir::ImplItemKind::TyAlias(_) | hir::ImplItemKind::OpaqueTy(_) => {
+        hir::ImplItemKind::TyAlias(_) => {
             // Account for `type T = _;`
             let mut visitor = PlaceholderHirTyCollector::default();
             visitor.visit_impl_item(impl_item);
@@ -1202,22 +1202,11 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
             ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => {
                 impl_trait_fn.or_else(|| {
                     let parent_id = tcx.hir().get_parent_item(hir_id);
-                    if parent_id != hir_id && parent_id != CRATE_HIR_ID {
-                        debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
-                        // If this 'impl Trait' is nested inside another 'impl Trait'
-                        // (e.g. `impl Foo<MyType = impl Bar<A>>`), we need to use the 'parent'
-                        // 'impl Trait' for its generic parameters, since we can reference them
-                        // from the 'child' 'impl Trait'
-                        if let Node::Item(hir::Item { kind: ItemKind::OpaqueTy(..), .. }) =
-                            tcx.hir().get(parent_id)
-                        {
-                            Some(tcx.hir().local_def_id(parent_id).to_def_id())
-                        } else {
-                            None
-                        }
-                    } else {
-                        None
-                    }
+                    assert!(parent_id != hir_id && parent_id != CRATE_HIR_ID);
+                    debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
+                    // Opaque types are always nested within another item, and
+                    // inherit the generics of the item.
+                    Some(tcx.hir().local_def_id(parent_id).to_def_id())
                 })
             }
             _ => None,
@@ -1428,7 +1417,7 @@ fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool {
         Slice(ty) | Array(ty, _) => is_suggestable_infer_ty(ty),
         Tup(tys) => tys.iter().any(is_suggestable_infer_ty),
         Ptr(mut_ty) | Rptr(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty),
-        Def(_, generic_args) => are_suggestable_generic_args(generic_args),
+        OpaqueDef(_, generic_args) => are_suggestable_generic_args(generic_args),
         Path(hir::QPath::TypeRelative(ty, segment)) => {
             is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.generic_args().args)
         }
@@ -1715,31 +1704,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat
     let ast_generics = match node {
         Node::TraitItem(item) => &item.generics,
 
-        Node::ImplItem(item) => match item.kind {
-            ImplItemKind::OpaqueTy(ref bounds) => {
-                ty::print::with_no_queries(|| {
-                    let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                    let opaque_ty = tcx.mk_opaque(def_id, substs);
-                    debug!(
-                        "explicit_predicates_of({:?}): created opaque type {:?}",
-                        def_id, opaque_ty
-                    );
-
-                    // Collect the bounds, i.e., the `A + B + 'c` in `impl A + B + 'c`.
-                    let bounds = AstConv::compute_bounds(
-                        &icx,
-                        opaque_ty,
-                        bounds,
-                        SizedByDefault::Yes,
-                        tcx.def_span(def_id),
-                    );
-
-                    predicates.extend(bounds.predicates(tcx, opaque_ty));
-                    &item.generics
-                })
-            }
-            _ => &item.generics,
-        },
+        Node::ImplItem(item) => &item.generics,
 
         Node::Item(item) => {
             match item.kind {
diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs
index cf0e3f9cdf5..549a20531e2 100644
--- a/src/librustc_typeck/collect/type_of.rs
+++ b/src/librustc_typeck/collect/type_of.rs
@@ -64,13 +64,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     icx.to_ty(ty)
                 }
             }
-            ImplItemKind::OpaqueTy(_) => {
-                if tcx.impl_trait_ref(tcx.hir().get_parent_did(hir_id).to_def_id()).is_none() {
-                    report_assoc_ty_on_inherent_impl(tcx, item.span);
-                }
-
-                find_opaque_ty_constraints(tcx, def_id.expect_local())
-            }
             ImplItemKind::TyAlias(ref ty) => {
                 if tcx.impl_trait_ref(tcx.hir().get_parent_did(hir_id).to_def_id()).is_none() {
                     report_assoc_ty_on_inherent_impl(tcx, item.span);
@@ -107,26 +100,17 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     let substs = InternalSubsts::identity_for_item(tcx, def_id);
                     tcx.mk_adt(def, substs)
                 }
+                ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::Binding, .. }) => {
+                    let_position_impl_trait_type(tcx, def_id.expect_local())
+                }
                 ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => {
                     find_opaque_ty_constraints(tcx, def_id.expect_local())
                 }
                 // Opaque types desugared from `impl Trait`.
-                ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: Some(owner), origin, .. }) => {
-                    let concrete_types = match origin {
-                        OpaqueTyOrigin::FnReturn | OpaqueTyOrigin::AsyncFn => {
-                            &tcx.mir_borrowck(owner.expect_local()).concrete_opaque_types
-                        }
-                        OpaqueTyOrigin::Misc => {
-                            // We shouldn't leak borrowck results through impl trait in bindings.
-                            // For example, we shouldn't be able to tell if `x` in
-                            // `let x: impl Sized + 'a = &()` has type `&'static ()` or `&'a ()`.
-                            &tcx.typeck_tables_of(owner.expect_local()).concrete_opaque_types
-                        }
-                        OpaqueTyOrigin::TypeAlias => {
-                            span_bug!(item.span, "Type alias impl trait shouldn't have an owner")
-                        }
-                    };
-                    let concrete_ty = concrete_types
+                ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: Some(owner), .. }) => {
+                    let concrete_ty = tcx
+                        .mir_borrowck(owner.expect_local())
+                        .concrete_opaque_types
                         .get(&def_id)
                         .map(|opaque| opaque.concrete_type)
                         .unwrap_or_else(|| {
@@ -155,13 +139,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                             }
                         });
                     debug!("concrete_ty = {:?}", concrete_ty);
-                    if concrete_ty.has_erased_regions() {
-                        // FIXME(impl_trait_in_bindings) Handle this case.
-                        tcx.sess.span_fatal(
-                            item.span,
-                            "lifetimes in impl Trait types in bindings are not currently supported",
-                        );
-                    }
                     concrete_ty
                 }
                 ItemKind::Trait(..)
@@ -596,6 +573,60 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
     }
 }
 
+/// Retrieve the inferred concrete type for let position impl trait.
+///
+/// This is different to other kinds of impl trait because:
+///
+/// 1. We know which function contains the defining use (the function that
+///    contains the let statement)
+/// 2. We do not currently allow (free) lifetimes in the return type. `let`
+///    statements in some statically unreachable code are removed from the MIR
+///    by the time we borrow check, and it's not clear how we should handle
+///    those.
+fn let_position_impl_trait_type(tcx: TyCtxt<'_>, opaque_ty_id: LocalDefId) -> Ty<'_> {
+    let scope = tcx.hir().get_defining_scope(tcx.hir().as_local_hir_id(opaque_ty_id));
+    let scope_def_id = tcx.hir().local_def_id(scope);
+
+    let opaque_ty_def_id = opaque_ty_id.to_def_id();
+
+    let owner_tables = tcx.typeck_tables_of(scope_def_id);
+    let concrete_ty = owner_tables
+        .concrete_opaque_types
+        .get(&opaque_ty_def_id)
+        .map(|opaque| opaque.concrete_type)
+        .unwrap_or_else(|| {
+            tcx.sess.delay_span_bug(
+                DUMMY_SP,
+                &format!(
+                    "owner {:?} has no opaque type for {:?} in its tables",
+                    scope_def_id, opaque_ty_id
+                ),
+            );
+            if let Some(ErrorReported) = owner_tables.tainted_by_errors {
+                // Some error in the owner fn prevented us from populating the
+                // `concrete_opaque_types` table.
+                tcx.types.err
+            } else {
+                // We failed to resolve the opaque type or it resolves to
+                // itself. Return the non-revealed type, which should result in
+                // E0720.
+                tcx.mk_opaque(
+                    opaque_ty_def_id,
+                    InternalSubsts::identity_for_item(tcx, opaque_ty_def_id),
+                )
+            }
+        });
+    debug!("concrete_ty = {:?}", concrete_ty);
+    if concrete_ty.has_erased_regions() {
+        // FIXME(impl_trait_in_bindings) Handle this case.
+        tcx.sess.span_fatal(
+            tcx.hir().span(tcx.hir().as_local_hir_id(opaque_ty_id)),
+            "lifetimes in impl Trait types in bindings are not currently supported",
+        );
+    }
+    concrete_ty
+}
+
 fn infer_placeholder_type(
     tcx: TyCtxt<'_>,
     def_id: LocalDefId,
diff --git a/src/librustc_typeck/expr_use_visitor.rs b/src/librustc_typeck/expr_use_visitor.rs
index 53973eba229..6baadb8febd 100644
--- a/src/librustc_typeck/expr_use_visitor.rs
+++ b/src/librustc_typeck/expr_use_visitor.rs
@@ -185,7 +185,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
                 self.consume_exprs(args);
             }
 
-            hir::ExprKind::MethodCall(.., ref args) => {
+            hir::ExprKind::MethodCall(.., ref args, _) => {
                 // callee.m(args)
                 self.consume_exprs(args);
             }
diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs
index e13d9ea2b26..37d383db68a 100644
--- a/src/librustc_typeck/impl_wf_check.rs
+++ b/src/librustc_typeck/impl_wf_check.rs
@@ -140,13 +140,6 @@ fn enforce_impl_params_are_constrained(
                         Vec::new()
                     }
                 }
-                ty::AssocKind::OpaqueTy => {
-                    // We don't know which lifetimes appear in the actual
-                    // opaque type, so use all of the lifetimes that appear
-                    // in the type's predicates.
-                    let predicates = tcx.predicates_of(def_id).instantiate_identity(tcx);
-                    cgp::parameters_for(&predicates, true)
-                }
                 ty::AssocKind::Fn | ty::AssocKind::Const => Vec::new(),
             }
         })
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index dd4df11b1df..adb2ae9a5d6 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1138,10 +1138,6 @@ impl Clean<Item> for hir::ImplItem<'_> {
                 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() },
-                true,
-            ),
         };
         let local_did = cx.tcx.hir().local_def_id(self.hir_id);
         Item {
@@ -1308,7 +1304,6 @@ impl Clean<Item> for ty::AssocItem {
                     )
                 }
             }
-            ty::AssocKind::OpaqueTy => unimplemented!(),
         };
 
         let visibility = match self.container {
@@ -1356,7 +1351,7 @@ impl Clean<Type> for hir::Ty<'_> {
                 Array(box ty.clean(cx), length)
             }
             TyKind::Tup(ref tys) => Tuple(tys.clean(cx)),
-            TyKind::Def(item_id, _) => {
+            TyKind::OpaqueDef(item_id, _) => {
                 let item = cx.tcx.hir().expect_item(item_id.id);
                 if let hir::ItemKind::OpaqueTy(ref ty) = item.kind {
                     ImplTrait(ty.bounds.clean(cx))
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index 018c0e82c45..f0900c34a4b 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -126,7 +126,7 @@ impl<'a> SourceCollector<'a> {
             &self.scx.themes,
         );
         self.scx.fs.write(&cur, v.as_bytes())?;
-        self.scx.local_sources.insert(p.clone(), href);
+        self.scx.local_sources.insert(p, href);
         Ok(())
     }
 }
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 149480ec80f..f5b2f1bb5b1 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -12,6 +12,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::ty;
 use rustc_resolve::ParentScope;
 use rustc_session::lint;
+use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::Ident;
 use rustc_span::symbol::Symbol;
 use rustc_span::DUMMY_SP;
@@ -122,6 +123,42 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
         }
     }
 
+    /// Resolves a string as a macro.
+    fn macro_resolve(&self, path_str: &str, parent_id: Option<hir::HirId>) -> Option<Res> {
+        let cx = self.cx;
+        let path = ast::Path::from_ident(Ident::from_str(path_str));
+        cx.enter_resolver(|resolver| {
+            if let Ok((Some(ext), res)) = resolver.resolve_macro_path(
+                &path,
+                None,
+                &ParentScope::module(resolver.graph_root()),
+                false,
+                false,
+            ) {
+                if let SyntaxExtensionKind::LegacyBang { .. } = ext.kind {
+                    return Some(res.map_id(|_| panic!("unexpected id")));
+                }
+            }
+            if let Some(res) = resolver.all_macros().get(&Symbol::intern(path_str)) {
+                return Some(res.map_id(|_| panic!("unexpected id")));
+            }
+            if let Some(module_id) = parent_id.or(self.mod_ids.last().cloned()) {
+                let module_id = cx.tcx.hir().local_def_id(module_id);
+                if let Ok((_, res)) =
+                    resolver.resolve_str_path_error(DUMMY_SP, path_str, MacroNS, module_id)
+                {
+                    // don't resolve builtins like `#[derive]`
+                    if let Res::Def(..) = res {
+                        let res = res.map_id(|_| panic!("unexpected node_id"));
+                        return Some(res);
+                    }
+                }
+            } else {
+                debug!("attempting to resolve item without parent module: {}", path_str);
+            }
+            None
+        })
+    }
     /// Resolves a string as a path within a particular namespace. Also returns an optional
     /// URL fragment in the case of variants and methods.
     fn resolve(
@@ -371,6 +408,22 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
     }
 }
 
+/// Check for resolve collisions between a trait and its derive
+///
+/// These are common and we should just resolve to the trait in that case
+fn is_derive_trait_collision<T>(ns: &PerNS<Option<(Res, T)>>) -> bool {
+    if let PerNS {
+        type_ns: Some((Res::Def(DefKind::Trait, _), _)),
+        macro_ns: Some((Res::Def(DefKind::Macro(MacroKind::Derive), _), _)),
+        ..
+    } = *ns
+    {
+        true
+    } else {
+        false
+    }
+}
+
 impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
     fn fold_item(&mut self, mut item: Item) -> Option<Item> {
         let item_hir_id = if item.is_mod() {
@@ -451,7 +504,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
                             ..
                         },
                     ..
-                })) => segments.first().and_then(|seg| Some(seg.ident.to_string())),
+                })) => segments.first().map(|seg| seg.ident.to_string()),
                 Some(hir::Node::Item(hir::Item {
                     ident, kind: hir::ItemKind::Enum(..), ..
                 }))
@@ -532,6 +585,9 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
                 } else if link.starts_with("macro@") {
                     kind = Some(MacroNS);
                     link.trim_start_matches("macro@")
+                } else if link.starts_with("derive@") {
+                    kind = Some(MacroNS);
+                    link.trim_start_matches("derive@")
                 } else if link.ends_with('!') {
                     kind = Some(MacroNS);
                     link.trim_end_matches('!')
@@ -614,8 +670,9 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
                     }
                     None => {
                         // Try everything!
-                        let candidates = PerNS {
-                            macro_ns: macro_resolve(cx, path_str)
+                        let mut candidates = PerNS {
+                            macro_ns: self
+                                .macro_resolve(path_str, base_node)
                                 .map(|res| (res, extra_fragment.clone())),
                             type_ns: match self.resolve(
                                 path_str,
@@ -668,10 +725,16 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
                             continue;
                         }
 
-                        let is_unambiguous = candidates.clone().present_items().count() == 1;
-                        if is_unambiguous {
+                        let len = candidates.clone().present_items().count();
+
+                        if len == 1 {
                             candidates.present_items().next().unwrap()
+                        } else if len == 2 && is_derive_trait_collision(&candidates) {
+                            candidates.type_ns.unwrap()
                         } else {
+                            if is_derive_trait_collision(&candidates) {
+                                candidates.macro_ns = None;
+                            }
                             ambiguity_error(
                                 cx,
                                 &item,
@@ -684,7 +747,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
                         }
                     }
                     Some(MacroNS) => {
-                        if let Some(res) = macro_resolve(cx, path_str) {
+                        if let Some(res) = self.macro_resolve(path_str, base_node) {
                             (res, extra_fragment)
                         } else {
                             resolution_failure(cx, &item, path_str, &dox, link_range);
@@ -727,28 +790,6 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
     }
 }
 
-/// Resolves a string as a macro.
-fn macro_resolve(cx: &DocContext<'_>, path_str: &str) -> Option<Res> {
-    let path = ast::Path::from_ident(Ident::from_str(path_str));
-    cx.enter_resolver(|resolver| {
-        if let Ok((Some(ext), res)) = resolver.resolve_macro_path(
-            &path,
-            None,
-            &ParentScope::module(resolver.graph_root()),
-            false,
-            false,
-        ) {
-            if let SyntaxExtensionKind::LegacyBang { .. } = ext.kind {
-                return Some(res.map_id(|_| panic!("unexpected id")));
-            }
-        }
-        if let Some(res) = resolver.all_macros().get(&Symbol::intern(path_str)) {
-            return Some(res.map_id(|_| panic!("unexpected id")));
-        }
-        None
-    })
-}
-
 fn build_diagnostic(
     cx: &DocContext<'_>,
     item: &Item,
@@ -916,7 +957,7 @@ fn ambiguity_error(
                             Res::Def(DefKind::AssocFn | DefKind::Fn, _) => {
                                 ("add parentheses", format!("{}()", path_str))
                             }
-                            Res::Def(DefKind::Macro(..), _) => {
+                            Res::Def(DefKind::Macro(MacroKind::Bang), _) => {
                                 ("add an exclamation mark", format!("{}!", path_str))
                             }
                             _ => {
@@ -930,6 +971,9 @@ fn ambiguity_error(
                                     (Res::Def(DefKind::Mod, _), _) => "module",
                                     (_, TypeNS) => "type",
                                     (_, ValueNS) => "value",
+                                    (Res::Def(DefKind::Macro(MacroKind::Derive), _), MacroNS) => {
+                                        "derive"
+                                    }
                                     (_, MacroNS) => "macro",
                                 };
 
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 4b15a591da7..21aa0ded5a4 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -676,7 +676,11 @@ impl Collector {
     }
 
     fn generate_name(&self, line: usize, filename: &FileName) -> String {
-        format!("{} - {} (line {})", filename, self.names.join("::"), line)
+        let mut item_path = self.names.join("::");
+        if !item_path.is_empty() {
+            item_path.push(' ');
+        }
+        format!("{} - {}(line {})", filename, item_path, line)
     }
 
     pub fn set_position(&mut self, position: Span) {
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 6af1cbb34b6..83029a86420 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -41,7 +41,7 @@ dlmalloc = { version = "0.1", features = ['rustc-dep-of-std'] }
 fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] }
 
 [target.'cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_os = "hermit"))'.dependencies]
-hermit-abi = { version = "0.1.13", features = ['rustc-dep-of-std'] }
+hermit-abi = { version = "0.1.14", features = ['rustc-dep-of-std'] }
 
 [target.wasm32-wasi.dependencies]
 wasi = { version = "0.9.0", features = ['rustc-dep-of-std'], default-features = false }
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index 8ff19557a30..d752ba89a27 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -916,8 +916,7 @@ impl f32 {
 
 #[cfg(test)]
 mod tests {
-    use crate::f32;
-    use crate::f32::*;
+    use crate::f32::consts;
     use crate::num::FpCategory as Fp;
     use crate::num::*;
 
@@ -928,14 +927,14 @@ mod tests {
 
     #[test]
     fn test_min_nan() {
-        assert_eq!(NAN.min(2.0), 2.0);
-        assert_eq!(2.0f32.min(NAN), 2.0);
+        assert_eq!(f32::NAN.min(2.0), 2.0);
+        assert_eq!(2.0f32.min(f32::NAN), 2.0);
     }
 
     #[test]
     fn test_max_nan() {
-        assert_eq!(NAN.max(2.0), 2.0);
-        assert_eq!(2.0f32.max(NAN), 2.0);
+        assert_eq!(f32::NAN.max(2.0), 2.0);
+        assert_eq!(2.0f32.max(f32::NAN), 2.0);
     }
 
     #[test]
@@ -1158,52 +1157,52 @@ mod tests {
 
     #[test]
     fn test_abs() {
-        assert_eq!(INFINITY.abs(), INFINITY);
+        assert_eq!(f32::INFINITY.abs(), f32::INFINITY);
         assert_eq!(1f32.abs(), 1f32);
         assert_eq!(0f32.abs(), 0f32);
         assert_eq!((-0f32).abs(), 0f32);
         assert_eq!((-1f32).abs(), 1f32);
-        assert_eq!(NEG_INFINITY.abs(), INFINITY);
-        assert_eq!((1f32 / NEG_INFINITY).abs(), 0f32);
-        assert!(NAN.abs().is_nan());
+        assert_eq!(f32::NEG_INFINITY.abs(), f32::INFINITY);
+        assert_eq!((1f32 / f32::NEG_INFINITY).abs(), 0f32);
+        assert!(f32::NAN.abs().is_nan());
     }
 
     #[test]
     fn test_signum() {
-        assert_eq!(INFINITY.signum(), 1f32);
+        assert_eq!(f32::INFINITY.signum(), 1f32);
         assert_eq!(1f32.signum(), 1f32);
         assert_eq!(0f32.signum(), 1f32);
         assert_eq!((-0f32).signum(), -1f32);
         assert_eq!((-1f32).signum(), -1f32);
-        assert_eq!(NEG_INFINITY.signum(), -1f32);
-        assert_eq!((1f32 / NEG_INFINITY).signum(), -1f32);
-        assert!(NAN.signum().is_nan());
+        assert_eq!(f32::NEG_INFINITY.signum(), -1f32);
+        assert_eq!((1f32 / f32::NEG_INFINITY).signum(), -1f32);
+        assert!(f32::NAN.signum().is_nan());
     }
 
     #[test]
     fn test_is_sign_positive() {
-        assert!(INFINITY.is_sign_positive());
+        assert!(f32::INFINITY.is_sign_positive());
         assert!(1f32.is_sign_positive());
         assert!(0f32.is_sign_positive());
         assert!(!(-0f32).is_sign_positive());
         assert!(!(-1f32).is_sign_positive());
-        assert!(!NEG_INFINITY.is_sign_positive());
-        assert!(!(1f32 / NEG_INFINITY).is_sign_positive());
-        assert!(NAN.is_sign_positive());
-        assert!(!(-NAN).is_sign_positive());
+        assert!(!f32::NEG_INFINITY.is_sign_positive());
+        assert!(!(1f32 / f32::NEG_INFINITY).is_sign_positive());
+        assert!(f32::NAN.is_sign_positive());
+        assert!(!(-f32::NAN).is_sign_positive());
     }
 
     #[test]
     fn test_is_sign_negative() {
-        assert!(!INFINITY.is_sign_negative());
+        assert!(!f32::INFINITY.is_sign_negative());
         assert!(!1f32.is_sign_negative());
         assert!(!0f32.is_sign_negative());
         assert!((-0f32).is_sign_negative());
         assert!((-1f32).is_sign_negative());
-        assert!(NEG_INFINITY.is_sign_negative());
-        assert!((1f32 / NEG_INFINITY).is_sign_negative());
-        assert!(!NAN.is_sign_negative());
-        assert!((-NAN).is_sign_negative());
+        assert!(f32::NEG_INFINITY.is_sign_negative());
+        assert!((1f32 / f32::NEG_INFINITY).is_sign_negative());
+        assert!(!f32::NAN.is_sign_negative());
+        assert!((-f32::NAN).is_sign_negative());
     }
 
     #[test]
@@ -1268,13 +1267,13 @@ mod tests {
 
     #[test]
     fn test_sqrt_domain() {
-        assert!(NAN.sqrt().is_nan());
-        assert!(NEG_INFINITY.sqrt().is_nan());
+        assert!(f32::NAN.sqrt().is_nan());
+        assert!(f32::NEG_INFINITY.sqrt().is_nan());
         assert!((-1.0f32).sqrt().is_nan());
         assert_eq!((-0.0f32).sqrt(), -0.0);
         assert_eq!(0.0f32.sqrt(), 0.0);
         assert_eq!(1.0f32.sqrt(), 1.0);
-        assert_eq!(INFINITY.sqrt(), INFINITY);
+        assert_eq!(f32::INFINITY.sqrt(), f32::INFINITY);
     }
 
     #[test]
@@ -1523,13 +1522,13 @@ mod tests {
     #[test]
     #[should_panic]
     fn test_clamp_min_is_nan() {
-        let _ = 1.0f32.clamp(NAN, 1.0);
+        let _ = 1.0f32.clamp(f32::NAN, 1.0);
     }
 
     #[test]
     #[should_panic]
     fn test_clamp_max_is_nan() {
-        let _ = 1.0f32.clamp(3.0, NAN);
+        let _ = 1.0f32.clamp(3.0, f32::NAN);
     }
 
     #[test]
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index d7845fd2c4d..9cd60d846a7 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -943,8 +943,7 @@ impl f64 {
 
 #[cfg(test)]
 mod tests {
-    use crate::f64;
-    use crate::f64::*;
+    use crate::f64::consts;
     use crate::num::FpCategory as Fp;
     use crate::num::*;
 
@@ -955,19 +954,19 @@ mod tests {
 
     #[test]
     fn test_min_nan() {
-        assert_eq!(NAN.min(2.0), 2.0);
-        assert_eq!(2.0f64.min(NAN), 2.0);
+        assert_eq!(f64::NAN.min(2.0), 2.0);
+        assert_eq!(2.0f64.min(f64::NAN), 2.0);
     }
 
     #[test]
     fn test_max_nan() {
-        assert_eq!(NAN.max(2.0), 2.0);
-        assert_eq!(2.0f64.max(NAN), 2.0);
+        assert_eq!(f64::NAN.max(2.0), 2.0);
+        assert_eq!(2.0f64.max(f64::NAN), 2.0);
     }
 
     #[test]
     fn test_nan() {
-        let nan: f64 = NAN;
+        let nan: f64 = f64::NAN;
         assert!(nan.is_nan());
         assert!(!nan.is_infinite());
         assert!(!nan.is_finite());
@@ -979,7 +978,7 @@ mod tests {
 
     #[test]
     fn test_infinity() {
-        let inf: f64 = INFINITY;
+        let inf: f64 = f64::INFINITY;
         assert!(inf.is_infinite());
         assert!(!inf.is_finite());
         assert!(inf.is_sign_positive());
@@ -991,7 +990,7 @@ mod tests {
 
     #[test]
     fn test_neg_infinity() {
-        let neg_inf: f64 = NEG_INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
         assert!(neg_inf.is_infinite());
         assert!(!neg_inf.is_finite());
         assert!(!neg_inf.is_sign_positive());
@@ -1043,9 +1042,9 @@ mod tests {
 
     #[test]
     fn test_is_nan() {
-        let nan: f64 = NAN;
-        let inf: f64 = INFINITY;
-        let neg_inf: f64 = NEG_INFINITY;
+        let nan: f64 = f64::NAN;
+        let inf: f64 = f64::INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
         assert!(nan.is_nan());
         assert!(!0.0f64.is_nan());
         assert!(!5.3f64.is_nan());
@@ -1056,9 +1055,9 @@ mod tests {
 
     #[test]
     fn test_is_infinite() {
-        let nan: f64 = NAN;
-        let inf: f64 = INFINITY;
-        let neg_inf: f64 = NEG_INFINITY;
+        let nan: f64 = f64::NAN;
+        let inf: f64 = f64::INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
         assert!(!nan.is_infinite());
         assert!(inf.is_infinite());
         assert!(neg_inf.is_infinite());
@@ -1069,9 +1068,9 @@ mod tests {
 
     #[test]
     fn test_is_finite() {
-        let nan: f64 = NAN;
-        let inf: f64 = INFINITY;
-        let neg_inf: f64 = NEG_INFINITY;
+        let nan: f64 = f64::NAN;
+        let inf: f64 = f64::INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
         assert!(!nan.is_finite());
         assert!(!inf.is_finite());
         assert!(!neg_inf.is_finite());
@@ -1083,9 +1082,9 @@ mod tests {
     #[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
     #[test]
     fn test_is_normal() {
-        let nan: f64 = NAN;
-        let inf: f64 = INFINITY;
-        let neg_inf: f64 = NEG_INFINITY;
+        let nan: f64 = f64::NAN;
+        let inf: f64 = f64::INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
         let zero: f64 = 0.0f64;
         let neg_zero: f64 = -0.0;
         assert!(!nan.is_normal());
@@ -1101,9 +1100,9 @@ mod tests {
     #[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630
     #[test]
     fn test_classify() {
-        let nan: f64 = NAN;
-        let inf: f64 = INFINITY;
-        let neg_inf: f64 = NEG_INFINITY;
+        let nan: f64 = f64::NAN;
+        let inf: f64 = f64::INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
         let zero: f64 = 0.0f64;
         let neg_zero: f64 = -0.0;
         assert_eq!(nan.classify(), Fp::Nan);
@@ -1187,59 +1186,59 @@ mod tests {
 
     #[test]
     fn test_abs() {
-        assert_eq!(INFINITY.abs(), INFINITY);
+        assert_eq!(f64::INFINITY.abs(), f64::INFINITY);
         assert_eq!(1f64.abs(), 1f64);
         assert_eq!(0f64.abs(), 0f64);
         assert_eq!((-0f64).abs(), 0f64);
         assert_eq!((-1f64).abs(), 1f64);
-        assert_eq!(NEG_INFINITY.abs(), INFINITY);
-        assert_eq!((1f64 / NEG_INFINITY).abs(), 0f64);
-        assert!(NAN.abs().is_nan());
+        assert_eq!(f64::NEG_INFINITY.abs(), f64::INFINITY);
+        assert_eq!((1f64 / f64::NEG_INFINITY).abs(), 0f64);
+        assert!(f64::NAN.abs().is_nan());
     }
 
     #[test]
     fn test_signum() {
-        assert_eq!(INFINITY.signum(), 1f64);
+        assert_eq!(f64::INFINITY.signum(), 1f64);
         assert_eq!(1f64.signum(), 1f64);
         assert_eq!(0f64.signum(), 1f64);
         assert_eq!((-0f64).signum(), -1f64);
         assert_eq!((-1f64).signum(), -1f64);
-        assert_eq!(NEG_INFINITY.signum(), -1f64);
-        assert_eq!((1f64 / NEG_INFINITY).signum(), -1f64);
-        assert!(NAN.signum().is_nan());
+        assert_eq!(f64::NEG_INFINITY.signum(), -1f64);
+        assert_eq!((1f64 / f64::NEG_INFINITY).signum(), -1f64);
+        assert!(f64::NAN.signum().is_nan());
     }
 
     #[test]
     fn test_is_sign_positive() {
-        assert!(INFINITY.is_sign_positive());
+        assert!(f64::INFINITY.is_sign_positive());
         assert!(1f64.is_sign_positive());
         assert!(0f64.is_sign_positive());
         assert!(!(-0f64).is_sign_positive());
         assert!(!(-1f64).is_sign_positive());
-        assert!(!NEG_INFINITY.is_sign_positive());
-        assert!(!(1f64 / NEG_INFINITY).is_sign_positive());
-        assert!(NAN.is_sign_positive());
-        assert!(!(-NAN).is_sign_positive());
+        assert!(!f64::NEG_INFINITY.is_sign_positive());
+        assert!(!(1f64 / f64::NEG_INFINITY).is_sign_positive());
+        assert!(f64::NAN.is_sign_positive());
+        assert!(!(-f64::NAN).is_sign_positive());
     }
 
     #[test]
     fn test_is_sign_negative() {
-        assert!(!INFINITY.is_sign_negative());
+        assert!(!f64::INFINITY.is_sign_negative());
         assert!(!1f64.is_sign_negative());
         assert!(!0f64.is_sign_negative());
         assert!((-0f64).is_sign_negative());
         assert!((-1f64).is_sign_negative());
-        assert!(NEG_INFINITY.is_sign_negative());
-        assert!((1f64 / NEG_INFINITY).is_sign_negative());
-        assert!(!NAN.is_sign_negative());
-        assert!((-NAN).is_sign_negative());
+        assert!(f64::NEG_INFINITY.is_sign_negative());
+        assert!((1f64 / f64::NEG_INFINITY).is_sign_negative());
+        assert!(!f64::NAN.is_sign_negative());
+        assert!((-f64::NAN).is_sign_negative());
     }
 
     #[test]
     fn test_mul_add() {
-        let nan: f64 = NAN;
-        let inf: f64 = INFINITY;
-        let neg_inf: f64 = NEG_INFINITY;
+        let nan: f64 = f64::NAN;
+        let inf: f64 = f64::INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
         assert_approx_eq!(12.3f64.mul_add(4.5, 6.7), 62.05);
         assert_approx_eq!((-12.3f64).mul_add(-4.5, -6.7), 48.65);
         assert_approx_eq!(0.0f64.mul_add(8.9, 1.2), 1.2);
@@ -1253,9 +1252,9 @@ mod tests {
 
     #[test]
     fn test_recip() {
-        let nan: f64 = NAN;
-        let inf: f64 = INFINITY;
-        let neg_inf: f64 = NEG_INFINITY;
+        let nan: f64 = f64::NAN;
+        let inf: f64 = f64::INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
         assert_eq!(1.0f64.recip(), 1.0);
         assert_eq!(2.0f64.recip(), 0.5);
         assert_eq!((-0.4f64).recip(), -2.5);
@@ -1267,9 +1266,9 @@ mod tests {
 
     #[test]
     fn test_powi() {
-        let nan: f64 = NAN;
-        let inf: f64 = INFINITY;
-        let neg_inf: f64 = NEG_INFINITY;
+        let nan: f64 = f64::NAN;
+        let inf: f64 = f64::INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
         assert_eq!(1.0f64.powi(1), 1.0);
         assert_approx_eq!((-3.1f64).powi(2), 9.61);
         assert_approx_eq!(5.9f64.powi(-2), 0.028727);
@@ -1281,9 +1280,9 @@ mod tests {
 
     #[test]
     fn test_powf() {
-        let nan: f64 = NAN;
-        let inf: f64 = INFINITY;
-        let neg_inf: f64 = NEG_INFINITY;
+        let nan: f64 = f64::NAN;
+        let inf: f64 = f64::INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
         assert_eq!(1.0f64.powf(1.0), 1.0);
         assert_approx_eq!(3.4f64.powf(4.5), 246.408183);
         assert_approx_eq!(2.7f64.powf(-3.2), 0.041652);
@@ -1297,13 +1296,13 @@ mod tests {
 
     #[test]
     fn test_sqrt_domain() {
-        assert!(NAN.sqrt().is_nan());
-        assert!(NEG_INFINITY.sqrt().is_nan());
+        assert!(f64::NAN.sqrt().is_nan());
+        assert!(f64::NEG_INFINITY.sqrt().is_nan());
         assert!((-1.0f64).sqrt().is_nan());
         assert_eq!((-0.0f64).sqrt(), -0.0);
         assert_eq!(0.0f64.sqrt(), 0.0);
         assert_eq!(1.0f64.sqrt(), 1.0);
-        assert_eq!(INFINITY.sqrt(), INFINITY);
+        assert_eq!(f64::INFINITY.sqrt(), f64::INFINITY);
     }
 
     #[test]
@@ -1312,9 +1311,9 @@ mod tests {
         assert_approx_eq!(2.718282, 1.0f64.exp());
         assert_approx_eq!(148.413159, 5.0f64.exp());
 
-        let inf: f64 = INFINITY;
-        let neg_inf: f64 = NEG_INFINITY;
-        let nan: f64 = NAN;
+        let inf: f64 = f64::INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
+        let nan: f64 = f64::NAN;
         assert_eq!(inf, inf.exp());
         assert_eq!(0.0, neg_inf.exp());
         assert!(nan.exp().is_nan());
@@ -1325,9 +1324,9 @@ mod tests {
         assert_eq!(32.0, 5.0f64.exp2());
         assert_eq!(1.0, 0.0f64.exp2());
 
-        let inf: f64 = INFINITY;
-        let neg_inf: f64 = NEG_INFINITY;
-        let nan: f64 = NAN;
+        let inf: f64 = f64::INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
+        let nan: f64 = f64::NAN;
         assert_eq!(inf, inf.exp2());
         assert_eq!(0.0, neg_inf.exp2());
         assert!(nan.exp2().is_nan());
@@ -1335,9 +1334,9 @@ mod tests {
 
     #[test]
     fn test_ln() {
-        let nan: f64 = NAN;
-        let inf: f64 = INFINITY;
-        let neg_inf: f64 = NEG_INFINITY;
+        let nan: f64 = f64::NAN;
+        let inf: f64 = f64::INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
         assert_approx_eq!(1.0f64.exp().ln(), 1.0);
         assert!(nan.ln().is_nan());
         assert_eq!(inf.ln(), inf);
@@ -1350,9 +1349,9 @@ mod tests {
 
     #[test]
     fn test_log() {
-        let nan: f64 = NAN;
-        let inf: f64 = INFINITY;
-        let neg_inf: f64 = NEG_INFINITY;
+        let nan: f64 = f64::NAN;
+        let inf: f64 = f64::INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
         assert_eq!(10.0f64.log(10.0), 1.0);
         assert_approx_eq!(2.3f64.log(3.5), 0.664858);
         assert_eq!(1.0f64.exp().log(1.0f64.exp()), 1.0);
@@ -1368,9 +1367,9 @@ mod tests {
 
     #[test]
     fn test_log2() {
-        let nan: f64 = NAN;
-        let inf: f64 = INFINITY;
-        let neg_inf: f64 = NEG_INFINITY;
+        let nan: f64 = f64::NAN;
+        let inf: f64 = f64::INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
         assert_approx_eq!(10.0f64.log2(), 3.321928);
         assert_approx_eq!(2.3f64.log2(), 1.201634);
         assert_approx_eq!(1.0f64.exp().log2(), 1.442695);
@@ -1384,9 +1383,9 @@ mod tests {
 
     #[test]
     fn test_log10() {
-        let nan: f64 = NAN;
-        let inf: f64 = INFINITY;
-        let neg_inf: f64 = NEG_INFINITY;
+        let nan: f64 = f64::NAN;
+        let inf: f64 = f64::INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
         assert_eq!(10.0f64.log10(), 1.0);
         assert_approx_eq!(2.3f64.log10(), 0.361728);
         assert_approx_eq!(1.0f64.exp().log10(), 0.434294);
@@ -1402,9 +1401,9 @@ mod tests {
     #[test]
     fn test_to_degrees() {
         let pi: f64 = consts::PI;
-        let nan: f64 = NAN;
-        let inf: f64 = INFINITY;
-        let neg_inf: f64 = NEG_INFINITY;
+        let nan: f64 = f64::NAN;
+        let inf: f64 = f64::INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
         assert_eq!(0.0f64.to_degrees(), 0.0);
         assert_approx_eq!((-5.8f64).to_degrees(), -332.315521);
         assert_eq!(pi.to_degrees(), 180.0);
@@ -1416,9 +1415,9 @@ mod tests {
     #[test]
     fn test_to_radians() {
         let pi: f64 = consts::PI;
-        let nan: f64 = NAN;
-        let inf: f64 = INFINITY;
-        let neg_inf: f64 = NEG_INFINITY;
+        let nan: f64 = f64::NAN;
+        let inf: f64 = f64::INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
         assert_eq!(0.0f64.to_radians(), 0.0);
         assert_approx_eq!(154.6f64.to_radians(), 2.698279);
         assert_approx_eq!((-332.31f64).to_radians(), -5.799903);
@@ -1433,9 +1432,9 @@ mod tests {
         assert_eq!(0.0f64.asinh(), 0.0f64);
         assert_eq!((-0.0f64).asinh(), -0.0f64);
 
-        let inf: f64 = INFINITY;
-        let neg_inf: f64 = NEG_INFINITY;
-        let nan: f64 = NAN;
+        let inf: f64 = f64::INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
+        let nan: f64 = f64::NAN;
         assert_eq!(inf.asinh(), inf);
         assert_eq!(neg_inf.asinh(), neg_inf);
         assert!(nan.asinh().is_nan());
@@ -1450,9 +1449,9 @@ mod tests {
         assert_eq!(1.0f64.acosh(), 0.0f64);
         assert!(0.999f64.acosh().is_nan());
 
-        let inf: f64 = INFINITY;
-        let neg_inf: f64 = NEG_INFINITY;
-        let nan: f64 = NAN;
+        let inf: f64 = f64::INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
+        let nan: f64 = f64::NAN;
         assert_eq!(inf.acosh(), inf);
         assert!(neg_inf.acosh().is_nan());
         assert!(nan.acosh().is_nan());
@@ -1465,9 +1464,9 @@ mod tests {
         assert_eq!(0.0f64.atanh(), 0.0f64);
         assert_eq!((-0.0f64).atanh(), -0.0f64);
 
-        let inf: f64 = INFINITY;
-        let neg_inf: f64 = NEG_INFINITY;
-        let nan: f64 = NAN;
+        let inf: f64 = f64::INFINITY;
+        let neg_inf: f64 = f64::NEG_INFINITY;
+        let nan: f64 = f64::NAN;
         assert_eq!(1.0f64.atanh(), inf);
         assert_eq!((-1.0f64).atanh(), neg_inf);
         assert!(2f64.atanh().atanh().is_nan());
@@ -1546,13 +1545,13 @@ mod tests {
     #[test]
     #[should_panic]
     fn test_clamp_min_is_nan() {
-        let _ = 1.0f64.clamp(NAN, 1.0);
+        let _ = 1.0f64.clamp(f64::NAN, 1.0);
     }
 
     #[test]
     #[should_panic]
     fn test_clamp_max_is_nan() {
-        let _ = 1.0f64.clamp(3.0, NAN);
+        let _ = 1.0f64.clamp(3.0, f64::NAN);
     }
 
     #[test]
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index b324b161896..dca1fdde482 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -234,15 +234,14 @@ pub struct NulError(usize, Vec<u8>);
 
 /// An error indicating that a nul byte was not in the expected position.
 ///
-/// The slice used to create a [`CStr`] must have one and only one nul
-/// byte at the end of the slice.
+/// The slice used to create a [`CStr`] must have one and only one nul byte,
+/// positioned at the end.
 ///
-/// This error is created by the
-/// [`from_bytes_with_nul`][`CStr::from_bytes_with_nul`] method on
-/// [`CStr`]. See its documentation for more.
+/// This error is created by the [`from_bytes_with_nul`] method on [`CStr`].
+/// See its documentation for more.
 ///
 /// [`CStr`]: struct.CStr.html
-/// [`CStr::from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul
+/// [`from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul
 ///
 /// # Examples
 ///
@@ -257,6 +256,32 @@ pub struct FromBytesWithNulError {
     kind: FromBytesWithNulErrorKind,
 }
 
+/// An error indicating that a nul byte was not in the expected position.
+///
+/// The vector used to create a [`CString`] must have one and only one nul byte,
+/// positioned at the end.
+///
+/// This error is created by the [`from_vec_with_nul`] method on [`CString`].
+/// See its documentation for more.
+///
+/// [`CString`]: struct.CString.html
+/// [`from_vec_with_nul`]: struct.CString.html#method.from_vec_with_nul
+///
+/// # Examples
+///
+/// ```
+/// #![feature(cstring_from_vec_with_nul)]
+/// use std::ffi::{CString, FromVecWithNulError};
+///
+/// let _: FromVecWithNulError = CString::from_vec_with_nul(b"f\0oo".to_vec()).unwrap_err();
+/// ```
+#[derive(Clone, PartialEq, Eq, Debug)]
+#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
+pub struct FromVecWithNulError {
+    error_kind: FromBytesWithNulErrorKind,
+    bytes: Vec<u8>,
+}
+
 #[derive(Clone, PartialEq, Eq, Debug)]
 enum FromBytesWithNulErrorKind {
     InteriorNul(usize),
@@ -272,6 +297,59 @@ impl FromBytesWithNulError {
     }
 }
 
+#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
+impl FromVecWithNulError {
+    /// Returns a slice of [`u8`]s bytes that were attempted to convert to a [`CString`].
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(cstring_from_vec_with_nul)]
+    /// use std::ffi::CString;
+    ///
+    /// // Some invalid bytes in a vector
+    /// let bytes = b"f\0oo".to_vec();
+    ///
+    /// let value = CString::from_vec_with_nul(bytes.clone());
+    ///
+    /// assert_eq!(&bytes[..], value.unwrap_err().as_bytes());
+    /// ```
+    ///
+    /// [`CString`]: struct.CString.html
+    pub fn as_bytes(&self) -> &[u8] {
+        &self.bytes[..]
+    }
+
+    /// Returns the bytes that were attempted to convert to a [`CString`].
+    ///
+    /// This method is carefully constructed to avoid allocation. It will
+    /// consume the error, moving out the bytes, so that a copy of the bytes
+    /// does not need to be made.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(cstring_from_vec_with_nul)]
+    /// use std::ffi::CString;
+    ///
+    /// // Some invalid bytes in a vector
+    /// let bytes = b"f\0oo".to_vec();
+    ///
+    /// let value = CString::from_vec_with_nul(bytes.clone());
+    ///
+    /// assert_eq!(bytes, value.unwrap_err().into_bytes());
+    /// ```
+    ///
+    /// [`CString`]: struct.CString.html
+    pub fn into_bytes(self) -> Vec<u8> {
+        self.bytes
+    }
+}
+
 /// An error indicating invalid UTF-8 when converting a [`CString`] into a [`String`].
 ///
 /// `CString` is just a wrapper over a buffer of bytes with a nul
@@ -643,6 +721,86 @@ impl CString {
         let this = mem::ManuallyDrop::new(self);
         unsafe { ptr::read(&this.inner) }
     }
+
+    /// Converts a `Vec` of `u8` to a `CString` without checking the invariants
+    /// on the given `Vec`.
+    ///
+    /// # Safety
+    ///
+    /// The given `Vec` **must** have one nul byte as its last element.
+    /// This means it cannot be empty nor have any other nul byte anywhere else.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(cstring_from_vec_with_nul)]
+    /// use std::ffi::CString;
+    /// assert_eq!(
+    ///     unsafe { CString::from_vec_with_nul_unchecked(b"abc\0".to_vec()) },
+    ///     unsafe { CString::from_vec_unchecked(b"abc".to_vec()) }
+    /// );
+    /// ```
+    #[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
+    pub unsafe fn from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
+        Self { inner: v.into_boxed_slice() }
+    }
+
+    /// Attempts to converts a `Vec` of `u8` to a `CString`.
+    ///
+    /// Runtime checks are present to ensure there is only one nul byte in the
+    /// `Vec`, its last element.
+    ///
+    /// # Errors
+    ///
+    /// If a nul byte is present and not the last element or no nul bytes
+    /// is present, an error will be returned.
+    ///
+    /// # Examples
+    ///
+    /// A successful conversion will produce the same result as [`new`] when
+    /// called without the ending nul byte.
+    ///
+    /// ```
+    /// #![feature(cstring_from_vec_with_nul)]
+    /// use std::ffi::CString;
+    /// assert_eq!(
+    ///     CString::from_vec_with_nul(b"abc\0".to_vec())
+    ///         .expect("CString::from_vec_with_nul failed"),
+    ///     CString::new(b"abc".to_vec()).expect("CString::new failed")
+    /// );
+    /// ```
+    ///
+    /// A incorrectly formatted vector will produce an error.
+    ///
+    /// ```
+    /// #![feature(cstring_from_vec_with_nul)]
+    /// use std::ffi::{CString, FromVecWithNulError};
+    /// // Interior nul byte
+    /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"a\0bc".to_vec()).unwrap_err();
+    /// // No nul byte
+    /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"abc".to_vec()).unwrap_err();
+    /// ```
+    ///
+    /// [`new`]: #method.new
+    #[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
+    pub fn from_vec_with_nul(v: Vec<u8>) -> Result<Self, FromVecWithNulError> {
+        let nul_pos = memchr::memchr(0, &v);
+        match nul_pos {
+            Some(nul_pos) if nul_pos + 1 == v.len() => {
+                // SAFETY: We know there is only one nul byte, at the end
+                // of the vec.
+                Ok(unsafe { Self::from_vec_with_nul_unchecked(v) })
+            }
+            Some(nul_pos) => Err(FromVecWithNulError {
+                error_kind: FromBytesWithNulErrorKind::InteriorNul(nul_pos),
+                bytes: v,
+            }),
+            None => Err(FromVecWithNulError {
+                error_kind: FromBytesWithNulErrorKind::NotNulTerminated,
+                bytes: v,
+            }),
+        }
+    }
 }
 
 // Turns this `CString` into an empty string to prevent
@@ -976,6 +1134,23 @@ impl fmt::Display for FromBytesWithNulError {
     }
 }
 
+#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
+impl Error for FromVecWithNulError {}
+
+#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
+impl fmt::Display for FromVecWithNulError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self.error_kind {
+            FromBytesWithNulErrorKind::InteriorNul(pos) => {
+                write!(f, "data provided contains an interior nul byte at pos {}", pos)
+            }
+            FromBytesWithNulErrorKind::NotNulTerminated => {
+                write!(f, "data provided is not nul terminated")
+            }
+        }
+    }
+}
+
 impl IntoStringError {
     /// Consumes this error, returning original [`CString`] which generated the
     /// error.
diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs
index 5aca7b7476a..f442d7fde1a 100644
--- a/src/libstd/ffi/mod.rs
+++ b/src/libstd/ffi/mod.rs
@@ -157,6 +157,8 @@
 
 #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
 pub use self::c_str::FromBytesWithNulError;
+#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
+pub use self::c_str::FromVecWithNulError;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::c_str::{CStr, CString, IntoStringError, NulError};
 
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index e986a39eb03..0737008a94c 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -366,7 +366,7 @@ impl<R: Seek> Seek for BufReader<R> {
             // it should be safe to assume that remainder fits within an i64 as the alternative
             // means we managed to allocate 8 exbibytes and that's absurd.
             // But it's not out of the realm of possibility for some weird underlying reader to
-            // support seeking by i64::min_value() so we need to handle underflow when subtracting
+            // support seeking by i64::MIN so we need to handle underflow when subtracting
             // remainder.
             if let Some(offset) = n.checked_sub(remainder) {
                 result = self.inner.seek(SeekFrom::Current(offset))?;
@@ -1268,7 +1268,7 @@ mod tests {
                         self.pos = self.pos.wrapping_add(n as u64);
                     }
                     SeekFrom::End(n) => {
-                        self.pos = u64::max_value().wrapping_add(n as u64);
+                        self.pos = u64::MAX.wrapping_add(n as u64);
                     }
                 }
                 Ok(self.pos)
@@ -1277,11 +1277,11 @@ mod tests {
 
         let mut reader = BufReader::with_capacity(5, PositionReader { pos: 0 });
         assert_eq!(reader.fill_buf().ok(), Some(&[0, 1, 2, 3, 4][..]));
-        assert_eq!(reader.seek(SeekFrom::End(-5)).ok(), Some(u64::max_value() - 5));
+        assert_eq!(reader.seek(SeekFrom::End(-5)).ok(), Some(u64::MAX - 5));
         assert_eq!(reader.fill_buf().ok().map(|s| s.len()), Some(5));
         // the following seek will require two underlying seeks
         let expected = 9223372036854775802;
-        assert_eq!(reader.seek(SeekFrom::Current(i64::min_value())).ok(), Some(expected));
+        assert_eq!(reader.seek(SeekFrom::Current(i64::MIN)).ok(), Some(expected));
         assert_eq!(reader.fill_buf().ok().map(|s| s.len()), Some(5));
         // seeking to 0 should empty the buffer.
         assert_eq!(reader.seek(SeekFrom::Current(0)).ok(), Some(expected));
@@ -1319,7 +1319,7 @@ mod tests {
         // The following seek will require two underlying seeks.  The first will
         // succeed but the second will fail.  This should still invalidate the
         // buffer.
-        assert!(reader.seek(SeekFrom::Current(i64::min_value())).is_err());
+        assert!(reader.seek(SeekFrom::Current(i64::MIN)).is_err());
         assert_eq!(reader.buffer().len(), 0);
     }
 
diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs
index f3e3fc81a5d..f4db5f81450 100644
--- a/src/libstd/io/cursor.rs
+++ b/src/libstd/io/cursor.rs
@@ -963,7 +963,7 @@ mod tests {
     #[cfg(target_pointer_width = "32")]
     fn vec_seek_and_write_past_usize_max() {
         let mut c = Cursor::new(Vec::new());
-        c.set_position(<usize>::max_value() as u64 + 1);
+        c.set_position(usize::MAX as u64 + 1);
         assert!(c.write_all(&[1, 2, 3]).is_err());
     }
 
diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs
index b780340884e..b8fa1a7f744 100644
--- a/src/libstd/net/addr.rs
+++ b/src/libstd/net/addr.rs
@@ -694,42 +694,6 @@ impl PartialEq for SocketAddrV6 {
             && self.inner.sin6_scope_id == other.inner.sin6_scope_id
     }
 }
-#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
-impl PartialEq<SocketAddrV4> for SocketAddr {
-    fn eq(&self, other: &SocketAddrV4) -> bool {
-        match self {
-            SocketAddr::V4(v4) => v4 == other,
-            SocketAddr::V6(_) => false,
-        }
-    }
-}
-#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
-impl PartialEq<SocketAddrV6> for SocketAddr {
-    fn eq(&self, other: &SocketAddrV6) -> bool {
-        match self {
-            SocketAddr::V4(_) => false,
-            SocketAddr::V6(v6) => v6 == other,
-        }
-    }
-}
-#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
-impl PartialEq<SocketAddr> for SocketAddrV4 {
-    fn eq(&self, other: &SocketAddr) -> bool {
-        match other {
-            SocketAddr::V4(v4) => self == v4,
-            SocketAddr::V6(_) => false,
-        }
-    }
-}
-#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
-impl PartialEq<SocketAddr> for SocketAddrV6 {
-    fn eq(&self, other: &SocketAddr) -> bool {
-        match other {
-            SocketAddr::V4(_) => false,
-            SocketAddr::V6(v6) => self == v6,
-        }
-    }
-}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Eq for SocketAddrV4 {}
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1242,12 +1206,8 @@ mod tests {
         // equality
         assert_eq!(v4_1, v4_1);
         assert_eq!(v6_1, v6_1);
-        assert_eq!(v4_1, SocketAddr::V4(v4_1));
-        assert_eq!(v6_1, SocketAddr::V6(v6_1));
         assert_eq!(SocketAddr::V4(v4_1), SocketAddr::V4(v4_1));
         assert_eq!(SocketAddr::V6(v6_1), SocketAddr::V6(v6_1));
-        assert!(v4_1 != SocketAddr::V6(v6_1));
-        assert!(v6_1 != SocketAddr::V4(v4_1));
         assert!(v4_1 != v4_2);
         assert!(v6_1 != v6_2);
 
@@ -1268,5 +1228,10 @@ mod tests {
         assert!(v6_1 < v6_3);
         assert!(v4_3 > v4_1);
         assert!(v6_3 > v6_1);
+
+        // compare with an inferred right-hand side
+        assert_eq!(v4_1, "224.120.45.1:23456".parse().unwrap());
+        assert_eq!(v6_1, "[2001:db8:f00::1002]:23456".parse().unwrap());
+        assert_eq!(SocketAddr::V4(v4_1), "224.120.45.1:23456".parse().unwrap());
     }
 }
diff --git a/src/libstd/num.rs b/src/libstd/num.rs
index de8acf8d9d4..b496c16a749 100644
--- a/src/libstd/num.rs
+++ b/src/libstd/num.rs
@@ -52,52 +52,43 @@ where
 #[cfg(test)]
 mod tests {
     use crate::ops::Mul;
-    use crate::u16;
-    use crate::u32;
-    use crate::u64;
-    use crate::u8;
-    use crate::usize;
 
     #[test]
     fn test_saturating_add_uint() {
-        use crate::usize::MAX;
         assert_eq!(3_usize.saturating_add(5_usize), 8_usize);
-        assert_eq!(3_usize.saturating_add(MAX - 1), MAX);
-        assert_eq!(MAX.saturating_add(MAX), MAX);
-        assert_eq!((MAX - 2).saturating_add(1), MAX - 1);
+        assert_eq!(3_usize.saturating_add(usize::MAX - 1), usize::MAX);
+        assert_eq!(usize::MAX.saturating_add(usize::MAX), usize::MAX);
+        assert_eq!((usize::MAX - 2).saturating_add(1), usize::MAX - 1);
     }
 
     #[test]
     fn test_saturating_sub_uint() {
-        use crate::usize::MAX;
         assert_eq!(5_usize.saturating_sub(3_usize), 2_usize);
         assert_eq!(3_usize.saturating_sub(5_usize), 0_usize);
         assert_eq!(0_usize.saturating_sub(1_usize), 0_usize);
-        assert_eq!((MAX - 1).saturating_sub(MAX), 0);
+        assert_eq!((usize::MAX - 1).saturating_sub(usize::MAX), 0);
     }
 
     #[test]
     fn test_saturating_add_int() {
-        use crate::isize::{MAX, MIN};
         assert_eq!(3i32.saturating_add(5), 8);
-        assert_eq!(3isize.saturating_add(MAX - 1), MAX);
-        assert_eq!(MAX.saturating_add(MAX), MAX);
-        assert_eq!((MAX - 2).saturating_add(1), MAX - 1);
+        assert_eq!(3isize.saturating_add(isize::MAX - 1), isize::MAX);
+        assert_eq!(isize::MAX.saturating_add(isize::MAX), isize::MAX);
+        assert_eq!((isize::MAX - 2).saturating_add(1), isize::MAX - 1);
         assert_eq!(3i32.saturating_add(-5), -2);
-        assert_eq!(MIN.saturating_add(-1), MIN);
-        assert_eq!((-2isize).saturating_add(-MAX), MIN);
+        assert_eq!(isize::MIN.saturating_add(-1), isize::MIN);
+        assert_eq!((-2isize).saturating_add(-isize::MAX), isize::MIN);
     }
 
     #[test]
     fn test_saturating_sub_int() {
-        use crate::isize::{MAX, MIN};
         assert_eq!(3i32.saturating_sub(5), -2);
-        assert_eq!(MIN.saturating_sub(1), MIN);
-        assert_eq!((-2isize).saturating_sub(MAX), MIN);
+        assert_eq!(isize::MIN.saturating_sub(1), isize::MIN);
+        assert_eq!((-2isize).saturating_sub(isize::MAX), isize::MIN);
         assert_eq!(3i32.saturating_sub(-5), 8);
-        assert_eq!(3isize.saturating_sub(-(MAX - 1)), MAX);
-        assert_eq!(MAX.saturating_sub(-MAX), MAX);
-        assert_eq!((MAX - 2).saturating_sub(-1), MAX - 1);
+        assert_eq!(3isize.saturating_sub(-(isize::MAX - 1)), isize::MAX);
+        assert_eq!(isize::MAX.saturating_sub(-isize::MAX), isize::MAX);
+        assert_eq!((isize::MAX - 2).saturating_sub(-1), isize::MAX - 1);
     }
 
     #[test]
diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs
index 77e521eae9a..2250c0d4203 100644
--- a/src/libstd/sync/condvar.rs
+++ b/src/libstd/sync/condvar.rs
@@ -609,7 +609,6 @@ mod tests {
     use crate::sync::{Arc, Condvar, Mutex};
     use crate::thread;
     use crate::time::Duration;
-    use crate::u64;
 
     #[test]
     fn smoke() {
diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs
index e70204d6839..d6cc811154f 100644
--- a/src/libstd/sync/mpsc/mod.rs
+++ b/src/libstd/sync/mpsc/mod.rs
@@ -2176,8 +2176,7 @@ mod tests {
     #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn very_long_recv_timeout_wont_panic() {
         let (tx, rx) = channel::<()>();
-        let join_handle =
-            thread::spawn(move || rx.recv_timeout(Duration::from_secs(u64::max_value())));
+        let join_handle = thread::spawn(move || rx.recv_timeout(Duration::from_secs(u64::MAX)));
         thread::sleep(Duration::from_secs(1));
         assert!(tx.send(()).is_ok());
         assert_eq!(join_handle.join().unwrap(), Ok(()));
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index 797b22fdd12..8478457eabf 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -107,6 +107,60 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult};
 ///
 /// *guard += 1;
 /// ```
+///
+/// It is sometimes necessary to manually drop the mutex guard to unlock it
+/// sooner than the end of the enclosing scope.
+///
+/// ```
+/// use std::sync::{Arc, Mutex};
+/// use std::thread;
+///
+/// const N: usize = 3;
+///
+/// let data_mutex = Arc::new(Mutex::new(vec![1, 2, 3, 4]));
+/// let res_mutex = Arc::new(Mutex::new(0));
+///
+/// let mut threads = Vec::with_capacity(N);
+/// (0..N).for_each(|_| {
+///     let data_mutex_clone = Arc::clone(&data_mutex);
+///     let res_mutex_clone = Arc::clone(&res_mutex);
+///
+///     threads.push(thread::spawn(move || {
+///         let mut data = data_mutex_clone.lock().unwrap();
+///         // This is the result of some important and long-ish work.
+///         let result = data.iter().fold(0, |acc, x| acc + x * 2);
+///         data.push(result);
+///         drop(data);
+///         *res_mutex_clone.lock().unwrap() += result;
+///     }));
+/// });
+///
+/// let mut data = data_mutex.lock().unwrap();
+/// // This is the result of some important and long-ish work.
+/// let result = data.iter().fold(0, |acc, x| acc + x * 2);
+/// data.push(result);
+/// // We drop the `data` explicitly because it's not necessary anymore and the
+/// // thread still has work to do. This allow other threads to start working on
+/// // the data immediately, without waiting for the rest of the unrelated work
+/// // to be done here.
+/// //
+/// // It's even more important here than in the threads because we `.join` the
+/// // threads after that. If we had not dropped the mutex guard, a thread could
+/// // be waiting forever for it, causing a deadlock.
+/// drop(data);
+/// // Here the mutex guard is not assigned to a variable and so, even if the
+/// // scope does not end after this line, the mutex is still released: there is
+/// // no deadlock.
+/// *res_mutex.lock().unwrap() += result;
+///
+/// threads.into_iter().for_each(|thread| {
+///     thread
+///         .join()
+///         .expect("The thread creating or execution failed !")
+/// });
+///
+/// assert_eq!(*res_mutex.lock().unwrap(), 800);
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "mutex_type")]
 pub struct Mutex<T: ?Sized> {
diff --git a/src/libstd/sys/cloudabi/condvar.rs b/src/libstd/sys/cloudabi/condvar.rs
index 3ba51d77494..dabdc0c9b51 100644
--- a/src/libstd/sys/cloudabi/condvar.rs
+++ b/src/libstd/sys/cloudabi/condvar.rs
@@ -42,7 +42,7 @@ impl Condvar {
             let ret = abi::condvar_signal(
                 condvar as *mut abi::condvar,
                 abi::scope::PRIVATE,
-                abi::nthreads::max_value(),
+                abi::nthreads::MAX,
             );
             assert_eq!(ret, abi::errno::SUCCESS, "Failed to broadcast on condition variable");
         }
diff --git a/src/libstd/sys/hermit/condvar.rs b/src/libstd/sys/hermit/condvar.rs
index 94e3275448a..132e579b3a5 100644
--- a/src/libstd/sys/hermit/condvar.rs
+++ b/src/libstd/sys/hermit/condvar.rs
@@ -35,7 +35,7 @@ impl Condvar {
 
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
         let nanos = dur.as_nanos();
-        let nanos = cmp::min(i64::max_value() as u128, nanos);
+        let nanos = cmp::min(i64::MAX as u128, nanos);
 
         // add current task to the wait queue
         let _ = abi::add_queue(self.id(), nanos as i64);
diff --git a/src/libstd/sys/hermit/net.rs b/src/libstd/sys/hermit/net.rs
index 5b5379c8b05..9e588c4265a 100644
--- a/src/libstd/sys/hermit/net.rs
+++ b/src/libstd/sys/hermit/net.rs
@@ -1,10 +1,13 @@
 use crate::convert::TryFrom;
 use crate::fmt;
 use crate::io::{self, ErrorKind, IoSlice, IoSliceMut};
-use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
+use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
 use crate::str;
+use crate::sync::Arc;
 use crate::sys::hermit::abi;
+use crate::sys::hermit::abi::IpAddress::{Ipv4, Ipv6};
 use crate::sys::{unsupported, Void};
+use crate::sys_common::AsInner;
 use crate::time::Duration;
 
 /// Checks whether the HermitCore's socket interface has been started already, and
@@ -17,14 +20,33 @@ pub fn init() -> io::Result<()> {
     Ok(())
 }
 
-pub struct TcpStream(abi::Handle);
+#[derive(Debug, Clone)]
+pub struct Socket(abi::Handle);
+
+impl AsInner<abi::Handle> for Socket {
+    fn as_inner(&self) -> &abi::Handle {
+        &self.0
+    }
+}
+
+impl Drop for Socket {
+    fn drop(&mut self) {
+        let _ = abi::tcpstream::close(self.0);
+    }
+}
+
+// Arc is used to count the number of used sockets.
+// Only if all sockets are released, the drop
+// method will close the socket.
+#[derive(Clone)]
+pub struct TcpStream(Arc<Socket>);
 
 impl TcpStream {
     pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
         let addr = addr?;
 
         match abi::tcpstream::connect(addr.ip().to_string().as_bytes(), addr.port(), None) {
-            Ok(handle) => Ok(TcpStream(handle)),
+            Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))),
             _ => {
                 Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket"))
             }
@@ -37,7 +59,7 @@ impl TcpStream {
             saddr.port(),
             Some(duration.as_millis() as u64),
         ) {
-            Ok(handle) => Ok(TcpStream(handle)),
+            Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))),
             _ => {
                 Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket"))
             }
@@ -45,31 +67,34 @@ impl TcpStream {
     }
 
     pub fn set_read_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
-        abi::tcpstream::set_read_timeout(self.0, duration.map(|d| d.as_millis() as u64))
+        abi::tcpstream::set_read_timeout(*self.0.as_inner(), duration.map(|d| d.as_millis() as u64))
             .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value"))
     }
 
     pub fn set_write_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
-        abi::tcpstream::set_write_timeout(self.0, duration.map(|d| d.as_millis() as u64))
-            .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value"))
+        abi::tcpstream::set_write_timeout(
+            *self.0.as_inner(),
+            duration.map(|d| d.as_millis() as u64),
+        )
+        .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value"))
     }
 
     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
-        let duration = abi::tcpstream::get_read_timeout(self.0)
+        let duration = abi::tcpstream::get_read_timeout(*self.0.as_inner())
             .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to determine timeout value"))?;
 
         Ok(duration.map(|d| Duration::from_millis(d)))
     }
 
     pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
-        let duration = abi::tcpstream::get_write_timeout(self.0)
+        let duration = abi::tcpstream::get_write_timeout(*self.0.as_inner())
             .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to determine timeout value"))?;
 
         Ok(duration.map(|d| Duration::from_millis(d)))
     }
 
     pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
-        abi::tcpstream::peek(self.0, buf)
+        abi::tcpstream::peek(*self.0.as_inner(), buf)
             .map_err(|_| io::Error::new(ErrorKind::Other, "set_nodelay failed"))
     }
 
@@ -81,18 +106,11 @@ impl TcpStream {
         let mut size: usize = 0;
 
         for i in ioslice.iter_mut() {
-            let mut pos: usize = 0;
-
-            while pos < i.len() {
-                let ret = abi::tcpstream::read(self.0, &mut i[pos..])
-                    .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to read on socket"))?;
-
-                if ret == 0 {
-                    return Ok(size);
-                } else {
-                    size += ret;
-                    pos += ret;
-                }
+            let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..])
+                .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to read on socket"))?;
+
+            if ret != 0 {
+                size += ret;
             }
         }
 
@@ -112,7 +130,7 @@ impl TcpStream {
         let mut size: usize = 0;
 
         for i in ioslice.iter() {
-            size += abi::tcpstream::write(self.0, i)
+            size += abi::tcpstream::write(*self.0.as_inner(), i)
                 .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to write on socket"))?;
         }
 
@@ -125,7 +143,21 @@ impl TcpStream {
     }
 
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        Err(io::Error::new(ErrorKind::Other, "peer_addr isn't supported"))
+        let (ipaddr, port) = abi::tcpstream::peer_addr(*self.0.as_inner())
+            .map_err(|_| io::Error::new(ErrorKind::Other, "peer_addr failed"))?;
+
+        let saddr = match ipaddr {
+            Ipv4(ref addr) => SocketAddr::new(
+                IpAddr::V4(Ipv4Addr::new(addr.0[0], addr.0[1], addr.0[2], addr.0[3])),
+                port,
+            ),
+            Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port),
+            _ => {
+                return Err(io::Error::new(ErrorKind::Other, "peer_addr failed"));
+            }
+        };
+
+        Ok(saddr)
     }
 
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
@@ -133,34 +165,31 @@ impl TcpStream {
     }
 
     pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
-        abi::tcpstream::shutdown(self.0, how as i32)
+        abi::tcpstream::shutdown(*self.0.as_inner(), how as i32)
             .map_err(|_| io::Error::new(ErrorKind::Other, "unable to shutdown socket"))
     }
 
     pub fn duplicate(&self) -> io::Result<TcpStream> {
-        let handle = abi::tcpstream::duplicate(self.0)
-            .map_err(|_| io::Error::new(ErrorKind::Other, "unable to duplicate stream"))?;
-
-        Ok(TcpStream(handle))
+        Ok(self.clone())
     }
 
     pub fn set_nodelay(&self, mode: bool) -> io::Result<()> {
-        abi::tcpstream::set_nodelay(self.0, mode)
+        abi::tcpstream::set_nodelay(*self.0.as_inner(), mode)
             .map_err(|_| io::Error::new(ErrorKind::Other, "set_nodelay failed"))
     }
 
     pub fn nodelay(&self) -> io::Result<bool> {
-        abi::tcpstream::nodelay(self.0)
+        abi::tcpstream::nodelay(*self.0.as_inner())
             .map_err(|_| io::Error::new(ErrorKind::Other, "nodelay failed"))
     }
 
     pub fn set_ttl(&self, tll: u32) -> io::Result<()> {
-        abi::tcpstream::set_tll(self.0, tll)
+        abi::tcpstream::set_tll(*self.0.as_inner(), tll)
             .map_err(|_| io::Error::new(ErrorKind::Other, "unable to set TTL"))
     }
 
     pub fn ttl(&self) -> io::Result<u32> {
-        abi::tcpstream::get_tll(self.0)
+        abi::tcpstream::get_tll(*self.0.as_inner())
             .map_err(|_| io::Error::new(ErrorKind::Other, "unable to get TTL"))
     }
 
@@ -169,40 +198,50 @@ impl TcpStream {
     }
 
     pub fn set_nonblocking(&self, mode: bool) -> io::Result<()> {
-        abi::tcpstream::set_nonblocking(self.0, mode)
+        abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode)
             .map_err(|_| io::Error::new(ErrorKind::Other, "unable to set blocking mode"))
     }
 }
 
-impl Drop for TcpStream {
-    fn drop(&mut self) {
-        let _ = abi::tcpstream::close(self.0);
-    }
-}
-
 impl fmt::Debug for TcpStream {
     fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         Ok(())
     }
 }
 
-pub struct TcpListener(abi::Handle);
+#[derive(Clone)]
+pub struct TcpListener(SocketAddr);
 
 impl TcpListener {
-    pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+    pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
+        let addr = addr?;
+
+        Ok(TcpListener(*addr))
     }
 
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Ok(self.0)
     }
 
     pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        let (handle, ipaddr, port) = abi::tcplistener::accept(self.0.port())
+            .map_err(|_| io::Error::new(ErrorKind::Other, "accept failed"))?;
+        let saddr = match ipaddr {
+            Ipv4(ref addr) => SocketAddr::new(
+                IpAddr::V4(Ipv4Addr::new(addr.0[0], addr.0[1], addr.0[2], addr.0[3])),
+                port,
+            ),
+            Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port),
+            _ => {
+                return Err(io::Error::new(ErrorKind::Other, "accept failed"));
+            }
+        };
+
+        Ok((TcpStream(Arc::new(Socket(handle))), saddr))
     }
 
     pub fn duplicate(&self) -> io::Result<TcpListener> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Ok(self.clone())
     }
 
     pub fn set_ttl(&self, _: u32) -> io::Result<()> {
diff --git a/src/libstd/sys/unix/android.rs b/src/libstd/sys/unix/android.rs
index 8fc2599f0d7..ea05ee3d7ce 100644
--- a/src/libstd/sys/unix/android.rs
+++ b/src/libstd/sys/unix/android.rs
@@ -95,7 +95,7 @@ pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> {
         match ftruncate64.get() {
             Some(f) => cvt_r(|| f(fd, size as i64)).map(drop),
             None => {
-                if size > i32::max_value() as u64 {
+                if size > i32::MAX as u64 {
                     Err(io::Error::new(io::ErrorKind::InvalidInput, "cannot truncate >2GB"))
                 } else {
                     cvt_r(|| ftruncate(fd, size as i32)).map(drop)
diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs
index b4896b7ad74..9f1847943f3 100644
--- a/src/libstd/sys/unix/condvar.rs
+++ b/src/libstd/sys/unix/condvar.rs
@@ -10,14 +10,10 @@ unsafe impl Send for Condvar {}
 unsafe impl Sync for Condvar {}
 
 const TIMESPEC_MAX: libc::timespec =
-    libc::timespec { tv_sec: <libc::time_t>::max_value(), tv_nsec: 1_000_000_000 - 1 };
+    libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
 
 fn saturating_cast_to_time_t(value: u64) -> libc::time_t {
-    if value > <libc::time_t>::max_value() as u64 {
-        <libc::time_t>::max_value()
-    } else {
-        value as libc::time_t
-    }
+    if value > <libc::time_t>::MAX as u64 { <libc::time_t>::MAX } else { value as libc::time_t }
 }
 
 impl Condvar {
diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs
index 32c2ac43129..cd24605ec7a 100644
--- a/src/libstd/sys/unix/ext/net.rs
+++ b/src/libstd/sys/unix/ext/net.rs
@@ -1090,7 +1090,7 @@ impl<'a> Iterator for Incoming<'a> {
     }
 
     fn size_hint(&self) -> (usize, Option<usize>) {
-        (usize::max_value(), None)
+        (usize::MAX, None)
     }
 }
 
diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs
index 1ef7ffacfcf..c481ca8961f 100644
--- a/src/libstd/sys/unix/fd.rs
+++ b/src/libstd/sys/unix/fd.rs
@@ -23,11 +23,7 @@ fn max_len() -> usize {
     // intentionally showing odd behavior by rejecting any read with a size
     // larger than or equal to INT_MAX. To handle both of these the read
     // size is capped on both platforms.
-    if cfg!(target_os = "macos") {
-        <c_int>::max_value() as usize - 1
-    } else {
-        <ssize_t>::max_value() as usize
-    }
+    if cfg!(target_os = "macos") { <c_int>::MAX as usize - 1 } else { <ssize_t>::MAX as usize }
 }
 
 impl FileDesc {
@@ -58,7 +54,7 @@ impl FileDesc {
             libc::readv(
                 self.fd,
                 bufs.as_ptr() as *const libc::iovec,
-                cmp::min(bufs.len(), c_int::max_value() as usize) as c_int,
+                cmp::min(bufs.len(), c_int::MAX as usize) as c_int,
             )
         })?;
         Ok(ret as usize)
@@ -115,7 +111,7 @@ impl FileDesc {
             libc::writev(
                 self.fd,
                 bufs.as_ptr() as *const libc::iovec,
-                cmp::min(bufs.len(), c_int::max_value() as usize) as c_int,
+                cmp::min(bufs.len(), c_int::MAX as usize) as c_int,
             )
         })?;
         Ok(ret as usize)
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index 80cf6a5dbc2..29cdbf05354 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -1196,7 +1196,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
     let mut written = 0u64;
     while written < len {
         let copy_result = if has_copy_file_range {
-            let bytes_to_copy = cmp::min(len - written, usize::max_value() as u64) as usize;
+            let bytes_to_copy = cmp::min(len - written, usize::MAX as u64) as usize;
             let copy_result = unsafe {
                 // We actually don't have to adjust the offsets,
                 // because copy_file_range adjusts the file offset automatically
diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs
index f062bc012f7..3717c660b57 100644
--- a/src/libstd/sys/unix/net.rs
+++ b/src/libstd/sys/unix/net.rs
@@ -148,7 +148,7 @@ impl Socket {
                 timeout = 1;
             }
 
-            let timeout = cmp::min(timeout, c_int::max_value() as u64) as c_int;
+            let timeout = cmp::min(timeout, c_int::MAX as u64) as c_int;
 
             match unsafe { libc::poll(&mut pollfd, 1, timeout) } {
                 -1 => {
@@ -283,8 +283,8 @@ impl Socket {
                     ));
                 }
 
-                let secs = if dur.as_secs() > libc::time_t::max_value() as u64 {
-                    libc::time_t::max_value()
+                let secs = if dur.as_secs() > libc::time_t::MAX as u64 {
+                    libc::time_t::MAX
                 } else {
                     dur.as_secs() as libc::time_t
                 };
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index 895ea48e2b4..7b3d69dcaa0 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -171,7 +171,7 @@ impl Thread {
         unsafe {
             while secs > 0 || nsecs > 0 {
                 let mut ts = libc::timespec {
-                    tv_sec: cmp::min(libc::time_t::max_value() as u64, secs) as libc::time_t,
+                    tv_sec: cmp::min(libc::time_t::MAX as u64, secs) as libc::time_t,
                     tv_nsec: nsecs,
                 };
                 secs -= ts.tv_sec as u64;
diff --git a/src/libstd/sys/vxworks/condvar.rs b/src/libstd/sys/vxworks/condvar.rs
index f2a1d681529..5a77966d974 100644
--- a/src/libstd/sys/vxworks/condvar.rs
+++ b/src/libstd/sys/vxworks/condvar.rs
@@ -10,14 +10,10 @@ unsafe impl Send for Condvar {}
 unsafe impl Sync for Condvar {}
 
 const TIMESPEC_MAX: libc::timespec =
-    libc::timespec { tv_sec: <libc::time_t>::max_value(), tv_nsec: 1_000_000_000 - 1 };
+    libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
 
 fn saturating_cast_to_time_t(value: u64) -> libc::time_t {
-    if value > <libc::time_t>::max_value() as u64 {
-        <libc::time_t>::max_value()
-    } else {
-        value as libc::time_t
-    }
+    if value > <libc::time_t>::MAX as u64 { <libc::time_t>::MAX } else { value as libc::time_t }
 }
 
 impl Condvar {
diff --git a/src/libstd/sys/vxworks/fd.rs b/src/libstd/sys/vxworks/fd.rs
index 23e9dc428ce..7fa86f0db04 100644
--- a/src/libstd/sys/vxworks/fd.rs
+++ b/src/libstd/sys/vxworks/fd.rs
@@ -17,7 +17,7 @@ fn max_len() -> usize {
     // The maximum read limit on most posix-like systems is `SSIZE_MAX`,
     // with the man page quoting that if the count of bytes to read is
     // greater than `SSIZE_MAX` the result is "unspecified".
-    <ssize_t>::max_value() as usize
+    <ssize_t>::MAX as usize
 }
 
 impl FileDesc {
@@ -48,7 +48,7 @@ impl FileDesc {
             libc::readv(
                 self.fd,
                 bufs.as_ptr() as *const libc::iovec,
-                cmp::min(bufs.len(), c_int::max_value() as usize) as c_int,
+                cmp::min(bufs.len(), c_int::MAX as usize) as c_int,
             )
         })?;
         Ok(ret as usize)
@@ -98,7 +98,7 @@ impl FileDesc {
             libc::writev(
                 self.fd,
                 bufs.as_ptr() as *const libc::iovec,
-                cmp::min(bufs.len(), c_int::max_value() as usize) as c_int,
+                cmp::min(bufs.len(), c_int::MAX as usize) as c_int,
             )
         })?;
         Ok(ret as usize)
diff --git a/src/libstd/sys/vxworks/net.rs b/src/libstd/sys/vxworks/net.rs
index de0b15b43a2..32c27ab6e9e 100644
--- a/src/libstd/sys/vxworks/net.rs
+++ b/src/libstd/sys/vxworks/net.rs
@@ -107,7 +107,7 @@ impl Socket {
                 timeout = 1;
             }
 
-            let timeout = cmp::min(timeout, c_int::max_value() as u64) as c_int;
+            let timeout = cmp::min(timeout, c_int::MAX as u64) as c_int;
 
             match unsafe { libc::poll(&mut pollfd, 1, timeout) } {
                 -1 => {
@@ -220,8 +220,8 @@ impl Socket {
                     ));
                 }
 
-                let secs = if dur.as_secs() > libc::time_t::max_value() as u64 {
-                    libc::time_t::max_value()
+                let secs = if dur.as_secs() > libc::time_t::MAX as u64 {
+                    libc::time_t::MAX
                 } else {
                     dur.as_secs() as libc::time_t
                 };
diff --git a/src/libstd/sys/vxworks/thread.rs b/src/libstd/sys/vxworks/thread.rs
index 4d0196e4b4d..24a2e0f965d 100644
--- a/src/libstd/sys/vxworks/thread.rs
+++ b/src/libstd/sys/vxworks/thread.rs
@@ -96,7 +96,7 @@ impl Thread {
         unsafe {
             while secs > 0 || nsecs > 0 {
                 let mut ts = libc::timespec {
-                    tv_sec: cmp::min(libc::time_t::max_value() as u64, secs) as libc::time_t,
+                    tv_sec: cmp::min(libc::time_t::MAX as u64, secs) as libc::time_t,
                     tv_nsec: nsecs,
                 };
                 secs -= ts.tv_sec as u64;
diff --git a/src/libstd/sys/wasi/mod.rs b/src/libstd/sys/wasi/mod.rs
index 29fafaaa0b9..4fe9661421b 100644
--- a/src/libstd/sys/wasi/mod.rs
+++ b/src/libstd/sys/wasi/mod.rs
@@ -64,7 +64,7 @@ pub fn unsupported_err() -> std_io::Error {
 
 pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind {
     use std_io::ErrorKind::*;
-    if errno > u16::max_value() as i32 || errno < 0 {
+    if errno > u16::MAX as i32 || errno < 0 {
         return Other;
     }
     match errno as u16 {
diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs
index 0986759b89b..0d39b1cec32 100644
--- a/src/libstd/sys/wasi/thread.rs
+++ b/src/libstd/sys/wasi/thread.rs
@@ -25,7 +25,7 @@ impl Thread {
 
     pub fn sleep(dur: Duration) {
         let nanos = dur.as_nanos();
-        assert!(nanos <= u64::max_value() as u128);
+        assert!(nanos <= u64::MAX as u128);
 
         const USERDATA: wasi::Userdata = 0x0123_45678;
 
diff --git a/src/libstd/sys/wasm/condvar_atomics.rs b/src/libstd/sys/wasm/condvar_atomics.rs
index a4021c0ee83..1859cdd5a0e 100644
--- a/src/libstd/sys/wasm/condvar_atomics.rs
+++ b/src/libstd/sys/wasm/condvar_atomics.rs
@@ -48,7 +48,7 @@ impl Condvar {
     #[inline]
     pub unsafe fn notify_all(&self) {
         self.cnt.fetch_add(1, SeqCst);
-        wasm32::atomic_notify(self.ptr(), u32::max_value()); // -1 == "wake everyone"
+        wasm32::atomic_notify(self.ptr(), u32::MAX); // -1 == "wake everyone"
     }
 
     pub unsafe fn wait(&self, mutex: &Mutex) {
@@ -72,7 +72,7 @@ impl Condvar {
         let ticket = self.cnt.load(SeqCst) as i32;
         mutex.unlock();
         let nanos = dur.as_nanos();
-        let nanos = cmp::min(i64::max_value() as u128, nanos);
+        let nanos = cmp::min(i64::MAX as u128, nanos);
 
         // If the return value is 2 then a timeout happened, so we return
         // `false` as we weren't actually notified.
diff --git a/src/libstd/sys/wasm/thread.rs b/src/libstd/sys/wasm/thread.rs
index 0e0e78a8276..0a11896a004 100644
--- a/src/libstd/sys/wasm/thread.rs
+++ b/src/libstd/sys/wasm/thread.rs
@@ -38,7 +38,7 @@ impl Thread {
         // 2).
         let mut nanos = dur.as_nanos();
         while nanos > 0 {
-            let amt = cmp::min(i64::max_value() as u128, nanos);
+            let amt = cmp::min(i64::MAX as u128, nanos);
             let mut x = 0;
             let val = unsafe { wasm32::i32_atomic_wait(&mut x, 0, amt as i64) };
             debug_assert_eq!(val, 2);
diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs
index 2131cfc2c94..0d4baa3b340 100644
--- a/src/libstd/sys/windows/handle.rs
+++ b/src/libstd/sys/windows/handle.rs
@@ -70,7 +70,7 @@ impl RawHandle {
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         let mut read = 0;
-        let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
+        let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD;
         let res = cvt(unsafe {
             c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID, len, &mut read, ptr::null_mut())
         });
@@ -99,7 +99,7 @@ impl RawHandle {
 
     pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
         let mut read = 0;
-        let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
+        let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD;
         let res = unsafe {
             let mut overlapped: c::OVERLAPPED = mem::zeroed();
             overlapped.Offset = offset as u32;
@@ -118,7 +118,7 @@ impl RawHandle {
         buf: &mut [u8],
         overlapped: *mut c::OVERLAPPED,
     ) -> io::Result<Option<usize>> {
-        let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
+        let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD;
         let mut amt = 0;
         let res = cvt(c::ReadFile(self.0, buf.as_ptr() as c::LPVOID, len, &mut amt, overlapped));
         match res {
@@ -165,7 +165,7 @@ impl RawHandle {
 
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         let mut amt = 0;
-        let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
+        let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD;
         cvt(unsafe {
             c::WriteFile(self.0, buf.as_ptr() as c::LPVOID, len, &mut amt, ptr::null_mut())
         })?;
@@ -183,7 +183,7 @@ impl RawHandle {
 
     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
         let mut written = 0;
-        let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
+        let len = cmp::min(buf.len(), <c::DWORD>::MAX as usize) as c::DWORD;
         unsafe {
             let mut overlapped: c::OVERLAPPED = mem::zeroed();
             overlapped.Offset = offset as u32;
diff --git a/src/libstd/sys/windows/io.rs b/src/libstd/sys/windows/io.rs
index 5525d283252..fb06df1f80c 100644
--- a/src/libstd/sys/windows/io.rs
+++ b/src/libstd/sys/windows/io.rs
@@ -12,7 +12,7 @@ pub struct IoSlice<'a> {
 impl<'a> IoSlice<'a> {
     #[inline]
     pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
-        assert!(buf.len() <= c::ULONG::max_value() as usize);
+        assert!(buf.len() <= c::ULONG::MAX as usize);
         IoSlice {
             vec: c::WSABUF {
                 len: buf.len() as c::ULONG,
@@ -49,7 +49,7 @@ pub struct IoSliceMut<'a> {
 impl<'a> IoSliceMut<'a> {
     #[inline]
     pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
-        assert!(buf.len() <= c::ULONG::max_value() as usize);
+        assert!(buf.len() <= c::ULONG::MAX as usize);
         IoSliceMut {
             vec: c::WSABUF { len: buf.len() as c::ULONG, buf: buf.as_mut_ptr() as *mut c::CHAR },
             _p: PhantomData,
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
index 69877e68ba8..d63139d8052 100644
--- a/src/libstd/sys/windows/mod.rs
+++ b/src/libstd/sys/windows/mod.rs
@@ -295,7 +295,7 @@ pub fn dur2timeout(dur: Duration) -> c::DWORD {
         .checked_mul(1000)
         .and_then(|ms| ms.checked_add((dur.subsec_nanos() as u64) / 1_000_000))
         .and_then(|ms| ms.checked_add(if dur.subsec_nanos() % 1_000_000 > 0 { 1 } else { 0 }))
-        .map(|ms| if ms > <c::DWORD>::max_value() as u64 { c::INFINITE } else { ms as c::DWORD })
+        .map(|ms| if ms > <c::DWORD>::MAX as u64 { c::INFINITE } else { ms as c::DWORD })
         .unwrap_or(c::INFINITE)
 }
 
diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs
index a15ded92f08..9e74454bc23 100644
--- a/src/libstd/sys/windows/net.rs
+++ b/src/libstd/sys/windows/net.rs
@@ -228,7 +228,7 @@ impl Socket {
     fn recv_with_flags(&self, buf: &mut [u8], flags: c_int) -> io::Result<usize> {
         // On unix when a socket is shut down all further reads return 0, so we
         // do the same on windows to map a shut down socket to returning EOF.
-        let len = cmp::min(buf.len(), i32::max_value() as usize) as i32;
+        let len = cmp::min(buf.len(), i32::MAX as usize) as i32;
         unsafe {
             match c::recv(self.0, buf.as_mut_ptr() as *mut c_void, len, flags) {
                 -1 if c::WSAGetLastError() == c::WSAESHUTDOWN => Ok(0),
@@ -245,7 +245,7 @@ impl Socket {
     pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         // On unix when a socket is shut down all further reads return 0, so we
         // do the same on windows to map a shut down socket to returning EOF.
-        let len = cmp::min(bufs.len(), c::DWORD::max_value() as usize) as c::DWORD;
+        let len = cmp::min(bufs.len(), c::DWORD::MAX as usize) as c::DWORD;
         let mut nread = 0;
         let mut flags = 0;
         unsafe {
@@ -282,7 +282,7 @@ impl Socket {
     ) -> io::Result<(usize, SocketAddr)> {
         let mut storage: c::SOCKADDR_STORAGE_LH = unsafe { mem::zeroed() };
         let mut addrlen = mem::size_of_val(&storage) as c::socklen_t;
-        let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
+        let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
 
         // On unix when a socket is shut down all further reads return 0, so we
         // do the same on windows to map a shut down socket to returning EOF.
@@ -313,7 +313,7 @@ impl Socket {
     }
 
     pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        let len = cmp::min(bufs.len(), c::DWORD::max_value() as usize) as c::DWORD;
+        let len = cmp::min(bufs.len(), c::DWORD::MAX as usize) as c::DWORD;
         let mut nwritten = 0;
         unsafe {
             cvt(c::WSASend(
diff --git a/src/libstd/sys_common/net.rs b/src/libstd/sys_common/net.rs
index 1c03bc92344..81a5ef95e82 100644
--- a/src/libstd/sys_common/net.rs
+++ b/src/libstd/sys_common/net.rs
@@ -271,7 +271,7 @@ impl TcpStream {
     }
 
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
-        let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
+        let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
         let ret = cvt(unsafe {
             c::send(*self.inner.as_inner(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
         })?;
@@ -502,7 +502,7 @@ impl UdpSocket {
     }
 
     pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
-        let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
+        let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
         let (dstp, dstlen) = dst.into_inner();
         let ret = cvt(unsafe {
             c::sendto(
@@ -641,7 +641,7 @@ impl UdpSocket {
     }
 
     pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
-        let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
+        let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
         let ret = cvt(unsafe {
             c::send(*self.inner.as_inner(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
         })?;
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index 3134a596756..d435ca68425 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -1530,7 +1530,6 @@ mod tests {
     use crate::sync::mpsc::{channel, Sender};
     use crate::thread::{self, ThreadId};
     use crate::time::Duration;
-    use crate::u32;
 
     // !!! These tests are dangerous. If something is buggy, they will hang, !!!
     // !!! instead of exiting cleanly. This might wedge the buildbots.       !!!
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
index c36e78b1d00..bc3bfde6d75 100644
--- a/src/libstd/time.rs
+++ b/src/libstd/time.rs
@@ -686,7 +686,7 @@ mod tests {
 
         // checked_add_duration will not panic on overflow
         let mut maybe_t = Some(Instant::now());
-        let max_duration = Duration::from_secs(u64::max_value());
+        let max_duration = Duration::from_secs(u64::MAX);
         // in case `Instant` can store `>= now + max_duration`.
         for _ in 0..2 {
             maybe_t = maybe_t.and_then(|t| t.checked_add(max_duration));
@@ -766,7 +766,7 @@ mod tests {
 
         // checked_add_duration will not panic on overflow
         let mut maybe_t = Some(SystemTime::UNIX_EPOCH);
-        let max_duration = Duration::from_secs(u64::max_value());
+        let max_duration = Duration::from_secs(u64::MAX);
         // in case `SystemTime` can store `>= UNIX_EPOCH + max_duration`.
         for _ in 0..2 {
             maybe_t = maybe_t.and_then(|t| t.checked_add(max_duration));
diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs
index 00749d93d55..f6f16f686e5 100644
--- a/src/libunwind/build.rs
+++ b/src/libunwind/build.rs
@@ -36,12 +36,6 @@ fn main() {
         println!("cargo:rustc-link-lib=gcc_pic");
     } else if target.contains("pc-windows-gnu") {
         // This is handled in the target spec with late_link_args_[static|dynamic]
-
-        // cfg!(bootstrap) doesn't work in build scripts
-        if env::var("RUSTC_STAGE").ok() == Some("0".to_string()) {
-            println!("cargo:rustc-link-lib=static-nobundle=gcc_eh");
-            println!("cargo:rustc-link-lib=static-nobundle=pthread");
-        }
     } else if target.contains("uwp-windows-gnu") {
         println!("cargo:rustc-link-lib=unwind");
     } else if target.contains("fuchsia") {
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 02dcfb8e829..3d252fe70af 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -203,6 +203,12 @@ void LLVMRustAddLastExtensionPasses(
 #define SUBTARGET_AARCH64
 #endif
 
+#ifdef LLVM_COMPONENT_AVR
+#define SUBTARGET_AVR SUBTARGET(AVR)
+#else
+#define SUBTARGET_AVR
+#endif
+
 #ifdef LLVM_COMPONENT_MIPS
 #define SUBTARGET_MIPS SUBTARGET(Mips)
 #else
@@ -249,6 +255,7 @@ void LLVMRustAddLastExtensionPasses(
   SUBTARGET_X86                                                                \
   SUBTARGET_ARM                                                                \
   SUBTARGET_AARCH64                                                            \
+  SUBTARGET_AVR                                                                \
   SUBTARGET_MIPS                                                               \
   SUBTARGET_PPC                                                                \
   SUBTARGET_SYSTEMZ                                                            \
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 6fac2662506..4704622922a 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -1094,8 +1094,17 @@ extern "C" void LLVMRustUnpackOptimizationDiagnostic(
   MessageOS << Opt->getMsg();
 }
 
+enum class LLVMRustDiagnosticLevel {
+    Error,
+    Warning,
+    Note,
+    Remark,
+};
+
 extern "C" void
-LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI, unsigned *CookieOut,
+LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
+                                  LLVMRustDiagnosticLevel *LevelOut,
+                                  unsigned *CookieOut,
                                   LLVMTwineRef *MessageOut,
                                   LLVMValueRef *InstructionOut) {
   // Undefined to call this not on an inline assembly diagnostic!
@@ -1105,6 +1114,23 @@ LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI, unsigned *CookieOut,
   *CookieOut = IA->getLocCookie();
   *MessageOut = wrap(&IA->getMsgStr());
   *InstructionOut = wrap(IA->getInstruction());
+
+  switch (IA->getSeverity()) {
+    case DS_Error:
+      *LevelOut = LLVMRustDiagnosticLevel::Error;
+      break;
+    case DS_Warning:
+      *LevelOut = LLVMRustDiagnosticLevel::Warning;
+      break;
+    case DS_Note:
+      *LevelOut = LLVMRustDiagnosticLevel::Note;
+      break;
+    case DS_Remark:
+      *LevelOut = LLVMRustDiagnosticLevel::Remark;
+      break;
+    default:
+      report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
+  }
 }
 
 extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
@@ -1166,6 +1192,7 @@ extern "C" LLVMRustDiagnosticKind
 LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
   return toRust((DiagnosticKind)unwrap(DI)->getKind());
 }
+
 // This is kept distinct from LLVMGetTypeKind, because when
 // a new type kind is added, the Rust-side enum must be
 // updated or UB will result.
@@ -1219,6 +1246,7 @@ extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
 extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
                                            RustStringRef MessageOut,
                                            RustStringRef BufferOut,
+                                           LLVMRustDiagnosticLevel* LevelOut,
                                            unsigned* LocOut,
                                            unsigned* RangesOut,
                                            size_t* NumRanges) {
@@ -1226,6 +1254,23 @@ extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
   RawRustStringOstream MessageOS(MessageOut);
   MessageOS << D.getMessage();
 
+  switch (D.getKind()) {
+    case SourceMgr::DK_Error:
+      *LevelOut = LLVMRustDiagnosticLevel::Error;
+      break;
+    case SourceMgr::DK_Warning:
+      *LevelOut = LLVMRustDiagnosticLevel::Warning;
+      break;
+    case SourceMgr::DK_Note:
+      *LevelOut = LLVMRustDiagnosticLevel::Note;
+      break;
+    case SourceMgr::DK_Remark:
+      *LevelOut = LLVMRustDiagnosticLevel::Remark;
+      break;
+    default:
+      report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
+  }
+
   if (D.getLoc() == SMLoc())
     return false;
 
diff --git a/src/test/debuginfo/associated-types.rs b/src/test/debuginfo/associated-types.rs
index 8d1170fd974..0a0ce3c671f 100644
--- a/src/test/debuginfo/associated-types.rs
+++ b/src/test/debuginfo/associated-types.rs
@@ -43,8 +43,8 @@
 // lldb-command:run
 
 // lldb-command:print arg
-// lldbg-check:[...]$0 = Struct<i32> { b: -1, b1: 0 }
-// lldbr-check:(associated_types::Struct<i32>) arg = Struct<i32> { b: -1, b1: 0 }
+// lldbg-check:[...]$0 = { b = -1, b1 = 0 }
+// lldbr-check:(associated_types::Struct<i32>) arg = { b = -1, b1 = 0 }
 // lldb-command:continue
 
 // lldb-command:print inferred
diff --git a/src/test/debuginfo/borrowed-struct.rs b/src/test/debuginfo/borrowed-struct.rs
index 3a164a41101..7f97d96b8db 100644
--- a/src/test/debuginfo/borrowed-struct.rs
+++ b/src/test/debuginfo/borrowed-struct.rs
@@ -35,8 +35,8 @@
 // lldb-command:run
 
 // lldb-command:print *stack_val_ref
-// lldbg-check:[...]$0 = SomeStruct { x: 10, y: 23.5 }
-// lldbr-check:(borrowed_struct::SomeStruct) *stack_val_ref = SomeStruct { x: 10, y: 23.5 }
+// lldbg-check:[...]$0 = { x = 10 y = 23.5 }
+// lldbr-check:(borrowed_struct::SomeStruct) *stack_val_ref = (x = 10, y = 23.5)
 
 // lldb-command:print *stack_val_interior_ref_1
 // lldbg-check:[...]$1 = 10
@@ -47,12 +47,12 @@
 // lldbr-check:(f64) *stack_val_interior_ref_2 = 23.5
 
 // lldb-command:print *ref_to_unnamed
-// lldbg-check:[...]$3 = SomeStruct { x: 11, y: 24.5 }
-// lldbr-check:(borrowed_struct::SomeStruct) *ref_to_unnamed = SomeStruct { x: 11, y: 24.5 }
+// lldbg-check:[...]$3 = { x = 11 y = 24.5 }
+// lldbr-check:(borrowed_struct::SomeStruct) *ref_to_unnamed = (x = 11, y = 24.5)
 
 // lldb-command:print *unique_val_ref
-// lldbg-check:[...]$4 = SomeStruct { x: 13, y: 26.5 }
-// lldbr-check:(borrowed_struct::SomeStruct) *unique_val_ref = SomeStruct { x: 13, y: 26.5 }
+// lldbg-check:[...]$4 = { x = 13 y = 26.5 }
+// lldbr-check:(borrowed_struct::SomeStruct) *unique_val_ref = (x = 13, y = 26.5)
 
 // lldb-command:print *unique_val_interior_ref_1
 // lldbg-check:[...]$5 = 13
diff --git a/src/test/debuginfo/borrowed-tuple.rs b/src/test/debuginfo/borrowed-tuple.rs
index fc92b629ef3..be4895ef536 100644
--- a/src/test/debuginfo/borrowed-tuple.rs
+++ b/src/test/debuginfo/borrowed-tuple.rs
@@ -24,16 +24,16 @@
 // lldb-command:run
 
 // lldb-command:print *stack_val_ref
-// lldbg-check:[...]$0 = (-14, -19)
-// lldbr-check:((i16, f32)) *stack_val_ref = { = -14 = -19 }
+// lldbg-check:[...]$0 = { 0 = -14 1 = -19 }
+// lldbr-check:((i16, f32)) *stack_val_ref = { 0 = -14 1 = -19 }
 
 // lldb-command:print *ref_to_unnamed
-// lldbg-check:[...]$1 = (-15, -20)
-// lldbr-check:((i16, f32)) *ref_to_unnamed = { = -15 = -20 }
+// lldbg-check:[...]$1 = { 0 = -15 1 = -20 }
+// lldbr-check:((i16, f32)) *ref_to_unnamed = { 0 = -15 1 = -20 }
 
 // lldb-command:print *unique_val_ref
-// lldbg-check:[...]$2 = (-17, -22)
-// lldbr-check:((i16, f32)) *unique_val_ref = { = -17 = -22 }
+// lldbg-check:[...]$2 = { 0 = -17 1 = -22 }
+// lldbr-check:((i16, f32)) *unique_val_ref = { 0 = -17 1 = -22 }
 
 
 #![allow(unused_variables)]
diff --git a/src/test/debuginfo/box.rs b/src/test/debuginfo/box.rs
index a539d78d3c9..e443b67ebfb 100644
--- a/src/test/debuginfo/box.rs
+++ b/src/test/debuginfo/box.rs
@@ -20,8 +20,8 @@
 // lldbg-check:[...]$0 = 1
 // lldbr-check:(i32) *a = 1
 // lldb-command:print *b
-// lldbg-check:[...]$1 = (2, 3.5)
-// lldbr-check:((i32, f64)) *b = { = 2 = 3.5 }
+// lldbg-check:[...]$1 = { 0 = 2 1 = 3.5 }
+// lldbr-check:((i32, f64)) *b = { 0 = 2 1 = 3.5 }
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
diff --git a/src/test/debuginfo/boxed-struct.rs b/src/test/debuginfo/boxed-struct.rs
index 8709fb68170..04bdf728901 100644
--- a/src/test/debuginfo/boxed-struct.rs
+++ b/src/test/debuginfo/boxed-struct.rs
@@ -22,12 +22,12 @@
 // lldb-command:run
 
 // lldb-command:print *boxed_with_padding
-// lldbg-check:[...]$0 = StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }
-// lldbr-check:(boxed_struct::StructWithSomePadding) *boxed_with_padding = StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 }
+// lldbg-check:[...]$0 = { x = 99 y = 999 z = 9999 w = 99999 }
+// lldbr-check:(boxed_struct::StructWithSomePadding) *boxed_with_padding = { x = 99 y = 999 z = 9999 w = 99999 }
 
 // lldb-command:print *boxed_with_dtor
-// lldbg-check:[...]$1 = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }
-// lldbr-check:(boxed_struct::StructWithDestructor) *boxed_with_dtor = StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 }
+// lldbg-check:[...]$1 = { x = 77 y = 777 z = 7777 w = 77777 }
+// lldbr-check:(boxed_struct::StructWithDestructor) *boxed_with_dtor = { x = 77 y = 777 z = 7777 w = 77777 }
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
diff --git a/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs b/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs
index deba18cc44a..e60cfc9242a 100644
--- a/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs
+++ b/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs
@@ -31,13 +31,13 @@
 // lldb-command:continue
 
 // lldb-command:print self
-// lldbg-check:[...]$1 = Struct { x: 2222, y: 3333 }
-// lldbr-check:(by_value_self_argument_in_trait_impl::Struct) self = Struct { x: 2222, y: 3333 }
+// lldbg-check:[...]$1 = { x = 2222 y = 3333 }
+// lldbr-check:(by_value_self_argument_in_trait_impl::Struct) self = { x = 2222 y = 3333 }
 // lldb-command:continue
 
 // lldb-command:print self
-// lldbg-check:[...]$2 = (4444.5, 5555, 6666, 7777.5)
-// lldbr-check:((f64, isize, isize, f64)) self = { = 4444.5 = 5555 = 6666 = 7777.5 }
+// lldbg-check:[...] $2 = { 0 = 4444.5 1 = 5555 2 = 6666 3 = 7777.5 }
+// lldbr-check:((f64, isize, isize, f64)) self = { 0 = 4444.5 1 = 5555 2 = 6666 3 = 7777.5 }
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
diff --git a/src/test/debuginfo/c-style-enum-in-composite.rs b/src/test/debuginfo/c-style-enum-in-composite.rs
index 8a356f62d3c..f859fe8d1ce 100644
--- a/src/test/debuginfo/c-style-enum-in-composite.rs
+++ b/src/test/debuginfo/c-style-enum-in-composite.rs
@@ -40,31 +40,32 @@
 // lldb-command:run
 
 // lldb-command:print tuple_interior_padding
-// lldbg-check:[...]$0 = (0, OneHundred)
-// lldbr-check:((i16, c_style_enum_in_composite::AnEnum)) tuple_interior_padding = { = 0 = c_style_enum_in_composite::AnEnum::OneHundred }
+// lldbg-check:[...]$0 = { 0 = 0 1 = OneHundred }
+// lldbr-check:((i16, c_style_enum_in_composite::AnEnum)) tuple_interior_padding = { 0 = 0 1 = OneHundred }
 
 // lldb-command:print tuple_padding_at_end
-// lldbg-check:[...]$1 = ((1, OneThousand), 2)
-// lldbr-check:(((u64, c_style_enum_in_composite::AnEnum), u64)) tuple_padding_at_end = { = { = 1 = c_style_enum_in_composite::AnEnum::OneThousand } = 2 }
+// lldbg-check:[...]$1 = { 0 = { 0 = 1 1 = OneThousand } 1 = 2 }
+// lldbr-check:(((u64, c_style_enum_in_composite::AnEnum), u64)) tuple_padding_at_end = { 0 = { 0 = 1 1 = OneThousand } 1 = 2 }
+
 // lldb-command:print tuple_different_enums
-// lldbg-check:[...]$2 = (OneThousand, MountainView, OneMillion, Vienna)
-// lldbr-check:((c_style_enum_in_composite::AnEnum, c_style_enum_in_composite::AnotherEnum, c_style_enum_in_composite::AnEnum, c_style_enum_in_composite::AnotherEnum)) tuple_different_enums = { = c_style_enum_in_composite::AnEnum::OneThousand = c_style_enum_in_composite::AnotherEnum::MountainView = c_style_enum_in_composite::AnEnum::OneMillion = c_style_enum_in_composite::AnotherEnum::Vienna }
+// lldbg-check:[...]$2 = { 0 = OneThousand 1 = MountainView 2 = OneMillion 3 = Vienna }
+// lldbr-check:((c_style_enum_in_composite::AnEnum, c_style_enum_in_composite::AnotherEnum, c_style_enum_in_composite::AnEnum, c_style_enum_in_composite::AnotherEnum)) tuple_different_enums = { 0 = c_style_enum_in_composite::AnEnum::OneThousand 1 = c_style_enum_in_composite::AnotherEnum::MountainView 2 = c_style_enum_in_composite::AnEnum::OneMillion 3 = c_style_enum_in_composite::AnotherEnum::Vienna }
 
 // lldb-command:print padded_struct
-// lldbg-check:[...]$3 = PaddedStruct { a: 3, b: OneMillion, c: 4, d: Toronto, e: 5 }
-// lldbr-check:(c_style_enum_in_composite::PaddedStruct) padded_struct = PaddedStruct { a: 3, b: c_style_enum_in_composite::AnEnum::OneMillion, c: 4, d: c_style_enum_in_composite::AnotherEnum::Toronto, e: 5 }
+// lldbg-check:[...]$3 = { a = 3 b = OneMillion c = 4 d = Toronto e = 5 }
+// lldbr-check:(c_style_enum_in_composite::PaddedStruct) padded_struct = { a = 3 b = c_style_enum_in_composite::AnEnum::OneMillion c = 4 d = Toronto e = 5 }
 
 // lldb-command:print packed_struct
-// lldbg-check:[...]$4 = PackedStruct { a: 6, b: OneHundred, c: 7, d: Vienna, e: 8 }
-// lldbr-check:(c_style_enum_in_composite::PackedStruct) packed_struct = PackedStruct { a: 6, b: c_style_enum_in_composite::AnEnum::OneHundred, c: 7, d: c_style_enum_in_composite::AnotherEnum::Vienna, e: 8 }
+// lldbg-check:[...]$4 = { a = 6 b = OneHundred c = 7 d = Vienna e = 8 }
+// lldbr-check:(c_style_enum_in_composite::PackedStruct) packed_struct = { a = 6 b = c_style_enum_in_composite::AnEnum::OneHundred c = 7 d = Vienna e = 8 }
 
 // lldb-command:print non_padded_struct
-// lldbg-check:[...]$5 = NonPaddedStruct { a: OneMillion, b: MountainView, c: OneThousand, d: Toronto }
-// lldbr-check:(c_style_enum_in_composite::NonPaddedStruct) non_padded_struct = NonPaddedStruct { a: c_style_enum_in_composite::AnEnum::OneMillion, b: c_style_enum_in_composite::AnotherEnum::MountainView, c: c_style_enum_in_composite::AnEnum::OneThousand, d: c_style_enum_in_composite::AnotherEnum::Toronto }
+// lldbg-check:[...]$5 = { a = OneMillion b = MountainView c = OneThousand d = Toronto }
+// lldbr-check:(c_style_enum_in_composite::NonPaddedStruct) non_padded_struct = { a = c_style_enum_in_composite::AnEnum::OneMillion, b = c_style_enum_in_composite::AnotherEnum::MountainView, c = c_style_enum_in_composite::AnEnum::OneThousand, d = c_style_enum_in_composite::AnotherEnum::Toronto }
 
 // lldb-command:print struct_with_drop
-// lldbg-check:[...]$6 = (StructWithDrop { a: OneHundred, b: Vienna }, 9)
-// lldbr-check:((c_style_enum_in_composite::StructWithDrop, i64)) struct_with_drop = { = StructWithDrop { a: c_style_enum_in_composite::AnEnum::OneHundred, b: c_style_enum_in_composite::AnotherEnum::Vienna } = 9 }
+// lldbg-check:[...]$6 = { 0 = { a = OneHundred b = Vienna } 1 = 9 }
+// lldbr-check:((c_style_enum_in_composite::StructWithDrop, i64)) struct_with_drop = { 0 = { a = c_style_enum_in_composite::AnEnum::OneHundred b = c_style_enum_in_composite::AnotherEnum::Vienna } 1 = 9 }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
diff --git a/src/test/debuginfo/cross-crate-spans.rs b/src/test/debuginfo/cross-crate-spans.rs
index 96ddfd2a39e..7c58e1db23f 100644
--- a/src/test/debuginfo/cross-crate-spans.rs
+++ b/src/test/debuginfo/cross-crate-spans.rs
@@ -44,8 +44,8 @@ extern crate cross_crate_spans;
 // lldb-command:run
 
 // lldb-command:print result
-// lldbg-check:[...]$0 = (17, 17)
-// lldbr-check:((u32, u32)) result = { = 17 = 17 }
+// lldbg-check:[...]$0 = { 0 = 17 1 = 17 }
+// lldbr-check:((u32, u32)) result = { 0 = 17 1 = 17 }
 // lldb-command:print a_variable
 // lldbg-check:[...]$1 = 123456789
 // lldbr-check:(u32) a_variable = 123456789
@@ -55,8 +55,8 @@ extern crate cross_crate_spans;
 // lldb-command:continue
 
 // lldb-command:print result
-// lldbg-check:[...]$3 = (1212, 1212)
-// lldbr-check:((i16, i16)) result = { = 1212 = 1212 }
+// lldbg-check:[...]$3 = { 0 = 1212 1 = 1212 }
+// lldbr-check:((i16, i16)) result = { 0 = 1212 1 = 1212 }
 // lldb-command:print a_variable
 // lldbg-check:[...]$4 = 123456789
 // lldbr-check:(u32) a_variable = 123456789
diff --git a/src/test/debuginfo/destructured-fn-argument.rs b/src/test/debuginfo/destructured-fn-argument.rs
index 64133dc6860..a776f519071 100644
--- a/src/test/debuginfo/destructured-fn-argument.rs
+++ b/src/test/debuginfo/destructured-fn-argument.rs
@@ -186,16 +186,16 @@
 // lldbg-check:[...]$5 = 5
 // lldbr-check:(isize) a = 5
 // lldb-command:print b
-// lldbg-check:[...]$6 = (6, 7)
-// lldbr-check:((u32, u32)) b = { = 6 = 7 }
+// lldbg-check:[...]$6 = { 0 = 6 1 = 7 }
+// lldbr-check:((u32, u32)) b = { 0 = 6 1 = 7 }
 // lldb-command:continue
 
 // lldb-command:print h
 // lldbg-check:[...]$7 = 8
 // lldbr-check:(i16) h = 8
 // lldb-command:print i
-// lldbg-check:[...]$8 = Struct { a: 9, b: 10 }
-// lldbr-check:(destructured_fn_argument::Struct) i = Struct { a: 9, b: 10 }
+// lldbg-check:[...]$8 = { a = 9 b = 10 }
+// lldbr-check:(destructured_fn_argument::Struct) i = { a = 9 b = 10 }
 // lldb-command:print j
 // lldbg-check:[...]$9 = 11
 // lldbr-check:(i16) j = 11
@@ -229,8 +229,8 @@
 // lldbg-check:[...]$16 = 20
 // lldbr-check:(i32) q = 20
 // lldb-command:print r
-// lldbg-check:[...]$17 = Struct { a: 21, b: 22 }
-// lldbr-check:(destructured_fn_argument::Struct) r = Struct { a: 21, b: 22 }
+// lldbg-check:[...]$17 = { a = 21 b = 22 }
+// lldbr-check:(destructured_fn_argument::Struct) r = { a = 21, b = 22 }
 // lldb-command:continue
 
 // lldb-command:print s
@@ -271,13 +271,13 @@
 // lldb-command:continue
 
 // lldb-command:print aa
-// lldbg-check:[...]$29 = (34, 35)
-// lldbr-check:((isize, isize)) aa = { = 34 = 35 }
+// lldbg-check:[...]$29 = { 0 = 34 1 = 35 }
+// lldbr-check:((isize, isize)) aa = { 0 = 34 1 = 35 }
 // lldb-command:continue
 
 // lldb-command:print bb
-// lldbg-check:[...]$30 = (36, 37)
-// lldbr-check:((isize, isize)) bb = { = 36 = 37 }
+// lldbg-check:[...]$30 = { 0 = 36 1 = 37 }
+// lldbr-check:((isize, isize)) bb = { 0 = 36 1 = 37 }
 // lldb-command:continue
 
 // lldb-command:print cc
@@ -286,21 +286,21 @@
 // lldb-command:continue
 
 // lldb-command:print dd
-// lldbg-check:[...]$32 = (40, 41, 42)
-// lldbr-check:((isize, isize, isize)) dd = { = 40 = 41 = 42 }
+// lldbg-check:[...]$32 = { 0 = 40 1 = 41 2 = 42 }
+// lldbr-check:((isize, isize, isize)) dd = { 0 = 40 1 = 41 2 = 42 }
 // lldb-command:continue
 
 // lldb-command:print *ee
-// lldbg-check:[...]$33 = (43, 44, 45)
-// lldbr-check:((isize, isize, isize)) *ee = { = 43 = 44 = 45 }
+// lldbg-check:[...]$33 = { 0 = 43 1 = 44 2 = 45 }
+// lldbr-check:((isize, isize, isize)) *ee = { 0 = 43 1 = 44 2 = 45 }
 // lldb-command:continue
 
 // lldb-command:print *ff
 // lldbg-check:[...]$34 = 46
 // lldbr-check:(isize) *ff = 46
 // lldb-command:print gg
-// lldbg-check:[...]$35 = (47, 48)
-// lldbr-check:((isize, isize)) gg = { = 47 = 48 }
+// lldbg-check:[...]$35 = { 0 = 47 1 = 48 }
+// lldbr-check:((isize, isize)) gg = { 0 = 47 1 = 48 }
 // lldb-command:continue
 
 // lldb-command:print *hh
diff --git a/src/test/debuginfo/destructured-for-loop-variable.rs b/src/test/debuginfo/destructured-for-loop-variable.rs
index dbb98322317..868f2285f35 100644
--- a/src/test/debuginfo/destructured-for-loop-variable.rs
+++ b/src/test/debuginfo/destructured-for-loop-variable.rs
@@ -164,13 +164,13 @@
 // lldb-command:continue
 
 // lldb-command:print simple_struct_ident
-// lldbg-check:[...]$22 = Struct { x: 3537, y: 35437.5, z: true }
-// lldbr-check:(destructured_for_loop_variable::Struct) simple_struct_ident = Struct { x: 3537, y: 35437.5, z: true }
+// lldbg-check:[...]$22 = { x = 3537 y = 35437.5 z = true }
+// lldbr-check:(destructured_for_loop_variable::Struct) simple_struct_ident = { x = 3537 y = 35437.5 z = true }
 // lldb-command:continue
 
 // lldb-command:print simple_tuple_ident
-// lldbg-check:[...]$23 = (34903493, 232323)
-// lldbr-check:((u32, i64)) simple_tuple_ident = { = 34903493 = 232323 }
+// lldbg-check:[...]$23 = { 0 = 34903493 1 = 232323 }
+// lldbr-check:((u32, i64)) simple_tuple_ident = { 0 = 34903493 1 = 232323 }
 // lldb-command:continue
 
 #![allow(unused_variables)]
diff --git a/src/test/debuginfo/destructured-local.rs b/src/test/debuginfo/destructured-local.rs
index 78b6b2764e0..712168b5baa 100644
--- a/src/test/debuginfo/destructured-local.rs
+++ b/src/test/debuginfo/destructured-local.rs
@@ -150,15 +150,15 @@
 // lldbg-check:[...]$5 = 5
 // lldbr-check:(isize) f = 5
 // lldb-command:print g
-// lldbg-check:[...]$6 = (6, 7)
-// lldbr-check:((u32, u32)) g = { = 6 = 7 }
+// lldbg-check:[...]$6 = { 0 = 6 1 = 7 }
+// lldbr-check:((u32, u32)) g = { 0 = 6 1 = 7 }
 
 // lldb-command:print h
 // lldbg-check:[...]$7 = 8
 // lldbr-check:(i16) h = 8
 // lldb-command:print i
-// lldbg-check:[...]$8 = Struct { a: 9, b: 10 }
-// lldbr-check:(destructured_local::Struct) i = Struct { a: 9, b: 10 }
+// lldbg-check:[...]$8 = { a = 9 b = 10 }
+// lldbr-check:(destructured_local::Struct) i = { a = 9 b = 10 }
 // lldb-command:print j
 // lldbg-check:[...]$9 = 11
 // lldbr-check:(i16) j = 11
@@ -188,8 +188,8 @@
 // lldbg-check:[...]$16 = 20
 // lldbr-check:(i32) q = 20
 // lldb-command:print r
-// lldbg-check:[...]$17 = Struct { a: 21, b: 22 }
-// lldbr-check:(destructured_local::Struct) r = Struct { a: 21, b: 22 }
+// lldbg-check:[...]$17 = { a = 21 b = 22 }
+// lldbr-check:(destructured_local::Struct) r = { a = 21 b = 22 }
 
 // lldb-command:print s
 // lldbg-check:[...]$18 = 24
@@ -227,32 +227,32 @@
 // lldbr-check:(i32) ue = 33
 
 // lldb-command:print aa
-// lldbg-check:[...]$29 = (34, 35)
-// lldbr-check:((i32, i32)) aa = { = 34 = 35 }
+// lldbg-check:[...]$29 = { 0 = 34 1 = 35 }
+// lldbr-check:((i32, i32)) aa = { 0 = 34 1 = 35 }
 
 // lldb-command:print bb
-// lldbg-check:[...]$30 = (36, 37)
-// lldbr-check:((i32, i32)) bb = { = 36 = 37 }
+// lldbg-check:[...]$30 = { 0 = 36 1 = 37 }
+// lldbr-check:((i32, i32)) bb = { 0 = 36 1 = 37 }
 
 // lldb-command:print cc
 // lldbg-check:[...]$31 = 38
 // lldbr-check:(i32) cc = 38
 
 // lldb-command:print dd
-// lldbg-check:[...]$32 = (40, 41, 42)
-// lldbr-check:((i32, i32, i32)) dd = { = 40 = 41 = 42 }
+// lldbg-check:[...]$32 = { 0 = 40 1 = 41 2 = 42 }
+// lldbr-check:((i32, i32, i32)) dd = { 0 = 40 1 = 41 2 = 42}
 
 // lldb-command:print *ee
-// lldbg-check:[...]$33 = (43, 44, 45)
-// lldbr-check:((i32, i32, i32)) *ee = { = 43 = 44 = 45 }
+// lldbg-check:[...]$33 = { 0 = 43 1 = 44 2 = 45 }
+// lldbr-check:((i32, i32, i32)) *ee = { 0 = 43 1 = 44 2 = 45}
 
 // lldb-command:print *ff
 // lldbg-check:[...]$34 = 46
 // lldbr-check:(i32) *ff = 46
 
 // lldb-command:print gg
-// lldbg-check:[...]$35 = (47, 48)
-// lldbr-check:((i32, i32)) gg = { = 47 = 48 }
+// lldbg-check:[...]$35 = { 0 = 47 1 = 48 }
+// lldbr-check:((i32, i32)) gg = { 0 = 47 1 = 48 }
 
 // lldb-command:print *hh
 // lldbg-check:[...]$36 = 50
diff --git a/src/test/debuginfo/empty-string.rs b/src/test/debuginfo/empty-string.rs
index bc4fac3183c..66eb8bae26b 100644
--- a/src/test/debuginfo/empty-string.rs
+++ b/src/test/debuginfo/empty-string.rs
@@ -1,7 +1,7 @@
 // ignore-windows failing on win32 bot
 // ignore-android: FIXME(#10381)
 // compile-flags:-g
-// min-gdb-version: 7.7
+// min-gdb-version: 8.1
 // ignore-gdb-version: 7.11.90 - 8.0.9
 // min-lldb-version: 310
 
@@ -20,10 +20,10 @@
 // lldb-command: run
 
 // lldb-command: fr v empty_string
-// lldb-check:[...]empty_string = ""
+// lldb-check:[...]empty_string = "" { vec = size=0 }
 
 // lldb-command: fr v empty_str
-// lldb-check:[...]empty_str = ""
+// lldb-check:[...]empty_str = "" { data_ptr = [...] length = 0 }
 
 fn main() {
     let empty_string = String::new();
diff --git a/src/test/debuginfo/enum-thinlto.rs b/src/test/debuginfo/enum-thinlto.rs
index 9359e55dcee..b10e04a4a9e 100644
--- a/src/test/debuginfo/enum-thinlto.rs
+++ b/src/test/debuginfo/enum-thinlto.rs
@@ -15,7 +15,8 @@
 // lldb-command:run
 
 // lldb-command:print *abc
-// lldbg-check:(enum_thinlto::ABC) $0 = ABC { }
+// lldbg-check:(enum_thinlto::ABC) $0 =
+// lldbr-check:(enum_thinlto::ABC) *abc = (x = 0, y = 8970181431921507452)
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
diff --git a/src/test/debuginfo/evec-in-struct.rs b/src/test/debuginfo/evec-in-struct.rs
index cf86374ab31..2033966adad 100644
--- a/src/test/debuginfo/evec-in-struct.rs
+++ b/src/test/debuginfo/evec-in-struct.rs
@@ -33,23 +33,23 @@
 // lldb-command:run
 
 // lldb-command:print no_padding1
-// lldbg-check:[...]$0 = NoPadding1 { x: [0, 1, 2], y: -3, z: [4.5, 5.5] }
-// lldbr-check:(evec_in_struct::NoPadding1) no_padding1 = NoPadding1 { x: [0, 1, 2], y: -3, z: [4.5, 5.5] }
+// lldbg-check:[...]$0 = { x = { [0] = 0 [1] = 1 [2] = 2 } y = -3 z = { [0] = 4.5 [1] = 5.5 } }
+// lldbr-check:(evec_in_struct::NoPadding1) no_padding1 = { x = { [0] = 0 [1] = 1 [2] = 2 } y = -3 z = { [0] = 4.5 [1] = 5.5 } }
 // lldb-command:print no_padding2
-// lldbg-check:[...]$1 = NoPadding2 { x: [6, 7, 8], y: [[9, 10], [11, 12]] }
-// lldbr-check:(evec_in_struct::NoPadding2) no_padding2 = NoPadding2 { x: [6, 7, 8], y: [[9, 10], [11, 12]] }
+// lldbg-check:[...]$1 = { x = { [0] = 6 [1] = 7 [2] = 8 } y = { [0] = { [0] = 9 [1] = 10 } [1] = { [0] = 11 [1] = 12 } } }
+// lldbr-check:(evec_in_struct::NoPadding2) no_padding2 = { x = { [0] = 6 [1] = 7 [2] = 8 } y = { [0] = { [0] = 9 [1] = 10 } [1] = { [0] = 11 [1] = 12 } } }
 
 // lldb-command:print struct_internal_padding
-// lldbg-check:[...]$2 = StructInternalPadding { x: [13, 14], y: [15, 16] }
-// lldbr-check:(evec_in_struct::StructInternalPadding) struct_internal_padding = StructInternalPadding { x: [13, 14], y: [15, 16] }
+// lldbg-check:[...]$2 = { x = { [0] = 13 [1] = 14 } y = { [0] = 15 [1] = 16 } }
+// lldbr-check:(evec_in_struct::StructInternalPadding) struct_internal_padding = { x = { [0] = 13 [1] = 14 } y = { [0] = 15 [1] = 16 } }
 
 // lldb-command:print single_vec
-// lldbg-check:[...]$3 = SingleVec { x: [17, 18, 19, 20, 21] }
-// lldbr-check:(evec_in_struct::SingleVec) single_vec = SingleVec { x: [17, 18, 19, 20, 21] }
+// lldbg-check:[...]$3 = { x = { [0] = 17 [1] = 18 [2] = 19 [3] = 20 [4] = 21 } }
+// lldbr-check:(evec_in_struct::SingleVec) single_vec = { x = { [0] = 17 [1] = 18 [2] = 19 [3] = 20 [4] = 21 } }
 
 // lldb-command:print struct_padded_at_end
-// lldbg-check:[...]$4 = StructPaddedAtEnd { x: [22, 23], y: [24, 25] }
-// lldbr-check:(evec_in_struct::StructPaddedAtEnd) struct_padded_at_end = StructPaddedAtEnd { x: [22, 23], y: [24, 25] }
+// lldbg-check:[...]$4 = { x = { [0] = 22 [1] = 23 } y = { [0] = 24 [1] = 25 } }
+// lldbr-check:(evec_in_struct::StructPaddedAtEnd) struct_padded_at_end = { x = { [0] = 22 [1] = 23 } y = { [0] = 24 [1] = 25 } }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
diff --git a/src/test/debuginfo/function-prologue-stepping-regular.rs b/src/test/debuginfo/function-prologue-stepping-regular.rs
index 46901030f65..699ff84ee0a 100644
--- a/src/test/debuginfo/function-prologue-stepping-regular.rs
+++ b/src/test/debuginfo/function-prologue-stepping-regular.rs
@@ -30,9 +30,9 @@
 
 // NON IMMEDIATE ARGS
 // lldb-command:print a
-// lldb-check:[...]$3 = BigStruct { a: 3, b: 4, c: 5, d: 6, e: 7, f: 8, g: 9, h: 10 }
+// lldb-check:[...]$3 = { a = 3, b = 4, c = 5, d = 6, e = 7, f = 8, g = 9, h = 10 }
 // lldb-command:print b
-// lldb-check:[...]$4 = BigStruct { a: 11, b: 12, c: 13, d: 14, e: 15, f: 16, g: 17, h: 18 }
+// lldb-check:[...]$4 = { a = 11, b = 12, c = 13, d = 14, e = 15, f = 16, g = 17, h = 18 }
 // lldb-command:continue
 
 // BINDING
diff --git a/src/test/debuginfo/gdb-pretty-struct-and-enums.rs b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs
index 7d2b4c95a05..2a8359de522 100644
--- a/src/test/debuginfo/gdb-pretty-struct-and-enums.rs
+++ b/src/test/debuginfo/gdb-pretty-struct-and-enums.rs
@@ -1,14 +1,14 @@
 // ignore-tidy-linelength
 // ignore-lldb
 // ignore-android: FIXME(#10381)
-// min-gdb-version: 7.11
+// min-gdb-version: 8.1
 
 // compile-flags:-g
 
 // gdb-command: run
 
 // gdb-command: print regular_struct
-// gdbg-check:$1 = RegularStruct = {the_first_field = 101, the_second_field = 102.5, the_third_field = false}
+// gdbg-check:$1 = {the_first_field = 101, the_second_field = 102.5, the_third_field = false}
 // gdbr-check:$1 = gdb_pretty_struct_and_enums::RegularStruct {the_first_field: 101, the_second_field: 102.5, the_third_field: false}
 
 // gdb-command: print empty_struct
diff --git a/src/test/debuginfo/generator-objects.rs b/src/test/debuginfo/generator-objects.rs
index 382b0231d3b..0023f69d27f 100644
--- a/src/test/debuginfo/generator-objects.rs
+++ b/src/test/debuginfo/generator-objects.rs
@@ -24,16 +24,16 @@
 
 // lldb-command:run
 // lldb-command:print b
-// lldbg-check:(generator_objects::main::generator-0) $0 = generator-0(&0x[...])
+// lldbg-check:(generator_objects::main::generator-0) $0 = { 0 = 0x[...] }
 // lldb-command:continue
 // lldb-command:print b
-// lldbg-check:(generator_objects::main::generator-0) $1 = generator-0(&0x[...])
+// lldbg-check:(generator_objects::main::generator-0) $1 = { 0 = 0x[...] }
 // lldb-command:continue
 // lldb-command:print b
-// lldbg-check:(generator_objects::main::generator-0) $2 = generator-0(&0x[...])
+// lldbg-check:(generator_objects::main::generator-0) $2 = { 0 = 0x[...] }
 // lldb-command:continue
 // lldb-command:print b
-// lldbg-check:(generator_objects::main::generator-0) $3 = generator-0(&0x[...])
+// lldbg-check:(generator_objects::main::generator-0) $3 = { 0 = 0x[...] }
 
 #![feature(omit_gdb_pretty_printer_section, generators, generator_trait)]
 #![omit_gdb_pretty_printer_section]
diff --git a/src/test/debuginfo/generic-function.rs b/src/test/debuginfo/generic-function.rs
index f5e34c39119..e8f3940c836 100644
--- a/src/test/debuginfo/generic-function.rs
+++ b/src/test/debuginfo/generic-function.rs
@@ -49,8 +49,8 @@
 // lldbg-check:[...]$4 = 5
 // lldbr-check:(i32) *t0 = 5
 // lldb-command:print *t1
-// lldbg-check:[...]$5 = Struct { a: 6, b: 7.5 }
-// lldbr-check:(generic_function::Struct) *t1 = Struct { a: 6, b: 7.5 }
+// lldbg-check:[...]$5 = { a = 6 b = 7.5 }
+// lldbr-check:(generic_function::Struct) *t1 = { a = 6 b = 7.5 }
 // lldb-command:continue
 
 #![feature(omit_gdb_pretty_printer_section)]
diff --git a/src/test/debuginfo/generic-method-on-generic-struct.rs b/src/test/debuginfo/generic-method-on-generic-struct.rs
index 7d151cfaa4a..f7767292222 100644
--- a/src/test/debuginfo/generic-method-on-generic-struct.rs
+++ b/src/test/debuginfo/generic-method-on-generic-struct.rs
@@ -67,8 +67,8 @@
 
 // STACK BY REF
 // lldb-command:print *self
-// lldbg-check:[...]$0 = Struct<(u32, i32)> { x: (8888, -8888) }
-// lldbr-check:(generic_method_on_generic_struct::Struct<(u32, i32)>) *self = { x = { = 8888 = -8888 } }
+// lldbg-check:[...]$0 = { x = { 0 = 8888, 1 = -8888 } }
+// lldbr-check:(generic_method_on_generic_struct::Struct<(u32, i32)>) *self = { x = { 0 = 8888 1 = -8888 } }
 // lldb-command:print arg1
 // lldbg-check:[...]$1 = -1
 // lldbr-check:(isize) arg1 = -1
@@ -79,8 +79,8 @@
 
 // STACK BY VAL
 // lldb-command:print self
-// lldbg-check:[...]$3 = Struct<(u32, i32)> { x: (8888, -8888) }
-// lldbr-check:(generic_method_on_generic_struct::Struct<(u32, i32)>) self = { x = { = 8888 = -8888 } }
+// lldbg-check:[...]$3 = { x = { 0 = 8888, 1 = -8888 } }
+// lldbr-check:(generic_method_on_generic_struct::Struct<(u32, i32)>) self = { x = { 0 = 8888, 1 = -8888 } }
 // lldb-command:print arg1
 // lldbg-check:[...]$4 = -3
 // lldbr-check:(isize) arg1 = -3
@@ -91,8 +91,8 @@
 
 // OWNED BY REF
 // lldb-command:print *self
-// lldbg-check:[...]$6 = Struct<f64> { x: 1234.5 }
-// lldbr-check:(generic_method_on_generic_struct::Struct<f64>) *self = Struct<f64> { x: 1234.5 }
+// lldbg-check:[...]$6 = { x = 1234.5 }
+// lldbr-check:(generic_method_on_generic_struct::Struct<f64>) *self = { x = 1234.5 }
 // lldb-command:print arg1
 // lldbg-check:[...]$7 = -5
 // lldbr-check:(isize) arg1 = -5
@@ -103,8 +103,8 @@
 
 // OWNED BY VAL
 // lldb-command:print self
-// lldbg-check:[...]$9 = Struct<f64> { x: 1234.5 }
-// lldbr-check:(generic_method_on_generic_struct::Struct<f64>) self = Struct<f64> { x: 1234.5 }
+// lldbg-check:[...]$9 = { x = 1234.5 }
+// lldbr-check:(generic_method_on_generic_struct::Struct<f64>) self = { x = 1234.5 }
 // lldb-command:print arg1
 // lldbg-check:[...]$10 = -7
 // lldbr-check:(isize) arg1 = -7
@@ -115,8 +115,8 @@
 
 // OWNED MOVED
 // lldb-command:print *self
-// lldbg-check:[...]$12 = Struct<f64> { x: 1234.5 }
-// lldbr-check:(generic_method_on_generic_struct::Struct<f64>) *self = Struct<f64> { x: 1234.5 }
+// lldbg-check:[...]$12 = { x = 1234.5 }
+// lldbr-check:(generic_method_on_generic_struct::Struct<f64>) *self = { x = 1234.5 }
 // lldb-command:print arg1
 // lldbg-check:[...]$13 = -9
 // lldbr-check:(isize) arg1 = -9
diff --git a/src/test/debuginfo/issue-22656.rs b/src/test/debuginfo/issue-22656.rs
index e4634d96a6f..f286566277e 100644
--- a/src/test/debuginfo/issue-22656.rs
+++ b/src/test/debuginfo/issue-22656.rs
@@ -4,7 +4,6 @@
 
 // min-lldb-version: 310
 // ignore-gdb
-// ignore-tidy-linelength
 
 // compile-flags:-g
 
@@ -12,11 +11,11 @@
 // lldb-command:run
 
 // lldb-command:print v
-// lldbg-check:[...]$0 = vec![1, 2, 3]
-// lldbr-check:(alloc::vec::Vec<i32>) v = vec![1, 2, 3]
+// lldbg-check:[...]$0 = size=3 { [0] = 1 [1] = 2 [2] = 3 }
+// lldbr-check:(alloc::vec::Vec<i32>) v = size=3 { [0] = 1 [1] = 2 [2] = 3 }
 // lldb-command:print zs
-// lldbg-check:[...]$1 = StructWithZeroSizedField { x: ZeroSizedStruct[...], y: 123, z: ZeroSizedStruct[...], w: 456 }
-// lldbr-check:(issue_22656::StructWithZeroSizedField) zs = StructWithZeroSizedField { x: ZeroSizedStruct { }, y: 123, z: ZeroSizedStruct { }, w: 456 }
+// lldbg-check:[...]$1 = { x = y = 123 z = w = 456 }
+// lldbr-check:(issue_22656::StructWithZeroSizedField) zs = { x = y = 123 z = w = 456 }
 // lldbr-command:continue
 
 #![allow(unused_variables)]
diff --git a/src/test/debuginfo/issue-57822.rs b/src/test/debuginfo/issue-57822.rs
index e9cfa3f7d69..c2cc6f9d24c 100644
--- a/src/test/debuginfo/issue-57822.rs
+++ b/src/test/debuginfo/issue-57822.rs
@@ -22,10 +22,10 @@
 // lldb-command:run
 
 // lldb-command:print g
-// lldbg-check:(issue_57822::main::closure-1) $0 = closure-1(closure-0(1))
+// lldbg-check:(issue_57822::main::closure-1) $0 = { 0 = { 0 = 1 } }
 
 // lldb-command:print b
-// lldbg-check:(issue_57822::main::generator-3) $1 = generator-3(generator-2(2))
+// lldbg-check:(issue_57822::main::generator-3) $1 = { 0 = { 0 = 2 } }
 
 #![feature(omit_gdb_pretty_printer_section, generators, generator_trait)]
 #![omit_gdb_pretty_printer_section]
diff --git a/src/test/debuginfo/method-on-struct.rs b/src/test/debuginfo/method-on-struct.rs
index cf8ed13e814..c764cf68323 100644
--- a/src/test/debuginfo/method-on-struct.rs
+++ b/src/test/debuginfo/method-on-struct.rs
@@ -63,7 +63,7 @@
 
 // STACK BY REF
 // lldb-command:print *self
-// lldbg-check:[...]$0 = Struct { x: 100 }
+// lldbg-check:[...]$0 = { x = 100 }
 // lldbr-check:(method_on_struct::Struct) *self = Struct { x: 100 }
 // lldb-command:print arg1
 // lldbg-check:[...]$1 = -1
@@ -75,7 +75,7 @@
 
 // STACK BY VAL
 // lldb-command:print self
-// lldbg-check:[...]$3 = Struct { x: 100 }
+// lldbg-check:[...]$3 = { x = 100 }
 // lldbr-check:(method_on_struct::Struct) self = Struct { x: 100 }
 // lldb-command:print arg1
 // lldbg-check:[...]$4 = -3
@@ -87,7 +87,7 @@
 
 // OWNED BY REF
 // lldb-command:print *self
-// lldbg-check:[...]$6 = Struct { x: 200 }
+// lldbg-check:[...]$6 = { x = 200 }
 // lldbr-check:(method_on_struct::Struct) *self = Struct { x: 200 }
 // lldb-command:print arg1
 // lldbg-check:[...]$7 = -5
@@ -99,7 +99,7 @@
 
 // OWNED BY VAL
 // lldb-command:print self
-// lldbg-check:[...]$9 = Struct { x: 200 }
+// lldbg-check:[...]$9 = { x = 200 }
 // lldbr-check:(method_on_struct::Struct) self = Struct { x: 200 }
 // lldb-command:print arg1
 // lldbg-check:[...]$10 = -7
@@ -111,7 +111,7 @@
 
 // OWNED MOVED
 // lldb-command:print *self
-// lldbg-check:[...]$12 = Struct { x: 200 }
+// lldbg-check:[...]$12 = { x = 200 }
 // lldbr-check:(method_on_struct::Struct) *self = Struct { x: 200 }
 // lldb-command:print arg1
 // lldbg-check:[...]$13 = -9
diff --git a/src/test/debuginfo/method-on-trait.rs b/src/test/debuginfo/method-on-trait.rs
index 9b321a8fad2..6dcf2896777 100644
--- a/src/test/debuginfo/method-on-trait.rs
+++ b/src/test/debuginfo/method-on-trait.rs
@@ -63,8 +63,8 @@
 
 // STACK BY REF
 // lldb-command:print *self
-// lldbg-check:[...]$0 = Struct { x: 100 }
-// lldbr-check:(method_on_trait::Struct) *self = Struct { x: 100 }
+// lldbg-check:[...]$0 = { x = 100 }
+// lldbr-check:(method_on_trait::Struct) *self = { x = 100 }
 // lldb-command:print arg1
 // lldbg-check:[...]$1 = -1
 // lldbr-check:(isize) arg1 = -1
@@ -75,8 +75,8 @@
 
 // STACK BY VAL
 // lldb-command:print self
-// lldbg-check:[...]$3 = Struct { x: 100 }
-// lldbr-check:(method_on_trait::Struct) self = Struct { x: 100 }
+// lldbg-check:[...]$3 = { x = 100 }
+// lldbr-check:(method_on_trait::Struct) self = { x = 100 }
 // lldb-command:print arg1
 // lldbg-check:[...]$4 = -3
 // lldbr-check:(isize) arg1 = -3
@@ -87,8 +87,8 @@
 
 // OWNED BY REF
 // lldb-command:print *self
-// lldbg-check:[...]$6 = Struct { x: 200 }
-// lldbr-check:(method_on_trait::Struct) *self = Struct { x: 200 }
+// lldbg-check:[...]$6 = { x = 200 }
+// lldbr-check:(method_on_trait::Struct) *self = { x = 200 }
 // lldb-command:print arg1
 // lldbg-check:[...]$7 = -5
 // lldbr-check:(isize) arg1 = -5
@@ -99,8 +99,8 @@
 
 // OWNED BY VAL
 // lldb-command:print self
-// lldbg-check:[...]$9 = Struct { x: 200 }
-// lldbr-check:(method_on_trait::Struct) self = Struct { x: 200 }
+// lldbg-check:[...]$9 = { x = 200 }
+// lldbr-check:(method_on_trait::Struct) self = { x = 200 }
 // lldb-command:print arg1
 // lldbg-check:[...]$10 = -7
 // lldbr-check:(isize) arg1 = -7
@@ -111,8 +111,8 @@
 
 // OWNED MOVED
 // lldb-command:print *self
-// lldbg-check:[...]$12 = Struct { x: 200 }
-// lldbr-check:(method_on_trait::Struct) *self = Struct { x: 200 }
+// lldbg-check:[...]$12 = { x = 200 }
+// lldbr-check:(method_on_trait::Struct) *self = { x = 200 }
 // lldb-command:print arg1
 // lldbg-check:[...]$13 = -9
 // lldbr-check:(isize) arg1 = -9
diff --git a/src/test/debuginfo/method-on-tuple-struct.rs b/src/test/debuginfo/method-on-tuple-struct.rs
index dc32edd07a4..d06b606e973 100644
--- a/src/test/debuginfo/method-on-tuple-struct.rs
+++ b/src/test/debuginfo/method-on-tuple-struct.rs
@@ -63,8 +63,8 @@
 
 // STACK BY REF
 // lldb-command:print *self
-// lldbg-check:[...]$0 = TupleStruct(100, -100.5)
-// lldbr-check:(method_on_tuple_struct::TupleStruct) *self = TupleStruct(100, -100.5)
+// lldbg-check:[...]$0 = { 0 = 100 1 = -100.5 }
+// lldbr-check:(method_on_tuple_struct::TupleStruct) *self = { 0 = 100 1 = -100.5 }
 // lldb-command:print arg1
 // lldbg-check:[...]$1 = -1
 // lldbr-check:(isize) arg1 = -1
@@ -75,8 +75,8 @@
 
 // STACK BY VAL
 // lldb-command:print self
-// lldbg-check:[...]$3 = TupleStruct(100, -100.5)
-// lldbr-check:(method_on_tuple_struct::TupleStruct) self = TupleStruct(100, -100.5)
+// lldbg-check:[...]$3 = { 0 = 100 1 = -100.5 }
+// lldbr-check:(method_on_tuple_struct::TupleStruct) self = { 0 = 100 1 = -100.5 }
 // lldb-command:print arg1
 // lldbg-check:[...]$4 = -3
 // lldbr-check:(isize) arg1 = -3
@@ -87,8 +87,8 @@
 
 // OWNED BY REF
 // lldb-command:print *self
-// lldbg-check:[...]$6 = TupleStruct(200, -200.5)
-// lldbr-check:(method_on_tuple_struct::TupleStruct) *self = TupleStruct(200, -200.5)
+// lldbg-check:[...]$6 = { 0 = 200 1 = -200.5 }
+// lldbr-check:(method_on_tuple_struct::TupleStruct) *self = { 0 = 200 1 = -200.5 }
 // lldb-command:print arg1
 // lldbg-check:[...]$7 = -5
 // lldbr-check:(isize) arg1 = -5
@@ -99,8 +99,8 @@
 
 // OWNED BY VAL
 // lldb-command:print self
-// lldbg-check:[...]$9 = TupleStruct(200, -200.5)
-// lldbr-check:(method_on_tuple_struct::TupleStruct) self = TupleStruct(200, -200.5)
+// lldbg-check:[...]$9 = { 0 = 200 1 = -200.5 }
+// lldbr-check:(method_on_tuple_struct::TupleStruct) self = { 0 = 200 1 = -200.5 }
 // lldb-command:print arg1
 // lldbg-check:[...]$10 = -7
 // lldbr-check:(isize) arg1 = -7
@@ -111,8 +111,8 @@
 
 // OWNED MOVED
 // lldb-command:print *self
-// lldbg-check:[...]$12 = TupleStruct(200, -200.5)
-// lldbr-check:(method_on_tuple_struct::TupleStruct) *self = TupleStruct(200, -200.5)
+// lldbg-check:[...]$12 = { 0 = 200 1 = -200.5 }
+// lldbr-check:(method_on_tuple_struct::TupleStruct) *self = { 0 = 200 1 = -200.5 }
 // lldb-command:print arg1
 // lldbg-check:[...]$13 = -9
 // lldbr-check:(isize) arg1 = -9
diff --git a/src/test/debuginfo/packed-struct-with-destructor.rs b/src/test/debuginfo/packed-struct-with-destructor.rs
index d17e6e8193e..380e882a0fb 100644
--- a/src/test/debuginfo/packed-struct-with-destructor.rs
+++ b/src/test/debuginfo/packed-struct-with-destructor.rs
@@ -46,36 +46,36 @@
 // lldb-command:run
 
 // lldb-command:print packed
-// lldbg-check:[...]$0 = Packed { x: 123, y: 234, z: 345 }
-// lldbr-check:(packed_struct_with_destructor::Packed) packed = Packed { x: 123, y: 234, z: 345 }
+// lldbg-check:[...]$0 = { x = 123 y = 234 z = 345 }
+// lldbr-check:(packed_struct_with_destructor::Packed) packed = { x = 123 y = 234 z = 345 }
 
 // lldb-command:print packedInPacked
-// lldbg-check:[...]$1 = PackedInPacked { a: 1111, b: Packed { x: 2222, y: 3333, z: 4444 }, c: 5555, d: Packed { x: 6666, y: 7777, z: 8888 } }
-// lldbr-check:(packed_struct_with_destructor::PackedInPacked) packedInPacked = PackedInPacked { a: 1111, b: Packed { x: 2222, y: 3333, z: 4444 }, c: 5555, d: Packed { x: 6666, y: 7777, z: 8888 } }
+// lldbg-check:[...]$1 = { a = 1111 b = { x = 2222 y = 3333 z = 4444 } c = 5555 d = { x = 6666 y = 7777 z = 8888 } }
+// lldbr-check:(packed_struct_with_destructor::PackedInPacked) packedInPacked = { a = 1111 b = { x = 2222 y = 3333 z = 4444 } c = 5555 d = { x = 6666 y = 7777 z = 8888 } }
 
 // lldb-command:print packedInUnpacked
-// lldbg-check:[...]$2 = PackedInUnpacked { a: -1111, b: Packed { x: -2222, y: -3333, z: -4444 }, c: -5555, d: Packed { x: -6666, y: -7777, z: -8888 } }
-// lldbr-check:(packed_struct_with_destructor::PackedInUnpacked) packedInUnpacked = PackedInUnpacked { a: -1111, b: Packed { x: -2222, y: -3333, z: -4444 }, c: -5555, d: Packed { x: -6666, y: -7777, z: -8888 } }
+// lldbg-check:[...]$2 = { a = -1111 b = { x = -2222 y = -3333 z = -4444 } c = -5555 d = { x = -6666 y = -7777 z = -8888 } }
+// lldbr-check:(packed_struct_with_destructor::PackedInUnpacked) packedInUnpacked = { a = -1111 b = { x = -2222 y = -3333 z = -4444 } c = -5555 d = { x = -6666 y = -7777 z = -8888 } }
 
 // lldb-command:print unpackedInPacked
-// lldbg-check:[...]$3 = UnpackedInPacked { a: 987, b: Unpacked { x: 876, y: 765, z: 654 }, c: Unpacked { x: 543, y: 432, z: 321 }, d: 210 }
-// lldbr-check:(packed_struct_with_destructor::UnpackedInPacked) unpackedInPacked = UnpackedInPacked { a: 987, b: Unpacked { x: 876, y: 765, z: 654 }, c: Unpacked { x: 543, y: 432, z: 321 }, d: 210 }
+// lldbg-check:[...]$3 = { a = 987 b = { x = 876 y = 765 z = 654 } c = { x = 543 y = 432 z = 321 } d = 210 }
+// lldbr-check:(packed_struct_with_destructor::UnpackedInPacked) unpackedInPacked = { a = 987 b = { x = 876 y = 765 z = 654 } c = { x = 543 y = 432 z = 321 } d = 210 }
 
 // lldb-command:print packedInPackedWithDrop
-// lldbg-check:[...]$4 = PackedInPackedWithDrop { a: 11, b: Packed { x: 22, y: 33, z: 44 }, c: 55, d: Packed { x: 66, y: 77, z: 88 } }
-// lldbr-check:(packed_struct_with_destructor::PackedInPackedWithDrop) packedInPackedWithDrop = PackedInPackedWithDrop { a: 11, b: Packed { x: 22, y: 33, z: 44 }, c: 55, d: Packed { x: 66, y: 77, z: 88 } }
+// lldbg-check:[...]$4 = { a = 11 b = { x = 22 y = 33 z = 44 } c = 55 d = { x = 66 y = 77 z = 88 } }
+// lldbr-check:(packed_struct_with_destructor::PackedInPackedWithDrop) packedInPackedWithDrop = { a = 11 b = { x = 22 y = 33 z = 44 } c = 55 d = { x = 66 y = 77 z = 88 } }
 
 // lldb-command:print packedInUnpackedWithDrop
-// lldbg-check:[...]$5 = PackedInUnpackedWithDrop { a: -11, b: Packed { x: -22, y: -33, z: -44 }, c: -55, d: Packed { x: -66, y: -77, z: -88 } }
-// lldbr-check:(packed_struct_with_destructor::PackedInUnpackedWithDrop) packedInUnpackedWithDrop = PackedInUnpackedWithDrop { a: -11, b: Packed { x: -22, y: -33, z: -44 }, c: -55, d: Packed { x: -66, y: -77, z: -88 } }
+// lldbg-check:[...]$5 = { a = -11 b = { x = -22 y = -33 z = -44 } c = -55 d = { x = -66 y = -77 z = -88 } }
+// lldbr-check:(packed_struct_with_destructor::PackedInUnpackedWithDrop) packedInUnpackedWithDrop = { a = -11 b = { x = -22 y = -33 z = -44 } c = -55 d = { x = -66 y = -77 z = -88 } }
 
 // lldb-command:print unpackedInPackedWithDrop
-// lldbg-check:[...]$6 = UnpackedInPackedWithDrop { a: 98, b: Unpacked { x: 87, y: 76, z: 65 }, c: Unpacked { x: 54, y: 43, z: 32 }, d: 21 }
-// lldbr-check:(packed_struct_with_destructor::UnpackedInPackedWithDrop) unpackedInPackedWithDrop = UnpackedInPackedWithDrop { a: 98, b: Unpacked { x: 87, y: 76, z: 65 }, c: Unpacked { x: 54, y: 43, z: 32 }, d: 21 }
+// lldbg-check:[...]$6 = { a = 98 b = { x = 87 y = 76 z = 65 } c = { x = 54 y = 43 z = 32 } d = 21 }
+// lldbr-check:(packed_struct_with_destructor::UnpackedInPackedWithDrop) unpackedInPackedWithDrop = { a = 98 b = { x = 87 y = 76 z = 65 } c = { x = 54 y = 43 z = 32 } d = 21 }
 
 // lldb-command:print deeplyNested
-// lldbg-check:[...]$7 = DeeplyNested { a: PackedInPacked { a: 1, b: Packed { x: 2, y: 3, z: 4 }, c: 5, d: Packed { x: 6, y: 7, z: 8 } }, b: UnpackedInPackedWithDrop { a: 9, b: Unpacked { x: 10, y: 11, z: 12 }, c: Unpacked { x: 13, y: 14, z: 15 }, d: 16 }, c: PackedInUnpacked { a: 17, b: Packed { x: 18, y: 19, z: 20 }, c: 21, d: Packed { x: 22, y: 23, z: 24 } }, d: PackedInUnpackedWithDrop { a: 25, b: Packed { x: 26, y: 27, z: 28 }, c: 29, d: Packed { x: 30, y: 31, z: 32 } }, e: UnpackedInPacked { a: 33, b: Unpacked { x: 34, y: 35, z: 36 }, c: Unpacked { x: 37, y: 38, z: 39 }, d: 40 }, f: PackedInPackedWithDrop { a: 41, b: Packed { x: 42, y: 43, z: 44 }, c: 45, d: Packed { x: 46, y: 47, z: 48 } } }
-// lldbr-check:(packed_struct_with_destructor::DeeplyNested) deeplyNested = DeeplyNested { a: PackedInPacked { a: 1, b: Packed { x: 2, y: 3, z: 4 }, c: 5, d: Packed { x: 6, y: 7, z: 8 } }, b: UnpackedInPackedWithDrop { a: 9, b: Unpacked { x: 10, y: 11, z: 12 }, c: Unpacked { x: 13, y: 14, z: 15 }, d: 16 }, c: PackedInUnpacked { a: 17, b: Packed { x: 18, y: 19, z: 20 }, c: 21, d: Packed { x: 22, y: 23, z: 24 } }, d: PackedInUnpackedWithDrop { a: 25, b: Packed { x: 26, y: 27, z: 28 }, c: 29, d: Packed { x: 30, y: 31, z: 32 } }, e: UnpackedInPacked { a: 33, b: Unpacked { x: 34, y: 35, z: 36 }, c: Unpacked { x: 37, y: 38, z: 39 }, d: 40 }, f: PackedInPackedWithDrop { a: 41, b: Packed { x: 42, y: 43, z: 44 }, c: 45, d: Packed { x: 46, y: 47, z: 48 } } }
+// lldbg-check:[...]$7 = { a = { a = 1 b = { x = 2 y = 3 z = 4 } c = 5 d = { x = 6 y = 7 z = 8 } } b = { a = 9 b = { x = 10 y = 11 z = 12 } c = { x = 13 y = 14 z = 15 } d = 16 } c = { a = 17 b = { x = 18 y = 19 z = 20 } c = 21 d = { x = 22 y = 23 z = 24 } } d = { a = 25 b = { x = 26 y = 27 z = 28 } c = 29 d = { x = 30 y = 31 z = 32 } } e = { a = 33 b = { x = 34 y = 35 z = 36 } c = { x = 37 y = 38 z = 39 } d = 40 } f = { a = 41 b = { x = 42 y = 43 z = 44 } c = 45 d = { x = 46 y = 47 z = 48 } } }
+// lldbr-check:(packed_struct_with_destructor::DeeplyNested) deeplyNested = { a = { a = 1 b = { x = 2 y = 3 z = 4 } c = 5 d = { x = 6 y = 7 z = 8 } } b = { a = 9 b = { x = 10 y = 11 z = 12 } c = { x = 13 y = 14 z = 15 } d = 16 } c = { a = 17 b = { x = 18 y = 19 z = 20 } c = 21 d = { x = 22 y = 23 z = 24 } } d = { a = 25 b = { x = 26 y = 27 z = 28 } c = 29 d = { x = 30 y = 31 z = 32 } } e = { a = 33 b = { x = 34 y = 35 z = 36 } c = { x = 37 y = 38 z = 39 } d = 40 } f = { a = 41 b = { x = 42 y = 43 z = 44 } c = 45 d = { x = 46 y = 47 z = 48 } } }
 
 
 #![allow(unused_variables)]
diff --git a/src/test/debuginfo/packed-struct.rs b/src/test/debuginfo/packed-struct.rs
index 494b61f9a24..9654847ce5d 100644
--- a/src/test/debuginfo/packed-struct.rs
+++ b/src/test/debuginfo/packed-struct.rs
@@ -36,20 +36,20 @@
 // lldb-command:run
 
 // lldb-command:print packed
-// lldbg-check:[...]$0 = Packed { x: 123, y: 234, z: 345 }
-// lldbr-check:(packed_struct::Packed) packed = Packed { x: 123, y: 234, z: 345 }
+// lldbg-check:[...]$0 = { x = 123 y = 234 z = 345 }
+// lldbr-check:(packed_struct::Packed) packed = { x = 123 y = 234 z = 345 }
 
 // lldb-command:print packedInPacked
-// lldbg-check:[...]$1 = PackedInPacked { a: 1111, b: Packed { x: 2222, y: 3333, z: 4444 }, c: 5555, d: Packed { x: 6666, y: 7777, z: 8888 } }
-// lldbr-check:(packed_struct::PackedInPacked) packedInPacked = PackedInPacked { a: 1111, b: Packed { x: 2222, y: 3333, z: 4444 }, c: 5555, d: Packed { x: 6666, y: 7777, z: 8888 } }
+// lldbg-check:[...]$1 = { a = 1111 b = { x = 2222 y = 3333 z = 4444 } c = 5555 d = { x = 6666 y = 7777 z = 8888 } }
+// lldbr-check:(packed_struct::PackedInPacked) packedInPacked = { a = 1111 b = { x = 2222 y = 3333 z = 4444 } c = 5555 d = { x = 6666 y = 7777 z = 8888 } }
 
 // lldb-command:print packedInUnpacked
-// lldbg-check:[...]$2 = PackedInUnpacked { a: -1111, b: Packed { x: -2222, y: -3333, z: -4444 }, c: -5555, d: Packed { x: -6666, y: -7777, z: -8888 } }
-// lldbr-check:(packed_struct::PackedInUnpacked) packedInUnpacked = PackedInUnpacked { a: -1111, b: Packed { x: -2222, y: -3333, z: -4444 }, c: -5555, d: Packed { x: -6666, y: -7777, z: -8888 } }
+// lldbg-check:[...]$2 = { a = -1111 b = { x = -2222 y = -3333 z = -4444 } c = -5555 d = { x = -6666 y = -7777 z = -8888 } }
+// lldbr-check:(packed_struct::PackedInUnpacked) packedInUnpacked = { a = -1111 b = { x = -2222 y = -3333 z = -4444 } c = -5555 d = { x = -6666 y = -7777 z = -8888 } }
 
 // lldb-command:print unpackedInPacked
-// lldbg-check:[...]$3 = UnpackedInPacked { a: 987, b: Unpacked { x: 876, y: 765, z: 654, w: 543 }, c: Unpacked { x: 432, y: 321, z: 210, w: 109 }, d: -98 }
-// lldbr-check:(packed_struct::UnpackedInPacked) unpackedInPacked = UnpackedInPacked { a: 987, b: Unpacked { x: 876, y: 765, z: 654, w: 543 }, c: Unpacked { x: 432, y: 321, z: 210, w: 109 }, d: -98 }
+// lldbg-check:[...]$3 = { a = 987 b = { x = 876 y = 765 z = 654 w = 543 } c = { x = 432 y = 321 z = 210 w = 109 } d = -98 }
+// lldbr-check:(packed_struct::UnpackedInPacked) unpackedInPacked = { a = 987 b = { x = 876 y = 765 z = 654 w = 543 } c = { x = 432 y = 321 z = 210 w = 109 } d = -98 }
 
 // lldb-command:print sizeof(packed)
 // lldbg-check:[...]$4 = 14
diff --git a/src/test/debuginfo/pretty-huge-vec.rs b/src/test/debuginfo/pretty-huge-vec.rs
index 2e3386b7a36..2616c946524 100644
--- a/src/test/debuginfo/pretty-huge-vec.rs
+++ b/src/test/debuginfo/pretty-huge-vec.rs
@@ -2,7 +2,7 @@
 // ignore-freebsd: gdb package too new
 // ignore-android: FIXME(#10381)
 // compile-flags:-g
-// min-gdb-version 7.7
+// min-gdb-version 8.1
 // min-lldb-version: 310
 
 // === GDB TESTS ===================================================================================
@@ -10,11 +10,10 @@
 // gdb-command: run
 
 // gdb-command: print vec
-// gdb-check:$1 = Vec<u8>(len: 1000000000, cap: 1000000000) = {[...]...}
+// gdb-check:$1 = Vec(size=1000000000) = {[...]...}
 
 // gdb-command: print slice
-// gdb-check:$2 = &[u8](len: 1000000000) = {[...]...}
-
+// gdb-check:$2 = &[u8] {data_ptr: [...]"\000", length: 1000000000}
 
 #![allow(unused_variables)]
 
diff --git a/src/test/debuginfo/pretty-std-collections.rs b/src/test/debuginfo/pretty-std-collections.rs
index 1f4ff00100a..4e95a028e07 100644
--- a/src/test/debuginfo/pretty-std-collections.rs
+++ b/src/test/debuginfo/pretty-std-collections.rs
@@ -15,38 +15,76 @@
 // gdb-command: run
 
 // gdb-command: print btree_set
-// gdb-check:$1 = BTreeSet<i32>(len: 15) = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
+// gdb-check:$1 = BTreeSet(size=15) = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
 
 // gdb-command: print empty_btree_set
-// gdb-check:$2 = BTreeSet<i32>(len: 0)
+// gdb-check:$2 = BTreeSet(size=0)
 
 // gdb-command: print btree_map
-// gdb-check:$3 = BTreeMap<i32, i32>(len: 15) = {[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6, [7] = 7, [8] = 8, [9] = 9, [10] = 10, [11] = 11, [12] = 12, [13] = 13, [14] = 14}
+// gdb-check:$3 = BTreeMap(size=15) = {[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6, [7] = 7, [8] = 8, [9] = 9, [10] = 10, [11] = 11, [12] = 12, [13] = 13, [14] = 14}
 
 // gdb-command: print empty_btree_map
-// gdb-check:$4 = BTreeMap<i32, u32>(len: 0)
+// gdb-check:$4 = BTreeMap(size=0)
 
 // gdb-command: print option_btree_map
-// gdb-check:$5 = BTreeMap<bool, core::option::Option<bool>>(len: 2) = {[false] = [...], [true] = [...]}
+// gdb-check:$5 = BTreeMap(size=2) = {[false] = [...], [true] = [...]}
 // (abbreviated because both values vary wildly over gdb versions and/or linux distributions)
 
 // gdb-command: print nasty_btree_map
-// gdb-check:$6 = BTreeMap<i32, pretty_std_collections::MyLeafNode>(len: 15) = {[0] = pretty_std_collections::MyLeafNode (0), [...]}
+// gdb-check:$6 = BTreeMap(size=15) = {[0] = pretty_std_collections::MyLeafNode (0), [...]}
 // (abbreviated because it's boring but we need enough elements to include internal nodes)
 
 // gdb-command: print vec_deque
-// gdb-check:$7 = VecDeque<i32>(len: 3, cap: 8) = {5, 3, 7}
+// gdb-check:$7 = VecDeque(size=3) = {5, 3, 7}
 
 // gdb-command: print vec_deque2
-// gdb-check:$8 = VecDeque<i32>(len: 7, cap: 8) = {2, 3, 4, 5, 6, 7, 8}
+// gdb-check:$8 = VecDeque(size=7) = {2, 3, 4, 5, 6, 7, 8}
+
+// gdb-command: print hash_map
+// gdb-check:$9 = HashMap(size=4) = {[1] = 10, [2] = 20, [3] = 30, [4] = 40}
+
+// gdb-command: print hash_set
+// gdb-check:$10 = HashSet(size=4) = {1, 2, 3, 4}
+
+// === LLDB TESTS ==================================================================================
+
+// lldb-command:run
+
+// lldb-command:print vec_deque
+// lldbg-check:[...]$0 = size=3 { [0] = 5 [1] = 3 [2] = 7 }
+// lldbr-check:(alloc::collections::vec_deque::VecDeque<i32>) vec_deque = size=3 = { [0] = 5 [1] = 3 [2] = 7 }
+
+// lldb-command:print vec_deque2
+// lldbg-check:[...]$1 = size=7 { [0] = 2 [1] = 3 [2] = 4 [3] = 5 [4] = 6 [5] = 7 [6] = 8 }
+// lldbr-check:(alloc::collections::vec_deque::VecDeque<i32>) vec_deque2 = size=7 = { [0] = 2 [1] = 3 [2] = 4 [3] = 5 [4] = 6 [5] = 7 [6] = 8 }
+
+// lldb-command:print hash_map
+// lldbg-check:[...]$2 = size=4 { [0] = { 0 = 1 1 = 10 } [1] = { 0 = 2 1 = 20 } [2] = { 0 = 3 1 = 30 } [3] = { 0 = 4 1 = 40 } }
+// lldbr-check:(std::collections::hash::map::HashMap<u64, u64, [...]>) hash_map = size=4 size=4 { [0] = { 0 = 1 1 = 10 } [1] = { 0 = 2 1 = 20 } [2] = { 0 = 3 1 = 30 } [3] = { 0 = 4 1 = 40 } }
+
+// lldb-command:print hash_set
+// lldbg-check:[...]$3 = size=4 { [0] = 1 [1] = 2 [2] = 3 [3] = 4 }
+// lldbr-check:(std::collections::hash::set::HashSet<u64, [...]>) hash_set = size=4 { [0] = 1 [1] = 2 [2] = 3 [3] = 4 }
 
 #![allow(unused_variables)]
 use std::collections::BTreeMap;
 use std::collections::BTreeSet;
 use std::collections::VecDeque;
+use std::collections::HashMap;
+use std::collections::HashSet;
+use std::hash::{BuildHasherDefault, Hasher};
 
 struct MyLeafNode(i32); // helps to ensure we don't blindly replace substring "LeafNode"
 
+#[derive(Default)]
+struct SimpleHasher { hash: u64 }
+
+impl Hasher for SimpleHasher {
+    fn finish(&self) -> u64 { self.hash }
+    fn write(&mut self, bytes: &[u8]) {}
+    fn write_u64(&mut self, i: u64) { self.hash = i }
+}
+
 fn main() {
     // BTreeSet
     let mut btree_set = BTreeSet::new();
@@ -87,6 +125,18 @@ fn main() {
     vec_deque2.pop_front();
     vec_deque2.push_back(8);
 
+    // HashMap
+    let mut hash_map = HashMap::<u64, u64, BuildHasherDefault<SimpleHasher>>::default();
+    for i in 1..5 {
+        hash_map.insert(i, i * 10);
+    }
+
+    // HashSet
+    let mut hash_set = HashSet::<u64, BuildHasherDefault<SimpleHasher>>::default();
+    for i in 1..5 {
+        hash_set.insert(i);
+    }
+
     zzz(); // #break
 }
 
diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs
index a684d3b88fd..57721ce103c 100644
--- a/src/test/debuginfo/pretty-std.rs
+++ b/src/test/debuginfo/pretty-std.rs
@@ -61,6 +61,9 @@
 // lldb-command: print none
 // lldb-check:[...]$5 = None
 
+// lldb-command: print os_string
+// lldb-check:[...]$6 = "IAMA OS string 😃"[...]
+
 
 // === CDB TESTS ==================================================================================
 
diff --git a/src/test/debuginfo/pretty-uninitialized-vec.rs b/src/test/debuginfo/pretty-uninitialized-vec.rs
index 37aae65d42b..7ce004681e1 100644
--- a/src/test/debuginfo/pretty-uninitialized-vec.rs
+++ b/src/test/debuginfo/pretty-uninitialized-vec.rs
@@ -2,7 +2,7 @@
 // ignore-freebsd: gdb package too new
 // ignore-android: FIXME(#10381)
 // compile-flags:-g
-// min-gdb-version 7.7
+// min-gdb-version 8.1
 // min-lldb-version: 310
 
 // === GDB TESTS ===================================================================================
@@ -10,7 +10,7 @@
 // gdb-command: run
 
 // gdb-command: print vec
-// gdb-check:$1 = Vec<i32>(len: [...], cap: [...])[...]
+// gdb-check:$1 = Vec(size=[...])[...]
 
 
 #![allow(unused_variables)]
diff --git a/src/test/debuginfo/rc_arc.rs b/src/test/debuginfo/rc_arc.rs
new file mode 100644
index 00000000000..8ab8a2f9c1c
--- /dev/null
+++ b/src/test/debuginfo/rc_arc.rs
@@ -0,0 +1,37 @@
+// compile-flags:-g
+
+// min-gdb-version: 8.1
+
+// === GDB TESTS ==================================================================================
+
+// gdb-command:run
+
+// gdb-command:print r
+// gdb-check:[...]$1 = Rc(strong=2, weak=1) = {value = 42, strong = 2, weak = 1}
+// gdb-command:print a
+// gdb-check:[...]$2 = Arc(strong=2, weak=1) = {value = 42, strong = 2, weak = 1}
+
+
+// === LLDB TESTS ==================================================================================
+
+// lldb-command:run
+
+// lldb-command:print r
+// lldb-check:[...]$0 = strong=2, weak=1 { value = 42 }
+// lldb-command:print a
+// lldb-check:[...]$1 = strong=2, weak=1 { data = 42 }
+
+use std::rc::Rc;
+use std::sync::Arc;
+
+fn main() {
+    let r = Rc::new(42);
+    let r1 = Rc::clone(&r);
+    let w1 = Rc::downgrade(&r);
+
+    let a = Arc::new(42);
+    let a1 = Arc::clone(&a);
+    let w2 = Arc::downgrade(&a);
+
+    print!(""); // #break
+}
diff --git a/src/test/debuginfo/self-in-default-method.rs b/src/test/debuginfo/self-in-default-method.rs
index bc150e33789..e15c08577e1 100644
--- a/src/test/debuginfo/self-in-default-method.rs
+++ b/src/test/debuginfo/self-in-default-method.rs
@@ -63,7 +63,7 @@
 
 // STACK BY REF
 // lldb-command:print *self
-// lldbg-check:[...]$0 = Struct { x: 100 }
+// lldbg-check:[...]$0 = { x = 100 }
 // lldbr-check:(self_in_default_method::Struct) *self = Struct { x: 100 }
 // lldb-command:print arg1
 // lldbg-check:[...]$1 = -1
@@ -75,7 +75,7 @@
 
 // STACK BY VAL
 // lldb-command:print self
-// lldbg-check:[...]$3 = Struct { x: 100 }
+// lldbg-check:[...]$3 = { x = 100 }
 // lldbr-check:(self_in_default_method::Struct) self = Struct { x: 100 }
 // lldb-command:print arg1
 // lldbg-check:[...]$4 = -3
@@ -87,7 +87,7 @@
 
 // OWNED BY REF
 // lldb-command:print *self
-// lldbg-check:[...]$6 = Struct { x: 200 }
+// lldbg-check:[...]$6 = { x = 200 }
 // lldbr-check:(self_in_default_method::Struct) *self = Struct { x: 200 }
 // lldb-command:print arg1
 // lldbg-check:[...]$7 = -5
@@ -99,7 +99,7 @@
 
 // OWNED BY VAL
 // lldb-command:print self
-// lldbg-check:[...]$9 = Struct { x: 200 }
+// lldbg-check:[...]$9 = { x = 200 }
 // lldbr-check:(self_in_default_method::Struct) self = Struct { x: 200 }
 // lldb-command:print arg1
 // lldbg-check:[...]$10 = -7
@@ -111,7 +111,7 @@
 
 // OWNED MOVED
 // lldb-command:print *self
-// lldbg-check:[...]$12 = Struct { x: 200 }
+// lldbg-check:[...]$12 = { x = 200 }
 // lldbr-check:(self_in_default_method::Struct) *self = Struct { x: 200 }
 // lldb-command:print arg1
 // lldbg-check:[...]$13 = -9
diff --git a/src/test/debuginfo/self-in-generic-default-method.rs b/src/test/debuginfo/self-in-generic-default-method.rs
index 6c156230e53..7634e3247d5 100644
--- a/src/test/debuginfo/self-in-generic-default-method.rs
+++ b/src/test/debuginfo/self-in-generic-default-method.rs
@@ -63,7 +63,7 @@
 
 // STACK BY REF
 // lldb-command:print *self
-// lldbg-check:[...]$0 = Struct { x: 987 }
+// lldbg-check:[...]$0 = { x = 987 }
 // lldbr-check:(self_in_generic_default_method::Struct) *self = Struct { x: 987 }
 // lldb-command:print arg1
 // lldbg-check:[...]$1 = -1
@@ -75,7 +75,7 @@
 
 // STACK BY VAL
 // lldb-command:print self
-// lldbg-check:[...]$3 = Struct { x: 987 }
+// lldbg-check:[...]$3 = { x = 987 }
 // lldbr-check:(self_in_generic_default_method::Struct) self = Struct { x: 987 }
 // lldb-command:print arg1
 // lldbg-check:[...]$4 = -3
@@ -87,7 +87,7 @@
 
 // OWNED BY REF
 // lldb-command:print *self
-// lldbg-check:[...]$6 = Struct { x: 879 }
+// lldbg-check:[...]$6 = { x = 879 }
 // lldbr-check:(self_in_generic_default_method::Struct) *self = Struct { x: 879 }
 // lldb-command:print arg1
 // lldbg-check:[...]$7 = -5
@@ -99,7 +99,7 @@
 
 // OWNED BY VAL
 // lldb-command:print self
-// lldbg-check:[...]$9 = Struct { x: 879 }
+// lldbg-check:[...]$9 = { x = 879 }
 // lldbr-check:(self_in_generic_default_method::Struct) self = Struct { x: 879 }
 // lldb-command:print arg1
 // lldbg-check:[...]$10 = -7
@@ -111,7 +111,7 @@
 
 // OWNED MOVED
 // lldb-command:print *self
-// lldbg-check:[...]$12 = Struct { x: 879 }
+// lldbg-check:[...]$12 = { x = 879 }
 // lldbr-check:(self_in_generic_default_method::Struct) *self = Struct { x: 879 }
 // lldb-command:print arg1
 // lldbg-check:[...]$13 = -9
diff --git a/src/test/debuginfo/simple-struct.rs b/src/test/debuginfo/simple-struct.rs
index b9475d5429a..49aa3bcbcaa 100644
--- a/src/test/debuginfo/simple-struct.rs
+++ b/src/test/debuginfo/simple-struct.rs
@@ -100,28 +100,28 @@
 // lldb-command:run
 
 // lldb-command:print no_padding16
-// lldbg-check:[...]$0 = NoPadding16 { x: 10000, y: -10001 }
-// lldbr-check:(simple_struct::NoPadding16) no_padding16 = NoPadding16 { x: 10000, y: -10001 }
+// lldbg-check:[...]$0 = { x = 10000 y = -10001 }
+// lldbr-check:(simple_struct::NoPadding16) no_padding16 = { x = 10000 y = -10001 }
 
 // lldb-command:print no_padding32
-// lldbg-check:[...]$1 = NoPadding32 { x: -10002, y: -10003.5, z: 10004 }
-// lldbr-check:(simple_struct::NoPadding32) no_padding32 = NoPadding32 { x: -10002, y: -10003.5, z: 10004 }
+// lldbg-check:[...]$1 = { x = -10002 y = -10003.5 z = 10004 }
+// lldbr-check:(simple_struct::NoPadding32) no_padding32 = { x = -10002 y = -10003.5 z = 10004 }
 
 // lldb-command:print no_padding64
-// lldbg-check:[...]$2 = NoPadding64 { x: -10005.5, y: 10006, z: 10007 }
-// lldbr-check:(simple_struct::NoPadding64) no_padding64 = NoPadding64 { x: -10005.5, y: 10006, z: 10007 }
+// lldbg-check:[...]$2 = { x = -10005.5 y = 10006 z = 10007 }
+// lldbr-check:(simple_struct::NoPadding64) no_padding64 = { x = -10005.5 y = 10006 z = 10007 }
 
 // lldb-command:print no_padding163264
-// lldbg-check:[...]$3 = NoPadding163264 { a: -10008, b: 10009, c: 10010, d: 10011 }
-// lldbr-check:(simple_struct::NoPadding163264) no_padding163264 = NoPadding163264 { a: -10008, b: 10009, c: 10010, d: 10011 }
+// lldbg-check:[...]$3 = { a = -10008 b = 10009 c = 10010 d = 10011 }
+// lldbr-check:(simple_struct::NoPadding163264) no_padding163264 = { a = -10008 b = 10009 c = 10010 d = 10011 }
 
 // lldb-command:print internal_padding
-// lldbg-check:[...]$4 = InternalPadding { x: 10012, y: -10013 }
-// lldbr-check:(simple_struct::InternalPadding) internal_padding = InternalPadding { x: 10012, y: -10013 }
+// lldbg-check:[...]$4 = { x = 10012 y = -10013 }
+// lldbr-check:(simple_struct::InternalPadding) internal_padding = { x = 10012 y = -10013 }
 
 // lldb-command:print padding_at_end
-// lldbg-check:[...]$5 = PaddingAtEnd { x: -10014, y: 10015 }
-// lldbr-check:(simple_struct::PaddingAtEnd) padding_at_end = PaddingAtEnd { x: -10014, y: 10015 }
+// lldbg-check:[...]$5 = { x = -10014 y = 10015 }
+// lldbr-check:(simple_struct::PaddingAtEnd) padding_at_end = { x = -10014 y = 10015 }
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
diff --git a/src/test/debuginfo/simple-tuple.rs b/src/test/debuginfo/simple-tuple.rs
index f7e5b5c982a..c2db5218e68 100644
--- a/src/test/debuginfo/simple-tuple.rs
+++ b/src/test/debuginfo/simple-tuple.rs
@@ -100,28 +100,28 @@
 // lldb-command:run
 
 // lldb-command:print/d noPadding8
-// lldbg-check:[...]$0 = (-100, 100)
-// lldbr-check:((i8, u8)) noPadding8 = { = -100 -100 = 100 100 }
+// lldbg-check:[...]$0 = { 0 = -100 1 = 100 }
+// lldbr-check:((i8, u8)) noPadding8 = { 0 = -100 1 = 100 }
 // lldb-command:print noPadding16
-// lldbg-check:[...]$1 = (0, 1, 2)
-// lldbr-check:((i16, i16, u16)) noPadding16 = { = 0 = 1 = 2 }
+// lldbg-check:[...]$1 = { 0 = 0 1 = 1 2 = 2 }
+// lldbr-check:((i16, i16, u16)) noPadding16 = { 0 = 0 1 = 1 2 = 2 }
 // lldb-command:print noPadding32
-// lldbg-check:[...]$2 = (3, 4.5, 5)
-// lldbr-check:((i32, f32, u32)) noPadding32 = { = 3 = 4.5 = 5 }
+// lldbg-check:[...]$2 = { 0 = 3 1 = 4.5 2 = 5 }
+// lldbr-check:((i32, f32, u32)) noPadding32 = { 0 = 3 1 = 4.5 2 = 5 }
 // lldb-command:print noPadding64
-// lldbg-check:[...]$3 = (6, 7.5, 8)
-// lldbr-check:((i64, f64, u64)) noPadding64 = { = 6 = 7.5 = 8 }
+// lldbg-check:[...]$3 = { 0 = 6 1 = 7.5 2 = 8 }
+// lldbr-check:((i64, f64, u64)) noPadding64 = { 0 = 6 1 = 7.5 2 = 8 }
 
 // lldb-command:print internalPadding1
-// lldbg-check:[...]$4 = (9, 10)
-// lldbr-check:((i16, i32)) internalPadding1 = { = 9 = 10 }
+// lldbg-check:[...]$4 = { 0 = 9 1 = 10 }
+// lldbr-check:((i16, i32)) internalPadding1 = { 0 = 9 1 = 10 }
 // lldb-command:print internalPadding2
-// lldbg-check:[...]$5 = (11, 12, 13, 14)
-// lldbr-check:((i16, i32, u32, u64)) internalPadding2 = { = 11 = 12 = 13 = 14 }
+// lldbg-check:[...]$5 = { 0 = 11 1 = 12 2 = 13 3 = 14 }
+// lldbr-check:((i16, i32, u32, u64)) internalPadding2 = { 0 = 11 1 = 12 2 = 13 3 = 14 }
 
 // lldb-command:print paddingAtEnd
-// lldbg-check:[...]$6 = (15, 16)
-// lldbr-check:((i32, i16)) paddingAtEnd = { = 15 = 16 }
+// lldbg-check:[...]$6 = { 0 = 15 1 = 16 }
+// lldbr-check:((i32, i16)) paddingAtEnd = { 0 = 15 1 = 16 }
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
diff --git a/src/test/debuginfo/struct-in-struct.rs b/src/test/debuginfo/struct-in-struct.rs
index 46340508ae0..a76a4c05d9b 100644
--- a/src/test/debuginfo/struct-in-struct.rs
+++ b/src/test/debuginfo/struct-in-struct.rs
@@ -25,36 +25,36 @@
 // lldb-command:run
 
 // lldb-command:print three_simple_structs
-// lldbg-check:[...]$0 = ThreeSimpleStructs { x: Simple { x: 1 }, y: Simple { x: 2 }, z: Simple { x: 3 } }
-// lldbr-check:(struct_in_struct::ThreeSimpleStructs) three_simple_structs = ThreeSimpleStructs { x: Simple { x: 1 }, y: Simple { x: 2 }, z: Simple { x: 3 } }
+// lldbg-check:[...]$0 = { x = { x = 1 } y = { x = 2 } z = { x = 3 } }
+// lldbr-check:(struct_in_struct::ThreeSimpleStructs) three_simple_structs = { x = { x = 1 } y = { x = 2 } z = { x = 3 } }
 
 // lldb-command:print internal_padding_parent
-// lldbg-check:[...]$1 = InternalPaddingParent { x: InternalPadding { x: 4, y: 5 }, y: InternalPadding { x: 6, y: 7 }, z: InternalPadding { x: 8, y: 9 } }
-// lldbr-check:(struct_in_struct::InternalPaddingParent) internal_padding_parent = InternalPaddingParent { x: InternalPadding { x: 4, y: 5 }, y: InternalPadding { x: 6, y: 7 }, z: InternalPadding { x: 8, y: 9 } }
+// lldbg-check:[...]$1 = { x = { x = 4 y = 5 } y = { x = 6 y = 7 } z = { x = 8 y = 9 } }
+// lldbr-check:(struct_in_struct::InternalPaddingParent) internal_padding_parent = { x = { x = 4 y = 5 } y = { x = 6 y = 7 } z = { x = 8 y = 9 } }
 
 // lldb-command:print padding_at_end_parent
-// lldbg-check:[...]$2 = PaddingAtEndParent { x: PaddingAtEnd { x: 10, y: 11 }, y: PaddingAtEnd { x: 12, y: 13 }, z: PaddingAtEnd { x: 14, y: 15 } }
-// lldbr-check:(struct_in_struct::PaddingAtEndParent) padding_at_end_parent = PaddingAtEndParent { x: PaddingAtEnd { x: 10, y: 11 }, y: PaddingAtEnd { x: 12, y: 13 }, z: PaddingAtEnd { x: 14, y: 15 } }
+// lldbg-check:[...]$2 = { x = { x = 10 y = 11 } y = { x = 12 y = 13 } z = { x = 14 y = 15 } }
+// lldbr-check:(struct_in_struct::PaddingAtEndParent) padding_at_end_parent = { x = { x = 10 y = 11 } y = { x = 12 y = 13 } z = { x = 14 y = 15 } }
 
 // lldb-command:print mixed
-// lldbg-check:[...]$3 = Mixed { x: PaddingAtEnd { x: 16, y: 17 }, y: InternalPadding { x: 18, y: 19 }, z: Simple { x: 20 }, w: 21 }
-// lldbr-check:(struct_in_struct::Mixed) mixed = Mixed { x: PaddingAtEnd { x: 16, y: 17 }, y: InternalPadding { x: 18, y: 19 }, z: Simple { x: 20 }, w: 21 }
+// lldbg-check:[...]$3 = { x = { x = 16 y = 17 } y = { x = 18 y = 19 } z = { x = 20 } w = 21 }
+// lldbr-check:(struct_in_struct::Mixed) mixed = { x = { x = 16 y = 17 } y = { x = 18 y = 19 } z = { x = 20 } w = 21 }
 
 // lldb-command:print bag
-// lldbg-check:[...]$4 = Bag { x: Simple { x: 22 } }
-// lldbr-check:(struct_in_struct::Bag) bag = Bag { x: Simple { x: 22 } }
+// lldbg-check:[...]$4 = { x = { x = 22 } }
+// lldbr-check:(struct_in_struct::Bag) bag = { x = { x = 22 } }
 
 // lldb-command:print bag_in_bag
-// lldbg-check:[...]$5 = BagInBag { x: Bag { x: Simple { x: 23 } } }
-// lldbr-check:(struct_in_struct::BagInBag) bag_in_bag = BagInBag { x: Bag { x: Simple { x: 23 } } }
+// lldbg-check:[...]$5 = { x = { x = { x = 23 } } }
+// lldbr-check:(struct_in_struct::BagInBag) bag_in_bag = { x = { x = { x = 23 } } }
 
 // lldb-command:print tjo
-// lldbg-check:[...]$6 = ThatsJustOverkill { x: BagInBag { x: Bag { x: Simple { x: 24 } } } }
-// lldbr-check:(struct_in_struct::ThatsJustOverkill) tjo = ThatsJustOverkill { x: BagInBag { x: Bag { x: Simple { x: 24 } } } }
+// lldbg-check:[...]$6 = { x = { x = { x = { x = 24 } } } }
+// lldbr-check:(struct_in_struct::ThatsJustOverkill) tjo = { x = { x = { x = { x = 24 } } } }
 
 // lldb-command:print tree
-// lldbg-check:[...]$7 = Tree { x: Simple { x: 25 }, y: InternalPaddingParent { x: InternalPadding { x: 26, y: 27 }, y: InternalPadding { x: 28, y: 29 }, z: InternalPadding { x: 30, y: 31 } }, z: BagInBag { x: Bag { x: Simple { x: 32 } } } }
-// lldbr-check:(struct_in_struct::Tree) tree = Tree { x: Simple { x: 25 }, y: InternalPaddingParent { x: InternalPadding { x: 26, y: 27 }, y: InternalPadding { x: 28, y: 29 }, z: InternalPadding { x: 30, y: 31 } }, z: BagInBag { x: Bag { x: Simple { x: 32 } } } }
+// lldbg-check:[...]$7 = { x = { x = 25 } y = { x = { x = 26 y = 27 } y = { x = 28 y = 29 } z = { x = 30 y = 31 } } z = { x = { x = { x = 32 } } } }
+// lldbr-check:(struct_in_struct::Tree) tree = { x = { x = 25 } y = { x = { x = 26 y = 27 } y = { x = 28 y = 29 } z = { x = 30 y = 31 } } z = { x = { x = { x = 32 } } } }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
diff --git a/src/test/debuginfo/struct-with-destructor.rs b/src/test/debuginfo/struct-with-destructor.rs
index c478e6d2222..ebae953cb4b 100644
--- a/src/test/debuginfo/struct-with-destructor.rs
+++ b/src/test/debuginfo/struct-with-destructor.rs
@@ -28,20 +28,20 @@
 
 // lldb-command:run
 // lldb-command:print simple
-// lldbg-check:[...]$0 = WithDestructor { x: 10, y: 20 }
-// lldbr-check:(struct_with_destructor::WithDestructor) simple = WithDestructor { x: 10, y: 20 }
+// lldbg-check:[...]$0 = { x = 10 y = 20 }
+// lldbr-check:(struct_with_destructor::WithDestructor) simple = { x = 10 y = 20 }
 
 // lldb-command:print noDestructor
-// lldbg-check:[...]$1 = NoDestructorGuarded { a: NoDestructor { x: 10, y: 20 }, guard: -1 }
-// lldbr-check:(struct_with_destructor::NoDestructorGuarded) noDestructor = NoDestructorGuarded { a: NoDestructor { x: 10, y: 20 }, guard: -1 }
+// lldbg-check:[...]$1 = { a = { x = 10 y = 20 } guard = -1 }
+// lldbr-check:(struct_with_destructor::NoDestructorGuarded) noDestructor = { a = { x = 10 y = 20 } guard = -1 }
 
 // lldb-command:print withDestructor
-// lldbg-check:[...]$2 = WithDestructorGuarded { a: WithDestructor { x: 10, y: 20 }, guard: -1 }
-// lldbr-check:(struct_with_destructor::WithDestructorGuarded) withDestructor = WithDestructorGuarded { a: WithDestructor { x: 10, y: 20 }, guard: -1 }
+// lldbg-check:[...]$2 = { a = { x = 10 y = 20 } guard = -1 }
+// lldbr-check:(struct_with_destructor::WithDestructorGuarded) withDestructor = { a = { x = 10 y = 20 } guard = -1 }
 
 // lldb-command:print nested
-// lldbg-check:[...]$3 = NestedOuter { a: NestedInner { a: WithDestructor { x: 7890, y: 9870 } } }
-// lldbr-check:(struct_with_destructor::NestedOuter) nested = NestedOuter { a: NestedInner { a: WithDestructor { x: 7890, y: 9870 } } }
+// lldbg-check:[...]$3 = { a = { a = { x = 7890 y = 9870 } } }
+// lldbr-check:(struct_with_destructor::NestedOuter) nested = { a = { a = { x = 7890 y = 9870 } } }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
diff --git a/src/test/debuginfo/tuple-in-tuple.rs b/src/test/debuginfo/tuple-in-tuple.rs
index 5727521f5f5..e0f940ca7a1 100644
--- a/src/test/debuginfo/tuple-in-tuple.rs
+++ b/src/test/debuginfo/tuple-in-tuple.rs
@@ -36,28 +36,28 @@
 // lldb-command:run
 
 // lldb-command:print no_padding1
-// lldbg-check:[...]$0 = ((0, 1), 2, 3)
-// lldbr-check:(((u32, u32), u32, u32)) no_padding1 = { = { = 0 = 1 } = 2 = 3 }
+// lldbg-check:[...]$0 = { 0 = { 0 = 0 1 = 1 } 1 = 2 2 = 3 }
+// lldbr-check:(((u32, u32), u32, u32)) no_padding1 = { 0 = { 0 = 0 1 = 1 } 1 = 2 2 = 3 }
 // lldb-command:print no_padding2
-// lldbg-check:[...]$1 = (4, (5, 6), 7)
-// lldbr-check:((u32, (u32, u32), u32)) no_padding2 = { = 4 = { = 5 = 6 } = 7 }
+// lldbg-check:[...]$1 = { 0 = 4 1 = { 0 = 5 1 = 6 } 2 = 7 }
+// lldbr-check:((u32, (u32, u32), u32)) no_padding2 = { 0 = 4 1 = { 0 = 5 1 = 6 } 2 = 7 }
 // lldb-command:print no_padding3
-// lldbg-check:[...]$2 = (8, 9, (10, 11))
-// lldbr-check:((u32, u32, (u32, u32))) no_padding3 = { = 8 = 9 = { = 10 = 11 } }
+// lldbg-check:[...]$2 = { 0 = 8 1 = 9 2 = { 0 = 10 1 = 11 } }
+// lldbr-check:((u32, u32, (u32, u32))) no_padding3 = { 0 = 8 1 = 9 2 = { 0 = 10 1 = 11 } }
 
 // lldb-command:print internal_padding1
-// lldbg-check:[...]$3 = (12, (13, 14))
-// lldbr-check:((i16, (i32, i32))) internal_padding1 = { = 12 = { = 13 = 14 } }
+// lldbg-check:[...]$3 = { 0 = 12 1 = { 0 = 13 1 = 14 } }
+// lldbr-check:((i16, (i32, i32))) internal_padding1 = { 0 = 12 1 = { 0 = 13 1 = 14 } }
 // lldb-command:print internal_padding2
-// lldbg-check:[...]$4 = (15, (16, 17))
-// lldbr-check:((i16, (i16, i32))) internal_padding2 = { = 15 = { = 16 = 17 } }
+// lldbg-check:[...]$4 = { 0 = 15 1 = { 0 = 16 1 = 17 } }
+// lldbr-check:((i16, (i16, i32))) internal_padding2 = { 0 = 15 1 = { 0 = 16 1 = 17 } }
 
 // lldb-command:print padding_at_end1
-// lldbg-check:[...]$5 = (18, (19, 20))
-// lldbr-check:((i32, (i32, i16))) padding_at_end1 = { = 18 = { = 19 = 20 } }
+// lldbg-check:[...]$5 = { 0 = 18 1 = { 0 = 19 1 = 20 } }
+// lldbr-check:((i32, (i32, i16))) padding_at_end1 = { 0 = 18 1 = { 0 = 19 1 = 20 } }
 // lldb-command:print padding_at_end2
-// lldbg-check:[...]$6 = ((21, 22), 23)
-// lldbr-check:(((i32, i16), i32)) padding_at_end2 = { = { = 21 = 22 } = 23 }
+// lldbg-check:[...]$6 = { 0 = { 0 = 21 1 = 22 } 1 = 23 }
+// lldbr-check:(((i32, i16), i32)) padding_at_end2 = { 0 = { 0 = 21 1 = 22 } 1 = 23 }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
diff --git a/src/test/debuginfo/tuple-struct.rs b/src/test/debuginfo/tuple-struct.rs
index f06ff176acd..78b6e6a54db 100644
--- a/src/test/debuginfo/tuple-struct.rs
+++ b/src/test/debuginfo/tuple-struct.rs
@@ -38,28 +38,28 @@
 // lldb-command:run
 
 // lldb-command:print no_padding16
-// lldbg-check:[...]$0 = NoPadding16(10000, -10001)
-// lldbr-check:(tuple_struct::NoPadding16) no_padding16 = { = 10000 = -10001 }
+// lldbg-check:[...]$0 = { 0 = 10000 1 = -10001 }
+// lldbr-check:(tuple_struct::NoPadding16) no_padding16 = { 0 = 10000 1 = -10001 }
 
 // lldb-command:print no_padding32
-// lldbg-check:[...]$1 = NoPadding32(-10002, -10003.5, 10004)
-// lldbr-check:(tuple_struct::NoPadding32) no_padding32 = { = -10002 = -10003.5 = 10004 }
+// lldbg-check:[...]$1 = { 0 = -10002 1 = -10003.5 2 = 10004 }
+// lldbr-check:(tuple_struct::NoPadding32) no_padding32 = { 0 = -10002 1 = -10003.5 2 = 10004 }
 
 // lldb-command:print no_padding64
-// lldbg-check:[...]$2 = NoPadding64(-10005.5, 10006, 10007)
-// lldbr-check:(tuple_struct::NoPadding64) no_padding64 = { = -10005.5 = 10006 = 10007 }
+// lldbg-check:[...]$2 = { 0 = -10005.5 1 = 10006 2 = 10007 }
+// lldbr-check:(tuple_struct::NoPadding64) no_padding64 = { 0 = -10005.5 1 = 10006 2 = 10007 }
 
 // lldb-command:print no_padding163264
-// lldbg-check:[...]$3 = NoPadding163264(-10008, 10009, 10010, 10011)
-// lldbr-check:(tuple_struct::NoPadding163264) no_padding163264 = { = -10008 = 10009 = 10010 = 10011 }
+// lldbg-check:[...]$3 = { 0 = -10008 1 = 10009 2 = 10010 3 = 10011 }
+// lldbr-check:(tuple_struct::NoPadding163264) no_padding163264 = { 0 = -10008 1 = 10009 2 = 10010 3 = 10011 }
 
 // lldb-command:print internal_padding
-// lldbg-check:[...]$4 = InternalPadding(10012, -10013)
-// lldbr-check:(tuple_struct::InternalPadding) internal_padding = { = 10012 = -10013 }
+// lldbg-check:[...]$4 = { 0 = 10012 1 = -10013 }
+// lldbr-check:(tuple_struct::InternalPadding) internal_padding = { 0 = 10012 1 = -10013 }
 
 // lldb-command:print padding_at_end
-// lldbg-check:[...]$5 = PaddingAtEnd(-10014, 10015)
-// lldbr-check:(tuple_struct::PaddingAtEnd) padding_at_end = { = -10014 = 10015 }
+// lldbg-check:[...]$5 = { 0 = -10014 1 = 10015 }
+// lldbr-check:(tuple_struct::PaddingAtEnd) padding_at_end = { 0 = -10014 1 = 10015 }
 
 // This test case mainly makes sure that no field names are generated for tuple structs (as opposed
 // to all fields having the name "<unnamed_field>"). Otherwise they are handled the same a normal
diff --git a/src/test/debuginfo/union-smoke.rs b/src/test/debuginfo/union-smoke.rs
index 79b4030ee34..4d4b6cc96fb 100644
--- a/src/test/debuginfo/union-smoke.rs
+++ b/src/test/debuginfo/union-smoke.rs
@@ -19,13 +19,13 @@
 
 // lldb-command:run
 // lldb-command:print u
-// lldbg-check:[...]$0 = U { a: ('\x02', '\x02'), b: 514 }
-// lldbr-check:(union_smoke::U) u = { a = { = 2 = 2 } b = 514 }
+// lldbg-check:[...]$0 = { a = { 0 = '\x02' 1 = '\x02' } b = 514 }
+// lldbr-check:(union_smoke::U) u = { a = { 0 = '\x02' 1 = '\x02' } b = 514 }
 
 // Don't test this with rust-enabled lldb for now; see
 // https://github.com/rust-lang-nursery/lldb/issues/18
 // lldbg-command:print union_smoke::SU
-// lldbg-check:[...]$1 = U { a: ('\x01', '\x01'), b: 257 }
+// lldbg-check:[...]$1 = { a = { 0 = '\x01' 1 = '\x01' } b = 257 }
 
 #![allow(unused)]
 #![feature(omit_gdb_pretty_printer_section)]
diff --git a/src/test/debuginfo/var-captured-in-nested-closure.rs b/src/test/debuginfo/var-captured-in-nested-closure.rs
index a0f0de20d0c..8ab6d141731 100644
--- a/src/test/debuginfo/var-captured-in-nested-closure.rs
+++ b/src/test/debuginfo/var-captured-in-nested-closure.rs
@@ -50,11 +50,11 @@
 // lldbg-check:[...]$1 = 2
 // lldbr-check:(isize) constant = 2
 // lldb-command:print a_struct
-// lldbg-check:[...]$2 = Struct { a: -3, b: 4.5, c: 5 }
-// lldbr-check:(var_captured_in_nested_closure::Struct) a_struct = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$2 = { a = -3 b = 4.5 c = 5 }
+// lldbr-check:(var_captured_in_nested_closure::Struct) a_struct = { a = -3 b = 4.5 c = 5 }
 // lldb-command:print *struct_ref
-// lldbg-check:[...]$3 = Struct { a: -3, b: 4.5, c: 5 }
-// lldbr-check:(var_captured_in_nested_closure::Struct) *struct_ref = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$3 = { a = -3 b = 4.5 c = 5 }
+// lldbr-check:(var_captured_in_nested_closure::Struct) *struct_ref = { a = -3 b = 4.5 c = 5 }
 // lldb-command:print *owned
 // lldbg-check:[...]$4 = 6
 // lldbr-check:(isize) *owned = 6
@@ -70,11 +70,11 @@
 // lldbg-check:[...]$7 = 2
 // lldbr-check:(isize) constant = 2
 // lldb-command:print a_struct
-// lldbg-check:[...]$8 = Struct { a: -3, b: 4.5, c: 5 }
-// lldbr-check:(var_captured_in_nested_closure::Struct) a_struct = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$8 = { a = -3 b = 4.5 c = 5 }
+// lldbr-check:(var_captured_in_nested_closure::Struct) a_struct = { a = -3 b = 4.5 c = 5 }
 // lldb-command:print *struct_ref
-// lldbg-check:[...]$9 = Struct { a: -3, b: 4.5, c: 5 }
-// lldbr-check:(var_captured_in_nested_closure::Struct) *struct_ref = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$9 = { a = -3 b = 4.5 c = 5 }
+// lldbr-check:(var_captured_in_nested_closure::Struct) *struct_ref = { a = -3 b = 4.5 c = 5 }
 // lldb-command:print *owned
 // lldbg-check:[...]$10 = 6
 // lldbr-check:(isize) *owned = 6
diff --git a/src/test/debuginfo/var-captured-in-sendable-closure.rs b/src/test/debuginfo/var-captured-in-sendable-closure.rs
index b6a3c32ac47..bd7c2bfe2c3 100644
--- a/src/test/debuginfo/var-captured-in-sendable-closure.rs
+++ b/src/test/debuginfo/var-captured-in-sendable-closure.rs
@@ -27,8 +27,8 @@
 // lldbg-check:[...]$0 = 1
 // lldbr-check:(isize) constant = 1
 // lldb-command:print a_struct
-// lldbg-check:[...]$1 = Struct { a: -2, b: 3.5, c: 4 }
-// lldbr-check:(var_captured_in_sendable_closure::Struct) a_struct = Struct { a: -2, b: 3.5, c: 4 }
+// lldbg-check:[...]$1 = { a = -2 b = 3.5 c = 4 }
+// lldbr-check:(var_captured_in_sendable_closure::Struct) a_struct = { a = -2 b = 3.5 c = 4 }
 // lldb-command:print *owned
 // lldbg-check:[...]$2 = 5
 // lldbr-check:(isize) *owned = 5
diff --git a/src/test/debuginfo/var-captured-in-stack-closure.rs b/src/test/debuginfo/var-captured-in-stack-closure.rs
index 2402b5f6851..f53f8aaa670 100644
--- a/src/test/debuginfo/var-captured-in-stack-closure.rs
+++ b/src/test/debuginfo/var-captured-in-stack-closure.rs
@@ -46,11 +46,11 @@
 // lldbg-check:[...]$1 = 2
 // lldbr-check:(isize) constant = 2
 // lldb-command:print a_struct
-// lldbg-check:[...]$2 = Struct { a: -3, b: 4.5, c: 5 }
-// lldbr-check:(var_captured_in_stack_closure::Struct) a_struct = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$2 = { a = -3 b = 4.5 c = 5 }
+// lldbr-check:(var_captured_in_stack_closure::Struct) a_struct = { a = -3 b = 4.5 c = 5 }
 // lldb-command:print *struct_ref
-// lldbg-check:[...]$3 = Struct { a: -3, b: 4.5, c: 5 }
-// lldbr-check:(var_captured_in_stack_closure::Struct) *struct_ref = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$3 = { a = -3 b = 4.5 c = 5 }
+// lldbr-check:(var_captured_in_stack_closure::Struct) *struct_ref = { a = -3 b = 4.5 c = 5 }
 // lldb-command:print *owned
 // lldbg-check:[...]$4 = 6
 // lldbr-check:(isize) *owned = 6
@@ -64,11 +64,11 @@
 // lldbg-check:[...]$6 = 2
 // lldbr-check:(isize) constant = 2
 // lldb-command:print a_struct
-// lldbg-check:[...]$7 = Struct { a: -3, b: 4.5, c: 5 }
-// lldbr-check:(var_captured_in_stack_closure::Struct) a_struct = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$7 = { a = -3 b = 4.5 c = 5 }
+// lldbr-check:(var_captured_in_stack_closure::Struct) a_struct = { a = -3 b = 4.5 c = 5 }
 // lldb-command:print *struct_ref
-// lldbg-check:[...]$8 = Struct { a: -3, b: 4.5, c: 5 }
-// lldbr-check:(var_captured_in_stack_closure::Struct) *struct_ref = Struct { a: -3, b: 4.5, c: 5 }
+// lldbg-check:[...]$8 = { a = -3 b = 4.5 c = 5 }
+// lldbr-check:(var_captured_in_stack_closure::Struct) *struct_ref = { a = -3 b = 4.5 c = 5 }
 // lldb-command:print *owned
 // lldbg-check:[...]$9 = 6
 // lldbr-check:(isize) *owned = 6
diff --git a/src/test/debuginfo/vec-slices.rs b/src/test/debuginfo/vec-slices.rs
index 8d9fc498882..c385491bd1d 100644
--- a/src/test/debuginfo/vec-slices.rs
+++ b/src/test/debuginfo/vec-slices.rs
@@ -72,28 +72,28 @@
 // lldb-command:run
 
 // lldb-command:print empty
-// lldbg-check:[...]$0 = &[]
-// lldbr-check:(&[i64]) empty = &[]
+// lldbg-check:[...]$0 = size=0
+// lldbr-check:(&[i64]) empty = size=0
 
 // lldb-command:print singleton
-// lldbg-check:[...]$1 = &[1]
+// lldbg-check:[...]$1 = size=1 { [0] = 1 }
 // lldbr-check:(&[i64]) singleton = &[1]
 
 // lldb-command:print multiple
-// lldbg-check:[...]$2 = &[2, 3, 4, 5]
-// lldbr-check:(&[i64]) multiple = &[2, 3, 4, 5]
+// lldbg-check:[...]$2 = size=4 { [0] = 2 [1] = 3 [2] = 4 [3] = 5 }
+// lldbr-check:(&[i64]) multiple = size=4 { [0] = 2 [1] = 3 [2] = 4 [3] = 5 }
 
 // lldb-command:print slice_of_slice
-// lldbg-check:[...]$3 = &[3, 4]
-// lldbr-check:(&[i64]) slice_of_slice = &[3, 4]
+// lldbg-check:[...]$3 = size=2 { [0] = 3 [1] = 4 }
+// lldbr-check:(&[i64]) slice_of_slice = size=2 { [0] = 3 [1] = 4 }
 
 // lldb-command:print padded_tuple
-// lldbg-check:[...]$4 = &[(6, 7), (8, 9)]
-// lldbr-check:(&[(i32, i16)]) padded_tuple = { data_ptr = *[...] length = 2 }
+// lldbg-check:[...]$4 = size=2 { [0] = { 0 = 6 1 = 7 } [1] = { 0 = 8 1 = 9 } }
+// lldbr-check:(&[(i32, i16)]) padded_tuple = size=2 { [0] = { 0 = 6 1 = 7 } [1] = { 0 = 8 1 = 9 } }
 
 // lldb-command:print padded_struct
-// lldbg-check:[...]$5 = &[AStruct { x: 10, y: 11, z: 12 }, AStruct { x: 13, y: 14, z: 15 }]
-// lldbr-check:(&[vec_slices::AStruct]) padded_struct = &[AStruct { x: 10, y: 11, z: 12 }, AStruct { x: 13, y: 14, z: 15 }]
+// lldbg-check:[...]$5 = size=2 { [0] = { x = 10 y = 11 z = 12 } [1] = { x = 13 y = 14 z = 15 } }
+// lldbr-check:(&[vec_slices::AStruct]) padded_struct = size=2 { [0] = { x = 10 y = 11 z = 12 } [1] = { x = 13 y = 14 z = 15 } }
 
 #![allow(dead_code, unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
diff --git a/src/test/debuginfo/vec.rs b/src/test/debuginfo/vec.rs
index b0ee521c145..895661816b8 100644
--- a/src/test/debuginfo/vec.rs
+++ b/src/test/debuginfo/vec.rs
@@ -18,8 +18,8 @@
 
 // lldb-command:run
 // lldb-command:print a
-// lldbg-check:[...]$0 = [1, 2, 3]
-// lldbr-check:([i32; 3]) a = [1, 2, 3]
+// lldbg-check:[...]$0 = { [0] = 1 [1] = 2 [2] = 3 }
+// lldbr-check:([i32; 3]) a = { [0] = 1 [1] = 2 [2] = 3 }
 
 #![allow(unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
diff --git a/src/test/mir-opt/const_prop/bad_op_div_by_zero/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_div_by_zero/rustc.main.ConstProp.diff
index 333bf0e320b..de06e5334e0 100644
--- a/src/test/mir-opt/const_prop/bad_op_div_by_zero/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/bad_op_div_by_zero/rustc.main.ConstProp.diff
@@ -59,7 +59,7 @@
                                            // mir::Constant
                                            // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19
 -                                          // + literal: Const { ty: i32, val: Value(Scalar(0xffffffff)) }
--         _6 = Eq(const 1i32, const std::i32::MIN); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
+-         _6 = Eq(const 1i32, const i32::MIN); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
 +         _6 = const false;                // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19
                                            // ty::Const
diff --git a/src/test/mir-opt/const_prop/bad_op_mod_by_zero/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_mod_by_zero/rustc.main.ConstProp.diff
index c081b46366e..7052c838704 100644
--- a/src/test/mir-opt/const_prop/bad_op_mod_by_zero/rustc.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/bad_op_mod_by_zero/rustc.main.ConstProp.diff
@@ -59,7 +59,7 @@
                                            // mir::Constant
                                            // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
 -                                          // + literal: Const { ty: i32, val: Value(Scalar(0xffffffff)) }
--         _6 = Eq(const 1i32, const std::i32::MIN); // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
+-         _6 = Eq(const 1i32, const i32::MIN); // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
 +                                          // + literal: Const { ty: bool, val: Value(Scalar(0x00)) }
 +         _6 = const false;                // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19
                                            // ty::Const
diff --git a/src/test/mir-opt/simplify-arm/rustc.id.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify-arm/rustc.id.SimplifyArmIdentity.diff
index 8d08267d75b..8bb28206964 100644
--- a/src/test/mir-opt/simplify-arm/rustc.id.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/simplify-arm/rustc.id.SimplifyArmIdentity.diff
@@ -26,15 +26,14 @@
       }
   
       bb3: {
--         StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:11:14: 11:15
--         _3 = ((_1 as Some).0: u8);       // scope 0 at $DIR/simplify-arm.rs:11:14: 11:15
--         StorageLive(_4);                 // scope 1 at $DIR/simplify-arm.rs:11:25: 11:26
--         _4 = _3;                         // scope 1 at $DIR/simplify-arm.rs:11:25: 11:26
--         ((_0 as Some).0: u8) = move _4;  // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27
--         discriminant(_0) = 1;            // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27
--         StorageDead(_4);                 // scope 1 at $DIR/simplify-arm.rs:11:26: 11:27
--         StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:11:27: 11:28
-+         _0 = move _1;                    // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27
+          StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:11:14: 11:15
+          _3 = ((_1 as Some).0: u8);       // scope 0 at $DIR/simplify-arm.rs:11:14: 11:15
+          StorageLive(_4);                 // scope 1 at $DIR/simplify-arm.rs:11:25: 11:26
+          _4 = _3;                         // scope 1 at $DIR/simplify-arm.rs:11:25: 11:26
+          ((_0 as Some).0: u8) = move _4;  // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27
+          discriminant(_0) = 1;            // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27
+          StorageDead(_4);                 // scope 1 at $DIR/simplify-arm.rs:11:26: 11:27
+          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:11:27: 11:28
           goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6
       }
   
diff --git a/src/test/mir-opt/simplify-arm/rustc.id.SimplifyBranchSame.diff b/src/test/mir-opt/simplify-arm/rustc.id.SimplifyBranchSame.diff
index 23fa9817f80..1226b4feaf4 100644
--- a/src/test/mir-opt/simplify-arm/rustc.id.SimplifyBranchSame.diff
+++ b/src/test/mir-opt/simplify-arm/rustc.id.SimplifyBranchSame.diff
@@ -26,7 +26,14 @@
       }
   
       bb3: {
-          _0 = move _1;                    // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27
+          StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:11:14: 11:15
+          _3 = ((_1 as Some).0: u8);       // scope 0 at $DIR/simplify-arm.rs:11:14: 11:15
+          StorageLive(_4);                 // scope 1 at $DIR/simplify-arm.rs:11:25: 11:26
+          _4 = _3;                         // scope 1 at $DIR/simplify-arm.rs:11:25: 11:26
+          ((_0 as Some).0: u8) = move _4;  // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27
+          discriminant(_0) = 1;            // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27
+          StorageDead(_4);                 // scope 1 at $DIR/simplify-arm.rs:11:26: 11:27
+          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:11:27: 11:28
           goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6
       }
   
diff --git a/src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyArmIdentity.diff
index e2a12ca5be2..5a5d67b36d9 100644
--- a/src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyArmIdentity.diff
@@ -22,15 +22,14 @@
       }
   
       bb1: {
--         StorageLive(_5);                 // scope 0 at $DIR/simplify-arm.rs:19:13: 19:14
--         _5 = ((_1 as Err).0: i32);       // scope 0 at $DIR/simplify-arm.rs:19:13: 19:14
--         StorageLive(_6);                 // scope 2 at $DIR/simplify-arm.rs:19:23: 19:24
--         _6 = _5;                         // scope 2 at $DIR/simplify-arm.rs:19:23: 19:24
--         ((_0 as Err).0: i32) = move _6;  // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25
--         discriminant(_0) = 1;            // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25
--         StorageDead(_6);                 // scope 2 at $DIR/simplify-arm.rs:19:24: 19:25
--         StorageDead(_5);                 // scope 0 at $DIR/simplify-arm.rs:19:25: 19:26
-+         _0 = move _1;                    // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25
+          StorageLive(_5);                 // scope 0 at $DIR/simplify-arm.rs:19:13: 19:14
+          _5 = ((_1 as Err).0: i32);       // scope 0 at $DIR/simplify-arm.rs:19:13: 19:14
+          StorageLive(_6);                 // scope 2 at $DIR/simplify-arm.rs:19:23: 19:24
+          _6 = _5;                         // scope 2 at $DIR/simplify-arm.rs:19:23: 19:24
+          ((_0 as Err).0: i32) = move _6;  // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25
+          discriminant(_0) = 1;            // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25
+          StorageDead(_6);                 // scope 2 at $DIR/simplify-arm.rs:19:24: 19:25
+          StorageDead(_5);                 // scope 0 at $DIR/simplify-arm.rs:19:25: 19:26
           goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6
       }
   
@@ -39,15 +38,14 @@
       }
   
       bb3: {
--         StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:18:12: 18:13
--         _3 = ((_1 as Ok).0: u8);         // scope 0 at $DIR/simplify-arm.rs:18:12: 18:13
--         StorageLive(_4);                 // scope 1 at $DIR/simplify-arm.rs:18:21: 18:22
--         _4 = _3;                         // scope 1 at $DIR/simplify-arm.rs:18:21: 18:22
--         ((_0 as Ok).0: u8) = move _4;    // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23
--         discriminant(_0) = 0;            // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23
--         StorageDead(_4);                 // scope 1 at $DIR/simplify-arm.rs:18:22: 18:23
--         StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:18:23: 18:24
-+         _0 = move _1;                    // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23
+          StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:18:12: 18:13
+          _3 = ((_1 as Ok).0: u8);         // scope 0 at $DIR/simplify-arm.rs:18:12: 18:13
+          StorageLive(_4);                 // scope 1 at $DIR/simplify-arm.rs:18:21: 18:22
+          _4 = _3;                         // scope 1 at $DIR/simplify-arm.rs:18:21: 18:22
+          ((_0 as Ok).0: u8) = move _4;    // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23
+          discriminant(_0) = 0;            // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23
+          StorageDead(_4);                 // scope 1 at $DIR/simplify-arm.rs:18:22: 18:23
+          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:18:23: 18:24
           goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6
       }
   
diff --git a/src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyBranchSame.diff b/src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyBranchSame.diff
index 9d1ff22dc51..e8286516261 100644
--- a/src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyBranchSame.diff
+++ b/src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyBranchSame.diff
@@ -18,27 +18,38 @@
   
       bb0: {
           _2 = discriminant(_1);           // scope 0 at $DIR/simplify-arm.rs:18:9: 18:14
--         switchInt(move _2) -> [0isize: bb3, 1isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:18:9: 18:14
-+         goto -> bb1;                     // scope 0 at $DIR/simplify-arm.rs:18:9: 18:14
+          switchInt(move _2) -> [0isize: bb3, 1isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:18:9: 18:14
       }
   
       bb1: {
--         _0 = move _1;                    // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25
--         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6
--     }
-- 
--     bb2: {
--         unreachable;                     // scope 0 at $DIR/simplify-arm.rs:17:11: 17:12
--     }
-- 
--     bb3: {
-          _0 = move _1;                    // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23
--         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6
-+         goto -> bb2;                     // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6
+          StorageLive(_5);                 // scope 0 at $DIR/simplify-arm.rs:19:13: 19:14
+          _5 = ((_1 as Err).0: i32);       // scope 0 at $DIR/simplify-arm.rs:19:13: 19:14
+          StorageLive(_6);                 // scope 2 at $DIR/simplify-arm.rs:19:23: 19:24
+          _6 = _5;                         // scope 2 at $DIR/simplify-arm.rs:19:23: 19:24
+          ((_0 as Err).0: i32) = move _6;  // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25
+          discriminant(_0) = 1;            // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25
+          StorageDead(_6);                 // scope 2 at $DIR/simplify-arm.rs:19:24: 19:25
+          StorageDead(_5);                 // scope 0 at $DIR/simplify-arm.rs:19:25: 19:26
+          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6
       }
   
--     bb4: {
-+     bb2: {
+      bb2: {
+          unreachable;                     // scope 0 at $DIR/simplify-arm.rs:17:11: 17:12
+      }
+  
+      bb3: {
+          StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:18:12: 18:13
+          _3 = ((_1 as Ok).0: u8);         // scope 0 at $DIR/simplify-arm.rs:18:12: 18:13
+          StorageLive(_4);                 // scope 1 at $DIR/simplify-arm.rs:18:21: 18:22
+          _4 = _3;                         // scope 1 at $DIR/simplify-arm.rs:18:21: 18:22
+          ((_0 as Ok).0: u8) = move _4;    // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23
+          discriminant(_0) = 0;            // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23
+          StorageDead(_4);                 // scope 1 at $DIR/simplify-arm.rs:18:22: 18:23
+          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:18:23: 18:24
+          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6
+      }
+  
+      bb4: {
           return;                          // scope 0 at $DIR/simplify-arm.rs:21:2: 21:2
       }
   }
diff --git a/src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyArmIdentity.diff
index 64b5f174300..44f475346e0 100644
--- a/src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyArmIdentity.diff
@@ -49,17 +49,16 @@
       }
   
       bb2: {
--         StorageLive(_10);                // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
--         _10 = ((_3 as Ok).0: u8);        // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
--         _2 = _10;                        // scope 5 at $DIR/simplify-arm.rs:24:13: 24:15
--         StorageDead(_10);                // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-+         _0 = move _3;                    // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
+          StorageLive(_10);                // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
+          _10 = ((_3 as Ok).0: u8);        // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
+          _2 = _10;                        // scope 5 at $DIR/simplify-arm.rs:24:13: 24:15
+          StorageDead(_10);                // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
           StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16
--         StorageLive(_11);                // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9
--         _11 = _2;                        // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9
--         ((_0 as Ok).0: u8) = move _11;   // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
--         discriminant(_0) = 0;            // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
--         StorageDead(_11);                // scope 1 at $DIR/simplify-arm.rs:25:9: 25:10
+          StorageLive(_11);                // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9
+          _11 = _2;                        // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9
+          ((_0 as Ok).0: u8) = move _11;   // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
+          discriminant(_0) = 0;            // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
+          StorageDead(_11);                // scope 1 at $DIR/simplify-arm.rs:25:9: 25:10
           StorageDead(_2);                 // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2
           goto -> bb5;                     // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
       }
diff --git a/src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyBranchSame.diff b/src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyBranchSame.diff
index 01f57bec71a..c91c55dfb04 100644
--- a/src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyBranchSame.diff
+++ b/src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyBranchSame.diff
@@ -49,8 +49,16 @@
       }
   
       bb2: {
-          _0 = move _3;                    // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
+          StorageLive(_10);                // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
+          _10 = ((_3 as Ok).0: u8);        // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
+          _2 = _10;                        // scope 5 at $DIR/simplify-arm.rs:24:13: 24:15
+          StorageDead(_10);                // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
           StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16
+          StorageLive(_11);                // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9
+          _11 = _2;                        // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9
+          ((_0 as Ok).0: u8) = move _11;   // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
+          discriminant(_0) = 0;            // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
+          StorageDead(_11);                // scope 1 at $DIR/simplify-arm.rs:25:9: 25:10
           StorageDead(_2);                 // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2
           goto -> bb5;                     // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
       }
diff --git a/src/test/mir-opt/simplify_try_if_let/rustc.{{impl}}-append.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_try_if_let/rustc.{{impl}}-append.SimplifyArmIdentity.diff
index 6ccec937b9b..7d3537d0943 100644
--- a/src/test/mir-opt/simplify_try_if_let/rustc.{{impl}}-append.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/simplify_try_if_let/rustc.{{impl}}-append.SimplifyArmIdentity.diff
@@ -80,12 +80,11 @@
           StorageLive(_8);                 // scope 1 at $DIR/simplify_try_if_let.rs:26:29: 26:39
           _8 = ((_5 as Some).0: std::ptr::NonNull<Node>); // scope 1 at $DIR/simplify_try_if_let.rs:26:29: 26:39
           StorageLive(_9);                 // scope 3 at $DIR/simplify_try_if_let.rs:28:46: 28:62
--         StorageLive(_10);                // scope 3 at $DIR/simplify_try_if_let.rs:28:51: 28:61
--         _10 = _8;                        // scope 3 at $DIR/simplify_try_if_let.rs:28:51: 28:61
--         ((_9 as Some).0: std::ptr::NonNull<Node>) = move _10; // scope 3 at $DIR/simplify_try_if_let.rs:28:46: 28:62
--         discriminant(_9) = 1;            // scope 3 at $DIR/simplify_try_if_let.rs:28:46: 28:62
--         StorageDead(_10);                // scope 3 at $DIR/simplify_try_if_let.rs:28:61: 28:62
-+         _9 = move _5;                    // scope 3 at $DIR/simplify_try_if_let.rs:28:46: 28:62
+          StorageLive(_10);                // scope 3 at $DIR/simplify_try_if_let.rs:28:51: 28:61
+          _10 = _8;                        // scope 3 at $DIR/simplify_try_if_let.rs:28:51: 28:61
+          ((_9 as Some).0: std::ptr::NonNull<Node>) = move _10; // scope 3 at $DIR/simplify_try_if_let.rs:28:46: 28:62
+          discriminant(_9) = 1;            // scope 3 at $DIR/simplify_try_if_let.rs:28:46: 28:62
+          StorageDead(_10);                // scope 3 at $DIR/simplify_try_if_let.rs:28:61: 28:62
           StorageLive(_11);                // scope 3 at $DIR/simplify_try_if_let.rs:28:25: 28:38
           StorageLive(_12);                // scope 3 at $DIR/simplify_try_if_let.rs:28:25: 28:29
           _12 = &mut _4;                   // scope 3 at $DIR/simplify_try_if_let.rs:28:25: 28:29
diff --git a/src/test/pretty/asm.pp b/src/test/pretty/asm.pp
index 1723e1cc1cb..4903050e08e 100644
--- a/src/test/pretty/asm.pp
+++ b/src/test/pretty/asm.pp
@@ -8,6 +8,7 @@ extern crate std;
 
 // pretty-mode:expanded
 // pp-exact:asm.pp
+// only-x86_64
 
 pub fn main() {
     let a: i32;
diff --git a/src/test/pretty/asm.rs b/src/test/pretty/asm.rs
index 9812f1d97e5..12c32e6721b 100644
--- a/src/test/pretty/asm.rs
+++ b/src/test/pretty/asm.rs
@@ -2,6 +2,7 @@
 
 // pretty-mode:expanded
 // pp-exact:asm.pp
+// only-x86_64
 
 pub fn main() {
     let a: i32;
diff --git a/src/test/rustdoc-ui/doctest-output.rs b/src/test/rustdoc-ui/doctest-output.rs
new file mode 100644
index 00000000000..f812263c252
--- /dev/null
+++ b/src/test/rustdoc-ui/doctest-output.rs
@@ -0,0 +1,15 @@
+// compile-flags:--test --test-args=--test-threads=1
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// check-pass
+
+//! ```
+//! assert_eq!(1 + 1, 2);
+//! ```
+
+pub mod foo {
+
+    /// ```
+    /// assert_eq!(1 + 1, 2);
+    /// ```
+    pub fn bar() {}
+}
diff --git a/src/test/rustdoc-ui/doctest-output.stdout b/src/test/rustdoc-ui/doctest-output.stdout
new file mode 100644
index 00000000000..9a55bf50196
--- /dev/null
+++ b/src/test/rustdoc-ui/doctest-output.stdout
@@ -0,0 +1,7 @@
+
+running 2 tests
+test $DIR/doctest-output.rs - (line 5) ... ok
+test $DIR/doctest-output.rs - foo::bar (line 11) ... ok
+
+test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
+
diff --git a/src/test/rustdoc/auxiliary/intra-link-proc-macro-macro.rs b/src/test/rustdoc/auxiliary/intra-link-proc-macro-macro.rs
new file mode 100644
index 00000000000..04a431d9902
--- /dev/null
+++ b/src/test/rustdoc/auxiliary/intra-link-proc-macro-macro.rs
@@ -0,0 +1,35 @@
+// force-host
+// no-prefer-dynamic
+// compile-flags: --crate-type proc-macro
+
+#![crate_type="proc-macro"]
+#![crate_name="intra_link_proc_macro_macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(DeriveA)]
+pub fn a_derive(input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_derive(DeriveB)]
+pub fn b_derive(input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_derive(DeriveTrait)]
+pub fn trait_derive(input: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_attribute]
+pub fn attr_a(input: TokenStream, _args: TokenStream) -> TokenStream {
+    input
+}
+
+#[proc_macro_attribute]
+pub fn attr_b(input: TokenStream, _args: TokenStream) -> TokenStream {
+    input
+}
diff --git a/src/test/rustdoc/auxiliary/issue-73061.rs b/src/test/rustdoc/auxiliary/issue-73061.rs
new file mode 100644
index 00000000000..e05a3bc6d91
--- /dev/null
+++ b/src/test/rustdoc/auxiliary/issue-73061.rs
@@ -0,0 +1,17 @@
+//edition:2018
+
+#![feature(type_alias_impl_trait)]
+
+pub trait Foo {
+    type X: std::future::Future<Output = ()>;
+    fn x(&self) -> Self::X;
+}
+
+pub struct F;
+
+impl Foo for F {
+    type X = impl std::future::Future<Output = ()>;
+    fn x(&self) -> Self::X {
+        async {}
+    }
+}
diff --git a/src/test/rustdoc/intra-link-proc-macro.rs b/src/test/rustdoc/intra-link-proc-macro.rs
new file mode 100644
index 00000000000..7b6ea5d60f8
--- /dev/null
+++ b/src/test/rustdoc/intra-link-proc-macro.rs
@@ -0,0 +1,27 @@
+// aux-build:intra-link-proc-macro-macro.rs
+// build-aux-docs
+#![deny(intra_doc_link_resolution_failure)]
+
+extern crate intra_link_proc_macro_macro;
+
+
+pub use intra_link_proc_macro_macro::{DeriveA, attr_a};
+use intra_link_proc_macro_macro::{DeriveB, attr_b};
+
+// @has intra_link_proc_macro/struct.Foo.html
+// @has - '//a/@href' '../intra_link_proc_macro/derive.DeriveA.html'
+// @has - '//a/@href' '../intra_link_proc_macro/attr.attr_a.html'
+// @has - '//a/@href' '../intra_link_proc_macro/trait.DeriveTrait.html'
+// @has - '//a/@href' '../intra_link_proc_macro_macro/derive.DeriveB.html'
+// @has - '//a/@href' '../intra_link_proc_macro_macro/attr.attr_b.html'
+/// Link to [DeriveA], [attr_a], [DeriveB], [attr_b], [DeriveTrait]
+pub struct Foo;
+
+// @has intra_link_proc_macro/struct.Bar.html
+// @has - '//a/@href' '../intra_link_proc_macro/derive.DeriveA.html'
+// @has - '//a/@href' '../intra_link_proc_macro/attr.attr_a.html'
+/// Link to [deriveA](derive@DeriveA) [attr](macro@attr_a)
+pub struct Bar;
+
+// this should not cause ambiguity errors
+pub trait DeriveTrait {}
diff --git a/src/test/rustdoc/issue-73061-cross-crate-opaque-assoc-type.rs b/src/test/rustdoc/issue-73061-cross-crate-opaque-assoc-type.rs
new file mode 100644
index 00000000000..2700f2370ee
--- /dev/null
+++ b/src/test/rustdoc/issue-73061-cross-crate-opaque-assoc-type.rs
@@ -0,0 +1,14 @@
+// Regression test for ICE #73061
+
+// aux-build:issue-73061.rs
+
+extern crate issue_73061;
+
+pub struct Z;
+
+impl issue_73061::Foo for Z {
+    type X = <issue_73061::F as issue_73061::Foo>::X;
+    fn x(&self) -> Self::X {
+        issue_73061::F.x()
+    }
+}
diff --git a/src/test/rustdoc/show-const-contents.rs b/src/test/rustdoc/show-const-contents.rs
index b35f67ef912..814339e198f 100644
--- a/src/test/rustdoc/show-const-contents.rs
+++ b/src/test/rustdoc/show-const-contents.rs
@@ -28,8 +28,8 @@ pub const CONST_CALC_I32: i32 = 42 + 1;
 // @!has show_const_contents/constant.CONST_REF_I32.html '; //'
 pub const CONST_REF_I32: &'static i32 = &42;
 
-// @has show_const_contents/constant.CONST_I32_MAX.html '= i32::max_value(); // 2_147_483_647i32'
-pub const CONST_I32_MAX: i32 = i32::max_value();
+// @has show_const_contents/constant.CONST_I32_MAX.html '= i32::MAX; // 2_147_483_647i32'
+pub const CONST_I32_MAX: i32 = i32::MAX;
 
 // @!has show_const_contents/constant.UNIT.html '= ();'
 // @!has show_const_contents/constant.UNIT.html '; //'
@@ -56,11 +56,11 @@ pub use std::i32::MAX;
 
 macro_rules! int_module {
     ($T:ident) => (
-        pub const MIN: $T = $T::min_value();
+        pub const MIN: $T = $T::MIN;
     )
 }
 
-// @has show_const_contents/constant.MIN.html '= i16::min_value(); // -32_768i16'
+// @has show_const_contents/constant.MIN.html '= i16::MIN; // -32_768i16'
 int_module!(i16);
 
 // @has show_const_contents/constant.ESCAPE.html //pre '= r#"<script>alert("ESCAPE");</script>"#;'
diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
index cef600bed5f..6da26e6cfbe 100644
--- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
+++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
@@ -84,9 +84,9 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
             2 => {
                 let seg = PathSegment::from_ident(Ident::from_str("x"));
                 iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall(
-                            seg.clone(), vec![e, make_x()])));
+                            seg.clone(), vec![e, make_x()], DUMMY_SP)));
                 iter_exprs(depth - 1, &mut |e| g(ExprKind::MethodCall(
-                            seg.clone(), vec![make_x(), e])));
+                            seg.clone(), vec![make_x(), e], DUMMY_SP)));
             },
             3..=8 => {
                 let op = Spanned {
diff --git a/src/test/ui/asm/bad-template.rs b/src/test/ui/asm/bad-template.rs
index 0b333eca1ab..21ce8c6236d 100644
--- a/src/test/ui/asm/bad-template.rs
+++ b/src/test/ui/asm/bad-template.rs
@@ -22,5 +22,7 @@ fn main() {
         //~^ ERROR invalid reference to argument at index 0
         asm!("{:foo}", in(reg) foo);
         //~^ ERROR asm template modifier must be a single character
+        asm!("", in(reg) 0, in(reg) 1);
+        //~^ ERROR multiple unused asm arguments
     }
 }
diff --git a/src/test/ui/asm/bad-template.stderr b/src/test/ui/asm/bad-template.stderr
index 2de76ef8241..1aea7467ed0 100644
--- a/src/test/ui/asm/bad-template.stderr
+++ b/src/test/ui/asm/bad-template.stderr
@@ -19,6 +19,8 @@ error: argument never used
    |
 LL |         asm!("{1}", in(reg) foo);
    |                     ^^^^^^^^^^^ argument never used
+   |
+   = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"`
 
 error: there is no argument named `a`
   --> $DIR/bad-template.rs:13:15
@@ -46,6 +48,8 @@ error: named argument never used
    |
 LL |         asm!("{}", a = in(reg) foo);
    |                    ^^^^^^^^^^^^^^^ named argument never used
+   |
+   = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
 
 error: invalid reference to argument at index 1
   --> $DIR/bad-template.rs:18:15
@@ -60,6 +64,8 @@ error: named argument never used
    |
 LL |         asm!("{1}", a = in(reg) foo);
    |                     ^^^^^^^^^^^^^^^ named argument never used
+   |
+   = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {a} */"`
 
 error: invalid reference to argument at index 0
   --> $DIR/bad-template.rs:21:15
@@ -82,5 +88,15 @@ error: asm template modifier must be a single character
 LL |         asm!("{:foo}", in(reg) foo);
    |                 ^^^
 
-error: aborting due to 10 previous errors
+error: multiple unused asm arguments
+  --> $DIR/bad-template.rs:25:18
+   |
+LL |         asm!("", in(reg) 0, in(reg) 1);
+   |                  ^^^^^^^^^  ^^^^^^^^^ argument never used
+   |                  |
+   |                  argument never used
+   |
+   = help: if these arguments are intentionally unused, consider using them in an asm comment: `"/* {0} {1} */"`
+
+error: aborting due to 11 previous errors
 
diff --git a/src/test/ui/asm/parse-error.stderr b/src/test/ui/asm/parse-error.stderr
index fa422f56bec..583a1057036 100644
--- a/src/test/ui/asm/parse-error.stderr
+++ b/src/test/ui/asm/parse-error.stderr
@@ -127,6 +127,8 @@ error: argument never used
    |
 LL |         asm!("{a}", a = const foo, a = const bar);
    |                                    ^^^^^^^^^^^^^ argument never used
+   |
+   = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
 
 error: explicit register arguments cannot have names
   --> $DIR/parse-error.rs:47:18
diff --git a/src/test/ui/asm/srcloc.rs b/src/test/ui/asm/srcloc.rs
index 7af6f620a98..402adc50d5b 100644
--- a/src/test/ui/asm/srcloc.rs
+++ b/src/test/ui/asm/srcloc.rs
@@ -37,5 +37,8 @@ fn main() {
 
         asm!(concat!("invalid", "_", "instruction"));
         //~^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+        asm!("movaps %xmm3, (%esi, 2)", options(att_syntax));
+        //~^ WARN: scale factor without index register is ignored
     }
 }
diff --git a/src/test/ui/asm/srcloc.stderr b/src/test/ui/asm/srcloc.stderr
index 57a4fbb9742..d5d12b00481 100644
--- a/src/test/ui/asm/srcloc.stderr
+++ b/src/test/ui/asm/srcloc.stderr
@@ -70,5 +70,17 @@ note: instantiated into assembly here
 LL |     invalid_instruction
    |     ^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+warning: scale factor without index register is ignored
+  --> $DIR/srcloc.rs:41:15
+   |
+LL |         asm!("movaps %xmm3, (%esi, 2)", options(att_syntax));
+   |               ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:23
+   |
+LL |     movaps %xmm3, (%esi, 2)
+   |                          ^
+
+error: aborting due to 6 previous errors; 1 warning emitted
 
diff --git a/src/test/ui/asm/sym.rs b/src/test/ui/asm/sym.rs
index 83a3672af49..8cff16aa75f 100644
--- a/src/test/ui/asm/sym.rs
+++ b/src/test/ui/asm/sym.rs
@@ -1,8 +1,9 @@
 // no-system-llvm
 // only-x86_64
+// only-linux
 // run-pass
 
-#![feature(asm, track_caller)]
+#![feature(asm, track_caller, thread_local)]
 
 extern "C" fn f1() -> i32 {
     111
@@ -15,9 +16,9 @@ fn f2() -> i32 {
 }
 
 macro_rules! call {
-    ($func:path) => {{
-        let result: i32;
+    ($func:path) => {
         unsafe {
+            let result: i32;
             asm!("call {}", sym $func,
                 out("rax") result,
                 out("rcx") _, out("rdx") _, out("rdi") _, out("rsi") _,
@@ -27,12 +28,53 @@ macro_rules! call {
                 out("xmm8") _, out("xmm9") _, out("xmm10") _, out("xmm11") _,
                 out("xmm12") _, out("xmm13") _, out("xmm14") _, out("xmm15") _,
             );
+            result
         }
-        result
-    }}
+    }
 }
 
+macro_rules! static_addr {
+    ($s:expr) => {
+        unsafe {
+            let result: *const u32;
+            // LEA performs a RIP-relative address calculation and returns the address
+            asm!("lea {}, [rip + {}]", out(reg) result, sym $s);
+            result
+        }
+    }
+}
+macro_rules! static_tls_addr {
+    ($s:expr) => {
+        unsafe {
+            let result: *const u32;
+            asm!(
+                "
+                    # Load TLS base address
+                    mov {out}, qword ptr fs:[0]
+                    # Calculate the address of sym in the TLS block. The @tpoff
+                    # relocation gives the offset of the symbol from the start
+                    # of the TLS block.
+                    lea {out}, [{out} + {sym}@tpoff]
+                ",
+                out = out(reg) result,
+                sym = sym $s
+            );
+            result
+        }
+    }
+}
+
+static S1: u32 = 111;
+#[thread_local]
+static S2: u32 = 222;
+
 fn main() {
     assert_eq!(call!(f1), 111);
     assert_eq!(call!(f2), 222);
+    assert_eq!(static_addr!(S1), &S1 as *const u32);
+    assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
+    std::thread::spawn(|| {
+        assert_eq!(static_addr!(S1), &S1 as *const u32);
+        assert_eq!(static_tls_addr!(S2), &S2 as *const u32);
+    });
 }
diff --git a/src/test/ui/associated-type-bounds/duplicate.rs b/src/test/ui/associated-type-bounds/duplicate.rs
index 8b396f23efd..8b5c5219430 100644
--- a/src/test/ui/associated-type-bounds/duplicate.rs
+++ b/src/test/ui/associated-type-bounds/duplicate.rs
@@ -108,18 +108,12 @@ type TAW3<T> where T: Iterator<Item: 'static, Item: 'static> = T;
 type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
 //~^ ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
 //~| ERROR could not find defining uses
-//~| ERROR could not find defining uses
-//~| ERROR could not find defining uses
 type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
 //~^ ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
 //~| ERROR could not find defining uses
-//~| ERROR could not find defining uses
-//~| ERROR could not find defining uses
 type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
 //~^ ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
 //~| ERROR could not find defining uses
-//~| ERROR could not find defining uses
-//~| ERROR could not find defining uses
 type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
 //~^ ERROR the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified [E0719]
 //~| ERROR could not find defining uses
diff --git a/src/test/ui/associated-type-bounds/duplicate.stderr b/src/test/ui/associated-type-bounds/duplicate.stderr
index 71f6e4ff8b6..712211e60cb 100644
--- a/src/test/ui/associated-type-bounds/duplicate.stderr
+++ b/src/test/ui/associated-type-bounds/duplicate.stderr
@@ -224,30 +224,6 @@ LL | fn FAPIT3(_: impl Iterator<Item: 'static, Item: 'static>) {}
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:62:42
-   |
-LL | fn FRPIT1() -> impl Iterator<Item: Copy, Item: Send> { iter::empty() }
-   |                              ----------  ^^^^^^^^^^ re-bound here
-   |                              |
-   |                              `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:64:42
-   |
-LL | fn FRPIT2() -> impl Iterator<Item: Copy, Item: Copy> { iter::empty() }
-   |                              ----------  ^^^^^^^^^^ re-bound here
-   |                              |
-   |                              `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:66:45
-   |
-LL | fn FRPIT3() -> impl Iterator<Item: 'static, Item: 'static> { iter::empty() }
-   |                              -------------  ^^^^^^^^^^^^^ re-bound here
-   |                              |
-   |                              `Item` bound here first
-
-error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
   --> $DIR/duplicate.rs:75:39
    |
 LL | const CIT1: impl Iterator<Item: Copy, Item: Send> = iter::empty();
@@ -367,12 +343,6 @@ LL | type TAW3<T> where T: Iterator<Item: 'static, Item: 'static> = T;
    |                                |
    |                                `Item` bound here first
 
-error: could not find defining uses
-  --> $DIR/duplicate.rs:108:1
-   |
-LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
   --> $DIR/duplicate.rs:108:36
    |
@@ -381,14 +351,38 @@ LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
    |                        |
    |                        `Item` bound here first
 
+error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
+  --> $DIR/duplicate.rs:62:42
+   |
+LL | fn FRPIT1() -> impl Iterator<Item: Copy, Item: Send> { iter::empty() }
+   |                              ----------  ^^^^^^^^^^ re-bound here
+   |                              |
+   |                              `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
+  --> $DIR/duplicate.rs:64:42
+   |
+LL | fn FRPIT2() -> impl Iterator<Item: Copy, Item: Copy> { iter::empty() }
+   |                              ----------  ^^^^^^^^^^ re-bound here
+   |                              |
+   |                              `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
+  --> $DIR/duplicate.rs:66:45
+   |
+LL | fn FRPIT3() -> impl Iterator<Item: 'static, Item: 'static> { iter::empty() }
+   |                              -------------  ^^^^^^^^^^^^^ re-bound here
+   |                              |
+   |                              `Item` bound here first
+
 error: could not find defining uses
-  --> $DIR/duplicate.rs:113:1
+  --> $DIR/duplicate.rs:108:51
    |
-LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
+   |                                                   ^^^^^^^^^
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:113:36
+  --> $DIR/duplicate.rs:111:36
    |
 LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -396,13 +390,13 @@ LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
    |                        `Item` bound here first
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:118:1
+  --> $DIR/duplicate.rs:111:51
    |
-LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
+   |                                                   ^^^^^^^^^
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:118:39
+  --> $DIR/duplicate.rs:114:39
    |
 LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
    |                        -------------  ^^^^^^^^^^^^^ re-bound here
@@ -410,13 +404,19 @@ LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
    |                        `Item` bound here first
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:123:1
+  --> $DIR/duplicate.rs:114:57
+   |
+LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
+   |                                                         ^^^^^^^^^
+
+error: could not find defining uses
+  --> $DIR/duplicate.rs:117:14
    |
 LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:123:40
+  --> $DIR/duplicate.rs:117:40
    |
 LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -424,13 +424,13 @@ LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
    |                            `Item` bound here first
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:128:1
+  --> $DIR/duplicate.rs:122:14
    |
 LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:128:40
+  --> $DIR/duplicate.rs:122:40
    |
 LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -438,13 +438,13 @@ LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
    |                            `Item` bound here first
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:133:1
+  --> $DIR/duplicate.rs:127:14
    |
 LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:133:43
+  --> $DIR/duplicate.rs:127:43
    |
 LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
    |                            -------------  ^^^^^^^^^^^^^ re-bound here
@@ -452,7 +452,7 @@ LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:139:36
+  --> $DIR/duplicate.rs:133:36
    |
 LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -460,7 +460,7 @@ LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:141:36
+  --> $DIR/duplicate.rs:135:36
    |
 LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {}
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -468,7 +468,7 @@ LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {}
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:143:39
+  --> $DIR/duplicate.rs:137:39
    |
 LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {}
    |                        -------------  ^^^^^^^^^^^^^ re-bound here
@@ -476,7 +476,7 @@ LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {}
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:145:34
+  --> $DIR/duplicate.rs:139:34
    |
 LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -484,7 +484,7 @@ LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:147:34
+  --> $DIR/duplicate.rs:141:34
    |
 LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -492,7 +492,7 @@ LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:149:37
+  --> $DIR/duplicate.rs:143:37
    |
 LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
    |                      -------------  ^^^^^^^^^^^^^ re-bound here
@@ -500,7 +500,7 @@ LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:151:45
+  --> $DIR/duplicate.rs:145:45
    |
 LL | trait TRW1<T> where T: Iterator<Item: Copy, Item: Send> {}
    |                                 ----------  ^^^^^^^^^^ re-bound here
@@ -508,7 +508,7 @@ LL | trait TRW1<T> where T: Iterator<Item: Copy, Item: Send> {}
    |                                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:153:45
+  --> $DIR/duplicate.rs:147:45
    |
 LL | trait TRW2<T> where T: Iterator<Item: Copy, Item: Copy> {}
    |                                 ----------  ^^^^^^^^^^ re-bound here
@@ -516,7 +516,7 @@ LL | trait TRW2<T> where T: Iterator<Item: Copy, Item: Copy> {}
    |                                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:155:48
+  --> $DIR/duplicate.rs:149:48
    |
 LL | trait TRW3<T> where T: Iterator<Item: 'static, Item: 'static> {}
    |                                 -------------  ^^^^^^^^^^^^^ re-bound here
@@ -524,7 +524,7 @@ LL | trait TRW3<T> where T: Iterator<Item: 'static, Item: 'static> {}
    |                                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:157:46
+  --> $DIR/duplicate.rs:151:46
    |
 LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
    |                                  ----------  ^^^^^^^^^^ re-bound here
@@ -532,7 +532,7 @@ LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:157:46
+  --> $DIR/duplicate.rs:151:46
    |
 LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
    |                                  ----------  ^^^^^^^^^^ re-bound here
@@ -540,7 +540,7 @@ LL | trait TRSW1 where Self: Iterator<Item: Copy, Item: Send> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:160:46
+  --> $DIR/duplicate.rs:154:46
    |
 LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
    |                                  ----------  ^^^^^^^^^^ re-bound here
@@ -548,7 +548,7 @@ LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:160:46
+  --> $DIR/duplicate.rs:154:46
    |
 LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
    |                                  ----------  ^^^^^^^^^^ re-bound here
@@ -556,7 +556,7 @@ LL | trait TRSW2 where Self: Iterator<Item: Copy, Item: Copy> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:163:49
+  --> $DIR/duplicate.rs:157:49
    |
 LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
    |                                  -------------  ^^^^^^^^^^^^^ re-bound here
@@ -564,7 +564,7 @@ LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:163:49
+  --> $DIR/duplicate.rs:157:49
    |
 LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
    |                                  -------------  ^^^^^^^^^^^^^ re-bound here
@@ -572,7 +572,7 @@ LL | trait TRSW3 where Self: Iterator<Item: 'static, Item: 'static> {}
    |                                  `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:166:43
+  --> $DIR/duplicate.rs:160:43
    |
 LL | trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; }
    |                               ----------  ^^^^^^^^^^ re-bound here
@@ -580,7 +580,7 @@ LL | trait TRA1 { type A: Iterator<Item: Copy, Item: Send>; }
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:168:43
+  --> $DIR/duplicate.rs:162:43
    |
 LL | trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; }
    |                               ----------  ^^^^^^^^^^ re-bound here
@@ -588,7 +588,7 @@ LL | trait TRA2 { type A: Iterator<Item: Copy, Item: Copy>; }
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:170:46
+  --> $DIR/duplicate.rs:164:46
    |
 LL | trait TRA3 { type A: Iterator<Item: 'static, Item: 'static>; }
    |                               -------------  ^^^^^^^^^^^^^ re-bound here
@@ -596,7 +596,7 @@ LL | trait TRA3 { type A: Iterator<Item: 'static, Item: 'static>; }
    |                               `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:173:40
+  --> $DIR/duplicate.rs:167:40
    |
 LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -604,7 +604,7 @@ LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:177:44
+  --> $DIR/duplicate.rs:171:44
    |
 LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
    |                                ----------  ^^^^^^^^^^ re-bound here
@@ -612,7 +612,7 @@ LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
    |                                `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified
-  --> $DIR/duplicate.rs:181:43
+  --> $DIR/duplicate.rs:175:43
    |
 LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
    |                            -------------  ^^^^^^^^^^^^^ re-bound here
@@ -620,113 +620,77 @@ LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
    |                            `Item` bound here first
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:108:24
-   |
-LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
-   |                        ^^^^^^^^^^
-
-error: could not find defining uses
-  --> $DIR/duplicate.rs:108:36
-   |
-LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
-   |                                    ^^^^^^^^^^
-
-error: could not find defining uses
-  --> $DIR/duplicate.rs:113:24
-   |
-LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
-   |                        ^^^^^^^^^^
-
-error: could not find defining uses
-  --> $DIR/duplicate.rs:113:36
-   |
-LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
-   |                                    ^^^^^^^^^^
-
-error: could not find defining uses
-  --> $DIR/duplicate.rs:118:24
-   |
-LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
-   |                        ^^^^^^^^^^^^^
-
-error: could not find defining uses
-  --> $DIR/duplicate.rs:118:39
-   |
-LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
-   |                                       ^^^^^^^^^^^^^
-
-error: could not find defining uses
-  --> $DIR/duplicate.rs:123:28
+  --> $DIR/duplicate.rs:117:28
    |
 LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
    |                            ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:123:40
+  --> $DIR/duplicate.rs:117:40
    |
 LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
    |                                        ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:128:28
+  --> $DIR/duplicate.rs:122:28
    |
 LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
    |                            ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:128:40
+  --> $DIR/duplicate.rs:122:40
    |
 LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
    |                                        ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:133:28
+  --> $DIR/duplicate.rs:127:28
    |
 LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
    |                            ^^^^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:133:43
+  --> $DIR/duplicate.rs:127:43
    |
 LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
    |                                           ^^^^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:173:28
+  --> $DIR/duplicate.rs:167:28
    |
 LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
    |                            ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:173:40
+  --> $DIR/duplicate.rs:167:40
    |
 LL | type TADyn1 = dyn Iterator<Item: Copy, Item: Send>;
    |                                        ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:177:32
+  --> $DIR/duplicate.rs:171:32
    |
 LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
    |                                ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:177:44
+  --> $DIR/duplicate.rs:171:44
    |
 LL | type TADyn2 = Box<dyn Iterator<Item: Copy, Item: Copy>>;
    |                                            ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:181:28
+  --> $DIR/duplicate.rs:175:28
    |
 LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
    |                            ^^^^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/duplicate.rs:181:43
+  --> $DIR/duplicate.rs:175:43
    |
 LL | type TADyn3 = dyn Iterator<Item: 'static, Item: 'static>;
    |                                           ^^^^^^^^^^^^^
 
-error: aborting due to 96 previous errors; 1 warning emitted
+error: aborting due to 90 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0719`.
diff --git a/src/test/ui/async-await/issue-69446-fnmut-capture.rs b/src/test/ui/async-await/issue-69446-fnmut-capture.rs
new file mode 100644
index 00000000000..842115538c9
--- /dev/null
+++ b/src/test/ui/async-await/issue-69446-fnmut-capture.rs
@@ -0,0 +1,22 @@
+// Regression test for issue #69446 - we should display
+// which variable is captured
+// edition:2018
+
+use core::future::Future;
+
+struct Foo;
+impl Foo {
+    fn foo(&mut self) {}
+}
+
+async fn bar<T>(_: impl FnMut() -> T)
+where
+    T: Future<Output = ()>,
+{}
+
+fn main() {
+    let mut x = Foo;
+    bar(move || async { //~ ERROR captured
+        x.foo();
+    });
+}
diff --git a/src/test/ui/async-await/issue-69446-fnmut-capture.stderr b/src/test/ui/async-await/issue-69446-fnmut-capture.stderr
new file mode 100644
index 00000000000..3d2b0402bc5
--- /dev/null
+++ b/src/test/ui/async-await/issue-69446-fnmut-capture.stderr
@@ -0,0 +1,19 @@
+error: captured variable cannot escape `FnMut` closure body
+  --> $DIR/issue-69446-fnmut-capture.rs:19:17
+   |
+LL |       let mut x = Foo;
+   |           ----- variable defined here
+LL |       bar(move || async {
+   |  _______________-_^
+   | |               |
+   | |               inferred to be a `FnMut` closure
+LL | |         x.foo();
+   | |         - variable captured here
+LL | |     });
+   | |_____^ returns an `async` block that contains a reference to a captured variable, which then escapes the closure body
+   |
+   = note: `FnMut` closures only have access to their captured variables while they are executing...
+   = note: ...therefore, they cannot allow references to captured variables to escape
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/async-await/issue-73050.rs b/src/test/ui/async-await/issue-73050.rs
new file mode 100644
index 00000000000..790f24a230b
--- /dev/null
+++ b/src/test/ui/async-await/issue-73050.rs
@@ -0,0 +1,12 @@
+// check-pass
+// edition:2018
+
+#[allow(unused)]
+async fn foo<'a>() {
+    let _data = &mut [0u8; { 1 + 4 }];
+    bar().await
+}
+
+async fn bar() {}
+
+fn main() {}
diff --git a/src/test/ui/binop/binop-consume-args.stderr b/src/test/ui/binop/binop-consume-args.stderr
index acdc03e3726..addc8a0efe1 100644
--- a/src/test/ui/binop/binop-consume-args.stderr
+++ b/src/test/ui/binop/binop-consume-args.stderr
@@ -4,10 +4,15 @@ error[E0382]: use of moved value: `lhs`
 LL | fn add<A: Add<B, Output=()>, B>(lhs: A, rhs: B) {
    |                                 --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
 LL |     lhs + rhs;
-   |     --- value moved here
+   |     --------- `lhs` moved due to usage in operator
 LL |     drop(lhs);
    |          ^^^ value used here after move
    |
+note: calling this operator moves the left-hand side
+  --> $SRC_DIR/libcore/ops/arith.rs:LL:COL
+   |
+LL |     fn add(self, rhs: Rhs) -> Self::Output;
+   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn add<A: Add<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -35,10 +40,15 @@ error[E0382]: use of moved value: `lhs`
 LL | fn sub<A: Sub<B, Output=()>, B>(lhs: A, rhs: B) {
    |                                 --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
 LL |     lhs - rhs;
-   |     --- value moved here
+   |     --------- `lhs` moved due to usage in operator
 LL |     drop(lhs);
    |          ^^^ value used here after move
    |
+note: calling this operator moves the left-hand side
+  --> $SRC_DIR/libcore/ops/arith.rs:LL:COL
+   |
+LL |     fn sub(self, rhs: Rhs) -> Self::Output;
+   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn sub<A: Sub<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -66,10 +76,15 @@ error[E0382]: use of moved value: `lhs`
 LL | fn mul<A: Mul<B, Output=()>, B>(lhs: A, rhs: B) {
    |                                 --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
 LL |     lhs * rhs;
-   |     --- value moved here
+   |     --------- `lhs` moved due to usage in operator
 LL |     drop(lhs);
    |          ^^^ value used here after move
    |
+note: calling this operator moves the left-hand side
+  --> $SRC_DIR/libcore/ops/arith.rs:LL:COL
+   |
+LL |     fn mul(self, rhs: Rhs) -> Self::Output;
+   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn mul<A: Mul<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -97,10 +112,15 @@ error[E0382]: use of moved value: `lhs`
 LL | fn div<A: Div<B, Output=()>, B>(lhs: A, rhs: B) {
    |                                 --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
 LL |     lhs / rhs;
-   |     --- value moved here
+   |     --------- `lhs` moved due to usage in operator
 LL |     drop(lhs);
    |          ^^^ value used here after move
    |
+note: calling this operator moves the left-hand side
+  --> $SRC_DIR/libcore/ops/arith.rs:LL:COL
+   |
+LL |     fn div(self, rhs: Rhs) -> Self::Output;
+   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn div<A: Div<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -128,10 +148,15 @@ error[E0382]: use of moved value: `lhs`
 LL | fn rem<A: Rem<B, Output=()>, B>(lhs: A, rhs: B) {
    |                                 --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
 LL |     lhs % rhs;
-   |     --- value moved here
+   |     --------- `lhs` moved due to usage in operator
 LL |     drop(lhs);
    |          ^^^ value used here after move
    |
+note: calling this operator moves the left-hand side
+  --> $SRC_DIR/libcore/ops/arith.rs:LL:COL
+   |
+LL |     fn rem(self, rhs: Rhs) -> Self::Output;
+   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn rem<A: Rem<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -159,10 +184,15 @@ error[E0382]: use of moved value: `lhs`
 LL | fn bitand<A: BitAnd<B, Output=()>, B>(lhs: A, rhs: B) {
    |                                       --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
 LL |     lhs & rhs;
-   |     --- value moved here
+   |     --------- `lhs` moved due to usage in operator
 LL |     drop(lhs);
    |          ^^^ value used here after move
    |
+note: calling this operator moves the left-hand side
+  --> $SRC_DIR/libcore/ops/bit.rs:LL:COL
+   |
+LL |     fn bitand(self, rhs: Rhs) -> Self::Output;
+   |               ^^^^
 help: consider further restricting this bound
    |
 LL | fn bitand<A: BitAnd<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -190,10 +220,15 @@ error[E0382]: use of moved value: `lhs`
 LL | fn bitor<A: BitOr<B, Output=()>, B>(lhs: A, rhs: B) {
    |                                     --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
 LL |     lhs | rhs;
-   |     --- value moved here
+   |     --------- `lhs` moved due to usage in operator
 LL |     drop(lhs);
    |          ^^^ value used here after move
    |
+note: calling this operator moves the left-hand side
+  --> $SRC_DIR/libcore/ops/bit.rs:LL:COL
+   |
+LL |     fn bitor(self, rhs: Rhs) -> Self::Output;
+   |              ^^^^
 help: consider further restricting this bound
    |
 LL | fn bitor<A: BitOr<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -221,10 +256,15 @@ error[E0382]: use of moved value: `lhs`
 LL | fn bitxor<A: BitXor<B, Output=()>, B>(lhs: A, rhs: B) {
    |                                       --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
 LL |     lhs ^ rhs;
-   |     --- value moved here
+   |     --------- `lhs` moved due to usage in operator
 LL |     drop(lhs);
    |          ^^^ value used here after move
    |
+note: calling this operator moves the left-hand side
+  --> $SRC_DIR/libcore/ops/bit.rs:LL:COL
+   |
+LL |     fn bitxor(self, rhs: Rhs) -> Self::Output;
+   |               ^^^^
 help: consider further restricting this bound
    |
 LL | fn bitxor<A: BitXor<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -252,10 +292,15 @@ error[E0382]: use of moved value: `lhs`
 LL | fn shl<A: Shl<B, Output=()>, B>(lhs: A, rhs: B) {
    |                                 --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
 LL |     lhs << rhs;
-   |     --- value moved here
+   |     ---------- `lhs` moved due to usage in operator
 LL |     drop(lhs);
    |          ^^^ value used here after move
    |
+note: calling this operator moves the left-hand side
+  --> $SRC_DIR/libcore/ops/bit.rs:LL:COL
+   |
+LL |     fn shl(self, rhs: Rhs) -> Self::Output;
+   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn shl<A: Shl<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
@@ -283,10 +328,15 @@ error[E0382]: use of moved value: `lhs`
 LL | fn shr<A: Shr<B, Output=()>, B>(lhs: A, rhs: B) {
    |                                 --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
 LL |     lhs >> rhs;
-   |     --- value moved here
+   |     ---------- `lhs` moved due to usage in operator
 LL |     drop(lhs);
    |          ^^^ value used here after move
    |
+note: calling this operator moves the left-hand side
+  --> $SRC_DIR/libcore/ops/bit.rs:LL:COL
+   |
+LL |     fn shr(self, rhs: Rhs) -> Self::Output;
+   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn shr<A: Shr<B, Output=()> + Copy, B>(lhs: A, rhs: B) {
diff --git a/src/test/ui/binop/binop-move-semantics.stderr b/src/test/ui/binop/binop-move-semantics.stderr
index 6d5ac9cab30..97b70efe20e 100644
--- a/src/test/ui/binop/binop-move-semantics.stderr
+++ b/src/test/ui/binop/binop-move-semantics.stderr
@@ -1,14 +1,21 @@
 error[E0382]: use of moved value: `x`
   --> $DIR/binop-move-semantics.rs:8:5
    |
-LL | fn double_move<T: Add<Output=()>>(x: T) {
-   |                                   - move occurs because `x` has type `T`, which does not implement the `Copy` trait
-LL |     x
-   |     - value moved here
-LL |     +
-LL |     x;
-   |     ^ value used here after move
+LL |   fn double_move<T: Add<Output=()>>(x: T) {
+   |                                     - move occurs because `x` has type `T`, which does not implement the `Copy` trait
+LL | /     x
+LL | |     +
+LL | |     x;
+   | |     ^
+   | |     |
+   | |_____value used here after move
+   |       `x` moved due to usage in operator
+   |
+note: calling this operator moves the left-hand side
+  --> $SRC_DIR/libcore/ops/arith.rs:LL:COL
    |
+LL |     fn add(self, rhs: Rhs) -> Self::Output;
+   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn double_move<T: Add<Output=()> + Copy>(x: T) {
diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.stderr
index 075e0e2e451..4144d70cc16 100644
--- a/src/test/ui/borrowck/borrowck-describe-lvalue.stderr
+++ b/src/test/ui/borrowck/borrowck-describe-lvalue.stderr
@@ -21,10 +21,13 @@ LL |                    *y = 1;
 error: captured variable cannot escape `FnMut` closure body
   --> $DIR/borrowck-describe-lvalue.rs:264:16
    |
+LL |           let mut x = 0;
+   |               ----- variable defined here
 LL |              || {
    |               - inferred to be a `FnMut` closure
 LL | /                || {
 LL | |                    let y = &mut x;
+   | |                                 - variable captured here
 LL | |                    &mut x;
 LL | |                    *y = 1;
 LL | |                    drop(y);
diff --git a/src/test/ui/borrowck/borrowck-unboxed-closures.stderr b/src/test/ui/borrowck/borrowck-unboxed-closures.stderr
index a51cda548ef..bc1721944fb 100644
--- a/src/test/ui/borrowck/borrowck-unboxed-closures.stderr
+++ b/src/test/ui/borrowck/borrowck-unboxed-closures.stderr
@@ -22,10 +22,15 @@ error[E0382]: use of moved value: `f`
 LL | fn c<F:FnOnce(isize, isize) -> isize>(f: F) {
    |                                       - move occurs because `f` has type `F`, which does not implement the `Copy` trait
 LL |     f(1, 2);
-   |     - value moved here
+   |     ------- `f` moved due to this call
 LL |     f(1, 2);
    |     ^ value used here after move
    |
+note: this value implements `FnOnce`, which causes it to be moved when called
+  --> $DIR/borrowck-unboxed-closures.rs:11:5
+   |
+LL |     f(1, 2);
+   |     ^
 help: consider further restricting this bound
    |
 LL | fn c<F:FnOnce(isize, isize) -> isize + Copy>(f: F) {
diff --git a/src/test/ui/closure_context/issue-42065.stderr b/src/test/ui/closure_context/issue-42065.stderr
index 69d98654048..896bb6dc6be 100644
--- a/src/test/ui/closure_context/issue-42065.stderr
+++ b/src/test/ui/closure_context/issue-42065.stderr
@@ -2,7 +2,7 @@ error[E0382]: use of moved value: `debug_dump_dict`
   --> $DIR/issue-42065.rs:11:5
    |
 LL |     debug_dump_dict();
-   |     --------------- value moved here
+   |     ----------------- `debug_dump_dict` moved due to this call
 LL |     debug_dump_dict();
    |     ^^^^^^^^^^^^^^^ value used here after move
    |
@@ -11,6 +11,11 @@ note: closure cannot be invoked more than once because it moves the variable `di
    |
 LL |         for (key, value) in dict {
    |                             ^^^^
+note: this value implements `FnOnce`, which causes it to be moved when called
+  --> $DIR/issue-42065.rs:10:5
+   |
+LL |     debug_dump_dict();
+   |     ^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/codemap_tests/tab_3.stderr b/src/test/ui/codemap_tests/tab_3.stderr
index 97816a76004..614e69e89f6 100644
--- a/src/test/ui/codemap_tests/tab_3.stderr
+++ b/src/test/ui/codemap_tests/tab_3.stderr
@@ -4,10 +4,16 @@ error[E0382]: borrow of moved value: `some_vec`
 LL |     let some_vec = vec!["hi"];
    |         -------- move occurs because `some_vec` has type `std::vec::Vec<&str>`, which does not implement the `Copy` trait
 LL |     some_vec.into_iter();
-   |     -------- value moved here
+   |              ----------- `some_vec` moved due to this method call
 LL |     {
 LL |         println!("{:?}", some_vec);
    |                          ^^^^^^^^ value borrowed here after move
+   |
+note: this function consumes the receiver `self` by taking ownership of it, which moves `some_vec`
+  --> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |                  ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/codemap_tests/unicode.stderr b/src/test/ui/codemap_tests/unicode.stderr
index 4d4440fd07f..8b85adb5845 100644
--- a/src/test/ui/codemap_tests/unicode.stderr
+++ b/src/test/ui/codemap_tests/unicode.stderr
@@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `路濫狼á́́`
 LL | extern "路濫狼á́́" fn foo() {}
    |        ^^^^^^^^^ invalid ABI
    |
-   = help: valid ABIs: Rust, C, cdecl, stdcall, fastcall, vectorcall, thiscall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
+   = help: valid ABIs: Rust, C, cdecl, stdcall, fastcall, vectorcall, thiscall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr b/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr
index 44e5c6a99f7..93e16bac13b 100644
--- a/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr
+++ b/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr
@@ -121,7 +121,7 @@ error[E0308]: mismatched types
 LL |     let _ = Box::new(|x| (x as u8)): Box<dyn Fn(i32) -> _>;
    |             ^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::ops::Fn`, found closure
    |
-   = note: expected struct `std::boxed::Box<dyn std::ops::Fn(i32) -> _>`
+   = note: expected struct `std::boxed::Box<dyn std::ops::Fn(i32) -> u8>`
               found struct `std::boxed::Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:26:22: 26:35]>`
 
 error: aborting due to 14 previous errors
diff --git a/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.rs b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.rs
new file mode 100644
index 00000000000..225593c3178
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.rs
@@ -0,0 +1,20 @@
+// Regression test for #72819: ICE due to failure in resolving the const generic in `Arr`'s type
+// bounds.
+
+#![feature(const_generics)]
+#![allow(incomplete_features)]
+struct Arr<const N: usize>
+where Assert::<{N < usize::max_value() / 2}>: IsTrue,
+//~^ ERROR constant expression depends on a generic parameter
+{
+}
+
+enum Assert<const CHECK: bool> {}
+
+trait IsTrue {}
+
+impl IsTrue for Assert<true> {}
+
+fn main() {
+    let x: Arr<{usize::max_value()}> = Arr {};
+}
diff --git a/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.stderr b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.stderr
new file mode 100644
index 00000000000..a9f664d0ac8
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-72819-generic-in-const-eval.stderr
@@ -0,0 +1,10 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/issue-72819-generic-in-const-eval.rs:7:47
+   |
+LL | where Assert::<{N < usize::max_value() / 2}>: IsTrue,
+   |                                               ^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const-eval/infinite_loop.stderr b/src/test/ui/consts/const-eval/infinite_loop.stderr
index ebdb73c4467..3386e6e588e 100644
--- a/src/test/ui/consts/const-eval/infinite_loop.stderr
+++ b/src/test/ui/consts/const-eval/infinite_loop.stderr
@@ -23,10 +23,10 @@ LL |             n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/infinite_loop.rs:8:20
+  --> $DIR/infinite_loop.rs:8:17
    |
 LL |             n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
-   |                    ^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/consts/const-eval/shift_overflow.rs b/src/test/ui/consts/const-eval/shift_overflow.rs
index f7d0f6bd961..e843584b69b 100644
--- a/src/test/ui/consts/const-eval/shift_overflow.rs
+++ b/src/test/ui/consts/const-eval/shift_overflow.rs
@@ -1,6 +1,6 @@
 enum Foo {
     // test that we detect overflows for non-u32 discriminants
-    X = 1 << ((u32::max_value() as u64) + 1), //~ ERROR E0080
+    X = 1 << ((u32::MAX as u64) + 1), //~ ERROR E0080
     Y = 42,
 }
 
diff --git a/src/test/ui/consts/const-eval/shift_overflow.stderr b/src/test/ui/consts/const-eval/shift_overflow.stderr
index 5db231cd5b0..f4840e9ac96 100644
--- a/src/test/ui/consts/const-eval/shift_overflow.stderr
+++ b/src/test/ui/consts/const-eval/shift_overflow.stderr
@@ -1,8 +1,8 @@
 error[E0080]: evaluation of constant value failed
   --> $DIR/shift_overflow.rs:3:9
    |
-LL |     X = 1 << ((u32::max_value() as u64) + 1),
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to shift left with overflow
+LL |     X = 1 << ((u32::MAX as u64) + 1),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to shift left with overflow
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-int-arithmetic.rs b/src/test/ui/consts/const-int-arithmetic.rs
index ab24abeba32..9c94551f744 100644
--- a/src/test/ui/consts/const-int-arithmetic.rs
+++ b/src/test/ui/consts/const-int-arithmetic.rs
@@ -34,8 +34,8 @@ suite!(
         C6: 5i8.checked_mul(122), None;
         C7: (-127i8).checked_mul(-99), None;
 
-        C8: (i8::min_value() + 1).checked_div(-1), Some(127);
-        C9: i8::min_value().checked_div(-1), None;
+        C8: (i8::MIN + 1).checked_div(-1), Some(127);
+        C9: i8::MIN.checked_div(-1), None;
         C10: 1i8.checked_div(0), None;
 
         C11: 5i8.checked_rem(2), Some(1);
@@ -56,8 +56,8 @@ suite!(
         C21: i8::MIN.checked_abs(), None;
 
         // `const_euclidean_int_methods`
-        C22: (i8::min_value() + 1).checked_div_euclid(-1), Some(127);
-        C23: i8::min_value().checked_div_euclid(-1), None;
+        C22: (i8::MIN + 1).checked_div_euclid(-1), Some(127);
+        C23: i8::MIN.checked_div_euclid(-1), None;
         C24: (1i8).checked_div_euclid(0), None;
 
         C25: 5i8.checked_rem_euclid(2), Some(1);
@@ -72,12 +72,12 @@ suite!(
     saturating_and_wrapping -> i8 {
         // `const_saturating_int_methods`
         C28: 100i8.saturating_add(1), 101;
-        C29: i8::max_value().saturating_add(100), i8::max_value();
-        C30: i8::min_value().saturating_add(-1), i8::min_value();
+        C29: i8::MAX.saturating_add(100), i8::MAX;
+        C30: i8::MIN.saturating_add(-1), i8::MIN;
 
         C31: 100i8.saturating_sub(127), -27;
-        C32: i8::min_value().saturating_sub(100), i8::min_value();
-        C33: i8::max_value().saturating_sub(-1), i8::max_value();
+        C32: i8::MIN.saturating_sub(100), i8::MIN;
+        C33: i8::MAX.saturating_sub(-1), i8::MAX;
 
         C34: 10i8.saturating_mul(12), 120;
         C35: i8::MAX.saturating_mul(10), i8::MAX;
@@ -85,13 +85,13 @@ suite!(
 
         C37: 100i8.saturating_neg(), -100;
         C38: (-100i8).saturating_neg(), 100;
-        C39: i8::min_value().saturating_neg(), i8::max_value();
-        C40: i8::max_value().saturating_neg(), i8::min_value() + 1;
+        C39: i8::MIN.saturating_neg(), i8::MAX;
+        C40: i8::MAX.saturating_neg(), i8::MIN + 1;
 
         C57: 100i8.saturating_abs(), 100;
         C58: (-100i8).saturating_abs(), 100;
-        C59: i8::min_value().saturating_abs(), i8::max_value();
-        C60: (i8::min_value() + 1).saturating_abs(), i8::max_value();
+        C59: i8::MIN.saturating_abs(), i8::MAX;
+        C60: (i8::MIN + 1).saturating_abs(), i8::MAX;
 
         // `const_wrapping_int_methods`
         C41: 100i8.wrapping_div(10), 10;
diff --git a/src/test/ui/consts/const-int-conversion-rpass.rs b/src/test/ui/consts/const-int-conversion-rpass.rs
index 6484169dd9a..4aaeeaa3885 100644
--- a/src/test/ui/consts/const-int-conversion-rpass.rs
+++ b/src/test/ui/consts/const-int-conversion-rpass.rs
@@ -6,13 +6,13 @@ const FROM_LE_BYTES: i32 = i32::from_le_bytes([0x12, 0x34, 0x56, 0x78]);
 const FROM_NE_BYTES: i32 = i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0]));
 const TO_BE_BYTES: [u8; 4] = 0x12_34_56_78_i32.to_be_bytes();
 const TO_LE_BYTES: [u8; 4] = 0x12_34_56_78_i32.to_le_bytes();
-const TO_NE_BYTES: [u8; 4] = i32::min_value().to_be().to_ne_bytes();
+const TO_NE_BYTES: [u8; 4] = i32::MIN.to_be().to_ne_bytes();
 
 fn main() {
     assert_eq!(REVERSE, 0x1e6a2c48);
     assert_eq!(FROM_BE_BYTES, 0x12_34_56_78);
     assert_eq!(FROM_LE_BYTES, 0x78_56_34_12);
-    assert_eq!(FROM_NE_BYTES, i32::min_value());
+    assert_eq!(FROM_NE_BYTES, i32::MIN);
     assert_eq!(TO_BE_BYTES, [0x12, 0x34, 0x56, 0x78]);
     assert_eq!(TO_LE_BYTES, [0x78, 0x56, 0x34, 0x12]);
     assert_eq!(TO_NE_BYTES, [0x80, 0, 0, 0]);
diff --git a/src/test/ui/consts/const-int-conversion.rs b/src/test/ui/consts/const-int-conversion.rs
index b80e616eae7..5a05a2b3593 100644
--- a/src/test/ui/consts/const-int-conversion.rs
+++ b/src/test/ui/consts/const-int-conversion.rs
@@ -11,6 +11,6 @@ fn main() {
         //~^ ERROR temporary value dropped while borrowed
     let c: &'static [u8] = &(0x12_34_56_78_i32.to_le_bytes());
         //~^ ERROR temporary value dropped while borrowed
-    let d: &'static [u8] = &(i32::min_value().to_be().to_ne_bytes());
+    let d: &'static [u8] = &(i32::MIN.to_be().to_ne_bytes());
         //~^ ERROR temporary value dropped while borrowed
 }
diff --git a/src/test/ui/consts/const-int-conversion.stderr b/src/test/ui/consts/const-int-conversion.stderr
index 237f9627219..61162a79226 100644
--- a/src/test/ui/consts/const-int-conversion.stderr
+++ b/src/test/ui/consts/const-int-conversion.stderr
@@ -67,8 +67,8 @@ LL | }
 error[E0716]: temporary value dropped while borrowed
   --> $DIR/const-int-conversion.rs:14:29
    |
-LL |     let d: &'static [u8] = &(i32::min_value().to_be().to_ne_bytes());
-   |            -------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+LL |     let d: &'static [u8] = &(i32::MIN.to_be().to_ne_bytes());
+   |            -------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
    |            |
    |            type annotation requires that borrow lasts for `'static`
 LL |
diff --git a/src/test/ui/consts/const-int-overflowing-rpass.rs b/src/test/ui/consts/const-int-overflowing-rpass.rs
index 9be87a6447c..eecb88becab 100644
--- a/src/test/ui/consts/const-int-overflowing-rpass.rs
+++ b/src/test/ui/consts/const-int-overflowing-rpass.rs
@@ -1,7 +1,7 @@
 // run-pass
 
 const ADD_A: (u32, bool) = 5u32.overflowing_add(2);
-const ADD_B: (u32, bool) = u32::max_value().overflowing_add(1);
+const ADD_B: (u32, bool) = u32::MAX.overflowing_add(1);
 
 const SUB_A: (u32, bool) = 5u32.overflowing_sub(2);
 const SUB_B: (u32, bool) = 0u32.overflowing_sub(1);
@@ -20,14 +20,14 @@ const NEG_B: (u32, bool) = core::u32::MAX.overflowing_neg();
 
 const ABS_POS: (i32, bool) = 10i32.overflowing_abs();
 const ABS_NEG: (i32, bool) = (-10i32).overflowing_abs();
-const ABS_MIN: (i32, bool) = i32::min_value().overflowing_abs();
+const ABS_MIN: (i32, bool) = i32::MIN.overflowing_abs();
 
 fn main() {
     assert_eq!(ADD_A, (7, false));
     assert_eq!(ADD_B, (0, true));
 
     assert_eq!(SUB_A, (3, false));
-    assert_eq!(SUB_B, (u32::max_value(), true));
+    assert_eq!(SUB_B, (u32::MAX, true));
 
     assert_eq!(MUL_A, (10, false));
     assert_eq!(MUL_B, (1410065408, true));
@@ -43,5 +43,5 @@ fn main() {
 
     assert_eq!(ABS_POS, (10, false));
     assert_eq!(ABS_NEG, (10, false));
-    assert_eq!(ABS_MIN, (i32::min_value(), true));
+    assert_eq!(ABS_MIN, (i32::MIN, true));
 }
diff --git a/src/test/ui/consts/const-int-pow-rpass.rs b/src/test/ui/consts/const-int-pow-rpass.rs
index b0fba19455b..4f936236dbb 100644
--- a/src/test/ui/consts/const-int-pow-rpass.rs
+++ b/src/test/ui/consts/const-int-pow-rpass.rs
@@ -20,10 +20,10 @@ const NEXT_POWER_OF_TWO: u32 = 3u32.next_power_of_two();
 
 const CHECKED_NEXT_POWER_OF_TWO_OK: Option<u32> = 3u32.checked_next_power_of_two();
 const CHECKED_NEXT_POWER_OF_TWO_OVERFLOW: Option<u32> =
-    u32::max_value().checked_next_power_of_two();
+    u32::MAX.checked_next_power_of_two();
 
 const WRAPPING_NEXT_POWER_OF_TWO: u32 =
-    u32::max_value().wrapping_next_power_of_two();
+    u32::MAX.wrapping_next_power_of_two();
 
 fn main() {
     assert!(!IS_POWER_OF_TWO_A);
@@ -37,7 +37,7 @@ fn main() {
 
     assert_eq!(WRAPPING_POW, 217);
     assert_eq!(OVERFLOWING_POW, (217, true));
-    assert_eq!(SATURATING_POW, u8::max_value());
+    assert_eq!(SATURATING_POW, u8::MAX);
 
     assert_eq!(NEXT_POWER_OF_TWO, 4);
 
diff --git a/src/test/ui/consts/const-int-saturating-arith.rs b/src/test/ui/consts/const-int-saturating-arith.rs
index d0a3eccd177..4718120a51b 100644
--- a/src/test/ui/consts/const-int-saturating-arith.rs
+++ b/src/test/ui/consts/const-int-saturating-arith.rs
@@ -2,33 +2,33 @@
 #![feature(const_saturating_int_methods)]
 
 const INT_U32_NO: u32 = (42 as u32).saturating_add(2);
-const INT_U32: u32 = u32::max_value().saturating_add(1);
-const INT_U128: u128 = u128::max_value().saturating_add(1);
-const INT_I128: i128 = i128::max_value().saturating_add(1);
-const INT_I128_NEG: i128 = i128::min_value().saturating_add(-1);
+const INT_U32: u32 = u32::MAX.saturating_add(1);
+const INT_U128: u128 = u128::MAX.saturating_add(1);
+const INT_I128: i128 = i128::MAX.saturating_add(1);
+const INT_I128_NEG: i128 = i128::MIN.saturating_add(-1);
 
 const INT_U32_NO_SUB: u32 = (42 as u32).saturating_sub(2);
 const INT_U32_SUB: u32 = (1 as u32).saturating_sub(2);
 const INT_I32_NO_SUB: i32 = (-42 as i32).saturating_sub(2);
-const INT_I32_NEG_SUB: i32 = i32::min_value().saturating_sub(1);
-const INT_I32_POS_SUB: i32 = i32::max_value().saturating_sub(-1);
+const INT_I32_NEG_SUB: i32 = i32::MIN.saturating_sub(1);
+const INT_I32_POS_SUB: i32 = i32::MAX.saturating_sub(-1);
 const INT_U128_SUB: u128 = (0 as u128).saturating_sub(1);
-const INT_I128_NEG_SUB: i128 = i128::min_value().saturating_sub(1);
-const INT_I128_POS_SUB: i128 = i128::max_value().saturating_sub(-1);
+const INT_I128_NEG_SUB: i128 = i128::MIN.saturating_sub(1);
+const INT_I128_POS_SUB: i128 = i128::MAX.saturating_sub(-1);
 
 fn main() {
     assert_eq!(INT_U32_NO, 44);
-    assert_eq!(INT_U32, u32::max_value());
-    assert_eq!(INT_U128, u128::max_value());
-    assert_eq!(INT_I128, i128::max_value());
-    assert_eq!(INT_I128_NEG, i128::min_value());
+    assert_eq!(INT_U32, u32::MAX);
+    assert_eq!(INT_U128, u128::MAX);
+    assert_eq!(INT_I128, i128::MAX);
+    assert_eq!(INT_I128_NEG, i128::MIN);
 
     assert_eq!(INT_U32_NO_SUB, 40);
     assert_eq!(INT_U32_SUB, 0);
     assert_eq!(INT_I32_NO_SUB, -44);
-    assert_eq!(INT_I32_NEG_SUB, i32::min_value());
-    assert_eq!(INT_I32_POS_SUB, i32::max_value());
+    assert_eq!(INT_I32_NEG_SUB, i32::MIN);
+    assert_eq!(INT_I32_POS_SUB, i32::MAX);
     assert_eq!(INT_U128_SUB, 0);
-    assert_eq!(INT_I128_NEG_SUB, i128::min_value());
-    assert_eq!(INT_I128_POS_SUB, i128::max_value());
+    assert_eq!(INT_I128_NEG_SUB, i128::MIN);
+    assert_eq!(INT_I128_POS_SUB, i128::MAX);
 }
diff --git a/src/test/ui/consts/const-int-unchecked.rs b/src/test/ui/consts/const-int-unchecked.rs
index fb09f62854d..1596093b2c1 100644
--- a/src/test/ui/consts/const-int-unchecked.rs
+++ b/src/test/ui/consts/const-int-unchecked.rs
@@ -131,12 +131,12 @@ const _: u16 = unsafe { std::intrinsics::unchecked_mul(300u16, 250u16) };
 
 const _: i32 = unsafe { std::intrinsics::unchecked_div(1, 0) };
 //~^ ERROR any use of this value will cause an error
-const _: i32 = unsafe { std::intrinsics::unchecked_div(i32::min_value(), -1) };
+const _: i32 = unsafe { std::intrinsics::unchecked_div(i32::MIN, -1) };
 //~^ ERROR any use of this value will cause an error
 
 const _: i32 = unsafe { std::intrinsics::unchecked_rem(1, 0) };
 //~^ ERROR any use of this value will cause an error
-const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::min_value(), -1) };
+const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::MIN, -1) };
 //~^ ERROR any use of this value will cause an error
 
 fn main() {}
diff --git a/src/test/ui/consts/const-int-unchecked.stderr b/src/test/ui/consts/const-int-unchecked.stderr
index cf70454b6bf..0287b404e7d 100644
--- a/src/test/ui/consts/const-int-unchecked.stderr
+++ b/src/test/ui/consts/const-int-unchecked.stderr
@@ -355,8 +355,8 @@ LL | const _: i32 = unsafe { std::intrinsics::unchecked_div(1, 0) };
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:134:25
    |
-LL | const _: i32 = unsafe { std::intrinsics::unchecked_div(i32::min_value(), -1) };
-   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+LL | const _: i32 = unsafe { std::intrinsics::unchecked_div(i32::MIN, -1) };
+   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                         |
    |                         overflow executing `unchecked_div`
 
@@ -371,8 +371,8 @@ LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(1, 0) };
 error: any use of this value will cause an error
   --> $DIR/const-int-unchecked.rs:139:25
    |
-LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::min_value(), -1) };
-   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
+LL | const _: i32 = unsafe { std::intrinsics::unchecked_rem(i32::MIN, -1) };
+   | ------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---
    |                         |
    |                         overflow executing `unchecked_rem`
 
diff --git a/src/test/ui/consts/const-int-wrapping-rpass.rs b/src/test/ui/consts/const-int-wrapping-rpass.rs
index 2bbad99a52a..225d1e9393d 100644
--- a/src/test/ui/consts/const-int-wrapping-rpass.rs
+++ b/src/test/ui/consts/const-int-wrapping-rpass.rs
@@ -1,10 +1,10 @@
 // run-pass
 
 const ADD_A: u32 = 200u32.wrapping_add(55);
-const ADD_B: u32 = 200u32.wrapping_add(u32::max_value());
+const ADD_B: u32 = 200u32.wrapping_add(u32::MAX);
 
 const SUB_A: u32 = 100u32.wrapping_sub(100);
-const SUB_B: u32 = 100u32.wrapping_sub(u32::max_value());
+const SUB_B: u32 = 100u32.wrapping_sub(u32::MAX);
 
 const MUL_A: u8 = 10u8.wrapping_mul(12);
 const MUL_B: u8 = 25u8.wrapping_mul(12);
@@ -20,7 +20,7 @@ const NEG_B: u32 = 1234567890u32.wrapping_neg();
 
 const ABS_POS: i32 = 10i32.wrapping_abs();
 const ABS_NEG: i32 = (-10i32).wrapping_abs();
-const ABS_MIN: i32 = i32::min_value().wrapping_abs();
+const ABS_MIN: i32 = i32::MIN.wrapping_abs();
 
 fn main() {
     assert_eq!(ADD_A, 255);
@@ -43,5 +43,5 @@ fn main() {
 
     assert_eq!(ABS_POS, 10);
     assert_eq!(ABS_NEG, 10);
-    assert_eq!(ABS_MIN, i32::min_value());
+    assert_eq!(ABS_MIN, i32::MIN);
 }
diff --git a/src/test/ui/consts/const-match-check.eval1.stderr b/src/test/ui/consts/const-match-check.eval1.stderr
index 3850b1d82bf..12ba9cacabf 100644
--- a/src/test/ui/consts/const-match-check.eval1.stderr
+++ b/src/test/ui/consts/const-match-check.eval1.stderr
@@ -1,8 +1,8 @@
-error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
+error[E0005]: refutable pattern in local binding: `i32::MIN..=-1i32` and `1i32..=i32::MAX` not covered
   --> $DIR/const-match-check.rs:25:15
    |
 LL |     A = { let 0 = 0; 0 },
-   |               ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
+   |               ^ patterns `i32::MIN..=-1i32` and `1i32..=i32::MAX` not covered
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
diff --git a/src/test/ui/consts/const-match-check.eval2.stderr b/src/test/ui/consts/const-match-check.eval2.stderr
index 4e1d50f42d4..2eed7abdc65 100644
--- a/src/test/ui/consts/const-match-check.eval2.stderr
+++ b/src/test/ui/consts/const-match-check.eval2.stderr
@@ -1,8 +1,8 @@
-error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
+error[E0005]: refutable pattern in local binding: `i32::MIN..=-1i32` and `1i32..=i32::MAX` not covered
   --> $DIR/const-match-check.rs:31:24
    |
 LL |     let x: [i32; { let 0 = 0; 0 }] = [];
-   |                        ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
+   |                        ^ patterns `i32::MIN..=-1i32` and `1i32..=i32::MAX` not covered
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
diff --git a/src/test/ui/consts/const-match-check.matchck.stderr b/src/test/ui/consts/const-match-check.matchck.stderr
index 2aabc0ca494..1fa0cb17fe6 100644
--- a/src/test/ui/consts/const-match-check.matchck.stderr
+++ b/src/test/ui/consts/const-match-check.matchck.stderr
@@ -1,8 +1,8 @@
-error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
+error[E0005]: refutable pattern in local binding: `i32::MIN..=-1i32` and `1i32..=i32::MAX` not covered
   --> $DIR/const-match-check.rs:4:22
    |
 LL | const X: i32 = { let 0 = 0; 0 };
-   |                      ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
+   |                      ^ patterns `i32::MIN..=-1i32` and `1i32..=i32::MAX` not covered
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
@@ -12,11 +12,11 @@ help: you might want to use `if let` to ignore the variant that isn't matched
 LL | const X: i32 = { if let 0 = 0 { /* */ } 0 };
    |                  ^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
+error[E0005]: refutable pattern in local binding: `i32::MIN..=-1i32` and `1i32..=i32::MAX` not covered
   --> $DIR/const-match-check.rs:8:23
    |
 LL | static Y: i32 = { let 0 = 0; 0 };
-   |                       ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
+   |                       ^ patterns `i32::MIN..=-1i32` and `1i32..=i32::MAX` not covered
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
@@ -26,11 +26,11 @@ help: you might want to use `if let` to ignore the variant that isn't matched
 LL | static Y: i32 = { if let 0 = 0 { /* */ } 0 };
    |                   ^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
+error[E0005]: refutable pattern in local binding: `i32::MIN..=-1i32` and `1i32..=i32::MAX` not covered
   --> $DIR/const-match-check.rs:13:26
    |
 LL |     const X: i32 = { let 0 = 0; 0 };
-   |                          ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
+   |                          ^ patterns `i32::MIN..=-1i32` and `1i32..=i32::MAX` not covered
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
@@ -40,11 +40,11 @@ help: you might want to use `if let` to ignore the variant that isn't matched
 LL |     const X: i32 = { if let 0 = 0 { /* */ } 0 };
    |                      ^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
+error[E0005]: refutable pattern in local binding: `i32::MIN..=-1i32` and `1i32..=i32::MAX` not covered
   --> $DIR/const-match-check.rs:19:26
    |
 LL |     const X: i32 = { let 0 = 0; 0 };
-   |                          ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered
+   |                          ^ patterns `i32::MIN..=-1i32` and `1i32..=i32::MAX` not covered
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
diff --git a/src/test/ui/consts/const-pattern-irrefutable.rs b/src/test/ui/consts/const-pattern-irrefutable.rs
index 60e16aaf895..65f09eb8009 100644
--- a/src/test/ui/consts/const-pattern-irrefutable.rs
+++ b/src/test/ui/consts/const-pattern-irrefutable.rs
@@ -9,8 +9,8 @@ use foo::d;
 const a: u8 = 2;
 
 fn main() {
-    let a = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX
-    let c = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX
-    let d = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX
+    let a = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` and `3u8..=u8::MAX
+    let c = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` and `3u8..=u8::MAX
+    let d = 4; //~ ERROR refutable pattern in local binding: `0u8..=1u8` and `3u8..=u8::MAX
     fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115).
 }
diff --git a/src/test/ui/consts/const-pattern-irrefutable.stderr b/src/test/ui/consts/const-pattern-irrefutable.stderr
index 863e1372a9b..bb2fdec72ba 100644
--- a/src/test/ui/consts/const-pattern-irrefutable.stderr
+++ b/src/test/ui/consts/const-pattern-irrefutable.stderr
@@ -1,4 +1,4 @@
-error[E0005]: refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX` not covered
+error[E0005]: refutable pattern in local binding: `0u8..=1u8` and `3u8..=u8::MAX` not covered
   --> $DIR/const-pattern-irrefutable.rs:12:9
    |
 LL | const a: u8 = 2;
@@ -12,7 +12,7 @@ LL |     let a = 4;
    |
    = note: the matched value is of type `u8`
 
-error[E0005]: refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX` not covered
+error[E0005]: refutable pattern in local binding: `0u8..=1u8` and `3u8..=u8::MAX` not covered
   --> $DIR/const-pattern-irrefutable.rs:13:9
    |
 LL |     pub const b: u8 = 2;
@@ -26,7 +26,7 @@ LL |     let c = 4;
    |
    = note: the matched value is of type `u8`
 
-error[E0005]: refutable pattern in local binding: `0u8..=1u8` and `3u8..=std::u8::MAX` not covered
+error[E0005]: refutable pattern in local binding: `0u8..=1u8` and `3u8..=u8::MAX` not covered
   --> $DIR/const-pattern-irrefutable.rs:14:9
    |
 LL |     pub const d: u8 = 2;
diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr
index 5fd7fe4480e..0aa30665f59 100644
--- a/src/test/ui/consts/const-size_of-cycle.stderr
+++ b/src/test/ui/consts/const-size_of-cycle.stderr
@@ -17,8 +17,8 @@ LL |     bytes: [u8; std::mem::size_of::<Foo>()]
 note: ...which requires const-evaluating `std::mem::size_of`...
   --> $SRC_DIR/libcore/mem/mod.rs:LL:COL
    |
-LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | pub const fn size_of<T>() -> usize {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires const-evaluating + checking `std::intrinsics::size_of`...
   --> $SRC_DIR/libcore/intrinsics.rs:LL:COL
    |
diff --git a/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr b/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr
index be522dd6d5d..8c2190b4e59 100644
--- a/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr
+++ b/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr
@@ -1,15 +1,18 @@
 error: any use of this value will cause an error
-  --> $DIR/const_eval_limit_reached.rs:8:11
+  --> $DIR/const_eval_limit_reached.rs:8:5
    |
-LL | / const X: usize = {
-LL | |     let mut x = 0;
-LL | |     while x != 1000 {
-   | |           ^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
-LL | |
-...  |
-LL | |     x
-LL | | };
-   | |__-
+LL |  / const X: usize = {
+LL |  |     let mut x = 0;
+LL |  |     while x != 1000 {
+   |  |_____^
+LL | ||
+LL | ||         x += 1;
+LL | ||     }
+   | ||_____^ exceeded interpreter step limit (see `#[const_eval_limit]`)
+LL |  |
+LL |  |     x
+LL |  | };
+   |  |__-
    |
    = note: `#[deny(const_err)]` on by default
 
diff --git a/src/test/ui/consts/control-flow/drop-fail.precise.stderr b/src/test/ui/consts/control-flow/drop-fail.precise.stderr
new file mode 100644
index 00000000000..b4b6be8a1e5
--- /dev/null
+++ b/src/test/ui/consts/control-flow/drop-fail.precise.stderr
@@ -0,0 +1,15 @@
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/drop-fail.rs:10:9
+   |
+LL |     let x = Some(Vec::new());
+   |         ^ constants cannot evaluate destructors
+
+error[E0493]: destructors cannot be evaluated at compile-time
+  --> $DIR/drop-fail.rs:41:9
+   |
+LL |     let mut tmp = None;
+   |         ^^^^^^^ constants cannot evaluate destructors
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/control-flow/drop-failure.rs b/src/test/ui/consts/control-flow/drop-fail.rs
index 9da5546976c..7bd36726cea 100644
--- a/src/test/ui/consts/control-flow/drop-failure.rs
+++ b/src/test/ui/consts/control-flow/drop-fail.rs
@@ -1,11 +1,14 @@
+// revisions: stock precise
+
 #![feature(const_if_match)]
 #![feature(const_loop)]
+#![cfg_attr(precise, feature(const_precise_live_drops))]
 
-// `x` is *not* always moved into the final value may be dropped inside the initializer.
+// `x` is *not* always moved into the final value and may be dropped inside the initializer.
 const _: Option<Vec<i32>> = {
     let y: Option<Vec<i32>> = None;
     let x = Some(Vec::new());
-    //~^ ERROR destructors cannot be evaluated at compile-time
+    //[stock,precise]~^ ERROR destructors cannot be evaluated at compile-time
 
     if true {
         x
@@ -18,7 +21,7 @@ const _: Option<Vec<i32>> = {
 // existing analysis.
 const _: Vec<i32> = {
     let vec_tuple = (Vec::new(),);
-    //~^ ERROR destructors cannot be evaluated at compile-time
+    //[stock]~^ ERROR destructors cannot be evaluated at compile-time
 
     vec_tuple.0
 };
@@ -26,7 +29,7 @@ const _: Vec<i32> = {
 // This applies to single-field enum variants as well.
 const _: Vec<i32> = {
     let x: Result<_, Vec<i32>> = Ok(Vec::new());
-    //~^ ERROR destructors cannot be evaluated at compile-time
+    //[stock]~^ ERROR destructors cannot be evaluated at compile-time
 
     match x {
         Ok(x) | Err(x) => x,
@@ -36,7 +39,7 @@ const _: Vec<i32> = {
 const _: Option<Vec<i32>> = {
     let mut some = Some(Vec::new());
     let mut tmp = None;
-    //~^ ERROR destructors cannot be evaluated at compile-time
+    //[stock,precise]~^ ERROR destructors cannot be evaluated at compile-time
 
     let mut i = 0;
     while i < 10 {
diff --git a/src/test/ui/consts/control-flow/drop-failure.stderr b/src/test/ui/consts/control-flow/drop-fail.stock.stderr
index 3eec3a929a0..77cded5c438 100644
--- a/src/test/ui/consts/control-flow/drop-failure.stderr
+++ b/src/test/ui/consts/control-flow/drop-fail.stock.stderr
@@ -1,23 +1,23 @@
 error[E0493]: destructors cannot be evaluated at compile-time
-  --> $DIR/drop-failure.rs:7:9
+  --> $DIR/drop-fail.rs:10:9
    |
 LL |     let x = Some(Vec::new());
    |         ^ constants cannot evaluate destructors
 
 error[E0493]: destructors cannot be evaluated at compile-time
-  --> $DIR/drop-failure.rs:20:9
+  --> $DIR/drop-fail.rs:23:9
    |
 LL |     let vec_tuple = (Vec::new(),);
    |         ^^^^^^^^^ constants cannot evaluate destructors
 
 error[E0493]: destructors cannot be evaluated at compile-time
-  --> $DIR/drop-failure.rs:28:9
+  --> $DIR/drop-fail.rs:31:9
    |
 LL |     let x: Result<_, Vec<i32>> = Ok(Vec::new());
    |         ^ constants cannot evaluate destructors
 
 error[E0493]: destructors cannot be evaluated at compile-time
-  --> $DIR/drop-failure.rs:38:9
+  --> $DIR/drop-fail.rs:41:9
    |
 LL |     let mut tmp = None;
    |         ^^^^^^^ constants cannot evaluate destructors
diff --git a/src/test/ui/consts/control-flow/drop-success.rs b/src/test/ui/consts/control-flow/drop-pass.rs
index 185d6b63996..b0afd76c4e6 100644
--- a/src/test/ui/consts/control-flow/drop-success.rs
+++ b/src/test/ui/consts/control-flow/drop-pass.rs
@@ -1,7 +1,9 @@
 // run-pass
+// revisions: stock precise
 
 #![feature(const_if_match)]
 #![feature(const_loop)]
+#![cfg_attr(precise, feature(const_precise_live_drops))]
 
 // `x` is always moved into the final value and is not dropped inside the initializer.
 const _: Option<Vec<i32>> = {
diff --git a/src/test/ui/consts/control-flow/drop-precise.rs b/src/test/ui/consts/control-flow/drop-precise.rs
new file mode 100644
index 00000000000..95df76d9905
--- /dev/null
+++ b/src/test/ui/consts/control-flow/drop-precise.rs
@@ -0,0 +1,20 @@
+// run-pass
+// gate-test-const_precise_live_drops
+
+#![feature(const_if_match)]
+#![feature(const_loop)]
+#![feature(const_precise_live_drops)]
+
+const _: Vec<i32> = {
+    let vec_tuple = (Vec::new(),);
+    vec_tuple.0
+};
+
+const _: Vec<i32> = {
+    let x: Result<_, Vec<i32>> = Ok(Vec::new());
+    match x {
+        Ok(x) | Err(x) => x,
+    }
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/enum-discr-type-err.stderr b/src/test/ui/consts/enum-discr-type-err.stderr
index 492b79e2e60..9834a99b79a 100644
--- a/src/test/ui/consts/enum-discr-type-err.stderr
+++ b/src/test/ui/consts/enum-discr-type-err.stderr
@@ -11,10 +11,6 @@ LL | | }
    | |_- in this macro invocation
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-help: you can convert an `i32` to `isize` and panic if the converted value wouldn't fit
-   |
-LL |             $( $v = $s::V.try_into().unwrap(), )*
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/enum-discr-type-err.rs:18:21
@@ -29,10 +25,6 @@ LL | | }
    | |_- in this macro invocation
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-help: you can convert an `i32` to `isize` and panic if the converted value wouldn't fit
-   |
-LL |             $( $v = $s::V.try_into().unwrap(), )*
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.rs b/src/test/ui/consts/miri_unleashed/ptr_arith.rs
index 65fc49c0b27..064dc6c262c 100644
--- a/src/test/ui/consts/miri_unleashed/ptr_arith.rs
+++ b/src/test/ui/consts/miri_unleashed/ptr_arith.rs
@@ -6,14 +6,15 @@
 
 static CMP: () = {
     let x = &0 as *const _;
-    let _v = x == x;
+    let _v = x == x; //~ NOTE in this
     //~^ ERROR could not evaluate static initializer
     //~| NOTE pointer arithmetic or comparison
+    //~| NOTE in this
 };
 
 static INT_PTR_ARITH: () = unsafe {
     let x: usize = std::mem::transmute(&0);
-    let _v = x + 0;
+    let _v = x + 0; //~ NOTE in this
     //~^ ERROR could not evaluate static initializer
     //~| NOTE pointer-to-integer cast
 };
diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr
index 805ba9c6b03..4b3fe995700 100644
--- a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr
+++ b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr
@@ -5,7 +5,7 @@ LL |     let _v = x == x;
    |              ^^^^^^ "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ptr_arith.rs:16:14
+  --> $DIR/ptr_arith.rs:17:14
    |
 LL |     let _v = x + 0;
    |              ^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants
@@ -18,7 +18,7 @@ help: skipping check for `const_compare_raw_pointers` feature
 LL |     let _v = x == x;
    |              ^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/ptr_arith.rs:15:20
+  --> $DIR/ptr_arith.rs:16:20
    |
 LL |     let x: usize = std::mem::transmute(&0);
    |                    ^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/consts/recursive-zst-static.default.stderr b/src/test/ui/consts/recursive-zst-static.default.stderr
index d424b22f000..9042c6f6be1 100644
--- a/src/test/ui/consts/recursive-zst-static.default.stderr
+++ b/src/test/ui/consts/recursive-zst-static.default.stderr
@@ -1,8 +1,8 @@
 error[E0391]: cycle detected when const-evaluating `FOO`
-  --> $DIR/recursive-zst-static.rs:10:18
+  --> $DIR/recursive-zst-static.rs:10:1
    |
 LL | static FOO: () = FOO;
-   |                  ^^^
+   | ^^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires const-evaluating `FOO`...
   --> $DIR/recursive-zst-static.rs:10:1
diff --git a/src/test/ui/consts/recursive-zst-static.unleash.stderr b/src/test/ui/consts/recursive-zst-static.unleash.stderr
index d424b22f000..9042c6f6be1 100644
--- a/src/test/ui/consts/recursive-zst-static.unleash.stderr
+++ b/src/test/ui/consts/recursive-zst-static.unleash.stderr
@@ -1,8 +1,8 @@
 error[E0391]: cycle detected when const-evaluating `FOO`
-  --> $DIR/recursive-zst-static.rs:10:18
+  --> $DIR/recursive-zst-static.rs:10:1
    |
 LL | static FOO: () = FOO;
-   |                  ^^^
+   | ^^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires const-evaluating `FOO`...
   --> $DIR/recursive-zst-static.rs:10:1
diff --git a/src/test/ui/consts/uninhabited-const-issue-61744.rs b/src/test/ui/consts/uninhabited-const-issue-61744.rs
index 15436f9c1b2..55f42d84f9c 100644
--- a/src/test/ui/consts/uninhabited-const-issue-61744.rs
+++ b/src/test/ui/consts/uninhabited-const-issue-61744.rs
@@ -1,11 +1,11 @@
 // build-fail
 
 pub const unsafe fn fake_type<T>() -> T {
-    hint_unreachable()
+    hint_unreachable() //~ ERROR evaluation of constant value failed
 }
 
 pub const unsafe fn hint_unreachable() -> ! {
-    fake_type() //~ ERROR evaluation of constant value failed
+    fake_type()
 }
 
 trait Const {
diff --git a/src/test/ui/consts/uninhabited-const-issue-61744.stderr b/src/test/ui/consts/uninhabited-const-issue-61744.stderr
index ca232380897..fc908b2b222 100644
--- a/src/test/ui/consts/uninhabited-const-issue-61744.stderr
+++ b/src/test/ui/consts/uninhabited-const-issue-61744.stderr
@@ -1,9 +1,10 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
    |
 LL |     hint_unreachable()
-   |     ------------------
+   |     ^^^^^^^^^^^^^^^^^^
    |     |
+   |     reached the configured maximum number of stack frames
    |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
    |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
    |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
@@ -71,9 +72,8 @@ LL |     hint_unreachable()
    |     inside `fake_type::<i32>` at $DIR/uninhabited-const-issue-61744.rs:4:5
 ...
 LL |     fake_type()
-   |     ^^^^^^^^^^^
+   |     -----------
    |     |
-   |     reached the configured maximum number of stack frames
    |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
    |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
    |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
diff --git a/src/test/ui/derived-errors/issue-31997-1.stderr b/src/test/ui/derived-errors/issue-31997-1.stderr
index a4daf86cc8a..229c5c9e80f 100644
--- a/src/test/ui/derived-errors/issue-31997-1.stderr
+++ b/src/test/ui/derived-errors/issue-31997-1.stderr
@@ -4,12 +4,10 @@ error[E0433]: failed to resolve: use of undeclared type or module `HashMap`
 LL |     let mut map = HashMap::new();
    |                   ^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this struct
    |
 LL | use std::collections::HashMap;
    |
-LL | use std::collections::hash_map::HashMap;
-   |
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs b/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs
index e9c6104e387..4e2cc89948a 100644
--- a/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs
+++ b/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs
@@ -5,7 +5,7 @@
 #[repr(i128)]
 enum Test {
     A(Box<u64>) = 0,
-    B(usize) = u64::max_value() as i128 + 1,
+    B(usize) = u64::MAX as i128 + 1,
 }
 
 fn main() {
diff --git a/src/test/ui/enum-discriminant/repr128.rs b/src/test/ui/enum-discriminant/repr128.rs
index 420b6007c6d..eefbc44f585 100644
--- a/src/test/ui/enum-discriminant/repr128.rs
+++ b/src/test/ui/enum-discriminant/repr128.rs
@@ -8,9 +8,9 @@ use std::marker::DiscriminantKind;
 enum Signed {
     Zero = 0,
     Staircase = 0x01_02_03_04_05_06_07_08_09_0a_0b_0c_0d_0e_0f,
-    U64Limit = u64::max_value() as i128 + 1,
+    U64Limit = u64::MAX as i128 + 1,
     SmallNegative = -1,
-    BigNegative = i128::min_value(),
+    BigNegative = i128::MIN,
     Next,
 }
 
@@ -18,7 +18,7 @@ enum Signed {
 enum Unsigned {
     Zero = 0,
     Staircase = 0x01_02_03_04_05_06_07_08_09_0a_0b_0c_0d_0e_0f,
-    U64Limit = u64::max_value() as u128 + 1,
+    U64Limit = u64::MAX as u128 + 1,
     Next,
 }
 
@@ -32,13 +32,13 @@ where
 fn main() {
     discr(Signed::Zero, 0);
     discr(Signed::Staircase, 0x01_02_03_04_05_06_07_08_09_0a_0b_0c_0d_0e_0f);
-    discr(Signed::U64Limit, u64::max_value() as i128 + 1);
+    discr(Signed::U64Limit, u64::MAX as i128 + 1);
     discr(Signed::SmallNegative, -1);
-    discr(Signed::BigNegative, i128::min_value());
-    discr(Signed::Next, i128::min_value() + 1);
+    discr(Signed::BigNegative, i128::MIN);
+    discr(Signed::Next, i128::MIN + 1);
 
     discr(Unsigned::Zero, 0);
     discr(Unsigned::Staircase, 0x01_02_03_04_05_06_07_08_09_0a_0b_0c_0d_0e_0f);
-    discr(Unsigned::U64Limit, u64::max_value() as u128 + 1);
-    discr(Unsigned::Next, u64::max_value() as u128 + 2);
+    discr(Unsigned::U64Limit, u64::MAX as u128 + 1);
+    discr(Unsigned::Next, u64::MAX as u128 + 2);
 }
diff --git a/src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.rs b/src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.rs
new file mode 100644
index 00000000000..0d7df8182c4
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.rs
@@ -0,0 +1,9 @@
+// Test that the AVR interrupt ABI cannot be used when avr_interrupt
+// feature gate is not used.
+
+extern "avr-interrupt" fn foo() {}
+//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+
+fn main() {
+    foo();
+}
diff --git a/src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr b/src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr
new file mode 100644
index 00000000000..be7040e1491
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr
@@ -0,0 +1,12 @@
+error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+  --> $DIR/feature-gate-abi-avr-interrupt.rs:4:8
+   |
+LL | extern "avr-interrupt" fn foo() {}
+   |        ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #69664 <https://github.com/rust-lang/rust/issues/69664> for more information
+   = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
index 6088331cded..3b6c9791722 100644
--- a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
+++ b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
@@ -9,10 +9,14 @@ trait Bar {
 
 impl Bar for () {
     type Baa = impl Debug; //~ ERROR `impl Trait` in type aliases is unstable
-    fn define() -> Self::Baa { 0 }
+    fn define() -> Self::Baa {
+        0
+    }
 }
 
-fn define() -> Foo { 0 }
+fn define() -> Foo {
+    0
+}
 
 trait TraitWithDefault {
     type Assoc = impl Debug;
@@ -26,20 +30,20 @@ type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>
 //~| ERROR `impl Trait` in type aliases is unstable
 //~| ERROR `impl Trait` in type aliases is unstable
 //~| ERROR `impl Trait` in type aliases is unstable
-//~| ERROR `impl Trait` not allowed outside of function
-//~| ERROR `impl Trait` not allowed outside of function
-//~| ERROR `impl Trait` not allowed outside of function
+
+fn define_multiple() -> NestedFree {
+    (vec![true], 0u8, 0i32..1)
+}
 
 impl Bar for u8 {
-    type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
+    type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug> + Debug);
     //~^ ERROR `impl Trait` in type aliases is unstable
     //~| ERROR `impl Trait` in type aliases is unstable
     //~| ERROR `impl Trait` in type aliases is unstable
     //~| ERROR `impl Trait` in type aliases is unstable
-    //~| ERROR `impl Trait` not allowed outside of function
-    //~| ERROR `impl Trait` not allowed outside of function
-    //~| ERROR `impl Trait` not allowed outside of function
-    fn define() -> Self::Baa { (vec![true], 0u8, 0i32..1) }
+    fn define() -> Self::Baa {
+        (vec![true], 0u8, 0i32..1)
+    }
 }
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr
index 55cd2984ab6..8bab0d0c4a9 100644
--- a/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr
+++ b/src/test/ui/feature-gates/feature-gate-type_alias_impl_trait.stderr
@@ -17,7 +17,7 @@ LL |     type Baa = impl Debug;
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: associated type defaults are unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:18:5
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:22:5
    |
 LL |     type Assoc = impl Debug;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ LL |     type Assoc = impl Debug;
    = help: add `#![feature(associated_type_defaults)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:18:18
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:22:18
    |
 LL |     type Assoc = impl Debug;
    |                  ^^^^^^^^^^
@@ -35,7 +35,7 @@ LL |     type Assoc = impl Debug;
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:24:24
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:28:24
    |
 LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
    |                        ^^^^^^^^^^
@@ -44,7 +44,7 @@ LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl D
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:24:37
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:28:37
    |
 LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
    |                                     ^^^^^^^^^^
@@ -53,7 +53,7 @@ LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl D
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:24:49
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:28:49
    |
 LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -62,7 +62,7 @@ LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl D
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:24:70
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:28:70
    |
 LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
    |                                                                      ^^^^^^^^^^
@@ -71,84 +71,48 @@ LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl D
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:34:21
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:39:21
    |
-LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
+LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug> + Debug);
    |                     ^^^^^^^^^^
    |
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:34:34
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:39:34
    |
-LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
+LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug> + Debug);
    |                                  ^^^^^^^^^^
    |
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:34:46
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:39:46
    |
-LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
-   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug> + Debug);
+   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:34:67
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:39:67
    |
-LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
+LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug> + Debug);
    |                                                                   ^^^^^^^^^^
    |
    = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:18:18
+  --> $DIR/feature-gate-type_alias_impl_trait.rs:22:18
    |
 LL |     type Assoc = impl Debug;
    |                  ^^^^^^^^^^
 
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:24:24
-   |
-LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
-   |                        ^^^^^^^^^^
-
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:24:37
-   |
-LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
-   |                                     ^^^^^^^^^^
-
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:24:49
-   |
-LL | type NestedFree = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
-   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:34:21
-   |
-LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
-   |                     ^^^^^^^^^^
-
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:34:34
-   |
-LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
-   |                                  ^^^^^^^^^^
-
-error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
-  --> $DIR/feature-gate-type_alias_impl_trait.rs:34:46
-   |
-LL |     type Baa = (Vec<impl Debug>, impl Debug, impl Iterator<Item = impl Debug>);
-   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 19 previous errors
+error: aborting due to 13 previous errors
 
 Some errors have detailed explanations: E0562, E0658.
 For more information about an error, try `rustc --explain E0562`.
diff --git a/src/test/ui/ffi_returns_twice.stderr b/src/test/ui/ffi_returns_twice.stderr
index 862892e27be..2b7f5694f02 100644
--- a/src/test/ui/ffi_returns_twice.stderr
+++ b/src/test/ui/ffi_returns_twice.stderr
@@ -6,3 +6,4 @@ LL | #[ffi_returns_twice]
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0724`.
diff --git a/src/test/ui/for/for-loop-refutable-pattern-error-message.stderr b/src/test/ui/for/for-loop-refutable-pattern-error-message.stderr
index ce12b7853b6..e32005e21a8 100644
--- a/src/test/ui/for/for-loop-refutable-pattern-error-message.stderr
+++ b/src/test/ui/for/for-loop-refutable-pattern-error-message.stderr
@@ -1,8 +1,8 @@
-error[E0005]: refutable pattern in `for` loop binding: `&std::i32::MIN..=0i32` and `&2i32..=std::i32::MAX` not covered
+error[E0005]: refutable pattern in `for` loop binding: `&i32::MIN..=0i32` and `&2i32..=i32::MAX` not covered
   --> $DIR/for-loop-refutable-pattern-error-message.rs:2:9
    |
 LL |     for &1 in [1].iter() {}
-   |         ^^ patterns `&std::i32::MIN..=0i32` and `&2i32..=std::i32::MAX` not covered
+   |         ^^ patterns `&i32::MIN..=0i32` and `&2i32..=i32::MAX` not covered
    |
    = note: the matched value is of type `&i32`
 
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
index 6c7a0cdb77a..028bfb89312 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
@@ -70,20 +70,20 @@ LL |     m!('a', ..VAL_1 | VAL_2..);
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `char`
 
-error[E0004]: non-exhaustive patterns: `std::u8::MAX` not covered
+error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:41:12
    |
 LL |         m!(0, ..core::u8::MAX);
-   |            ^ pattern `std::u8::MAX` not covered
+   |            ^ pattern `u8::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
 
-error[E0004]: non-exhaustive patterns: `254u8..=std::u8::MAX` not covered
+error[E0004]: non-exhaustive patterns: `254u8..=u8::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:42:12
    |
 LL |         m!(0, ..ALMOST_MAX);
-   |            ^ pattern `254u8..=std::u8::MAX` not covered
+   |            ^ pattern `254u8..=u8::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
@@ -97,11 +97,11 @@ LL |         m!(0, ALMOST_MIN..);
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
 
-error[E0004]: non-exhaustive patterns: `std::u8::MAX` not covered
+error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:44:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
-   |            ^ pattern `std::u8::MAX` not covered
+   |            ^ pattern `u8::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
@@ -124,20 +124,20 @@ LL |         m!(0, ..VAL_1 | VAL_2..);
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
 
-error[E0004]: non-exhaustive patterns: `std::u16::MAX` not covered
+error[E0004]: non-exhaustive patterns: `u16::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:54:12
    |
 LL |         m!(0, ..core::u16::MAX);
-   |            ^ pattern `std::u16::MAX` not covered
+   |            ^ pattern `u16::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u16`
 
-error[E0004]: non-exhaustive patterns: `65534u16..=std::u16::MAX` not covered
+error[E0004]: non-exhaustive patterns: `65534u16..=u16::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:55:12
    |
 LL |         m!(0, ..ALMOST_MAX);
-   |            ^ pattern `65534u16..=std::u16::MAX` not covered
+   |            ^ pattern `65534u16..=u16::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u16`
@@ -151,11 +151,11 @@ LL |         m!(0, ALMOST_MIN..);
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u16`
 
-error[E0004]: non-exhaustive patterns: `std::u16::MAX` not covered
+error[E0004]: non-exhaustive patterns: `u16::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:57:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
-   |            ^ pattern `std::u16::MAX` not covered
+   |            ^ pattern `u16::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u16`
@@ -178,20 +178,20 @@ LL |         m!(0, ..VAL_1 | VAL_2..);
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u16`
 
-error[E0004]: non-exhaustive patterns: `std::u32::MAX` not covered
+error[E0004]: non-exhaustive patterns: `u32::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:67:12
    |
 LL |         m!(0, ..core::u32::MAX);
-   |            ^ pattern `std::u32::MAX` not covered
+   |            ^ pattern `u32::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u32`
 
-error[E0004]: non-exhaustive patterns: `4294967294u32..=std::u32::MAX` not covered
+error[E0004]: non-exhaustive patterns: `4294967294u32..=u32::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:68:12
    |
 LL |         m!(0, ..ALMOST_MAX);
-   |            ^ pattern `4294967294u32..=std::u32::MAX` not covered
+   |            ^ pattern `4294967294u32..=u32::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u32`
@@ -205,11 +205,11 @@ LL |         m!(0, ALMOST_MIN..);
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u32`
 
-error[E0004]: non-exhaustive patterns: `std::u32::MAX` not covered
+error[E0004]: non-exhaustive patterns: `u32::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:70:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
-   |            ^ pattern `std::u32::MAX` not covered
+   |            ^ pattern `u32::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u32`
@@ -232,20 +232,20 @@ LL |         m!(0, ..VAL_1 | VAL_2..);
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u32`
 
-error[E0004]: non-exhaustive patterns: `std::u64::MAX` not covered
+error[E0004]: non-exhaustive patterns: `u64::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:80:12
    |
 LL |         m!(0, ..core::u64::MAX);
-   |            ^ pattern `std::u64::MAX` not covered
+   |            ^ pattern `u64::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u64`
 
-error[E0004]: non-exhaustive patterns: `18446744073709551614u64..=std::u64::MAX` not covered
+error[E0004]: non-exhaustive patterns: `18446744073709551614u64..=u64::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:81:12
    |
 LL |         m!(0, ..ALMOST_MAX);
-   |            ^ pattern `18446744073709551614u64..=std::u64::MAX` not covered
+   |            ^ pattern `18446744073709551614u64..=u64::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u64`
@@ -259,11 +259,11 @@ LL |         m!(0, ALMOST_MIN..);
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u64`
 
-error[E0004]: non-exhaustive patterns: `std::u64::MAX` not covered
+error[E0004]: non-exhaustive patterns: `u64::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:83:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
-   |            ^ pattern `std::u64::MAX` not covered
+   |            ^ pattern `u64::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u64`
@@ -286,20 +286,20 @@ LL |         m!(0, ..VAL_1 | VAL_2..);
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u64`
 
-error[E0004]: non-exhaustive patterns: `std::u128::MAX` not covered
+error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12
    |
 LL |         m!(0, ..core::u128::MAX);
-   |            ^ pattern `std::u128::MAX` not covered
+   |            ^ pattern `u128::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u128`
 
-error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211454u128..=std::u128::MAX` not covered
+error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211454u128..=u128::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12
    |
 LL |         m!(0, ..ALMOST_MAX);
-   |            ^ pattern `340282366920938463463374607431768211454u128..=std::u128::MAX` not covered
+   |            ^ pattern `340282366920938463463374607431768211454u128..=u128::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u128`
@@ -313,11 +313,11 @@ LL |         m!(0, ALMOST_MIN..);
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u128`
 
-error[E0004]: non-exhaustive patterns: `std::u128::MAX` not covered
+error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:96:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
-   |            ^ pattern `std::u128::MAX` not covered
+   |            ^ pattern `u128::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u128`
@@ -340,38 +340,38 @@ LL |         m!(0, ..VAL_1 | VAL_2..);
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u128`
 
-error[E0004]: non-exhaustive patterns: `std::i8::MAX` not covered
+error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:109:12
    |
 LL |         m!(0, ..core::i8::MAX);
-   |            ^ pattern `std::i8::MAX` not covered
+   |            ^ pattern `i8::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i8`
 
-error[E0004]: non-exhaustive patterns: `126i8..=std::i8::MAX` not covered
+error[E0004]: non-exhaustive patterns: `126i8..=i8::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:110:12
    |
 LL |         m!(0, ..ALMOST_MAX);
-   |            ^ pattern `126i8..=std::i8::MAX` not covered
+   |            ^ pattern `126i8..=i8::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i8`
 
-error[E0004]: non-exhaustive patterns: `std::i8::MIN` not covered
+error[E0004]: non-exhaustive patterns: `i8::MIN` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:111:12
    |
 LL |         m!(0, ALMOST_MIN..);
-   |            ^ pattern `std::i8::MIN` not covered
+   |            ^ pattern `i8::MIN` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i8`
 
-error[E0004]: non-exhaustive patterns: `std::i8::MAX` not covered
+error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:112:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
-   |            ^ pattern `std::i8::MAX` not covered
+   |            ^ pattern `i8::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i8`
@@ -394,38 +394,38 @@ LL |         m!(0, ..VAL_1 | VAL_2..);
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i8`
 
-error[E0004]: non-exhaustive patterns: `std::i16::MAX` not covered
+error[E0004]: non-exhaustive patterns: `i16::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:122:12
    |
 LL |         m!(0, ..core::i16::MAX);
-   |            ^ pattern `std::i16::MAX` not covered
+   |            ^ pattern `i16::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i16`
 
-error[E0004]: non-exhaustive patterns: `32766i16..=std::i16::MAX` not covered
+error[E0004]: non-exhaustive patterns: `32766i16..=i16::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:123:12
    |
 LL |         m!(0, ..ALMOST_MAX);
-   |            ^ pattern `32766i16..=std::i16::MAX` not covered
+   |            ^ pattern `32766i16..=i16::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i16`
 
-error[E0004]: non-exhaustive patterns: `std::i16::MIN` not covered
+error[E0004]: non-exhaustive patterns: `i16::MIN` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:124:12
    |
 LL |         m!(0, ALMOST_MIN..);
-   |            ^ pattern `std::i16::MIN` not covered
+   |            ^ pattern `i16::MIN` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i16`
 
-error[E0004]: non-exhaustive patterns: `std::i16::MAX` not covered
+error[E0004]: non-exhaustive patterns: `i16::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:125:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
-   |            ^ pattern `std::i16::MAX` not covered
+   |            ^ pattern `i16::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i16`
@@ -448,38 +448,38 @@ LL |         m!(0, ..VAL_1 | VAL_2..);
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i16`
 
-error[E0004]: non-exhaustive patterns: `std::i32::MAX` not covered
+error[E0004]: non-exhaustive patterns: `i32::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:135:12
    |
 LL |         m!(0, ..core::i32::MAX);
-   |            ^ pattern `std::i32::MAX` not covered
+   |            ^ pattern `i32::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i32`
 
-error[E0004]: non-exhaustive patterns: `2147483646i32..=std::i32::MAX` not covered
+error[E0004]: non-exhaustive patterns: `2147483646i32..=i32::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:136:12
    |
 LL |         m!(0, ..ALMOST_MAX);
-   |            ^ pattern `2147483646i32..=std::i32::MAX` not covered
+   |            ^ pattern `2147483646i32..=i32::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i32`
 
-error[E0004]: non-exhaustive patterns: `std::i32::MIN` not covered
+error[E0004]: non-exhaustive patterns: `i32::MIN` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:137:12
    |
 LL |         m!(0, ALMOST_MIN..);
-   |            ^ pattern `std::i32::MIN` not covered
+   |            ^ pattern `i32::MIN` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i32`
 
-error[E0004]: non-exhaustive patterns: `std::i32::MAX` not covered
+error[E0004]: non-exhaustive patterns: `i32::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:138:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
-   |            ^ pattern `std::i32::MAX` not covered
+   |            ^ pattern `i32::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i32`
@@ -502,38 +502,38 @@ LL |         m!(0, ..VAL_1 | VAL_2..);
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i32`
 
-error[E0004]: non-exhaustive patterns: `std::i64::MAX` not covered
+error[E0004]: non-exhaustive patterns: `i64::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:148:12
    |
 LL |         m!(0, ..core::i64::MAX);
-   |            ^ pattern `std::i64::MAX` not covered
+   |            ^ pattern `i64::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i64`
 
-error[E0004]: non-exhaustive patterns: `9223372036854775806i64..=std::i64::MAX` not covered
+error[E0004]: non-exhaustive patterns: `9223372036854775806i64..=i64::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:149:12
    |
 LL |         m!(0, ..ALMOST_MAX);
-   |            ^ pattern `9223372036854775806i64..=std::i64::MAX` not covered
+   |            ^ pattern `9223372036854775806i64..=i64::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i64`
 
-error[E0004]: non-exhaustive patterns: `std::i64::MIN` not covered
+error[E0004]: non-exhaustive patterns: `i64::MIN` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:150:12
    |
 LL |         m!(0, ALMOST_MIN..);
-   |            ^ pattern `std::i64::MIN` not covered
+   |            ^ pattern `i64::MIN` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i64`
 
-error[E0004]: non-exhaustive patterns: `std::i64::MAX` not covered
+error[E0004]: non-exhaustive patterns: `i64::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:151:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
-   |            ^ pattern `std::i64::MAX` not covered
+   |            ^ pattern `i64::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i64`
@@ -556,38 +556,38 @@ LL |         m!(0, ..VAL_1 | VAL_2..);
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i64`
 
-error[E0004]: non-exhaustive patterns: `std::i128::MAX` not covered
+error[E0004]: non-exhaustive patterns: `i128::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12
    |
 LL |         m!(0, ..core::i128::MAX);
-   |            ^ pattern `std::i128::MAX` not covered
+   |            ^ pattern `i128::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i128`
 
-error[E0004]: non-exhaustive patterns: `170141183460469231731687303715884105726i128..=std::i128::MAX` not covered
+error[E0004]: non-exhaustive patterns: `170141183460469231731687303715884105726i128..=i128::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12
    |
 LL |         m!(0, ..ALMOST_MAX);
-   |            ^ pattern `170141183460469231731687303715884105726i128..=std::i128::MAX` not covered
+   |            ^ pattern `170141183460469231731687303715884105726i128..=i128::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i128`
 
-error[E0004]: non-exhaustive patterns: `std::i128::MIN` not covered
+error[E0004]: non-exhaustive patterns: `i128::MIN` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:163:12
    |
 LL |         m!(0, ALMOST_MIN..);
-   |            ^ pattern `std::i128::MIN` not covered
+   |            ^ pattern `i128::MIN` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i128`
 
-error[E0004]: non-exhaustive patterns: `std::i128::MAX` not covered
+error[E0004]: non-exhaustive patterns: `i128::MAX` not covered
   --> $DIR/half-open-range-pats-exhaustive-fail.rs:164:12
    |
 LL |         m!(0, ..=ALMOST_MAX);
-   |            ^ pattern `std::i128::MAX` not covered
+   |            ^ pattern `i128::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i128`
diff --git a/src/test/ui/hygiene/no_implicit_prelude.stderr b/src/test/ui/hygiene/no_implicit_prelude.stderr
index c0539434d02..990210ffb6b 100644
--- a/src/test/ui/hygiene/no_implicit_prelude.stderr
+++ b/src/test/ui/hygiene/no_implicit_prelude.stderr
@@ -16,9 +16,7 @@ LL |         Vec::new();
    |         ^^^ not found in this scope
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider importing one of these items
-   |
-LL |     use std::prelude::v1::Vec;
+help: consider importing this struct
    |
 LL |     use std::vec::Vec;
    |
diff --git a/src/test/ui/hygiene/unpretty-debug.stdout b/src/test/ui/hygiene/unpretty-debug.stdout
index acd852103ca..fc5ed724e3c 100644
--- a/src/test/ui/hygiene/unpretty-debug.stdout
+++ b/src/test/ui/hygiene/unpretty-debug.stdout
@@ -18,8 +18,12 @@ fn y /* 0#0 */() { }
 Expansions:
 0: parent: ExpnId(0), call_site_ctxt: #0, kind: Root
 1: parent: ExpnId(0), call_site_ctxt: #0, kind: Macro(Bang, "foo")
+2: parent: ExpnId(0), call_site_ctxt: #1, kind: Desugaring(Operator)
+3: parent: ExpnId(0), call_site_ctxt: #1, kind: Desugaring(Operator)
 
 SyntaxContexts:
 #0: parent: #0, outer_mark: (ExpnId(0), Opaque)
 #1: parent: #0, outer_mark: (ExpnId(1), SemiTransparent)
+#2: parent: #1, outer_mark: (ExpnId(2), Transparent)
+#3: parent: #1, outer_mark: (ExpnId(3), Transparent)
 */
diff --git a/src/test/ui/impl-trait-in-bindings-issue-73003.rs b/src/test/ui/impl-trait-in-bindings-issue-73003.rs
new file mode 100644
index 00000000000..fd8fe5f48df
--- /dev/null
+++ b/src/test/ui/impl-trait-in-bindings-issue-73003.rs
@@ -0,0 +1,8 @@
+// check-pass
+
+#![feature(impl_trait_in_bindings)]
+//~^ WARN the feature `impl_trait_in_bindings` is incomplete
+
+const _: impl Fn() = ||();
+
+fn main() {}
diff --git a/src/test/ui/impl-trait-in-bindings-issue-73003.stderr b/src/test/ui/impl-trait-in-bindings-issue-73003.stderr
new file mode 100644
index 00000000000..715671c8add
--- /dev/null
+++ b/src/test/ui/impl-trait-in-bindings-issue-73003.stderr
@@ -0,0 +1,11 @@
+warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/impl-trait-in-bindings-issue-73003.rs:3:12
+   |
+LL | #![feature(impl_trait_in_bindings)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/impl-trait/auto-trait-leak.rs b/src/test/ui/impl-trait/auto-trait-leak.rs
index a6012835f44..087f4582b21 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.rs
+++ b/src/test/ui/impl-trait/auto-trait-leak.rs
@@ -11,8 +11,6 @@ fn main() {
 // return type, which can't depend on the obligation.
 fn cycle1() -> impl Clone {
     //~^ ERROR cycle detected
-    //~| ERROR cycle detected
-    //~| ERROR cycle detected
     send(cycle2().clone());
     //~^ ERROR cannot be sent between threads safely
 
diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr
index 64d02f07048..679b26efe59 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.stderr
+++ b/src/test/ui/impl-trait/auto-trait-leak.stderr
@@ -36,37 +36,37 @@ LL | fn cycle1() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
 note: ...which requires computing type of `cycle2::{{opaque}}#0`...
-  --> $DIR/auto-trait-leak.rs:22:16
+  --> $DIR/auto-trait-leak.rs:20:16
    |
 LL | fn cycle2() -> impl Clone {
    |                ^^^^^^^^^^
 note: ...which requires borrow-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires processing `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires processing MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires unsafety-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires building MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires type-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
+  --> $DIR/auto-trait-leak.rs:20:1
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -84,178 +84,8 @@ LL | |     Rc::new(String::from("foo"))
 LL | | }
    | |_^
 
-error[E0391]: cycle detected when computing type of `cycle1::{{opaque}}#0`
-  --> $DIR/auto-trait-leak.rs:12:16
-   |
-LL | fn cycle1() -> impl Clone {
-   |                ^^^^^^^^^^
-   |
-note: ...which requires borrow-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing MIR for `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires unsafety-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires building MIR for `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires type-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
-note: ...which requires computing type of `cycle2::{{opaque}}#0`...
-  --> $DIR/auto-trait-leak.rs:22:16
-   |
-LL | fn cycle2() -> impl Clone {
-   |                ^^^^^^^^^^
-note: ...which requires borrow-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires unsafety-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires building MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires type-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which again requires computing type of `cycle1::{{opaque}}#0`, completing the cycle
-note: cycle used when checking item types in top-level module
-  --> $DIR/auto-trait-leak.rs:1:1
-   |
-LL | / use std::cell::Cell;
-LL | | use std::rc::Rc;
-LL | |
-LL | | fn send<T: Send>(_: T) {}
-...  |
-LL | |     Rc::new(String::from("foo"))
-LL | | }
-   | |_^
-
-error[E0391]: cycle detected when computing type of `cycle1::{{opaque}}#0`
-  --> $DIR/auto-trait-leak.rs:12:16
-   |
-LL | fn cycle1() -> impl Clone {
-   |                ^^^^^^^^^^
-   |
-note: ...which requires borrow-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing MIR for `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires unsafety-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires building MIR for `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires type-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`...
-note: ...which requires computing type of `cycle2::{{opaque}}#0`...
-  --> $DIR/auto-trait-leak.rs:22:16
-   |
-LL | fn cycle2() -> impl Clone {
-   |                ^^^^^^^^^^
-note: ...which requires borrow-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires unsafety-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires building MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires type-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:22:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which again requires computing type of `cycle1::{{opaque}}#0`, completing the cycle
-note: cycle used when checking item types in top-level module
-  --> $DIR/auto-trait-leak.rs:1:1
-   |
-LL | / use std::cell::Cell;
-LL | | use std::rc::Rc;
-LL | |
-LL | | fn send<T: Send>(_: T) {}
-...  |
-LL | |     Rc::new(String::from("foo"))
-LL | | }
-   | |_^
-
 error[E0277]: `std::rc::Rc<std::string::String>` cannot be sent between threads safely
-  --> $DIR/auto-trait-leak.rs:16:5
+  --> $DIR/auto-trait-leak.rs:14:5
    |
 LL | fn send<T: Send>(_: T) {}
    |            ---- required by this bound in `send`
@@ -269,7 +99,7 @@ LL | fn cycle2() -> impl Clone {
    = help: within `impl std::clone::Clone`, the trait `std::marker::Send` is not implemented for `std::rc::Rc<std::string::String>`
    = note: required because it appears within the type `impl std::clone::Clone`
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0277, E0391.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/auto-trait.rs b/src/test/ui/impl-trait/auto-trait.rs
index c7675781208..cf2773f4ef5 100644
--- a/src/test/ui/impl-trait/auto-trait.rs
+++ b/src/test/ui/impl-trait/auto-trait.rs
@@ -2,22 +2,24 @@
 // the purposes of coherence checking
 #![feature(type_alias_impl_trait)]
 
-trait OpaqueTrait { }
-impl<T> OpaqueTrait for T { }
+trait OpaqueTrait {}
+impl<T> OpaqueTrait for T {}
 type OpaqueType = impl OpaqueTrait;
-fn mk_opaque() -> OpaqueType { () }
+fn mk_opaque() -> OpaqueType {
+    ()
+}
 
 #[derive(Debug)]
 struct D<T>(T);
 
-trait AnotherTrait { }
-impl<T: Send> AnotherTrait for T { }
+trait AnotherTrait {}
+impl<T: Send> AnotherTrait for T {}
 
 // This is in error, because we cannot assume that `OpaqueType: !Send`.
 // (We treat opaque types as "foreign types" that could grow more impls
 // in the future.)
 impl AnotherTrait for D<OpaqueType> {
-    //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
+    //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>`
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/auto-trait.stderr b/src/test/ui/impl-trait/auto-trait.stderr
index 5e72ca7a47b..16fe1b56b50 100644
--- a/src/test/ui/impl-trait/auto-trait.stderr
+++ b/src/test/ui/impl-trait/auto-trait.stderr
@@ -1,11 +1,11 @@
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`:
-  --> $DIR/auto-trait.rs:19:1
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>`:
+  --> $DIR/auto-trait.rs:21:1
    |
-LL | impl<T: Send> AnotherTrait for T { }
+LL | impl<T: Send> AnotherTrait for T {}
    | -------------------------------- first implementation here
 ...
 LL | impl AnotherTrait for D<OpaqueType> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<impl OpaqueTrait>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/issue-55872-1.stderr b/src/test/ui/impl-trait/issue-55872-1.stderr
index 6cb2c9fb892..5131509cdf0 100644
--- a/src/test/ui/impl-trait/issue-55872-1.stderr
+++ b/src/test/ui/impl-trait/issue-55872-1.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `S: std::marker::Copy` is not satisfied in `(S, T)`
-  --> $DIR/issue-55872-1.rs:12:5
+  --> $DIR/issue-55872-1.rs:12:14
    |
 LL |     type E = impl Copy;
-   |     ^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `std::marker::Copy` is not implemented for `S`
+   |              ^^^^^^^^^ within `(S, T)`, the trait `std::marker::Copy` is not implemented for `S`
    |
    = note: required because it appears within the type `(S, T)`
    = note: the return type of a function must have a statically known size
@@ -12,10 +12,10 @@ LL | impl<S: Default + std::marker::Copy> Bar for S {
    |                 ^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied in `(S, T)`
-  --> $DIR/issue-55872-1.rs:12:5
+  --> $DIR/issue-55872-1.rs:12:14
    |
 LL |     type E = impl Copy;
-   |     ^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `std::marker::Copy` is not implemented for `T`
+   |              ^^^^^^^^^ within `(S, T)`, the trait `std::marker::Copy` is not implemented for `T`
    |
    = note: required because it appears within the type `(S, T)`
    = note: the return type of a function must have a statically known size
diff --git a/src/test/ui/impl-trait/issue-55872-2.stderr b/src/test/ui/impl-trait/issue-55872-2.stderr
index 01371b4d5c6..649109e4c93 100644
--- a/src/test/ui/impl-trait/issue-55872-2.stderr
+++ b/src/test/ui/impl-trait/issue-55872-2.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `impl std::future::Future: std::marker::Copy` is not satisfied
-  --> $DIR/issue-55872-2.rs:13:5
+  --> $DIR/issue-55872-2.rs:13:14
    |
 LL |     type E = impl Copy;
-   |     ^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `impl std::future::Future`
+   |              ^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `impl std::future::Future`
    |
    = note: the return type of a function must have a statically known size
 
diff --git a/src/test/ui/impl-trait/issue-60473.rs b/src/test/ui/impl-trait/issue-60473.rs
index 50cf0c8c6d6..2ef86f03d34 100644
--- a/src/test/ui/impl-trait/issue-60473.rs
+++ b/src/test/ui/impl-trait/issue-60473.rs
@@ -5,13 +5,11 @@
 
 struct A<'a>(&'a ());
 
-trait Trait<T> {
-}
+trait Trait<T> {}
 
-impl<T> Trait<T> for () {
-}
+impl<T> Trait<T> for () {}
 
 fn main() {
-    let x: impl Trait<A> = (); // FIXME: The error doesn't seem correct.
-    //~^ ERROR: opaque type expands to a recursive type
+    let x: impl Trait<A> = ();
+    //~^ ERROR: missing lifetime specifier
 }
diff --git a/src/test/ui/impl-trait/issue-60473.stderr b/src/test/ui/impl-trait/issue-60473.stderr
index 2d95be4e52c..367b5db5d2d 100644
--- a/src/test/ui/impl-trait/issue-60473.stderr
+++ b/src/test/ui/impl-trait/issue-60473.stderr
@@ -1,11 +1,15 @@
-error[E0720]: opaque type expands to a recursive type
-  --> $DIR/issue-60473.rs:15:12
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-60473.rs:13:23
    |
-LL |     let x: impl Trait<A> = (); // FIXME: The error doesn't seem correct.
-   |            ^^^^^^^^^^^^^ expands to a recursive type
+LL |     let x: impl Trait<A> = ();
+   |                       ^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | fn main<'a>() {
+LL |     let x: impl Trait<A<'a>> = ();
    |
-   = note: type resolves to itself
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0720`.
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/impl-trait/issue-67166.rs b/src/test/ui/impl-trait/issue-67166.rs
index de7433a9bfc..efa67558bd7 100644
--- a/src/test/ui/impl-trait/issue-67166.rs
+++ b/src/test/ui/impl-trait/issue-67166.rs
@@ -4,8 +4,8 @@
 #![allow(incomplete_features)]
 
 pub fn run() {
-    let _foo: Box<impl Copy + '_> = Box::new(()); // FIXME: The error doesn't much make sense.
-    //~^ ERROR: opaque type expands to a recursive type
+    let _foo: Box<impl Copy + '_> = Box::new(());
+    //~^ ERROR: missing lifetime specifier
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/issue-67166.stderr b/src/test/ui/impl-trait/issue-67166.stderr
index 56cba3cff0b..14c78684e3e 100644
--- a/src/test/ui/impl-trait/issue-67166.stderr
+++ b/src/test/ui/impl-trait/issue-67166.stderr
@@ -1,11 +1,15 @@
-error[E0720]: opaque type expands to a recursive type
-  --> $DIR/issue-67166.rs:7:19
+error[E0106]: missing lifetime specifier
+  --> $DIR/issue-67166.rs:7:31
    |
-LL |     let _foo: Box<impl Copy + '_> = Box::new(()); // FIXME: The error doesn't much make sense.
-   |                   ^^^^^^^^^^^^^^ expands to a recursive type
+LL |     let _foo: Box<impl Copy + '_> = Box::new(());
+   |                               ^^ expected named lifetime parameter
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL | pub fn run<'a>() {
+LL |     let _foo: Box<impl Copy + 'a> = Box::new(());
    |
-   = note: type resolves to itself
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0720`.
+For more information about this error, try `rustc --explain E0106`.
diff --git a/src/test/ui/impl-trait/negative-reasoning.rs b/src/test/ui/impl-trait/negative-reasoning.rs
index 4977f9bdbac..d173fe83fb7 100644
--- a/src/test/ui/impl-trait/negative-reasoning.rs
+++ b/src/test/ui/impl-trait/negative-reasoning.rs
@@ -2,21 +2,22 @@
 // other trait
 #![feature(type_alias_impl_trait)]
 
-trait OpaqueTrait { }
-impl<T> OpaqueTrait for T { }
+trait OpaqueTrait {}
+impl<T> OpaqueTrait for T {}
 type OpaqueType = impl OpaqueTrait;
-fn mk_opaque() -> OpaqueType { () }
+fn mk_opaque() -> OpaqueType {
+    ()
+}
 
 #[derive(Debug)]
 struct D<T>(T);
 
-trait AnotherTrait { }
-impl<T: std::fmt::Debug> AnotherTrait for T { }
-
+trait AnotherTrait {}
+impl<T: std::fmt::Debug> AnotherTrait for T {}
 
 // This is in error, because we cannot assume that `OpaqueType: !Debug`
 impl AnotherTrait for D<OpaqueType> {
-    //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`
+    //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>`
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/negative-reasoning.stderr b/src/test/ui/impl-trait/negative-reasoning.stderr
index 526a664726a..e43d8c857b2 100644
--- a/src/test/ui/impl-trait/negative-reasoning.stderr
+++ b/src/test/ui/impl-trait/negative-reasoning.stderr
@@ -1,13 +1,13 @@
-error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<OpaqueType>`:
-  --> $DIR/negative-reasoning.rs:18:1
+error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<impl OpaqueTrait>`:
+  --> $DIR/negative-reasoning.rs:19:1
    |
-LL | impl<T: std::fmt::Debug> AnotherTrait for T { }
+LL | impl<T: std::fmt::Debug> AnotherTrait for T {}
    | ------------------------------------------- first implementation here
 ...
 LL | impl AnotherTrait for D<OpaqueType> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<impl OpaqueTrait>`
    |
-   = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `OpaqueType` in future versions
+   = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `impl OpaqueTrait` in future versions
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/where-allowed.stderr b/src/test/ui/impl-trait/where-allowed.stderr
index 5d9ae6a0301..7addc006e19 100644
--- a/src/test/ui/impl-trait/where-allowed.stderr
+++ b/src/test/ui/impl-trait/where-allowed.stderr
@@ -256,16 +256,16 @@ LL |     let _in_return_in_local_variable = || -> impl Fn() { || {} };
    |                                              ^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/where-allowed.rs:155:1
+  --> $DIR/where-allowed.rs:119:16
    |
-LL | type InTypeAlias<R> = impl Debug;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     type Out = impl Debug;
+   |                ^^^^^^^^^^
 
 error: could not find defining uses
-  --> $DIR/where-allowed.rs:119:5
+  --> $DIR/where-allowed.rs:155:23
    |
-LL |     type Out = impl Debug;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+LL | type InTypeAlias<R> = impl Debug;
+   |                       ^^^^^^^^^^
 
 error: aborting due to 42 previous errors
 
diff --git a/src/test/ui/infinite/infinite-recursion-const-fn.stderr b/src/test/ui/infinite/infinite-recursion-const-fn.stderr
index 6bd5e035f57..de0c579f630 100644
--- a/src/test/ui/infinite/infinite-recursion-const-fn.stderr
+++ b/src/test/ui/infinite/infinite-recursion-const-fn.stderr
@@ -1,14 +1,14 @@
 error[E0391]: cycle detected when const-evaluating `a`
-  --> $DIR/infinite-recursion-const-fn.rs:3:25
+  --> $DIR/infinite-recursion-const-fn.rs:3:1
    |
 LL | const fn a() -> usize { b() }
-   |                         ^^^
+   | ^^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires const-evaluating `b`...
-  --> $DIR/infinite-recursion-const-fn.rs:4:25
+  --> $DIR/infinite-recursion-const-fn.rs:4:1
    |
 LL | const fn b() -> usize { a() }
-   |                         ^^^
+   | ^^^^^^^^^^^^^^^^^^^^^
    = note: ...which again requires const-evaluating `a`, completing the cycle
 note: cycle used when const-evaluating `ARR::{{constant}}#0`
   --> $DIR/infinite-recursion-const-fn.rs:5:18
diff --git a/src/test/ui/infinite/infinite-tag-type-recursion.stderr b/src/test/ui/infinite/infinite-tag-type-recursion.stderr
index 11f82b842ba..6d1df4fda2e 100644
--- a/src/test/ui/infinite/infinite-tag-type-recursion.stderr
+++ b/src/test/ui/infinite/infinite-tag-type-recursion.stderr
@@ -6,7 +6,10 @@ LL | enum MList { Cons(isize, MList), Nil }
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `MList` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `MList` representable
+   |
+LL | enum MList { Cons(isize, Box<MList>), Nil }
+   |                          ^^^^     ^
 
 error[E0391]: cycle detected when computing drop-check constraints for `MList`
   --> $DIR/infinite-tag-type-recursion.rs:1:1
diff --git a/src/test/ui/issues/issue-12127.stderr b/src/test/ui/issues/issue-12127.stderr
index 2283b1275d0..b759aa45e3e 100644
--- a/src/test/ui/issues/issue-12127.stderr
+++ b/src/test/ui/issues/issue-12127.stderr
@@ -2,10 +2,15 @@ error[E0382]: use of moved value: `f`
   --> $DIR/issue-12127.rs:11:9
    |
 LL |         f();
-   |         - value moved here
+   |         --- `f` moved due to this call
 LL |         f();
    |         ^ value used here after move
    |
+note: this value implements `FnOnce`, which causes it to be moved when called
+  --> $DIR/issue-12127.rs:10:9
+   |
+LL |         f();
+   |         ^
    = note: move occurs because `f` has type `[closure@$DIR/issue-12127.rs:8:24: 8:41 x:std::boxed::Box<isize>]`, which does not implement the `Copy` trait
 
 error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-17431-1.stderr b/src/test/ui/issues/issue-17431-1.stderr
index eb5a1366e89..58d087ca199 100644
--- a/src/test/ui/issues/issue-17431-1.stderr
+++ b/src/test/ui/issues/issue-17431-1.stderr
@@ -2,11 +2,14 @@ error[E0072]: recursive type `Foo` has infinite size
   --> $DIR/issue-17431-1.rs:1:1
    |
 LL | struct Foo { foo: Option<Option<Foo>> }
-   | ^^^^^^^^^^   ------------------------ recursive without indirection
+   | ^^^^^^^^^^        ------------------- recursive without indirection
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+   |
+LL | struct Foo { foo: Box<Option<Option<Foo>>> }
+   |                   ^^^^                   ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17431-2.stderr b/src/test/ui/issues/issue-17431-2.stderr
index 3a7b0e9ce79..eba4bf6d1d5 100644
--- a/src/test/ui/issues/issue-17431-2.stderr
+++ b/src/test/ui/issues/issue-17431-2.stderr
@@ -2,21 +2,27 @@ error[E0072]: recursive type `Baz` has infinite size
   --> $DIR/issue-17431-2.rs:1:1
    |
 LL | struct Baz { q: Option<Foo> }
-   | ^^^^^^^^^^   -------------- recursive without indirection
+   | ^^^^^^^^^^      ----------- recursive without indirection
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Baz` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Baz` representable
+   |
+LL | struct Baz { q: Box<Option<Foo>> }
+   |                 ^^^^           ^
 
 error[E0072]: recursive type `Foo` has infinite size
   --> $DIR/issue-17431-2.rs:4:1
    |
 LL | struct Foo { q: Option<Baz> }
-   | ^^^^^^^^^^   -------------- recursive without indirection
+   | ^^^^^^^^^^      ----------- recursive without indirection
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+   |
+LL | struct Foo { q: Box<Option<Baz>> }
+   |                 ^^^^           ^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-17431-3.stderr b/src/test/ui/issues/issue-17431-3.stderr
index 675a2e27142..f6b15d0528a 100644
--- a/src/test/ui/issues/issue-17431-3.stderr
+++ b/src/test/ui/issues/issue-17431-3.stderr
@@ -2,11 +2,14 @@ error[E0072]: recursive type `Foo` has infinite size
   --> $DIR/issue-17431-3.rs:3:1
    |
 LL | struct Foo { foo: Mutex<Option<Foo>> }
-   | ^^^^^^^^^^   ----------------------- recursive without indirection
+   | ^^^^^^^^^^        ------------------ recursive without indirection
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+   |
+LL | struct Foo { foo: Box<Mutex<Option<Foo>>> }
+   |                   ^^^^                  ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17431-4.stderr b/src/test/ui/issues/issue-17431-4.stderr
index aff9071095c..aa709e1ad51 100644
--- a/src/test/ui/issues/issue-17431-4.stderr
+++ b/src/test/ui/issues/issue-17431-4.stderr
@@ -2,11 +2,14 @@ error[E0072]: recursive type `Foo` has infinite size
   --> $DIR/issue-17431-4.rs:3:1
    |
 LL | struct Foo<T> { foo: Option<Option<Foo<T>>>, marker: marker::PhantomData<T> }
-   | ^^^^^^^^^^^^^   --------------------------- recursive without indirection
+   | ^^^^^^^^^^^^^        ---------------------- recursive without indirection
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+   |
+LL | struct Foo<T> { foo: Box<Option<Option<Foo<T>>>>, marker: marker::PhantomData<T> }
+   |                      ^^^^                      ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17431-5.stderr b/src/test/ui/issues/issue-17431-5.stderr
index 537f9f34f55..1558cffb036 100644
--- a/src/test/ui/issues/issue-17431-5.stderr
+++ b/src/test/ui/issues/issue-17431-5.stderr
@@ -2,11 +2,14 @@ error[E0072]: recursive type `Bar` has infinite size
   --> $DIR/issue-17431-5.rs:5:1
    |
 LL | struct Bar<T> { x: Bar<Foo> , marker: marker::PhantomData<T> }
-   | ^^^^^^^^^^^^^   ----------- recursive without indirection
+   | ^^^^^^^^^^^^^      -------- recursive without indirection
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
+   |
+LL | struct Bar<T> { x: Box<Bar<Foo>> , marker: marker::PhantomData<T> }
+   |                    ^^^^        ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17431-6.stderr b/src/test/ui/issues/issue-17431-6.stderr
index cb2dab95014..f2aa2a79c82 100644
--- a/src/test/ui/issues/issue-17431-6.stderr
+++ b/src/test/ui/issues/issue-17431-6.stderr
@@ -6,7 +6,10 @@ LL | enum Foo { X(Mutex<Option<Foo>>) }
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+   |
+LL | enum Foo { X(Box<Mutex<Option<Foo>>>) }
+   |              ^^^^                  ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17431-7.stderr b/src/test/ui/issues/issue-17431-7.stderr
index de70851da4b..684c3089e85 100644
--- a/src/test/ui/issues/issue-17431-7.stderr
+++ b/src/test/ui/issues/issue-17431-7.stderr
@@ -6,7 +6,10 @@ LL | enum Foo { Voo(Option<Option<Foo>>) }
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+   |
+LL | enum Foo { Voo(Box<Option<Option<Foo>>>) }
+   |                ^^^^                   ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17546.stderr b/src/test/ui/issues/issue-17546.stderr
index 8bf40790f0b..95939cf6b38 100644
--- a/src/test/ui/issues/issue-17546.stderr
+++ b/src/test/ui/issues/issue-17546.stderr
@@ -30,11 +30,10 @@ LL |     use std::fmt::Result;
    |
 LL |     use std::io::Result;
    |
-LL |     use std::prelude::v1::Result;
-   |
 LL |     use std::result::Result;
    |
-     and 1 other candidate
+LL |     use std::thread::Result;
+   |
 
 error[E0573]: expected type, found variant `Result`
   --> $DIR/issue-17546.rs:30:13
@@ -48,11 +47,10 @@ LL | use std::fmt::Result;
    |
 LL | use std::io::Result;
    |
-LL | use std::prelude::v1::Result;
-   |
 LL | use std::result::Result;
    |
-     and 1 other candidate
+LL | use std::thread::Result;
+   |
 
 error[E0573]: expected type, found variant `NoResult`
   --> $DIR/issue-17546.rs:35:15
diff --git a/src/test/ui/issues/issue-20605.stderr b/src/test/ui/issues/issue-20605.stderr
index 89df58dd2dc..5e050f27ac5 100644
--- a/src/test/ui/issues/issue-20605.stderr
+++ b/src/test/ui/issues/issue-20605.stderr
@@ -1,10 +1,10 @@
-error[E0277]: the size for values of type `dyn std::iter::Iterator<Item = &mut u8>` cannot be known at compilation time
+error[E0277]: the size for values of type `dyn std::iter::Iterator<Item = &'a mut u8>` cannot be known at compilation time
   --> $DIR/issue-20605.rs:2:17
    |
 LL |     for item in *things { *item = 0 }
    |                 ^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: the trait `std::marker::Sized` is not implemented for `dyn std::iter::Iterator<Item = &mut u8>`
+   = help: the trait `std::marker::Sized` is not implemented for `dyn std::iter::Iterator<Item = &'a mut u8>`
    = 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 by `std::iter::IntoIterator::into_iter`
 
diff --git a/src/test/ui/issues/issue-2718-a.stderr b/src/test/ui/issues/issue-2718-a.stderr
index 0f52c791928..d152ffde4e5 100644
--- a/src/test/ui/issues/issue-2718-a.stderr
+++ b/src/test/ui/issues/issue-2718-a.stderr
@@ -7,7 +7,10 @@ LL |     pub struct Pong(SendPacket<Ping>);
    |     |               recursive without indirection
    |     recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `pingpong::Pong` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `pingpong::Pong` representable
+   |
+LL |     pub struct Pong(Box<SendPacket<Ping>>);
+   |                     ^^^^                ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-3008-1.stderr b/src/test/ui/issues/issue-3008-1.stderr
index f12274134ee..87ee36df216 100644
--- a/src/test/ui/issues/issue-3008-1.stderr
+++ b/src/test/ui/issues/issue-3008-1.stderr
@@ -7,7 +7,10 @@ LL | enum Bar {
 LL |     BarSome(Bar)
    |             --- recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
+   |
+LL |     BarSome(Box<Bar>)
+   |             ^^^^   ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-3008-2.stderr b/src/test/ui/issues/issue-3008-2.stderr
index acc15f4b57c..369a19d37e6 100644
--- a/src/test/ui/issues/issue-3008-2.stderr
+++ b/src/test/ui/issues/issue-3008-2.stderr
@@ -2,11 +2,14 @@ error[E0072]: recursive type `Bar` has infinite size
   --> $DIR/issue-3008-2.rs:2:1
    |
 LL | struct Bar { x: Bar }
-   | ^^^^^^^^^^   ------ recursive without indirection
+   | ^^^^^^^^^^      --- recursive without indirection
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
+   |
+LL | struct Bar { x: Box<Bar> }
+   |                 ^^^^   ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-3008-3.stderr b/src/test/ui/issues/issue-3008-3.stderr
index d08a3d9708d..0b162eff94a 100644
--- a/src/test/ui/issues/issue-3008-3.stderr
+++ b/src/test/ui/issues/issue-3008-3.stderr
@@ -6,7 +6,10 @@ LL | enum E2<T> { V2(E2<E1>, marker::PhantomData<T>), }
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `E2` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `E2` representable
+   |
+LL | enum E2<T> { V2(Box<E2<E1>>, marker::PhantomData<T>), }
+   |                 ^^^^      ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-31910.stderr b/src/test/ui/issues/issue-31910.stderr
index c5c988cdaa7..2603c944207 100644
--- a/src/test/ui/issues/issue-31910.stderr
+++ b/src/test/ui/issues/issue-31910.stderr
@@ -3,11 +3,6 @@ error[E0308]: mismatched types
    |
 LL |     X = Trait::Number,
    |         ^^^^^^^^^^^^^ expected `isize`, found `i32`
-   |
-help: you can convert an `i32` to `isize` and panic if the converted value wouldn't fit
-   |
-LL |     X = Trait::Number.try_into().unwrap(),
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-32326.stderr b/src/test/ui/issues/issue-32326.stderr
index 5967627e51a..0f3d3690b73 100644
--- a/src/test/ui/issues/issue-32326.stderr
+++ b/src/test/ui/issues/issue-32326.stderr
@@ -8,7 +8,10 @@ LL |     Plus(Expr, Expr),
    |          |
    |          recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Expr` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Expr` representable
+   |
+LL |     Plus(Box<Expr>, Box<Expr>),
+   |          ^^^^    ^  ^^^^    ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-33941.rs b/src/test/ui/issues/issue-33941.rs
index ccaa6334856..4fb805b37e0 100644
--- a/src/test/ui/issues/issue-33941.rs
+++ b/src/test/ui/issues/issue-33941.rs
@@ -3,4 +3,5 @@ use std::collections::HashMap;
 fn main() {
     for _ in HashMap::new().iter().cloned() {} //~ ERROR type mismatch
     //~^ ERROR type mismatch
+    //~| ERROR type mismatch
 }
diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr
index 734ae78f362..20335d2cdd6 100644
--- a/src/test/ui/issues/issue-33941.stderr
+++ b/src/test/ui/issues/issue-33941.stderr
@@ -17,6 +17,16 @@ LL |     for _ in HashMap::new().iter().cloned() {}
            found reference `&_`
    = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Cloned<std::collections::hash_map::Iter<'_, _, _>>`
 
-error: aborting due to 2 previous errors
+error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> as std::iter::Iterator>::Item == &_`
+  --> $DIR/issue-33941.rs:4:14
+   |
+LL |     for _ in HashMap::new().iter().cloned() {}
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference
+   |
+   = note:  expected tuple `(&_, &_)`
+           found reference `&_`
+   = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Cloned<std::collections::hash_map::Iter<'_, _, _>>`
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/issues/issue-34721.stderr b/src/test/ui/issues/issue-34721.stderr
index 6cfed20f43a..b4cc1a0aa7e 100644
--- a/src/test/ui/issues/issue-34721.stderr
+++ b/src/test/ui/issues/issue-34721.stderr
@@ -5,14 +5,19 @@ LL |     pub fn baz<T: Foo>(x: T) -> T {
    |                        - move occurs because `x` has type `T`, which does not implement the `Copy` trait
 LL |         if 0 == 1 {
 LL |             bar::bar(x.zero())
-   |                      - value moved here
+   |                        ------ `x` moved due to this method call
 LL |         } else {
 LL |             x.zero()
-   |             - value moved here
+   |               ------ `x` moved due to this method call
 LL |         };
 LL |         x.zero()
    |         ^ value used here after move
    |
+note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
+  --> $DIR/issue-34721.rs:4:13
+   |
+LL |     fn zero(self) -> Self;
+   |             ^^^^
 help: consider further restricting this bound
    |
 LL |     pub fn baz<T: Foo + Copy>(x: T) -> T {
diff --git a/src/test/ui/issues/issue-3779.stderr b/src/test/ui/issues/issue-3779.stderr
index ba1e842c610..7b17e914216 100644
--- a/src/test/ui/issues/issue-3779.stderr
+++ b/src/test/ui/issues/issue-3779.stderr
@@ -5,9 +5,12 @@ LL | struct S {
    | ^^^^^^^^ recursive type has infinite size
 LL |
 LL |     element: Option<S>
-   |     ------------------ recursive without indirection
+   |              --------- recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `S` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `S` representable
+   |
+LL |     element: Box<Option<S>>
+   |              ^^^^         ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-40510-1.stderr b/src/test/ui/issues/issue-40510-1.stderr
index f4fda0abc20..54df40b6e3d 100644
--- a/src/test/ui/issues/issue-40510-1.stderr
+++ b/src/test/ui/issues/issue-40510-1.stderr
@@ -1,10 +1,16 @@
 error: captured variable cannot escape `FnMut` closure body
   --> $DIR/issue-40510-1.rs:7:9
    |
+LL |     let mut x: Box<()> = Box::new(());
+   |         ----- variable defined here
+LL | 
 LL |     || {
    |      - inferred to be a `FnMut` closure
 LL |         &mut x
-   |         ^^^^^^ returns a reference to a captured variable which escapes the closure body
+   |         ^^^^^-
+   |         |    |
+   |         |    variable captured here
+   |         returns a reference to a captured variable which escapes the closure body
    |
    = note: `FnMut` closures only have access to their captured variables while they are executing...
    = note: ...therefore, they cannot allow references to captured variables to escape
diff --git a/src/test/ui/issues/issue-40510-3.stderr b/src/test/ui/issues/issue-40510-3.stderr
index 4bc7d0f5dea..cb885ec7d95 100644
--- a/src/test/ui/issues/issue-40510-3.stderr
+++ b/src/test/ui/issues/issue-40510-3.stderr
@@ -1,10 +1,14 @@
 error: captured variable cannot escape `FnMut` closure body
   --> $DIR/issue-40510-3.rs:7:9
    |
+LL |       let mut x: Vec<()> = Vec::new();
+   |           ----- variable defined here
+LL | 
 LL |       || {
    |        - inferred to be a `FnMut` closure
 LL | /         || {
 LL | |             x.push(())
+   | |             - variable captured here
 LL | |         }
    | |_________^ returns a closure that contains a reference to a captured variable, which then escapes the closure body
    |
diff --git a/src/test/ui/issues/issue-44216-add-instant.rs b/src/test/ui/issues/issue-44216-add-instant.rs
index c2f3598f645..78cfecf2f32 100644
--- a/src/test/ui/issues/issue-44216-add-instant.rs
+++ b/src/test/ui/issues/issue-44216-add-instant.rs
@@ -6,5 +6,5 @@ use std::time::{Instant, Duration};
 
 fn main() {
     let now = Instant::now();
-    let _ = now + Duration::from_secs(u64::max_value());
+    let _ = now + Duration::from_secs(u64::MAX);
 }
diff --git a/src/test/ui/issues/issue-44216-add-system-time.rs b/src/test/ui/issues/issue-44216-add-system-time.rs
index 9a88cb7c189..7e9a3f802ec 100644
--- a/src/test/ui/issues/issue-44216-add-system-time.rs
+++ b/src/test/ui/issues/issue-44216-add-system-time.rs
@@ -6,5 +6,5 @@ use std::time::{Duration, SystemTime};
 
 fn main() {
     let now = SystemTime::now();
-    let _ = now + Duration::from_secs(u64::max_value());
+    let _ = now + Duration::from_secs(u64::MAX);
 }
diff --git a/src/test/ui/issues/issue-44216-sub-instant.rs b/src/test/ui/issues/issue-44216-sub-instant.rs
index 2decd88bbc0..e40f80d449d 100644
--- a/src/test/ui/issues/issue-44216-sub-instant.rs
+++ b/src/test/ui/issues/issue-44216-sub-instant.rs
@@ -6,5 +6,5 @@ use std::time::{Instant, Duration};
 
 fn main() {
     let now = Instant::now();
-    let _ = now - Duration::from_secs(u64::max_value());
+    let _ = now - Duration::from_secs(u64::MAX);
 }
diff --git a/src/test/ui/issues/issue-44216-sub-system-time.rs b/src/test/ui/issues/issue-44216-sub-system-time.rs
index e58a31a41a5..2c5a000fab6 100644
--- a/src/test/ui/issues/issue-44216-sub-system-time.rs
+++ b/src/test/ui/issues/issue-44216-sub-system-time.rs
@@ -6,5 +6,5 @@ use std::time::{Duration, SystemTime};
 
 fn main() {
     let now = SystemTime::now();
-    let _ = now - Duration::from_secs(u64::max_value());
+    let _ = now - Duration::from_secs(u64::MAX);
 }
diff --git a/src/test/ui/issues/issue-49824.stderr b/src/test/ui/issues/issue-49824.stderr
index 6b486aafcdf..2fec482543d 100644
--- a/src/test/ui/issues/issue-49824.stderr
+++ b/src/test/ui/issues/issue-49824.stderr
@@ -1,11 +1,14 @@
 error: captured variable cannot escape `FnMut` closure body
   --> $DIR/issue-49824.rs:4:9
    |
+LL |       let mut x = 0;
+   |           ----- variable defined here
 LL |       || {
    |        - inferred to be a `FnMut` closure
 LL | /         || {
 LL | |
 LL | |             let _y = &mut x;
+   | |                           - variable captured here
 LL | |         }
    | |_________^ returns a closure that contains a reference to a captured variable, which then escapes the closure body
    |
diff --git a/src/test/ui/issues/issue-57271.stderr b/src/test/ui/issues/issue-57271.stderr
index 4f164624f7a..b7c799e163c 100644
--- a/src/test/ui/issues/issue-57271.stderr
+++ b/src/test/ui/issues/issue-57271.stderr
@@ -7,7 +7,10 @@ LL |     Class(ClassTypeSignature),
 LL |     Array(TypeSignature),
    |           ------------- recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ObjectType` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ObjectType` representable
+   |
+LL |     Array(Box<TypeSignature>),
+   |           ^^^^             ^
 
 error[E0072]: recursive type `TypeSignature` has infinite size
   --> $DIR/issue-57271.rs:19:1
@@ -18,7 +21,10 @@ LL |     Base(BaseType),
 LL |     Object(ObjectType),
    |            ---------- recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `TypeSignature` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `TypeSignature` representable
+   |
+LL |     Object(Box<ObjectType>),
+   |            ^^^^          ^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-60662.stdout b/src/test/ui/issues/issue-60662.stdout
index 5a4b49cfa1e..cebe834824a 100644
--- a/src/test/ui/issues/issue-60662.stdout
+++ b/src/test/ui/issues/issue-60662.stdout
@@ -10,5 +10,5 @@ extern crate std;
 trait Animal { }
 
 fn main() {
-              pub type ServeFut = impl Animal;
+              pub type ServeFut = /*impl Trait*/;
           }
diff --git a/src/test/ui/issues/issue-61108.stderr b/src/test/ui/issues/issue-61108.stderr
index 8523a6f6548..ba43f2d33ee 100644
--- a/src/test/ui/issues/issue-61108.stderr
+++ b/src/test/ui/issues/issue-61108.stderr
@@ -6,11 +6,17 @@ LL |     let mut bad_letters = vec!['e', 't', 'o', 'i'];
 LL |     for l in bad_letters {
    |              -----------
    |              |
-   |              value moved here
+   |              `bad_letters` moved due to this implicit call to `.into_iter()`
    |              help: consider borrowing to avoid moving into the for loop: `&bad_letters`
 ...
 LL |     bad_letters.push('s');
    |     ^^^^^^^^^^^ value borrowed here after move
+   |
+note: this function consumes the receiver `self` by taking ownership of it, which moves `bad_letters`
+  --> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |                  ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-64559.stderr b/src/test/ui/issues/issue-64559.stderr
index 3c685dc8d08..2c337bae130 100644
--- a/src/test/ui/issues/issue-64559.stderr
+++ b/src/test/ui/issues/issue-64559.stderr
@@ -6,12 +6,18 @@ LL |     let orig = vec![true];
 LL |     for _val in orig {}
    |                 ----
    |                 |
-   |                 value moved here
+   |                 `orig` moved due to this implicit call to `.into_iter()`
    |                 help: consider borrowing to avoid moving into the for loop: `&orig`
 LL |     let _closure = || orig;
    |                    ^^ ---- use occurs due to use in closure
    |                    |
    |                    value used here after move
+   |
+note: this function consumes the receiver `self` by taking ownership of it, which moves `orig`
+  --> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |                  ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-72554.stderr b/src/test/ui/issues/issue-72554.stderr
index 9db65f4a2ee..9de94c393a7 100644
--- a/src/test/ui/issues/issue-72554.stderr
+++ b/src/test/ui/issues/issue-72554.stderr
@@ -6,7 +6,10 @@ LL | pub enum ElemDerived {
 LL |     A(ElemDerived)
    |       ----------- recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ElemDerived` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ElemDerived` representable
+   |
+LL |     A(Box<ElemDerived>)
+   |       ^^^^           ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-72839-error-overflow.rs b/src/test/ui/issues/issue-72839-error-overflow.rs
new file mode 100644
index 00000000000..6562d228409
--- /dev/null
+++ b/src/test/ui/issues/issue-72839-error-overflow.rs
@@ -0,0 +1,19 @@
+// Regression test for issue #72839
+// Tests that we do not overflow during trait selection after
+// a type error occurs
+use std::ops::Rem;
+trait Foo {}
+struct MyStruct<T>(T);
+
+impl<T, U> Rem<MyStruct<T>> for MyStruct<U> where MyStruct<U>: Rem<MyStruct<T>> {
+    type Output = u8;
+    fn rem(self, _: MyStruct<T>) -> Self::Output {
+        panic!()
+    }
+}
+
+fn main() {}
+
+fn foo() {
+    if missing_var % 8 == 0 {} //~ ERROR cannot find
+}
diff --git a/src/test/ui/issues/issue-72839-error-overflow.stderr b/src/test/ui/issues/issue-72839-error-overflow.stderr
new file mode 100644
index 00000000000..c4b6f90ca69
--- /dev/null
+++ b/src/test/ui/issues/issue-72839-error-overflow.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `missing_var` in this scope
+  --> $DIR/issue-72839-error-overflow.rs:18:8
+   |
+LL |     if missing_var % 8 == 0 {}
+   |        ^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-72933-match-stack-overflow.rs b/src/test/ui/issues/issue-72933-match-stack-overflow.rs
new file mode 100644
index 00000000000..aa796bcf5a0
--- /dev/null
+++ b/src/test/ui/issues/issue-72933-match-stack-overflow.rs
@@ -0,0 +1,5208 @@
+// build-pass
+// ignore-tidy-filelength
+#![crate_type="rlib"]
+
+fn banana(v: &str) -> u32 {
+    match v {
+        "0" => 0,
+        "1" => 1,
+        "2" => 2,
+        "3" => 3,
+        "4" => 4,
+        "5" => 5,
+        "6" => 6,
+        "7" => 7,
+        "8" => 8,
+        "9" => 9,
+        "10" => 10,
+        "11" => 11,
+        "12" => 12,
+        "13" => 13,
+        "14" => 14,
+        "15" => 15,
+        "16" => 16,
+        "17" => 17,
+        "18" => 18,
+        "19" => 19,
+        "20" => 20,
+        "21" => 21,
+        "22" => 22,
+        "23" => 23,
+        "24" => 24,
+        "25" => 25,
+        "26" => 26,
+        "27" => 27,
+        "28" => 28,
+        "29" => 29,
+        "30" => 30,
+        "31" => 31,
+        "32" => 32,
+        "33" => 33,
+        "34" => 34,
+        "35" => 35,
+        "36" => 36,
+        "37" => 37,
+        "38" => 38,
+        "39" => 39,
+        "40" => 40,
+        "41" => 41,
+        "42" => 42,
+        "43" => 43,
+        "44" => 44,
+        "45" => 45,
+        "46" => 46,
+        "47" => 47,
+        "48" => 48,
+        "49" => 49,
+        "50" => 50,
+        "51" => 51,
+        "52" => 52,
+        "53" => 53,
+        "54" => 54,
+        "55" => 55,
+        "56" => 56,
+        "57" => 57,
+        "58" => 58,
+        "59" => 59,
+        "60" => 60,
+        "61" => 61,
+        "62" => 62,
+        "63" => 63,
+        "64" => 64,
+        "65" => 65,
+        "66" => 66,
+        "67" => 67,
+        "68" => 68,
+        "69" => 69,
+        "70" => 70,
+        "71" => 71,
+        "72" => 72,
+        "73" => 73,
+        "74" => 74,
+        "75" => 75,
+        "76" => 76,
+        "77" => 77,
+        "78" => 78,
+        "79" => 79,
+        "80" => 80,
+        "81" => 81,
+        "82" => 82,
+        "83" => 83,
+        "84" => 84,
+        "85" => 85,
+        "86" => 86,
+        "87" => 87,
+        "88" => 88,
+        "89" => 89,
+        "90" => 90,
+        "91" => 91,
+        "92" => 92,
+        "93" => 93,
+        "94" => 94,
+        "95" => 95,
+        "96" => 96,
+        "97" => 97,
+        "98" => 98,
+        "99" => 99,
+        "100" => 100,
+        "101" => 101,
+        "102" => 102,
+        "103" => 103,
+        "104" => 104,
+        "105" => 105,
+        "106" => 106,
+        "107" => 107,
+        "108" => 108,
+        "109" => 109,
+        "110" => 110,
+        "111" => 111,
+        "112" => 112,
+        "113" => 113,
+        "114" => 114,
+        "115" => 115,
+        "116" => 116,
+        "117" => 117,
+        "118" => 118,
+        "119" => 119,
+        "120" => 120,
+        "121" => 121,
+        "122" => 122,
+        "123" => 123,
+        "124" => 124,
+        "125" => 125,
+        "126" => 126,
+        "127" => 127,
+        "128" => 128,
+        "129" => 129,
+        "130" => 130,
+        "131" => 131,
+        "132" => 132,
+        "133" => 133,
+        "134" => 134,
+        "135" => 135,
+        "136" => 136,
+        "137" => 137,
+        "138" => 138,
+        "139" => 139,
+        "140" => 140,
+        "141" => 141,
+        "142" => 142,
+        "143" => 143,
+        "144" => 144,
+        "145" => 145,
+        "146" => 146,
+        "147" => 147,
+        "148" => 148,
+        "149" => 149,
+        "150" => 150,
+        "151" => 151,
+        "152" => 152,
+        "153" => 153,
+        "154" => 154,
+        "155" => 155,
+        "156" => 156,
+        "157" => 157,
+        "158" => 158,
+        "159" => 159,
+        "160" => 160,
+        "161" => 161,
+        "162" => 162,
+        "163" => 163,
+        "164" => 164,
+        "165" => 165,
+        "166" => 166,
+        "167" => 167,
+        "168" => 168,
+        "169" => 169,
+        "170" => 170,
+        "171" => 171,
+        "172" => 172,
+        "173" => 173,
+        "174" => 174,
+        "175" => 175,
+        "176" => 176,
+        "177" => 177,
+        "178" => 178,
+        "179" => 179,
+        "180" => 180,
+        "181" => 181,
+        "182" => 182,
+        "183" => 183,
+        "184" => 184,
+        "185" => 185,
+        "186" => 186,
+        "187" => 187,
+        "188" => 188,
+        "189" => 189,
+        "190" => 190,
+        "191" => 191,
+        "192" => 192,
+        "193" => 193,
+        "194" => 194,
+        "195" => 195,
+        "196" => 196,
+        "197" => 197,
+        "198" => 198,
+        "199" => 199,
+        "200" => 200,
+        "201" => 201,
+        "202" => 202,
+        "203" => 203,
+        "204" => 204,
+        "205" => 205,
+        "206" => 206,
+        "207" => 207,
+        "208" => 208,
+        "209" => 209,
+        "210" => 210,
+        "211" => 211,
+        "212" => 212,
+        "213" => 213,
+        "214" => 214,
+        "215" => 215,
+        "216" => 216,
+        "217" => 217,
+        "218" => 218,
+        "219" => 219,
+        "220" => 220,
+        "221" => 221,
+        "222" => 222,
+        "223" => 223,
+        "224" => 224,
+        "225" => 225,
+        "226" => 226,
+        "227" => 227,
+        "228" => 228,
+        "229" => 229,
+        "230" => 230,
+        "231" => 231,
+        "232" => 232,
+        "233" => 233,
+        "234" => 234,
+        "235" => 235,
+        "236" => 236,
+        "237" => 237,
+        "238" => 238,
+        "239" => 239,
+        "240" => 240,
+        "241" => 241,
+        "242" => 242,
+        "243" => 243,
+        "244" => 244,
+        "245" => 245,
+        "246" => 246,
+        "247" => 247,
+        "248" => 248,
+        "249" => 249,
+        "250" => 250,
+        "251" => 251,
+        "252" => 252,
+        "253" => 253,
+        "254" => 254,
+        "255" => 255,
+        "256" => 256,
+        "257" => 257,
+        "258" => 258,
+        "259" => 259,
+        "260" => 260,
+        "261" => 261,
+        "262" => 262,
+        "263" => 263,
+        "264" => 264,
+        "265" => 265,
+        "266" => 266,
+        "267" => 267,
+        "268" => 268,
+        "269" => 269,
+        "270" => 270,
+        "271" => 271,
+        "272" => 272,
+        "273" => 273,
+        "274" => 274,
+        "275" => 275,
+        "276" => 276,
+        "277" => 277,
+        "278" => 278,
+        "279" => 279,
+        "280" => 280,
+        "281" => 281,
+        "282" => 282,
+        "283" => 283,
+        "284" => 284,
+        "285" => 285,
+        "286" => 286,
+        "287" => 287,
+        "288" => 288,
+        "289" => 289,
+        "290" => 290,
+        "291" => 291,
+        "292" => 292,
+        "293" => 293,
+        "294" => 294,
+        "295" => 295,
+        "296" => 296,
+        "297" => 297,
+        "298" => 298,
+        "299" => 299,
+        "300" => 300,
+        "301" => 301,
+        "302" => 302,
+        "303" => 303,
+        "304" => 304,
+        "305" => 305,
+        "306" => 306,
+        "307" => 307,
+        "308" => 308,
+        "309" => 309,
+        "310" => 310,
+        "311" => 311,
+        "312" => 312,
+        "313" => 313,
+        "314" => 314,
+        "315" => 315,
+        "316" => 316,
+        "317" => 317,
+        "318" => 318,
+        "319" => 319,
+        "320" => 320,
+        "321" => 321,
+        "322" => 322,
+        "323" => 323,
+        "324" => 324,
+        "325" => 325,
+        "326" => 326,
+        "327" => 327,
+        "328" => 328,
+        "329" => 329,
+        "330" => 330,
+        "331" => 331,
+        "332" => 332,
+        "333" => 333,
+        "334" => 334,
+        "335" => 335,
+        "336" => 336,
+        "337" => 337,
+        "338" => 338,
+        "339" => 339,
+        "340" => 340,
+        "341" => 341,
+        "342" => 342,
+        "343" => 343,
+        "344" => 344,
+        "345" => 345,
+        "346" => 346,
+        "347" => 347,
+        "348" => 348,
+        "349" => 349,
+        "350" => 350,
+        "351" => 351,
+        "352" => 352,
+        "353" => 353,
+        "354" => 354,
+        "355" => 355,
+        "356" => 356,
+        "357" => 357,
+        "358" => 358,
+        "359" => 359,
+        "360" => 360,
+        "361" => 361,
+        "362" => 362,
+        "363" => 363,
+        "364" => 364,
+        "365" => 365,
+        "366" => 366,
+        "367" => 367,
+        "368" => 368,
+        "369" => 369,
+        "370" => 370,
+        "371" => 371,
+        "372" => 372,
+        "373" => 373,
+        "374" => 374,
+        "375" => 375,
+        "376" => 376,
+        "377" => 377,
+        "378" => 378,
+        "379" => 379,
+        "380" => 380,
+        "381" => 381,
+        "382" => 382,
+        "383" => 383,
+        "384" => 384,
+        "385" => 385,
+        "386" => 386,
+        "387" => 387,
+        "388" => 388,
+        "389" => 389,
+        "390" => 390,
+        "391" => 391,
+        "392" => 392,
+        "393" => 393,
+        "394" => 394,
+        "395" => 395,
+        "396" => 396,
+        "397" => 397,
+        "398" => 398,
+        "399" => 399,
+        "400" => 400,
+        "401" => 401,
+        "402" => 402,
+        "403" => 403,
+        "404" => 404,
+        "405" => 405,
+        "406" => 406,
+        "407" => 407,
+        "408" => 408,
+        "409" => 409,
+        "410" => 410,
+        "411" => 411,
+        "412" => 412,
+        "413" => 413,
+        "414" => 414,
+        "415" => 415,
+        "416" => 416,
+        "417" => 417,
+        "418" => 418,
+        "419" => 419,
+        "420" => 420,
+        "421" => 421,
+        "422" => 422,
+        "423" => 423,
+        "424" => 424,
+        "425" => 425,
+        "426" => 426,
+        "427" => 427,
+        "428" => 428,
+        "429" => 429,
+        "430" => 430,
+        "431" => 431,
+        "432" => 432,
+        "433" => 433,
+        "434" => 434,
+        "435" => 435,
+        "436" => 436,
+        "437" => 437,
+        "438" => 438,
+        "439" => 439,
+        "440" => 440,
+        "441" => 441,
+        "442" => 442,
+        "443" => 443,
+        "444" => 444,
+        "445" => 445,
+        "446" => 446,
+        "447" => 447,
+        "448" => 448,
+        "449" => 449,
+        "450" => 450,
+        "451" => 451,
+        "452" => 452,
+        "453" => 453,
+        "454" => 454,
+        "455" => 455,
+        "456" => 456,
+        "457" => 457,
+        "458" => 458,
+        "459" => 459,
+        "460" => 460,
+        "461" => 461,
+        "462" => 462,
+        "463" => 463,
+        "464" => 464,
+        "465" => 465,
+        "466" => 466,
+        "467" => 467,
+        "468" => 468,
+        "469" => 469,
+        "470" => 470,
+        "471" => 471,
+        "472" => 472,
+        "473" => 473,
+        "474" => 474,
+        "475" => 475,
+        "476" => 476,
+        "477" => 477,
+        "478" => 478,
+        "479" => 479,
+        "480" => 480,
+        "481" => 481,
+        "482" => 482,
+        "483" => 483,
+        "484" => 484,
+        "485" => 485,
+        "486" => 486,
+        "487" => 487,
+        "488" => 488,
+        "489" => 489,
+        "490" => 490,
+        "491" => 491,
+        "492" => 492,
+        "493" => 493,
+        "494" => 494,
+        "495" => 495,
+        "496" => 496,
+        "497" => 497,
+        "498" => 498,
+        "499" => 499,
+        "500" => 500,
+        "501" => 501,
+        "502" => 502,
+        "503" => 503,
+        "504" => 504,
+        "505" => 505,
+        "506" => 506,
+        "507" => 507,
+        "508" => 508,
+        "509" => 509,
+        "510" => 510,
+        "511" => 511,
+        "512" => 512,
+        "513" => 513,
+        "514" => 514,
+        "515" => 515,
+        "516" => 516,
+        "517" => 517,
+        "518" => 518,
+        "519" => 519,
+        "520" => 520,
+        "521" => 521,
+        "522" => 522,
+        "523" => 523,
+        "524" => 524,
+        "525" => 525,
+        "526" => 526,
+        "527" => 527,
+        "528" => 528,
+        "529" => 529,
+        "530" => 530,
+        "531" => 531,
+        "532" => 532,
+        "533" => 533,
+        "534" => 534,
+        "535" => 535,
+        "536" => 536,
+        "537" => 537,
+        "538" => 538,
+        "539" => 539,
+        "540" => 540,
+        "541" => 541,
+        "542" => 542,
+        "543" => 543,
+        "544" => 544,
+        "545" => 545,
+        "546" => 546,
+        "547" => 547,
+        "548" => 548,
+        "549" => 549,
+        "550" => 550,
+        "551" => 551,
+        "552" => 552,
+        "553" => 553,
+        "554" => 554,
+        "555" => 555,
+        "556" => 556,
+        "557" => 557,
+        "558" => 558,
+        "559" => 559,
+        "560" => 560,
+        "561" => 561,
+        "562" => 562,
+        "563" => 563,
+        "564" => 564,
+        "565" => 565,
+        "566" => 566,
+        "567" => 567,
+        "568" => 568,
+        "569" => 569,
+        "570" => 570,
+        "571" => 571,
+        "572" => 572,
+        "573" => 573,
+        "574" => 574,
+        "575" => 575,
+        "576" => 576,
+        "577" => 577,
+        "578" => 578,
+        "579" => 579,
+        "580" => 580,
+        "581" => 581,
+        "582" => 582,
+        "583" => 583,
+        "584" => 584,
+        "585" => 585,
+        "586" => 586,
+        "587" => 587,
+        "588" => 588,
+        "589" => 589,
+        "590" => 590,
+        "591" => 591,
+        "592" => 592,
+        "593" => 593,
+        "594" => 594,
+        "595" => 595,
+        "596" => 596,
+        "597" => 597,
+        "598" => 598,
+        "599" => 599,
+        "600" => 600,
+        "601" => 601,
+        "602" => 602,
+        "603" => 603,
+        "604" => 604,
+        "605" => 605,
+        "606" => 606,
+        "607" => 607,
+        "608" => 608,
+        "609" => 609,
+        "610" => 610,
+        "611" => 611,
+        "612" => 612,
+        "613" => 613,
+        "614" => 614,
+        "615" => 615,
+        "616" => 616,
+        "617" => 617,
+        "618" => 618,
+        "619" => 619,
+        "620" => 620,
+        "621" => 621,
+        "622" => 622,
+        "623" => 623,
+        "624" => 624,
+        "625" => 625,
+        "626" => 626,
+        "627" => 627,
+        "628" => 628,
+        "629" => 629,
+        "630" => 630,
+        "631" => 631,
+        "632" => 632,
+        "633" => 633,
+        "634" => 634,
+        "635" => 635,
+        "636" => 636,
+        "637" => 637,
+        "638" => 638,
+        "639" => 639,
+        "640" => 640,
+        "641" => 641,
+        "642" => 642,
+        "643" => 643,
+        "644" => 644,
+        "645" => 645,
+        "646" => 646,
+        "647" => 647,
+        "648" => 648,
+        "649" => 649,
+        "650" => 650,
+        "651" => 651,
+        "652" => 652,
+        "653" => 653,
+        "654" => 654,
+        "655" => 655,
+        "656" => 656,
+        "657" => 657,
+        "658" => 658,
+        "659" => 659,
+        "660" => 660,
+        "661" => 661,
+        "662" => 662,
+        "663" => 663,
+        "664" => 664,
+        "665" => 665,
+        "666" => 666,
+        "667" => 667,
+        "668" => 668,
+        "669" => 669,
+        "670" => 670,
+        "671" => 671,
+        "672" => 672,
+        "673" => 673,
+        "674" => 674,
+        "675" => 675,
+        "676" => 676,
+        "677" => 677,
+        "678" => 678,
+        "679" => 679,
+        "680" => 680,
+        "681" => 681,
+        "682" => 682,
+        "683" => 683,
+        "684" => 684,
+        "685" => 685,
+        "686" => 686,
+        "687" => 687,
+        "688" => 688,
+        "689" => 689,
+        "690" => 690,
+        "691" => 691,
+        "692" => 692,
+        "693" => 693,
+        "694" => 694,
+        "695" => 695,
+        "696" => 696,
+        "697" => 697,
+        "698" => 698,
+        "699" => 699,
+        "700" => 700,
+        "701" => 701,
+        "702" => 702,
+        "703" => 703,
+        "704" => 704,
+        "705" => 705,
+        "706" => 706,
+        "707" => 707,
+        "708" => 708,
+        "709" => 709,
+        "710" => 710,
+        "711" => 711,
+        "712" => 712,
+        "713" => 713,
+        "714" => 714,
+        "715" => 715,
+        "716" => 716,
+        "717" => 717,
+        "718" => 718,
+        "719" => 719,
+        "720" => 720,
+        "721" => 721,
+        "722" => 722,
+        "723" => 723,
+        "724" => 724,
+        "725" => 725,
+        "726" => 726,
+        "727" => 727,
+        "728" => 728,
+        "729" => 729,
+        "730" => 730,
+        "731" => 731,
+        "732" => 732,
+        "733" => 733,
+        "734" => 734,
+        "735" => 735,
+        "736" => 736,
+        "737" => 737,
+        "738" => 738,
+        "739" => 739,
+        "740" => 740,
+        "741" => 741,
+        "742" => 742,
+        "743" => 743,
+        "744" => 744,
+        "745" => 745,
+        "746" => 746,
+        "747" => 747,
+        "748" => 748,
+        "749" => 749,
+        "750" => 750,
+        "751" => 751,
+        "752" => 752,
+        "753" => 753,
+        "754" => 754,
+        "755" => 755,
+        "756" => 756,
+        "757" => 757,
+        "758" => 758,
+        "759" => 759,
+        "760" => 760,
+        "761" => 761,
+        "762" => 762,
+        "763" => 763,
+        "764" => 764,
+        "765" => 765,
+        "766" => 766,
+        "767" => 767,
+        "768" => 768,
+        "769" => 769,
+        "770" => 770,
+        "771" => 771,
+        "772" => 772,
+        "773" => 773,
+        "774" => 774,
+        "775" => 775,
+        "776" => 776,
+        "777" => 777,
+        "778" => 778,
+        "779" => 779,
+        "780" => 780,
+        "781" => 781,
+        "782" => 782,
+        "783" => 783,
+        "784" => 784,
+        "785" => 785,
+        "786" => 786,
+        "787" => 787,
+        "788" => 788,
+        "789" => 789,
+        "790" => 790,
+        "791" => 791,
+        "792" => 792,
+        "793" => 793,
+        "794" => 794,
+        "795" => 795,
+        "796" => 796,
+        "797" => 797,
+        "798" => 798,
+        "799" => 799,
+        "800" => 800,
+        "801" => 801,
+        "802" => 802,
+        "803" => 803,
+        "804" => 804,
+        "805" => 805,
+        "806" => 806,
+        "807" => 807,
+        "808" => 808,
+        "809" => 809,
+        "810" => 810,
+        "811" => 811,
+        "812" => 812,
+        "813" => 813,
+        "814" => 814,
+        "815" => 815,
+        "816" => 816,
+        "817" => 817,
+        "818" => 818,
+        "819" => 819,
+        "820" => 820,
+        "821" => 821,
+        "822" => 822,
+        "823" => 823,
+        "824" => 824,
+        "825" => 825,
+        "826" => 826,
+        "827" => 827,
+        "828" => 828,
+        "829" => 829,
+        "830" => 830,
+        "831" => 831,
+        "832" => 832,
+        "833" => 833,
+        "834" => 834,
+        "835" => 835,
+        "836" => 836,
+        "837" => 837,
+        "838" => 838,
+        "839" => 839,
+        "840" => 840,
+        "841" => 841,
+        "842" => 842,
+        "843" => 843,
+        "844" => 844,
+        "845" => 845,
+        "846" => 846,
+        "847" => 847,
+        "848" => 848,
+        "849" => 849,
+        "850" => 850,
+        "851" => 851,
+        "852" => 852,
+        "853" => 853,
+        "854" => 854,
+        "855" => 855,
+        "856" => 856,
+        "857" => 857,
+        "858" => 858,
+        "859" => 859,
+        "860" => 860,
+        "861" => 861,
+        "862" => 862,
+        "863" => 863,
+        "864" => 864,
+        "865" => 865,
+        "866" => 866,
+        "867" => 867,
+        "868" => 868,
+        "869" => 869,
+        "870" => 870,
+        "871" => 871,
+        "872" => 872,
+        "873" => 873,
+        "874" => 874,
+        "875" => 875,
+        "876" => 876,
+        "877" => 877,
+        "878" => 878,
+        "879" => 879,
+        "880" => 880,
+        "881" => 881,
+        "882" => 882,
+        "883" => 883,
+        "884" => 884,
+        "885" => 885,
+        "886" => 886,
+        "887" => 887,
+        "888" => 888,
+        "889" => 889,
+        "890" => 890,
+        "891" => 891,
+        "892" => 892,
+        "893" => 893,
+        "894" => 894,
+        "895" => 895,
+        "896" => 896,
+        "897" => 897,
+        "898" => 898,
+        "899" => 899,
+        "900" => 900,
+        "901" => 901,
+        "902" => 902,
+        "903" => 903,
+        "904" => 904,
+        "905" => 905,
+        "906" => 906,
+        "907" => 907,
+        "908" => 908,
+        "909" => 909,
+        "910" => 910,
+        "911" => 911,
+        "912" => 912,
+        "913" => 913,
+        "914" => 914,
+        "915" => 915,
+        "916" => 916,
+        "917" => 917,
+        "918" => 918,
+        "919" => 919,
+        "920" => 920,
+        "921" => 921,
+        "922" => 922,
+        "923" => 923,
+        "924" => 924,
+        "925" => 925,
+        "926" => 926,
+        "927" => 927,
+        "928" => 928,
+        "929" => 929,
+        "930" => 930,
+        "931" => 931,
+        "932" => 932,
+        "933" => 933,
+        "934" => 934,
+        "935" => 935,
+        "936" => 936,
+        "937" => 937,
+        "938" => 938,
+        "939" => 939,
+        "940" => 940,
+        "941" => 941,
+        "942" => 942,
+        "943" => 943,
+        "944" => 944,
+        "945" => 945,
+        "946" => 946,
+        "947" => 947,
+        "948" => 948,
+        "949" => 949,
+        "950" => 950,
+        "951" => 951,
+        "952" => 952,
+        "953" => 953,
+        "954" => 954,
+        "955" => 955,
+        "956" => 956,
+        "957" => 957,
+        "958" => 958,
+        "959" => 959,
+        "960" => 960,
+        "961" => 961,
+        "962" => 962,
+        "963" => 963,
+        "964" => 964,
+        "965" => 965,
+        "966" => 966,
+        "967" => 967,
+        "968" => 968,
+        "969" => 969,
+        "970" => 970,
+        "971" => 971,
+        "972" => 972,
+        "973" => 973,
+        "974" => 974,
+        "975" => 975,
+        "976" => 976,
+        "977" => 977,
+        "978" => 978,
+        "979" => 979,
+        "980" => 980,
+        "981" => 981,
+        "982" => 982,
+        "983" => 983,
+        "984" => 984,
+        "985" => 985,
+        "986" => 986,
+        "987" => 987,
+        "988" => 988,
+        "989" => 989,
+        "990" => 990,
+        "991" => 991,
+        "992" => 992,
+        "993" => 993,
+        "994" => 994,
+        "995" => 995,
+        "996" => 996,
+        "997" => 997,
+        "998" => 998,
+        "999" => 999,
+        "1000" => 1000,
+        "1001" => 1001,
+        "1002" => 1002,
+        "1003" => 1003,
+        "1004" => 1004,
+        "1005" => 1005,
+        "1006" => 1006,
+        "1007" => 1007,
+        "1008" => 1008,
+        "1009" => 1009,
+        "1010" => 1010,
+        "1011" => 1011,
+        "1012" => 1012,
+        "1013" => 1013,
+        "1014" => 1014,
+        "1015" => 1015,
+        "1016" => 1016,
+        "1017" => 1017,
+        "1018" => 1018,
+        "1019" => 1019,
+        "1020" => 1020,
+        "1021" => 1021,
+        "1022" => 1022,
+        "1023" => 1023,
+        "1024" => 1024,
+        "1025" => 1025,
+        "1026" => 1026,
+        "1027" => 1027,
+        "1028" => 1028,
+        "1029" => 1029,
+        "1030" => 1030,
+        "1031" => 1031,
+        "1032" => 1032,
+        "1033" => 1033,
+        "1034" => 1034,
+        "1035" => 1035,
+        "1036" => 1036,
+        "1037" => 1037,
+        "1038" => 1038,
+        "1039" => 1039,
+        "1040" => 1040,
+        "1041" => 1041,
+        "1042" => 1042,
+        "1043" => 1043,
+        "1044" => 1044,
+        "1045" => 1045,
+        "1046" => 1046,
+        "1047" => 1047,
+        "1048" => 1048,
+        "1049" => 1049,
+        "1050" => 1050,
+        "1051" => 1051,
+        "1052" => 1052,
+        "1053" => 1053,
+        "1054" => 1054,
+        "1055" => 1055,
+        "1056" => 1056,
+        "1057" => 1057,
+        "1058" => 1058,
+        "1059" => 1059,
+        "1060" => 1060,
+        "1061" => 1061,
+        "1062" => 1062,
+        "1063" => 1063,
+        "1064" => 1064,
+        "1065" => 1065,
+        "1066" => 1066,
+        "1067" => 1067,
+        "1068" => 1068,
+        "1069" => 1069,
+        "1070" => 1070,
+        "1071" => 1071,
+        "1072" => 1072,
+        "1073" => 1073,
+        "1074" => 1074,
+        "1075" => 1075,
+        "1076" => 1076,
+        "1077" => 1077,
+        "1078" => 1078,
+        "1079" => 1079,
+        "1080" => 1080,
+        "1081" => 1081,
+        "1082" => 1082,
+        "1083" => 1083,
+        "1084" => 1084,
+        "1085" => 1085,
+        "1086" => 1086,
+        "1087" => 1087,
+        "1088" => 1088,
+        "1089" => 1089,
+        "1090" => 1090,
+        "1091" => 1091,
+        "1092" => 1092,
+        "1093" => 1093,
+        "1094" => 1094,
+        "1095" => 1095,
+        "1096" => 1096,
+        "1097" => 1097,
+        "1098" => 1098,
+        "1099" => 1099,
+        "1100" => 1100,
+        "1101" => 1101,
+        "1102" => 1102,
+        "1103" => 1103,
+        "1104" => 1104,
+        "1105" => 1105,
+        "1106" => 1106,
+        "1107" => 1107,
+        "1108" => 1108,
+        "1109" => 1109,
+        "1110" => 1110,
+        "1111" => 1111,
+        "1112" => 1112,
+        "1113" => 1113,
+        "1114" => 1114,
+        "1115" => 1115,
+        "1116" => 1116,
+        "1117" => 1117,
+        "1118" => 1118,
+        "1119" => 1119,
+        "1120" => 1120,
+        "1121" => 1121,
+        "1122" => 1122,
+        "1123" => 1123,
+        "1124" => 1124,
+        "1125" => 1125,
+        "1126" => 1126,
+        "1127" => 1127,
+        "1128" => 1128,
+        "1129" => 1129,
+        "1130" => 1130,
+        "1131" => 1131,
+        "1132" => 1132,
+        "1133" => 1133,
+        "1134" => 1134,
+        "1135" => 1135,
+        "1136" => 1136,
+        "1137" => 1137,
+        "1138" => 1138,
+        "1139" => 1139,
+        "1140" => 1140,
+        "1141" => 1141,
+        "1142" => 1142,
+        "1143" => 1143,
+        "1144" => 1144,
+        "1145" => 1145,
+        "1146" => 1146,
+        "1147" => 1147,
+        "1148" => 1148,
+        "1149" => 1149,
+        "1150" => 1150,
+        "1151" => 1151,
+        "1152" => 1152,
+        "1153" => 1153,
+        "1154" => 1154,
+        "1155" => 1155,
+        "1156" => 1156,
+        "1157" => 1157,
+        "1158" => 1158,
+        "1159" => 1159,
+        "1160" => 1160,
+        "1161" => 1161,
+        "1162" => 1162,
+        "1163" => 1163,
+        "1164" => 1164,
+        "1165" => 1165,
+        "1166" => 1166,
+        "1167" => 1167,
+        "1168" => 1168,
+        "1169" => 1169,
+        "1170" => 1170,
+        "1171" => 1171,
+        "1172" => 1172,
+        "1173" => 1173,
+        "1174" => 1174,
+        "1175" => 1175,
+        "1176" => 1176,
+        "1177" => 1177,
+        "1178" => 1178,
+        "1179" => 1179,
+        "1180" => 1180,
+        "1181" => 1181,
+        "1182" => 1182,
+        "1183" => 1183,
+        "1184" => 1184,
+        "1185" => 1185,
+        "1186" => 1186,
+        "1187" => 1187,
+        "1188" => 1188,
+        "1189" => 1189,
+        "1190" => 1190,
+        "1191" => 1191,
+        "1192" => 1192,
+        "1193" => 1193,
+        "1194" => 1194,
+        "1195" => 1195,
+        "1196" => 1196,
+        "1197" => 1197,
+        "1198" => 1198,
+        "1199" => 1199,
+        "1200" => 1200,
+        "1201" => 1201,
+        "1202" => 1202,
+        "1203" => 1203,
+        "1204" => 1204,
+        "1205" => 1205,
+        "1206" => 1206,
+        "1207" => 1207,
+        "1208" => 1208,
+        "1209" => 1209,
+        "1210" => 1210,
+        "1211" => 1211,
+        "1212" => 1212,
+        "1213" => 1213,
+        "1214" => 1214,
+        "1215" => 1215,
+        "1216" => 1216,
+        "1217" => 1217,
+        "1218" => 1218,
+        "1219" => 1219,
+        "1220" => 1220,
+        "1221" => 1221,
+        "1222" => 1222,
+        "1223" => 1223,
+        "1224" => 1224,
+        "1225" => 1225,
+        "1226" => 1226,
+        "1227" => 1227,
+        "1228" => 1228,
+        "1229" => 1229,
+        "1230" => 1230,
+        "1231" => 1231,
+        "1232" => 1232,
+        "1233" => 1233,
+        "1234" => 1234,
+        "1235" => 1235,
+        "1236" => 1236,
+        "1237" => 1237,
+        "1238" => 1238,
+        "1239" => 1239,
+        "1240" => 1240,
+        "1241" => 1241,
+        "1242" => 1242,
+        "1243" => 1243,
+        "1244" => 1244,
+        "1245" => 1245,
+        "1246" => 1246,
+        "1247" => 1247,
+        "1248" => 1248,
+        "1249" => 1249,
+        "1250" => 1250,
+        "1251" => 1251,
+        "1252" => 1252,
+        "1253" => 1253,
+        "1254" => 1254,
+        "1255" => 1255,
+        "1256" => 1256,
+        "1257" => 1257,
+        "1258" => 1258,
+        "1259" => 1259,
+        "1260" => 1260,
+        "1261" => 1261,
+        "1262" => 1262,
+        "1263" => 1263,
+        "1264" => 1264,
+        "1265" => 1265,
+        "1266" => 1266,
+        "1267" => 1267,
+        "1268" => 1268,
+        "1269" => 1269,
+        "1270" => 1270,
+        "1271" => 1271,
+        "1272" => 1272,
+        "1273" => 1273,
+        "1274" => 1274,
+        "1275" => 1275,
+        "1276" => 1276,
+        "1277" => 1277,
+        "1278" => 1278,
+        "1279" => 1279,
+        "1280" => 1280,
+        "1281" => 1281,
+        "1282" => 1282,
+        "1283" => 1283,
+        "1284" => 1284,
+        "1285" => 1285,
+        "1286" => 1286,
+        "1287" => 1287,
+        "1288" => 1288,
+        "1289" => 1289,
+        "1290" => 1290,
+        "1291" => 1291,
+        "1292" => 1292,
+        "1293" => 1293,
+        "1294" => 1294,
+        "1295" => 1295,
+        "1296" => 1296,
+        "1297" => 1297,
+        "1298" => 1298,
+        "1299" => 1299,
+        "1300" => 1300,
+        "1301" => 1301,
+        "1302" => 1302,
+        "1303" => 1303,
+        "1304" => 1304,
+        "1305" => 1305,
+        "1306" => 1306,
+        "1307" => 1307,
+        "1308" => 1308,
+        "1309" => 1309,
+        "1310" => 1310,
+        "1311" => 1311,
+        "1312" => 1312,
+        "1313" => 1313,
+        "1314" => 1314,
+        "1315" => 1315,
+        "1316" => 1316,
+        "1317" => 1317,
+        "1318" => 1318,
+        "1319" => 1319,
+        "1320" => 1320,
+        "1321" => 1321,
+        "1322" => 1322,
+        "1323" => 1323,
+        "1324" => 1324,
+        "1325" => 1325,
+        "1326" => 1326,
+        "1327" => 1327,
+        "1328" => 1328,
+        "1329" => 1329,
+        "1330" => 1330,
+        "1331" => 1331,
+        "1332" => 1332,
+        "1333" => 1333,
+        "1334" => 1334,
+        "1335" => 1335,
+        "1336" => 1336,
+        "1337" => 1337,
+        "1338" => 1338,
+        "1339" => 1339,
+        "1340" => 1340,
+        "1341" => 1341,
+        "1342" => 1342,
+        "1343" => 1343,
+        "1344" => 1344,
+        "1345" => 1345,
+        "1346" => 1346,
+        "1347" => 1347,
+        "1348" => 1348,
+        "1349" => 1349,
+        "1350" => 1350,
+        "1351" => 1351,
+        "1352" => 1352,
+        "1353" => 1353,
+        "1354" => 1354,
+        "1355" => 1355,
+        "1356" => 1356,
+        "1357" => 1357,
+        "1358" => 1358,
+        "1359" => 1359,
+        "1360" => 1360,
+        "1361" => 1361,
+        "1362" => 1362,
+        "1363" => 1363,
+        "1364" => 1364,
+        "1365" => 1365,
+        "1366" => 1366,
+        "1367" => 1367,
+        "1368" => 1368,
+        "1369" => 1369,
+        "1370" => 1370,
+        "1371" => 1371,
+        "1372" => 1372,
+        "1373" => 1373,
+        "1374" => 1374,
+        "1375" => 1375,
+        "1376" => 1376,
+        "1377" => 1377,
+        "1378" => 1378,
+        "1379" => 1379,
+        "1380" => 1380,
+        "1381" => 1381,
+        "1382" => 1382,
+        "1383" => 1383,
+        "1384" => 1384,
+        "1385" => 1385,
+        "1386" => 1386,
+        "1387" => 1387,
+        "1388" => 1388,
+        "1389" => 1389,
+        "1390" => 1390,
+        "1391" => 1391,
+        "1392" => 1392,
+        "1393" => 1393,
+        "1394" => 1394,
+        "1395" => 1395,
+        "1396" => 1396,
+        "1397" => 1397,
+        "1398" => 1398,
+        "1399" => 1399,
+        "1400" => 1400,
+        "1401" => 1401,
+        "1402" => 1402,
+        "1403" => 1403,
+        "1404" => 1404,
+        "1405" => 1405,
+        "1406" => 1406,
+        "1407" => 1407,
+        "1408" => 1408,
+        "1409" => 1409,
+        "1410" => 1410,
+        "1411" => 1411,
+        "1412" => 1412,
+        "1413" => 1413,
+        "1414" => 1414,
+        "1415" => 1415,
+        "1416" => 1416,
+        "1417" => 1417,
+        "1418" => 1418,
+        "1419" => 1419,
+        "1420" => 1420,
+        "1421" => 1421,
+        "1422" => 1422,
+        "1423" => 1423,
+        "1424" => 1424,
+        "1425" => 1425,
+        "1426" => 1426,
+        "1427" => 1427,
+        "1428" => 1428,
+        "1429" => 1429,
+        "1430" => 1430,
+        "1431" => 1431,
+        "1432" => 1432,
+        "1433" => 1433,
+        "1434" => 1434,
+        "1435" => 1435,
+        "1436" => 1436,
+        "1437" => 1437,
+        "1438" => 1438,
+        "1439" => 1439,
+        "1440" => 1440,
+        "1441" => 1441,
+        "1442" => 1442,
+        "1443" => 1443,
+        "1444" => 1444,
+        "1445" => 1445,
+        "1446" => 1446,
+        "1447" => 1447,
+        "1448" => 1448,
+        "1449" => 1449,
+        "1450" => 1450,
+        "1451" => 1451,
+        "1452" => 1452,
+        "1453" => 1453,
+        "1454" => 1454,
+        "1455" => 1455,
+        "1456" => 1456,
+        "1457" => 1457,
+        "1458" => 1458,
+        "1459" => 1459,
+        "1460" => 1460,
+        "1461" => 1461,
+        "1462" => 1462,
+        "1463" => 1463,
+        "1464" => 1464,
+        "1465" => 1465,
+        "1466" => 1466,
+        "1467" => 1467,
+        "1468" => 1468,
+        "1469" => 1469,
+        "1470" => 1470,
+        "1471" => 1471,
+        "1472" => 1472,
+        "1473" => 1473,
+        "1474" => 1474,
+        "1475" => 1475,
+        "1476" => 1476,
+        "1477" => 1477,
+        "1478" => 1478,
+        "1479" => 1479,
+        "1480" => 1480,
+        "1481" => 1481,
+        "1482" => 1482,
+        "1483" => 1483,
+        "1484" => 1484,
+        "1485" => 1485,
+        "1486" => 1486,
+        "1487" => 1487,
+        "1488" => 1488,
+        "1489" => 1489,
+        "1490" => 1490,
+        "1491" => 1491,
+        "1492" => 1492,
+        "1493" => 1493,
+        "1494" => 1494,
+        "1495" => 1495,
+        "1496" => 1496,
+        "1497" => 1497,
+        "1498" => 1498,
+        "1499" => 1499,
+        "1500" => 1500,
+        "1501" => 1501,
+        "1502" => 1502,
+        "1503" => 1503,
+        "1504" => 1504,
+        "1505" => 1505,
+        "1506" => 1506,
+        "1507" => 1507,
+        "1508" => 1508,
+        "1509" => 1509,
+        "1510" => 1510,
+        "1511" => 1511,
+        "1512" => 1512,
+        "1513" => 1513,
+        "1514" => 1514,
+        "1515" => 1515,
+        "1516" => 1516,
+        "1517" => 1517,
+        "1518" => 1518,
+        "1519" => 1519,
+        "1520" => 1520,
+        "1521" => 1521,
+        "1522" => 1522,
+        "1523" => 1523,
+        "1524" => 1524,
+        "1525" => 1525,
+        "1526" => 1526,
+        "1527" => 1527,
+        "1528" => 1528,
+        "1529" => 1529,
+        "1530" => 1530,
+        "1531" => 1531,
+        "1532" => 1532,
+        "1533" => 1533,
+        "1534" => 1534,
+        "1535" => 1535,
+        "1536" => 1536,
+        "1537" => 1537,
+        "1538" => 1538,
+        "1539" => 1539,
+        "1540" => 1540,
+        "1541" => 1541,
+        "1542" => 1542,
+        "1543" => 1543,
+        "1544" => 1544,
+        "1545" => 1545,
+        "1546" => 1546,
+        "1547" => 1547,
+        "1548" => 1548,
+        "1549" => 1549,
+        "1550" => 1550,
+        "1551" => 1551,
+        "1552" => 1552,
+        "1553" => 1553,
+        "1554" => 1554,
+        "1555" => 1555,
+        "1556" => 1556,
+        "1557" => 1557,
+        "1558" => 1558,
+        "1559" => 1559,
+        "1560" => 1560,
+        "1561" => 1561,
+        "1562" => 1562,
+        "1563" => 1563,
+        "1564" => 1564,
+        "1565" => 1565,
+        "1566" => 1566,
+        "1567" => 1567,
+        "1568" => 1568,
+        "1569" => 1569,
+        "1570" => 1570,
+        "1571" => 1571,
+        "1572" => 1572,
+        "1573" => 1573,
+        "1574" => 1574,
+        "1575" => 1575,
+        "1576" => 1576,
+        "1577" => 1577,
+        "1578" => 1578,
+        "1579" => 1579,
+        "1580" => 1580,
+        "1581" => 1581,
+        "1582" => 1582,
+        "1583" => 1583,
+        "1584" => 1584,
+        "1585" => 1585,
+        "1586" => 1586,
+        "1587" => 1587,
+        "1588" => 1588,
+        "1589" => 1589,
+        "1590" => 1590,
+        "1591" => 1591,
+        "1592" => 1592,
+        "1593" => 1593,
+        "1594" => 1594,
+        "1595" => 1595,
+        "1596" => 1596,
+        "1597" => 1597,
+        "1598" => 1598,
+        "1599" => 1599,
+        "1600" => 1600,
+        "1601" => 1601,
+        "1602" => 1602,
+        "1603" => 1603,
+        "1604" => 1604,
+        "1605" => 1605,
+        "1606" => 1606,
+        "1607" => 1607,
+        "1608" => 1608,
+        "1609" => 1609,
+        "1610" => 1610,
+        "1611" => 1611,
+        "1612" => 1612,
+        "1613" => 1613,
+        "1614" => 1614,
+        "1615" => 1615,
+        "1616" => 1616,
+        "1617" => 1617,
+        "1618" => 1618,
+        "1619" => 1619,
+        "1620" => 1620,
+        "1621" => 1621,
+        "1622" => 1622,
+        "1623" => 1623,
+        "1624" => 1624,
+        "1625" => 1625,
+        "1626" => 1626,
+        "1627" => 1627,
+        "1628" => 1628,
+        "1629" => 1629,
+        "1630" => 1630,
+        "1631" => 1631,
+        "1632" => 1632,
+        "1633" => 1633,
+        "1634" => 1634,
+        "1635" => 1635,
+        "1636" => 1636,
+        "1637" => 1637,
+        "1638" => 1638,
+        "1639" => 1639,
+        "1640" => 1640,
+        "1641" => 1641,
+        "1642" => 1642,
+        "1643" => 1643,
+        "1644" => 1644,
+        "1645" => 1645,
+        "1646" => 1646,
+        "1647" => 1647,
+        "1648" => 1648,
+        "1649" => 1649,
+        "1650" => 1650,
+        "1651" => 1651,
+        "1652" => 1652,
+        "1653" => 1653,
+        "1654" => 1654,
+        "1655" => 1655,
+        "1656" => 1656,
+        "1657" => 1657,
+        "1658" => 1658,
+        "1659" => 1659,
+        "1660" => 1660,
+        "1661" => 1661,
+        "1662" => 1662,
+        "1663" => 1663,
+        "1664" => 1664,
+        "1665" => 1665,
+        "1666" => 1666,
+        "1667" => 1667,
+        "1668" => 1668,
+        "1669" => 1669,
+        "1670" => 1670,
+        "1671" => 1671,
+        "1672" => 1672,
+        "1673" => 1673,
+        "1674" => 1674,
+        "1675" => 1675,
+        "1676" => 1676,
+        "1677" => 1677,
+        "1678" => 1678,
+        "1679" => 1679,
+        "1680" => 1680,
+        "1681" => 1681,
+        "1682" => 1682,
+        "1683" => 1683,
+        "1684" => 1684,
+        "1685" => 1685,
+        "1686" => 1686,
+        "1687" => 1687,
+        "1688" => 1688,
+        "1689" => 1689,
+        "1690" => 1690,
+        "1691" => 1691,
+        "1692" => 1692,
+        "1693" => 1693,
+        "1694" => 1694,
+        "1695" => 1695,
+        "1696" => 1696,
+        "1697" => 1697,
+        "1698" => 1698,
+        "1699" => 1699,
+        "1700" => 1700,
+        "1701" => 1701,
+        "1702" => 1702,
+        "1703" => 1703,
+        "1704" => 1704,
+        "1705" => 1705,
+        "1706" => 1706,
+        "1707" => 1707,
+        "1708" => 1708,
+        "1709" => 1709,
+        "1710" => 1710,
+        "1711" => 1711,
+        "1712" => 1712,
+        "1713" => 1713,
+        "1714" => 1714,
+        "1715" => 1715,
+        "1716" => 1716,
+        "1717" => 1717,
+        "1718" => 1718,
+        "1719" => 1719,
+        "1720" => 1720,
+        "1721" => 1721,
+        "1722" => 1722,
+        "1723" => 1723,
+        "1724" => 1724,
+        "1725" => 1725,
+        "1726" => 1726,
+        "1727" => 1727,
+        "1728" => 1728,
+        "1729" => 1729,
+        "1730" => 1730,
+        "1731" => 1731,
+        "1732" => 1732,
+        "1733" => 1733,
+        "1734" => 1734,
+        "1735" => 1735,
+        "1736" => 1736,
+        "1737" => 1737,
+        "1738" => 1738,
+        "1739" => 1739,
+        "1740" => 1740,
+        "1741" => 1741,
+        "1742" => 1742,
+        "1743" => 1743,
+        "1744" => 1744,
+        "1745" => 1745,
+        "1746" => 1746,
+        "1747" => 1747,
+        "1748" => 1748,
+        "1749" => 1749,
+        "1750" => 1750,
+        "1751" => 1751,
+        "1752" => 1752,
+        "1753" => 1753,
+        "1754" => 1754,
+        "1755" => 1755,
+        "1756" => 1756,
+        "1757" => 1757,
+        "1758" => 1758,
+        "1759" => 1759,
+        "1760" => 1760,
+        "1761" => 1761,
+        "1762" => 1762,
+        "1763" => 1763,
+        "1764" => 1764,
+        "1765" => 1765,
+        "1766" => 1766,
+        "1767" => 1767,
+        "1768" => 1768,
+        "1769" => 1769,
+        "1770" => 1770,
+        "1771" => 1771,
+        "1772" => 1772,
+        "1773" => 1773,
+        "1774" => 1774,
+        "1775" => 1775,
+        "1776" => 1776,
+        "1777" => 1777,
+        "1778" => 1778,
+        "1779" => 1779,
+        "1780" => 1780,
+        "1781" => 1781,
+        "1782" => 1782,
+        "1783" => 1783,
+        "1784" => 1784,
+        "1785" => 1785,
+        "1786" => 1786,
+        "1787" => 1787,
+        "1788" => 1788,
+        "1789" => 1789,
+        "1790" => 1790,
+        "1791" => 1791,
+        "1792" => 1792,
+        "1793" => 1793,
+        "1794" => 1794,
+        "1795" => 1795,
+        "1796" => 1796,
+        "1797" => 1797,
+        "1798" => 1798,
+        "1799" => 1799,
+        "1800" => 1800,
+        "1801" => 1801,
+        "1802" => 1802,
+        "1803" => 1803,
+        "1804" => 1804,
+        "1805" => 1805,
+        "1806" => 1806,
+        "1807" => 1807,
+        "1808" => 1808,
+        "1809" => 1809,
+        "1810" => 1810,
+        "1811" => 1811,
+        "1812" => 1812,
+        "1813" => 1813,
+        "1814" => 1814,
+        "1815" => 1815,
+        "1816" => 1816,
+        "1817" => 1817,
+        "1818" => 1818,
+        "1819" => 1819,
+        "1820" => 1820,
+        "1821" => 1821,
+        "1822" => 1822,
+        "1823" => 1823,
+        "1824" => 1824,
+        "1825" => 1825,
+        "1826" => 1826,
+        "1827" => 1827,
+        "1828" => 1828,
+        "1829" => 1829,
+        "1830" => 1830,
+        "1831" => 1831,
+        "1832" => 1832,
+        "1833" => 1833,
+        "1834" => 1834,
+        "1835" => 1835,
+        "1836" => 1836,
+        "1837" => 1837,
+        "1838" => 1838,
+        "1839" => 1839,
+        "1840" => 1840,
+        "1841" => 1841,
+        "1842" => 1842,
+        "1843" => 1843,
+        "1844" => 1844,
+        "1845" => 1845,
+        "1846" => 1846,
+        "1847" => 1847,
+        "1848" => 1848,
+        "1849" => 1849,
+        "1850" => 1850,
+        "1851" => 1851,
+        "1852" => 1852,
+        "1853" => 1853,
+        "1854" => 1854,
+        "1855" => 1855,
+        "1856" => 1856,
+        "1857" => 1857,
+        "1858" => 1858,
+        "1859" => 1859,
+        "1860" => 1860,
+        "1861" => 1861,
+        "1862" => 1862,
+        "1863" => 1863,
+        "1864" => 1864,
+        "1865" => 1865,
+        "1866" => 1866,
+        "1867" => 1867,
+        "1868" => 1868,
+        "1869" => 1869,
+        "1870" => 1870,
+        "1871" => 1871,
+        "1872" => 1872,
+        "1873" => 1873,
+        "1874" => 1874,
+        "1875" => 1875,
+        "1876" => 1876,
+        "1877" => 1877,
+        "1878" => 1878,
+        "1879" => 1879,
+        "1880" => 1880,
+        "1881" => 1881,
+        "1882" => 1882,
+        "1883" => 1883,
+        "1884" => 1884,
+        "1885" => 1885,
+        "1886" => 1886,
+        "1887" => 1887,
+        "1888" => 1888,
+        "1889" => 1889,
+        "1890" => 1890,
+        "1891" => 1891,
+        "1892" => 1892,
+        "1893" => 1893,
+        "1894" => 1894,
+        "1895" => 1895,
+        "1896" => 1896,
+        "1897" => 1897,
+        "1898" => 1898,
+        "1899" => 1899,
+        "1900" => 1900,
+        "1901" => 1901,
+        "1902" => 1902,
+        "1903" => 1903,
+        "1904" => 1904,
+        "1905" => 1905,
+        "1906" => 1906,
+        "1907" => 1907,
+        "1908" => 1908,
+        "1909" => 1909,
+        "1910" => 1910,
+        "1911" => 1911,
+        "1912" => 1912,
+        "1913" => 1913,
+        "1914" => 1914,
+        "1915" => 1915,
+        "1916" => 1916,
+        "1917" => 1917,
+        "1918" => 1918,
+        "1919" => 1919,
+        "1920" => 1920,
+        "1921" => 1921,
+        "1922" => 1922,
+        "1923" => 1923,
+        "1924" => 1924,
+        "1925" => 1925,
+        "1926" => 1926,
+        "1927" => 1927,
+        "1928" => 1928,
+        "1929" => 1929,
+        "1930" => 1930,
+        "1931" => 1931,
+        "1932" => 1932,
+        "1933" => 1933,
+        "1934" => 1934,
+        "1935" => 1935,
+        "1936" => 1936,
+        "1937" => 1937,
+        "1938" => 1938,
+        "1939" => 1939,
+        "1940" => 1940,
+        "1941" => 1941,
+        "1942" => 1942,
+        "1943" => 1943,
+        "1944" => 1944,
+        "1945" => 1945,
+        "1946" => 1946,
+        "1947" => 1947,
+        "1948" => 1948,
+        "1949" => 1949,
+        "1950" => 1950,
+        "1951" => 1951,
+        "1952" => 1952,
+        "1953" => 1953,
+        "1954" => 1954,
+        "1955" => 1955,
+        "1956" => 1956,
+        "1957" => 1957,
+        "1958" => 1958,
+        "1959" => 1959,
+        "1960" => 1960,
+        "1961" => 1961,
+        "1962" => 1962,
+        "1963" => 1963,
+        "1964" => 1964,
+        "1965" => 1965,
+        "1966" => 1966,
+        "1967" => 1967,
+        "1968" => 1968,
+        "1969" => 1969,
+        "1970" => 1970,
+        "1971" => 1971,
+        "1972" => 1972,
+        "1973" => 1973,
+        "1974" => 1974,
+        "1975" => 1975,
+        "1976" => 1976,
+        "1977" => 1977,
+        "1978" => 1978,
+        "1979" => 1979,
+        "1980" => 1980,
+        "1981" => 1981,
+        "1982" => 1982,
+        "1983" => 1983,
+        "1984" => 1984,
+        "1985" => 1985,
+        "1986" => 1986,
+        "1987" => 1987,
+        "1988" => 1988,
+        "1989" => 1989,
+        "1990" => 1990,
+        "1991" => 1991,
+        "1992" => 1992,
+        "1993" => 1993,
+        "1994" => 1994,
+        "1995" => 1995,
+        "1996" => 1996,
+        "1997" => 1997,
+        "1998" => 1998,
+        "1999" => 1999,
+        "2000" => 2000,
+        "2001" => 2001,
+        "2002" => 2002,
+        "2003" => 2003,
+        "2004" => 2004,
+        "2005" => 2005,
+        "2006" => 2006,
+        "2007" => 2007,
+        "2008" => 2008,
+        "2009" => 2009,
+        "2010" => 2010,
+        "2011" => 2011,
+        "2012" => 2012,
+        "2013" => 2013,
+        "2014" => 2014,
+        "2015" => 2015,
+        "2016" => 2016,
+        "2017" => 2017,
+        "2018" => 2018,
+        "2019" => 2019,
+        "2020" => 2020,
+        "2021" => 2021,
+        "2022" => 2022,
+        "2023" => 2023,
+        "2024" => 2024,
+        "2025" => 2025,
+        "2026" => 2026,
+        "2027" => 2027,
+        "2028" => 2028,
+        "2029" => 2029,
+        "2030" => 2030,
+        "2031" => 2031,
+        "2032" => 2032,
+        "2033" => 2033,
+        "2034" => 2034,
+        "2035" => 2035,
+        "2036" => 2036,
+        "2037" => 2037,
+        "2038" => 2038,
+        "2039" => 2039,
+        "2040" => 2040,
+        "2041" => 2041,
+        "2042" => 2042,
+        "2043" => 2043,
+        "2044" => 2044,
+        "2045" => 2045,
+        "2046" => 2046,
+        "2047" => 2047,
+        "2048" => 2048,
+        "2049" => 2049,
+        "2050" => 2050,
+        "2051" => 2051,
+        "2052" => 2052,
+        "2053" => 2053,
+        "2054" => 2054,
+        "2055" => 2055,
+        "2056" => 2056,
+        "2057" => 2057,
+        "2058" => 2058,
+        "2059" => 2059,
+        "2060" => 2060,
+        "2061" => 2061,
+        "2062" => 2062,
+        "2063" => 2063,
+        "2064" => 2064,
+        "2065" => 2065,
+        "2066" => 2066,
+        "2067" => 2067,
+        "2068" => 2068,
+        "2069" => 2069,
+        "2070" => 2070,
+        "2071" => 2071,
+        "2072" => 2072,
+        "2073" => 2073,
+        "2074" => 2074,
+        "2075" => 2075,
+        "2076" => 2076,
+        "2077" => 2077,
+        "2078" => 2078,
+        "2079" => 2079,
+        "2080" => 2080,
+        "2081" => 2081,
+        "2082" => 2082,
+        "2083" => 2083,
+        "2084" => 2084,
+        "2085" => 2085,
+        "2086" => 2086,
+        "2087" => 2087,
+        "2088" => 2088,
+        "2089" => 2089,
+        "2090" => 2090,
+        "2091" => 2091,
+        "2092" => 2092,
+        "2093" => 2093,
+        "2094" => 2094,
+        "2095" => 2095,
+        "2096" => 2096,
+        "2097" => 2097,
+        "2098" => 2098,
+        "2099" => 2099,
+        "2100" => 2100,
+        "2101" => 2101,
+        "2102" => 2102,
+        "2103" => 2103,
+        "2104" => 2104,
+        "2105" => 2105,
+        "2106" => 2106,
+        "2107" => 2107,
+        "2108" => 2108,
+        "2109" => 2109,
+        "2110" => 2110,
+        "2111" => 2111,
+        "2112" => 2112,
+        "2113" => 2113,
+        "2114" => 2114,
+        "2115" => 2115,
+        "2116" => 2116,
+        "2117" => 2117,
+        "2118" => 2118,
+        "2119" => 2119,
+        "2120" => 2120,
+        "2121" => 2121,
+        "2122" => 2122,
+        "2123" => 2123,
+        "2124" => 2124,
+        "2125" => 2125,
+        "2126" => 2126,
+        "2127" => 2127,
+        "2128" => 2128,
+        "2129" => 2129,
+        "2130" => 2130,
+        "2131" => 2131,
+        "2132" => 2132,
+        "2133" => 2133,
+        "2134" => 2134,
+        "2135" => 2135,
+        "2136" => 2136,
+        "2137" => 2137,
+        "2138" => 2138,
+        "2139" => 2139,
+        "2140" => 2140,
+        "2141" => 2141,
+        "2142" => 2142,
+        "2143" => 2143,
+        "2144" => 2144,
+        "2145" => 2145,
+        "2146" => 2146,
+        "2147" => 2147,
+        "2148" => 2148,
+        "2149" => 2149,
+        "2150" => 2150,
+        "2151" => 2151,
+        "2152" => 2152,
+        "2153" => 2153,
+        "2154" => 2154,
+        "2155" => 2155,
+        "2156" => 2156,
+        "2157" => 2157,
+        "2158" => 2158,
+        "2159" => 2159,
+        "2160" => 2160,
+        "2161" => 2161,
+        "2162" => 2162,
+        "2163" => 2163,
+        "2164" => 2164,
+        "2165" => 2165,
+        "2166" => 2166,
+        "2167" => 2167,
+        "2168" => 2168,
+        "2169" => 2169,
+        "2170" => 2170,
+        "2171" => 2171,
+        "2172" => 2172,
+        "2173" => 2173,
+        "2174" => 2174,
+        "2175" => 2175,
+        "2176" => 2176,
+        "2177" => 2177,
+        "2178" => 2178,
+        "2179" => 2179,
+        "2180" => 2180,
+        "2181" => 2181,
+        "2182" => 2182,
+        "2183" => 2183,
+        "2184" => 2184,
+        "2185" => 2185,
+        "2186" => 2186,
+        "2187" => 2187,
+        "2188" => 2188,
+        "2189" => 2189,
+        "2190" => 2190,
+        "2191" => 2191,
+        "2192" => 2192,
+        "2193" => 2193,
+        "2194" => 2194,
+        "2195" => 2195,
+        "2196" => 2196,
+        "2197" => 2197,
+        "2198" => 2198,
+        "2199" => 2199,
+        "2200" => 2200,
+        "2201" => 2201,
+        "2202" => 2202,
+        "2203" => 2203,
+        "2204" => 2204,
+        "2205" => 2205,
+        "2206" => 2206,
+        "2207" => 2207,
+        "2208" => 2208,
+        "2209" => 2209,
+        "2210" => 2210,
+        "2211" => 2211,
+        "2212" => 2212,
+        "2213" => 2213,
+        "2214" => 2214,
+        "2215" => 2215,
+        "2216" => 2216,
+        "2217" => 2217,
+        "2218" => 2218,
+        "2219" => 2219,
+        "2220" => 2220,
+        "2221" => 2221,
+        "2222" => 2222,
+        "2223" => 2223,
+        "2224" => 2224,
+        "2225" => 2225,
+        "2226" => 2226,
+        "2227" => 2227,
+        "2228" => 2228,
+        "2229" => 2229,
+        "2230" => 2230,
+        "2231" => 2231,
+        "2232" => 2232,
+        "2233" => 2233,
+        "2234" => 2234,
+        "2235" => 2235,
+        "2236" => 2236,
+        "2237" => 2237,
+        "2238" => 2238,
+        "2239" => 2239,
+        "2240" => 2240,
+        "2241" => 2241,
+        "2242" => 2242,
+        "2243" => 2243,
+        "2244" => 2244,
+        "2245" => 2245,
+        "2246" => 2246,
+        "2247" => 2247,
+        "2248" => 2248,
+        "2249" => 2249,
+        "2250" => 2250,
+        "2251" => 2251,
+        "2252" => 2252,
+        "2253" => 2253,
+        "2254" => 2254,
+        "2255" => 2255,
+        "2256" => 2256,
+        "2257" => 2257,
+        "2258" => 2258,
+        "2259" => 2259,
+        "2260" => 2260,
+        "2261" => 2261,
+        "2262" => 2262,
+        "2263" => 2263,
+        "2264" => 2264,
+        "2265" => 2265,
+        "2266" => 2266,
+        "2267" => 2267,
+        "2268" => 2268,
+        "2269" => 2269,
+        "2270" => 2270,
+        "2271" => 2271,
+        "2272" => 2272,
+        "2273" => 2273,
+        "2274" => 2274,
+        "2275" => 2275,
+        "2276" => 2276,
+        "2277" => 2277,
+        "2278" => 2278,
+        "2279" => 2279,
+        "2280" => 2280,
+        "2281" => 2281,
+        "2282" => 2282,
+        "2283" => 2283,
+        "2284" => 2284,
+        "2285" => 2285,
+        "2286" => 2286,
+        "2287" => 2287,
+        "2288" => 2288,
+        "2289" => 2289,
+        "2290" => 2290,
+        "2291" => 2291,
+        "2292" => 2292,
+        "2293" => 2293,
+        "2294" => 2294,
+        "2295" => 2295,
+        "2296" => 2296,
+        "2297" => 2297,
+        "2298" => 2298,
+        "2299" => 2299,
+        "2300" => 2300,
+        "2301" => 2301,
+        "2302" => 2302,
+        "2303" => 2303,
+        "2304" => 2304,
+        "2305" => 2305,
+        "2306" => 2306,
+        "2307" => 2307,
+        "2308" => 2308,
+        "2309" => 2309,
+        "2310" => 2310,
+        "2311" => 2311,
+        "2312" => 2312,
+        "2313" => 2313,
+        "2314" => 2314,
+        "2315" => 2315,
+        "2316" => 2316,
+        "2317" => 2317,
+        "2318" => 2318,
+        "2319" => 2319,
+        "2320" => 2320,
+        "2321" => 2321,
+        "2322" => 2322,
+        "2323" => 2323,
+        "2324" => 2324,
+        "2325" => 2325,
+        "2326" => 2326,
+        "2327" => 2327,
+        "2328" => 2328,
+        "2329" => 2329,
+        "2330" => 2330,
+        "2331" => 2331,
+        "2332" => 2332,
+        "2333" => 2333,
+        "2334" => 2334,
+        "2335" => 2335,
+        "2336" => 2336,
+        "2337" => 2337,
+        "2338" => 2338,
+        "2339" => 2339,
+        "2340" => 2340,
+        "2341" => 2341,
+        "2342" => 2342,
+        "2343" => 2343,
+        "2344" => 2344,
+        "2345" => 2345,
+        "2346" => 2346,
+        "2347" => 2347,
+        "2348" => 2348,
+        "2349" => 2349,
+        "2350" => 2350,
+        "2351" => 2351,
+        "2352" => 2352,
+        "2353" => 2353,
+        "2354" => 2354,
+        "2355" => 2355,
+        "2356" => 2356,
+        "2357" => 2357,
+        "2358" => 2358,
+        "2359" => 2359,
+        "2360" => 2360,
+        "2361" => 2361,
+        "2362" => 2362,
+        "2363" => 2363,
+        "2364" => 2364,
+        "2365" => 2365,
+        "2366" => 2366,
+        "2367" => 2367,
+        "2368" => 2368,
+        "2369" => 2369,
+        "2370" => 2370,
+        "2371" => 2371,
+        "2372" => 2372,
+        "2373" => 2373,
+        "2374" => 2374,
+        "2375" => 2375,
+        "2376" => 2376,
+        "2377" => 2377,
+        "2378" => 2378,
+        "2379" => 2379,
+        "2380" => 2380,
+        "2381" => 2381,
+        "2382" => 2382,
+        "2383" => 2383,
+        "2384" => 2384,
+        "2385" => 2385,
+        "2386" => 2386,
+        "2387" => 2387,
+        "2388" => 2388,
+        "2389" => 2389,
+        "2390" => 2390,
+        "2391" => 2391,
+        "2392" => 2392,
+        "2393" => 2393,
+        "2394" => 2394,
+        "2395" => 2395,
+        "2396" => 2396,
+        "2397" => 2397,
+        "2398" => 2398,
+        "2399" => 2399,
+        "2400" => 2400,
+        "2401" => 2401,
+        "2402" => 2402,
+        "2403" => 2403,
+        "2404" => 2404,
+        "2405" => 2405,
+        "2406" => 2406,
+        "2407" => 2407,
+        "2408" => 2408,
+        "2409" => 2409,
+        "2410" => 2410,
+        "2411" => 2411,
+        "2412" => 2412,
+        "2413" => 2413,
+        "2414" => 2414,
+        "2415" => 2415,
+        "2416" => 2416,
+        "2417" => 2417,
+        "2418" => 2418,
+        "2419" => 2419,
+        "2420" => 2420,
+        "2421" => 2421,
+        "2422" => 2422,
+        "2423" => 2423,
+        "2424" => 2424,
+        "2425" => 2425,
+        "2426" => 2426,
+        "2427" => 2427,
+        "2428" => 2428,
+        "2429" => 2429,
+        "2430" => 2430,
+        "2431" => 2431,
+        "2432" => 2432,
+        "2433" => 2433,
+        "2434" => 2434,
+        "2435" => 2435,
+        "2436" => 2436,
+        "2437" => 2437,
+        "2438" => 2438,
+        "2439" => 2439,
+        "2440" => 2440,
+        "2441" => 2441,
+        "2442" => 2442,
+        "2443" => 2443,
+        "2444" => 2444,
+        "2445" => 2445,
+        "2446" => 2446,
+        "2447" => 2447,
+        "2448" => 2448,
+        "2449" => 2449,
+        "2450" => 2450,
+        "2451" => 2451,
+        "2452" => 2452,
+        "2453" => 2453,
+        "2454" => 2454,
+        "2455" => 2455,
+        "2456" => 2456,
+        "2457" => 2457,
+        "2458" => 2458,
+        "2459" => 2459,
+        "2460" => 2460,
+        "2461" => 2461,
+        "2462" => 2462,
+        "2463" => 2463,
+        "2464" => 2464,
+        "2465" => 2465,
+        "2466" => 2466,
+        "2467" => 2467,
+        "2468" => 2468,
+        "2469" => 2469,
+        "2470" => 2470,
+        "2471" => 2471,
+        "2472" => 2472,
+        "2473" => 2473,
+        "2474" => 2474,
+        "2475" => 2475,
+        "2476" => 2476,
+        "2477" => 2477,
+        "2478" => 2478,
+        "2479" => 2479,
+        "2480" => 2480,
+        "2481" => 2481,
+        "2482" => 2482,
+        "2483" => 2483,
+        "2484" => 2484,
+        "2485" => 2485,
+        "2486" => 2486,
+        "2487" => 2487,
+        "2488" => 2488,
+        "2489" => 2489,
+        "2490" => 2490,
+        "2491" => 2491,
+        "2492" => 2492,
+        "2493" => 2493,
+        "2494" => 2494,
+        "2495" => 2495,
+        "2496" => 2496,
+        "2497" => 2497,
+        "2498" => 2498,
+        "2499" => 2499,
+        "2500" => 2500,
+        "2501" => 2501,
+        "2502" => 2502,
+        "2503" => 2503,
+        "2504" => 2504,
+        "2505" => 2505,
+        "2506" => 2506,
+        "2507" => 2507,
+        "2508" => 2508,
+        "2509" => 2509,
+        "2510" => 2510,
+        "2511" => 2511,
+        "2512" => 2512,
+        "2513" => 2513,
+        "2514" => 2514,
+        "2515" => 2515,
+        "2516" => 2516,
+        "2517" => 2517,
+        "2518" => 2518,
+        "2519" => 2519,
+        "2520" => 2520,
+        "2521" => 2521,
+        "2522" => 2522,
+        "2523" => 2523,
+        "2524" => 2524,
+        "2525" => 2525,
+        "2526" => 2526,
+        "2527" => 2527,
+        "2528" => 2528,
+        "2529" => 2529,
+        "2530" => 2530,
+        "2531" => 2531,
+        "2532" => 2532,
+        "2533" => 2533,
+        "2534" => 2534,
+        "2535" => 2535,
+        "2536" => 2536,
+        "2537" => 2537,
+        "2538" => 2538,
+        "2539" => 2539,
+        "2540" => 2540,
+        "2541" => 2541,
+        "2542" => 2542,
+        "2543" => 2543,
+        "2544" => 2544,
+        "2545" => 2545,
+        "2546" => 2546,
+        "2547" => 2547,
+        "2548" => 2548,
+        "2549" => 2549,
+        "2550" => 2550,
+        "2551" => 2551,
+        "2552" => 2552,
+        "2553" => 2553,
+        "2554" => 2554,
+        "2555" => 2555,
+        "2556" => 2556,
+        "2557" => 2557,
+        "2558" => 2558,
+        "2559" => 2559,
+        "2560" => 2560,
+        "2561" => 2561,
+        "2562" => 2562,
+        "2563" => 2563,
+        "2564" => 2564,
+        "2565" => 2565,
+        "2566" => 2566,
+        "2567" => 2567,
+        "2568" => 2568,
+        "2569" => 2569,
+        "2570" => 2570,
+        "2571" => 2571,
+        "2572" => 2572,
+        "2573" => 2573,
+        "2574" => 2574,
+        "2575" => 2575,
+        "2576" => 2576,
+        "2577" => 2577,
+        "2578" => 2578,
+        "2579" => 2579,
+        "2580" => 2580,
+        "2581" => 2581,
+        "2582" => 2582,
+        "2583" => 2583,
+        "2584" => 2584,
+        "2585" => 2585,
+        "2586" => 2586,
+        "2587" => 2587,
+        "2588" => 2588,
+        "2589" => 2589,
+        "2590" => 2590,
+        "2591" => 2591,
+        "2592" => 2592,
+        "2593" => 2593,
+        "2594" => 2594,
+        "2595" => 2595,
+        "2596" => 2596,
+        "2597" => 2597,
+        "2598" => 2598,
+        "2599" => 2599,
+        "2600" => 2600,
+        "2601" => 2601,
+        "2602" => 2602,
+        "2603" => 2603,
+        "2604" => 2604,
+        "2605" => 2605,
+        "2606" => 2606,
+        "2607" => 2607,
+        "2608" => 2608,
+        "2609" => 2609,
+        "2610" => 2610,
+        "2611" => 2611,
+        "2612" => 2612,
+        "2613" => 2613,
+        "2614" => 2614,
+        "2615" => 2615,
+        "2616" => 2616,
+        "2617" => 2617,
+        "2618" => 2618,
+        "2619" => 2619,
+        "2620" => 2620,
+        "2621" => 2621,
+        "2622" => 2622,
+        "2623" => 2623,
+        "2624" => 2624,
+        "2625" => 2625,
+        "2626" => 2626,
+        "2627" => 2627,
+        "2628" => 2628,
+        "2629" => 2629,
+        "2630" => 2630,
+        "2631" => 2631,
+        "2632" => 2632,
+        "2633" => 2633,
+        "2634" => 2634,
+        "2635" => 2635,
+        "2636" => 2636,
+        "2637" => 2637,
+        "2638" => 2638,
+        "2639" => 2639,
+        "2640" => 2640,
+        "2641" => 2641,
+        "2642" => 2642,
+        "2643" => 2643,
+        "2644" => 2644,
+        "2645" => 2645,
+        "2646" => 2646,
+        "2647" => 2647,
+        "2648" => 2648,
+        "2649" => 2649,
+        "2650" => 2650,
+        "2651" => 2651,
+        "2652" => 2652,
+        "2653" => 2653,
+        "2654" => 2654,
+        "2655" => 2655,
+        "2656" => 2656,
+        "2657" => 2657,
+        "2658" => 2658,
+        "2659" => 2659,
+        "2660" => 2660,
+        "2661" => 2661,
+        "2662" => 2662,
+        "2663" => 2663,
+        "2664" => 2664,
+        "2665" => 2665,
+        "2666" => 2666,
+        "2667" => 2667,
+        "2668" => 2668,
+        "2669" => 2669,
+        "2670" => 2670,
+        "2671" => 2671,
+        "2672" => 2672,
+        "2673" => 2673,
+        "2674" => 2674,
+        "2675" => 2675,
+        "2676" => 2676,
+        "2677" => 2677,
+        "2678" => 2678,
+        "2679" => 2679,
+        "2680" => 2680,
+        "2681" => 2681,
+        "2682" => 2682,
+        "2683" => 2683,
+        "2684" => 2684,
+        "2685" => 2685,
+        "2686" => 2686,
+        "2687" => 2687,
+        "2688" => 2688,
+        "2689" => 2689,
+        "2690" => 2690,
+        "2691" => 2691,
+        "2692" => 2692,
+        "2693" => 2693,
+        "2694" => 2694,
+        "2695" => 2695,
+        "2696" => 2696,
+        "2697" => 2697,
+        "2698" => 2698,
+        "2699" => 2699,
+        "2700" => 2700,
+        "2701" => 2701,
+        "2702" => 2702,
+        "2703" => 2703,
+        "2704" => 2704,
+        "2705" => 2705,
+        "2706" => 2706,
+        "2707" => 2707,
+        "2708" => 2708,
+        "2709" => 2709,
+        "2710" => 2710,
+        "2711" => 2711,
+        "2712" => 2712,
+        "2713" => 2713,
+        "2714" => 2714,
+        "2715" => 2715,
+        "2716" => 2716,
+        "2717" => 2717,
+        "2718" => 2718,
+        "2719" => 2719,
+        "2720" => 2720,
+        "2721" => 2721,
+        "2722" => 2722,
+        "2723" => 2723,
+        "2724" => 2724,
+        "2725" => 2725,
+        "2726" => 2726,
+        "2727" => 2727,
+        "2728" => 2728,
+        "2729" => 2729,
+        "2730" => 2730,
+        "2731" => 2731,
+        "2732" => 2732,
+        "2733" => 2733,
+        "2734" => 2734,
+        "2735" => 2735,
+        "2736" => 2736,
+        "2737" => 2737,
+        "2738" => 2738,
+        "2739" => 2739,
+        "2740" => 2740,
+        "2741" => 2741,
+        "2742" => 2742,
+        "2743" => 2743,
+        "2744" => 2744,
+        "2745" => 2745,
+        "2746" => 2746,
+        "2747" => 2747,
+        "2748" => 2748,
+        "2749" => 2749,
+        "2750" => 2750,
+        "2751" => 2751,
+        "2752" => 2752,
+        "2753" => 2753,
+        "2754" => 2754,
+        "2755" => 2755,
+        "2756" => 2756,
+        "2757" => 2757,
+        "2758" => 2758,
+        "2759" => 2759,
+        "2760" => 2760,
+        "2761" => 2761,
+        "2762" => 2762,
+        "2763" => 2763,
+        "2764" => 2764,
+        "2765" => 2765,
+        "2766" => 2766,
+        "2767" => 2767,
+        "2768" => 2768,
+        "2769" => 2769,
+        "2770" => 2770,
+        "2771" => 2771,
+        "2772" => 2772,
+        "2773" => 2773,
+        "2774" => 2774,
+        "2775" => 2775,
+        "2776" => 2776,
+        "2777" => 2777,
+        "2778" => 2778,
+        "2779" => 2779,
+        "2780" => 2780,
+        "2781" => 2781,
+        "2782" => 2782,
+        "2783" => 2783,
+        "2784" => 2784,
+        "2785" => 2785,
+        "2786" => 2786,
+        "2787" => 2787,
+        "2788" => 2788,
+        "2789" => 2789,
+        "2790" => 2790,
+        "2791" => 2791,
+        "2792" => 2792,
+        "2793" => 2793,
+        "2794" => 2794,
+        "2795" => 2795,
+        "2796" => 2796,
+        "2797" => 2797,
+        "2798" => 2798,
+        "2799" => 2799,
+        "2800" => 2800,
+        "2801" => 2801,
+        "2802" => 2802,
+        "2803" => 2803,
+        "2804" => 2804,
+        "2805" => 2805,
+        "2806" => 2806,
+        "2807" => 2807,
+        "2808" => 2808,
+        "2809" => 2809,
+        "2810" => 2810,
+        "2811" => 2811,
+        "2812" => 2812,
+        "2813" => 2813,
+        "2814" => 2814,
+        "2815" => 2815,
+        "2816" => 2816,
+        "2817" => 2817,
+        "2818" => 2818,
+        "2819" => 2819,
+        "2820" => 2820,
+        "2821" => 2821,
+        "2822" => 2822,
+        "2823" => 2823,
+        "2824" => 2824,
+        "2825" => 2825,
+        "2826" => 2826,
+        "2827" => 2827,
+        "2828" => 2828,
+        "2829" => 2829,
+        "2830" => 2830,
+        "2831" => 2831,
+        "2832" => 2832,
+        "2833" => 2833,
+        "2834" => 2834,
+        "2835" => 2835,
+        "2836" => 2836,
+        "2837" => 2837,
+        "2838" => 2838,
+        "2839" => 2839,
+        "2840" => 2840,
+        "2841" => 2841,
+        "2842" => 2842,
+        "2843" => 2843,
+        "2844" => 2844,
+        "2845" => 2845,
+        "2846" => 2846,
+        "2847" => 2847,
+        "2848" => 2848,
+        "2849" => 2849,
+        "2850" => 2850,
+        "2851" => 2851,
+        "2852" => 2852,
+        "2853" => 2853,
+        "2854" => 2854,
+        "2855" => 2855,
+        "2856" => 2856,
+        "2857" => 2857,
+        "2858" => 2858,
+        "2859" => 2859,
+        "2860" => 2860,
+        "2861" => 2861,
+        "2862" => 2862,
+        "2863" => 2863,
+        "2864" => 2864,
+        "2865" => 2865,
+        "2866" => 2866,
+        "2867" => 2867,
+        "2868" => 2868,
+        "2869" => 2869,
+        "2870" => 2870,
+        "2871" => 2871,
+        "2872" => 2872,
+        "2873" => 2873,
+        "2874" => 2874,
+        "2875" => 2875,
+        "2876" => 2876,
+        "2877" => 2877,
+        "2878" => 2878,
+        "2879" => 2879,
+        "2880" => 2880,
+        "2881" => 2881,
+        "2882" => 2882,
+        "2883" => 2883,
+        "2884" => 2884,
+        "2885" => 2885,
+        "2886" => 2886,
+        "2887" => 2887,
+        "2888" => 2888,
+        "2889" => 2889,
+        "2890" => 2890,
+        "2891" => 2891,
+        "2892" => 2892,
+        "2893" => 2893,
+        "2894" => 2894,
+        "2895" => 2895,
+        "2896" => 2896,
+        "2897" => 2897,
+        "2898" => 2898,
+        "2899" => 2899,
+        "2900" => 2900,
+        "2901" => 2901,
+        "2902" => 2902,
+        "2903" => 2903,
+        "2904" => 2904,
+        "2905" => 2905,
+        "2906" => 2906,
+        "2907" => 2907,
+        "2908" => 2908,
+        "2909" => 2909,
+        "2910" => 2910,
+        "2911" => 2911,
+        "2912" => 2912,
+        "2913" => 2913,
+        "2914" => 2914,
+        "2915" => 2915,
+        "2916" => 2916,
+        "2917" => 2917,
+        "2918" => 2918,
+        "2919" => 2919,
+        "2920" => 2920,
+        "2921" => 2921,
+        "2922" => 2922,
+        "2923" => 2923,
+        "2924" => 2924,
+        "2925" => 2925,
+        "2926" => 2926,
+        "2927" => 2927,
+        "2928" => 2928,
+        "2929" => 2929,
+        "2930" => 2930,
+        "2931" => 2931,
+        "2932" => 2932,
+        "2933" => 2933,
+        "2934" => 2934,
+        "2935" => 2935,
+        "2936" => 2936,
+        "2937" => 2937,
+        "2938" => 2938,
+        "2939" => 2939,
+        "2940" => 2940,
+        "2941" => 2941,
+        "2942" => 2942,
+        "2943" => 2943,
+        "2944" => 2944,
+        "2945" => 2945,
+        "2946" => 2946,
+        "2947" => 2947,
+        "2948" => 2948,
+        "2949" => 2949,
+        "2950" => 2950,
+        "2951" => 2951,
+        "2952" => 2952,
+        "2953" => 2953,
+        "2954" => 2954,
+        "2955" => 2955,
+        "2956" => 2956,
+        "2957" => 2957,
+        "2958" => 2958,
+        "2959" => 2959,
+        "2960" => 2960,
+        "2961" => 2961,
+        "2962" => 2962,
+        "2963" => 2963,
+        "2964" => 2964,
+        "2965" => 2965,
+        "2966" => 2966,
+        "2967" => 2967,
+        "2968" => 2968,
+        "2969" => 2969,
+        "2970" => 2970,
+        "2971" => 2971,
+        "2972" => 2972,
+        "2973" => 2973,
+        "2974" => 2974,
+        "2975" => 2975,
+        "2976" => 2976,
+        "2977" => 2977,
+        "2978" => 2978,
+        "2979" => 2979,
+        "2980" => 2980,
+        "2981" => 2981,
+        "2982" => 2982,
+        "2983" => 2983,
+        "2984" => 2984,
+        "2985" => 2985,
+        "2986" => 2986,
+        "2987" => 2987,
+        "2988" => 2988,
+        "2989" => 2989,
+        "2990" => 2990,
+        "2991" => 2991,
+        "2992" => 2992,
+        "2993" => 2993,
+        "2994" => 2994,
+        "2995" => 2995,
+        "2996" => 2996,
+        "2997" => 2997,
+        "2998" => 2998,
+        "2999" => 2999,
+        "3000" => 3000,
+        "3001" => 3001,
+        "3002" => 3002,
+        "3003" => 3003,
+        "3004" => 3004,
+        "3005" => 3005,
+        "3006" => 3006,
+        "3007" => 3007,
+        "3008" => 3008,
+        "3009" => 3009,
+        "3010" => 3010,
+        "3011" => 3011,
+        "3012" => 3012,
+        "3013" => 3013,
+        "3014" => 3014,
+        "3015" => 3015,
+        "3016" => 3016,
+        "3017" => 3017,
+        "3018" => 3018,
+        "3019" => 3019,
+        "3020" => 3020,
+        "3021" => 3021,
+        "3022" => 3022,
+        "3023" => 3023,
+        "3024" => 3024,
+        "3025" => 3025,
+        "3026" => 3026,
+        "3027" => 3027,
+        "3028" => 3028,
+        "3029" => 3029,
+        "3030" => 3030,
+        "3031" => 3031,
+        "3032" => 3032,
+        "3033" => 3033,
+        "3034" => 3034,
+        "3035" => 3035,
+        "3036" => 3036,
+        "3037" => 3037,
+        "3038" => 3038,
+        "3039" => 3039,
+        "3040" => 3040,
+        "3041" => 3041,
+        "3042" => 3042,
+        "3043" => 3043,
+        "3044" => 3044,
+        "3045" => 3045,
+        "3046" => 3046,
+        "3047" => 3047,
+        "3048" => 3048,
+        "3049" => 3049,
+        "3050" => 3050,
+        "3051" => 3051,
+        "3052" => 3052,
+        "3053" => 3053,
+        "3054" => 3054,
+        "3055" => 3055,
+        "3056" => 3056,
+        "3057" => 3057,
+        "3058" => 3058,
+        "3059" => 3059,
+        "3060" => 3060,
+        "3061" => 3061,
+        "3062" => 3062,
+        "3063" => 3063,
+        "3064" => 3064,
+        "3065" => 3065,
+        "3066" => 3066,
+        "3067" => 3067,
+        "3068" => 3068,
+        "3069" => 3069,
+        "3070" => 3070,
+        "3071" => 3071,
+        "3072" => 3072,
+        "3073" => 3073,
+        "3074" => 3074,
+        "3075" => 3075,
+        "3076" => 3076,
+        "3077" => 3077,
+        "3078" => 3078,
+        "3079" => 3079,
+        "3080" => 3080,
+        "3081" => 3081,
+        "3082" => 3082,
+        "3083" => 3083,
+        "3084" => 3084,
+        "3085" => 3085,
+        "3086" => 3086,
+        "3087" => 3087,
+        "3088" => 3088,
+        "3089" => 3089,
+        "3090" => 3090,
+        "3091" => 3091,
+        "3092" => 3092,
+        "3093" => 3093,
+        "3094" => 3094,
+        "3095" => 3095,
+        "3096" => 3096,
+        "3097" => 3097,
+        "3098" => 3098,
+        "3099" => 3099,
+        "3100" => 3100,
+        "3101" => 3101,
+        "3102" => 3102,
+        "3103" => 3103,
+        "3104" => 3104,
+        "3105" => 3105,
+        "3106" => 3106,
+        "3107" => 3107,
+        "3108" => 3108,
+        "3109" => 3109,
+        "3110" => 3110,
+        "3111" => 3111,
+        "3112" => 3112,
+        "3113" => 3113,
+        "3114" => 3114,
+        "3115" => 3115,
+        "3116" => 3116,
+        "3117" => 3117,
+        "3118" => 3118,
+        "3119" => 3119,
+        "3120" => 3120,
+        "3121" => 3121,
+        "3122" => 3122,
+        "3123" => 3123,
+        "3124" => 3124,
+        "3125" => 3125,
+        "3126" => 3126,
+        "3127" => 3127,
+        "3128" => 3128,
+        "3129" => 3129,
+        "3130" => 3130,
+        "3131" => 3131,
+        "3132" => 3132,
+        "3133" => 3133,
+        "3134" => 3134,
+        "3135" => 3135,
+        "3136" => 3136,
+        "3137" => 3137,
+        "3138" => 3138,
+        "3139" => 3139,
+        "3140" => 3140,
+        "3141" => 3141,
+        "3142" => 3142,
+        "3143" => 3143,
+        "3144" => 3144,
+        "3145" => 3145,
+        "3146" => 3146,
+        "3147" => 3147,
+        "3148" => 3148,
+        "3149" => 3149,
+        "3150" => 3150,
+        "3151" => 3151,
+        "3152" => 3152,
+        "3153" => 3153,
+        "3154" => 3154,
+        "3155" => 3155,
+        "3156" => 3156,
+        "3157" => 3157,
+        "3158" => 3158,
+        "3159" => 3159,
+        "3160" => 3160,
+        "3161" => 3161,
+        "3162" => 3162,
+        "3163" => 3163,
+        "3164" => 3164,
+        "3165" => 3165,
+        "3166" => 3166,
+        "3167" => 3167,
+        "3168" => 3168,
+        "3169" => 3169,
+        "3170" => 3170,
+        "3171" => 3171,
+        "3172" => 3172,
+        "3173" => 3173,
+        "3174" => 3174,
+        "3175" => 3175,
+        "3176" => 3176,
+        "3177" => 3177,
+        "3178" => 3178,
+        "3179" => 3179,
+        "3180" => 3180,
+        "3181" => 3181,
+        "3182" => 3182,
+        "3183" => 3183,
+        "3184" => 3184,
+        "3185" => 3185,
+        "3186" => 3186,
+        "3187" => 3187,
+        "3188" => 3188,
+        "3189" => 3189,
+        "3190" => 3190,
+        "3191" => 3191,
+        "3192" => 3192,
+        "3193" => 3193,
+        "3194" => 3194,
+        "3195" => 3195,
+        "3196" => 3196,
+        "3197" => 3197,
+        "3198" => 3198,
+        "3199" => 3199,
+        "3200" => 3200,
+        "3201" => 3201,
+        "3202" => 3202,
+        "3203" => 3203,
+        "3204" => 3204,
+        "3205" => 3205,
+        "3206" => 3206,
+        "3207" => 3207,
+        "3208" => 3208,
+        "3209" => 3209,
+        "3210" => 3210,
+        "3211" => 3211,
+        "3212" => 3212,
+        "3213" => 3213,
+        "3214" => 3214,
+        "3215" => 3215,
+        "3216" => 3216,
+        "3217" => 3217,
+        "3218" => 3218,
+        "3219" => 3219,
+        "3220" => 3220,
+        "3221" => 3221,
+        "3222" => 3222,
+        "3223" => 3223,
+        "3224" => 3224,
+        "3225" => 3225,
+        "3226" => 3226,
+        "3227" => 3227,
+        "3228" => 3228,
+        "3229" => 3229,
+        "3230" => 3230,
+        "3231" => 3231,
+        "3232" => 3232,
+        "3233" => 3233,
+        "3234" => 3234,
+        "3235" => 3235,
+        "3236" => 3236,
+        "3237" => 3237,
+        "3238" => 3238,
+        "3239" => 3239,
+        "3240" => 3240,
+        "3241" => 3241,
+        "3242" => 3242,
+        "3243" => 3243,
+        "3244" => 3244,
+        "3245" => 3245,
+        "3246" => 3246,
+        "3247" => 3247,
+        "3248" => 3248,
+        "3249" => 3249,
+        "3250" => 3250,
+        "3251" => 3251,
+        "3252" => 3252,
+        "3253" => 3253,
+        "3254" => 3254,
+        "3255" => 3255,
+        "3256" => 3256,
+        "3257" => 3257,
+        "3258" => 3258,
+        "3259" => 3259,
+        "3260" => 3260,
+        "3261" => 3261,
+        "3262" => 3262,
+        "3263" => 3263,
+        "3264" => 3264,
+        "3265" => 3265,
+        "3266" => 3266,
+        "3267" => 3267,
+        "3268" => 3268,
+        "3269" => 3269,
+        "3270" => 3270,
+        "3271" => 3271,
+        "3272" => 3272,
+        "3273" => 3273,
+        "3274" => 3274,
+        "3275" => 3275,
+        "3276" => 3276,
+        "3277" => 3277,
+        "3278" => 3278,
+        "3279" => 3279,
+        "3280" => 3280,
+        "3281" => 3281,
+        "3282" => 3282,
+        "3283" => 3283,
+        "3284" => 3284,
+        "3285" => 3285,
+        "3286" => 3286,
+        "3287" => 3287,
+        "3288" => 3288,
+        "3289" => 3289,
+        "3290" => 3290,
+        "3291" => 3291,
+        "3292" => 3292,
+        "3293" => 3293,
+        "3294" => 3294,
+        "3295" => 3295,
+        "3296" => 3296,
+        "3297" => 3297,
+        "3298" => 3298,
+        "3299" => 3299,
+        "3300" => 3300,
+        "3301" => 3301,
+        "3302" => 3302,
+        "3303" => 3303,
+        "3304" => 3304,
+        "3305" => 3305,
+        "3306" => 3306,
+        "3307" => 3307,
+        "3308" => 3308,
+        "3309" => 3309,
+        "3310" => 3310,
+        "3311" => 3311,
+        "3312" => 3312,
+        "3313" => 3313,
+        "3314" => 3314,
+        "3315" => 3315,
+        "3316" => 3316,
+        "3317" => 3317,
+        "3318" => 3318,
+        "3319" => 3319,
+        "3320" => 3320,
+        "3321" => 3321,
+        "3322" => 3322,
+        "3323" => 3323,
+        "3324" => 3324,
+        "3325" => 3325,
+        "3326" => 3326,
+        "3327" => 3327,
+        "3328" => 3328,
+        "3329" => 3329,
+        "3330" => 3330,
+        "3331" => 3331,
+        "3332" => 3332,
+        "3333" => 3333,
+        "3334" => 3334,
+        "3335" => 3335,
+        "3336" => 3336,
+        "3337" => 3337,
+        "3338" => 3338,
+        "3339" => 3339,
+        "3340" => 3340,
+        "3341" => 3341,
+        "3342" => 3342,
+        "3343" => 3343,
+        "3344" => 3344,
+        "3345" => 3345,
+        "3346" => 3346,
+        "3347" => 3347,
+        "3348" => 3348,
+        "3349" => 3349,
+        "3350" => 3350,
+        "3351" => 3351,
+        "3352" => 3352,
+        "3353" => 3353,
+        "3354" => 3354,
+        "3355" => 3355,
+        "3356" => 3356,
+        "3357" => 3357,
+        "3358" => 3358,
+        "3359" => 3359,
+        "3360" => 3360,
+        "3361" => 3361,
+        "3362" => 3362,
+        "3363" => 3363,
+        "3364" => 3364,
+        "3365" => 3365,
+        "3366" => 3366,
+        "3367" => 3367,
+        "3368" => 3368,
+        "3369" => 3369,
+        "3370" => 3370,
+        "3371" => 3371,
+        "3372" => 3372,
+        "3373" => 3373,
+        "3374" => 3374,
+        "3375" => 3375,
+        "3376" => 3376,
+        "3377" => 3377,
+        "3378" => 3378,
+        "3379" => 3379,
+        "3380" => 3380,
+        "3381" => 3381,
+        "3382" => 3382,
+        "3383" => 3383,
+        "3384" => 3384,
+        "3385" => 3385,
+        "3386" => 3386,
+        "3387" => 3387,
+        "3388" => 3388,
+        "3389" => 3389,
+        "3390" => 3390,
+        "3391" => 3391,
+        "3392" => 3392,
+        "3393" => 3393,
+        "3394" => 3394,
+        "3395" => 3395,
+        "3396" => 3396,
+        "3397" => 3397,
+        "3398" => 3398,
+        "3399" => 3399,
+        "3400" => 3400,
+        "3401" => 3401,
+        "3402" => 3402,
+        "3403" => 3403,
+        "3404" => 3404,
+        "3405" => 3405,
+        "3406" => 3406,
+        "3407" => 3407,
+        "3408" => 3408,
+        "3409" => 3409,
+        "3410" => 3410,
+        "3411" => 3411,
+        "3412" => 3412,
+        "3413" => 3413,
+        "3414" => 3414,
+        "3415" => 3415,
+        "3416" => 3416,
+        "3417" => 3417,
+        "3418" => 3418,
+        "3419" => 3419,
+        "3420" => 3420,
+        "3421" => 3421,
+        "3422" => 3422,
+        "3423" => 3423,
+        "3424" => 3424,
+        "3425" => 3425,
+        "3426" => 3426,
+        "3427" => 3427,
+        "3428" => 3428,
+        "3429" => 3429,
+        "3430" => 3430,
+        "3431" => 3431,
+        "3432" => 3432,
+        "3433" => 3433,
+        "3434" => 3434,
+        "3435" => 3435,
+        "3436" => 3436,
+        "3437" => 3437,
+        "3438" => 3438,
+        "3439" => 3439,
+        "3440" => 3440,
+        "3441" => 3441,
+        "3442" => 3442,
+        "3443" => 3443,
+        "3444" => 3444,
+        "3445" => 3445,
+        "3446" => 3446,
+        "3447" => 3447,
+        "3448" => 3448,
+        "3449" => 3449,
+        "3450" => 3450,
+        "3451" => 3451,
+        "3452" => 3452,
+        "3453" => 3453,
+        "3454" => 3454,
+        "3455" => 3455,
+        "3456" => 3456,
+        "3457" => 3457,
+        "3458" => 3458,
+        "3459" => 3459,
+        "3460" => 3460,
+        "3461" => 3461,
+        "3462" => 3462,
+        "3463" => 3463,
+        "3464" => 3464,
+        "3465" => 3465,
+        "3466" => 3466,
+        "3467" => 3467,
+        "3468" => 3468,
+        "3469" => 3469,
+        "3470" => 3470,
+        "3471" => 3471,
+        "3472" => 3472,
+        "3473" => 3473,
+        "3474" => 3474,
+        "3475" => 3475,
+        "3476" => 3476,
+        "3477" => 3477,
+        "3478" => 3478,
+        "3479" => 3479,
+        "3480" => 3480,
+        "3481" => 3481,
+        "3482" => 3482,
+        "3483" => 3483,
+        "3484" => 3484,
+        "3485" => 3485,
+        "3486" => 3486,
+        "3487" => 3487,
+        "3488" => 3488,
+        "3489" => 3489,
+        "3490" => 3490,
+        "3491" => 3491,
+        "3492" => 3492,
+        "3493" => 3493,
+        "3494" => 3494,
+        "3495" => 3495,
+        "3496" => 3496,
+        "3497" => 3497,
+        "3498" => 3498,
+        "3499" => 3499,
+        "3500" => 3500,
+        "3501" => 3501,
+        "3502" => 3502,
+        "3503" => 3503,
+        "3504" => 3504,
+        "3505" => 3505,
+        "3506" => 3506,
+        "3507" => 3507,
+        "3508" => 3508,
+        "3509" => 3509,
+        "3510" => 3510,
+        "3511" => 3511,
+        "3512" => 3512,
+        "3513" => 3513,
+        "3514" => 3514,
+        "3515" => 3515,
+        "3516" => 3516,
+        "3517" => 3517,
+        "3518" => 3518,
+        "3519" => 3519,
+        "3520" => 3520,
+        "3521" => 3521,
+        "3522" => 3522,
+        "3523" => 3523,
+        "3524" => 3524,
+        "3525" => 3525,
+        "3526" => 3526,
+        "3527" => 3527,
+        "3528" => 3528,
+        "3529" => 3529,
+        "3530" => 3530,
+        "3531" => 3531,
+        "3532" => 3532,
+        "3533" => 3533,
+        "3534" => 3534,
+        "3535" => 3535,
+        "3536" => 3536,
+        "3537" => 3537,
+        "3538" => 3538,
+        "3539" => 3539,
+        "3540" => 3540,
+        "3541" => 3541,
+        "3542" => 3542,
+        "3543" => 3543,
+        "3544" => 3544,
+        "3545" => 3545,
+        "3546" => 3546,
+        "3547" => 3547,
+        "3548" => 3548,
+        "3549" => 3549,
+        "3550" => 3550,
+        "3551" => 3551,
+        "3552" => 3552,
+        "3553" => 3553,
+        "3554" => 3554,
+        "3555" => 3555,
+        "3556" => 3556,
+        "3557" => 3557,
+        "3558" => 3558,
+        "3559" => 3559,
+        "3560" => 3560,
+        "3561" => 3561,
+        "3562" => 3562,
+        "3563" => 3563,
+        "3564" => 3564,
+        "3565" => 3565,
+        "3566" => 3566,
+        "3567" => 3567,
+        "3568" => 3568,
+        "3569" => 3569,
+        "3570" => 3570,
+        "3571" => 3571,
+        "3572" => 3572,
+        "3573" => 3573,
+        "3574" => 3574,
+        "3575" => 3575,
+        "3576" => 3576,
+        "3577" => 3577,
+        "3578" => 3578,
+        "3579" => 3579,
+        "3580" => 3580,
+        "3581" => 3581,
+        "3582" => 3582,
+        "3583" => 3583,
+        "3584" => 3584,
+        "3585" => 3585,
+        "3586" => 3586,
+        "3587" => 3587,
+        "3588" => 3588,
+        "3589" => 3589,
+        "3590" => 3590,
+        "3591" => 3591,
+        "3592" => 3592,
+        "3593" => 3593,
+        "3594" => 3594,
+        "3595" => 3595,
+        "3596" => 3596,
+        "3597" => 3597,
+        "3598" => 3598,
+        "3599" => 3599,
+        "3600" => 3600,
+        "3601" => 3601,
+        "3602" => 3602,
+        "3603" => 3603,
+        "3604" => 3604,
+        "3605" => 3605,
+        "3606" => 3606,
+        "3607" => 3607,
+        "3608" => 3608,
+        "3609" => 3609,
+        "3610" => 3610,
+        "3611" => 3611,
+        "3612" => 3612,
+        "3613" => 3613,
+        "3614" => 3614,
+        "3615" => 3615,
+        "3616" => 3616,
+        "3617" => 3617,
+        "3618" => 3618,
+        "3619" => 3619,
+        "3620" => 3620,
+        "3621" => 3621,
+        "3622" => 3622,
+        "3623" => 3623,
+        "3624" => 3624,
+        "3625" => 3625,
+        "3626" => 3626,
+        "3627" => 3627,
+        "3628" => 3628,
+        "3629" => 3629,
+        "3630" => 3630,
+        "3631" => 3631,
+        "3632" => 3632,
+        "3633" => 3633,
+        "3634" => 3634,
+        "3635" => 3635,
+        "3636" => 3636,
+        "3637" => 3637,
+        "3638" => 3638,
+        "3639" => 3639,
+        "3640" => 3640,
+        "3641" => 3641,
+        "3642" => 3642,
+        "3643" => 3643,
+        "3644" => 3644,
+        "3645" => 3645,
+        "3646" => 3646,
+        "3647" => 3647,
+        "3648" => 3648,
+        "3649" => 3649,
+        "3650" => 3650,
+        "3651" => 3651,
+        "3652" => 3652,
+        "3653" => 3653,
+        "3654" => 3654,
+        "3655" => 3655,
+        "3656" => 3656,
+        "3657" => 3657,
+        "3658" => 3658,
+        "3659" => 3659,
+        "3660" => 3660,
+        "3661" => 3661,
+        "3662" => 3662,
+        "3663" => 3663,
+        "3664" => 3664,
+        "3665" => 3665,
+        "3666" => 3666,
+        "3667" => 3667,
+        "3668" => 3668,
+        "3669" => 3669,
+        "3670" => 3670,
+        "3671" => 3671,
+        "3672" => 3672,
+        "3673" => 3673,
+        "3674" => 3674,
+        "3675" => 3675,
+        "3676" => 3676,
+        "3677" => 3677,
+        "3678" => 3678,
+        "3679" => 3679,
+        "3680" => 3680,
+        "3681" => 3681,
+        "3682" => 3682,
+        "3683" => 3683,
+        "3684" => 3684,
+        "3685" => 3685,
+        "3686" => 3686,
+        "3687" => 3687,
+        "3688" => 3688,
+        "3689" => 3689,
+        "3690" => 3690,
+        "3691" => 3691,
+        "3692" => 3692,
+        "3693" => 3693,
+        "3694" => 3694,
+        "3695" => 3695,
+        "3696" => 3696,
+        "3697" => 3697,
+        "3698" => 3698,
+        "3699" => 3699,
+        "3700" => 3700,
+        "3701" => 3701,
+        "3702" => 3702,
+        "3703" => 3703,
+        "3704" => 3704,
+        "3705" => 3705,
+        "3706" => 3706,
+        "3707" => 3707,
+        "3708" => 3708,
+        "3709" => 3709,
+        "3710" => 3710,
+        "3711" => 3711,
+        "3712" => 3712,
+        "3713" => 3713,
+        "3714" => 3714,
+        "3715" => 3715,
+        "3716" => 3716,
+        "3717" => 3717,
+        "3718" => 3718,
+        "3719" => 3719,
+        "3720" => 3720,
+        "3721" => 3721,
+        "3722" => 3722,
+        "3723" => 3723,
+        "3724" => 3724,
+        "3725" => 3725,
+        "3726" => 3726,
+        "3727" => 3727,
+        "3728" => 3728,
+        "3729" => 3729,
+        "3730" => 3730,
+        "3731" => 3731,
+        "3732" => 3732,
+        "3733" => 3733,
+        "3734" => 3734,
+        "3735" => 3735,
+        "3736" => 3736,
+        "3737" => 3737,
+        "3738" => 3738,
+        "3739" => 3739,
+        "3740" => 3740,
+        "3741" => 3741,
+        "3742" => 3742,
+        "3743" => 3743,
+        "3744" => 3744,
+        "3745" => 3745,
+        "3746" => 3746,
+        "3747" => 3747,
+        "3748" => 3748,
+        "3749" => 3749,
+        "3750" => 3750,
+        "3751" => 3751,
+        "3752" => 3752,
+        "3753" => 3753,
+        "3754" => 3754,
+        "3755" => 3755,
+        "3756" => 3756,
+        "3757" => 3757,
+        "3758" => 3758,
+        "3759" => 3759,
+        "3760" => 3760,
+        "3761" => 3761,
+        "3762" => 3762,
+        "3763" => 3763,
+        "3764" => 3764,
+        "3765" => 3765,
+        "3766" => 3766,
+        "3767" => 3767,
+        "3768" => 3768,
+        "3769" => 3769,
+        "3770" => 3770,
+        "3771" => 3771,
+        "3772" => 3772,
+        "3773" => 3773,
+        "3774" => 3774,
+        "3775" => 3775,
+        "3776" => 3776,
+        "3777" => 3777,
+        "3778" => 3778,
+        "3779" => 3779,
+        "3780" => 3780,
+        "3781" => 3781,
+        "3782" => 3782,
+        "3783" => 3783,
+        "3784" => 3784,
+        "3785" => 3785,
+        "3786" => 3786,
+        "3787" => 3787,
+        "3788" => 3788,
+        "3789" => 3789,
+        "3790" => 3790,
+        "3791" => 3791,
+        "3792" => 3792,
+        "3793" => 3793,
+        "3794" => 3794,
+        "3795" => 3795,
+        "3796" => 3796,
+        "3797" => 3797,
+        "3798" => 3798,
+        "3799" => 3799,
+        "3800" => 3800,
+        "3801" => 3801,
+        "3802" => 3802,
+        "3803" => 3803,
+        "3804" => 3804,
+        "3805" => 3805,
+        "3806" => 3806,
+        "3807" => 3807,
+        "3808" => 3808,
+        "3809" => 3809,
+        "3810" => 3810,
+        "3811" => 3811,
+        "3812" => 3812,
+        "3813" => 3813,
+        "3814" => 3814,
+        "3815" => 3815,
+        "3816" => 3816,
+        "3817" => 3817,
+        "3818" => 3818,
+        "3819" => 3819,
+        "3820" => 3820,
+        "3821" => 3821,
+        "3822" => 3822,
+        "3823" => 3823,
+        "3824" => 3824,
+        "3825" => 3825,
+        "3826" => 3826,
+        "3827" => 3827,
+        "3828" => 3828,
+        "3829" => 3829,
+        "3830" => 3830,
+        "3831" => 3831,
+        "3832" => 3832,
+        "3833" => 3833,
+        "3834" => 3834,
+        "3835" => 3835,
+        "3836" => 3836,
+        "3837" => 3837,
+        "3838" => 3838,
+        "3839" => 3839,
+        "3840" => 3840,
+        "3841" => 3841,
+        "3842" => 3842,
+        "3843" => 3843,
+        "3844" => 3844,
+        "3845" => 3845,
+        "3846" => 3846,
+        "3847" => 3847,
+        "3848" => 3848,
+        "3849" => 3849,
+        "3850" => 3850,
+        "3851" => 3851,
+        "3852" => 3852,
+        "3853" => 3853,
+        "3854" => 3854,
+        "3855" => 3855,
+        "3856" => 3856,
+        "3857" => 3857,
+        "3858" => 3858,
+        "3859" => 3859,
+        "3860" => 3860,
+        "3861" => 3861,
+        "3862" => 3862,
+        "3863" => 3863,
+        "3864" => 3864,
+        "3865" => 3865,
+        "3866" => 3866,
+        "3867" => 3867,
+        "3868" => 3868,
+        "3869" => 3869,
+        "3870" => 3870,
+        "3871" => 3871,
+        "3872" => 3872,
+        "3873" => 3873,
+        "3874" => 3874,
+        "3875" => 3875,
+        "3876" => 3876,
+        "3877" => 3877,
+        "3878" => 3878,
+        "3879" => 3879,
+        "3880" => 3880,
+        "3881" => 3881,
+        "3882" => 3882,
+        "3883" => 3883,
+        "3884" => 3884,
+        "3885" => 3885,
+        "3886" => 3886,
+        "3887" => 3887,
+        "3888" => 3888,
+        "3889" => 3889,
+        "3890" => 3890,
+        "3891" => 3891,
+        "3892" => 3892,
+        "3893" => 3893,
+        "3894" => 3894,
+        "3895" => 3895,
+        "3896" => 3896,
+        "3897" => 3897,
+        "3898" => 3898,
+        "3899" => 3899,
+        "3900" => 3900,
+        "3901" => 3901,
+        "3902" => 3902,
+        "3903" => 3903,
+        "3904" => 3904,
+        "3905" => 3905,
+        "3906" => 3906,
+        "3907" => 3907,
+        "3908" => 3908,
+        "3909" => 3909,
+        "3910" => 3910,
+        "3911" => 3911,
+        "3912" => 3912,
+        "3913" => 3913,
+        "3914" => 3914,
+        "3915" => 3915,
+        "3916" => 3916,
+        "3917" => 3917,
+        "3918" => 3918,
+        "3919" => 3919,
+        "3920" => 3920,
+        "3921" => 3921,
+        "3922" => 3922,
+        "3923" => 3923,
+        "3924" => 3924,
+        "3925" => 3925,
+        "3926" => 3926,
+        "3927" => 3927,
+        "3928" => 3928,
+        "3929" => 3929,
+        "3930" => 3930,
+        "3931" => 3931,
+        "3932" => 3932,
+        "3933" => 3933,
+        "3934" => 3934,
+        "3935" => 3935,
+        "3936" => 3936,
+        "3937" => 3937,
+        "3938" => 3938,
+        "3939" => 3939,
+        "3940" => 3940,
+        "3941" => 3941,
+        "3942" => 3942,
+        "3943" => 3943,
+        "3944" => 3944,
+        "3945" => 3945,
+        "3946" => 3946,
+        "3947" => 3947,
+        "3948" => 3948,
+        "3949" => 3949,
+        "3950" => 3950,
+        "3951" => 3951,
+        "3952" => 3952,
+        "3953" => 3953,
+        "3954" => 3954,
+        "3955" => 3955,
+        "3956" => 3956,
+        "3957" => 3957,
+        "3958" => 3958,
+        "3959" => 3959,
+        "3960" => 3960,
+        "3961" => 3961,
+        "3962" => 3962,
+        "3963" => 3963,
+        "3964" => 3964,
+        "3965" => 3965,
+        "3966" => 3966,
+        "3967" => 3967,
+        "3968" => 3968,
+        "3969" => 3969,
+        "3970" => 3970,
+        "3971" => 3971,
+        "3972" => 3972,
+        "3973" => 3973,
+        "3974" => 3974,
+        "3975" => 3975,
+        "3976" => 3976,
+        "3977" => 3977,
+        "3978" => 3978,
+        "3979" => 3979,
+        "3980" => 3980,
+        "3981" => 3981,
+        "3982" => 3982,
+        "3983" => 3983,
+        "3984" => 3984,
+        "3985" => 3985,
+        "3986" => 3986,
+        "3987" => 3987,
+        "3988" => 3988,
+        "3989" => 3989,
+        "3990" => 3990,
+        "3991" => 3991,
+        "3992" => 3992,
+        "3993" => 3993,
+        "3994" => 3994,
+        "3995" => 3995,
+        "3996" => 3996,
+        "3997" => 3997,
+        "3998" => 3998,
+        "3999" => 3999,
+        "4000" => 4000,
+        "4001" => 4001,
+        "4002" => 4002,
+        "4003" => 4003,
+        "4004" => 4004,
+        "4005" => 4005,
+        "4006" => 4006,
+        "4007" => 4007,
+        "4008" => 4008,
+        "4009" => 4009,
+        "4010" => 4010,
+        "4011" => 4011,
+        "4012" => 4012,
+        "4013" => 4013,
+        "4014" => 4014,
+        "4015" => 4015,
+        "4016" => 4016,
+        "4017" => 4017,
+        "4018" => 4018,
+        "4019" => 4019,
+        "4020" => 4020,
+        "4021" => 4021,
+        "4022" => 4022,
+        "4023" => 4023,
+        "4024" => 4024,
+        "4025" => 4025,
+        "4026" => 4026,
+        "4027" => 4027,
+        "4028" => 4028,
+        "4029" => 4029,
+        "4030" => 4030,
+        "4031" => 4031,
+        "4032" => 4032,
+        "4033" => 4033,
+        "4034" => 4034,
+        "4035" => 4035,
+        "4036" => 4036,
+        "4037" => 4037,
+        "4038" => 4038,
+        "4039" => 4039,
+        "4040" => 4040,
+        "4041" => 4041,
+        "4042" => 4042,
+        "4043" => 4043,
+        "4044" => 4044,
+        "4045" => 4045,
+        "4046" => 4046,
+        "4047" => 4047,
+        "4048" => 4048,
+        "4049" => 4049,
+        "4050" => 4050,
+        "4051" => 4051,
+        "4052" => 4052,
+        "4053" => 4053,
+        "4054" => 4054,
+        "4055" => 4055,
+        "4056" => 4056,
+        "4057" => 4057,
+        "4058" => 4058,
+        "4059" => 4059,
+        "4060" => 4060,
+        "4061" => 4061,
+        "4062" => 4062,
+        "4063" => 4063,
+        "4064" => 4064,
+        "4065" => 4065,
+        "4066" => 4066,
+        "4067" => 4067,
+        "4068" => 4068,
+        "4069" => 4069,
+        "4070" => 4070,
+        "4071" => 4071,
+        "4072" => 4072,
+        "4073" => 4073,
+        "4074" => 4074,
+        "4075" => 4075,
+        "4076" => 4076,
+        "4077" => 4077,
+        "4078" => 4078,
+        "4079" => 4079,
+        "4080" => 4080,
+        "4081" => 4081,
+        "4082" => 4082,
+        "4083" => 4083,
+        "4084" => 4084,
+        "4085" => 4085,
+        "4086" => 4086,
+        "4087" => 4087,
+        "4088" => 4088,
+        "4089" => 4089,
+        "4090" => 4090,
+        "4091" => 4091,
+        "4092" => 4092,
+        "4093" => 4093,
+        "4094" => 4094,
+        "4095" => 4095,
+        "4096" => 4096,
+        "4097" => 4097,
+        "4098" => 4098,
+        "4099" => 4099,
+        "4100" => 4100,
+        "4101" => 4101,
+        "4102" => 4102,
+        "4103" => 4103,
+        "4104" => 4104,
+        "4105" => 4105,
+        "4106" => 4106,
+        "4107" => 4107,
+        "4108" => 4108,
+        "4109" => 4109,
+        "4110" => 4110,
+        "4111" => 4111,
+        "4112" => 4112,
+        "4113" => 4113,
+        "4114" => 4114,
+        "4115" => 4115,
+        "4116" => 4116,
+        "4117" => 4117,
+        "4118" => 4118,
+        "4119" => 4119,
+        "4120" => 4120,
+        "4121" => 4121,
+        "4122" => 4122,
+        "4123" => 4123,
+        "4124" => 4124,
+        "4125" => 4125,
+        "4126" => 4126,
+        "4127" => 4127,
+        "4128" => 4128,
+        "4129" => 4129,
+        "4130" => 4130,
+        "4131" => 4131,
+        "4132" => 4132,
+        "4133" => 4133,
+        "4134" => 4134,
+        "4135" => 4135,
+        "4136" => 4136,
+        "4137" => 4137,
+        "4138" => 4138,
+        "4139" => 4139,
+        "4140" => 4140,
+        "4141" => 4141,
+        "4142" => 4142,
+        "4143" => 4143,
+        "4144" => 4144,
+        "4145" => 4145,
+        "4146" => 4146,
+        "4147" => 4147,
+        "4148" => 4148,
+        "4149" => 4149,
+        "4150" => 4150,
+        "4151" => 4151,
+        "4152" => 4152,
+        "4153" => 4153,
+        "4154" => 4154,
+        "4155" => 4155,
+        "4156" => 4156,
+        "4157" => 4157,
+        "4158" => 4158,
+        "4159" => 4159,
+        "4160" => 4160,
+        "4161" => 4161,
+        "4162" => 4162,
+        "4163" => 4163,
+        "4164" => 4164,
+        "4165" => 4165,
+        "4166" => 4166,
+        "4167" => 4167,
+        "4168" => 4168,
+        "4169" => 4169,
+        "4170" => 4170,
+        "4171" => 4171,
+        "4172" => 4172,
+        "4173" => 4173,
+        "4174" => 4174,
+        "4175" => 4175,
+        "4176" => 4176,
+        "4177" => 4177,
+        "4178" => 4178,
+        "4179" => 4179,
+        "4180" => 4180,
+        "4181" => 4181,
+        "4182" => 4182,
+        "4183" => 4183,
+        "4184" => 4184,
+        "4185" => 4185,
+        "4186" => 4186,
+        "4187" => 4187,
+        "4188" => 4188,
+        "4189" => 4189,
+        "4190" => 4190,
+        "4191" => 4191,
+        "4192" => 4192,
+        "4193" => 4193,
+        "4194" => 4194,
+        "4195" => 4195,
+        "4196" => 4196,
+        "4197" => 4197,
+        "4198" => 4198,
+        "4199" => 4199,
+        "4200" => 4200,
+        "4201" => 4201,
+        "4202" => 4202,
+        "4203" => 4203,
+        "4204" => 4204,
+        "4205" => 4205,
+        "4206" => 4206,
+        "4207" => 4207,
+        "4208" => 4208,
+        "4209" => 4209,
+        "4210" => 4210,
+        "4211" => 4211,
+        "4212" => 4212,
+        "4213" => 4213,
+        "4214" => 4214,
+        "4215" => 4215,
+        "4216" => 4216,
+        "4217" => 4217,
+        "4218" => 4218,
+        "4219" => 4219,
+        "4220" => 4220,
+        "4221" => 4221,
+        "4222" => 4222,
+        "4223" => 4223,
+        "4224" => 4224,
+        "4225" => 4225,
+        "4226" => 4226,
+        "4227" => 4227,
+        "4228" => 4228,
+        "4229" => 4229,
+        "4230" => 4230,
+        "4231" => 4231,
+        "4232" => 4232,
+        "4233" => 4233,
+        "4234" => 4234,
+        "4235" => 4235,
+        "4236" => 4236,
+        "4237" => 4237,
+        "4238" => 4238,
+        "4239" => 4239,
+        "4240" => 4240,
+        "4241" => 4241,
+        "4242" => 4242,
+        "4243" => 4243,
+        "4244" => 4244,
+        "4245" => 4245,
+        "4246" => 4246,
+        "4247" => 4247,
+        "4248" => 4248,
+        "4249" => 4249,
+        "4250" => 4250,
+        "4251" => 4251,
+        "4252" => 4252,
+        "4253" => 4253,
+        "4254" => 4254,
+        "4255" => 4255,
+        "4256" => 4256,
+        "4257" => 4257,
+        "4258" => 4258,
+        "4259" => 4259,
+        "4260" => 4260,
+        "4261" => 4261,
+        "4262" => 4262,
+        "4263" => 4263,
+        "4264" => 4264,
+        "4265" => 4265,
+        "4266" => 4266,
+        "4267" => 4267,
+        "4268" => 4268,
+        "4269" => 4269,
+        "4270" => 4270,
+        "4271" => 4271,
+        "4272" => 4272,
+        "4273" => 4273,
+        "4274" => 4274,
+        "4275" => 4275,
+        "4276" => 4276,
+        "4277" => 4277,
+        "4278" => 4278,
+        "4279" => 4279,
+        "4280" => 4280,
+        "4281" => 4281,
+        "4282" => 4282,
+        "4283" => 4283,
+        "4284" => 4284,
+        "4285" => 4285,
+        "4286" => 4286,
+        "4287" => 4287,
+        "4288" => 4288,
+        "4289" => 4289,
+        "4290" => 4290,
+        "4291" => 4291,
+        "4292" => 4292,
+        "4293" => 4293,
+        "4294" => 4294,
+        "4295" => 4295,
+        "4296" => 4296,
+        "4297" => 4297,
+        "4298" => 4298,
+        "4299" => 4299,
+        "4300" => 4300,
+        "4301" => 4301,
+        "4302" => 4302,
+        "4303" => 4303,
+        "4304" => 4304,
+        "4305" => 4305,
+        "4306" => 4306,
+        "4307" => 4307,
+        "4308" => 4308,
+        "4309" => 4309,
+        "4310" => 4310,
+        "4311" => 4311,
+        "4312" => 4312,
+        "4313" => 4313,
+        "4314" => 4314,
+        "4315" => 4315,
+        "4316" => 4316,
+        "4317" => 4317,
+        "4318" => 4318,
+        "4319" => 4319,
+        "4320" => 4320,
+        "4321" => 4321,
+        "4322" => 4322,
+        "4323" => 4323,
+        "4324" => 4324,
+        "4325" => 4325,
+        "4326" => 4326,
+        "4327" => 4327,
+        "4328" => 4328,
+        "4329" => 4329,
+        "4330" => 4330,
+        "4331" => 4331,
+        "4332" => 4332,
+        "4333" => 4333,
+        "4334" => 4334,
+        "4335" => 4335,
+        "4336" => 4336,
+        "4337" => 4337,
+        "4338" => 4338,
+        "4339" => 4339,
+        "4340" => 4340,
+        "4341" => 4341,
+        "4342" => 4342,
+        "4343" => 4343,
+        "4344" => 4344,
+        "4345" => 4345,
+        "4346" => 4346,
+        "4347" => 4347,
+        "4348" => 4348,
+        "4349" => 4349,
+        "4350" => 4350,
+        "4351" => 4351,
+        "4352" => 4352,
+        "4353" => 4353,
+        "4354" => 4354,
+        "4355" => 4355,
+        "4356" => 4356,
+        "4357" => 4357,
+        "4358" => 4358,
+        "4359" => 4359,
+        "4360" => 4360,
+        "4361" => 4361,
+        "4362" => 4362,
+        "4363" => 4363,
+        "4364" => 4364,
+        "4365" => 4365,
+        "4366" => 4366,
+        "4367" => 4367,
+        "4368" => 4368,
+        "4369" => 4369,
+        "4370" => 4370,
+        "4371" => 4371,
+        "4372" => 4372,
+        "4373" => 4373,
+        "4374" => 4374,
+        "4375" => 4375,
+        "4376" => 4376,
+        "4377" => 4377,
+        "4378" => 4378,
+        "4379" => 4379,
+        "4380" => 4380,
+        "4381" => 4381,
+        "4382" => 4382,
+        "4383" => 4383,
+        "4384" => 4384,
+        "4385" => 4385,
+        "4386" => 4386,
+        "4387" => 4387,
+        "4388" => 4388,
+        "4389" => 4389,
+        "4390" => 4390,
+        "4391" => 4391,
+        "4392" => 4392,
+        "4393" => 4393,
+        "4394" => 4394,
+        "4395" => 4395,
+        "4396" => 4396,
+        "4397" => 4397,
+        "4398" => 4398,
+        "4399" => 4399,
+        "4400" => 4400,
+        "4401" => 4401,
+        "4402" => 4402,
+        "4403" => 4403,
+        "4404" => 4404,
+        "4405" => 4405,
+        "4406" => 4406,
+        "4407" => 4407,
+        "4408" => 4408,
+        "4409" => 4409,
+        "4410" => 4410,
+        "4411" => 4411,
+        "4412" => 4412,
+        "4413" => 4413,
+        "4414" => 4414,
+        "4415" => 4415,
+        "4416" => 4416,
+        "4417" => 4417,
+        "4418" => 4418,
+        "4419" => 4419,
+        "4420" => 4420,
+        "4421" => 4421,
+        "4422" => 4422,
+        "4423" => 4423,
+        "4424" => 4424,
+        "4425" => 4425,
+        "4426" => 4426,
+        "4427" => 4427,
+        "4428" => 4428,
+        "4429" => 4429,
+        "4430" => 4430,
+        "4431" => 4431,
+        "4432" => 4432,
+        "4433" => 4433,
+        "4434" => 4434,
+        "4435" => 4435,
+        "4436" => 4436,
+        "4437" => 4437,
+        "4438" => 4438,
+        "4439" => 4439,
+        "4440" => 4440,
+        "4441" => 4441,
+        "4442" => 4442,
+        "4443" => 4443,
+        "4444" => 4444,
+        "4445" => 4445,
+        "4446" => 4446,
+        "4447" => 4447,
+        "4448" => 4448,
+        "4449" => 4449,
+        "4450" => 4450,
+        "4451" => 4451,
+        "4452" => 4452,
+        "4453" => 4453,
+        "4454" => 4454,
+        "4455" => 4455,
+        "4456" => 4456,
+        "4457" => 4457,
+        "4458" => 4458,
+        "4459" => 4459,
+        "4460" => 4460,
+        "4461" => 4461,
+        "4462" => 4462,
+        "4463" => 4463,
+        "4464" => 4464,
+        "4465" => 4465,
+        "4466" => 4466,
+        "4467" => 4467,
+        "4468" => 4468,
+        "4469" => 4469,
+        "4470" => 4470,
+        "4471" => 4471,
+        "4472" => 4472,
+        "4473" => 4473,
+        "4474" => 4474,
+        "4475" => 4475,
+        "4476" => 4476,
+        "4477" => 4477,
+        "4478" => 4478,
+        "4479" => 4479,
+        "4480" => 4480,
+        "4481" => 4481,
+        "4482" => 4482,
+        "4483" => 4483,
+        "4484" => 4484,
+        "4485" => 4485,
+        "4486" => 4486,
+        "4487" => 4487,
+        "4488" => 4488,
+        "4489" => 4489,
+        "4490" => 4490,
+        "4491" => 4491,
+        "4492" => 4492,
+        "4493" => 4493,
+        "4494" => 4494,
+        "4495" => 4495,
+        "4496" => 4496,
+        "4497" => 4497,
+        "4498" => 4498,
+        "4499" => 4499,
+        "4500" => 4500,
+        "4501" => 4501,
+        "4502" => 4502,
+        "4503" => 4503,
+        "4504" => 4504,
+        "4505" => 4505,
+        "4506" => 4506,
+        "4507" => 4507,
+        "4508" => 4508,
+        "4509" => 4509,
+        "4510" => 4510,
+        "4511" => 4511,
+        "4512" => 4512,
+        "4513" => 4513,
+        "4514" => 4514,
+        "4515" => 4515,
+        "4516" => 4516,
+        "4517" => 4517,
+        "4518" => 4518,
+        "4519" => 4519,
+        "4520" => 4520,
+        "4521" => 4521,
+        "4522" => 4522,
+        "4523" => 4523,
+        "4524" => 4524,
+        "4525" => 4525,
+        "4526" => 4526,
+        "4527" => 4527,
+        "4528" => 4528,
+        "4529" => 4529,
+        "4530" => 4530,
+        "4531" => 4531,
+        "4532" => 4532,
+        "4533" => 4533,
+        "4534" => 4534,
+        "4535" => 4535,
+        "4536" => 4536,
+        "4537" => 4537,
+        "4538" => 4538,
+        "4539" => 4539,
+        "4540" => 4540,
+        "4541" => 4541,
+        "4542" => 4542,
+        "4543" => 4543,
+        "4544" => 4544,
+        "4545" => 4545,
+        "4546" => 4546,
+        "4547" => 4547,
+        "4548" => 4548,
+        "4549" => 4549,
+        "4550" => 4550,
+        "4551" => 4551,
+        "4552" => 4552,
+        "4553" => 4553,
+        "4554" => 4554,
+        "4555" => 4555,
+        "4556" => 4556,
+        "4557" => 4557,
+        "4558" => 4558,
+        "4559" => 4559,
+        "4560" => 4560,
+        "4561" => 4561,
+        "4562" => 4562,
+        "4563" => 4563,
+        "4564" => 4564,
+        "4565" => 4565,
+        "4566" => 4566,
+        "4567" => 4567,
+        "4568" => 4568,
+        "4569" => 4569,
+        "4570" => 4570,
+        "4571" => 4571,
+        "4572" => 4572,
+        "4573" => 4573,
+        "4574" => 4574,
+        "4575" => 4575,
+        "4576" => 4576,
+        "4577" => 4577,
+        "4578" => 4578,
+        "4579" => 4579,
+        "4580" => 4580,
+        "4581" => 4581,
+        "4582" => 4582,
+        "4583" => 4583,
+        "4584" => 4584,
+        "4585" => 4585,
+        "4586" => 4586,
+        "4587" => 4587,
+        "4588" => 4588,
+        "4589" => 4589,
+        "4590" => 4590,
+        "4591" => 4591,
+        "4592" => 4592,
+        "4593" => 4593,
+        "4594" => 4594,
+        "4595" => 4595,
+        "4596" => 4596,
+        "4597" => 4597,
+        "4598" => 4598,
+        "4599" => 4599,
+        "4600" => 4600,
+        "4601" => 4601,
+        "4602" => 4602,
+        "4603" => 4603,
+        "4604" => 4604,
+        "4605" => 4605,
+        "4606" => 4606,
+        "4607" => 4607,
+        "4608" => 4608,
+        "4609" => 4609,
+        "4610" => 4610,
+        "4611" => 4611,
+        "4612" => 4612,
+        "4613" => 4613,
+        "4614" => 4614,
+        "4615" => 4615,
+        "4616" => 4616,
+        "4617" => 4617,
+        "4618" => 4618,
+        "4619" => 4619,
+        "4620" => 4620,
+        "4621" => 4621,
+        "4622" => 4622,
+        "4623" => 4623,
+        "4624" => 4624,
+        "4625" => 4625,
+        "4626" => 4626,
+        "4627" => 4627,
+        "4628" => 4628,
+        "4629" => 4629,
+        "4630" => 4630,
+        "4631" => 4631,
+        "4632" => 4632,
+        "4633" => 4633,
+        "4634" => 4634,
+        "4635" => 4635,
+        "4636" => 4636,
+        "4637" => 4637,
+        "4638" => 4638,
+        "4639" => 4639,
+        "4640" => 4640,
+        "4641" => 4641,
+        "4642" => 4642,
+        "4643" => 4643,
+        "4644" => 4644,
+        "4645" => 4645,
+        "4646" => 4646,
+        "4647" => 4647,
+        "4648" => 4648,
+        "4649" => 4649,
+        "4650" => 4650,
+        "4651" => 4651,
+        "4652" => 4652,
+        "4653" => 4653,
+        "4654" => 4654,
+        "4655" => 4655,
+        "4656" => 4656,
+        "4657" => 4657,
+        "4658" => 4658,
+        "4659" => 4659,
+        "4660" => 4660,
+        "4661" => 4661,
+        "4662" => 4662,
+        "4663" => 4663,
+        "4664" => 4664,
+        "4665" => 4665,
+        "4666" => 4666,
+        "4667" => 4667,
+        "4668" => 4668,
+        "4669" => 4669,
+        "4670" => 4670,
+        "4671" => 4671,
+        "4672" => 4672,
+        "4673" => 4673,
+        "4674" => 4674,
+        "4675" => 4675,
+        "4676" => 4676,
+        "4677" => 4677,
+        "4678" => 4678,
+        "4679" => 4679,
+        "4680" => 4680,
+        "4681" => 4681,
+        "4682" => 4682,
+        "4683" => 4683,
+        "4684" => 4684,
+        "4685" => 4685,
+        "4686" => 4686,
+        "4687" => 4687,
+        "4688" => 4688,
+        "4689" => 4689,
+        "4690" => 4690,
+        "4691" => 4691,
+        "4692" => 4692,
+        "4693" => 4693,
+        "4694" => 4694,
+        "4695" => 4695,
+        "4696" => 4696,
+        "4697" => 4697,
+        "4698" => 4698,
+        "4699" => 4699,
+        "4700" => 4700,
+        "4701" => 4701,
+        "4702" => 4702,
+        "4703" => 4703,
+        "4704" => 4704,
+        "4705" => 4705,
+        "4706" => 4706,
+        "4707" => 4707,
+        "4708" => 4708,
+        "4709" => 4709,
+        "4710" => 4710,
+        "4711" => 4711,
+        "4712" => 4712,
+        "4713" => 4713,
+        "4714" => 4714,
+        "4715" => 4715,
+        "4716" => 4716,
+        "4717" => 4717,
+        "4718" => 4718,
+        "4719" => 4719,
+        "4720" => 4720,
+        "4721" => 4721,
+        "4722" => 4722,
+        "4723" => 4723,
+        "4724" => 4724,
+        "4725" => 4725,
+        "4726" => 4726,
+        "4727" => 4727,
+        "4728" => 4728,
+        "4729" => 4729,
+        "4730" => 4730,
+        "4731" => 4731,
+        "4732" => 4732,
+        "4733" => 4733,
+        "4734" => 4734,
+        "4735" => 4735,
+        "4736" => 4736,
+        "4737" => 4737,
+        "4738" => 4738,
+        "4739" => 4739,
+        "4740" => 4740,
+        "4741" => 4741,
+        "4742" => 4742,
+        "4743" => 4743,
+        "4744" => 4744,
+        "4745" => 4745,
+        "4746" => 4746,
+        "4747" => 4747,
+        "4748" => 4748,
+        "4749" => 4749,
+        "4750" => 4750,
+        "4751" => 4751,
+        "4752" => 4752,
+        "4753" => 4753,
+        "4754" => 4754,
+        "4755" => 4755,
+        "4756" => 4756,
+        "4757" => 4757,
+        "4758" => 4758,
+        "4759" => 4759,
+        "4760" => 4760,
+        "4761" => 4761,
+        "4762" => 4762,
+        "4763" => 4763,
+        "4764" => 4764,
+        "4765" => 4765,
+        "4766" => 4766,
+        "4767" => 4767,
+        "4768" => 4768,
+        "4769" => 4769,
+        "4770" => 4770,
+        "4771" => 4771,
+        "4772" => 4772,
+        "4773" => 4773,
+        "4774" => 4774,
+        "4775" => 4775,
+        "4776" => 4776,
+        "4777" => 4777,
+        "4778" => 4778,
+        "4779" => 4779,
+        "4780" => 4780,
+        "4781" => 4781,
+        "4782" => 4782,
+        "4783" => 4783,
+        "4784" => 4784,
+        "4785" => 4785,
+        "4786" => 4786,
+        "4787" => 4787,
+        "4788" => 4788,
+        "4789" => 4789,
+        "4790" => 4790,
+        "4791" => 4791,
+        "4792" => 4792,
+        "4793" => 4793,
+        "4794" => 4794,
+        "4795" => 4795,
+        "4796" => 4796,
+        "4797" => 4797,
+        "4798" => 4798,
+        "4799" => 4799,
+        "4800" => 4800,
+        "4801" => 4801,
+        "4802" => 4802,
+        "4803" => 4803,
+        "4804" => 4804,
+        "4805" => 4805,
+        "4806" => 4806,
+        "4807" => 4807,
+        "4808" => 4808,
+        "4809" => 4809,
+        "4810" => 4810,
+        "4811" => 4811,
+        "4812" => 4812,
+        "4813" => 4813,
+        "4814" => 4814,
+        "4815" => 4815,
+        "4816" => 4816,
+        "4817" => 4817,
+        "4818" => 4818,
+        "4819" => 4819,
+        "4820" => 4820,
+        "4821" => 4821,
+        "4822" => 4822,
+        "4823" => 4823,
+        "4824" => 4824,
+        "4825" => 4825,
+        "4826" => 4826,
+        "4827" => 4827,
+        "4828" => 4828,
+        "4829" => 4829,
+        "4830" => 4830,
+        "4831" => 4831,
+        "4832" => 4832,
+        "4833" => 4833,
+        "4834" => 4834,
+        "4835" => 4835,
+        "4836" => 4836,
+        "4837" => 4837,
+        "4838" => 4838,
+        "4839" => 4839,
+        "4840" => 4840,
+        "4841" => 4841,
+        "4842" => 4842,
+        "4843" => 4843,
+        "4844" => 4844,
+        "4845" => 4845,
+        "4846" => 4846,
+        "4847" => 4847,
+        "4848" => 4848,
+        "4849" => 4849,
+        "4850" => 4850,
+        "4851" => 4851,
+        "4852" => 4852,
+        "4853" => 4853,
+        "4854" => 4854,
+        "4855" => 4855,
+        "4856" => 4856,
+        "4857" => 4857,
+        "4858" => 4858,
+        "4859" => 4859,
+        "4860" => 4860,
+        "4861" => 4861,
+        "4862" => 4862,
+        "4863" => 4863,
+        "4864" => 4864,
+        "4865" => 4865,
+        "4866" => 4866,
+        "4867" => 4867,
+        "4868" => 4868,
+        "4869" => 4869,
+        "4870" => 4870,
+        "4871" => 4871,
+        "4872" => 4872,
+        "4873" => 4873,
+        "4874" => 4874,
+        "4875" => 4875,
+        "4876" => 4876,
+        "4877" => 4877,
+        "4878" => 4878,
+        "4879" => 4879,
+        "4880" => 4880,
+        "4881" => 4881,
+        "4882" => 4882,
+        "4883" => 4883,
+        "4884" => 4884,
+        "4885" => 4885,
+        "4886" => 4886,
+        "4887" => 4887,
+        "4888" => 4888,
+        "4889" => 4889,
+        "4890" => 4890,
+        "4891" => 4891,
+        "4892" => 4892,
+        "4893" => 4893,
+        "4894" => 4894,
+        "4895" => 4895,
+        "4896" => 4896,
+        "4897" => 4897,
+        "4898" => 4898,
+        "4899" => 4899,
+        "4900" => 4900,
+        "4901" => 4901,
+        "4902" => 4902,
+        "4903" => 4903,
+        "4904" => 4904,
+        "4905" => 4905,
+        "4906" => 4906,
+        "4907" => 4907,
+        "4908" => 4908,
+        "4909" => 4909,
+        "4910" => 4910,
+        "4911" => 4911,
+        "4912" => 4912,
+        "4913" => 4913,
+        "4914" => 4914,
+        "4915" => 4915,
+        "4916" => 4916,
+        "4917" => 4917,
+        "4918" => 4918,
+        "4919" => 4919,
+        "4920" => 4920,
+        "4921" => 4921,
+        "4922" => 4922,
+        "4923" => 4923,
+        "4924" => 4924,
+        "4925" => 4925,
+        "4926" => 4926,
+        "4927" => 4927,
+        "4928" => 4928,
+        "4929" => 4929,
+        "4930" => 4930,
+        "4931" => 4931,
+        "4932" => 4932,
+        "4933" => 4933,
+        "4934" => 4934,
+        "4935" => 4935,
+        "4936" => 4936,
+        "4937" => 4937,
+        "4938" => 4938,
+        "4939" => 4939,
+        "4940" => 4940,
+        "4941" => 4941,
+        "4942" => 4942,
+        "4943" => 4943,
+        "4944" => 4944,
+        "4945" => 4945,
+        "4946" => 4946,
+        "4947" => 4947,
+        "4948" => 4948,
+        "4949" => 4949,
+        "4950" => 4950,
+        "4951" => 4951,
+        "4952" => 4952,
+        "4953" => 4953,
+        "4954" => 4954,
+        "4955" => 4955,
+        "4956" => 4956,
+        "4957" => 4957,
+        "4958" => 4958,
+        "4959" => 4959,
+        "4960" => 4960,
+        "4961" => 4961,
+        "4962" => 4962,
+        "4963" => 4963,
+        "4964" => 4964,
+        "4965" => 4965,
+        "4966" => 4966,
+        "4967" => 4967,
+        "4968" => 4968,
+        "4969" => 4969,
+        "4970" => 4970,
+        "4971" => 4971,
+        "4972" => 4972,
+        "4973" => 4973,
+        "4974" => 4974,
+        "4975" => 4975,
+        "4976" => 4976,
+        "4977" => 4977,
+        "4978" => 4978,
+        "4979" => 4979,
+        "4980" => 4980,
+        "4981" => 4981,
+        "4982" => 4982,
+        "4983" => 4983,
+        "4984" => 4984,
+        "4985" => 4985,
+        "4986" => 4986,
+        "4987" => 4987,
+        "4988" => 4988,
+        "4989" => 4989,
+        "4990" => 4990,
+        "4991" => 4991,
+        "4992" => 4992,
+        "4993" => 4993,
+        "4994" => 4994,
+        "4995" => 4995,
+        "4996" => 4996,
+        "4997" => 4997,
+        "4998" => 4998,
+        "4999" => 4999,
+        "5000" => 5000,
+        "5001" => 5001,
+        "5002" => 5002,
+        "5003" => 5003,
+        "5004" => 5004,
+        "5005" => 5005,
+        "5006" => 5006,
+        "5007" => 5007,
+        "5008" => 5008,
+        "5009" => 5009,
+        "5010" => 5010,
+        "5011" => 5011,
+        "5012" => 5012,
+        "5013" => 5013,
+        "5014" => 5014,
+        "5015" => 5015,
+        "5016" => 5016,
+        "5017" => 5017,
+        "5018" => 5018,
+        "5019" => 5019,
+        "5020" => 5020,
+        "5021" => 5021,
+        "5022" => 5022,
+        "5023" => 5023,
+        "5024" => 5024,
+        "5025" => 5025,
+        "5026" => 5026,
+        "5027" => 5027,
+        "5028" => 5028,
+        "5029" => 5029,
+        "5030" => 5030,
+        "5031" => 5031,
+        "5032" => 5032,
+        "5033" => 5033,
+        "5034" => 5034,
+        "5035" => 5035,
+        "5036" => 5036,
+        "5037" => 5037,
+        "5038" => 5038,
+        "5039" => 5039,
+        "5040" => 5040,
+        "5041" => 5041,
+        "5042" => 5042,
+        "5043" => 5043,
+        "5044" => 5044,
+        "5045" => 5045,
+        "5046" => 5046,
+        "5047" => 5047,
+        "5048" => 5048,
+        "5049" => 5049,
+        "5050" => 5050,
+        "5051" => 5051,
+        "5052" => 5052,
+        "5053" => 5053,
+        "5054" => 5054,
+        "5055" => 5055,
+        "5056" => 5056,
+        "5057" => 5057,
+        "5058" => 5058,
+        "5059" => 5059,
+        "5060" => 5060,
+        "5061" => 5061,
+        "5062" => 5062,
+        "5063" => 5063,
+        "5064" => 5064,
+        "5065" => 5065,
+        "5066" => 5066,
+        "5067" => 5067,
+        "5068" => 5068,
+        "5069" => 5069,
+        "5070" => 5070,
+        "5071" => 5071,
+        "5072" => 5072,
+        "5073" => 5073,
+        "5074" => 5074,
+        "5075" => 5075,
+        "5076" => 5076,
+        "5077" => 5077,
+        "5078" => 5078,
+        "5079" => 5079,
+        "5080" => 5080,
+        "5081" => 5081,
+        "5082" => 5082,
+        "5083" => 5083,
+        "5084" => 5084,
+        "5085" => 5085,
+        "5086" => 5086,
+        "5087" => 5087,
+        "5088" => 5088,
+        "5089" => 5089,
+        "5090" => 5090,
+        "5091" => 5091,
+        "5092" => 5092,
+        "5093" => 5093,
+        "5094" => 5094,
+        "5095" => 5095,
+        "5096" => 5096,
+        "5097" => 5097,
+        "5098" => 5098,
+        "5099" => 5099,
+        "5100" => 5100,
+        "5101" => 5101,
+        "5102" => 5102,
+        "5103" => 5103,
+        "5104" => 5104,
+        "5105" => 5105,
+        "5106" => 5106,
+        "5107" => 5107,
+        "5108" => 5108,
+        "5109" => 5109,
+        "5110" => 5110,
+        "5111" => 5111,
+        "5112" => 5112,
+        "5113" => 5113,
+        "5114" => 5114,
+        "5115" => 5115,
+        "5116" => 5116,
+        "5117" => 5117,
+        "5118" => 5118,
+        "5119" => 5119,
+        "5120" => 5120,
+        "5121" => 5121,
+        "5122" => 5122,
+        "5123" => 5123,
+        "5124" => 5124,
+        "5125" => 5125,
+        "5126" => 5126,
+        "5127" => 5127,
+        "5128" => 5128,
+        "5129" => 5129,
+        "5130" => 5130,
+        "5131" => 5131,
+        "5132" => 5132,
+        "5133" => 5133,
+        "5134" => 5134,
+        "5135" => 5135,
+        "5136" => 5136,
+        "5137" => 5137,
+        "5138" => 5138,
+        "5139" => 5139,
+        "5140" => 5140,
+        "5141" => 5141,
+        "5142" => 5142,
+        "5143" => 5143,
+        "5144" => 5144,
+        "5145" => 5145,
+        "5146" => 5146,
+        "5147" => 5147,
+        "5148" => 5148,
+        "5149" => 5149,
+        "5150" => 5150,
+        "5151" => 5151,
+        "5152" => 5152,
+        "5153" => 5153,
+        "5154" => 5154,
+        "5155" => 5155,
+        "5156" => 5156,
+        "5157" => 5157,
+        "5158" => 5158,
+        "5159" => 5159,
+        "5160" => 5160,
+        "5161" => 5161,
+        "5162" => 5162,
+        "5163" => 5163,
+        "5164" => 5164,
+        "5165" => 5165,
+        "5166" => 5166,
+        "5167" => 5167,
+        "5168" => 5168,
+        "5169" => 5169,
+        "5170" => 5170,
+        "5171" => 5171,
+        "5172" => 5172,
+        "5173" => 5173,
+        "5174" => 5174,
+        "5175" => 5175,
+        "5176" => 5176,
+        "5177" => 5177,
+        "5178" => 5178,
+        "5179" => 5179,
+        "5180" => 5180,
+        "5181" => 5181,
+        "5182" => 5182,
+        "5183" => 5183,
+        "5184" => 5184,
+        "5185" => 5185,
+        "5186" => 5186,
+        "5187" => 5187,
+        "5188" => 5188,
+        "5189" => 5189,
+        "5190" => 5190,
+        "5191" => 5191,
+        "5192" => 5192,
+        "5193" => 5193,
+        "5194" => 5194,
+        "5195" => 5195,
+        "5196" => 5196,
+        "5197" => 5197,
+        "5198" => 5198,
+        _ => 5199,
+    }
+}
diff --git a/src/test/ui/issues/issue-8460.rs b/src/test/ui/issues/issue-8460.rs
index 3fd576a8d35..a7de4bd74aa 100644
--- a/src/test/ui/issues/issue-8460.rs
+++ b/src/test/ui/issues/issue-8460.rs
@@ -27,21 +27,21 @@ macro_rules! check {
 
 fn main() {
     check![
-        isize::min_value() / -isize::one(),
-        i8::min_value() / -i8::one(),
-        i16::min_value() / -i16::one(),
-        i32::min_value() / -i32::one(),
-        i64::min_value() / -i64::one(),
+        isize::MIN / -isize::one(),
+        i8::MIN / -i8::one(),
+        i16::MIN / -i16::one(),
+        i32::MIN / -i32::one(),
+        i64::MIN / -i64::one(),
         1isize / isize::zero(),
         1i8 / i8::zero(),
         1i16 / i16::zero(),
         1i32 / i32::zero(),
         1i64 / i64::zero(),
-        isize::min_value() % -isize::one(),
-        i8::min_value() % -i8::one(),
-        i16::min_value() % -i16::one(),
-        i32::min_value() % -i32::one(),
-        i64::min_value() % -i64::one(),
+        isize::MIN % -isize::one(),
+        i8::MIN % -i8::one(),
+        i16::MIN % -i16::one(),
+        i32::MIN % -i32::one(),
+        i64::MIN % -i64::one(),
         1isize % isize::zero(),
         1i8 % i8::zero(),
         1i16 % i16::zero(),
diff --git a/src/test/ui/iterators/iter-step-overflow-debug.rs b/src/test/ui/iterators/iter-step-overflow-debug.rs
index 5d67c7cbb42..67605d2fcc2 100644
--- a/src/test/ui/iterators/iter-step-overflow-debug.rs
+++ b/src/test/ui/iterators/iter-step-overflow-debug.rs
@@ -6,14 +6,14 @@ use std::panic;
 
 fn main() {
     let r = panic::catch_unwind(|| {
-        let mut it = u8::max_value()..;
+        let mut it = u8::MAX..;
         it.next().unwrap(); // 255
         it.next().unwrap();
     });
     assert!(r.is_err());
 
     let r = panic::catch_unwind(|| {
-        let mut it = i8::max_value()..;
+        let mut it = i8::MAX..;
         it.next().unwrap(); // 127
         it.next().unwrap();
     });
diff --git a/src/test/ui/iterators/iter-step-overflow-ndebug.rs b/src/test/ui/iterators/iter-step-overflow-ndebug.rs
index a0ad92071b6..33e708769ba 100644
--- a/src/test/ui/iterators/iter-step-overflow-ndebug.rs
+++ b/src/test/ui/iterators/iter-step-overflow-ndebug.rs
@@ -2,11 +2,11 @@
 // compile-flags: -C debug_assertions=no
 
 fn main() {
-    let mut it = u8::max_value()..;
+    let mut it = u8::MAX..;
     assert_eq!(it.next().unwrap(), 255);
-    assert_eq!(it.next().unwrap(), u8::min_value());
+    assert_eq!(it.next().unwrap(), u8::MIN);
 
-    let mut it = i8::max_value()..;
+    let mut it = i8::MAX..;
     assert_eq!(it.next().unwrap(), 127);
-    assert_eq!(it.next().unwrap(), i8::min_value());
+    assert_eq!(it.next().unwrap(), i8::MIN);
 }
diff --git a/src/test/ui/iterators/iter-sum-overflow-debug.rs b/src/test/ui/iterators/iter-sum-overflow-debug.rs
index ee4ab4d24c6..b7667d1bbf6 100644
--- a/src/test/ui/iterators/iter-sum-overflow-debug.rs
+++ b/src/test/ui/iterators/iter-sum-overflow-debug.rs
@@ -6,22 +6,22 @@ use std::panic;
 
 fn main() {
     let r = panic::catch_unwind(|| {
-        [1, i32::max_value()].iter().sum::<i32>();
+        [1, i32::MAX].iter().sum::<i32>();
     });
     assert!(r.is_err());
 
     let r = panic::catch_unwind(|| {
-        [2, i32::max_value()].iter().product::<i32>();
+        [2, i32::MAX].iter().product::<i32>();
     });
     assert!(r.is_err());
 
     let r = panic::catch_unwind(|| {
-        [1, i32::max_value()].iter().cloned().sum::<i32>();
+        [1, i32::MAX].iter().cloned().sum::<i32>();
     });
     assert!(r.is_err());
 
     let r = panic::catch_unwind(|| {
-        [2, i32::max_value()].iter().cloned().product::<i32>();
+        [2, i32::MAX].iter().cloned().product::<i32>();
     });
     assert!(r.is_err());
 }
diff --git a/src/test/ui/iterators/iter-sum-overflow-ndebug.rs b/src/test/ui/iterators/iter-sum-overflow-ndebug.rs
index 61d63d41fb8..69f4744cc2a 100644
--- a/src/test/ui/iterators/iter-sum-overflow-ndebug.rs
+++ b/src/test/ui/iterators/iter-sum-overflow-ndebug.rs
@@ -2,13 +2,13 @@
 // compile-flags: -C debug_assertions=no
 
 fn main() {
-    assert_eq!([1i32, i32::max_value()].iter().sum::<i32>(),
-               1i32.wrapping_add(i32::max_value()));
-    assert_eq!([2i32, i32::max_value()].iter().product::<i32>(),
-               2i32.wrapping_mul(i32::max_value()));
+    assert_eq!([1i32, i32::MAX].iter().sum::<i32>(),
+               1i32.wrapping_add(i32::MAX));
+    assert_eq!([2i32, i32::MAX].iter().product::<i32>(),
+               2i32.wrapping_mul(i32::MAX));
 
-    assert_eq!([1i32, i32::max_value()].iter().cloned().sum::<i32>(),
-               1i32.wrapping_add(i32::max_value()));
-    assert_eq!([2i32, i32::max_value()].iter().cloned().product::<i32>(),
-               2i32.wrapping_mul(i32::max_value()));
+    assert_eq!([1i32, i32::MAX].iter().cloned().sum::<i32>(),
+               1i32.wrapping_add(i32::MAX));
+    assert_eq!([2i32, i32::MAX].iter().cloned().product::<i32>(),
+               2i32.wrapping_mul(i32::MAX));
 }
diff --git a/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs b/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs
index 429f8e0bc96..04ca7f8a315 100644
--- a/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs
+++ b/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs
@@ -6,22 +6,22 @@ use std::panic;
 
 fn main() {
     let r = panic::catch_unwind(|| {
-        [1, i32::max_value()].iter().sum::<i32>();
+        [1, i32::MAX].iter().sum::<i32>();
     });
     assert!(r.is_err());
 
     let r = panic::catch_unwind(|| {
-        [2, i32::max_value()].iter().product::<i32>();
+        [2, i32::MAX].iter().product::<i32>();
     });
     assert!(r.is_err());
 
     let r = panic::catch_unwind(|| {
-        [1, i32::max_value()].iter().cloned().sum::<i32>();
+        [1, i32::MAX].iter().cloned().sum::<i32>();
     });
     assert!(r.is_err());
 
     let r = panic::catch_unwind(|| {
-        [2, i32::max_value()].iter().cloned().product::<i32>();
+        [2, i32::MAX].iter().cloned().product::<i32>();
     });
     assert!(r.is_err());
 }
diff --git a/src/test/ui/iterators/skip-count-overflow.rs b/src/test/ui/iterators/skip-count-overflow.rs
index d8efc948664..64dee3e3c8b 100644
--- a/src/test/ui/iterators/skip-count-overflow.rs
+++ b/src/test/ui/iterators/skip-count-overflow.rs
@@ -3,6 +3,6 @@
 // compile-flags: -C overflow-checks -C opt-level=3
 
 fn main() {
-    let i = (0..usize::max_value()).chain(0..10).skip(usize::max_value());
+    let i = (0..usize::MAX).chain(0..10).skip(usize::MAX);
     assert_eq!(i.count(), 10);
 }
diff --git a/src/test/ui/lexical-scopes.stderr b/src/test/ui/lexical-scopes.stderr
index dce70545170..1e6a35ed479 100644
--- a/src/test/ui/lexical-scopes.stderr
+++ b/src/test/ui/lexical-scopes.stderr
@@ -3,11 +3,6 @@ error[E0574]: expected struct, variant or union type, found type parameter `T`
    |
 LL |     let t = T { i: 0 };
    |             ^ not a struct, variant or union type
-   |
-help: consider importing this struct instead
-   |
-LL | use T;
-   |
 
 error[E0599]: no function or associated item named `f` found for type parameter `Foo` in the current scope
   --> $DIR/lexical-scopes.rs:10:10
diff --git a/src/test/ui/lint/expansion-time-include.rs b/src/test/ui/lint/expansion-time-include.rs
new file mode 100644
index 00000000000..4ea89d5adff
--- /dev/null
+++ b/src/test/ui/lint/expansion-time-include.rs
@@ -0,0 +1,4 @@
+// ignore-test auxiliary file for expansion-time.rs
+
+1
+2
diff --git a/src/test/ui/lint/expansion-time.rs b/src/test/ui/lint/expansion-time.rs
new file mode 100644
index 00000000000..6e420c51f0a
--- /dev/null
+++ b/src/test/ui/lint/expansion-time.rs
@@ -0,0 +1,23 @@
+// check-pass
+
+#[warn(meta_variable_misuse)]
+macro_rules! foo {
+    ( $($i:ident)* ) => { $($i)+ }; //~ WARN meta-variable repeats with different Kleene operator
+}
+
+#[warn(missing_fragment_specifier)]
+macro_rules! m { ($i) => {} } //~ WARN missing fragment specifier
+                              //~| WARN this was previously accepted
+
+#[warn(soft_unstable)]
+mod benches {
+    #[bench] //~ WARN use of unstable library feature 'test'
+             //~| WARN this was previously accepted
+    fn foo() {}
+}
+
+#[warn(incomplete_include)]
+fn main() {
+    // WARN see in the stderr file, the warning points to the included file.
+    include!("expansion-time-include.rs");
+}
diff --git a/src/test/ui/lint/expansion-time.stderr b/src/test/ui/lint/expansion-time.stderr
new file mode 100644
index 00000000000..e6b5cf67e39
--- /dev/null
+++ b/src/test/ui/lint/expansion-time.stderr
@@ -0,0 +1,56 @@
+warning: meta-variable repeats with different Kleene operator
+  --> $DIR/expansion-time.rs:5:29
+   |
+LL |     ( $($i:ident)* ) => { $($i)+ };
+   |                  -          ^^ - conflicting repetition
+   |                  |
+   |                  expected repetition
+   |
+note: the lint level is defined here
+  --> $DIR/expansion-time.rs:3:8
+   |
+LL | #[warn(meta_variable_misuse)]
+   |        ^^^^^^^^^^^^^^^^^^^^
+
+warning: missing fragment specifier
+  --> $DIR/expansion-time.rs:9:19
+   |
+LL | macro_rules! m { ($i) => {} }
+   |                   ^^
+   |
+note: the lint level is defined here
+  --> $DIR/expansion-time.rs:8:8
+   |
+LL | #[warn(missing_fragment_specifier)]
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
+
+warning: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable
+  --> $DIR/expansion-time.rs:14:7
+   |
+LL |     #[bench]
+   |       ^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/expansion-time.rs:12:8
+   |
+LL | #[warn(soft_unstable)]
+   |        ^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
+
+warning: include macro expected single expression in source
+  --> $DIR/expansion-time-include.rs:4:1
+   |
+LL | 2
+   | ^
+   |
+note: the lint level is defined here
+  --> $DIR/expansion-time.rs:19:8
+   |
+LL | #[warn(incomplete_include)]
+   |        ^^^^^^^^^^^^^^^^^^
+
+warning: 4 warnings emitted
+
diff --git a/src/test/ui/lint/inline-trait-and-foreign-items.stderr b/src/test/ui/lint/inline-trait-and-foreign-items.stderr
index 15aaf8961b7..ae04612a4dd 100644
--- a/src/test/ui/lint/inline-trait-and-foreign-items.stderr
+++ b/src/test/ui/lint/inline-trait-and-foreign-items.stderr
@@ -62,10 +62,10 @@ LL |     type U = impl Trait;
    |     -------------------- not a function or closure
 
 error: could not find defining uses
-  --> $DIR/inline-trait-and-foreign-items.rs:26:5
+  --> $DIR/inline-trait-and-foreign-items.rs:26:14
    |
 LL |     type U = impl Trait;
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |              ^^^^^^^^^^
 
 error: aborting due to 6 previous errors; 2 warnings emitted
 
diff --git a/src/test/ui/lint/lint-ctypes-66202.rs b/src/test/ui/lint/lint-ctypes-66202.rs
new file mode 100644
index 00000000000..ebab41d143e
--- /dev/null
+++ b/src/test/ui/lint/lint-ctypes-66202.rs
@@ -0,0 +1,17 @@
+// check-pass
+
+#![deny(improper_ctypes)]
+
+// This test checks that return types are normalized before being checked for FFI-safety, and that
+// transparent newtype wrappers are FFI-safe if the type being wrapped is FFI-safe.
+
+#[repr(transparent)]
+pub struct W<T>(T);
+
+extern "C" {
+    pub fn bare() -> ();
+    pub fn normalize() -> <() as ToOwned>::Owned;
+    pub fn transparent() -> W<()>;
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/opaque-ty-ffi-unsafe.rs b/src/test/ui/lint/opaque-ty-ffi-unsafe.rs
index 25d5f8ec68a..3cbc084ecae 100644
--- a/src/test/ui/lint/opaque-ty-ffi-unsafe.rs
+++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.rs
@@ -1,5 +1,4 @@
 #![feature(type_alias_impl_trait)]
-
 #![deny(improper_ctypes)]
 
 type A = impl Fn();
@@ -10,7 +9,7 @@ pub fn ret_closure() -> A {
 
 extern "C" {
     pub fn a(_: A);
-    //~^ ERROR `extern` block uses type `A`, which is not FFI-safe
+//~^ ERROR `extern` block uses type `impl std::ops::Fn<()>`, which is not FFI-safe
 }
 
 fn main() {}
diff --git a/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr
index 712095e3208..06dfb7b8fbe 100644
--- a/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr
+++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr
@@ -1,11 +1,11 @@
-error: `extern` block uses type `A`, which is not FFI-safe
-  --> $DIR/opaque-ty-ffi-unsafe.rs:12:17
+error: `extern` block uses type `impl std::ops::Fn<()>`, which is not FFI-safe
+  --> $DIR/opaque-ty-ffi-unsafe.rs:11:17
    |
 LL |     pub fn a(_: A);
    |                 ^ not FFI-safe
    |
 note: the lint level is defined here
-  --> $DIR/opaque-ty-ffi-unsafe.rs:3:9
+  --> $DIR/opaque-ty-ffi-unsafe.rs:2:9
    |
 LL | #![deny(improper_ctypes)]
    |         ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/match/issue-72896.rs b/src/test/ui/match/issue-72896.rs
new file mode 100644
index 00000000000..3a8b8203731
--- /dev/null
+++ b/src/test/ui/match/issue-72896.rs
@@ -0,0 +1,23 @@
+// run-pass
+trait EnumSetType {
+    type Repr;
+}
+
+enum Enum8 { }
+impl EnumSetType for Enum8 {
+    type Repr = u8;
+}
+
+#[derive(PartialEq, Eq)]
+struct EnumSet<T: EnumSetType> {
+    __enumset_underlying: T::Repr,
+}
+
+const CONST_SET: EnumSet<Enum8> = EnumSet { __enumset_underlying: 3 };
+
+fn main() {
+    match CONST_SET {
+        CONST_SET => { /* ok */ }
+        _ => panic!("match fell through?"),
+    }
+}
diff --git a/src/test/ui/moves/move-fn-self-receiver.rs b/src/test/ui/moves/move-fn-self-receiver.rs
new file mode 100644
index 00000000000..6107f53fa19
--- /dev/null
+++ b/src/test/ui/moves/move-fn-self-receiver.rs
@@ -0,0 +1,74 @@
+use std::pin::Pin;
+use std::rc::Rc;
+use std::ops::Add;
+
+struct Foo;
+
+impl Add for Foo {
+    type Output = ();
+    fn add(self, _rhs: Self) -> () {}
+}
+
+impl Foo {
+    fn use_self(self) {}
+    fn use_box_self(self: Box<Self>) {}
+    fn use_pin_box_self(self: Pin<Box<Self>>) {}
+    fn use_rc_self(self: Rc<Self>) {}
+    fn use_mut_self(&mut self) -> &mut Self { self }
+}
+
+struct Container(Vec<bool>);
+
+impl Container {
+    fn custom_into_iter(self) -> impl Iterator<Item = bool> {
+        self.0.into_iter()
+    }
+}
+
+fn move_out(val: Container) {
+    val.0.into_iter().next();
+    val.0; //~ ERROR use of moved
+
+    let foo = Foo;
+    foo.use_self();
+    foo; //~ ERROR use of moved
+
+    let second_foo = Foo;
+    second_foo.use_self();
+    second_foo; //~ ERROR use of moved
+
+    let boxed_foo = Box::new(Foo);
+    boxed_foo.use_box_self();
+    boxed_foo; //~ ERROR use of moved
+
+    let pin_box_foo = Box::pin(Foo);
+    pin_box_foo.use_pin_box_self();
+    pin_box_foo; //~ ERROR use of moved
+
+    let mut mut_foo = Foo;
+    let ret = mut_foo.use_mut_self();
+    mut_foo; //~ ERROR cannot move out
+    ret;
+
+    let rc_foo = Rc::new(Foo);
+    rc_foo.use_rc_self();
+    rc_foo; //~ ERROR use of moved
+
+    let foo_add = Foo;
+    foo_add + Foo;
+    foo_add; //~ ERROR use of moved
+
+    let implicit_into_iter = vec![true];
+    for _val in implicit_into_iter {}
+    implicit_into_iter; //~ ERROR use of moved
+
+    let explicit_into_iter = vec![true];
+    for _val in explicit_into_iter.into_iter() {}
+    explicit_into_iter; //~ ERROR use of moved
+
+    let container = Container(vec![]);
+    for _val in container.custom_into_iter() {}
+    container; //~ ERROR use of moved
+}
+
+fn main() {}
diff --git a/src/test/ui/moves/move-fn-self-receiver.stderr b/src/test/ui/moves/move-fn-self-receiver.stderr
new file mode 100644
index 00000000000..4333e8a23e8
--- /dev/null
+++ b/src/test/ui/moves/move-fn-self-receiver.stderr
@@ -0,0 +1,158 @@
+error[E0382]: use of moved value: `val.0`
+  --> $DIR/move-fn-self-receiver.rs:30:5
+   |
+LL |     val.0.into_iter().next();
+   |           ----------- `val.0` moved due to this method call
+LL |     val.0;
+   |     ^^^^^ value used here after move
+   |
+note: this function consumes the receiver `self` by taking ownership of it, which moves `val.0`
+  --> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |                  ^^^^
+   = note: move occurs because `val.0` has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `foo`
+  --> $DIR/move-fn-self-receiver.rs:34:5
+   |
+LL |     let foo = Foo;
+   |         --- move occurs because `foo` has type `Foo`, which does not implement the `Copy` trait
+LL |     foo.use_self();
+   |         ---------- `foo` moved due to this method call
+LL |     foo;
+   |     ^^^ value used here after move
+   |
+note: this function consumes the receiver `self` by taking ownership of it, which moves `foo`
+  --> $DIR/move-fn-self-receiver.rs:13:17
+   |
+LL |     fn use_self(self) {}
+   |                 ^^^^
+
+error[E0382]: use of moved value: `second_foo`
+  --> $DIR/move-fn-self-receiver.rs:38:5
+   |
+LL |     let second_foo = Foo;
+   |         ---------- move occurs because `second_foo` has type `Foo`, which does not implement the `Copy` trait
+LL |     second_foo.use_self();
+   |                ---------- `second_foo` moved due to this method call
+LL |     second_foo;
+   |     ^^^^^^^^^^ value used here after move
+
+error[E0382]: use of moved value: `boxed_foo`
+  --> $DIR/move-fn-self-receiver.rs:42:5
+   |
+LL |     let boxed_foo = Box::new(Foo);
+   |         --------- move occurs because `boxed_foo` has type `std::boxed::Box<Foo>`, which does not implement the `Copy` trait
+LL |     boxed_foo.use_box_self();
+   |               -------------- `boxed_foo` moved due to this method call
+LL |     boxed_foo;
+   |     ^^^^^^^^^ value used here after move
+   |
+note: this function consumes the receiver `self` by taking ownership of it, which moves `boxed_foo`
+  --> $DIR/move-fn-self-receiver.rs:14:21
+   |
+LL |     fn use_box_self(self: Box<Self>) {}
+   |                     ^^^^
+
+error[E0382]: use of moved value: `pin_box_foo`
+  --> $DIR/move-fn-self-receiver.rs:46:5
+   |
+LL |     let pin_box_foo = Box::pin(Foo);
+   |         ----------- move occurs because `pin_box_foo` has type `std::pin::Pin<std::boxed::Box<Foo>>`, which does not implement the `Copy` trait
+LL |     pin_box_foo.use_pin_box_self();
+   |                 ------------------ `pin_box_foo` moved due to this method call
+LL |     pin_box_foo;
+   |     ^^^^^^^^^^^ value used here after move
+   |
+note: this function consumes the receiver `self` by taking ownership of it, which moves `pin_box_foo`
+  --> $DIR/move-fn-self-receiver.rs:15:25
+   |
+LL |     fn use_pin_box_self(self: Pin<Box<Self>>) {}
+   |                         ^^^^
+
+error[E0505]: cannot move out of `mut_foo` because it is borrowed
+  --> $DIR/move-fn-self-receiver.rs:50:5
+   |
+LL |     let ret = mut_foo.use_mut_self();
+   |               ------- borrow of `mut_foo` occurs here
+LL |     mut_foo;
+   |     ^^^^^^^ move out of `mut_foo` occurs here
+LL |     ret;
+   |     --- borrow later used here
+
+error[E0382]: use of moved value: `rc_foo`
+  --> $DIR/move-fn-self-receiver.rs:55:5
+   |
+LL |     let rc_foo = Rc::new(Foo);
+   |         ------ move occurs because `rc_foo` has type `std::rc::Rc<Foo>`, which does not implement the `Copy` trait
+LL |     rc_foo.use_rc_self();
+   |            ------------- `rc_foo` moved due to this method call
+LL |     rc_foo;
+   |     ^^^^^^ value used here after move
+   |
+note: this function consumes the receiver `self` by taking ownership of it, which moves `rc_foo`
+  --> $DIR/move-fn-self-receiver.rs:16:20
+   |
+LL |     fn use_rc_self(self: Rc<Self>) {}
+   |                    ^^^^
+
+error[E0382]: use of moved value: `foo_add`
+  --> $DIR/move-fn-self-receiver.rs:59:5
+   |
+LL |     let foo_add = Foo;
+   |         ------- move occurs because `foo_add` has type `Foo`, which does not implement the `Copy` trait
+LL |     foo_add + Foo;
+   |     ------------- `foo_add` moved due to usage in operator
+LL |     foo_add;
+   |     ^^^^^^^ value used here after move
+   |
+note: calling this operator moves the left-hand side
+  --> $SRC_DIR/libcore/ops/arith.rs:LL:COL
+   |
+LL |     fn add(self, rhs: Rhs) -> Self::Output;
+   |            ^^^^
+
+error[E0382]: use of moved value: `implicit_into_iter`
+  --> $DIR/move-fn-self-receiver.rs:63:5
+   |
+LL |     let implicit_into_iter = vec![true];
+   |         ------------------ move occurs because `implicit_into_iter` has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
+LL |     for _val in implicit_into_iter {}
+   |                 ------------------
+   |                 |
+   |                 `implicit_into_iter` moved due to this implicit call to `.into_iter()`
+   |                 help: consider borrowing to avoid moving into the for loop: `&implicit_into_iter`
+LL |     implicit_into_iter;
+   |     ^^^^^^^^^^^^^^^^^^ value used here after move
+
+error[E0382]: use of moved value: `explicit_into_iter`
+  --> $DIR/move-fn-self-receiver.rs:67:5
+   |
+LL |     let explicit_into_iter = vec![true];
+   |         ------------------ move occurs because `explicit_into_iter` has type `std::vec::Vec<bool>`, which does not implement the `Copy` trait
+LL |     for _val in explicit_into_iter.into_iter() {}
+   |                                    ----------- `explicit_into_iter` moved due to this method call
+LL |     explicit_into_iter;
+   |     ^^^^^^^^^^^^^^^^^^ value used here after move
+
+error[E0382]: use of moved value: `container`
+  --> $DIR/move-fn-self-receiver.rs:71:5
+   |
+LL |     let container = Container(vec![]);
+   |         --------- move occurs because `container` has type `Container`, which does not implement the `Copy` trait
+LL |     for _val in container.custom_into_iter() {}
+   |                           ------------------ `container` moved due to this method call
+LL |     container;
+   |     ^^^^^^^^^ value used here after move
+   |
+note: this function consumes the receiver `self` by taking ownership of it, which moves `container`
+  --> $DIR/move-fn-self-receiver.rs:23:25
+   |
+LL |     fn custom_into_iter(self) -> impl Iterator<Item = bool> {
+   |                         ^^^^
+
+error: aborting due to 11 previous errors
+
+Some errors have detailed explanations: E0382, E0505.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/moves/moves-based-on-type-access-to-field.stderr b/src/test/ui/moves/moves-based-on-type-access-to-field.stderr
index 71a3c4506ea..142feb280d1 100644
--- a/src/test/ui/moves/moves-based-on-type-access-to-field.stderr
+++ b/src/test/ui/moves/moves-based-on-type-access-to-field.stderr
@@ -4,9 +4,15 @@ error[E0382]: borrow of moved value: `x`
 LL |     let x = vec!["hi".to_string()];
    |         - move occurs because `x` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
 LL |     consume(x.into_iter().next().unwrap());
-   |             - value moved here
+   |               ----------- `x` moved due to this method call
 LL |     touch(&x[0]);
    |            ^ value borrowed here after move
+   |
+note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
+  --> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |                  ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/moves/moves-based-on-type-exprs.stderr b/src/test/ui/moves/moves-based-on-type-exprs.stderr
index 67fae606c4e..ff98aab50c9 100644
--- a/src/test/ui/moves/moves-based-on-type-exprs.stderr
+++ b/src/test/ui/moves/moves-based-on-type-exprs.stderr
@@ -104,9 +104,15 @@ error[E0382]: borrow of moved value: `x`
 LL |     let x = vec!["hi".to_string()];
    |         - move occurs because `x` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
 LL |     let _y = x.into_iter().next().unwrap();
-   |              - value moved here
+   |                ----------- `x` moved due to this method call
 LL |     touch(&x);
    |           ^^ value borrowed here after move
+   |
+note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
+  --> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |                  ^^^^
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/moves-based-on-type-exprs.rs:83:11
@@ -114,9 +120,15 @@ error[E0382]: borrow of moved value: `x`
 LL |     let x = vec!["hi".to_string()];
    |         - move occurs because `x` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
 LL |     let _y = [x.into_iter().next().unwrap(); 1];
-   |               - value moved here
+   |                 ----------- `x` moved due to this method call
 LL |     touch(&x);
    |           ^^ value borrowed here after move
+   |
+note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
+  --> $SRC_DIR/libcore/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |                  ^^^^
 
 error: aborting due to 11 previous errors
 
diff --git a/src/test/ui/nll/issue-53040.stderr b/src/test/ui/nll/issue-53040.stderr
index 7cba32c6743..87ffe9b1abf 100644
--- a/src/test/ui/nll/issue-53040.stderr
+++ b/src/test/ui/nll/issue-53040.stderr
@@ -1,9 +1,13 @@
 error: captured variable cannot escape `FnMut` closure body
   --> $DIR/issue-53040.rs:3:8
    |
+LL |     let mut v: Vec<()> = Vec::new();
+   |         ----- variable defined here
 LL |     || &mut v;
-   |      - ^^^^^^ returns a reference to a captured variable which escapes the closure body
-   |      |
+   |      - ^^^^^-
+   |      | |    |
+   |      | |    variable captured here
+   |      | returns a reference to a captured variable which escapes the closure body
    |      inferred to be a `FnMut` closure
    |
    = note: `FnMut` closures only have access to their captured variables while they are executing...
diff --git a/src/test/ui/no-implicit-prelude-nested.stderr b/src/test/ui/no-implicit-prelude-nested.stderr
index 8a26366d751..198b630c52c 100644
--- a/src/test/ui/no-implicit-prelude-nested.stderr
+++ b/src/test/ui/no-implicit-prelude-nested.stderr
@@ -15,12 +15,10 @@ error[E0404]: expected trait, found derive macro `Clone`
 LL |         impl Clone for Test {}
    |              ^^^^^ not a trait
    |
-help: consider importing one of these items instead
+help: consider importing this trait instead
    |
 LL |         use std::clone::Clone;
    |
-LL |         use std::prelude::v1::Clone;
-   |
 
 error[E0405]: cannot find trait `Iterator` in this scope
   --> $DIR/no-implicit-prelude-nested.rs:13:14
@@ -28,12 +26,10 @@ error[E0405]: cannot find trait `Iterator` in this scope
 LL |         impl Iterator for Test {}
    |              ^^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this trait
    |
 LL |         use std::iter::Iterator;
    |
-LL |         use std::prelude::v1::Iterator;
-   |
 
 error[E0405]: cannot find trait `ToString` in this scope
   --> $DIR/no-implicit-prelude-nested.rs:14:14
@@ -41,9 +37,7 @@ error[E0405]: cannot find trait `ToString` in this scope
 LL |         impl ToString for Test {}
    |              ^^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
-   |
-LL |         use std::prelude::v1::ToString;
+help: consider importing this trait
    |
 LL |         use std::string::ToString;
    |
@@ -60,12 +54,10 @@ error[E0425]: cannot find function `drop` in this scope
 LL |             drop(2)
    |             ^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this function
    |
 LL |         use std::mem::drop;
    |
-LL |         use std::prelude::v1::drop;
-   |
 
 error[E0405]: cannot find trait `Add` in this scope
   --> $DIR/no-implicit-prelude-nested.rs:23:10
@@ -84,12 +76,10 @@ error[E0404]: expected trait, found derive macro `Clone`
 LL |     impl Clone for Test {}
    |          ^^^^^ not a trait
    |
-help: consider importing one of these items instead
+help: consider importing this trait instead
    |
 LL |     use std::clone::Clone;
    |
-LL |     use std::prelude::v1::Clone;
-   |
 
 error[E0405]: cannot find trait `Iterator` in this scope
   --> $DIR/no-implicit-prelude-nested.rs:25:10
@@ -97,12 +87,10 @@ error[E0405]: cannot find trait `Iterator` in this scope
 LL |     impl Iterator for Test {}
    |          ^^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this trait
    |
 LL |     use std::iter::Iterator;
    |
-LL |     use std::prelude::v1::Iterator;
-   |
 
 error[E0405]: cannot find trait `ToString` in this scope
   --> $DIR/no-implicit-prelude-nested.rs:26:10
@@ -110,9 +98,7 @@ error[E0405]: cannot find trait `ToString` in this scope
 LL |     impl ToString for Test {}
    |          ^^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
-   |
-LL |     use std::prelude::v1::ToString;
+help: consider importing this trait
    |
 LL |     use std::string::ToString;
    |
@@ -129,12 +115,10 @@ error[E0425]: cannot find function `drop` in this scope
 LL |         drop(2)
    |         ^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this function
    |
 LL |     use std::mem::drop;
    |
-LL |     use std::prelude::v1::drop;
-   |
 
 error[E0405]: cannot find trait `Add` in this scope
   --> $DIR/no-implicit-prelude-nested.rs:38:14
@@ -153,12 +137,10 @@ error[E0404]: expected trait, found derive macro `Clone`
 LL |         impl Clone for Test {}
    |              ^^^^^ not a trait
    |
-help: consider importing one of these items instead
+help: consider importing this trait instead
    |
 LL |         use std::clone::Clone;
    |
-LL |         use std::prelude::v1::Clone;
-   |
 
 error[E0405]: cannot find trait `Iterator` in this scope
   --> $DIR/no-implicit-prelude-nested.rs:40:14
@@ -166,12 +148,10 @@ error[E0405]: cannot find trait `Iterator` in this scope
 LL |         impl Iterator for Test {}
    |              ^^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this trait
    |
 LL |         use std::iter::Iterator;
    |
-LL |         use std::prelude::v1::Iterator;
-   |
 
 error[E0405]: cannot find trait `ToString` in this scope
   --> $DIR/no-implicit-prelude-nested.rs:41:14
@@ -179,9 +159,7 @@ error[E0405]: cannot find trait `ToString` in this scope
 LL |         impl ToString for Test {}
    |              ^^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
-   |
-LL |         use std::prelude::v1::ToString;
+help: consider importing this trait
    |
 LL |         use std::string::ToString;
    |
@@ -198,12 +176,10 @@ error[E0425]: cannot find function `drop` in this scope
 LL |             drop(2)
    |             ^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this function
    |
 LL |         use std::mem::drop;
    |
-LL |         use std::prelude::v1::drop;
-   |
 
 error: aborting due to 18 previous errors
 
diff --git a/src/test/ui/no-implicit-prelude.stderr b/src/test/ui/no-implicit-prelude.stderr
index 9cda4f64c79..36a9b65b7d1 100644
--- a/src/test/ui/no-implicit-prelude.stderr
+++ b/src/test/ui/no-implicit-prelude.stderr
@@ -15,12 +15,10 @@ error[E0404]: expected trait, found derive macro `Clone`
 LL | impl Clone for Test {}
    |      ^^^^^ not a trait
    |
-help: consider importing one of these items instead
+help: consider importing this trait instead
    |
 LL | use std::clone::Clone;
    |
-LL | use std::prelude::v1::Clone;
-   |
 
 error[E0405]: cannot find trait `Iterator` in this scope
   --> $DIR/no-implicit-prelude.rs:12:6
@@ -28,12 +26,10 @@ error[E0405]: cannot find trait `Iterator` in this scope
 LL | impl Iterator for Test {}
    |      ^^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this trait
    |
 LL | use std::iter::Iterator;
    |
-LL | use std::prelude::v1::Iterator;
-   |
 
 error[E0405]: cannot find trait `ToString` in this scope
   --> $DIR/no-implicit-prelude.rs:13:6
@@ -41,9 +37,7 @@ error[E0405]: cannot find trait `ToString` in this scope
 LL | impl ToString for Test {}
    |      ^^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
-   |
-LL | use std::prelude::v1::ToString;
+help: consider importing this trait
    |
 LL | use std::string::ToString;
    |
@@ -60,12 +54,10 @@ error[E0425]: cannot find function `drop` in this scope
 LL |     drop(2)
    |     ^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this function
    |
 LL | use std::mem::drop;
    |
-LL | use std::prelude::v1::drop;
-   |
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/numbers-arithmetic/i128.rs b/src/test/ui/numbers-arithmetic/i128.rs
index ef558c0aa0c..d61a1ab03b6 100644
--- a/src/test/ui/numbers-arithmetic/i128.rs
+++ b/src/test/ui/numbers-arithmetic/i128.rs
@@ -87,7 +87,7 @@ fn main() {
     assert_eq!((-z).checked_mul(-z), Some(0x734C_C2F2_A521));
     assert_eq!((z).checked_mul(z), Some(0x734C_C2F2_A521));
     assert_eq!((k).checked_mul(k), None);
-    let l: i128 = b(i128::min_value());
+    let l: i128 = b(i128::MIN);
     let o: i128 = b(17);
     assert_eq!(l.checked_sub(b(2)), None);
     assert_eq!(l.checked_add(l), None);
diff --git a/src/test/ui/numbers-arithmetic/int-abs-overflow.rs b/src/test/ui/numbers-arithmetic/int-abs-overflow.rs
index 2bc018445db..10ec3f0c662 100644
--- a/src/test/ui/numbers-arithmetic/int-abs-overflow.rs
+++ b/src/test/ui/numbers-arithmetic/int-abs-overflow.rs
@@ -5,9 +5,9 @@
 use std::thread;
 
 fn main() {
-    assert!(thread::spawn(|| i8::min_value().abs()).join().is_err());
-    assert!(thread::spawn(|| i16::min_value().abs()).join().is_err());
-    assert!(thread::spawn(|| i32::min_value().abs()).join().is_err());
-    assert!(thread::spawn(|| i64::min_value().abs()).join().is_err());
-    assert!(thread::spawn(|| isize::min_value().abs()).join().is_err());
+    assert!(thread::spawn(|| i8::MIN.abs()).join().is_err());
+    assert!(thread::spawn(|| i16::MIN.abs()).join().is_err());
+    assert!(thread::spawn(|| i32::MIN.abs()).join().is_err());
+    assert!(thread::spawn(|| i64::MIN.abs()).join().is_err());
+    assert!(thread::spawn(|| isize::MIN.abs()).join().is_err());
 }
diff --git a/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs b/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs
index e9927304f23..101c5d50b20 100644
--- a/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs
+++ b/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs
@@ -9,12 +9,12 @@ fn main() {
     macro_rules! overflow_test {
         ($t:ident) => (
             let r = panic::catch_unwind(|| {
-                ($t::max_value()).next_power_of_two()
+                ($t::MAX).next_power_of_two()
             });
             assert!(r.is_err());
 
             let r = panic::catch_unwind(|| {
-                (($t::max_value() >> 1) + 2).next_power_of_two()
+                (($t::MAX >> 1) + 2).next_power_of_two()
             });
             assert!(r.is_err());
         )
diff --git a/src/test/ui/numbers-arithmetic/promoted_overflow_opt.rs b/src/test/ui/numbers-arithmetic/promoted_overflow_opt.rs
index a3b8ff58a73..4785abbc554 100644
--- a/src/test/ui/numbers-arithmetic/promoted_overflow_opt.rs
+++ b/src/test/ui/numbers-arithmetic/promoted_overflow_opt.rs
@@ -5,5 +5,5 @@
 
 fn main() {
     let x = &(0u32 - 1);
-    assert_eq!(*x, u32::max_value())
+    assert_eq!(*x, u32::MAX)
 }
diff --git a/src/test/ui/numbers-arithmetic/u128.rs b/src/test/ui/numbers-arithmetic/u128.rs
index 0b2305c6e8b..d7e28055b21 100644
--- a/src/test/ui/numbers-arithmetic/u128.rs
+++ b/src/test/ui/numbers-arithmetic/u128.rs
@@ -53,14 +53,14 @@ fn main() {
     assert_eq!("10000000000000000000000000000000000000000000000000000000000000000000",
                format!("{:b}", j));
     assert_eq!("340282366920938463463374607431768211455",
-        format!("{}", u128::max_value()));
+        format!("{}", u128::MAX));
     assert_eq!("147573952589676412928", format!("{:?}", j));
     // common traits
     assert_eq!(x, b(x.clone()));
     // overflow checks
     assert_eq!((z).checked_mul(z), Some(0x734C_C2F2_A521));
     assert_eq!((k).checked_mul(k), None);
-    let l: u128 = b(u128::max_value() - 10);
+    let l: u128 = b(u128::MAX - 10);
     let o: u128 = b(17);
     assert_eq!(l.checked_add(b(11)), None);
     assert_eq!(l.checked_sub(l), Some(0));
diff --git a/src/test/ui/numeric/const-scope.stderr b/src/test/ui/numeric/const-scope.stderr
index 6e1990e3a72..d7f18e19b41 100644
--- a/src/test/ui/numeric/const-scope.stderr
+++ b/src/test/ui/numeric/const-scope.stderr
@@ -3,6 +3,11 @@ error[E0308]: mismatched types
    |
 LL | const C: i32 = 1i8;
    |                ^^^ expected `i32`, found `i8`
+   |
+help: change the type of the numeric literal from `i8` to `i32`
+   |
+LL | const C: i32 = 1i32;
+   |                ^^^^
 
 error[E0308]: mismatched types
   --> $DIR/const-scope.rs:2:15
@@ -17,6 +22,11 @@ LL |     let c: i32 = 1i8;
    |            ---   ^^^ expected `i32`, found `i8`
    |            |
    |            expected due to this
+   |
+help: change the type of the numeric literal from `i8` to `i32`
+   |
+LL |     let c: i32 = 1i32;
+   |                  ^^^^
 
 error[E0308]: mismatched types
   --> $DIR/const-scope.rs:6:17
diff --git a/src/test/ui/numeric/numeric-cast-binop.fixed b/src/test/ui/numeric/numeric-cast-binop.fixed
new file mode 100644
index 00000000000..edb085e71d3
--- /dev/null
+++ b/src/test/ui/numeric/numeric-cast-binop.fixed
@@ -0,0 +1,320 @@
+// run-rustfix
+
+// The `try_into` suggestion doesn't include this, but we do suggest it after applying it
+use std::convert::TryInto;
+
+#[allow(unused_must_use)]
+fn main() {
+    let x_usize: usize = 1;
+    let x_u128: u128 = 2;
+    let x_u64: u64 = 3;
+    let x_u32: u32 = 4;
+    let x_u16: u16 = 5;
+    let x_u8: u8 = 6;
+    let x_isize: isize = 7;
+    let x_i64: i64 = 8;
+    let x_i32: i32 = 9;
+    let x_i16: i16 = 10;
+    let x_i8: i8 = 11;
+    let x_i128: i128 = 12;
+
+    /* u<->u */
+    {
+        u16::from(x_u8) > x_u16;
+        //~^ ERROR mismatched types
+        u32::from(x_u8) > x_u32;
+        //~^ ERROR mismatched types
+        u64::from(x_u8) > x_u64;
+        //~^ ERROR mismatched types
+        u128::from(x_u8) > x_u128;
+        //~^ ERROR mismatched types
+        usize::from(x_u8) > x_usize;
+        //~^ ERROR mismatched types
+
+        x_u16 > x_u8.into();
+        //~^ ERROR mismatched types
+        u32::from(x_u16) > x_u32;
+        //~^ ERROR mismatched types
+        u64::from(x_u16) > x_u64;
+        //~^ ERROR mismatched types
+        u128::from(x_u16) > x_u128;
+        //~^ ERROR mismatched types
+        usize::from(x_u16) > x_usize;
+        //~^ ERROR mismatched types
+
+        x_u32 > x_u8.into();
+        //~^ ERROR mismatched types
+        x_u32 > x_u16.into();
+        //~^ ERROR mismatched types
+        u64::from(x_u32) > x_u64;
+        //~^ ERROR mismatched types
+        u128::from(x_u32) > x_u128;
+        //~^ ERROR mismatched types
+        x_u32 > x_usize.try_into().unwrap();
+        //~^ ERROR mismatched types
+
+        x_u64 > x_u8.into();
+        //~^ ERROR mismatched types
+        x_u64 > x_u16.into();
+        //~^ ERROR mismatched types
+        x_u64 > x_u32.into();
+        //~^ ERROR mismatched types
+        u128::from(x_u64) > x_u128;
+        //~^ ERROR mismatched types
+        x_u64 > x_usize.try_into().unwrap();
+        //~^ ERROR mismatched types
+
+        x_u128 > x_u8.into();
+        //~^ ERROR mismatched types
+        x_u128 > x_u16.into();
+        //~^ ERROR mismatched types
+        x_u128 > x_u32.into();
+        //~^ ERROR mismatched types
+        x_u128 > x_u64.into();
+        //~^ ERROR mismatched types
+        x_u128 > x_usize.try_into().unwrap();
+        //~^ ERROR mismatched types
+
+        x_usize > x_u8.into();
+        //~^ ERROR mismatched types
+        x_usize > x_u16.into();
+        //~^ ERROR mismatched types
+        x_usize > x_u32.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_usize > x_u64.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_usize > x_u128.try_into().unwrap();
+        //~^ ERROR mismatched types
+    }
+
+    /* i<->i */
+    {
+        i16::from(x_i8) > x_i16;
+        //~^ ERROR mismatched types
+        i32::from(x_i8) > x_i32;
+        //~^ ERROR mismatched types
+        i64::from(x_i8) > x_i64;
+        //~^ ERROR mismatched types
+        i128::from(x_i8) > x_i128;
+        //~^ ERROR mismatched types
+        isize::from(x_i8) > x_isize;
+        //~^ ERROR mismatched types
+
+        x_i16 > x_i8.into();
+        //~^ ERROR mismatched types
+        i32::from(x_i16) > x_i32;
+        //~^ ERROR mismatched types
+        i64::from(x_i16) > x_i64;
+        //~^ ERROR mismatched types
+        i128::from(x_i16) > x_i128;
+        //~^ ERROR mismatched types
+        isize::from(x_i16) > x_isize;
+        //~^ ERROR mismatched types
+
+        x_i32 > x_i8.into();
+        //~^ ERROR mismatched types
+        x_i32 > x_i16.into();
+        //~^ ERROR mismatched types
+        i64::from(x_i32) > x_i64;
+        //~^ ERROR mismatched types
+        i128::from(x_i32) > x_i128;
+        //~^ ERROR mismatched types
+        x_i32 > x_isize.try_into().unwrap();
+        //~^ ERROR mismatched types
+
+        x_i64 > x_i8.into();
+        //~^ ERROR mismatched types
+        x_i64 > x_i16.into();
+        //~^ ERROR mismatched types
+        x_i64 > x_i32.into();
+        //~^ ERROR mismatched types
+        i128::from(x_i64) > x_i128;
+        //~^ ERROR mismatched types
+        x_i64 > x_isize.try_into().unwrap();
+        //~^ ERROR mismatched types
+
+        x_i128 > x_i8.into();
+        //~^ ERROR mismatched types
+        x_i128 > x_i16.into();
+        //~^ ERROR mismatched types
+        x_i128 > x_i32.into();
+        //~^ ERROR mismatched types
+        x_i128 > x_i64.into();
+        //~^ ERROR mismatched types
+        x_i128 > x_isize.try_into().unwrap();
+        //~^ ERROR mismatched types
+
+        x_isize > x_i8.into();
+        //~^ ERROR mismatched types
+        x_isize > x_i16.into();
+        //~^ ERROR mismatched types
+        x_isize > x_i32.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_isize > x_i64.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_isize > x_i128.try_into().unwrap();
+        //~^ ERROR mismatched types
+    }
+
+    /* u<->i */
+    {
+        x_u8 > x_i8.try_into().unwrap();
+        //~^ ERROR mismatched types
+        i16::from(x_u8) > x_i16;
+        //~^ ERROR mismatched types
+        i32::from(x_u8) > x_i32;
+        //~^ ERROR mismatched types
+        i64::from(x_u8) > x_i64;
+        //~^ ERROR mismatched types
+        i128::from(x_u8) > x_i128;
+        //~^ ERROR mismatched types
+        isize::from(x_u8) > x_isize;
+        //~^ ERROR mismatched types
+
+        x_u16 > x_i8.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_u16 > x_i16.try_into().unwrap();
+        //~^ ERROR mismatched types
+        i32::from(x_u16) > x_i32;
+        //~^ ERROR mismatched types
+        i64::from(x_u16) > x_i64;
+        //~^ ERROR mismatched types
+        i128::from(x_u16) > x_i128;
+        //~^ ERROR mismatched types
+        x_u16 > x_isize.try_into().unwrap();
+        //~^ ERROR mismatched types
+
+        x_u32 > x_i8.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_u32 > x_i16.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_u32 > x_i32.try_into().unwrap();
+        //~^ ERROR mismatched types
+        i64::from(x_u32) > x_i64;
+        //~^ ERROR mismatched types
+        i128::from(x_u32) > x_i128;
+        //~^ ERROR mismatched types
+        x_u32 > x_isize.try_into().unwrap();
+        //~^ ERROR mismatched types
+
+        x_u64 > x_i8.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_u64 > x_i16.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_u64 > x_i32.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_u64 > x_i64.try_into().unwrap();
+        //~^ ERROR mismatched types
+        i128::from(x_u64) > x_i128;
+        //~^ ERROR mismatched types
+        x_u64 > x_isize.try_into().unwrap();
+        //~^ ERROR mismatched types
+
+        x_u128 > x_i8.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_u128 > x_i16.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_u128 > x_i32.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_u128 > x_i64.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_u128 > x_i128.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_u128 > x_isize.try_into().unwrap();
+        //~^ ERROR mismatched types
+
+        x_usize > x_i8.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_usize > x_i16.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_usize > x_i32.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_usize > x_i64.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_usize > x_i128.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_usize > x_isize.try_into().unwrap();
+        //~^ ERROR mismatched types
+    }
+
+    /* i<->u */
+    {
+        x_i8 > x_u8.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_i8 > x_u16.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_i8 > x_u32.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_i8 > x_u64.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_i8 > x_u128.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_i8 > x_usize.try_into().unwrap();
+        //~^ ERROR mismatched types
+
+        x_i16 > x_u8.into();
+        //~^ ERROR mismatched types
+        x_i16 > x_u16.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_i16 > x_u32.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_i16 > x_u64.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_i16 > x_u128.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_i16 > x_usize.try_into().unwrap();
+        //~^ ERROR mismatched types
+
+        x_i32 > x_u8.into();
+        //~^ ERROR mismatched types
+        x_i32 > x_u16.into();
+        //~^ ERROR mismatched types
+        x_i32 > x_u32.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_i32 > x_u64.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_i32 > x_u128.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_i32 > x_usize.try_into().unwrap();
+        //~^ ERROR mismatched types
+
+        x_i64 > x_u8.into();
+        //~^ ERROR mismatched types
+        x_i64 > x_u16.into();
+        //~^ ERROR mismatched types
+        x_i64 > x_u32.into();
+        //~^ ERROR mismatched types
+        x_i64 > x_u64.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_i64 > x_u128.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_i64 > x_usize.try_into().unwrap();
+        //~^ ERROR mismatched types
+
+        x_i128 > x_u8.into();
+        //~^ ERROR mismatched types
+        x_i128 > x_u16.into();
+        //~^ ERROR mismatched types
+        x_i128 > x_u32.into();
+        //~^ ERROR mismatched types
+        x_i128 > x_u64.into();
+        //~^ ERROR mismatched types
+        x_i128 > x_u128.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_i128 > x_usize.try_into().unwrap();
+        //~^ ERROR mismatched types
+
+        x_isize > x_u8.into();
+        //~^ ERROR mismatched types
+        x_isize > x_u16.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_isize > x_u32.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_isize > x_u64.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_isize > x_u128.try_into().unwrap();
+        //~^ ERROR mismatched types
+        x_isize > x_usize.try_into().unwrap();
+        //~^ ERROR mismatched types
+    }
+}
diff --git a/src/test/ui/numeric/numeric-cast-binop.rs b/src/test/ui/numeric/numeric-cast-binop.rs
new file mode 100644
index 00000000000..c1ed8de8ad8
--- /dev/null
+++ b/src/test/ui/numeric/numeric-cast-binop.rs
@@ -0,0 +1,320 @@
+// run-rustfix
+
+// The `try_into` suggestion doesn't include this, but we do suggest it after applying it
+use std::convert::TryInto;
+
+#[allow(unused_must_use)]
+fn main() {
+    let x_usize: usize = 1;
+    let x_u128: u128 = 2;
+    let x_u64: u64 = 3;
+    let x_u32: u32 = 4;
+    let x_u16: u16 = 5;
+    let x_u8: u8 = 6;
+    let x_isize: isize = 7;
+    let x_i64: i64 = 8;
+    let x_i32: i32 = 9;
+    let x_i16: i16 = 10;
+    let x_i8: i8 = 11;
+    let x_i128: i128 = 12;
+
+    /* u<->u */
+    {
+        x_u8 > x_u16;
+        //~^ ERROR mismatched types
+        x_u8 > x_u32;
+        //~^ ERROR mismatched types
+        x_u8 > x_u64;
+        //~^ ERROR mismatched types
+        x_u8 > x_u128;
+        //~^ ERROR mismatched types
+        x_u8 > x_usize;
+        //~^ ERROR mismatched types
+
+        x_u16 > x_u8;
+        //~^ ERROR mismatched types
+        x_u16 > x_u32;
+        //~^ ERROR mismatched types
+        x_u16 > x_u64;
+        //~^ ERROR mismatched types
+        x_u16 > x_u128;
+        //~^ ERROR mismatched types
+        x_u16 > x_usize;
+        //~^ ERROR mismatched types
+
+        x_u32 > x_u8;
+        //~^ ERROR mismatched types
+        x_u32 > x_u16;
+        //~^ ERROR mismatched types
+        x_u32 > x_u64;
+        //~^ ERROR mismatched types
+        x_u32 > x_u128;
+        //~^ ERROR mismatched types
+        x_u32 > x_usize;
+        //~^ ERROR mismatched types
+
+        x_u64 > x_u8;
+        //~^ ERROR mismatched types
+        x_u64 > x_u16;
+        //~^ ERROR mismatched types
+        x_u64 > x_u32;
+        //~^ ERROR mismatched types
+        x_u64 > x_u128;
+        //~^ ERROR mismatched types
+        x_u64 > x_usize;
+        //~^ ERROR mismatched types
+
+        x_u128 > x_u8;
+        //~^ ERROR mismatched types
+        x_u128 > x_u16;
+        //~^ ERROR mismatched types
+        x_u128 > x_u32;
+        //~^ ERROR mismatched types
+        x_u128 > x_u64;
+        //~^ ERROR mismatched types
+        x_u128 > x_usize;
+        //~^ ERROR mismatched types
+
+        x_usize > x_u8;
+        //~^ ERROR mismatched types
+        x_usize > x_u16;
+        //~^ ERROR mismatched types
+        x_usize > x_u32;
+        //~^ ERROR mismatched types
+        x_usize > x_u64;
+        //~^ ERROR mismatched types
+        x_usize > x_u128;
+        //~^ ERROR mismatched types
+    }
+
+    /* i<->i */
+    {
+        x_i8 > x_i16;
+        //~^ ERROR mismatched types
+        x_i8 > x_i32;
+        //~^ ERROR mismatched types
+        x_i8 > x_i64;
+        //~^ ERROR mismatched types
+        x_i8 > x_i128;
+        //~^ ERROR mismatched types
+        x_i8 > x_isize;
+        //~^ ERROR mismatched types
+
+        x_i16 > x_i8;
+        //~^ ERROR mismatched types
+        x_i16 > x_i32;
+        //~^ ERROR mismatched types
+        x_i16 > x_i64;
+        //~^ ERROR mismatched types
+        x_i16 > x_i128;
+        //~^ ERROR mismatched types
+        x_i16 > x_isize;
+        //~^ ERROR mismatched types
+
+        x_i32 > x_i8;
+        //~^ ERROR mismatched types
+        x_i32 > x_i16;
+        //~^ ERROR mismatched types
+        x_i32 > x_i64;
+        //~^ ERROR mismatched types
+        x_i32 > x_i128;
+        //~^ ERROR mismatched types
+        x_i32 > x_isize;
+        //~^ ERROR mismatched types
+
+        x_i64 > x_i8;
+        //~^ ERROR mismatched types
+        x_i64 > x_i16;
+        //~^ ERROR mismatched types
+        x_i64 > x_i32;
+        //~^ ERROR mismatched types
+        x_i64 > x_i128;
+        //~^ ERROR mismatched types
+        x_i64 > x_isize;
+        //~^ ERROR mismatched types
+
+        x_i128 > x_i8;
+        //~^ ERROR mismatched types
+        x_i128 > x_i16;
+        //~^ ERROR mismatched types
+        x_i128 > x_i32;
+        //~^ ERROR mismatched types
+        x_i128 > x_i64;
+        //~^ ERROR mismatched types
+        x_i128 > x_isize;
+        //~^ ERROR mismatched types
+
+        x_isize > x_i8;
+        //~^ ERROR mismatched types
+        x_isize > x_i16;
+        //~^ ERROR mismatched types
+        x_isize > x_i32;
+        //~^ ERROR mismatched types
+        x_isize > x_i64;
+        //~^ ERROR mismatched types
+        x_isize > x_i128;
+        //~^ ERROR mismatched types
+    }
+
+    /* u<->i */
+    {
+        x_u8 > x_i8;
+        //~^ ERROR mismatched types
+        x_u8 > x_i16;
+        //~^ ERROR mismatched types
+        x_u8 > x_i32;
+        //~^ ERROR mismatched types
+        x_u8 > x_i64;
+        //~^ ERROR mismatched types
+        x_u8 > x_i128;
+        //~^ ERROR mismatched types
+        x_u8 > x_isize;
+        //~^ ERROR mismatched types
+
+        x_u16 > x_i8;
+        //~^ ERROR mismatched types
+        x_u16 > x_i16;
+        //~^ ERROR mismatched types
+        x_u16 > x_i32;
+        //~^ ERROR mismatched types
+        x_u16 > x_i64;
+        //~^ ERROR mismatched types
+        x_u16 > x_i128;
+        //~^ ERROR mismatched types
+        x_u16 > x_isize;
+        //~^ ERROR mismatched types
+
+        x_u32 > x_i8;
+        //~^ ERROR mismatched types
+        x_u32 > x_i16;
+        //~^ ERROR mismatched types
+        x_u32 > x_i32;
+        //~^ ERROR mismatched types
+        x_u32 > x_i64;
+        //~^ ERROR mismatched types
+        x_u32 > x_i128;
+        //~^ ERROR mismatched types
+        x_u32 > x_isize;
+        //~^ ERROR mismatched types
+
+        x_u64 > x_i8;
+        //~^ ERROR mismatched types
+        x_u64 > x_i16;
+        //~^ ERROR mismatched types
+        x_u64 > x_i32;
+        //~^ ERROR mismatched types
+        x_u64 > x_i64;
+        //~^ ERROR mismatched types
+        x_u64 > x_i128;
+        //~^ ERROR mismatched types
+        x_u64 > x_isize;
+        //~^ ERROR mismatched types
+
+        x_u128 > x_i8;
+        //~^ ERROR mismatched types
+        x_u128 > x_i16;
+        //~^ ERROR mismatched types
+        x_u128 > x_i32;
+        //~^ ERROR mismatched types
+        x_u128 > x_i64;
+        //~^ ERROR mismatched types
+        x_u128 > x_i128;
+        //~^ ERROR mismatched types
+        x_u128 > x_isize;
+        //~^ ERROR mismatched types
+
+        x_usize > x_i8;
+        //~^ ERROR mismatched types
+        x_usize > x_i16;
+        //~^ ERROR mismatched types
+        x_usize > x_i32;
+        //~^ ERROR mismatched types
+        x_usize > x_i64;
+        //~^ ERROR mismatched types
+        x_usize > x_i128;
+        //~^ ERROR mismatched types
+        x_usize > x_isize;
+        //~^ ERROR mismatched types
+    }
+
+    /* i<->u */
+    {
+        x_i8 > x_u8;
+        //~^ ERROR mismatched types
+        x_i8 > x_u16;
+        //~^ ERROR mismatched types
+        x_i8 > x_u32;
+        //~^ ERROR mismatched types
+        x_i8 > x_u64;
+        //~^ ERROR mismatched types
+        x_i8 > x_u128;
+        //~^ ERROR mismatched types
+        x_i8 > x_usize;
+        //~^ ERROR mismatched types
+
+        x_i16 > x_u8;
+        //~^ ERROR mismatched types
+        x_i16 > x_u16;
+        //~^ ERROR mismatched types
+        x_i16 > x_u32;
+        //~^ ERROR mismatched types
+        x_i16 > x_u64;
+        //~^ ERROR mismatched types
+        x_i16 > x_u128;
+        //~^ ERROR mismatched types
+        x_i16 > x_usize;
+        //~^ ERROR mismatched types
+
+        x_i32 > x_u8;
+        //~^ ERROR mismatched types
+        x_i32 > x_u16;
+        //~^ ERROR mismatched types
+        x_i32 > x_u32;
+        //~^ ERROR mismatched types
+        x_i32 > x_u64;
+        //~^ ERROR mismatched types
+        x_i32 > x_u128;
+        //~^ ERROR mismatched types
+        x_i32 > x_usize;
+        //~^ ERROR mismatched types
+
+        x_i64 > x_u8;
+        //~^ ERROR mismatched types
+        x_i64 > x_u16;
+        //~^ ERROR mismatched types
+        x_i64 > x_u32;
+        //~^ ERROR mismatched types
+        x_i64 > x_u64;
+        //~^ ERROR mismatched types
+        x_i64 > x_u128;
+        //~^ ERROR mismatched types
+        x_i64 > x_usize;
+        //~^ ERROR mismatched types
+
+        x_i128 > x_u8;
+        //~^ ERROR mismatched types
+        x_i128 > x_u16;
+        //~^ ERROR mismatched types
+        x_i128 > x_u32;
+        //~^ ERROR mismatched types
+        x_i128 > x_u64;
+        //~^ ERROR mismatched types
+        x_i128 > x_u128;
+        //~^ ERROR mismatched types
+        x_i128 > x_usize;
+        //~^ ERROR mismatched types
+
+        x_isize > x_u8;
+        //~^ ERROR mismatched types
+        x_isize > x_u16;
+        //~^ ERROR mismatched types
+        x_isize > x_u32;
+        //~^ ERROR mismatched types
+        x_isize > x_u64;
+        //~^ ERROR mismatched types
+        x_isize > x_u128;
+        //~^ ERROR mismatched types
+        x_isize > x_usize;
+        //~^ ERROR mismatched types
+    }
+}
diff --git a/src/test/ui/numeric/numeric-cast-binop.stderr b/src/test/ui/numeric/numeric-cast-binop.stderr
new file mode 100644
index 00000000000..47be817b789
--- /dev/null
+++ b/src/test/ui/numeric/numeric-cast-binop.stderr
@@ -0,0 +1,1385 @@
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:23:16
+   |
+LL |         x_u8 > x_u16;
+   |                ^^^^^ expected `u8`, found `u16`
+   |
+help: you can convert `x_u8` from `u8` to `u16`, matching the type of `x_u16`
+   |
+LL |         u16::from(x_u8) > x_u16;
+   |         ^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:25:16
+   |
+LL |         x_u8 > x_u32;
+   |                ^^^^^ expected `u8`, found `u32`
+   |
+help: you can convert `x_u8` from `u8` to `u32`, matching the type of `x_u32`
+   |
+LL |         u32::from(x_u8) > x_u32;
+   |         ^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:27:16
+   |
+LL |         x_u8 > x_u64;
+   |                ^^^^^ expected `u8`, found `u64`
+   |
+help: you can convert `x_u8` from `u8` to `u64`, matching the type of `x_u64`
+   |
+LL |         u64::from(x_u8) > x_u64;
+   |         ^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:29:16
+   |
+LL |         x_u8 > x_u128;
+   |                ^^^^^^ expected `u8`, found `u128`
+   |
+help: you can convert `x_u8` from `u8` to `u128`, matching the type of `x_u128`
+   |
+LL |         u128::from(x_u8) > x_u128;
+   |         ^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:31:16
+   |
+LL |         x_u8 > x_usize;
+   |                ^^^^^^^ expected `u8`, found `usize`
+   |
+help: you can convert `x_u8` from `u8` to `usize`, matching the type of `x_usize`
+   |
+LL |         usize::from(x_u8) > x_usize;
+   |         ^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:34:17
+   |
+LL |         x_u16 > x_u8;
+   |                 ^^^^
+   |                 |
+   |                 expected `u16`, found `u8`
+   |                 help: you can convert an `u8` to `u16`: `x_u8.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:36:17
+   |
+LL |         x_u16 > x_u32;
+   |                 ^^^^^ expected `u16`, found `u32`
+   |
+help: you can convert `x_u16` from `u16` to `u32`, matching the type of `x_u32`
+   |
+LL |         u32::from(x_u16) > x_u32;
+   |         ^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:38:17
+   |
+LL |         x_u16 > x_u64;
+   |                 ^^^^^ expected `u16`, found `u64`
+   |
+help: you can convert `x_u16` from `u16` to `u64`, matching the type of `x_u64`
+   |
+LL |         u64::from(x_u16) > x_u64;
+   |         ^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:40:17
+   |
+LL |         x_u16 > x_u128;
+   |                 ^^^^^^ expected `u16`, found `u128`
+   |
+help: you can convert `x_u16` from `u16` to `u128`, matching the type of `x_u128`
+   |
+LL |         u128::from(x_u16) > x_u128;
+   |         ^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:42:17
+   |
+LL |         x_u16 > x_usize;
+   |                 ^^^^^^^ expected `u16`, found `usize`
+   |
+help: you can convert `x_u16` from `u16` to `usize`, matching the type of `x_usize`
+   |
+LL |         usize::from(x_u16) > x_usize;
+   |         ^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:45:17
+   |
+LL |         x_u32 > x_u8;
+   |                 ^^^^
+   |                 |
+   |                 expected `u32`, found `u8`
+   |                 help: you can convert an `u8` to `u32`: `x_u8.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:47:17
+   |
+LL |         x_u32 > x_u16;
+   |                 ^^^^^
+   |                 |
+   |                 expected `u32`, found `u16`
+   |                 help: you can convert an `u16` to `u32`: `x_u16.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:49:17
+   |
+LL |         x_u32 > x_u64;
+   |                 ^^^^^ expected `u32`, found `u64`
+   |
+help: you can convert `x_u32` from `u32` to `u64`, matching the type of `x_u64`
+   |
+LL |         u64::from(x_u32) > x_u64;
+   |         ^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:51:17
+   |
+LL |         x_u32 > x_u128;
+   |                 ^^^^^^ expected `u32`, found `u128`
+   |
+help: you can convert `x_u32` from `u32` to `u128`, matching the type of `x_u128`
+   |
+LL |         u128::from(x_u32) > x_u128;
+   |         ^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:53:17
+   |
+LL |         x_u32 > x_usize;
+   |                 ^^^^^^^ expected `u32`, found `usize`
+   |
+help: you can convert an `usize` to `u32` and panic if the converted value wouldn't fit
+   |
+LL |         x_u32 > x_usize.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:56:17
+   |
+LL |         x_u64 > x_u8;
+   |                 ^^^^
+   |                 |
+   |                 expected `u64`, found `u8`
+   |                 help: you can convert an `u8` to `u64`: `x_u8.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:58:17
+   |
+LL |         x_u64 > x_u16;
+   |                 ^^^^^
+   |                 |
+   |                 expected `u64`, found `u16`
+   |                 help: you can convert an `u16` to `u64`: `x_u16.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:60:17
+   |
+LL |         x_u64 > x_u32;
+   |                 ^^^^^
+   |                 |
+   |                 expected `u64`, found `u32`
+   |                 help: you can convert an `u32` to `u64`: `x_u32.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:62:17
+   |
+LL |         x_u64 > x_u128;
+   |                 ^^^^^^ expected `u64`, found `u128`
+   |
+help: you can convert `x_u64` from `u64` to `u128`, matching the type of `x_u128`
+   |
+LL |         u128::from(x_u64) > x_u128;
+   |         ^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:64:17
+   |
+LL |         x_u64 > x_usize;
+   |                 ^^^^^^^ expected `u64`, found `usize`
+   |
+help: you can convert an `usize` to `u64` and panic if the converted value wouldn't fit
+   |
+LL |         x_u64 > x_usize.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:67:18
+   |
+LL |         x_u128 > x_u8;
+   |                  ^^^^
+   |                  |
+   |                  expected `u128`, found `u8`
+   |                  help: you can convert an `u8` to `u128`: `x_u8.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:69:18
+   |
+LL |         x_u128 > x_u16;
+   |                  ^^^^^
+   |                  |
+   |                  expected `u128`, found `u16`
+   |                  help: you can convert an `u16` to `u128`: `x_u16.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:71:18
+   |
+LL |         x_u128 > x_u32;
+   |                  ^^^^^
+   |                  |
+   |                  expected `u128`, found `u32`
+   |                  help: you can convert an `u32` to `u128`: `x_u32.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:73:18
+   |
+LL |         x_u128 > x_u64;
+   |                  ^^^^^
+   |                  |
+   |                  expected `u128`, found `u64`
+   |                  help: you can convert an `u64` to `u128`: `x_u64.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:75:18
+   |
+LL |         x_u128 > x_usize;
+   |                  ^^^^^^^ expected `u128`, found `usize`
+   |
+help: you can convert an `usize` to `u128` and panic if the converted value wouldn't fit
+   |
+LL |         x_u128 > x_usize.try_into().unwrap();
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:78:19
+   |
+LL |         x_usize > x_u8;
+   |                   ^^^^
+   |                   |
+   |                   expected `usize`, found `u8`
+   |                   help: you can convert an `u8` to `usize`: `x_u8.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:80:19
+   |
+LL |         x_usize > x_u16;
+   |                   ^^^^^
+   |                   |
+   |                   expected `usize`, found `u16`
+   |                   help: you can convert an `u16` to `usize`: `x_u16.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:82:19
+   |
+LL |         x_usize > x_u32;
+   |                   ^^^^^ expected `usize`, found `u32`
+   |
+help: you can convert an `u32` to `usize` and panic if the converted value wouldn't fit
+   |
+LL |         x_usize > x_u32.try_into().unwrap();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:84:19
+   |
+LL |         x_usize > x_u64;
+   |                   ^^^^^ expected `usize`, found `u64`
+   |
+help: you can convert an `u64` to `usize` and panic if the converted value wouldn't fit
+   |
+LL |         x_usize > x_u64.try_into().unwrap();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:86:19
+   |
+LL |         x_usize > x_u128;
+   |                   ^^^^^^ expected `usize`, found `u128`
+   |
+help: you can convert an `u128` to `usize` and panic if the converted value wouldn't fit
+   |
+LL |         x_usize > x_u128.try_into().unwrap();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:92:16
+   |
+LL |         x_i8 > x_i16;
+   |                ^^^^^ expected `i8`, found `i16`
+   |
+help: you can convert `x_i8` from `i8` to `i16`, matching the type of `x_i16`
+   |
+LL |         i16::from(x_i8) > x_i16;
+   |         ^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:94:16
+   |
+LL |         x_i8 > x_i32;
+   |                ^^^^^ expected `i8`, found `i32`
+   |
+help: you can convert `x_i8` from `i8` to `i32`, matching the type of `x_i32`
+   |
+LL |         i32::from(x_i8) > x_i32;
+   |         ^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:96:16
+   |
+LL |         x_i8 > x_i64;
+   |                ^^^^^ expected `i8`, found `i64`
+   |
+help: you can convert `x_i8` from `i8` to `i64`, matching the type of `x_i64`
+   |
+LL |         i64::from(x_i8) > x_i64;
+   |         ^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:98:16
+   |
+LL |         x_i8 > x_i128;
+   |                ^^^^^^ expected `i8`, found `i128`
+   |
+help: you can convert `x_i8` from `i8` to `i128`, matching the type of `x_i128`
+   |
+LL |         i128::from(x_i8) > x_i128;
+   |         ^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:100:16
+   |
+LL |         x_i8 > x_isize;
+   |                ^^^^^^^ expected `i8`, found `isize`
+   |
+help: you can convert `x_i8` from `i8` to `isize`, matching the type of `x_isize`
+   |
+LL |         isize::from(x_i8) > x_isize;
+   |         ^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:103:17
+   |
+LL |         x_i16 > x_i8;
+   |                 ^^^^
+   |                 |
+   |                 expected `i16`, found `i8`
+   |                 help: you can convert an `i8` to `i16`: `x_i8.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:105:17
+   |
+LL |         x_i16 > x_i32;
+   |                 ^^^^^ expected `i16`, found `i32`
+   |
+help: you can convert `x_i16` from `i16` to `i32`, matching the type of `x_i32`
+   |
+LL |         i32::from(x_i16) > x_i32;
+   |         ^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:107:17
+   |
+LL |         x_i16 > x_i64;
+   |                 ^^^^^ expected `i16`, found `i64`
+   |
+help: you can convert `x_i16` from `i16` to `i64`, matching the type of `x_i64`
+   |
+LL |         i64::from(x_i16) > x_i64;
+   |         ^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:109:17
+   |
+LL |         x_i16 > x_i128;
+   |                 ^^^^^^ expected `i16`, found `i128`
+   |
+help: you can convert `x_i16` from `i16` to `i128`, matching the type of `x_i128`
+   |
+LL |         i128::from(x_i16) > x_i128;
+   |         ^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:111:17
+   |
+LL |         x_i16 > x_isize;
+   |                 ^^^^^^^ expected `i16`, found `isize`
+   |
+help: you can convert `x_i16` from `i16` to `isize`, matching the type of `x_isize`
+   |
+LL |         isize::from(x_i16) > x_isize;
+   |         ^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:114:17
+   |
+LL |         x_i32 > x_i8;
+   |                 ^^^^
+   |                 |
+   |                 expected `i32`, found `i8`
+   |                 help: you can convert an `i8` to `i32`: `x_i8.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:116:17
+   |
+LL |         x_i32 > x_i16;
+   |                 ^^^^^
+   |                 |
+   |                 expected `i32`, found `i16`
+   |                 help: you can convert an `i16` to `i32`: `x_i16.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:118:17
+   |
+LL |         x_i32 > x_i64;
+   |                 ^^^^^ expected `i32`, found `i64`
+   |
+help: you can convert `x_i32` from `i32` to `i64`, matching the type of `x_i64`
+   |
+LL |         i64::from(x_i32) > x_i64;
+   |         ^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:120:17
+   |
+LL |         x_i32 > x_i128;
+   |                 ^^^^^^ expected `i32`, found `i128`
+   |
+help: you can convert `x_i32` from `i32` to `i128`, matching the type of `x_i128`
+   |
+LL |         i128::from(x_i32) > x_i128;
+   |         ^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:122:17
+   |
+LL |         x_i32 > x_isize;
+   |                 ^^^^^^^ expected `i32`, found `isize`
+   |
+help: you can convert an `isize` to `i32` and panic if the converted value wouldn't fit
+   |
+LL |         x_i32 > x_isize.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:125:17
+   |
+LL |         x_i64 > x_i8;
+   |                 ^^^^
+   |                 |
+   |                 expected `i64`, found `i8`
+   |                 help: you can convert an `i8` to `i64`: `x_i8.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:127:17
+   |
+LL |         x_i64 > x_i16;
+   |                 ^^^^^
+   |                 |
+   |                 expected `i64`, found `i16`
+   |                 help: you can convert an `i16` to `i64`: `x_i16.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:129:17
+   |
+LL |         x_i64 > x_i32;
+   |                 ^^^^^
+   |                 |
+   |                 expected `i64`, found `i32`
+   |                 help: you can convert an `i32` to `i64`: `x_i32.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:131:17
+   |
+LL |         x_i64 > x_i128;
+   |                 ^^^^^^ expected `i64`, found `i128`
+   |
+help: you can convert `x_i64` from `i64` to `i128`, matching the type of `x_i128`
+   |
+LL |         i128::from(x_i64) > x_i128;
+   |         ^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:133:17
+   |
+LL |         x_i64 > x_isize;
+   |                 ^^^^^^^ expected `i64`, found `isize`
+   |
+help: you can convert an `isize` to `i64` and panic if the converted value wouldn't fit
+   |
+LL |         x_i64 > x_isize.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:136:18
+   |
+LL |         x_i128 > x_i8;
+   |                  ^^^^
+   |                  |
+   |                  expected `i128`, found `i8`
+   |                  help: you can convert an `i8` to `i128`: `x_i8.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:138:18
+   |
+LL |         x_i128 > x_i16;
+   |                  ^^^^^
+   |                  |
+   |                  expected `i128`, found `i16`
+   |                  help: you can convert an `i16` to `i128`: `x_i16.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:140:18
+   |
+LL |         x_i128 > x_i32;
+   |                  ^^^^^
+   |                  |
+   |                  expected `i128`, found `i32`
+   |                  help: you can convert an `i32` to `i128`: `x_i32.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:142:18
+   |
+LL |         x_i128 > x_i64;
+   |                  ^^^^^
+   |                  |
+   |                  expected `i128`, found `i64`
+   |                  help: you can convert an `i64` to `i128`: `x_i64.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:144:18
+   |
+LL |         x_i128 > x_isize;
+   |                  ^^^^^^^ expected `i128`, found `isize`
+   |
+help: you can convert an `isize` to `i128` and panic if the converted value wouldn't fit
+   |
+LL |         x_i128 > x_isize.try_into().unwrap();
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:147:19
+   |
+LL |         x_isize > x_i8;
+   |                   ^^^^
+   |                   |
+   |                   expected `isize`, found `i8`
+   |                   help: you can convert an `i8` to `isize`: `x_i8.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:149:19
+   |
+LL |         x_isize > x_i16;
+   |                   ^^^^^
+   |                   |
+   |                   expected `isize`, found `i16`
+   |                   help: you can convert an `i16` to `isize`: `x_i16.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:151:19
+   |
+LL |         x_isize > x_i32;
+   |                   ^^^^^ expected `isize`, found `i32`
+   |
+help: you can convert an `i32` to `isize` and panic if the converted value wouldn't fit
+   |
+LL |         x_isize > x_i32.try_into().unwrap();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:153:19
+   |
+LL |         x_isize > x_i64;
+   |                   ^^^^^ expected `isize`, found `i64`
+   |
+help: you can convert an `i64` to `isize` and panic if the converted value wouldn't fit
+   |
+LL |         x_isize > x_i64.try_into().unwrap();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:155:19
+   |
+LL |         x_isize > x_i128;
+   |                   ^^^^^^ expected `isize`, found `i128`
+   |
+help: you can convert an `i128` to `isize` and panic if the converted value wouldn't fit
+   |
+LL |         x_isize > x_i128.try_into().unwrap();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:161:16
+   |
+LL |         x_u8 > x_i8;
+   |                ^^^^ expected `u8`, found `i8`
+   |
+help: you can convert an `i8` to `u8` and panic if the converted value wouldn't fit
+   |
+LL |         x_u8 > x_i8.try_into().unwrap();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:163:16
+   |
+LL |         x_u8 > x_i16;
+   |                ^^^^^ expected `u8`, found `i16`
+   |
+help: you can convert `x_u8` from `u8` to `i16`, matching the type of `x_i16`
+   |
+LL |         i16::from(x_u8) > x_i16;
+   |         ^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:165:16
+   |
+LL |         x_u8 > x_i32;
+   |                ^^^^^ expected `u8`, found `i32`
+   |
+help: you can convert `x_u8` from `u8` to `i32`, matching the type of `x_i32`
+   |
+LL |         i32::from(x_u8) > x_i32;
+   |         ^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:167:16
+   |
+LL |         x_u8 > x_i64;
+   |                ^^^^^ expected `u8`, found `i64`
+   |
+help: you can convert `x_u8` from `u8` to `i64`, matching the type of `x_i64`
+   |
+LL |         i64::from(x_u8) > x_i64;
+   |         ^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:169:16
+   |
+LL |         x_u8 > x_i128;
+   |                ^^^^^^ expected `u8`, found `i128`
+   |
+help: you can convert `x_u8` from `u8` to `i128`, matching the type of `x_i128`
+   |
+LL |         i128::from(x_u8) > x_i128;
+   |         ^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:171:16
+   |
+LL |         x_u8 > x_isize;
+   |                ^^^^^^^ expected `u8`, found `isize`
+   |
+help: you can convert `x_u8` from `u8` to `isize`, matching the type of `x_isize`
+   |
+LL |         isize::from(x_u8) > x_isize;
+   |         ^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:174:17
+   |
+LL |         x_u16 > x_i8;
+   |                 ^^^^ expected `u16`, found `i8`
+   |
+help: you can convert an `i8` to `u16` and panic if the converted value wouldn't fit
+   |
+LL |         x_u16 > x_i8.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:176:17
+   |
+LL |         x_u16 > x_i16;
+   |                 ^^^^^ expected `u16`, found `i16`
+   |
+help: you can convert an `i16` to `u16` and panic if the converted value wouldn't fit
+   |
+LL |         x_u16 > x_i16.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:178:17
+   |
+LL |         x_u16 > x_i32;
+   |                 ^^^^^ expected `u16`, found `i32`
+   |
+help: you can convert `x_u16` from `u16` to `i32`, matching the type of `x_i32`
+   |
+LL |         i32::from(x_u16) > x_i32;
+   |         ^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:180:17
+   |
+LL |         x_u16 > x_i64;
+   |                 ^^^^^ expected `u16`, found `i64`
+   |
+help: you can convert `x_u16` from `u16` to `i64`, matching the type of `x_i64`
+   |
+LL |         i64::from(x_u16) > x_i64;
+   |         ^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:182:17
+   |
+LL |         x_u16 > x_i128;
+   |                 ^^^^^^ expected `u16`, found `i128`
+   |
+help: you can convert `x_u16` from `u16` to `i128`, matching the type of `x_i128`
+   |
+LL |         i128::from(x_u16) > x_i128;
+   |         ^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:184:17
+   |
+LL |         x_u16 > x_isize;
+   |                 ^^^^^^^ expected `u16`, found `isize`
+   |
+help: you can convert an `isize` to `u16` and panic if the converted value wouldn't fit
+   |
+LL |         x_u16 > x_isize.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:187:17
+   |
+LL |         x_u32 > x_i8;
+   |                 ^^^^ expected `u32`, found `i8`
+   |
+help: you can convert an `i8` to `u32` and panic if the converted value wouldn't fit
+   |
+LL |         x_u32 > x_i8.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:189:17
+   |
+LL |         x_u32 > x_i16;
+   |                 ^^^^^ expected `u32`, found `i16`
+   |
+help: you can convert an `i16` to `u32` and panic if the converted value wouldn't fit
+   |
+LL |         x_u32 > x_i16.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:191:17
+   |
+LL |         x_u32 > x_i32;
+   |                 ^^^^^ expected `u32`, found `i32`
+   |
+help: you can convert an `i32` to `u32` and panic if the converted value wouldn't fit
+   |
+LL |         x_u32 > x_i32.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:193:17
+   |
+LL |         x_u32 > x_i64;
+   |                 ^^^^^ expected `u32`, found `i64`
+   |
+help: you can convert `x_u32` from `u32` to `i64`, matching the type of `x_i64`
+   |
+LL |         i64::from(x_u32) > x_i64;
+   |         ^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:195:17
+   |
+LL |         x_u32 > x_i128;
+   |                 ^^^^^^ expected `u32`, found `i128`
+   |
+help: you can convert `x_u32` from `u32` to `i128`, matching the type of `x_i128`
+   |
+LL |         i128::from(x_u32) > x_i128;
+   |         ^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:197:17
+   |
+LL |         x_u32 > x_isize;
+   |                 ^^^^^^^ expected `u32`, found `isize`
+   |
+help: you can convert an `isize` to `u32` and panic if the converted value wouldn't fit
+   |
+LL |         x_u32 > x_isize.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:200:17
+   |
+LL |         x_u64 > x_i8;
+   |                 ^^^^ expected `u64`, found `i8`
+   |
+help: you can convert an `i8` to `u64` and panic if the converted value wouldn't fit
+   |
+LL |         x_u64 > x_i8.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:202:17
+   |
+LL |         x_u64 > x_i16;
+   |                 ^^^^^ expected `u64`, found `i16`
+   |
+help: you can convert an `i16` to `u64` and panic if the converted value wouldn't fit
+   |
+LL |         x_u64 > x_i16.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:204:17
+   |
+LL |         x_u64 > x_i32;
+   |                 ^^^^^ expected `u64`, found `i32`
+   |
+help: you can convert an `i32` to `u64` and panic if the converted value wouldn't fit
+   |
+LL |         x_u64 > x_i32.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:206:17
+   |
+LL |         x_u64 > x_i64;
+   |                 ^^^^^ expected `u64`, found `i64`
+   |
+help: you can convert an `i64` to `u64` and panic if the converted value wouldn't fit
+   |
+LL |         x_u64 > x_i64.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:208:17
+   |
+LL |         x_u64 > x_i128;
+   |                 ^^^^^^ expected `u64`, found `i128`
+   |
+help: you can convert `x_u64` from `u64` to `i128`, matching the type of `x_i128`
+   |
+LL |         i128::from(x_u64) > x_i128;
+   |         ^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:210:17
+   |
+LL |         x_u64 > x_isize;
+   |                 ^^^^^^^ expected `u64`, found `isize`
+   |
+help: you can convert an `isize` to `u64` and panic if the converted value wouldn't fit
+   |
+LL |         x_u64 > x_isize.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:213:18
+   |
+LL |         x_u128 > x_i8;
+   |                  ^^^^ expected `u128`, found `i8`
+   |
+help: you can convert an `i8` to `u128` and panic if the converted value wouldn't fit
+   |
+LL |         x_u128 > x_i8.try_into().unwrap();
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:215:18
+   |
+LL |         x_u128 > x_i16;
+   |                  ^^^^^ expected `u128`, found `i16`
+   |
+help: you can convert an `i16` to `u128` and panic if the converted value wouldn't fit
+   |
+LL |         x_u128 > x_i16.try_into().unwrap();
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:217:18
+   |
+LL |         x_u128 > x_i32;
+   |                  ^^^^^ expected `u128`, found `i32`
+   |
+help: you can convert an `i32` to `u128` and panic if the converted value wouldn't fit
+   |
+LL |         x_u128 > x_i32.try_into().unwrap();
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:219:18
+   |
+LL |         x_u128 > x_i64;
+   |                  ^^^^^ expected `u128`, found `i64`
+   |
+help: you can convert an `i64` to `u128` and panic if the converted value wouldn't fit
+   |
+LL |         x_u128 > x_i64.try_into().unwrap();
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:221:18
+   |
+LL |         x_u128 > x_i128;
+   |                  ^^^^^^ expected `u128`, found `i128`
+   |
+help: you can convert an `i128` to `u128` and panic if the converted value wouldn't fit
+   |
+LL |         x_u128 > x_i128.try_into().unwrap();
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:223:18
+   |
+LL |         x_u128 > x_isize;
+   |                  ^^^^^^^ expected `u128`, found `isize`
+   |
+help: you can convert an `isize` to `u128` and panic if the converted value wouldn't fit
+   |
+LL |         x_u128 > x_isize.try_into().unwrap();
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:226:19
+   |
+LL |         x_usize > x_i8;
+   |                   ^^^^ expected `usize`, found `i8`
+   |
+help: you can convert an `i8` to `usize` and panic if the converted value wouldn't fit
+   |
+LL |         x_usize > x_i8.try_into().unwrap();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:228:19
+   |
+LL |         x_usize > x_i16;
+   |                   ^^^^^ expected `usize`, found `i16`
+   |
+help: you can convert an `i16` to `usize` and panic if the converted value wouldn't fit
+   |
+LL |         x_usize > x_i16.try_into().unwrap();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:230:19
+   |
+LL |         x_usize > x_i32;
+   |                   ^^^^^ expected `usize`, found `i32`
+   |
+help: you can convert an `i32` to `usize` and panic if the converted value wouldn't fit
+   |
+LL |         x_usize > x_i32.try_into().unwrap();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:232:19
+   |
+LL |         x_usize > x_i64;
+   |                   ^^^^^ expected `usize`, found `i64`
+   |
+help: you can convert an `i64` to `usize` and panic if the converted value wouldn't fit
+   |
+LL |         x_usize > x_i64.try_into().unwrap();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:234:19
+   |
+LL |         x_usize > x_i128;
+   |                   ^^^^^^ expected `usize`, found `i128`
+   |
+help: you can convert an `i128` to `usize` and panic if the converted value wouldn't fit
+   |
+LL |         x_usize > x_i128.try_into().unwrap();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:236:19
+   |
+LL |         x_usize > x_isize;
+   |                   ^^^^^^^ expected `usize`, found `isize`
+   |
+help: you can convert an `isize` to `usize` and panic if the converted value wouldn't fit
+   |
+LL |         x_usize > x_isize.try_into().unwrap();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:242:16
+   |
+LL |         x_i8 > x_u8;
+   |                ^^^^ expected `i8`, found `u8`
+   |
+help: you can convert an `u8` to `i8` and panic if the converted value wouldn't fit
+   |
+LL |         x_i8 > x_u8.try_into().unwrap();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:244:16
+   |
+LL |         x_i8 > x_u16;
+   |                ^^^^^ expected `i8`, found `u16`
+   |
+help: you can convert an `u16` to `i8` and panic if the converted value wouldn't fit
+   |
+LL |         x_i8 > x_u16.try_into().unwrap();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:246:16
+   |
+LL |         x_i8 > x_u32;
+   |                ^^^^^ expected `i8`, found `u32`
+   |
+help: you can convert an `u32` to `i8` and panic if the converted value wouldn't fit
+   |
+LL |         x_i8 > x_u32.try_into().unwrap();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:248:16
+   |
+LL |         x_i8 > x_u64;
+   |                ^^^^^ expected `i8`, found `u64`
+   |
+help: you can convert an `u64` to `i8` and panic if the converted value wouldn't fit
+   |
+LL |         x_i8 > x_u64.try_into().unwrap();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:250:16
+   |
+LL |         x_i8 > x_u128;
+   |                ^^^^^^ expected `i8`, found `u128`
+   |
+help: you can convert an `u128` to `i8` and panic if the converted value wouldn't fit
+   |
+LL |         x_i8 > x_u128.try_into().unwrap();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:252:16
+   |
+LL |         x_i8 > x_usize;
+   |                ^^^^^^^ expected `i8`, found `usize`
+   |
+help: you can convert an `usize` to `i8` and panic if the converted value wouldn't fit
+   |
+LL |         x_i8 > x_usize.try_into().unwrap();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:255:17
+   |
+LL |         x_i16 > x_u8;
+   |                 ^^^^
+   |                 |
+   |                 expected `i16`, found `u8`
+   |                 help: you can convert an `u8` to `i16`: `x_u8.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:257:17
+   |
+LL |         x_i16 > x_u16;
+   |                 ^^^^^ expected `i16`, found `u16`
+   |
+help: you can convert an `u16` to `i16` and panic if the converted value wouldn't fit
+   |
+LL |         x_i16 > x_u16.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:259:17
+   |
+LL |         x_i16 > x_u32;
+   |                 ^^^^^ expected `i16`, found `u32`
+   |
+help: you can convert an `u32` to `i16` and panic if the converted value wouldn't fit
+   |
+LL |         x_i16 > x_u32.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:261:17
+   |
+LL |         x_i16 > x_u64;
+   |                 ^^^^^ expected `i16`, found `u64`
+   |
+help: you can convert an `u64` to `i16` and panic if the converted value wouldn't fit
+   |
+LL |         x_i16 > x_u64.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:263:17
+   |
+LL |         x_i16 > x_u128;
+   |                 ^^^^^^ expected `i16`, found `u128`
+   |
+help: you can convert an `u128` to `i16` and panic if the converted value wouldn't fit
+   |
+LL |         x_i16 > x_u128.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:265:17
+   |
+LL |         x_i16 > x_usize;
+   |                 ^^^^^^^ expected `i16`, found `usize`
+   |
+help: you can convert an `usize` to `i16` and panic if the converted value wouldn't fit
+   |
+LL |         x_i16 > x_usize.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:268:17
+   |
+LL |         x_i32 > x_u8;
+   |                 ^^^^
+   |                 |
+   |                 expected `i32`, found `u8`
+   |                 help: you can convert an `u8` to `i32`: `x_u8.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:270:17
+   |
+LL |         x_i32 > x_u16;
+   |                 ^^^^^
+   |                 |
+   |                 expected `i32`, found `u16`
+   |                 help: you can convert an `u16` to `i32`: `x_u16.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:272:17
+   |
+LL |         x_i32 > x_u32;
+   |                 ^^^^^ expected `i32`, found `u32`
+   |
+help: you can convert an `u32` to `i32` and panic if the converted value wouldn't fit
+   |
+LL |         x_i32 > x_u32.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:274:17
+   |
+LL |         x_i32 > x_u64;
+   |                 ^^^^^ expected `i32`, found `u64`
+   |
+help: you can convert an `u64` to `i32` and panic if the converted value wouldn't fit
+   |
+LL |         x_i32 > x_u64.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:276:17
+   |
+LL |         x_i32 > x_u128;
+   |                 ^^^^^^ expected `i32`, found `u128`
+   |
+help: you can convert an `u128` to `i32` and panic if the converted value wouldn't fit
+   |
+LL |         x_i32 > x_u128.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:278:17
+   |
+LL |         x_i32 > x_usize;
+   |                 ^^^^^^^ expected `i32`, found `usize`
+   |
+help: you can convert an `usize` to `i32` and panic if the converted value wouldn't fit
+   |
+LL |         x_i32 > x_usize.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:281:17
+   |
+LL |         x_i64 > x_u8;
+   |                 ^^^^
+   |                 |
+   |                 expected `i64`, found `u8`
+   |                 help: you can convert an `u8` to `i64`: `x_u8.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:283:17
+   |
+LL |         x_i64 > x_u16;
+   |                 ^^^^^
+   |                 |
+   |                 expected `i64`, found `u16`
+   |                 help: you can convert an `u16` to `i64`: `x_u16.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:285:17
+   |
+LL |         x_i64 > x_u32;
+   |                 ^^^^^
+   |                 |
+   |                 expected `i64`, found `u32`
+   |                 help: you can convert an `u32` to `i64`: `x_u32.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:287:17
+   |
+LL |         x_i64 > x_u64;
+   |                 ^^^^^ expected `i64`, found `u64`
+   |
+help: you can convert an `u64` to `i64` and panic if the converted value wouldn't fit
+   |
+LL |         x_i64 > x_u64.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:289:17
+   |
+LL |         x_i64 > x_u128;
+   |                 ^^^^^^ expected `i64`, found `u128`
+   |
+help: you can convert an `u128` to `i64` and panic if the converted value wouldn't fit
+   |
+LL |         x_i64 > x_u128.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:291:17
+   |
+LL |         x_i64 > x_usize;
+   |                 ^^^^^^^ expected `i64`, found `usize`
+   |
+help: you can convert an `usize` to `i64` and panic if the converted value wouldn't fit
+   |
+LL |         x_i64 > x_usize.try_into().unwrap();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:294:18
+   |
+LL |         x_i128 > x_u8;
+   |                  ^^^^
+   |                  |
+   |                  expected `i128`, found `u8`
+   |                  help: you can convert an `u8` to `i128`: `x_u8.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:296:18
+   |
+LL |         x_i128 > x_u16;
+   |                  ^^^^^
+   |                  |
+   |                  expected `i128`, found `u16`
+   |                  help: you can convert an `u16` to `i128`: `x_u16.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:298:18
+   |
+LL |         x_i128 > x_u32;
+   |                  ^^^^^
+   |                  |
+   |                  expected `i128`, found `u32`
+   |                  help: you can convert an `u32` to `i128`: `x_u32.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:300:18
+   |
+LL |         x_i128 > x_u64;
+   |                  ^^^^^
+   |                  |
+   |                  expected `i128`, found `u64`
+   |                  help: you can convert an `u64` to `i128`: `x_u64.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:302:18
+   |
+LL |         x_i128 > x_u128;
+   |                  ^^^^^^ expected `i128`, found `u128`
+   |
+help: you can convert an `u128` to `i128` and panic if the converted value wouldn't fit
+   |
+LL |         x_i128 > x_u128.try_into().unwrap();
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:304:18
+   |
+LL |         x_i128 > x_usize;
+   |                  ^^^^^^^ expected `i128`, found `usize`
+   |
+help: you can convert an `usize` to `i128` and panic if the converted value wouldn't fit
+   |
+LL |         x_i128 > x_usize.try_into().unwrap();
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:307:19
+   |
+LL |         x_isize > x_u8;
+   |                   ^^^^
+   |                   |
+   |                   expected `isize`, found `u8`
+   |                   help: you can convert an `u8` to `isize`: `x_u8.into()`
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:309:19
+   |
+LL |         x_isize > x_u16;
+   |                   ^^^^^ expected `isize`, found `u16`
+   |
+help: you can convert an `u16` to `isize` and panic if the converted value wouldn't fit
+   |
+LL |         x_isize > x_u16.try_into().unwrap();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:311:19
+   |
+LL |         x_isize > x_u32;
+   |                   ^^^^^ expected `isize`, found `u32`
+   |
+help: you can convert an `u32` to `isize` and panic if the converted value wouldn't fit
+   |
+LL |         x_isize > x_u32.try_into().unwrap();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:313:19
+   |
+LL |         x_isize > x_u64;
+   |                   ^^^^^ expected `isize`, found `u64`
+   |
+help: you can convert an `u64` to `isize` and panic if the converted value wouldn't fit
+   |
+LL |         x_isize > x_u64.try_into().unwrap();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:315:19
+   |
+LL |         x_isize > x_u128;
+   |                   ^^^^^^ expected `isize`, found `u128`
+   |
+help: you can convert an `u128` to `isize` and panic if the converted value wouldn't fit
+   |
+LL |         x_isize > x_u128.try_into().unwrap();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/numeric-cast-binop.rs:317:19
+   |
+LL |         x_isize > x_usize;
+   |                   ^^^^^^^ expected `isize`, found `usize`
+   |
+help: you can convert an `usize` to `isize` and panic if the converted value wouldn't fit
+   |
+LL |         x_isize > x_usize.try_into().unwrap();
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 132 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/once-cant-call-twice-on-heap.stderr b/src/test/ui/once-cant-call-twice-on-heap.stderr
index 7133a32431a..8761b5261d5 100644
--- a/src/test/ui/once-cant-call-twice-on-heap.stderr
+++ b/src/test/ui/once-cant-call-twice-on-heap.stderr
@@ -4,10 +4,15 @@ error[E0382]: use of moved value: `blk`
 LL | fn foo<F:FnOnce()>(blk: F) {
    |                    --- move occurs because `blk` has type `F`, which does not implement the `Copy` trait
 LL |     blk();
-   |     --- value moved here
+   |     ----- `blk` moved due to this call
 LL |     blk();
    |     ^^^ value used here after move
    |
+note: this value implements `FnOnce`, which causes it to be moved when called
+  --> $DIR/once-cant-call-twice-on-heap.rs:8:5
+   |
+LL |     blk();
+   |     ^^^
 help: consider further restricting this bound
    |
 LL | fn foo<F:FnOnce() + Copy>(blk: F) {
diff --git a/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs b/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs
index c8bc4a2a8d5..31b3407a46e 100644
--- a/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs
+++ b/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs
@@ -4,15 +4,15 @@
 // We wrap patterns in a tuple because top-level or-patterns were special-cased.
 fn main() {
     match (0u8, 0u8) {
-        //~^ ERROR non-exhaustive patterns: `(2u8..=std::u8::MAX, _)`
+        //~^ ERROR non-exhaustive patterns: `(2u8..=u8::MAX, _)`
         (0 | 1, 2 | 3) => {}
     }
     match ((0u8,),) {
-        //~^ ERROR non-exhaustive patterns: `((4u8..=std::u8::MAX))`
+        //~^ ERROR non-exhaustive patterns: `((4u8..=u8::MAX))`
         ((0 | 1,) | (2 | 3,),) => {}
     }
     match (Some(0u8),) {
-        //~^ ERROR non-exhaustive patterns: `(Some(2u8..=std::u8::MAX))`
+        //~^ ERROR non-exhaustive patterns: `(Some(2u8..=u8::MAX))`
         (None | Some(0 | 1),) => {}
     }
 }
diff --git a/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.stderr b/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.stderr
index b45e947f3ea..653f4978ab3 100644
--- a/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.stderr
+++ b/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.stderr
@@ -1,26 +1,26 @@
-error[E0004]: non-exhaustive patterns: `(2u8..=std::u8::MAX, _)` not covered
+error[E0004]: non-exhaustive patterns: `(2u8..=u8::MAX, _)` not covered
   --> $DIR/exhaustiveness-non-exhaustive.rs:6:11
    |
 LL |     match (0u8, 0u8) {
-   |           ^^^^^^^^^^ pattern `(2u8..=std::u8::MAX, _)` not covered
+   |           ^^^^^^^^^^ pattern `(2u8..=u8::MAX, _)` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(u8, u8)`
 
-error[E0004]: non-exhaustive patterns: `((4u8..=std::u8::MAX))` not covered
+error[E0004]: non-exhaustive patterns: `((4u8..=u8::MAX))` not covered
   --> $DIR/exhaustiveness-non-exhaustive.rs:10:11
    |
 LL |     match ((0u8,),) {
-   |           ^^^^^^^^^ pattern `((4u8..=std::u8::MAX))` not covered
+   |           ^^^^^^^^^ pattern `((4u8..=u8::MAX))` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `((u8,),)`
 
-error[E0004]: non-exhaustive patterns: `(Some(2u8..=std::u8::MAX))` not covered
+error[E0004]: non-exhaustive patterns: `(Some(2u8..=u8::MAX))` not covered
   --> $DIR/exhaustiveness-non-exhaustive.rs:14:11
    |
 LL |     match (Some(0u8),) {
-   |           ^^^^^^^^^^^^ pattern `(Some(2u8..=std::u8::MAX))` not covered
+   |           ^^^^^^^^^^^^ pattern `(Some(2u8..=u8::MAX))` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(std::option::Option<u8>,)`
diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr
index 351700a6aa5..2eadef9cb5c 100644
--- a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr
+++ b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr
@@ -1,8 +1,8 @@
-error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `3i32..=std::i32::MAX` not covered
+error[E0005]: refutable pattern in local binding: `i32::MIN..=-1i32` and `3i32..=i32::MAX` not covered
   --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:4:9
    |
 LL |     let 0 | (1 | 2) = 0;
-   |         ^^^^^^^^^^^ patterns `std::i32::MIN..=-1i32` and `3i32..=std::i32::MAX` not covered
+   |         ^^^^^^^^^^^ patterns `i32::MIN..=-1i32` and `3i32..=i32::MAX` not covered
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
@@ -12,11 +12,11 @@ help: you might want to use `if let` to ignore the variant that isn't matched
 LL |     if let 0 | (1 | 2) = 0 { /* */ }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0004]: non-exhaustive patterns: `std::i32::MIN..=-1i32` and `3i32..=std::i32::MAX` not covered
+error[E0004]: non-exhaustive patterns: `i32::MIN..=-1i32` and `3i32..=i32::MAX` not covered
   --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:5:11
    |
 LL |     match 0 {
-   |           ^ patterns `std::i32::MIN..=-1i32` and `3i32..=std::i32::MAX` not covered
+   |           ^ patterns `i32::MIN..=-1i32` and `3i32..=i32::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i32`
diff --git a/src/test/ui/parser/issue-8537.stderr b/src/test/ui/parser/issue-8537.stderr
index 9ff28ce51e0..e33adb239d7 100644
--- a/src/test/ui/parser/issue-8537.stderr
+++ b/src/test/ui/parser/issue-8537.stderr
@@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `invalid-ab_isize`
 LL |   "invalid-ab_isize"
    |   ^^^^^^^^^^^^^^^^^^ invalid ABI
    |
-   = help: valid ABIs: Rust, C, cdecl, stdcall, fastcall, vectorcall, thiscall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
+   = help: valid ABIs: Rust, C, cdecl, stdcall, fastcall, vectorcall, thiscall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/lex-bad-char-literals-4.stderr b/src/test/ui/parser/lex-bad-char-literals-4.stderr
index 8f8f806f6cf..fec4421c48a 100644
--- a/src/test/ui/parser/lex-bad-char-literals-4.stderr
+++ b/src/test/ui/parser/lex-bad-char-literals-4.stderr
@@ -1,4 +1,4 @@
-error: unterminated character literal
+error[E0762]: unterminated character literal
   --> $DIR/lex-bad-char-literals-4.rs:4:5
    |
 LL |     '●
@@ -6,3 +6,4 @@ LL |     '●
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0762`.
diff --git a/src/test/ui/parser/lex-bad-char-literals-7.stderr b/src/test/ui/parser/lex-bad-char-literals-7.stderr
index ee9aa869352..70ee8087b51 100644
--- a/src/test/ui/parser/lex-bad-char-literals-7.stderr
+++ b/src/test/ui/parser/lex-bad-char-literals-7.stderr
@@ -10,7 +10,7 @@ error: empty unicode escape (must have at least 1 hex digit)
 LL |     let _: char = '\u{}';
    |                    ^^^^
 
-error: unterminated character literal
+error[E0762]: unterminated character literal
   --> $DIR/lex-bad-char-literals-7.rs:11:13
    |
 LL |     let _ = ' hello // here's a comment
@@ -18,3 +18,4 @@ LL |     let _ = ' hello // here's a comment
 
 error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0762`.
diff --git a/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.stderr b/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.stderr
index edc5ece558a..6427a30b8f2 100644
--- a/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.stderr
+++ b/src/test/ui/pattern/usefulness/exhaustive_integer_patterns.stderr
@@ -10,11 +10,11 @@ note: the lint level is defined here
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error[E0004]: non-exhaustive patterns: `128u8..=std::u8::MAX` not covered
+error[E0004]: non-exhaustive patterns: `128u8..=u8::MAX` not covered
   --> $DIR/exhaustive_integer_patterns.rs:28:11
    |
 LL |     match x {
-   |           ^ pattern `128u8..=std::u8::MAX` not covered
+   |           ^ pattern `128u8..=u8::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
@@ -34,20 +34,20 @@ error: unreachable pattern
 LL |         -2..=20 => {}
    |         ^^^^^^^
 
-error[E0004]: non-exhaustive patterns: `std::i8::MIN..=-8i8`, `-6i8`, `121i8..=124i8` and 1 more not covered
+error[E0004]: non-exhaustive patterns: `i8::MIN..=-8i8`, `-6i8`, `121i8..=124i8` and 1 more not covered
   --> $DIR/exhaustive_integer_patterns.rs:41:11
    |
 LL |     match x {
-   |           ^ patterns `std::i8::MIN..=-8i8`, `-6i8`, `121i8..=124i8` and 1 more not covered
+   |           ^ patterns `i8::MIN..=-8i8`, `-6i8`, `121i8..=124i8` and 1 more not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i8`
 
-error[E0004]: non-exhaustive patterns: `std::i8::MIN` not covered
+error[E0004]: non-exhaustive patterns: `i8::MIN` not covered
   --> $DIR/exhaustive_integer_patterns.rs:83:11
    |
 LL |     match 0i8 {
-   |           ^^^ pattern `std::i8::MIN` not covered
+   |           ^^^ pattern `i8::MIN` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i8`
@@ -61,20 +61,20 @@ LL |     match 0i16 {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i16`
 
-error[E0004]: non-exhaustive patterns: `128u8..=std::u8::MAX` not covered
+error[E0004]: non-exhaustive patterns: `128u8..=u8::MAX` not covered
   --> $DIR/exhaustive_integer_patterns.rs:109:11
    |
 LL |     match 0u8 {
-   |           ^^^ pattern `128u8..=std::u8::MAX` not covered
+   |           ^^^ pattern `128u8..=u8::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u8`
 
-error[E0004]: non-exhaustive patterns: `(0u8, Some(_))` and `(2u8..=std::u8::MAX, Some(_))` not covered
+error[E0004]: non-exhaustive patterns: `(0u8, Some(_))` and `(2u8..=u8::MAX, Some(_))` not covered
   --> $DIR/exhaustive_integer_patterns.rs:121:11
    |
 LL |     match (0u8, Some(())) {
-   |           ^^^^^^^^^^^^^^^ patterns `(0u8, Some(_))` and `(2u8..=std::u8::MAX, Some(_))` not covered
+   |           ^^^^^^^^^^^^^^^ patterns `(0u8, Some(_))` and `(2u8..=u8::MAX, Some(_))` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(u8, std::option::Option<()>)`
@@ -102,20 +102,20 @@ note: the lint level is defined here
 LL | #![deny(overlapping_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error[E0004]: non-exhaustive patterns: `std::u128::MAX` not covered
+error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
   --> $DIR/exhaustive_integer_patterns.rs:146:11
    |
 LL |     match 0u128 {
-   |           ^^^^^ pattern `std::u128::MAX` not covered
+   |           ^^^^^ pattern `u128::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u128`
 
-error[E0004]: non-exhaustive patterns: `5u128..=std::u128::MAX` not covered
+error[E0004]: non-exhaustive patterns: `5u128..=u128::MAX` not covered
   --> $DIR/exhaustive_integer_patterns.rs:150:11
    |
 LL |     match 0u128 {
-   |           ^^^^^ pattern `5u128..=std::u128::MAX` not covered
+   |           ^^^^^ pattern `5u128..=u128::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `u128`
diff --git a/src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr b/src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr
index 323449eebc5..0e12b89de1b 100644
--- a/src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr
+++ b/src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr
@@ -1,8 +1,8 @@
-error[E0004]: non-exhaustive patterns: `&[0u8..=64u8, _, _, _]` and `&[66u8..=std::u8::MAX, _, _, _]` not covered
+error[E0004]: non-exhaustive patterns: `&[0u8..=64u8, _, _, _]` and `&[66u8..=u8::MAX, _, _, _]` not covered
   --> $DIR/match-byte-array-patterns-2.rs:4:11
    |
 LL |     match buf {
-   |           ^^^ patterns `&[0u8..=64u8, _, _, _]` and `&[66u8..=std::u8::MAX, _, _, _]` not covered
+   |           ^^^ patterns `&[0u8..=64u8, _, _, _]` and `&[66u8..=u8::MAX, _, _, _]` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[u8; 4]`
diff --git a/src/test/ui/pattern/usefulness/match-non-exhaustive.stderr b/src/test/ui/pattern/usefulness/match-non-exhaustive.stderr
index 84cfe1da315..c6a9329f9e8 100644
--- a/src/test/ui/pattern/usefulness/match-non-exhaustive.stderr
+++ b/src/test/ui/pattern/usefulness/match-non-exhaustive.stderr
@@ -1,8 +1,8 @@
-error[E0004]: non-exhaustive patterns: `std::i32::MIN..=0i32` and `2i32..=std::i32::MAX` not covered
+error[E0004]: non-exhaustive patterns: `i32::MIN..=0i32` and `2i32..=i32::MAX` not covered
   --> $DIR/match-non-exhaustive.rs:2:11
    |
 LL |     match 0 { 1 => () }
-   |           ^ patterns `std::i32::MIN..=0i32` and `2i32..=std::i32::MAX` not covered
+   |           ^ patterns `i32::MIN..=0i32` and `2i32..=i32::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `i32`
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match.rs b/src/test/ui/pattern/usefulness/non-exhaustive-match.rs
index 9947989dc12..9177345bc6f 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-match.rs
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-match.rs
@@ -11,8 +11,8 @@ fn main() {
     match Some(10) { //~ ERROR non-exhaustive patterns: `Some(_)` not covered
       None => {}
     }
-    match (2, 3, 4) { //~ ERROR non-exhaustive patterns: `(_, _, std::i32::MIN..=3i32)`
-                      //  and `(_, _, 5i32..=std::i32::MAX)` not covered
+    match (2, 3, 4) { //~ ERROR non-exhaustive patterns: `(_, _, i32::MIN..=3i32)`
+                      //  and `(_, _, 5i32..=i32::MAX)` not covered
       (_, _, 4) => {}
     }
     match (T::A, T::A) { //~ ERROR non-exhaustive patterns: `(A, A)` not covered
diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
index 436a293b6ce..3cdbd8a3433 100644
--- a/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
+++ b/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr
@@ -36,11 +36,11 @@ LL |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `std::option::Option<i32>`
 
-error[E0004]: non-exhaustive patterns: `(_, _, std::i32::MIN..=3i32)` and `(_, _, 5i32..=std::i32::MAX)` not covered
+error[E0004]: non-exhaustive patterns: `(_, _, i32::MIN..=3i32)` and `(_, _, 5i32..=i32::MAX)` not covered
   --> $DIR/non-exhaustive-match.rs:14:11
    |
 LL |     match (2, 3, 4) {
-   |           ^^^^^^^^^ patterns `(_, _, std::i32::MIN..=3i32)` and `(_, _, 5i32..=std::i32::MAX)` not covered
+   |           ^^^^^^^^^ patterns `(_, _, i32::MIN..=3i32)` and `(_, _, 5i32..=i32::MAX)` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `(i32, i32, i32)`
diff --git a/src/test/ui/pattern/usefulness/refutable-pattern-errors.rs b/src/test/ui/pattern/usefulness/refutable-pattern-errors.rs
index d4afe17ca74..3ef2ead32cb 100644
--- a/src/test/ui/pattern/usefulness/refutable-pattern-errors.rs
+++ b/src/test/ui/pattern/usefulness/refutable-pattern-errors.rs
@@ -5,5 +5,5 @@ fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
 
 fn main() {
     let (1, (Some(1), 2..=3)) = (1, (None, 2));
-    //~^ ERROR refutable pattern in local binding: `(std::i32::MIN..=0i32, _)` and `(2i32..=std::i32::MAX, _)` not covered
+    //~^ ERROR refutable pattern in local binding: `(i32::MIN..=0i32, _)` and `(2i32..=i32::MAX, _)` not covered
 }
diff --git a/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr b/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr
index f5895c01599..ac729ae9f7c 100644
--- a/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr
+++ b/src/test/ui/pattern/usefulness/refutable-pattern-errors.stderr
@@ -6,11 +6,11 @@ LL | fn func((1, (Some(1), 2..=3)): (isize, (Option<isize>, isize))) { }
    |
    = note: the matched value is of type `(isize, (std::option::Option<isize>, isize))`
 
-error[E0005]: refutable pattern in local binding: `(std::i32::MIN..=0i32, _)` and `(2i32..=std::i32::MAX, _)` not covered
+error[E0005]: refutable pattern in local binding: `(i32::MIN..=0i32, _)` and `(2i32..=i32::MAX, _)` not covered
   --> $DIR/refutable-pattern-errors.rs:7:9
    |
 LL |     let (1, (Some(1), 2..=3)) = (1, (None, 2));
-   |         ^^^^^^^^^^^^^^^^^^^^^ patterns `(std::i32::MIN..=0i32, _)` and `(2i32..=std::i32::MAX, _)` not covered
+   |         ^^^^^^^^^^^^^^^^^^^^^ patterns `(i32::MIN..=0i32, _)` and `(2i32..=i32::MAX, _)` not covered
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
diff --git a/src/test/ui/precise_pointer_size_matching.stderr b/src/test/ui/precise_pointer_size_matching.stderr
index 91ea323f07b..7b9e30f40fb 100644
--- a/src/test/ui/precise_pointer_size_matching.stderr
+++ b/src/test/ui/precise_pointer_size_matching.stderr
@@ -1,17 +1,17 @@
-error[E0004]: non-exhaustive patterns: `std::isize::MIN..=-6isize` and `21isize..=std::isize::MAX` not covered
+error[E0004]: non-exhaustive patterns: `isize::MIN..=-6isize` and `21isize..=isize::MAX` not covered
   --> $DIR/precise_pointer_size_matching.rs:24:11
    |
 LL |     match 0isize {
-   |           ^^^^^^ patterns `std::isize::MIN..=-6isize` and `21isize..=std::isize::MAX` not covered
+   |           ^^^^^^ patterns `isize::MIN..=-6isize` and `21isize..=isize::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `isize`
 
-error[E0004]: non-exhaustive patterns: `0usize` and `21usize..=std::usize::MAX` not covered
+error[E0004]: non-exhaustive patterns: `0usize` and `21usize..=usize::MAX` not covered
   --> $DIR/precise_pointer_size_matching.rs:29:11
    |
 LL |     match 0usize {
-   |           ^^^^^^ patterns `0usize` and `21usize..=std::usize::MAX` not covered
+   |           ^^^^^^ patterns `0usize` and `21usize..=usize::MAX` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `usize`
diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.rs b/src/test/ui/privacy/private-in-public-assoc-ty.rs
index 62faae1f399..cd7c37cb04b 100644
--- a/src/test/ui/privacy/private-in-public-assoc-ty.rs
+++ b/src/test/ui/privacy/private-in-public-assoc-ty.rs
@@ -9,7 +9,9 @@ mod m {
     trait PrivTr {}
     impl PrivTr for Priv {}
     pub trait PubTrAux1<T> {}
-    pub trait PubTrAux2 { type A; }
+    pub trait PubTrAux2 {
+        type A;
+    }
     impl<T> PubTrAux1<T> for u8 {}
     impl PubTrAux2 for u8 {
         type A = Priv;
@@ -41,8 +43,9 @@ mod m {
 
         type Exist = impl PrivTr;
         //~^ ERROR private trait `m::PrivTr` in public interface
-        //~| ERROR private trait `m::PrivTr` in public interface
-        fn infer_exist() -> Self::Exist { Priv }
+        fn infer_exist() -> Self::Exist {
+            Priv
+        }
     }
 }
 
diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.stderr b/src/test/ui/privacy/private-in-public-assoc-ty.stderr
index dd2ea7481f3..1a3ca3f16ed 100644
--- a/src/test/ui/privacy/private-in-public-assoc-ty.stderr
+++ b/src/test/ui/privacy/private-in-public-assoc-ty.stderr
@@ -1,5 +1,5 @@
 error[E0446]: private type `m::Priv` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:15:9
+  --> $DIR/private-in-public-assoc-ty.rs:17:9
    |
 LL |     struct Priv;
    |     - `m::Priv` declared as private
@@ -8,7 +8,7 @@ LL |         type A = Priv;
    |         ^^^^^^^^^^^^^^ can't leak private type
 
 warning: private trait `m::PrivTr` in public interface (error E0445)
-  --> $DIR/private-in-public-assoc-ty.rs:21:5
+  --> $DIR/private-in-public-assoc-ty.rs:23:5
    |
 LL | /     pub trait PubTr {
 LL | |
@@ -24,7 +24,7 @@ LL | |     }
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 warning: private type `m::Priv` in public interface (error E0446)
-  --> $DIR/private-in-public-assoc-ty.rs:21:5
+  --> $DIR/private-in-public-assoc-ty.rs:23:5
    |
 LL | /     pub trait PubTr {
 LL | |
@@ -39,7 +39,7 @@ LL | |     }
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 warning: private type `m::Priv` in public interface (error E0446)
-  --> $DIR/private-in-public-assoc-ty.rs:21:5
+  --> $DIR/private-in-public-assoc-ty.rs:23:5
    |
 LL | /     pub trait PubTr {
 LL | |
@@ -54,7 +54,7 @@ LL | |     }
    = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
 
 error[E0446]: private type `m::Priv` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:32:9
+  --> $DIR/private-in-public-assoc-ty.rs:34:9
    |
 LL |     struct Priv;
    |     - `m::Priv` declared as private
@@ -63,7 +63,7 @@ LL |         type Alias4 = Priv;
    |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `m::Priv` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:39:9
+  --> $DIR/private-in-public-assoc-ty.rs:41:9
    |
 LL |     struct Priv;
    |     - `m::Priv` declared as private
@@ -72,7 +72,7 @@ LL |         type Alias1 = Priv;
    |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0445]: private trait `m::PrivTr` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:42:9
+  --> $DIR/private-in-public-assoc-ty.rs:44:9
    |
 LL |     trait PrivTr {}
    |     - `m::PrivTr` declared as private
@@ -80,16 +80,7 @@ LL |     trait PrivTr {}
 LL |         type Exist = impl PrivTr;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
 
-error[E0445]: private trait `m::PrivTr` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:42:9
-   |
-LL |     trait PrivTr {}
-   |     - `m::PrivTr` declared as private
-...
-LL |         type Exist = impl PrivTr;
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
-
-error: aborting due to 5 previous errors; 3 warnings emitted
+error: aborting due to 4 previous errors; 3 warnings emitted
 
 Some errors have detailed explanations: E0445, E0446.
 For more information about an error, try `rustc --explain E0445`.
diff --git a/src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr b/src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr
index 163a2c9f44c..2c05bdbc492 100644
--- a/src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr
+++ b/src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr
@@ -1,166 +1,166 @@
-TokenStream [Ident { ident: "ident", span: $DIR/dump-debug-span-debug.rs:9:5: 9:10 }, Ident { ident: "r#ident", span: $DIR/dump-debug-span-debug.rs:10:5: 10:12 }, Punct { ch: ',', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:11:5: 11:6 }, Punct { ch: '=', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 }, Punct { ch: '=', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 }, Punct { ch: '>', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:12:7: 12:8 }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/dump-debug-span-debug.rs:13:5: 13:7 }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: $DIR/dump-debug-span-debug.rs:14:6: 14:7 }], span: $DIR/dump-debug-span-debug.rs:14:5: 14:8 }, Literal { kind: Integer, symbol: "0", suffix: None, span: $DIR/dump-debug-span-debug.rs:17:5: 17:6 }, Literal { kind: Float, symbol: "1.0", suffix: None, span: $DIR/dump-debug-span-debug.rs:18:5: 18:8 }, Literal { kind: Str, symbol: "S", suffix: None, span: $DIR/dump-debug-span-debug.rs:19:5: 19:8 }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: $DIR/dump-debug-span-debug.rs:20:5: 20:9 }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: $DIR/dump-debug-span-debug.rs:21:5: 21:9 }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: $DIR/dump-debug-span-debug.rs:22:5: 22:13 }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: $DIR/dump-debug-span-debug.rs:23:5: 23:11 }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: $DIR/dump-debug-span-debug.rs:24:5: 24:15 }, Literal { kind: Char, symbol: "C", suffix: None, span: $DIR/dump-debug-span-debug.rs:25:5: 25:8 }, Literal { kind: Byte, symbol: "B", suffix: None, span: $DIR/dump-debug-span-debug.rs:26:5: 26:9 }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:29:5: 29:7 }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:30:5: 30:9 }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:31:5: 31:9 }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:32:5: 32:10 }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:33:5: 33:10 }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:34:5: 34:14 }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:35:5: 35:12 }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:36:5: 36:16 }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:37:5: 37:9 }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:38:5: 38:10 }]
+TokenStream [Ident { ident: "ident", span: $DIR/dump-debug-span-debug.rs:9:5: 9:10 (#0) }, Ident { ident: "r#ident", span: $DIR/dump-debug-span-debug.rs:10:5: 10:12 (#0) }, Punct { ch: ',', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:11:5: 11:6 (#0) }, Punct { ch: '=', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 (#0) }, Punct { ch: '=', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 (#0) }, Punct { ch: '>', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:12:7: 12:8 (#0) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/dump-debug-span-debug.rs:13:5: 13:7 (#0) }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: $DIR/dump-debug-span-debug.rs:14:6: 14:7 (#0) }], span: $DIR/dump-debug-span-debug.rs:14:5: 14:8 (#0) }, Literal { kind: Integer, symbol: "0", suffix: None, span: $DIR/dump-debug-span-debug.rs:17:5: 17:6 (#0) }, Literal { kind: Float, symbol: "1.0", suffix: None, span: $DIR/dump-debug-span-debug.rs:18:5: 18:8 (#0) }, Literal { kind: Str, symbol: "S", suffix: None, span: $DIR/dump-debug-span-debug.rs:19:5: 19:8 (#0) }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: $DIR/dump-debug-span-debug.rs:20:5: 20:9 (#0) }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: $DIR/dump-debug-span-debug.rs:21:5: 21:9 (#0) }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: $DIR/dump-debug-span-debug.rs:22:5: 22:13 (#0) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: $DIR/dump-debug-span-debug.rs:23:5: 23:11 (#0) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: $DIR/dump-debug-span-debug.rs:24:5: 24:15 (#0) }, Literal { kind: Char, symbol: "C", suffix: None, span: $DIR/dump-debug-span-debug.rs:25:5: 25:8 (#0) }, Literal { kind: Byte, symbol: "B", suffix: None, span: $DIR/dump-debug-span-debug.rs:26:5: 26:9 (#0) }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:29:5: 29:7 (#0) }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:30:5: 30:9 (#0) }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:31:5: 31:9 (#0) }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:32:5: 32:10 (#0) }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:33:5: 33:10 (#0) }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:34:5: 34:14 (#0) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:35:5: 35:12 (#0) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:36:5: 36:16 (#0) }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:37:5: 37:9 (#0) }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:38:5: 38:10 (#0) }]
 TokenStream [
     Ident {
         ident: "ident",
-        span: $DIR/dump-debug-span-debug.rs:9:5: 9:10,
+        span: $DIR/dump-debug-span-debug.rs:9:5: 9:10 (#0),
     },
     Ident {
         ident: "r#ident",
-        span: $DIR/dump-debug-span-debug.rs:10:5: 10:12,
+        span: $DIR/dump-debug-span-debug.rs:10:5: 10:12 (#0),
     },
     Punct {
         ch: ',',
         spacing: Alone,
-        span: $DIR/dump-debug-span-debug.rs:11:5: 11:6,
+        span: $DIR/dump-debug-span-debug.rs:11:5: 11:6 (#0),
     },
     Punct {
         ch: '=',
         spacing: Joint,
-        span: $DIR/dump-debug-span-debug.rs:12:5: 12:7,
+        span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 (#0),
     },
     Punct {
         ch: '=',
         spacing: Joint,
-        span: $DIR/dump-debug-span-debug.rs:12:5: 12:7,
+        span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 (#0),
     },
     Punct {
         ch: '>',
         spacing: Alone,
-        span: $DIR/dump-debug-span-debug.rs:12:7: 12:8,
+        span: $DIR/dump-debug-span-debug.rs:12:7: 12:8 (#0),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [],
-        span: $DIR/dump-debug-span-debug.rs:13:5: 13:7,
+        span: $DIR/dump-debug-span-debug.rs:13:5: 13:7 (#0),
     },
     Group {
         delimiter: Bracket,
         stream: TokenStream [
             Ident {
                 ident: "_",
-                span: $DIR/dump-debug-span-debug.rs:14:6: 14:7,
+                span: $DIR/dump-debug-span-debug.rs:14:6: 14:7 (#0),
             },
         ],
-        span: $DIR/dump-debug-span-debug.rs:14:5: 14:8,
+        span: $DIR/dump-debug-span-debug.rs:14:5: 14:8 (#0),
     },
     Literal {
         kind: Integer,
         symbol: "0",
         suffix: None,
-        span: $DIR/dump-debug-span-debug.rs:17:5: 17:6,
+        span: $DIR/dump-debug-span-debug.rs:17:5: 17:6 (#0),
     },
     Literal {
         kind: Float,
         symbol: "1.0",
         suffix: None,
-        span: $DIR/dump-debug-span-debug.rs:18:5: 18:8,
+        span: $DIR/dump-debug-span-debug.rs:18:5: 18:8 (#0),
     },
     Literal {
         kind: Str,
         symbol: "S",
         suffix: None,
-        span: $DIR/dump-debug-span-debug.rs:19:5: 19:8,
+        span: $DIR/dump-debug-span-debug.rs:19:5: 19:8 (#0),
     },
     Literal {
         kind: ByteStr,
         symbol: "B",
         suffix: None,
-        span: $DIR/dump-debug-span-debug.rs:20:5: 20:9,
+        span: $DIR/dump-debug-span-debug.rs:20:5: 20:9 (#0),
     },
     Literal {
         kind: StrRaw(0),
         symbol: "R",
         suffix: None,
-        span: $DIR/dump-debug-span-debug.rs:21:5: 21:9,
+        span: $DIR/dump-debug-span-debug.rs:21:5: 21:9 (#0),
     },
     Literal {
         kind: StrRaw(2),
         symbol: "R",
         suffix: None,
-        span: $DIR/dump-debug-span-debug.rs:22:5: 22:13,
+        span: $DIR/dump-debug-span-debug.rs:22:5: 22:13 (#0),
     },
     Literal {
         kind: ByteStrRaw(0),
         symbol: "BR",
         suffix: None,
-        span: $DIR/dump-debug-span-debug.rs:23:5: 23:11,
+        span: $DIR/dump-debug-span-debug.rs:23:5: 23:11 (#0),
     },
     Literal {
         kind: ByteStrRaw(2),
         symbol: "BR",
         suffix: None,
-        span: $DIR/dump-debug-span-debug.rs:24:5: 24:15,
+        span: $DIR/dump-debug-span-debug.rs:24:5: 24:15 (#0),
     },
     Literal {
         kind: Char,
         symbol: "C",
         suffix: None,
-        span: $DIR/dump-debug-span-debug.rs:25:5: 25:8,
+        span: $DIR/dump-debug-span-debug.rs:25:5: 25:8 (#0),
     },
     Literal {
         kind: Byte,
         symbol: "B",
         suffix: None,
-        span: $DIR/dump-debug-span-debug.rs:26:5: 26:9,
+        span: $DIR/dump-debug-span-debug.rs:26:5: 26:9 (#0),
     },
     Literal {
         kind: Integer,
         symbol: "0",
         suffix: Some("q"),
-        span: $DIR/dump-debug-span-debug.rs:29:5: 29:7,
+        span: $DIR/dump-debug-span-debug.rs:29:5: 29:7 (#0),
     },
     Literal {
         kind: Float,
         symbol: "1.0",
         suffix: Some("q"),
-        span: $DIR/dump-debug-span-debug.rs:30:5: 30:9,
+        span: $DIR/dump-debug-span-debug.rs:30:5: 30:9 (#0),
     },
     Literal {
         kind: Str,
         symbol: "S",
         suffix: Some("q"),
-        span: $DIR/dump-debug-span-debug.rs:31:5: 31:9,
+        span: $DIR/dump-debug-span-debug.rs:31:5: 31:9 (#0),
     },
     Literal {
         kind: ByteStr,
         symbol: "B",
         suffix: Some("q"),
-        span: $DIR/dump-debug-span-debug.rs:32:5: 32:10,
+        span: $DIR/dump-debug-span-debug.rs:32:5: 32:10 (#0),
     },
     Literal {
         kind: StrRaw(0),
         symbol: "R",
         suffix: Some("q"),
-        span: $DIR/dump-debug-span-debug.rs:33:5: 33:10,
+        span: $DIR/dump-debug-span-debug.rs:33:5: 33:10 (#0),
     },
     Literal {
         kind: StrRaw(2),
         symbol: "R",
         suffix: Some("q"),
-        span: $DIR/dump-debug-span-debug.rs:34:5: 34:14,
+        span: $DIR/dump-debug-span-debug.rs:34:5: 34:14 (#0),
     },
     Literal {
         kind: ByteStrRaw(0),
         symbol: "BR",
         suffix: Some("q"),
-        span: $DIR/dump-debug-span-debug.rs:35:5: 35:12,
+        span: $DIR/dump-debug-span-debug.rs:35:5: 35:12 (#0),
     },
     Literal {
         kind: ByteStrRaw(2),
         symbol: "BR",
         suffix: Some("q"),
-        span: $DIR/dump-debug-span-debug.rs:36:5: 36:16,
+        span: $DIR/dump-debug-span-debug.rs:36:5: 36:16 (#0),
     },
     Literal {
         kind: Char,
         symbol: "C",
         suffix: Some("q"),
-        span: $DIR/dump-debug-span-debug.rs:37:5: 37:9,
+        span: $DIR/dump-debug-span-debug.rs:37:5: 37:9 (#0),
     },
     Literal {
         kind: Byte,
         symbol: "B",
         suffix: Some("q"),
-        span: $DIR/dump-debug-span-debug.rs:38:5: 38:10,
+        span: $DIR/dump-debug-span-debug.rs:38:5: 38:10 (#0),
     },
 ]
diff --git a/src/test/ui/proc-macro/empty-where-clause.rs b/src/test/ui/proc-macro/empty-where-clause.rs
new file mode 100644
index 00000000000..719555c092a
--- /dev/null
+++ b/src/test/ui/proc-macro/empty-where-clause.rs
@@ -0,0 +1,18 @@
+// aux-build:test-macros.rs
+
+extern crate test_macros;
+use test_macros::recollect_attr;
+
+#[recollect_attr]
+struct FieldStruct where {
+    field: MissingType1 //~ ERROR cannot find
+}
+
+#[recollect_attr]
+struct TupleStruct(MissingType2) where; //~ ERROR cannot find
+
+enum MyEnum where {
+    Variant(MissingType3) //~ ERROR cannot find
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/empty-where-clause.stderr b/src/test/ui/proc-macro/empty-where-clause.stderr
new file mode 100644
index 00000000000..192a2b30f0d
--- /dev/null
+++ b/src/test/ui/proc-macro/empty-where-clause.stderr
@@ -0,0 +1,21 @@
+error[E0412]: cannot find type `MissingType1` in this scope
+  --> $DIR/empty-where-clause.rs:8:12
+   |
+LL |     field: MissingType1
+   |            ^^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `MissingType2` in this scope
+  --> $DIR/empty-where-clause.rs:12:20
+   |
+LL | struct TupleStruct(MissingType2) where;
+   |                    ^^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `MissingType3` in this scope
+  --> $DIR/empty-where-clause.rs:15:13
+   |
+LL |     Variant(MissingType3)
+   |             ^^^^^^^^^^^^ not found in this scope
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/proc-macro/mixed-site-span.stderr b/src/test/ui/proc-macro/mixed-site-span.stderr
index 2b851a76f6a..6244ffc47a6 100644
--- a/src/test/ui/proc-macro/mixed-site-span.stderr
+++ b/src/test/ui/proc-macro/mixed-site-span.stderr
@@ -27,10 +27,6 @@ LL | pass_dollar_crate!();
    | ^^^^^^^^^^^^^^^^^^^^^ not found in `$crate`
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider importing this struct
-   |
-LL | use ItemUse;
-   |
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/recursion/recursive-enum.stderr b/src/test/ui/recursion/recursive-enum.stderr
index e4674b57a6d..ab4709d8e70 100644
--- a/src/test/ui/recursion/recursive-enum.stderr
+++ b/src/test/ui/recursion/recursive-enum.stderr
@@ -6,7 +6,10 @@ LL | enum List<T> { Cons(T, List<T>), Nil }
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `List` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `List` representable
+   |
+LL | enum List<T> { Cons(T, Box<List<T>>), Nil }
+   |                        ^^^^       ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/recursion/recursive-static-definition.stderr b/src/test/ui/recursion/recursive-static-definition.stderr
index b724c261a7c..093606e100c 100644
--- a/src/test/ui/recursion/recursive-static-definition.stderr
+++ b/src/test/ui/recursion/recursive-static-definition.stderr
@@ -1,8 +1,8 @@
 error[E0391]: cycle detected when const-evaluating `FOO`
-  --> $DIR/recursive-static-definition.rs:1:23
+  --> $DIR/recursive-static-definition.rs:1:1
    |
 LL | pub static FOO: u32 = FOO;
-   |                       ^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires const-evaluating `FOO`...
   --> $DIR/recursive-static-definition.rs:1:1
diff --git a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr
index 4c275b19492..b087e03b464 100644
--- a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr
+++ b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr
@@ -1,9 +1,13 @@
 error: captured variable cannot escape `FnMut` closure body
   --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:7:24
    |
+LL |         let mut x = 0;
+   |             ----- variable defined here
 LL |         let mut f = || &mut x;
-   |                      - ^^^^^^ returns a reference to a captured variable which escapes the closure body
-   |                      |
+   |                      - ^^^^^-
+   |                      | |    |
+   |                      | |    variable captured here
+   |                      | returns a reference to a captured variable which escapes the closure body
    |                      inferred to be a `FnMut` closure
    |
    = note: `FnMut` closures only have access to their captured variables while they are executing...
diff --git a/src/test/ui/repeat_count.rs b/src/test/ui/repeat_count.rs
index aca7af144a9..7e30491f0bd 100644
--- a/src/test/ui/repeat_count.rs
+++ b/src/test/ui/repeat_count.rs
@@ -22,6 +22,9 @@ fn main() {
     let f = [0_usize; -1_isize];
     //~^ ERROR mismatched types
     //~| expected `usize`, found `isize`
+    let f = [0; 4u8];
+    //~^ ERROR mismatched types
+    //~| expected `usize`, found `u8`
     struct G {
         g: (),
     }
diff --git a/src/test/ui/repeat_count.stderr b/src/test/ui/repeat_count.stderr
index 4a2d1d9f921..6a081e23d9d 100644
--- a/src/test/ui/repeat_count.stderr
+++ b/src/test/ui/repeat_count.stderr
@@ -29,7 +29,7 @@ LL |     let e = [0; "foo"];
    |                 ^^^^^ expected `usize`, found `&str`
 
 error[E0308]: mismatched types
-  --> $DIR/repeat_count.rs:28:17
+  --> $DIR/repeat_count.rs:31:17
    |
 LL |     let g = [0; G { g: () }];
    |                 ^^^^^^^^^^^ expected `usize`, found struct `main::G`
@@ -39,24 +39,25 @@ error[E0308]: mismatched types
    |
 LL |     let f = [0; -4_isize];
    |                 ^^^^^^^^ expected `usize`, found `isize`
-   |
-help: you can convert an `isize` to `usize` and panic if the converted value wouldn't fit
-   |
-LL |     let f = [0; (-4_isize).try_into().unwrap()];
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/repeat_count.rs:22:23
    |
 LL |     let f = [0_usize; -1_isize];
    |                       ^^^^^^^^ expected `usize`, found `isize`
+
+error[E0308]: mismatched types
+  --> $DIR/repeat_count.rs:25:17
+   |
+LL |     let f = [0; 4u8];
+   |                 ^^^ expected `usize`, found `u8`
    |
-help: you can convert an `isize` to `usize` and panic if the converted value wouldn't fit
+help: change the type of the numeric literal from `u8` to `usize`
    |
-LL |     let f = [0_usize; (-1_isize).try_into().unwrap()];
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     let f = [0; 4usize];
+   |                 ^^^^^^
 
-error: aborting due to 8 previous errors
+error: aborting due to 9 previous errors
 
 Some errors have detailed explanations: E0308, E0435.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/resolve/use_suggestion.stderr b/src/test/ui/resolve/use_suggestion.stderr
index 2fd3d5dccd2..72dda940729 100644
--- a/src/test/ui/resolve/use_suggestion.stderr
+++ b/src/test/ui/resolve/use_suggestion.stderr
@@ -10,12 +10,10 @@ error[E0433]: failed to resolve: use of undeclared type or module `HashMap`
 LL |     let x1 = HashMap::new();
    |              ^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this struct
    |
 LL | use std::collections::HashMap;
    |
-LL | use std::collections::hash_map::HashMap;
-   |
 
 error[E0412]: cannot find type `HashMap` in this scope
   --> $DIR/use_suggestion.rs:5:13
@@ -23,12 +21,10 @@ error[E0412]: cannot find type `HashMap` in this scope
 LL |     let y1: HashMap;
    |             ^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this struct
    |
 LL | use std::collections::HashMap;
    |
-LL | use std::collections::hash_map::HashMap;
-   |
 
 error[E0412]: cannot find type `GooMap` in this scope
   --> $DIR/use_suggestion.rs:6:13
diff --git a/src/test/ui/resolve/use_suggestion_placement.stderr b/src/test/ui/resolve/use_suggestion_placement.stderr
index 9c337f515ad..3f91760fe21 100644
--- a/src/test/ui/resolve/use_suggestion_placement.stderr
+++ b/src/test/ui/resolve/use_suggestion_placement.stderr
@@ -26,12 +26,10 @@ error[E0412]: cannot find type `HashMap` in this scope
 LL |     type Dict<K, V> = HashMap<K, V>;
    |                       ^^^^^^^ not found in this scope
    |
-help: consider importing one of these items
+help: consider importing this struct
    |
 LL | use std::collections::HashMap;
    |
-LL | use std::collections::hash_map::HashMap;
-   |
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/rfc-2091-track-caller/call-chain.rs b/src/test/ui/rfc-2091-track-caller/call-chain.rs
new file mode 100644
index 00000000000..3f1c8f7abe8
--- /dev/null
+++ b/src/test/ui/rfc-2091-track-caller/call-chain.rs
@@ -0,0 +1,28 @@
+// run-pass
+
+#![feature(track_caller)]
+
+use std::panic::Location;
+
+struct Foo;
+
+impl Foo {
+    #[track_caller]
+    fn check_loc(&self, line: u32, col: u32) -> &Self {
+        let loc = Location::caller();
+        assert_eq!(loc.file(), file!(), "file mismatch");
+        assert_eq!(loc.line(), line, "line mismatch");
+        assert_eq!(loc.column(), col, "column mismatch");
+        self
+    }
+}
+
+fn main() {
+    // Tests that when `Location::caller` is used in a method chain,
+    // it points to the start of the correct call (the first character after the dot)
+    // instead of to the very first expression in the chain
+    let foo = Foo;
+    foo.
+        check_loc(line!(), 9).check_loc(line!(), 31)
+        .check_loc(line!(), 10);
+}
diff --git a/src/test/ui/save-analysis/issue-68621.stderr b/src/test/ui/save-analysis/issue-68621.stderr
index 2c5bbd7782b..3af6d0a3e07 100644
--- a/src/test/ui/save-analysis/issue-68621.stderr
+++ b/src/test/ui/save-analysis/issue-68621.stderr
@@ -1,8 +1,8 @@
 error: could not find defining uses
-  --> $DIR/issue-68621.rs:14:5
+  --> $DIR/issue-68621.rs:14:19
    |
 LL |     type Future = impl Trait;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   ^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs b/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs
index e664ecadda2..b7b3ec99781 100644
--- a/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs
+++ b/src/test/ui/simd/simd-intrinsic-generic-arithmetic-saturating.rs
@@ -20,7 +20,7 @@ extern "platform-intrinsic" {
 fn main() {
     // unsigned
     {
-        const M: u32 = u32::max_value();
+        const M: u32 = u32::MAX;
 
         let a = u32x4(1, 2, 3, 4);
         let b = u32x4(2, 4, 6, 8);
@@ -48,8 +48,8 @@ fn main() {
 
     // signed
     {
-        const MIN: i32 = i32::min_value();
-        const MAX: i32 = i32::max_value();
+        const MIN: i32 = i32::MIN;
+        const MAX: i32 = i32::MAX;
 
         let a = i32x4(1, 2, 3, 4);
         let b = i32x4(2, 4, 6, 8);
diff --git a/src/test/ui/simd/simd-intrinsic-generic-bitmask.rs b/src/test/ui/simd/simd-intrinsic-generic-bitmask.rs
index b28f742a92e..a323bd9e82b 100644
--- a/src/test/ui/simd/simd-intrinsic-generic-bitmask.rs
+++ b/src/test/ui/simd/simd-intrinsic-generic-bitmask.rs
@@ -39,7 +39,7 @@ fn main() {
     let e = 0b_1101;
 
     // Check usize / isize
-    let msize: Tx4<usize> = Tx4(usize::max_value(), 0, usize::max_value(), usize::max_value());
+    let msize: Tx4<usize> = Tx4(usize::MAX, 0, usize::MAX, usize::MAX);
 
     unsafe {
         let r: u8 = simd_bitmask(z);
diff --git a/src/test/ui/simd/simd-intrinsic-generic-reduction.rs b/src/test/ui/simd/simd-intrinsic-generic-reduction.rs
index 4195444a73f..8b5afeac0bc 100644
--- a/src/test/ui/simd/simd-intrinsic-generic-reduction.rs
+++ b/src/test/ui/simd/simd-intrinsic-generic-reduction.rs
@@ -100,7 +100,7 @@ fn main() {
         let r: u32 = simd_reduce_max(x);
         assert_eq!(r, 4_u32);
 
-        let t = u32::max_value();
+        let t = u32::MAX;
         let x = u32x4(t, t, t, t);
         let r: u32 = simd_reduce_and(x);
         assert_eq!(r, t);
diff --git a/src/test/ui/sized-cycle-note.stderr b/src/test/ui/sized-cycle-note.stderr
index 95bdc349426..45062c2ea6c 100644
--- a/src/test/ui/sized-cycle-note.stderr
+++ b/src/test/ui/sized-cycle-note.stderr
@@ -2,21 +2,27 @@ error[E0072]: recursive type `Baz` has infinite size
   --> $DIR/sized-cycle-note.rs:9:1
    |
 LL | struct Baz { q: Option<Foo> }
-   | ^^^^^^^^^^   -------------- recursive without indirection
+   | ^^^^^^^^^^      ----------- recursive without indirection
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Baz` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Baz` representable
+   |
+LL | struct Baz { q: Box<Option<Foo>> }
+   |                 ^^^^           ^
 
 error[E0072]: recursive type `Foo` has infinite size
   --> $DIR/sized-cycle-note.rs:11:1
    |
 LL | struct Foo { q: Option<Baz> }
-   | ^^^^^^^^^^   -------------- recursive without indirection
+   | ^^^^^^^^^^      ----------- recursive without indirection
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+   |
+LL | struct Foo { q: Box<Option<Baz>> }
+   |                 ^^^^           ^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/E0072.stderr b/src/test/ui/span/E0072.stderr
index d4a5e7400d2..06493f05142 100644
--- a/src/test/ui/span/E0072.stderr
+++ b/src/test/ui/span/E0072.stderr
@@ -5,9 +5,12 @@ LL | struct ListNode {
    | ^^^^^^^^^^^^^^^ recursive type has infinite size
 LL |     head: u8,
 LL |     tail: Option<ListNode>,
-   |     ---------------------- recursive without indirection
+   |           ---------------- recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ListNode` representable
+   |
+LL |     tail: Box<Option<ListNode>>,
+   |           ^^^^                ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/span/multiline-span-E0072.stderr b/src/test/ui/span/multiline-span-E0072.stderr
index dd322fe833b..55128347f74 100644
--- a/src/test/ui/span/multiline-span-E0072.stderr
+++ b/src/test/ui/span/multiline-span-E0072.stderr
@@ -6,11 +6,14 @@ LL | | ListNode
 LL | | {
 LL | |     head: u8,
 LL | |     tail: Option<ListNode>,
-   | |     ---------------------- recursive without indirection
+   | |           ---------------- recursive without indirection
 LL | | }
    | |_^ recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ListNode` representable
+   |
+LL |     tail: Box<Option<ListNode>>,
+   |           ^^^^                ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/span/recursive-type-field.stderr b/src/test/ui/span/recursive-type-field.stderr
index d240872647e..fb1d98b58df 100644
--- a/src/test/ui/span/recursive-type-field.stderr
+++ b/src/test/ui/span/recursive-type-field.stderr
@@ -4,9 +4,12 @@ error[E0072]: recursive type `Foo` has infinite size
 LL | struct Foo<'a> {
    | ^^^^^^^^^^^^^^ recursive type has infinite size
 LL |     bar: Bar<'a>,
-   |     ------------ recursive without indirection
+   |          ------- recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+   |
+LL |     bar: Box<Bar<'a>>,
+   |          ^^^^       ^
 
 error[E0072]: recursive type `Bar` has infinite size
   --> $DIR/recursive-type-field.rs:8:1
@@ -14,18 +17,18 @@ error[E0072]: recursive type `Bar` has infinite size
 LL | struct Bar<'a> {
    | ^^^^^^^^^^^^^^ recursive type has infinite size
 LL |     y: (Foo<'a>, Foo<'a>),
-   |     --------------------- recursive without indirection
+   |        ------------------ recursive without indirection
 LL |     z: Option<Bar<'a>>,
-   |     ------------------ recursive without indirection
+   |        --------------- recursive without indirection
 ...
 LL |     d: [Bar<'a>; 1],
-   |     --------------- recursive without indirection
+   |        ------------ recursive without indirection
 LL |     e: Foo<'a>,
-   |     ---------- recursive without indirection
+   |        ------- recursive without indirection
 LL |     x: Bar<'a>,
-   |     ---------- recursive without indirection
+   |        ------- recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
+   = help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/suggestions/const-pat-non-exaustive-let-new-var.rs b/src/test/ui/suggestions/const-pat-non-exaustive-let-new-var.rs
index 2a11871db8e..21fb8d4a2e6 100644
--- a/src/test/ui/suggestions/const-pat-non-exaustive-let-new-var.rs
+++ b/src/test/ui/suggestions/const-pat-non-exaustive-let-new-var.rs
@@ -1,6 +1,6 @@
 fn main() {
     let A = 3;
-    //~^ ERROR refutable pattern in local binding: `std::i32::MIN..=1i32` and
+    //~^ ERROR refutable pattern in local binding: `i32::MIN..=1i32` and
     //~| interpreted as a constant pattern, not a new variable
     //~| HELP introduce a variable instead
     //~| SUGGESTION a_var
diff --git a/src/test/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr b/src/test/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr
index 1512eac7667..7a6269da07f 100644
--- a/src/test/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr
+++ b/src/test/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr
@@ -1,4 +1,4 @@
-error[E0005]: refutable pattern in local binding: `std::i32::MIN..=1i32` and `3i32..=std::i32::MAX` not covered
+error[E0005]: refutable pattern in local binding: `i32::MIN..=1i32` and `3i32..=i32::MAX` not covered
   --> $DIR/const-pat-non-exaustive-let-new-var.rs:2:9
    |
 LL |     let A = 3;
diff --git a/src/test/ui/traits/trait-alias/issue-60021-assoc-method-resolve.rs b/src/test/ui/traits/trait-alias/issue-60021-assoc-method-resolve.rs
new file mode 100644
index 00000000000..5e27ed3c646
--- /dev/null
+++ b/src/test/ui/traits/trait-alias/issue-60021-assoc-method-resolve.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+#![feature(trait_alias)]
+
+trait SomeTrait {
+    fn map(&self) {}
+}
+
+impl<T> SomeTrait for Option<T> {}
+
+trait SomeAlias = SomeTrait;
+
+fn main() {
+    let x = Some(123);
+    // This should resolve to the trait impl for Option
+    Option::map(x, |z| z);
+    // This should resolve to the trait impl for SomeTrait
+    SomeTrait::map(&x);
+}
diff --git a/src/test/ui/traits/trait-alias/issue-72415-assoc-const-resolve.rs b/src/test/ui/traits/trait-alias/issue-72415-assoc-const-resolve.rs
new file mode 100644
index 00000000000..e49125d1024
--- /dev/null
+++ b/src/test/ui/traits/trait-alias/issue-72415-assoc-const-resolve.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+#![feature(trait_alias)]
+
+trait Bounded { const MAX: Self; }
+
+impl Bounded for u32 {
+    // This should correctly resolve to the associated const in the inherent impl of u32.
+    const MAX: Self = u32::MAX;
+}
+
+trait Num = Bounded + Copy;
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr
index b871f79aa1d..9ebf63468e7 100644
--- a/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr
+++ b/src/test/ui/type-alias-impl-trait/bound_reduction2.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `T: TraitWithAssoc` is not satisfied
-  --> $DIR/bound_reduction2.rs:10:1
+  --> $DIR/bound_reduction2.rs:10:15
    |
 LL | type Foo<V> = impl Trait<V>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitWithAssoc` is not implemented for `T`
+   |               ^^^^^^^^^^^^^ the trait `TraitWithAssoc` is not implemented for `T`
    |
 help: consider further restricting this bound
    |
diff --git a/src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr b/src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr
index ae0fee4333b..21c2e8a9db6 100644
--- a/src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr
+++ b/src/test/ui/type-alias-impl-trait/declared_but_never_defined.stderr
@@ -1,8 +1,8 @@
 error: could not find defining uses
-  --> $DIR/declared_but_never_defined.rs:6:1
+  --> $DIR/declared_but_never_defined.rs:6:12
    |
 LL | type Bar = impl std::fmt::Debug;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr
index 0642407aba3..c0cb94b15d0 100644
--- a/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr
+++ b/src/test/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr
@@ -1,8 +1,8 @@
 error: could not find defining uses
-  --> $DIR/declared_but_not_defined_in_scope.rs:7:5
+  --> $DIR/declared_but_not_defined_in_scope.rs:7:20
    |
 LL |     pub type Boo = impl ::std::fmt::Debug;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                    ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr
index 9549074d4bf..76654d7a718 100644
--- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr
@@ -13,10 +13,10 @@ LL |     let z: i32 = x;
    |            expected due to this
 ...
 LL | type WrongGeneric<T> = impl 'static;
-   | ------------------------------------ the found opaque type
+   |                        ------------ the found opaque type
    |
    = note:     expected type `i32`
-           found opaque type `WrongGeneric::<&{integer}>`
+           found opaque type `impl Sized`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
index e2540e424cb..18d8daa05e6 100644
--- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
@@ -13,16 +13,16 @@ LL |     let z: i32 = x;
    |            expected due to this
 ...
 LL | type WrongGeneric<T> = impl 'static;
-   | ------------------------------------ the found opaque type
+   |                        ------------ the found opaque type
    |
    = note:     expected type `i32`
-           found opaque type `WrongGeneric::<&{integer}>`
+           found opaque type `impl Sized`
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/generic_type_does_not_live_long_enough.rs:9:1
+  --> $DIR/generic_type_does_not_live_long_enough.rs:9:24
    |
 LL | type WrongGeneric<T> = impl 'static;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+   |                        ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 ...
 LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
    |                  - help: consider adding an explicit lifetime bound...: `T: 'static`
diff --git a/src/test/ui/type-alias-impl-trait/generic_underconstrained.stderr b/src/test/ui/type-alias-impl-trait/generic_underconstrained.stderr
index f7a04263259..911f592f73f 100644
--- a/src/test/ui/type-alias-impl-trait/generic_underconstrained.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_underconstrained.stderr
@@ -5,10 +5,10 @@ LL | type Underconstrained<T: Trait> = impl 'static;
    |                                   ^^^^^^^^^^^^
 
 error[E0277]: the trait bound `T: Trait` is not satisfied
-  --> $DIR/generic_underconstrained.rs:6:1
+  --> $DIR/generic_underconstrained.rs:6:35
    |
 LL | type Underconstrained<T: Trait> = impl 'static;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
+   |                                   ^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
    |
    = note: the return type of a function must have a statically known size
 help: consider restricting type parameter `T`
diff --git a/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr b/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr
index ad160abcbd5..247d68ef2a1 100644
--- a/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr
@@ -11,10 +11,10 @@ LL | type Underconstrained2<T: std::fmt::Debug> = impl 'static;
    |                                              ^^^^^^^^^^^^
 
 error[E0277]: `U` doesn't implement `std::fmt::Debug`
-  --> $DIR/generic_underconstrained2.rs:5:1
+  --> $DIR/generic_underconstrained2.rs:5:45
    |
 LL | type Underconstrained<T: std::fmt::Debug> = impl 'static;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
+   |                                             ^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
 ...
 LL |     5u32
    |     ---- this returned value is of type `u32`
@@ -27,10 +27,10 @@ LL | fn underconstrained<U: std::fmt::Debug>(_: U) -> Underconstrained<U> {
    |                      ^^^^^^^^^^^^^^^^^
 
 error[E0277]: `V` doesn't implement `std::fmt::Debug`
-  --> $DIR/generic_underconstrained2.rs:14:1
+  --> $DIR/generic_underconstrained2.rs:14:46
    |
 LL | type Underconstrained2<T: std::fmt::Debug> = impl 'static;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
+   |                                              ^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
 ...
 LL |     5u32
    |     ---- this returned value is of type `u32`
diff --git a/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs b/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs
new file mode 100644
index 00000000000..bc6543a9229
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.rs
@@ -0,0 +1,18 @@
+// Ensure that we don't ICE if associated type impl trait is used in an impl
+// with an unconstrained type parameter.
+
+#![feature(type_alias_impl_trait)]
+
+trait X {
+    type I;
+    fn f() -> Self::I;
+}
+
+impl<T> X for () {
+    type I = impl Sized;
+    //~^ ERROR could not find defining uses
+    fn f() -> Self::I {}
+    //~^ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr b/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr
new file mode 100644
index 00000000000..e8b677113db
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/impl-with-unconstrained-param.stderr
@@ -0,0 +1,15 @@
+error[E0282]: type annotations needed
+  --> $DIR/impl-with-unconstrained-param.rs:14:23
+   |
+LL |     fn f() -> Self::I {}
+   |                       ^^ cannot infer type for type parameter `T`
+
+error: could not find defining uses
+  --> $DIR/impl-with-unconstrained-param.rs:12:14
+   |
+LL |     type I = impl Sized;
+   |              ^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs b/src/test/ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs
new file mode 100644
index 00000000000..3a7a5da075f
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs
@@ -0,0 +1,24 @@
+// Regression test for #57188
+
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+struct Baz<'a> {
+    source: &'a str,
+}
+
+trait Foo<'a> {
+    type T: Iterator<Item = Baz<'a>> + 'a;
+    fn foo(source: &'a str) -> Self::T;
+}
+
+struct Bar;
+impl<'a> Foo<'a> for Bar {
+    type T = impl Iterator<Item = Baz<'a>> + 'a;
+    fn foo(source: &'a str) -> Self::T {
+        std::iter::once(Baz { source })
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr
index f648b7bfc99..cc121ac89fb 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr
@@ -1,8 +1,8 @@
 error[E0631]: type mismatch in closure arguments
-  --> $DIR/issue-57611-trait-alias.rs:17:5
+  --> $DIR/issue-57611-trait-alias.rs:17:16
    |
 LL |     type Bar = impl Baz<Self, Self>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected signature of `for<'r> fn(&'r X) -> _`
+   |                ^^^^^^^^^^^^^^^^^^^^ expected signature of `for<'r> fn(&'r X) -> _`
 ...
 LL |         |x| x
    |         ----- found signature of `fn(_) -> _`
@@ -10,10 +10,10 @@ LL |         |x| x
    = note: the return type of a function must have a statically known size
 
 error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/issue-57611-trait-alias.rs:21:9: 21:14] as std::ops::FnOnce<(&'r X,)>>::Output == &'r X`
-  --> $DIR/issue-57611-trait-alias.rs:17:5
+  --> $DIR/issue-57611-trait-alias.rs:17:16
    |
 LL |     type Bar = impl Baz<Self, Self>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter, found concrete lifetime
+   |                ^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter, found concrete lifetime
    |
    = note: the return type of a function must have a statically known size
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-60371.stderr b/src/test/ui/type-alias-impl-trait/issue-60371.stderr
index 2796c77baa1..bf2d612fcdb 100644
--- a/src/test/ui/type-alias-impl-trait/issue-60371.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-60371.stderr
@@ -8,20 +8,20 @@ LL |     type Item = impl Bug;
    = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
 
 error[E0277]: the trait bound `(): Bug` is not satisfied
-  --> $DIR/issue-60371.rs:8:5
+  --> $DIR/issue-60371.rs:8:17
    |
 LL |     type Item = impl Bug;
-   |     ^^^^^^^^^^^^^^^^^^^^^ the trait `Bug` is not implemented for `()`
+   |                 ^^^^^^^^ the trait `Bug` is not implemented for `()`
    |
    = help: the following implementations were found:
              <&() as Bug>
    = note: the return type of a function must have a statically known size
 
 error: could not find defining uses
-  --> $DIR/issue-60371.rs:8:5
+  --> $DIR/issue-60371.rs:8:17
    |
 LL |     type Item = impl Bug;
-   |     ^^^^^^^^^^^^^^^^^^^^^
+   |                 ^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.rs b/src/test/ui/type-alias-impl-trait/issue-60564.rs
index 4eb7f7836d8..78def0d1136 100644
--- a/src/test/ui/type-alias-impl-trait/issue-60564.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-60564.rs
@@ -17,11 +17,8 @@ where
 {
     type BitsIter = IterBitsIter<T, E, u8>;
     fn iter_bits(self, n: u8) -> Self::BitsIter {
-    //~^ ERROR non-defining opaque type use in defining scope
-    //~| ERROR non-defining opaque type use in defining scope
-        (0u8..n)
-            .rev()
-            .map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
+        //~^ ERROR non-defining opaque type use in defining scope
+        (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
     }
 }
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.stderr b/src/test/ui/type-alias-impl-trait/issue-60564.stderr
index 55984609437..66fa862ef9d 100644
--- a/src/test/ui/type-alias-impl-trait/issue-60564.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-60564.stderr
@@ -4,23 +4,11 @@ error: non-defining opaque type use in defining scope
 LL |     fn iter_bits(self, n: u8) -> Self::BitsIter {
    |                                  ^^^^^^^^^^^^^^
    |
-note: used non-generic type `_` for generic parameter
-  --> $DIR/issue-60564.rs:8:22
-   |
-LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
-   |                      ^
-
-error: non-defining opaque type use in defining scope
-  --> $DIR/issue-60564.rs:19:34
-   |
-LL |     fn iter_bits(self, n: u8) -> Self::BitsIter {
-   |                                  ^^^^^^^^^^^^^^
-   |
 note: used non-generic type `u8` for generic parameter
   --> $DIR/issue-60564.rs:8:25
    |
 LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
    |                         ^
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-62000-associate-impl-trait-lifetimes.rs b/src/test/ui/type-alias-impl-trait/issue-62000-associate-impl-trait-lifetimes.rs
new file mode 100644
index 00000000000..36779a0ce89
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-62000-associate-impl-trait-lifetimes.rs
@@ -0,0 +1,38 @@
+// Regression test for #62988
+
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+trait MyTrait {
+    type AssocType: Send;
+    fn ret(&self) -> Self::AssocType;
+}
+
+impl MyTrait for () {
+    type AssocType = impl Send;
+    fn ret(&self) -> Self::AssocType {
+        ()
+    }
+}
+
+impl<'a> MyTrait for &'a () {
+    type AssocType = impl Send;
+    fn ret(&self) -> Self::AssocType {
+        ()
+    }
+}
+
+trait MyLifetimeTrait<'a> {
+    type AssocType: Send + 'a;
+    fn ret(&self) -> Self::AssocType;
+}
+
+impl<'a> MyLifetimeTrait<'a> for &'a () {
+    type AssocType = impl Send + 'a;
+    fn ret(&self) -> Self::AssocType {
+        *self
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-63279.stderr b/src/test/ui/type-alias-impl-trait/issue-63279.stderr
index bef4d01093c..d07f64c3312 100644
--- a/src/test/ui/type-alias-impl-trait/issue-63279.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-63279.stderr
@@ -1,10 +1,10 @@
 error[E0271]: type mismatch resolving `<[closure@$DIR/issue-63279.rs:8:5: 8:28] as std::ops::FnOnce<()>>::Output == ()`
-  --> $DIR/issue-63279.rs:5:1
+  --> $DIR/issue-63279.rs:5:16
    |
 LL | type Closure = impl FnOnce();
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found `()`
+   |                ^^^^^^^^^^^^^ expected opaque type, found `()`
    |
-   = note: expected opaque type `Closure`
+   = note: expected opaque type `impl std::ops::FnOnce<()>`
                 found unit type `()`
    = note: the return type of a function must have a statically known size
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs b/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs
new file mode 100644
index 00000000000..6732902c09a
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs
@@ -0,0 +1,22 @@
+// Regression test for #69136
+
+#![feature(type_alias_impl_trait)]
+
+trait SomeTrait {}
+
+impl SomeTrait for () {}
+
+trait WithAssoc<A> {
+    type AssocType;
+}
+
+impl<T> WithAssoc<T> for () {
+    type AssocType = ();
+}
+
+type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
+//~^ ERROR use of undeclared lifetime name `'a`
+
+fn my_fun() -> Return<()> {}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr b/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr
new file mode 100644
index 00000000000..fe45e39d938
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.stderr
@@ -0,0 +1,11 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/issue-69136-inner-lifetime-resolve-error.rs:17:65
+   |
+LL | type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
+   |             -                                                   ^^ undeclared lifetime
+   |             |
+   |             help: consider introducing lifetime `'a` here: `'a,`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs b/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs
new file mode 100644
index 00000000000..a6916eda8b0
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs
@@ -0,0 +1,23 @@
+// Test-pass variant of #69136
+
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+trait SomeTrait {}
+
+impl SomeTrait for () {}
+
+trait WithAssoc {
+    type AssocType;
+}
+
+impl WithAssoc for () {
+    type AssocType = ();
+}
+
+type Return<'a> = impl WithAssoc<AssocType = impl Sized + 'a>;
+
+fn my_fun<'a>() -> Return<'a> {}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr b/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr
index 70c99c944d6..4fbbf347528 100644
--- a/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr
+++ b/src/test/ui/type-alias-impl-trait/never_reveal_concrete_type.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/never_reveal_concrete_type.rs:13:27
    |
 LL | type NoReveal = impl std::fmt::Debug;
-   | ------------------------------------- the found opaque type
+   |                 -------------------- the found opaque type
 ...
 LL |     let _: &'static str = x;
    |            ------------   ^ expected `&str`, found opaque type
@@ -10,9 +10,9 @@ LL |     let _: &'static str = x;
    |            expected due to this
    |
    = note: expected reference `&'static str`
-            found opaque type `NoReveal`
+            found opaque type `impl std::fmt::Debug`
 
-error[E0605]: non-primitive cast: `NoReveal` as `&'static str`
+error[E0605]: non-primitive cast: `impl std::fmt::Debug` as `&'static str`
   --> $DIR/never_reveal_concrete_type.rs:14:13
    |
 LL |     let _ = x as &'static str;
diff --git a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr
index 444e6e8214f..61025e84692 100644
--- a/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr
+++ b/src/test/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr
@@ -1,8 +1,8 @@
 error: could not find defining uses
-  --> $DIR/no_inferrable_concrete_type.rs:6:1
+  --> $DIR/no_inferrable_concrete_type.rs:6:12
    |
 LL | type Foo = impl Copy;
-   | ^^^^^^^^^^^^^^^^^^^^^
+   |            ^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr b/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr
index 375c0bc7fe2..d237cc6238a 100644
--- a/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr
+++ b/src/test/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/no_revealing_outside_defining_module.rs:15:19
    |
 LL |     pub type Boo = impl ::std::fmt::Debug;
-   |     -------------------------------------- the found opaque type
+   |                    ---------------------- the found opaque type
 ...
 LL |     let _: &str = bomp();
    |            ----   ^^^^^^ expected `&str`, found opaque type
@@ -10,20 +10,20 @@ LL |     let _: &str = bomp();
    |            expected due to this
    |
    = note: expected reference `&str`
-            found opaque type `Boo`
+            found opaque type `impl std::fmt::Debug`
 
 error[E0308]: mismatched types
   --> $DIR/no_revealing_outside_defining_module.rs:19:5
    |
 LL |     pub type Boo = impl ::std::fmt::Debug;
-   |     -------------------------------------- the expected opaque type
+   |                    ---------------------- the expected opaque type
 ...
 LL | fn bomp() -> boo::Boo {
-   |              -------- expected `Boo` because of return type
+   |              -------- expected `impl std::fmt::Debug` because of return type
 LL |     ""
    |     ^^ expected opaque type, found `&str`
    |
-   = note: expected opaque type `Boo`
+   = note: expected opaque type `impl std::fmt::Debug`
                 found reference `&'static str`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr
index 02ab3399ea6..726f4ea6e00 100644
--- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr
+++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error.stderr
@@ -1,8 +1,8 @@
 error: could not find defining uses
-  --> $DIR/type-alias-impl-trait-with-cycle-error.rs:3:1
+  --> $DIR/type-alias-impl-trait-with-cycle-error.rs:3:12
    |
 LL | type Foo = impl Fn() -> Foo;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            ^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr
index e9abb795886..3947cc4d270 100644
--- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr
+++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error2.stderr
@@ -1,8 +1,8 @@
 error: could not find defining uses
-  --> $DIR/type-alias-impl-trait-with-cycle-error2.rs:7:1
+  --> $DIR/type-alias-impl-trait-with-cycle-error2.rs:7:12
    |
 LL | type Foo = impl Bar<Foo, Item = Foo>;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs b/src/test/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs
new file mode 100644
index 00000000000..fd954801dc0
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs
@@ -0,0 +1,14 @@
+// run-pass
+
+#![feature(type_alias_impl_trait)]
+
+use std::iter::{once, Chain};
+
+type I<A> = Chain<A, impl Iterator<Item = &'static str>>;
+fn test2<A: Iterator<Item = &'static str>>(x: A) -> I<A> {
+    x.chain(once("5"))
+}
+
+fn main() {
+    assert_eq!(vec!["1", "3", "5"], test2(["1", "3"].iter().cloned()).collect::<Vec<_>>());
+}
diff --git a/src/test/ui/type/type-recursive.stderr b/src/test/ui/type/type-recursive.stderr
index 72bf372e561..d6d32cc5d6f 100644
--- a/src/test/ui/type/type-recursive.stderr
+++ b/src/test/ui/type/type-recursive.stderr
@@ -5,9 +5,12 @@ LL | struct T1 {
    | ^^^^^^^^^ recursive type has infinite size
 LL |     foo: isize,
 LL |     foolish: T1
-   |     ----------- recursive without indirection
+   |              -- recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `T1` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T1` representable
+   |
+LL |     foolish: Box<T1>
+   |              ^^^^  ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr
index 0b9aa61a765..ab6f0651846 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-call-twice.stderr
@@ -2,7 +2,7 @@ error[E0382]: use of moved value: `tick`
   --> $DIR/unboxed-closures-infer-fnonce-call-twice.rs:10:5
    |
 LL |     tick();
-   |     ---- value moved here
+   |     ------ `tick` moved due to this call
 LL |     tick();
    |     ^^^^ value used here after move
    |
@@ -11,6 +11,11 @@ note: closure cannot be invoked more than once because it moves the variable `co
    |
 LL |     let tick = || mem::drop(counter);
    |                             ^^^^^^^
+note: this value implements `FnOnce`, which causes it to be moved when called
+  --> $DIR/unboxed-closures-infer-fnonce-call-twice.rs:9:5
+   |
+LL |     tick();
+   |     ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr
index 20773d561f9..8d70a2b1760 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fnonce-move-call-twice.stderr
@@ -2,7 +2,7 @@ error[E0382]: use of moved value: `tick`
   --> $DIR/unboxed-closures-infer-fnonce-move-call-twice.rs:10:5
    |
 LL |     tick();
-   |     ---- value moved here
+   |     ------ `tick` moved due to this call
 LL |     tick();
    |     ^^^^ value used here after move
    |
@@ -11,6 +11,11 @@ note: closure cannot be invoked more than once because it moves the variable `co
    |
 LL |     let tick = move || mem::drop(counter);
    |                                  ^^^^^^^
+note: this value implements `FnOnce`, which causes it to be moved when called
+  --> $DIR/unboxed-closures-infer-fnonce-move-call-twice.rs:9:5
+   |
+LL |     tick();
+   |     ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/union/union-nonrepresentable.stderr b/src/test/ui/union/union-nonrepresentable.stderr
index 746c1033ea3..c54d04de12c 100644
--- a/src/test/ui/union/union-nonrepresentable.stderr
+++ b/src/test/ui/union/union-nonrepresentable.stderr
@@ -5,9 +5,12 @@ LL | union U {
    | ^^^^^^^ recursive type has infinite size
 LL |     a: u8,
 LL |     b: U,
-   |     ---- recursive without indirection
+   |        - recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `U` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `U` representable
+   |
+LL |     b: Box<U>,
+   |        ^^^^ ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unop-move-semantics.stderr b/src/test/ui/unop-move-semantics.stderr
index e0499cfe95c..7e9c8559a4b 100644
--- a/src/test/ui/unop-move-semantics.stderr
+++ b/src/test/ui/unop-move-semantics.stderr
@@ -4,11 +4,16 @@ error[E0382]: borrow of moved value: `x`
 LL | fn move_then_borrow<T: Not<Output=T> + Clone>(x: T) {
    |                                               - move occurs because `x` has type `T`, which does not implement the `Copy` trait
 LL |     !x;
-   |      - value moved here
+   |     -- `x` moved due to this method call
 LL | 
 LL |     x.clone();
    |     ^ value borrowed here after move
    |
+note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
+  --> $SRC_DIR/libcore/ops/bit.rs:LL:COL
+   |
+LL |     fn not(self) -> Self::Output;
+   |            ^^^^
 help: consider further restricting this bound
    |
 LL | fn move_then_borrow<T: Not<Output=T> + Clone + Copy>(x: T) {
diff --git a/src/test/ui/unsized-locals/borrow-after-move.stderr b/src/test/ui/unsized-locals/borrow-after-move.stderr
index 110edab69be..906b543e421 100644
--- a/src/test/ui/unsized-locals/borrow-after-move.stderr
+++ b/src/test/ui/unsized-locals/borrow-after-move.stderr
@@ -37,10 +37,16 @@ error[E0382]: borrow of moved value: `y`
 LL |         let y = *x;
    |             - move occurs because `y` has type `str`, which does not implement the `Copy` trait
 LL |         y.foo();
-   |         - value moved here
+   |           ----- `y` moved due to this method call
 ...
 LL |         println!("{}", &y);
    |                        ^^ value borrowed here after move
+   |
+note: this function consumes the receiver `self` by taking ownership of it, which moves `y`
+  --> $DIR/borrow-after-move.rs:4:12
+   |
+LL |     fn foo(self) -> String;
+   |            ^^^^
 
 error[E0382]: borrow of moved value: `x`
   --> $DIR/borrow-after-move.rs:39:24
diff --git a/src/test/ui/unsized-locals/double-move.stderr b/src/test/ui/unsized-locals/double-move.stderr
index 5b936fb6447..49b2031c6b9 100644
--- a/src/test/ui/unsized-locals/double-move.stderr
+++ b/src/test/ui/unsized-locals/double-move.stderr
@@ -34,9 +34,15 @@ error[E0382]: use of moved value: `y`
 LL |         let y = *x;
    |             - move occurs because `y` has type `str`, which does not implement the `Copy` trait
 LL |         y.foo();
-   |         - value moved here
+   |           ----- `y` moved due to this method call
 LL |         y.foo();
    |         ^ value used here after move
+   |
+note: this function consumes the receiver `self` by taking ownership of it, which moves `y`
+  --> $DIR/double-move.rs:4:12
+   |
+LL |     fn foo(self) -> String;
+   |            ^^^^
 
 error[E0382]: use of moved value: `x`
   --> $DIR/double-move.rs:45:9
diff --git a/src/test/ui/use/use-after-move-self-based-on-type.stderr b/src/test/ui/use/use-after-move-self-based-on-type.stderr
index 9bf1175430c..b9440f4de07 100644
--- a/src/test/ui/use/use-after-move-self-based-on-type.stderr
+++ b/src/test/ui/use/use-after-move-self-based-on-type.stderr
@@ -4,9 +4,15 @@ error[E0382]: use of moved value: `self`
 LL |     pub fn foo(self) -> isize {
    |                ---- move occurs because `self` has type `S`, which does not implement the `Copy` trait
 LL |         self.bar();
-   |         ---- value moved here
+   |              ----- `self` moved due to this method call
 LL |         return self.x;
    |                ^^^^^^ value used here after move
+   |
+note: this function consumes the receiver `self` by taking ownership of it, which moves `self`
+  --> $DIR/use-after-move-self-based-on-type.rs:15:16
+   |
+LL |     pub fn bar(self) {}
+   |                ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/use/use-after-move-self.stderr b/src/test/ui/use/use-after-move-self.stderr
index 3be0a65550b..3da53b024db 100644
--- a/src/test/ui/use/use-after-move-self.stderr
+++ b/src/test/ui/use/use-after-move-self.stderr
@@ -4,9 +4,15 @@ error[E0382]: use of moved value: `self`
 LL |     pub fn foo(self) -> isize {
    |                ---- move occurs because `self` has type `S`, which does not implement the `Copy` trait
 LL |         self.bar();
-   |         ---- value moved here
+   |              ----- `self` moved due to this method call
 LL |         return *self.x;
    |                ^^^^^^^ value used here after move
+   |
+note: this function consumes the receiver `self` by taking ownership of it, which moves `self`
+  --> $DIR/use-after-move-self.rs:13:16
+   |
+LL |     pub fn bar(self) {}
+   |                ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/variance/variance-associated-types2.nll.stderr b/src/test/ui/variance/variance-associated-types2.nll.stderr
new file mode 100644
index 00000000000..27d1e184416
--- /dev/null
+++ b/src/test/ui/variance/variance-associated-types2.nll.stderr
@@ -0,0 +1,12 @@
+error: lifetime may not live long enough
+  --> $DIR/variance-associated-types2.rs:13:12
+   |
+LL | fn take<'a>(_: &'a u32) {
+   |         -- lifetime `'a` defined here
+LL |     let _: Box<dyn Foo<Bar = &'a u32>> = make();
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/variance/variance-associated-types2.rs b/src/test/ui/variance/variance-associated-types2.rs
new file mode 100644
index 00000000000..6a095fce7ab
--- /dev/null
+++ b/src/test/ui/variance/variance-associated-types2.rs
@@ -0,0 +1,17 @@
+// Test that dyn Foo<Bar = T> is invariant with respect to T.
+// Failure to enforce invariance here can be weaponized, see #71550 for details.
+
+trait Foo {
+    type Bar;
+}
+
+fn make() -> Box<dyn Foo<Bar = &'static u32>> {
+    panic!()
+}
+
+fn take<'a>(_: &'a u32) {
+    let _: Box<dyn Foo<Bar = &'a u32>> = make();
+    //~^ ERROR mismatched types [E0308]
+}
+
+fn main() {}
diff --git a/src/test/ui/variance/variance-associated-types2.stderr b/src/test/ui/variance/variance-associated-types2.stderr
new file mode 100644
index 00000000000..52cdd6493b0
--- /dev/null
+++ b/src/test/ui/variance/variance-associated-types2.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/variance-associated-types2.rs:13:42
+   |
+LL |     let _: Box<dyn Foo<Bar = &'a u32>> = make();
+   |                                          ^^^^^^ lifetime mismatch
+   |
+   = note: expected trait object `dyn Foo<Bar = &'a u32>`
+              found trait object `dyn Foo<Bar = &'static u32>`
+note: the lifetime `'a` as defined on the function body at 12:9...
+  --> $DIR/variance-associated-types2.rs:12:9
+   |
+LL | fn take<'a>(_: &'a u32) {
+   |         ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/walk-struct-literal-with.stderr b/src/test/ui/walk-struct-literal-with.stderr
index eeb594a21f3..ece63a2b819 100644
--- a/src/test/ui/walk-struct-literal-with.stderr
+++ b/src/test/ui/walk-struct-literal-with.stderr
@@ -4,9 +4,15 @@ error[E0382]: borrow of moved value: `start`
 LL |     let start = Mine{test:"Foo".to_string(), other_val:0};
    |         ----- move occurs because `start` has type `Mine`, which does not implement the `Copy` trait
 LL |     let end = Mine{other_val:1, ..start.make_string_bar()};
-   |                                   ----- value moved here
+   |                                         ----------------- `start` moved due to this method call
 LL |     println!("{}", start.test);
    |                    ^^^^^^^^^^ value borrowed here after move
+   |
+note: this function consumes the receiver `self` by taking ownership of it, which moves `start`
+  --> $DIR/walk-struct-literal-with.rs:7:28
+   |
+LL |     fn make_string_bar(mut self) -> Mine{
+   |                            ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/write-to-static-mut-in-static.stderr b/src/test/ui/write-to-static-mut-in-static.stderr
index 6c2bd13d433..50dfce3448c 100644
--- a/src/test/ui/write-to-static-mut-in-static.stderr
+++ b/src/test/ui/write-to-static-mut-in-static.stderr
@@ -5,10 +5,10 @@ LL | pub static mut B: () = unsafe { A = 1; };
    |                                 ^^^^^ modifying a static's initial value from another static's initializer
 
 error[E0391]: cycle detected when const-evaluating `C`
-  --> $DIR/write-to-static-mut-in-static.rs:5:34
+  --> $DIR/write-to-static-mut-in-static.rs:5:1
    |
 LL | pub static mut C: u32 = unsafe { C = 1; 0 };
-   |                                  ^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires const-evaluating `C`...
   --> $DIR/write-to-static-mut-in-static.rs:5:1
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 40ebd52206e25c7a576ee42c137cc06a745a167
+Subproject 79c769c3d7b4c2cf6a93781575b7f592ef97425
diff --git a/src/tools/clippy/clippy_lints/src/atomic_ordering.rs b/src/tools/clippy/clippy_lints/src/atomic_ordering.rs
index 73b4cef4725..fca9aaaff9d 100644
--- a/src/tools/clippy/clippy_lints/src/atomic_ordering.rs
+++ b/src/tools/clippy/clippy_lints/src/atomic_ordering.rs
@@ -70,7 +70,7 @@ fn match_ordering_def_path(cx: &LateContext<'_, '_>, did: DefId, orderings: &[&s
 
 fn check_atomic_load_store(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
     if_chain! {
-        if let ExprKind::MethodCall(ref method_path, _, args) = &expr.kind;
+        if let ExprKind::MethodCall(ref method_path, _, args, _) = &expr.kind;
         let method = method_path.ident.name.as_str();
         if type_is_atomic(cx, &args[0]);
         if method == "load" || method == "store";
diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs
index 8031052e073..f92c564543b 100644
--- a/src/tools/clippy/clippy_lints/src/booleans.rs
+++ b/src/tools/clippy/clippy_lints/src/booleans.rs
@@ -247,7 +247,7 @@ fn simplify_not(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<String> {
                 ))
             })
         },
-        ExprKind::MethodCall(path, _, args) if args.len() == 1 => {
+        ExprKind::MethodCall(path, _, args, _) if args.len() == 1 => {
             let type_of_receiver = cx.tables.expr_ty(&args[0]);
             if !is_type_diagnostic_item(cx, type_of_receiver, sym!(option_type))
                 && !is_type_diagnostic_item(cx, type_of_receiver, sym!(result_type))
diff --git a/src/tools/clippy/clippy_lints/src/bytecount.rs b/src/tools/clippy/clippy_lints/src/bytecount.rs
index 90c00ad098f..531531a654d 100644
--- a/src/tools/clippy/clippy_lints/src/bytecount.rs
+++ b/src/tools/clippy/clippy_lints/src/bytecount.rs
@@ -38,10 +38,10 @@ declare_lint_pass!(ByteCount => [NAIVE_BYTECOUNT]);
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount {
     fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
         if_chain! {
-            if let ExprKind::MethodCall(ref count, _, ref count_args) = expr.kind;
+            if let ExprKind::MethodCall(ref count, _, ref count_args, _) = expr.kind;
             if count.ident.name == sym!(count);
             if count_args.len() == 1;
-            if let ExprKind::MethodCall(ref filter, _, ref filter_args) = count_args[0].kind;
+            if let ExprKind::MethodCall(ref filter, _, ref filter_args, _) = count_args[0].kind;
             if filter.ident.name == sym!(filter);
             if filter_args.len() == 2;
             if let ExprKind::Closure(_, _, body_id, _, _) = filter_args[1].kind;
@@ -66,7 +66,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ByteCount {
                         if ty::Uint(UintTy::U8) != walk_ptrs_ty(cx.tables.expr_ty(needle)).kind {
                             return;
                         }
-                        let haystack = if let ExprKind::MethodCall(ref path, _, ref args) =
+                        let haystack = if let ExprKind::MethodCall(ref path, _, ref args, _) =
                                 filter_args[0].kind {
                             let p = path.ident.name;
                             if (p == sym!(iter) || p == sym!(iter_mut)) && args.len() == 1 {
diff --git a/src/tools/clippy/clippy_lints/src/checked_conversions.rs b/src/tools/clippy/clippy_lints/src/checked_conversions.rs
index e845ef99c7c..88145015ba8 100644
--- a/src/tools/clippy/clippy_lints/src/checked_conversions.rs
+++ b/src/tools/clippy/clippy_lints/src/checked_conversions.rs
@@ -88,7 +88,7 @@ fn double_check<'a>(cx: &LateContext<'_, '_>, left: &'a Expr<'_>, right: &'a Exp
         let upper = check_upper_bound(l);
         let lower = check_lower_bound(r);
 
-        transpose(upper, lower).and_then(|(l, r)| l.combine(r, cx))
+        upper.zip(lower).and_then(|(l, r)| l.combine(r, cx))
     };
 
     upper_lower(left, right).or_else(|| upper_lower(right, left))
@@ -131,7 +131,10 @@ impl<'a> Conversion<'a> {
 
     /// Checks if the to-type is the same (if there is a type constraint)
     fn has_compatible_to_type(&self, other: &Self) -> bool {
-        transpose(self.to_type.as_ref(), other.to_type.as_ref()).map_or(true, |(l, r)| l == r)
+        match (self.to_type, other.to_type) {
+            (Some(l), Some(r)) => l == r,
+            _ => true,
+        }
     }
 
     /// Try to construct a new conversion if the conversion type is valid
@@ -322,14 +325,6 @@ fn int_ty_to_sym<'tcx>(path: &QPath<'_>) -> Option<&'tcx str> {
     }
 }
 
-/// (Option<T>, Option<U>) -> Option<(T, U)>
-fn transpose<T, U>(lhs: Option<T>, rhs: Option<U>) -> Option<(T, U)> {
-    match (lhs, rhs) {
-        (Some(l), Some(r)) => Some((l, r)),
-        _ => None,
-    }
-}
-
 /// Will return the expressions as if they were expr1 <= expr2
 fn normalize_le_ge<'a>(op: &BinOp, left: &'a Expr<'a>, right: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> {
     match op.node {
diff --git a/src/tools/clippy/clippy_lints/src/consts.rs b/src/tools/clippy/clippy_lints/src/consts.rs
index 81ddc8c0067..22c5acca064 100644
--- a/src/tools/clippy/clippy_lints/src/consts.rs
+++ b/src/tools/clippy/clippy_lints/src/consts.rs
@@ -254,11 +254,11 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
                     if let ["core", "num", int_impl, "max_value"] = *def_path;
                     then {
                        let value = match int_impl {
-                           "<impl i8>" => i8::max_value() as u128,
-                           "<impl i16>" => i16::max_value() as u128,
-                           "<impl i32>" => i32::max_value() as u128,
-                           "<impl i64>" => i64::max_value() as u128,
-                           "<impl i128>" => i128::max_value() as u128,
+                           "<impl i8>" => i8::MAX as u128,
+                           "<impl i16>" => i16::MAX as u128,
+                           "<impl i32>" => i32::MAX as u128,
+                           "<impl i64>" => i64::MAX as u128,
+                           "<impl i128>" => i128::MAX as u128,
                            _ => return None,
                        };
                        Some(Constant::Int(value))
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 68ec07e2bcb..1cd30ae2c63 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -42,7 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Dereferencing {
     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! {
             if !expr.span.from_expansion();
-            if let ExprKind::MethodCall(ref method_name, _, ref args) = &expr.kind;
+            if let ExprKind::MethodCall(ref method_name, _, ref args, _) = &expr.kind;
             if args.len() == 1;
 
             then {
diff --git a/src/tools/clippy/clippy_lints/src/double_parens.rs b/src/tools/clippy/clippy_lints/src/double_parens.rs
index 05517f6f9f0..1eb380a22cc 100644
--- a/src/tools/clippy/clippy_lints/src/double_parens.rs
+++ b/src/tools/clippy/clippy_lints/src/double_parens.rs
@@ -70,7 +70,7 @@ impl EarlyLintPass for DoubleParens {
                     }
                 }
             },
-            ExprKind::MethodCall(_, ref params) => {
+            ExprKind::MethodCall(_, ref params, _) => {
                 if params.len() == 2 {
                     let param = &params[1];
                     if let ExprKind::Paren(_) = param.kind {
diff --git a/src/tools/clippy/clippy_lints/src/duration_subsec.rs b/src/tools/clippy/clippy_lints/src/duration_subsec.rs
index afefa250638..7171dcef968 100644
--- a/src/tools/clippy/clippy_lints/src/duration_subsec.rs
+++ b/src/tools/clippy/clippy_lints/src/duration_subsec.rs
@@ -42,7 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DurationSubsec {
     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! {
             if let ExprKind::Binary(Spanned { node: BinOpKind::Div, .. }, ref left, ref right) = expr.kind;
-            if let ExprKind::MethodCall(ref method_path, _ , ref args) = left.kind;
+            if let ExprKind::MethodCall(ref method_path, _ , ref args, _) = left.kind;
             if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&args[0])), &paths::DURATION);
             if let Some((Constant::Int(divisor), _)) = constant(cx, cx.tables, right);
             then {
diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs
index 7b332c761a0..f625058b670 100644
--- a/src/tools/clippy/clippy_lints/src/entry.rs
+++ b/src/tools/clippy/clippy_lints/src/entry.rs
@@ -103,7 +103,7 @@ fn check_cond<'a, 'tcx, 'b>(
     check: &'b Expr<'b>,
 ) -> Option<(&'static str, &'b Expr<'b>, &'b Expr<'b>)> {
     if_chain! {
-        if let ExprKind::MethodCall(ref path, _, ref params) = check.kind;
+        if let ExprKind::MethodCall(ref path, _, ref params, _) = check.kind;
         if params.len() >= 2;
         if path.ident.name == sym!(contains_key);
         if let ExprKind::AddrOf(BorrowKind::Ref, _, ref key) = params[1].kind;
@@ -140,7 +140,7 @@ impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> {
 
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         if_chain! {
-            if let ExprKind::MethodCall(ref path, _, ref params) = expr.kind;
+            if let ExprKind::MethodCall(ref path, _, ref params, _) = expr.kind;
             if params.len() == 3;
             if path.ident.name == sym!(insert);
             if get_item_name(self.cx, self.map) == get_item_name(self.cx, &params[0]);
diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs
index a1fed3fb6e2..12b62f5cf97 100644
--- a/src/tools/clippy/clippy_lints/src/enum_clike.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs
@@ -65,7 +65,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant {
                                     continue;
                                 }
                             },
-                            ty::Uint(UintTy::Usize) if val > u128::from(u32::max_value()) => {},
+                            ty::Uint(UintTy::Usize) if val > u128::from(u32::MAX) => {},
                             _ => continue,
                         }
                         span_lint(
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index d093025fd3d..a889856de27 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -71,7 +71,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaReduction {
         }
 
         match expr.kind {
-            ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args) => {
+            ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) => {
                 for arg in args {
                     check_closure(cx, arg)
                 }
@@ -120,7 +120,7 @@ fn check_closure(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
         );
 
         if_chain!(
-            if let ExprKind::MethodCall(ref path, _, ref args) = ex.kind;
+            if let ExprKind::MethodCall(ref path, _, ref args, _) = ex.kind;
 
             // Not the same number of arguments, there is no way the closure is the same as the function return;
             if args.len() == decl.inputs.len();
diff --git a/src/tools/clippy/clippy_lints/src/explicit_write.rs b/src/tools/clippy/clippy_lints/src/explicit_write.rs
index 320121b2771..7269e2b52c2 100644
--- a/src/tools/clippy/clippy_lints/src/explicit_write.rs
+++ b/src/tools/clippy/clippy_lints/src/explicit_write.rs
@@ -32,11 +32,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExplicitWrite {
     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! {
             // match call to unwrap
-            if let ExprKind::MethodCall(ref unwrap_fun, _, ref unwrap_args) = expr.kind;
+            if let ExprKind::MethodCall(ref unwrap_fun, _, ref unwrap_args, _) = expr.kind;
             if unwrap_fun.ident.name == sym!(unwrap);
             // match call to write_fmt
             if !unwrap_args.is_empty();
-            if let ExprKind::MethodCall(ref write_fun, _, write_args) =
+            if let ExprKind::MethodCall(ref write_fun, _, write_args, _) =
                 unwrap_args[0].kind;
             if write_fun.ident.name == sym!(write_fmt);
             // match calls to std::io::stdout() / std::io::stderr ()
diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
index 3a912d92837..ad4f66c52c2 100644
--- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
@@ -301,7 +301,7 @@ fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
         if cx.tables.expr_ty(lhs).is_floating_point();
         if let Some((value, _)) = constant(cx, cx.tables, rhs);
         if F32(1.0) == value || F64(1.0) == value;
-        if let ExprKind::MethodCall(ref path, _, ref method_args) = lhs.kind;
+        if let ExprKind::MethodCall(ref path, _, ref method_args, _) = lhs.kind;
         if cx.tables.expr_ty(&method_args[0]).is_floating_point();
         if path.ident.name.as_str() == "exp";
         then {
@@ -481,7 +481,7 @@ fn check_custom_abs(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic {
     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
-        if let ExprKind::MethodCall(ref path, _, args) = &expr.kind {
+        if let ExprKind::MethodCall(ref path, _, args, _) = &expr.kind {
             let recv_ty = cx.tables.expr_ty(&args[0]);
 
             if recv_ty.is_floating_point() {
diff --git a/src/tools/clippy/clippy_lints/src/format.rs b/src/tools/clippy/clippy_lints/src/format.rs
index 1530538aa7d..4cae5ca2c43 100644
--- a/src/tools/clippy/clippy_lints/src/format.rs
+++ b/src/tools/clippy/clippy_lints/src/format.rs
@@ -104,7 +104,7 @@ fn on_argumentv1_new<'a, 'tcx>(
                 }
             } else {
                 let snip = snippet(cx, format_args.span, "<arg>");
-                if let ExprKind::MethodCall(ref path, _, _) = format_args.kind {
+                if let ExprKind::MethodCall(ref path, _, _, _) = format_args.kind {
                     if path.ident.name == sym!(to_string) {
                         return Some(format!("{}", snip));
                     }
diff --git a/src/tools/clippy/clippy_lints/src/functions.rs b/src/tools/clippy/clippy_lints/src/functions.rs
index 325b6cf32a3..991d129e8f0 100644
--- a/src/tools/clippy/clippy_lints/src/functions.rs
+++ b/src/tools/clippy/clippy_lints/src/functions.rs
@@ -556,7 +556,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
                     }
                 }
             },
-            hir::ExprKind::MethodCall(_, _, args) => {
+            hir::ExprKind::MethodCall(_, _, args, _) => {
                 let def_id = self.tables.type_dependent_def_id(expr.hir_id).unwrap();
                 let base_type = self.cx.tcx.type_of(def_id);
 
@@ -610,7 +610,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> {
             return;
         }
         match expr.kind {
-            Call(_, args) | MethodCall(_, _, args) => {
+            Call(_, args) | MethodCall(_, _, args, _) => {
                 let mut tys = FxHashSet::default();
                 for arg in args {
                     let def_id = arg.hir_id.owner.to_def_id();
diff --git a/src/tools/clippy/clippy_lints/src/get_last_with_len.rs b/src/tools/clippy/clippy_lints/src/get_last_with_len.rs
index c32e0a2290d..3629ba623ce 100644
--- a/src/tools/clippy/clippy_lints/src/get_last_with_len.rs
+++ b/src/tools/clippy/clippy_lints/src/get_last_with_len.rs
@@ -47,7 +47,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for GetLastWithLen {
     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! {
             // Is a method call
-            if let ExprKind::MethodCall(ref path, _, ref args) = expr.kind;
+            if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind;
 
             // Method name is "get"
             if path.ident.name == sym!(get);
@@ -69,7 +69,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for GetLastWithLen {
             ) = &get_index_arg.kind;
 
             // LHS of subtraction is "x.len()"
-            if let ExprKind::MethodCall(arg_lhs_path, _, lhs_args) = &lhs.kind;
+            if let ExprKind::MethodCall(arg_lhs_path, _, lhs_args, _) = &lhs.kind;
             if arg_lhs_path.ident.name == sym!(len);
             if let Some(arg_lhs_struct) = lhs_args.get(0);
 
diff --git a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs
index ae92a96d163..04d17c91d63 100644
--- a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs
+++ b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs
@@ -147,7 +147,7 @@ impl<'tcx, 'l> ArmVisitor<'tcx, 'l> {
 
 fn is_mutex_lock_call<'a>(cx: &LateContext<'a, '_>, expr: &'a Expr<'_>) -> Option<&'a Expr<'a>> {
     if_chain! {
-        if let ExprKind::MethodCall(path, _span, args) = &expr.kind;
+        if let ExprKind::MethodCall(path, _span, args, _) = &expr.kind;
         if path.ident.to_string() == "lock";
         let ty = cx.tables.expr_ty(&args[0]);
         if is_type_diagnostic_item(cx, ty, sym!(mutex_type));
diff --git a/src/tools/clippy/clippy_lints/src/if_let_some_result.rs b/src/tools/clippy/clippy_lints/src/if_let_some_result.rs
index 9b13f760924..6a1fcdd1ce4 100644
--- a/src/tools/clippy/clippy_lints/src/if_let_some_result.rs
+++ b/src/tools/clippy/clippy_lints/src/if_let_some_result.rs
@@ -42,7 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OkIfLet {
         if_chain! { //begin checking variables
             if let ExprKind::Match(ref op, ref body, source) = expr.kind; //test if expr is a match
             if let MatchSource::IfLetDesugar { .. } = source; //test if it is an If Let
-            if let ExprKind::MethodCall(_, ok_span, ref result_types) = op.kind; //check is expr.ok() has type Result<T,E>.ok()
+            if let ExprKind::MethodCall(_, ok_span, ref result_types, _) = op.kind; //check is expr.ok() has type Result<T,E>.ok(, _)
             if let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _)  = body[0].pat.kind; //get operation
             if method_chain_args(op, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized;
             if is_type_diagnostic_item(cx, cx.tables.expr_ty(&result_types[0]), sym!(result_type));
diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
index cd989c0ea6f..a860a9def24 100644
--- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
@@ -142,7 +142,7 @@ const HEURISTICS: [(&str, usize, Heuristic, Finiteness); 19] = [
 
 fn is_infinite(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Finiteness {
     match expr.kind {
-        ExprKind::MethodCall(ref method, _, ref args) => {
+        ExprKind::MethodCall(ref method, _, ref args, _) => {
             for &(name, len, heuristic, cap) in &HEURISTICS {
                 if method.ident.name.as_str() == name && args.len() == len {
                     return (match heuristic {
@@ -218,7 +218,7 @@ const INFINITE_COLLECTORS: [&[&str]; 8] = [
 
 fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Finiteness {
     match expr.kind {
-        ExprKind::MethodCall(ref method, _, ref args) => {
+        ExprKind::MethodCall(ref method, _, ref args, _) => {
             for &(name, len) in &COMPLETING_METHODS {
                 if method.ident.name.as_str() == name && args.len() == len {
                     return is_infinite(cx, &args[0]);
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index f5bfede75a7..13e85fda8ff 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -211,7 +211,7 @@ fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item<'_>, impl_items: &[Imp
 }
 
 fn check_cmp(cx: &LateContext<'_, '_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>, op: &str, compare_to: u32) {
-    if let (&ExprKind::MethodCall(ref method_path, _, ref args), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind) {
+    if let (&ExprKind::MethodCall(ref method_path, _, ref args, _), &ExprKind::Lit(ref lit)) = (&method.kind, &lit.kind) {
         // check if we are in an is_empty() method
         if let Some(name) = get_item_name(cx, method) {
             if name.as_str() == "is_empty" {
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index d80ad47ab24..318d0b69d57 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -379,7 +379,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
             TyKind::Path(ref path) => {
                 self.collect_anonymous_lifetimes(path, ty);
             },
-            TyKind::Def(item, _) => {
+            TyKind::OpaqueDef(item, _) => {
                 let map = self.cx.tcx.hir();
                 if let ItemKind::OpaqueTy(ref exist_ty) = map.expect_item(item.id).kind {
                     for bound in exist_ty.bounds {
diff --git a/src/tools/clippy/clippy_lints/src/loops.rs b/src/tools/clippy/clippy_lints/src/loops.rs
index 57c62d73964..771bc8d0558 100644
--- a/src/tools/clippy/clippy_lints/src/loops.rs
+++ b/src/tools/clippy/clippy_lints/src/loops.rs
@@ -526,7 +526,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Loops {
             let pat = &arms[0].pat.kind;
             if let (
                 &PatKind::TupleStruct(ref qpath, ref pat_args, _),
-                &ExprKind::MethodCall(ref method_path, _, ref method_args),
+                &ExprKind::MethodCall(ref method_path, _, ref method_args, _),
             ) = (pat, &match_expr.kind)
             {
                 let iter_expr = &method_args[0];
@@ -654,7 +654,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
         | ExprKind::Struct(_, _, Some(ref e))
         | ExprKind::Repeat(ref e, _)
         | ExprKind::DropTemps(ref e) => never_loop_expr(e, main_loop_id),
-        ExprKind::Array(ref es) | ExprKind::MethodCall(_, _, ref es) | ExprKind::Tup(ref es) => {
+        ExprKind::Array(ref es) | ExprKind::MethodCall(_, _, ref es, _) | ExprKind::Tup(ref es) => {
             never_loop_expr_all(&mut es.iter(), main_loop_id)
         },
         ExprKind::Call(ref e, ref es) => never_loop_expr_all(&mut once(&**e).chain(es.iter()), main_loop_id),
@@ -806,7 +806,7 @@ fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'_>) -> bool {
 
 fn fetch_cloned_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
     if_chain! {
-        if let ExprKind::MethodCall(method, _, args) = expr.kind;
+        if let ExprKind::MethodCall(method, _, args, _) = expr.kind;
         if method.ident.name == sym!(clone);
         if args.len() == 1;
         if let Some(arg) = args.get(0);
@@ -915,7 +915,7 @@ fn build_manual_memcpy_suggestion<'a, 'tcx>(
 
     let print_limit = |end: &Expr<'_>, offset: Offset, var: &Expr<'_>| {
         if_chain! {
-            if let ExprKind::MethodCall(method, _, len_args) = end.kind;
+            if let ExprKind::MethodCall(method, _, len_args, _) = end.kind;
             if method.ident.name == sym!(len);
             if len_args.len() == 1;
             if let Some(arg) = len_args.get(0);
@@ -1190,7 +1190,7 @@ fn check_for_loop_range<'a, 'tcx>(
 
 fn is_len_call(expr: &Expr<'_>, var: Name) -> bool {
     if_chain! {
-        if let ExprKind::MethodCall(ref method, _, ref len_args) = expr.kind;
+        if let ExprKind::MethodCall(ref method, _, ref len_args, _) = expr.kind;
         if len_args.len() == 1;
         if method.ident.name == sym!(len);
         if let ExprKind::Path(QPath::Resolved(_, ref path)) = len_args[0].kind;
@@ -1244,7 +1244,7 @@ fn lint_iter_method(cx: &LateContext<'_, '_>, args: &[Expr<'_>], arg: &Expr<'_>,
 
 fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>, expr: &Expr<'_>) {
     let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used
-    if let ExprKind::MethodCall(ref method, _, ref args) = arg.kind {
+    if let ExprKind::MethodCall(ref method, _, ref args, _) = arg.kind {
         // just the receiver, no arguments
         if args.len() == 1 {
             let method_name = &*method.ident.as_str();
@@ -1718,7 +1718,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         if_chain! {
             // a range index op
-            if let ExprKind::MethodCall(ref meth, _, ref args) = expr.kind;
+            if let ExprKind::MethodCall(ref meth, _, ref args, _) = expr.kind;
             if (meth.ident.name == sym!(index) && match_trait_method(self.cx, expr, &paths::INDEX))
                 || (meth.ident.name == sym!(index_mut) && match_trait_method(self.cx, expr, &paths::INDEX_MUT));
             if !self.check(&args[1], &args[0], expr);
@@ -1776,7 +1776,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
                     self.visit_expr(expr);
                 }
             },
-            ExprKind::MethodCall(_, _, args) => {
+            ExprKind::MethodCall(_, _, args, _) => {
                 let def_id = self.cx.tables.type_dependent_def_id(expr.hir_id).unwrap();
                 for (ty, expr) in self.cx.tcx.fn_sig(def_id).inputs().skip_binder().iter().zip(args) {
                     self.prefer_mutable = false;
@@ -2369,8 +2369,8 @@ const NEEDLESS_COLLECT_MSG: &str = "avoid using `collect()` when not needed";
 
 fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'a, 'tcx>) {
     if_chain! {
-        if let ExprKind::MethodCall(ref method, _, ref args) = expr.kind;
-        if let ExprKind::MethodCall(ref chain_method, _, _) = args[0].kind;
+        if let ExprKind::MethodCall(ref method, _, ref args, _) = expr.kind;
+        if let ExprKind::MethodCall(ref chain_method, _, _, _) = args[0].kind;
         if chain_method.ident.name == sym!(collect) && match_trait_method(cx, &args[0], &paths::ITERATOR);
         if let Some(ref generic_args) = chain_method.args;
         if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0);
@@ -2437,7 +2437,7 @@ fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'a, '
 
 fn shorten_span(expr: &Expr<'_>, target_fn_name: Symbol) -> Span {
     let mut current_expr = expr;
-    while let ExprKind::MethodCall(ref path, ref span, ref args) = current_expr.kind {
+    while let ExprKind::MethodCall(ref path, ref span, ref args, _) = current_expr.kind {
         if path.ident.name == target_fn_name {
             return expr.span.with_lo(span.lo());
         }
diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
index cb72a240582..03ab274d9ca 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -99,7 +99,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ManualAsyncFn {
 
 fn future_trait_ref<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &'tcx Ty<'tcx>) -> Option<&'tcx TraitRef<'tcx>> {
     if_chain! {
-        if let TyKind::Def(item_id, _) = ty.kind;
+        if let TyKind::OpaqueDef(item_id, _) = ty.kind;
         let item = cx.tcx.hir().item(item_id.id);
         if let ItemKind::OpaqueTy(opaque) = &item.kind;
         if opaque.bounds.len() == 1;
diff --git a/src/tools/clippy/clippy_lints/src/map_clone.rs b/src/tools/clippy/clippy_lints/src/map_clone.rs
index d5adf6b0f0d..8f4fdc685ef 100644
--- a/src/tools/clippy/clippy_lints/src/map_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/map_clone.rs
@@ -49,7 +49,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MapClone {
         }
 
         if_chain! {
-            if let hir::ExprKind::MethodCall(ref method, _, ref args) = e.kind;
+            if let hir::ExprKind::MethodCall(ref method, _, ref args, _) = e.kind;
             if args.len() == 2;
             if method.ident.as_str() == "map";
             let ty = cx.tables.expr_ty(&args[0]);
@@ -75,7 +75,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MapClone {
                                     }
                                 }
                             },
-                            hir::ExprKind::MethodCall(ref method, _, ref obj) => {
+                            hir::ExprKind::MethodCall(ref method, _, ref obj, _) => {
                                 if ident_eq(name, &obj[0]) && method.ident.as_str() == "clone"
                                     && match_trait_method(cx, closure_expr, &paths::CLONE_TRAIT) {
 
diff --git a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
index fecd91c7814..8f4b674c04f 100644
--- a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
@@ -125,7 +125,7 @@ fn reduce_unit_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a hir::Expr<'_>)
     }
 
     match expr.kind {
-        hir::ExprKind::Call(_, _) | hir::ExprKind::MethodCall(_, _, _) => {
+        hir::ExprKind::Call(_, _) | hir::ExprKind::MethodCall(_, _, _, _) => {
             // Calls can't be reduced any more
             Some(expr.span)
         },
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 214cf0c130f..f25a9782813 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -1429,7 +1429,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
         }
 
         match expr.kind {
-            hir::ExprKind::MethodCall(ref method_call, ref method_span, ref args) => {
+            hir::ExprKind::MethodCall(ref method_call, ref method_span, ref args, _) => {
                 lint_or_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args);
                 lint_expect_fun_call(cx, expr, *method_span, &method_call.ident.as_str(), args);
 
@@ -1677,7 +1677,7 @@ fn lint_or_fun_call<'a, 'tcx>(
         or_has_args: bool,
         span: Span,
     ) {
-        if let hir::ExprKind::MethodCall(ref path, _, ref args) = &arg.kind {
+        if let hir::ExprKind::MethodCall(ref path, _, ref args, _) = &arg.kind {
             if path.ident.as_str() == "len" {
                 let ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0]));
 
@@ -1751,7 +1751,7 @@ fn lint_or_fun_call<'a, 'tcx>(
                     );
                 }
             },
-            hir::ExprKind::MethodCall(_, span, ref or_args) => check_general_case(
+            hir::ExprKind::MethodCall(_, span, ref or_args, _) => check_general_case(
                 cx,
                 name,
                 method_span,
@@ -1782,7 +1782,7 @@ fn lint_expect_fun_call(
         loop {
             arg_root = match &arg_root.kind {
                 hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, expr) => expr,
-                hir::ExprKind::MethodCall(method_name, _, call_args) => {
+                hir::ExprKind::MethodCall(method_name, _, call_args, _) => {
                     if call_args.len() == 1
                         && (method_name.ident.name == sym!(as_str) || method_name.ident.name == sym!(as_ref))
                         && {
@@ -2002,7 +2002,7 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, arg: &hir:
                     // &*x is a nop, &x.clone() is not
                     hir::ExprKind::AddrOf(..) => return,
                     // (*x).func() is useless, x.clone().func() can work in case func borrows mutably
-                    hir::ExprKind::MethodCall(_, _, parent_args) if expr.hir_id == parent_args[0].hir_id => return,
+                    hir::ExprKind::MethodCall(_, _, parent_args, _) if expr.hir_id == parent_args[0].hir_id => return,
 
                     _ => {},
                 },
@@ -2478,7 +2478,7 @@ fn derefs_to_slice<'a, 'tcx>(
         }
     }
 
-    if let hir::ExprKind::MethodCall(ref path, _, ref args) = expr.kind {
+    if let hir::ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind {
         if path.ident.name == sym!(iter) && may_slice(cx, cx.tables.expr_ty(&args[0])) {
             Some(&args[0])
         } else {
@@ -3182,7 +3182,7 @@ fn lint_asref(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, call_name: &str, a
             // allow the `as_ref` or `as_mut` if it is followed by another method call
             if_chain! {
                 if let Some(parent) = get_parent_expr(cx, expr);
-                if let hir::ExprKind::MethodCall(_, ref span, _) = parent.kind;
+                if let hir::ExprKind::MethodCall(_, ref span, _, _) = parent.kind;
                 if span != &expr.span;
                 then {
                     return;
@@ -3310,7 +3310,7 @@ fn lint_option_as_ref_deref<'a, 'tcx>(
             let closure_expr = remove_blocks(&closure_body.value);
 
             match &closure_expr.kind {
-                hir::ExprKind::MethodCall(_, _, args) => {
+                hir::ExprKind::MethodCall(_, _, args, _) => {
                     if_chain! {
                         if args.len() == 1;
                         if let hir::ExprKind::Path(qpath) = &args[0].kind;
diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs
index f513161bbbc..a0947608e60 100644
--- a/src/tools/clippy/clippy_lints/src/misc.rs
+++ b/src/tools/clippy/clippy_lints/src/misc.rs
@@ -545,7 +545,7 @@ fn is_signum(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
     }
 
     if_chain! {
-        if let ExprKind::MethodCall(ref method_name, _, ref expressions) = expr.kind;
+        if let ExprKind::MethodCall(ref method_name, _, ref expressions, _) = expr.kind;
         if sym!(signum) == method_name.ident.name;
         // Check that the receiver of the signum() is a float (expressions[0] is the receiver of
         // the method call)
@@ -572,7 +572,7 @@ fn is_array(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
 
 fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr<'_>, other: &Expr<'_>) {
     let (arg_ty, snip) = match expr.kind {
-        ExprKind::MethodCall(.., ref args) if args.len() == 1 => {
+        ExprKind::MethodCall(.., ref args, _) if args.len() == 1 => {
             if match_trait_method(cx, expr, &paths::TO_STRING) || match_trait_method(cx, expr, &paths::TO_OWNED) {
                 (cx.tables.expr_ty_adjusted(&args[0]), snippet(cx, args[0].span, ".."))
             } else {
diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs
index 2eefb6bbaf4..0fd1e87f9e4 100644
--- a/src/tools/clippy/clippy_lints/src/missing_doc.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs
@@ -187,7 +187,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
             hir::ImplItemKind::Const(..) => "an associated constant",
             hir::ImplItemKind::Fn(..) => "a method",
             hir::ImplItemKind::TyAlias(_) => "an associated type",
-            hir::ImplItemKind::OpaqueTy(_) => "an existential type",
         };
         self.check_missing_docs_attrs(cx, &impl_item.attrs, impl_item.span, desc);
     }
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index 3ad3d5aee4d..1802470b184 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -142,7 +142,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline {
 
         let desc = match impl_item.kind {
             hir::ImplItemKind::Fn(..) => "a method",
-            hir::ImplItemKind::Const(..) | hir::ImplItemKind::TyAlias(_) | hir::ImplItemKind::OpaqueTy(_) => return,
+            hir::ImplItemKind::Const(..) | hir::ImplItemKind::TyAlias(_) => return,
         };
 
         let def_id = cx.tcx.hir().local_def_id(impl_item.hir_id);
diff --git a/src/tools/clippy/clippy_lints/src/mut_reference.rs b/src/tools/clippy/clippy_lints/src/mut_reference.rs
index 58a8e1a1064..7fcf15f8acb 100644
--- a/src/tools/clippy/clippy_lints/src/mut_reference.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_reference.rs
@@ -42,7 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed {
                     );
                 }
             },
-            ExprKind::MethodCall(ref path, _, ref arguments) => {
+            ExprKind::MethodCall(ref path, _, ref arguments, _) => {
                 let def_id = cx.tables.type_dependent_def_id(e.hir_id).unwrap();
                 let substs = cx.tables.node_substs(e.hir_id);
                 let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs);
diff --git a/src/tools/clippy/clippy_lints/src/open_options.rs b/src/tools/clippy/clippy_lints/src/open_options.rs
index 9d3b67988db..2d4629b683f 100644
--- a/src/tools/clippy/clippy_lints/src/open_options.rs
+++ b/src/tools/clippy/clippy_lints/src/open_options.rs
@@ -29,7 +29,7 @@ declare_lint_pass!(OpenOptions => [NONSENSICAL_OPEN_OPTIONS]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OpenOptions {
     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) {
-        if let ExprKind::MethodCall(ref path, _, ref arguments) = e.kind {
+        if let ExprKind::MethodCall(ref path, _, ref arguments, _) = e.kind {
             let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&arguments[0]));
             if path.ident.name == sym!(open) && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) {
                 let mut options = Vec::new();
@@ -57,7 +57,7 @@ enum OpenOption {
 }
 
 fn get_open_options(cx: &LateContext<'_, '_>, argument: &Expr<'_>, options: &mut Vec<(OpenOption, Argument)>) {
-    if let ExprKind::MethodCall(ref path, _, ref arguments) = argument.kind {
+    if let ExprKind::MethodCall(ref path, _, ref arguments, _) = argument.kind {
         let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&arguments[0]));
 
         // Only proceed if this is a call on some object of type std::fs::OpenOptions
diff --git a/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs b/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs
index 66dfa20edb5..fd653044a1b 100644
--- a/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs
@@ -35,7 +35,7 @@ declare_lint_pass!(OptionEnvUnwrap => [OPTION_ENV_UNWRAP]);
 impl EarlyLintPass for OptionEnvUnwrap {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
         if_chain! {
-            if let ExprKind::MethodCall(path_segment, args) = &expr.kind;
+            if let ExprKind::MethodCall(path_segment, args, _) = &expr.kind;
             let method_name = path_segment.ident.as_str();
             if method_name == "expect" || method_name == "unwrap";
             if let ExprKind::Call(caller, _) = &args[0].kind;
diff --git a/src/tools/clippy/clippy_lints/src/path_buf_push_overwrite.rs b/src/tools/clippy/clippy_lints/src/path_buf_push_overwrite.rs
index bdbaf2695c8..88ad1e0914f 100644
--- a/src/tools/clippy/clippy_lints/src/path_buf_push_overwrite.rs
+++ b/src/tools/clippy/clippy_lints/src/path_buf_push_overwrite.rs
@@ -43,7 +43,7 @@ declare_lint_pass!(PathBufPushOverwrite => [PATH_BUF_PUSH_OVERWRITE]);
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PathBufPushOverwrite {
     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! {
-            if let ExprKind::MethodCall(ref path, _, ref args) = expr.kind;
+            if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind;
             if path.ident.name == sym!(push);
             if args.len() == 2;
             if match_type(cx, walk_ptrs_ty(cx.tables.expr_ty(&args[0])), &paths::PATH_BUF);
diff --git a/src/tools/clippy/clippy_lints/src/precedence.rs b/src/tools/clippy/clippy_lints/src/precedence.rs
index cc783baa687..7dce23dd223 100644
--- a/src/tools/clippy/clippy_lints/src/precedence.rs
+++ b/src/tools/clippy/clippy_lints/src/precedence.rs
@@ -103,7 +103,7 @@ impl EarlyLintPass for Precedence {
         }
 
         if let ExprKind::Unary(UnOp::Neg, ref rhs) = expr.kind {
-            if let ExprKind::MethodCall(ref path_segment, ref args) = rhs.kind {
+            if let ExprKind::MethodCall(ref path_segment, ref args, _) = rhs.kind {
                 let path_segment_str = path_segment.ident.name.as_str();
                 if let Some(slf) = args.first() {
                     if let ExprKind::Lit(ref lit) = slf.kind {
diff --git a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs
index ffc59d43750..d23d7e59b73 100644
--- a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs
@@ -90,7 +90,7 @@ fn expr_as_ptr_offset_call<'a, 'tcx>(
     cx: &LateContext<'a, 'tcx>,
     expr: &'tcx Expr<'_>,
 ) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Method)> {
-    if let ExprKind::MethodCall(ref path_segment, _, ref args) = expr.kind {
+    if let ExprKind::MethodCall(ref path_segment, _, ref args, _) = expr.kind {
         if is_expr_ty_raw_ptr(cx, &args[0]) {
             if path_segment.ident.name == sym!(offset) {
                 return Some((&args[0], &args[1], Method::Offset));
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index e4361b00fb4..3591972fe08 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -50,7 +50,7 @@ impl QuestionMark {
     fn check_is_none_and_early_return_none(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
         if_chain! {
             if let Some((if_expr, body, else_)) = higher::if_block(&expr);
-            if let ExprKind::MethodCall(segment, _, args) = &if_expr.kind;
+            if let ExprKind::MethodCall(segment, _, args, _) = &if_expr.kind;
             if segment.ident.name == sym!(is_none);
             if Self::expression_returns_none(cx, body);
             if let Some(subject) = args.get(0);
diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs
index 52e540d4e00..fcd02a196e7 100644
--- a/src/tools/clippy/clippy_lints/src/ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/ranges.rs
@@ -129,20 +129,20 @@ declare_lint_pass!(Ranges => [
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Ranges {
     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
-        if let ExprKind::MethodCall(ref path, _, ref args) = expr.kind {
+        if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind {
             let name = path.ident.as_str();
             if name == "zip" && args.len() == 2 {
                 let iter = &args[0].kind;
                 let zip_arg = &args[1];
                 if_chain! {
                     // `.iter()` call
-                    if let ExprKind::MethodCall(ref iter_path, _, ref iter_args ) = *iter;
+                    if let ExprKind::MethodCall(ref iter_path, _, ref iter_args , _) = *iter;
                     if iter_path.ident.name == sym!(iter);
                     // range expression in `.zip()` call: `0..x.len()`
                     if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(cx, zip_arg);
                     if is_integer_const(cx, start, 0);
                     // `.len()` call
-                    if let ExprKind::MethodCall(ref len_path, _, ref len_args) = end.kind;
+                    if let ExprKind::MethodCall(ref len_path, _, ref len_args, _) = end.kind;
                     if len_path.ident.name == sym!(len) && len_args.len() == 1;
                     // `.iter()` and `.len()` called on same `Path`
                     if let ExprKind::Path(QPath::Resolved(_, ref iter_path)) = iter_args[0].kind;
diff --git a/src/tools/clippy/clippy_lints/src/redundant_pattern_matching.rs b/src/tools/clippy/clippy_lints/src/redundant_pattern_matching.rs
index 7ee298e9833..f16b916441a 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_pattern_matching.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_pattern_matching.rs
@@ -89,7 +89,7 @@ fn find_sugg_for_if_let<'a, 'tcx>(
     // check that `while_let_on_iterator` lint does not trigger
     if_chain! {
         if keyword == "while";
-        if let ExprKind::MethodCall(method_path, _, _) = op.kind;
+        if let ExprKind::MethodCall(method_path, _, _, _) = op.kind;
         if method_path.ident.name == sym!(next);
         if match_trait_method(cx, op, &paths::ITERATOR);
         then {
diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
index a7c4f2c2291..44c9cc19cfb 100644
--- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
+++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
@@ -207,7 +207,7 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
     fn search_slow_extend_filling(&mut self, expr: &'tcx Expr<'_>) {
         if_chain! {
             if self.initialization_found;
-            if let ExprKind::MethodCall(ref path, _, ref args) = expr.kind;
+            if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind;
             if let ExprKind::Path(ref qpath_subj) = args[0].kind;
             if match_qpath(&qpath_subj, &[&*self.vec_alloc.variable_name.as_str()]);
             if path.ident.name == sym!(extend);
@@ -224,7 +224,7 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
     fn search_slow_resize_filling(&mut self, expr: &'tcx Expr<'_>) {
         if_chain! {
             if self.initialization_found;
-            if let ExprKind::MethodCall(ref path, _, ref args) = expr.kind;
+            if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind;
             if let ExprKind::Path(ref qpath_subj) = args[0].kind;
             if match_qpath(&qpath_subj, &[&*self.vec_alloc.variable_name.as_str()]);
             if path.ident.name == sym!(resize);
@@ -246,7 +246,7 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
     /// Returns `true` if give expression is `repeat(0).take(...)`
     fn is_repeat_take(&self, expr: &Expr<'_>) -> bool {
         if_chain! {
-            if let ExprKind::MethodCall(ref take_path, _, ref take_args) = expr.kind;
+            if let ExprKind::MethodCall(ref take_path, _, ref take_args, _) = expr.kind;
             if take_path.ident.name == sym!(take);
 
             // Check that take is applied to `repeat(0)`
diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs
index f84566ef707..d8e4bff3d70 100644
--- a/src/tools/clippy/clippy_lints/src/strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strings.rs
@@ -164,7 +164,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes {
         use rustc_ast::ast::LitKind;
 
         if_chain! {
-            if let ExprKind::MethodCall(path, _, args) = &e.kind;
+            if let ExprKind::MethodCall(path, _, args, _) = &e.kind;
             if path.ident.name == sym!(as_bytes);
             if let ExprKind::Lit(lit) = &args[0].kind;
             if let LitKind::Str(lit_content, _) = &lit.node;
diff --git a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs
index c6302ca03d9..4f132c6db76 100644
--- a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs
+++ b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs
@@ -34,12 +34,12 @@ declare_lint_pass!(ToDigitIsSome => [TO_DIGIT_IS_SOME]);
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ToDigitIsSome {
     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) {
         if_chain! {
-            if let hir::ExprKind::MethodCall(is_some_path, _, is_some_args) = &expr.kind;
+            if let hir::ExprKind::MethodCall(is_some_path, _, is_some_args, _) = &expr.kind;
             if is_some_path.ident.name.as_str() == "is_some";
             if let [to_digit_expr] = &**is_some_args;
             then {
                 let match_result = match &to_digit_expr.kind {
-                    hir::ExprKind::MethodCall(to_digits_path, _, to_digit_args) => {
+                    hir::ExprKind::MethodCall(to_digits_path, _, to_digit_args, _) => {
                         if_chain! {
                             if let [char_arg, radix_arg] = &**to_digit_args;
                             if to_digits_path.ident.name.as_str() == "to_digit";
diff --git a/src/tools/clippy/clippy_lints/src/types.rs b/src/tools/clippy/clippy_lints/src/types.rs
index bc5fe44b30f..d59a2f1bae0 100644
--- a/src/tools/clippy/clippy_lints/src/types.rs
+++ b/src/tools/clippy/clippy_lints/src/types.rs
@@ -778,7 +778,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg {
         }
 
         match expr.kind {
-            ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args) => {
+            ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) => {
                 let args_to_recover = args
                     .iter()
                     .filter(|arg| {
@@ -1262,14 +1262,14 @@ fn check_loss_of_sign(cx: &LateContext<'_, '_>, expr: &Expr<'_>, op: &Expr<'_>,
     }
 
     // don't lint for the result of methods that always return non-negative values
-    if let ExprKind::MethodCall(ref path, _, _) = op.kind {
+    if let ExprKind::MethodCall(ref path, _, _, _) = op.kind {
         let mut method_name = path.ident.name.as_str();
         let whitelisted_methods = ["abs", "checked_abs", "rem_euclid", "checked_rem_euclid"];
 
         if_chain! {
             if method_name == "unwrap";
             if let Some(arglist) = method_chain_args(op, &["unwrap"]);
-            if let ExprKind::MethodCall(ref inner_path, _, _) = &arglist[0][0].kind;
+            if let ExprKind::MethodCall(ref inner_path, _, _, _) = &arglist[0][0].kind;
             then {
                 method_name = inner_path.ident.name.as_str();
             }
@@ -1946,18 +1946,18 @@ fn detect_extreme_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_
     let which = match (&ty.kind, cv) {
         (&ty::Bool, Constant::Bool(false)) | (&ty::Uint(_), Constant::Int(0)) => Minimum,
         (&ty::Int(ity), Constant::Int(i))
-            if i == unsext(cx.tcx, i128::min_value() >> (128 - int_bits(cx.tcx, ity)), ity) =>
+            if i == unsext(cx.tcx, i128::MIN >> (128 - int_bits(cx.tcx, ity)), ity) =>
         {
             Minimum
         },
 
         (&ty::Bool, Constant::Bool(true)) => Maximum,
         (&ty::Int(ity), Constant::Int(i))
-            if i == unsext(cx.tcx, i128::max_value() >> (128 - int_bits(cx.tcx, ity)), ity) =>
+            if i == unsext(cx.tcx, i128::MAX >> (128 - int_bits(cx.tcx, ity)), ity) =>
         {
             Maximum
         },
-        (&ty::Uint(uty), Constant::Int(i)) if clip(cx.tcx, u128::max_value(), uty) == i => Maximum,
+        (&ty::Uint(uty), Constant::Int(i)) if clip(cx.tcx, u128::MAX, uty) == i => Maximum,
 
         _ => return None,
     };
@@ -2039,7 +2039,7 @@ impl FullInt {
     fn cmp_s_u(s: i128, u: u128) -> Ordering {
         if s < 0 {
             Ordering::Less
-        } else if u > (i128::max_value() as u128) {
+        } else if u > (i128::MAX as u128) {
             Ordering::Greater
         } else {
             (s as u128).cmp(&u)
@@ -2084,48 +2084,48 @@ fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'_>)
         match pre_cast_ty.kind {
             ty::Int(int_ty) => Some(match int_ty {
                 IntTy::I8 => (
-                    FullInt::S(i128::from(i8::min_value())),
-                    FullInt::S(i128::from(i8::max_value())),
+                    FullInt::S(i128::from(i8::MIN)),
+                    FullInt::S(i128::from(i8::MAX)),
                 ),
                 IntTy::I16 => (
-                    FullInt::S(i128::from(i16::min_value())),
-                    FullInt::S(i128::from(i16::max_value())),
+                    FullInt::S(i128::from(i16::MIN)),
+                    FullInt::S(i128::from(i16::MAX)),
                 ),
                 IntTy::I32 => (
-                    FullInt::S(i128::from(i32::min_value())),
-                    FullInt::S(i128::from(i32::max_value())),
+                    FullInt::S(i128::from(i32::MIN)),
+                    FullInt::S(i128::from(i32::MAX)),
                 ),
                 IntTy::I64 => (
-                    FullInt::S(i128::from(i64::min_value())),
-                    FullInt::S(i128::from(i64::max_value())),
+                    FullInt::S(i128::from(i64::MIN)),
+                    FullInt::S(i128::from(i64::MAX)),
                 ),
-                IntTy::I128 => (FullInt::S(i128::min_value()), FullInt::S(i128::max_value())),
+                IntTy::I128 => (FullInt::S(i128::MIN), FullInt::S(i128::MAX)),
                 IntTy::Isize => (
-                    FullInt::S(isize::min_value() as i128),
-                    FullInt::S(isize::max_value() as i128),
+                    FullInt::S(isize::MIN as i128),
+                    FullInt::S(isize::MAX as i128),
                 ),
             }),
             ty::Uint(uint_ty) => Some(match uint_ty {
                 UintTy::U8 => (
-                    FullInt::U(u128::from(u8::min_value())),
-                    FullInt::U(u128::from(u8::max_value())),
+                    FullInt::U(u128::from(u8::MIN)),
+                    FullInt::U(u128::from(u8::MAX)),
                 ),
                 UintTy::U16 => (
-                    FullInt::U(u128::from(u16::min_value())),
-                    FullInt::U(u128::from(u16::max_value())),
+                    FullInt::U(u128::from(u16::MIN)),
+                    FullInt::U(u128::from(u16::MAX)),
                 ),
                 UintTy::U32 => (
-                    FullInt::U(u128::from(u32::min_value())),
-                    FullInt::U(u128::from(u32::max_value())),
+                    FullInt::U(u128::from(u32::MIN)),
+                    FullInt::U(u128::from(u32::MAX)),
                 ),
                 UintTy::U64 => (
-                    FullInt::U(u128::from(u64::min_value())),
-                    FullInt::U(u128::from(u64::max_value())),
+                    FullInt::U(u128::from(u64::MIN)),
+                    FullInt::U(u128::from(u64::MAX)),
                 ),
-                UintTy::U128 => (FullInt::U(u128::min_value()), FullInt::U(u128::max_value())),
+                UintTy::U128 => (FullInt::U(u128::MIN), FullInt::U(u128::MAX)),
                 UintTy::Usize => (
-                    FullInt::U(usize::min_value() as u128),
-                    FullInt::U(usize::max_value() as u128),
+                    FullInt::U(usize::MIN as u128),
+                    FullInt::U(usize::MAX as u128),
                 ),
             }),
             _ => None,
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs b/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs
index 33d8331c292..e94eebb88e4 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs
@@ -95,7 +95,7 @@ fn mirrored_exprs(
         // The two exprs are method calls.
         // Check to see that the function is the same and the arguments are mirrored
         // This is enough because the receiver of the method is listed in the arguments
-        (ExprKind::MethodCall(left_segment, _, left_args), ExprKind::MethodCall(right_segment, _, right_args)) => {
+        (ExprKind::MethodCall(left_segment, _, left_args, _), ExprKind::MethodCall(right_segment, _, right_args, _)) => {
             left_segment.ident == right_segment.ident
                 && left_args
                     .iter()
@@ -170,7 +170,7 @@ fn mirrored_exprs(
 
 fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger> {
     if_chain! {
-        if let ExprKind::MethodCall(name_ident, _, args) = &expr.kind;
+        if let ExprKind::MethodCall(name_ident, _, args, _) = &expr.kind;
         if let name = name_ident.ident.name.to_ident_string();
         if name == "sort_by" || name == "sort_unstable_by";
         if let [vec, Expr { kind: ExprKind::Closure(_, _, closure_body_id, _, _), .. }] = args;
@@ -180,7 +180,7 @@ fn detect_lint(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<LintTrigger>
             Param { pat: Pat { kind: PatKind::Binding(_, _, left_ident, _), .. }, ..},
             Param { pat: Pat { kind: PatKind::Binding(_, _, right_ident, _), .. }, .. }
         ] = &closure_body.params;
-        if let ExprKind::MethodCall(method_path, _, [ref left_expr, ref right_expr]) = &closure_body.value.kind;
+        if let ExprKind::MethodCall(method_path, _, [ref left_expr, ref right_expr], _) = &closure_body.value.kind;
         if method_path.ident.name.to_ident_string() == "cmp";
         then {
             let (closure_body, closure_arg, reverse) = if mirrored_exprs(
diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
index b85134e3d7a..5f4b5fd9dd9 100644
--- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
@@ -52,7 +52,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount {
                 }
             },
 
-            hir::ExprKind::MethodCall(ref path, _, ref args) => match &*path.ident.as_str() {
+            hir::ExprKind::MethodCall(ref path, _, ref args, _) => match &*path.ident.as_str() {
                 "expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" => {
                     check_method_call(cx, &args[0], expr);
                 },
@@ -65,7 +65,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedIoAmount {
 }
 
 fn check_method_call(cx: &LateContext<'_, '_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>) {
-    if let hir::ExprKind::MethodCall(ref path, _, _) = call.kind {
+    if let hir::ExprKind::MethodCall(ref path, _, _, _) = call.kind {
         let symbol = &*path.ident.as_str();
         let read_trait = match_trait_method(cx, call, &paths::IO_READ);
         let write_trait = match_trait_method(cx, call, &paths::IO_WRITE);
diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs
index 036dd16a224..a6c7b5d405c 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap.rs
@@ -112,7 +112,7 @@ fn collect_unwrap_info<'a, 'tcx>(
         return collect_unwrap_info(cx, expr, branch, !invert);
     } else {
         if_chain! {
-            if let ExprKind::MethodCall(method_name, _, args) = &expr.kind;
+            if let ExprKind::MethodCall(method_name, _, args, _) = &expr.kind;
             if let ExprKind::Path(QPath::Resolved(None, path)) = &args[0].kind;
             let ty = cx.tables.expr_ty(&args[0]);
             let name = method_name.ident.as_str();
@@ -166,7 +166,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
         } else {
             // find `unwrap[_err]()` calls:
             if_chain! {
-                if let ExprKind::MethodCall(ref method_name, _, ref args) = expr.kind;
+                if let ExprKind::MethodCall(ref method_name, _, ref args, _) = expr.kind;
                 if let ExprKind::Path(QPath::Resolved(None, ref path)) = args[0].kind;
                 if [sym!(unwrap), sym!(unwrap_err)].contains(&method_name.ident.name);
                 let call_to_unwrap = method_name.ident.name == sym!(unwrap);
diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
index 141035a980a..78d249482d5 100644
--- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
@@ -61,7 +61,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion {
                 }
             },
 
-            ExprKind::MethodCall(ref name, .., ref args) => {
+            ExprKind::MethodCall(ref name, .., ref args, _) => {
                 if match_trait_method(cx, e, &paths::INTO) && &*name.ident.as_str() == "into" {
                     let a = cx.tables.expr_ty(e);
                     let b = cx.tables.expr_ty(&args[0]);
diff --git a/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs b/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs
index dcf09da198e..e60e2a81e07 100755
--- a/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs
@@ -120,7 +120,7 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
         (Array(l), Array(r)) | (Tup(l), Tup(r)) => over(l, r, |l, r| eq_expr(l, r)),
         (Repeat(le, ls), Repeat(re, rs)) => eq_expr(le, re) && eq_expr(&ls.value, &rs.value),
         (Call(lc, la), Call(rc, ra)) => eq_expr(lc, rc) && over(la, ra, |l, r| eq_expr(l, r)),
-        (MethodCall(lc, la), MethodCall(rc, ra)) => eq_path_seg(lc, rc) && over(la, ra, |l, r| eq_expr(l, r)),
+        (MethodCall(lc, la, _), MethodCall(rc, ra, _)) => eq_path_seg(lc, rc) && over(la, ra, |l, r| eq_expr(l, r)),
         (Binary(lo, ll, lr), Binary(ro, rl, rr)) => lo.node == ro.node && eq_expr(ll, rl) && eq_expr(lr, rr),
         (Unary(lo, l), Unary(ro, r)) => mem::discriminant(lo) == mem::discriminant(ro) && eq_expr(l, r),
         (Lit(l), Lit(r)) => l.kind == r.kind,
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index bbcf396eef7..8b58bbb5e65 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -250,8 +250,8 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                     self.visit_expr(arg);
                 }
             },
-            ExprKind::MethodCall(ref _method_name, ref _generics, ref _args) => {
-                println!("MethodCall(ref method_name, ref generics, ref args) = {};", current);
+            ExprKind::MethodCall(ref _method_name, ref _generics, ref _args, ref _fn_span) => {
+                println!("MethodCall(ref method_name, ref generics, ref args, ref fn_span) = {};", current);
                 println!("    // unimplemented: `ExprKind::MethodCall` is not further destructured at the moment");
             },
             ExprKind::Tup(ref elements) => {
diff --git a/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs b/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs
index f8d197c15e8..7a84f1c986a 100644
--- a/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/hir_utils.rs
@@ -132,7 +132,7 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
                             && self.eq_pat(&l.pat, &r.pat)
                     })
             },
-            (&ExprKind::MethodCall(l_path, _, l_args), &ExprKind::MethodCall(r_path, _, r_args)) => {
+            (&ExprKind::MethodCall(l_path, _, l_args, _), &ExprKind::MethodCall(r_path, _, r_args, _)) => {
                 !self.ignore_fn && self.eq_path_segment(l_path, r_path) && self.eq_exprs(l_args, r_args)
             },
             (&ExprKind::Repeat(ref le, ref ll_id), &ExprKind::Repeat(ref re, ref rl_id)) => {
@@ -542,7 +542,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
 
                 s.hash(&mut self.s);
             },
-            ExprKind::MethodCall(ref path, ref _tys, args) => {
+            ExprKind::MethodCall(ref path, ref _tys, args, ref _fn_span) => {
                 self.hash_name(path.ident.name);
                 self.hash_exprs(args);
             },
@@ -710,7 +710,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     segment.ident.name.hash(&mut self.s);
                 },
             },
-            TyKind::Def(_, arg_list) => {
+            TyKind::OpaqueDef(_, arg_list) => {
                 for arg in *arg_list {
                     match arg {
                         GenericArg::Lifetime(ref l) => self.hash_lifetime(l),
diff --git a/src/tools/clippy/clippy_lints/src/utils/inspector.rs b/src/tools/clippy/clippy_lints/src/utils/inspector.rs
index 9b672b9ec22..afde971f9df 100644
--- a/src/tools/clippy/clippy_lints/src/utils/inspector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/inspector.rs
@@ -63,7 +63,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DeepCodeInspector {
             },
             hir::ImplItemKind::Fn(..) => println!("method"),
             hir::ImplItemKind::TyAlias(_) => println!("associated type"),
-            hir::ImplItemKind::OpaqueTy(_) => println!("existential type"),
         }
     }
     // fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx
@@ -167,7 +166,7 @@ fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, indent: usize) {
                 print_expr(cx, arg, indent + 1);
             }
         },
-        hir::ExprKind::MethodCall(ref path, _, args) => {
+        hir::ExprKind::MethodCall(ref path, _, args, _) => {
             println!("{}MethodCall", ind);
             println!("{}method name: {}", ind, path.ident.name);
             for arg in args {
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
index 8e1b047f6f8..89e2bcdd793 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
@@ -402,7 +402,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CompilerLintFunctions {
         }
 
         if_chain! {
-            if let ExprKind::MethodCall(ref path, _, ref args) = expr.kind;
+            if let ExprKind::MethodCall(ref path, _, ref args, _) = expr.kind;
             let fn_name = path.ident;
             if let Some(sugg) = self.map.get(&*fn_name.as_str());
             let ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0]));
@@ -491,7 +491,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CollapsibleCalls {
             let stmts = &block.stmts;
             if stmts.len() == 1 && block.expr.is_none();
             if let StmtKind::Semi(only_expr) = &stmts[0].kind;
-            if let ExprKind::MethodCall(ref ps, _, ref span_call_args) = &only_expr.kind;
+            if let ExprKind::MethodCall(ref ps, _, ref span_call_args, _) = &only_expr.kind;
             let and_then_snippets = get_and_then_snippets(cx, and_then_args);
             let mut sle = SpanlessEq::new(cx).ignore_fn();
             then {
diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs
index 7b59917c2bb..60ab19e71f5 100644
--- a/src/tools/clippy/clippy_lints/src/utils/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs
@@ -379,7 +379,7 @@ pub fn method_calls<'tcx>(
 
     let mut current = expr;
     for _ in 0..max_depth {
-        if let ExprKind::MethodCall(path, span, args) = &current.kind {
+        if let ExprKind::MethodCall(path, span, args, _) = &current.kind {
             if args.iter().any(|e| e.span.from_expansion()) {
                 break;
             }
@@ -406,7 +406,7 @@ pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec
     let mut matched = Vec::with_capacity(methods.len());
     for method_name in methods.iter().rev() {
         // method chains are stored last -> first
-        if let ExprKind::MethodCall(ref path, _, ref args) = current.kind {
+        if let ExprKind::MethodCall(ref path, _, ref args, _) = current.kind {
             if path.ident.name.as_str() == *method_name {
                 if args.iter().any(|e| e.span.from_expansion()) {
                     return None;
@@ -1324,7 +1324,7 @@ pub fn is_must_use_func_call(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool
                 None
             }
         },
-        ExprKind::MethodCall(_, _, _) => cx.tables.type_dependent_def_id(expr.hir_id),
+        ExprKind::MethodCall(_, _, _, _) => cx.tables.type_dependent_def_id(expr.hir_id),
         _ => None,
     };
 
diff --git a/src/tools/clippy/clippy_lints/src/utils/ptr.rs b/src/tools/clippy/clippy_lints/src/utils/ptr.rs
index fb6bd5e8158..ee336ecc58d 100644
--- a/src/tools/clippy/clippy_lints/src/utils/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/ptr.rs
@@ -58,7 +58,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> {
         if self.abort {
             return;
         }
-        if let ExprKind::MethodCall(ref seg, _, ref args) = expr.kind {
+        if let ExprKind::MethodCall(ref seg, _, ref args, _) = expr.kind {
             if args.len() == 1 && match_var(&args[0], self.name) {
                 if seg.ident.name.as_str() == "capacity" {
                     self.abort = true;
diff --git a/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs b/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs
index 86cbfa8203d..55758efa32e 100644
--- a/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/vec_resize_to_zero.rs
@@ -31,7 +31,7 @@ declare_lint_pass!(VecResizeToZero => [VEC_RESIZE_TO_ZERO]);
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VecResizeToZero {
     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! {
-            if let hir::ExprKind::MethodCall(path_segment, _, ref args) = expr.kind;
+            if let hir::ExprKind::MethodCall(path_segment, _, ref args, _) = expr.kind;
             if let Some(method_def_id) = cx.tables.type_dependent_def_id(expr.hir_id);
             if match_def_path(cx, method_def_id, &paths::VEC_RESIZE) && args.len() == 3;
             if let ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = args[1].kind;
diff --git a/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs b/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs
index 7247518e19b..6d420d491c5 100644
--- a/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs
+++ b/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs
@@ -59,7 +59,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VerboseFileReads {
 
 fn is_file_read_to_end<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
     if_chain! {
-        if let ExprKind::MethodCall(method_name, _, exprs) = expr.kind;
+        if let ExprKind::MethodCall(method_name, _, exprs, _) = expr.kind;
         if method_name.ident.as_str() == "read_to_end";
         if let ExprKind::Path(QPath::Resolved(None, _)) = &exprs[0].kind;
         let ty = cx.tables.expr_ty(&exprs[0]);
@@ -73,7 +73,7 @@ fn is_file_read_to_end<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'t
 
 fn is_file_read_to_string<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
     if_chain! {
-        if let ExprKind::MethodCall(method_name, _, exprs) = expr.kind;
+        if let ExprKind::MethodCall(method_name, _, exprs, _) = expr.kind;
         if method_name.ident.as_str() == "read_to_string";
         if let ExprKind::Path(QPath::Resolved(None, _)) = &exprs[0].kind;
         let ty = cx.tables.expr_ty(&exprs[0]);
diff --git a/src/tools/clippy/tests/ui/cast.rs b/src/tools/clippy/tests/ui/cast.rs
index 7e0b211d862..8ee0969b0f0 100644
--- a/src/tools/clippy/tests/ui/cast.rs
+++ b/src/tools/clippy/tests/ui/cast.rs
@@ -37,11 +37,11 @@ fn main() {
     1isize as usize;
     -1isize as usize;
     0i8 as u8;
-    i8::max_value() as u8;
-    i16::max_value() as u16;
-    i32::max_value() as u32;
-    i64::max_value() as u64;
-    i128::max_value() as u128;
+    i8::MAX as u8;
+    i16::MAX as u16;
+    i32::MAX as u32;
+    i64::MAX as u64;
+    i128::MAX as u128;
 
     (-1i8).abs() as u8;
     (-1i16).abs() as u16;
diff --git a/src/tools/clippy/tests/ui/implicit_saturating_sub.rs b/src/tools/clippy/tests/ui/implicit_saturating_sub.rs
index 24cb216e79b..2f32a7b1578 100644
--- a/src/tools/clippy/tests/ui/implicit_saturating_sub.rs
+++ b/src/tools/clippy/tests/ui/implicit_saturating_sub.rs
@@ -110,7 +110,7 @@ fn main() {
     }
 
     // Lint
-    if i_8 > i8::min_value() {
+    if i_8 > i8::MIN {
         i_8 -= 1;
     }
 
@@ -120,7 +120,7 @@ fn main() {
     }
 
     // Lint
-    if i_8 != i8::min_value() {
+    if i_8 != i8::MIN {
         i_8 -= 1;
     }
 
@@ -135,7 +135,7 @@ fn main() {
     }
 
     // Lint
-    if i_16 > i16::min_value() {
+    if i_16 > i16::MIN {
         i_16 -= 1;
     }
 
@@ -145,7 +145,7 @@ fn main() {
     }
 
     // Lint
-    if i_16 != i16::min_value() {
+    if i_16 != i16::MIN {
         i_16 -= 1;
     }
 
@@ -160,7 +160,7 @@ fn main() {
     }
 
     // Lint
-    if i_32 > i32::min_value() {
+    if i_32 > i32::MIN {
         i_32 -= 1;
     }
 
@@ -170,7 +170,7 @@ fn main() {
     }
 
     // Lint
-    if i_32 != i32::min_value() {
+    if i_32 != i32::MIN {
         i_32 -= 1;
     }
 
@@ -180,7 +180,7 @@ fn main() {
     let mut i_64: i64 = endi_64 - starti_64;
 
     // Lint
-    if i64::min_value() < i_64 {
+    if i64::MIN < i_64 {
         i_64 -= 1;
     }
 
diff --git a/src/tools/clippy/tests/ui/implicit_saturating_sub.stderr b/src/tools/clippy/tests/ui/implicit_saturating_sub.stderr
index a8ba870b1dd..2eb2023b3b9 100644
--- a/src/tools/clippy/tests/ui/implicit_saturating_sub.stderr
+++ b/src/tools/clippy/tests/ui/implicit_saturating_sub.stderr
@@ -75,7 +75,7 @@ LL | |     }
 error: Implicitly performing saturating subtraction
   --> $DIR/implicit_saturating_sub.rs:113:5
    |
-LL | /     if i_8 > i8::min_value() {
+LL | /     if i_8 > i8::MIN {
 LL | |         i_8 -= 1;
 LL | |     }
    | |_____^ help: try: `i_8 = i_8.saturating_sub(1);`
@@ -91,7 +91,7 @@ LL | |     }
 error: Implicitly performing saturating subtraction
   --> $DIR/implicit_saturating_sub.rs:123:5
    |
-LL | /     if i_8 != i8::min_value() {
+LL | /     if i_8 != i8::MIN {
 LL | |         i_8 -= 1;
 LL | |     }
    | |_____^ help: try: `i_8 = i_8.saturating_sub(1);`
@@ -107,7 +107,7 @@ LL | |     }
 error: Implicitly performing saturating subtraction
   --> $DIR/implicit_saturating_sub.rs:138:5
    |
-LL | /     if i_16 > i16::min_value() {
+LL | /     if i_16 > i16::MIN {
 LL | |         i_16 -= 1;
 LL | |     }
    | |_____^ help: try: `i_16 = i_16.saturating_sub(1);`
@@ -123,7 +123,7 @@ LL | |     }
 error: Implicitly performing saturating subtraction
   --> $DIR/implicit_saturating_sub.rs:148:5
    |
-LL | /     if i_16 != i16::min_value() {
+LL | /     if i_16 != i16::MIN {
 LL | |         i_16 -= 1;
 LL | |     }
    | |_____^ help: try: `i_16 = i_16.saturating_sub(1);`
@@ -139,7 +139,7 @@ LL | |     }
 error: Implicitly performing saturating subtraction
   --> $DIR/implicit_saturating_sub.rs:163:5
    |
-LL | /     if i_32 > i32::min_value() {
+LL | /     if i_32 > i32::MIN {
 LL | |         i_32 -= 1;
 LL | |     }
    | |_____^ help: try: `i_32 = i_32.saturating_sub(1);`
@@ -155,7 +155,7 @@ LL | |     }
 error: Implicitly performing saturating subtraction
   --> $DIR/implicit_saturating_sub.rs:173:5
    |
-LL | /     if i_32 != i32::min_value() {
+LL | /     if i_32 != i32::MIN {
 LL | |         i_32 -= 1;
 LL | |     }
    | |_____^ help: try: `i_32 = i_32.saturating_sub(1);`
@@ -163,7 +163,7 @@ LL | |     }
 error: Implicitly performing saturating subtraction
   --> $DIR/implicit_saturating_sub.rs:183:5
    |
-LL | /     if i64::min_value() < i_64 {
+LL | /     if i64::MIN < i_64 {
 LL | |         i_64 -= 1;
 LL | |     }
    | |_____^ help: try: `i_64 = i_64.saturating_sub(1);`
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index 31d991e0c2f..f7355433463 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -27,6 +27,12 @@ fn test_parse_normalization_string() {
     let first = parse_normalization_string(&mut s);
     assert_eq!(first, Some("something (32 bits)".to_owned()));
     assert_eq!(s, " -> \"something ($WORD bits).");
+
+    // Nothing to normalize (No quotes, 16-bit)
+    let mut s = "normalize-stderr-16bit: something (16 bits) -> something ($WORD bits).";
+    let first = parse_normalization_string(&mut s);
+    assert_eq!(first, None);
+    assert_eq!(s, r#"normalize-stderr-16bit: something (16 bits) -> something ($WORD bits)."#);
 }
 
 fn config() -> Config {
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 93a414ff6b9..93c53e779d5 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -464,11 +464,13 @@ fn common_inputs_stamp(config: &Config) -> Stamp {
 
     // Relevant pretty printer files
     let pretty_printer_files = [
-        "src/etc/debugger_pretty_printers_common.py",
+        "src/etc/rust_types.py",
         "src/etc/gdb_load_rust_pretty_printers.py",
-        "src/etc/gdb_rust_pretty_printing.py",
+        "src/etc/gdb_lookup.py",
+        "src/etc/gdb_providers.py",
         "src/etc/lldb_batchmode.py",
-        "src/etc/lldb_rust_formatters.py",
+        "src/etc/lldb_lookup.py",
+        "src/etc/lldb_providers.py",
     ];
     for file in &pretty_printer_files {
         let path = rust_src_dir.join(file);
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 4f8cf92b869..18f00db3d8e 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1079,15 +1079,38 @@ impl<'test> TestCx<'test> {
         // Switch LLDB into "Rust mode"
         let rust_src_root =
             self.config.find_rust_src_root().expect("Could not find Rust source root");
-        let rust_pp_module_rel_path = Path::new("./src/etc/lldb_rust_formatters.py");
+        let rust_pp_module_rel_path = Path::new("./src/etc/lldb_lookup.py");
         let rust_pp_module_abs_path =
             rust_src_root.join(rust_pp_module_rel_path).to_str().unwrap().to_owned();
 
+        let rust_type_regexes = vec![
+            "^(alloc::([a-z_]+::)+)String$",
+            "^&str$",
+            "^&\\[.+\\]$",
+            "^(std::ffi::([a-z_]+::)+)OsString$",
+            "^(alloc::([a-z_]+::)+)Vec<.+>$",
+            "^(alloc::([a-z_]+::)+)VecDeque<.+>$",
+            "^(alloc::([a-z_]+::)+)BTreeSet<.+>$",
+            "^(alloc::([a-z_]+::)+)BTreeMap<.+>$",
+            "^(std::collections::([a-z_]+::)+)HashMap<.+>$",
+            "^(std::collections::([a-z_]+::)+)HashSet<.+>$",
+            "^(alloc::([a-z_]+::)+)Rc<.+>$",
+            "^(alloc::([a-z_]+::)+)Arc<.+>$",
+            "^(core::([a-z_]+::)+)Cell<.+>$",
+            "^(core::([a-z_]+::)+)Ref<.+>$",
+            "^(core::([a-z_]+::)+)RefMut<.+>$",
+            "^(core::([a-z_]+::)+)RefCell<.+>$",
+        ];
+
         script_str
             .push_str(&format!("command script import {}\n", &rust_pp_module_abs_path[..])[..]);
-        script_str.push_str("type summary add --no-value ");
-        script_str.push_str("--python-function lldb_rust_formatters.print_val ");
-        script_str.push_str("-x \".*\" --category Rust\n");
+        script_str.push_str("type synthetic add -l lldb_lookup.synthetic_lookup -x '.*' ");
+        script_str.push_str("--category Rust\n");
+        for type_regex in rust_type_regexes {
+            script_str.push_str("type summary add -F lldb_lookup.summary_lookup  -e -x -h ");
+            script_str.push_str(&format!("'{}' ", type_regex));
+            script_str.push_str("--category Rust\n");
+        }
         script_str.push_str("type category enable Rust\n");
 
         // Set breakpoints on every line that contains the string "#break"
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index c61bee0f8d9..ca36a15ffc7 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -47,6 +47,7 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[
     ("armv7", "arm"),
     ("armv7s", "arm"),
     ("asmjs", "asmjs"),
+    ("avr", "avr"),
     ("hexagon", "hexagon"),
     ("i386", "x86"),
     ("i586", "x86"),
@@ -114,6 +115,8 @@ pub fn matches_env(triple: &str, name: &str) -> bool {
 pub fn get_pointer_width(triple: &str) -> &'static str {
     if (triple.contains("64") && !triple.ends_with("gnux32")) || triple.starts_with("s390x") {
         "64bit"
+    } else if triple.starts_with("avr") {
+        "16bit"
     } else {
         "32bit"
     }
diff --git a/src/tools/unicode-table-generator/src/raw_emitter.rs b/src/tools/unicode-table-generator/src/raw_emitter.rs
index 95b63aca154..63cc29b670f 100644
--- a/src/tools/unicode-table-generator/src/raw_emitter.rs
+++ b/src/tools/unicode-table-generator/src/raw_emitter.rs
@@ -43,7 +43,7 @@ impl RawEmitter {
         words.push(0);
         let unique_words =
             words.iter().cloned().collect::<BTreeSet<_>>().into_iter().collect::<Vec<_>>();
-        if unique_words.len() > u8::max_value() as usize {
+        if unique_words.len() > u8::MAX as usize {
             panic!("cannot pack {} into 8 bits", unique_words.len());
         }
         // needed for the chunk mapping to work
diff --git a/triagebot.toml b/triagebot.toml
index e43cff55386..fc2dbb8d440 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -20,7 +20,7 @@ Hey LLVM ICE-breakers! This bug has been identified as a good
 [instructions] for tackling these sorts of bugs. Maybe take a look?
 Thanks! <3
 
-[instructions]: https://rustc-dev-guide.rust-lang.org/ice-breaker/llvm.html
+[instructions]: https://rustc-dev-guide.rust-lang.org/notification-groups/llvm.html
 """
 label = "ICEBreaker-LLVM"
 
@@ -32,16 +32,88 @@ Hey Cleanup Crew ICE-breakers! This bug has been identified as a good
 [instructions] for tackling these sorts of bugs. Maybe take a look?
 Thanks! <3
 
-[instructions]: https://rustc-dev-guide.rust-lang.org/ice-breaker/cleanup-crew.html
+[instructions]: https://rustc-dev-guide.rust-lang.org/notification-groups/cleanup-crew.html
 """
 label = "ICEBreaker-Cleanup-Crew"
 
+[ping.windows]
+message = """\
+Hey Windows Group! This bug has been identified as a good "Windows candidate".
+In case it's useful, here are some [instructions] for tackling these sorts of
+bugs. Maybe take a look?
+Thanks! <3
+
+[instructions]: https://rustc-dev-guide.rust-lang.org/notification-groups/windows.html
+"""
+label = "O-windows"
+
+[ping.arm]
+message = """\
+Hey ARM Group! This bug has been identified as a good "ARM candidate".
+In case it's useful, here are some [instructions] for tackling these sorts of
+bugs. Maybe take a look?
+Thanks! <3
+
+[instructions]: https://rustc-dev-guide.rust-lang.org/notification-groups/arm.html
+"""
+label = "O-ARM"
+
 [prioritize]
 label = "I-prioritize"
-prioritize_on = ["regression-from-stable-to-stable", "regression-from-stable-to-beta", "regression-from-stable-to-nightly"]
+
+[autolabel."I-prioritize"]
+trigger_labels = [
+    "regression-from-stable-to-stable",
+    "regression-from-stable-to-beta",
+    "regression-from-stable-to-nightly",
+    "I-unsound 💥",
+]
 exclude_labels = [
     "P-*",
     "T-infra",
     "T-release",
+    "requires-nightly",
 ]
-zulip_stream = 227806
+
+[notify-zulip."I-prioritize"]
+zulip_stream = 227806 # #t-compiler/wg-prioritization
+topic = "I-prioritize #{number} {title}"
+message_on_add = "@*WG-prioritization* issue #{number} has been requested for prioritization."
+message_on_remove = "Issue #{number}'s prioritization request has been removed."
+
+[notify-zulip."I-nominated"]
+required_labels = ["T-compiler"]
+zulip_stream = 227806 # #t-compiler/wg-prioritization
+topic = "I-prioritize #{number} {title}"
+message_on_add = "@*WG-prioritization* #{number} has been nominated for discussion in `T-compiler` meeting."
+message_on_remove = "#{number}'s nomination has been removed."
+
+[notify-zulip."beta-nominated"]
+zulip_stream = 227806 # #t-compiler/wg-prioritization
+topic = "Backport #{number} {title}"
+message_on_add = "@*WG-prioritization* PR #{number} has been requested for beta backport."
+message_on_remove = "PR #{number}'s beta backport request has been removed."
+
+[notify-zulip."stable-nominated"]
+zulip_stream = 227806 # #t-compiler/wg-prioritization
+topic = "Backport #{number} {title}"
+message_on_add = "@*WG-prioritization* PR #{number} has been requested for stable backport."
+message_on_remove = "PR #{number}'s stable backport request has been removed."
+
+[notify-zulip."S-waiting-on-team"]
+required_labels = ["T-compiler"]
+zulip_stream = 227806 # #t-compiler/wg-prioritization
+topic = "S-waiting-on-team #{number} {title}"
+message_on_add = "@*WG-prioritization* PR #{number} is waiting on `T-compiler`."
+message_on_remove = "PR #{number}'s is no longer waiting on `T-compiler`."
+
+[notify-zulip."P-critical"]
+zulip_stream = 227806 # #t-compiler/wg-prioritization
+topic = "P-critical #{number} {title}"
+message_on_add = "@*WG-prioritization* issue #{number} has been assigned `P-critical`."
+
+[notify-zulip."P-high"]
+required_labels = ["regression-from-stable-to-*"]
+zulip_stream = 227806 # #t-compiler/wg-prioritization
+topic = "P-high regression #{number} {title}"
+message_on_add = "@*WG-prioritization* issue #{number} has been assigned `P-high` and is a regression."