about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/library_tracking_issue.md32
-rw-r--r--Cargo.lock17
-rw-r--r--RELEASES.md2
-rw-r--r--compiler/rustc_ast/src/ast.rs21
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs14
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs20
-rw-r--r--compiler/rustc_ast/src/token.rs2
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs33
-rw-r--r--compiler/rustc_ast/src/util/literal.rs9
-rw-r--r--compiler/rustc_ast/src/visit.rs10
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs51
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs31
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs27
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/mod.rs5
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs34
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/hash.rs10
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs33
-rw-r--r--compiler/rustc_codegen_llvm/src/va_arg.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs11
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/analyze.rs11
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs56
-rw-r--r--compiler/rustc_data_structures/src/fingerprint.rs4
-rw-r--r--compiler/rustc_driver/src/lib.rs23
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0435.md6
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0492.md4
-rw-r--r--compiler/rustc_errors/src/emitter.rs25
-rw-r--r--compiler/rustc_errors/src/styled_buffer.rs27
-rw-r--r--compiler/rustc_expand/src/base.rs38
-rw-r--r--compiler/rustc_expand/src/expand.rs21
-rw-r--r--compiler/rustc_expand/src/placeholders.rs7
-rw-r--r--compiler/rustc_expand/src/proc_macro.rs7
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs2
-rw-r--r--compiler/rustc_feature/src/active.rs3
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs2
-rw-r--r--compiler/rustc_fs_util/src/lib.rs6
-rw-r--r--compiler/rustc_hir/Cargo.toml1
-rw-r--r--compiler/rustc_hir/src/hir.rs20
-rw-r--r--compiler/rustc_hir/src/intravisit.rs8
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs24
-rw-r--r--compiler/rustc_incremental/src/assert_dep_graph.rs6
-rw-r--r--compiler/rustc_incremental/src/persist/file_format.rs10
-rw-r--r--compiler/rustc_incremental/src/persist/fs.rs30
-rw-r--r--compiler/rustc_incremental/src/persist/save.rs26
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs28
-rw-r--r--compiler/rustc_interface/src/passes.rs2
-rw-r--r--compiler/rustc_interface/src/tests.rs3
-rw-r--r--compiler/rustc_lexer/src/cursor.rs2
-rw-r--r--compiler/rustc_lint/src/builtin.rs4
-rw-r--r--compiler/rustc_lint/src/context.rs3
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs21
-rw-r--r--compiler/rustc_lint/src/unused.rs8
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs12
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs1
-rw-r--r--compiler/rustc_macros/src/serialize.rs4
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs8
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs49
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs2
-rw-r--r--compiler/rustc_middle/src/dep_graph/dep_node.rs503
-rw-r--r--compiler/rustc_middle/src/dep_graph/mod.rs44
-rw-r--r--compiler/rustc_middle/src/hir/map/collector.rs23
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs11
-rw-r--r--compiler/rustc_middle/src/ich/hcx.rs9
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs21
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs44
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs4
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs25
-rw-r--r--compiler/rustc_middle/src/ty/query/mod.rs134
-rw-r--r--compiler/rustc_middle/src/ty/query/on_disk_cache.rs36
-rw-r--r--compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs180
-rw-r--r--compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs2
-rw-r--r--compiler/rustc_mir/src/borrow_check/mod.rs74
-rw-r--r--compiler/rustc_mir/src/borrow_check/prefixes.rs26
-rw-r--r--compiler/rustc_mir/src/borrow_check/type_check/mod.rs4
-rw-r--r--compiler/rustc_mir/src/const_eval/machine.rs2
-rw-r--r--compiler/rustc_mir/src/interpret/machine.rs4
-rw-r--r--compiler/rustc_mir/src/interpret/terminator.rs11
-rw-r--r--compiler/rustc_mir/src/transform/check_consts/ops.rs53
-rw-r--r--compiler/rustc_mir/src/transform/check_consts/validation.rs50
-rw-r--r--compiler/rustc_mir/src/transform/const_prop.rs2
-rw-r--r--compiler/rustc_mir/src/transform/inline.rs17
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs5
-rw-r--r--compiler/rustc_parse/src/lib.rs30
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs9
-rw-r--r--compiler/rustc_parse/src/parser/item.rs17
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs14
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs5
-rw-r--r--compiler/rustc_passes/src/check_attr.rs13
-rw-r--r--compiler/rustc_passes/src/intrinsicck.rs2
-rw-r--r--compiler/rustc_passes/src/naked_functions.rs2
-rw-r--r--compiler/rustc_privacy/src/lib.rs7
-rw-r--r--compiler/rustc_query_system/src/dep_graph/dep_node.rs6
-rw-r--r--compiler/rustc_query_system/src/dep_graph/mod.rs2
-rw-r--r--compiler/rustc_query_system/src/query/plumbing.rs1
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs49
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs5
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs23
-rw-r--r--compiler/rustc_resolve/src/late.rs124
-rw-r--r--compiler/rustc_resolve/src/lib.rs152
-rw-r--r--compiler/rustc_resolve/src/macros.rs25
-rw-r--r--compiler/rustc_save_analysis/src/dump_visitor.rs6
-rw-r--r--compiler/rustc_save_analysis/src/sig.rs1
-rw-r--r--compiler/rustc_serialize/src/collection_impls.rs42
-rw-r--r--compiler/rustc_serialize/src/lib.rs2
-rw-r--r--compiler/rustc_serialize/src/opaque.rs47
-rw-r--r--compiler/rustc_serialize/src/serialize.rs13
-rw-r--r--compiler/rustc_session/src/config.rs14
-rw-r--r--compiler/rustc_session/src/options.rs20
-rw-r--r--compiler/rustc_session/src/session.rs18
-rw-r--r--compiler/rustc_span/src/caching_source_map_view.rs245
-rw-r--r--compiler/rustc_span/src/hygiene.rs48
-rw-r--r--compiler/rustc_span/src/lib.rs30
-rw-r--r--compiler/rustc_span/src/source_map.rs4
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs10
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs9
-rw-r--r--compiler/rustc_target/src/abi/mod.rs75
-rw-r--r--compiler/rustc_target/src/spec/armebv7r_none_eabi.rs3
-rw-r--r--compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs3
-rw-r--r--compiler/rustc_target/src/spec/crt_objects.rs20
-rw-r--r--compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs3
-rw-r--r--compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs3
-rw-r--r--compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs3
-rw-r--r--compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs3
-rw-r--r--compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs3
-rw-r--r--compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs3
-rw-r--r--compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs3
-rw-r--r--compiler/rustc_target/src/spec/mod.rs17
-rw-r--r--compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs3
-rw-r--r--compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs3
-rw-r--r--compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs3
-rw-r--r--compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs3
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs3
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs3
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs3
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs7
-rw-r--r--compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs3
-rw-r--r--compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs3
-rw-r--r--compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs3
-rw-r--r--compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs3
-rw-r--r--compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs3
-rw-r--r--compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs10
-rw-r--r--compiler/rustc_typeck/src/astconv/generics.rs92
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs2
-rw-r--r--compiler/rustc_typeck/src/check/callee.rs6
-rw-r--r--compiler/rustc_typeck/src/check/check.rs6
-rw-r--r--compiler/rustc_typeck/src/check/coercion.rs12
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs55
-rw-r--r--compiler/rustc_typeck/src/check/intrinsic.rs2
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs2
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs2
-rw-r--r--compiler/rustc_typeck/src/collect.rs12
-rw-r--r--library/alloc/Cargo.toml4
-rw-r--r--library/alloc/src/borrow.rs5
-rw-r--r--library/alloc/src/boxed.rs2
-rw-r--r--library/alloc/src/collections/btree/node.rs58
-rw-r--r--library/alloc/src/lib.rs3
-rw-r--r--library/alloc/src/rc.rs1
-rw-r--r--library/alloc/src/str.rs2
-rw-r--r--library/alloc/src/vec/mod.rs3
-rw-r--r--library/core/src/alloc/layout.rs6
-rw-r--r--library/core/src/any.rs23
-rw-r--r--library/core/src/array/mod.rs75
-rw-r--r--library/core/src/borrow.rs3
-rw-r--r--library/core/src/char/convert.rs42
-rw-r--r--library/core/src/cmp.rs2
-rw-r--r--library/core/src/convert/mod.rs9
-rw-r--r--library/core/src/hint.rs2
-rw-r--r--library/core/src/intrinsics.rs29
-rw-r--r--library/core/src/iter/adapters/zip.rs2
-rw-r--r--library/core/src/iter/range.rs2
-rw-r--r--library/core/src/iter/traits/iterator.rs2
-rw-r--r--library/core/src/lib.rs3
-rw-r--r--library/core/src/mem/mod.rs17
-rw-r--r--library/core/src/option.rs2
-rw-r--r--library/core/src/pin.rs2
-rw-r--r--library/core/src/result.rs6
-rw-r--r--library/core/src/slice/iter.rs8
-rw-r--r--library/core/src/slice/mod.rs50
-rw-r--r--library/core/src/str/mod.rs2
-rw-r--r--library/std/Cargo.toml4
-rw-r--r--library/std/src/alloc.rs5
-rw-r--r--library/std/src/error.rs2
-rw-r--r--library/std/src/io/mod.rs2
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/path.rs1
-rw-r--r--library/std/src/prelude/v1.rs8
-rw-r--r--library/std/src/primitive_docs.rs16
-rw-r--r--library/std/src/sys_common/fs.rs10
-rw-r--r--library/test/Cargo.toml2
-rw-r--r--library/unwind/build.rs4
-rw-r--r--src/bootstrap/bootstrap.py40
-rw-r--r--src/bootstrap/bootstrap_test.py11
-rw-r--r--src/bootstrap/builder.rs2
-rw-r--r--src/bootstrap/channel.rs4
-rw-r--r--src/bootstrap/check.rs11
-rw-r--r--src/bootstrap/clean.rs1
-rw-r--r--src/bootstrap/compile.rs54
-rw-r--r--src/bootstrap/dist.rs8
-rw-r--r--src/bootstrap/install.rs99
-rw-r--r--src/bootstrap/lib.rs4
-rw-r--r--src/bootstrap/native.rs1
-rw-r--r--src/bootstrap/sanity.rs6
-rw-r--r--src/bootstrap/setup.rs4
-rw-r--r--src/bootstrap/test.rs16
-rw-r--r--src/doc/unstable-book/src/compiler-flags/sanitizer.md28
-rw-r--r--src/doc/unstable-book/src/compiler-flags/source-based-code-coverage.md2
-rw-r--r--src/etc/htmldocck.py12
-rw-r--r--src/librustdoc/clean/auto_trait.rs22
-rw-r--r--src/librustdoc/clean/blanket_impl.rs2
-rw-r--r--src/librustdoc/clean/cfg.rs16
-rw-r--r--src/librustdoc/clean/inline.rs123
-rw-r--r--src/librustdoc/clean/mod.rs58
-rw-r--r--src/librustdoc/clean/types.rs184
-rw-r--r--src/librustdoc/clean/utils.rs74
-rw-r--r--src/librustdoc/config.rs5
-rw-r--r--src/librustdoc/core.rs36
-rw-r--r--src/librustdoc/doctest.rs7
-rw-r--r--src/librustdoc/fold.rs2
-rw-r--r--src/librustdoc/formats/cache.rs2
-rw-r--r--src/librustdoc/html/format.rs20
-rw-r--r--src/librustdoc/html/markdown.rs199
-rw-r--r--src/librustdoc/html/render/cache.rs4
-rw-r--r--src/librustdoc/html/render/mod.rs237
-rw-r--r--src/librustdoc/html/static/main.js38
-rw-r--r--src/librustdoc/html/static/rustdoc.css6
-rw-r--r--src/librustdoc/html/toc.rs2
-rw-r--r--src/librustdoc/json/conversions.rs4
-rw-r--r--src/librustdoc/passes/calculate_doc_coverage.rs7
-rw-r--r--src/librustdoc/passes/check_code_block_syntax.rs15
-rw-r--r--src/librustdoc/passes/collapse_docs.rs72
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs369
-rw-r--r--src/librustdoc/passes/collect_trait_impls.rs100
-rw-r--r--src/librustdoc/passes/html_tags.rs2
-rw-r--r--src/librustdoc/passes/mod.rs5
-rw-r--r--src/librustdoc/passes/strip_hidden.rs4
-rw-r--r--src/librustdoc/passes/unindent_comments.rs18
-rw-r--r--src/librustdoc/passes/unindent_comments/tests.rs14
-rw-r--r--src/librustdoc/theme.rs10
-rw-r--r--src/librustdoc/visit_ast.rs54
-rw-r--r--src/test/codegen/sanitizer-no-sanitize.rs2
-rw-r--r--src/test/incremental/hygiene/load_cached_hygiene.rs9
-rw-r--r--src/test/incremental/remapped_paths_cc/main.rs9
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/Makefile2
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt124
-rw-r--r--src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest/doctest.main.-------.InstrumentCoverage.0.html104
-rw-r--r--src/test/run-make-fulldeps/coverage/doctest.rs43
-rw-r--r--src/test/run-make-fulldeps/inline-always-many-cgu/Makefile7
-rw-r--r--src/test/rustdoc-ui/deref-recursive-cycle.rs17
-rw-r--r--src/test/rustdoc-ui/doc-alias-crate-level.rs2
-rw-r--r--src/test/rustdoc-ui/doc-alias-crate-level.stderr4
-rw-r--r--src/test/rustdoc-ui/doc-alias-same-name.rs4
-rw-r--r--src/test/rustdoc-ui/doc-alias-same-name.stderr8
-rw-r--r--src/test/rustdoc-ui/ignore-block-help.rs7
-rw-r--r--src/test/rustdoc-ui/ignore-block-help.stderr17
-rw-r--r--src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.rs3
-rw-r--r--src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.stderr15
-rw-r--r--src/test/rustdoc-ui/intra-doc/unused-extern-crate.rs5
-rw-r--r--src/test/rustdoc-ui/intra-doc/unused-extern-crate.stderr15
-rw-r--r--src/test/rustdoc-ui/invalid-syntax.stderr6
-rw-r--r--src/test/rustdoc-ui/range-pattern.rs3
-rw-r--r--src/test/rustdoc-ui/reference-link-reports-error-once.rs20
-rw-r--r--src/test/rustdoc-ui/reference-link-reports-error-once.stderr63
-rw-r--r--src/test/rustdoc-ui/reference-links.rs1
-rw-r--r--src/test/rustdoc-ui/reference-links.stderr8
-rw-r--r--src/test/rustdoc/auxiliary/macro_pub_in_module.rs13
-rw-r--r--src/test/rustdoc/deref-recursive-pathbuf.rs26
-rw-r--r--src/test/rustdoc/deref-recursive.rs42
-rw-r--r--src/test/rustdoc/deref-typedef.rs21
-rw-r--r--src/test/rustdoc/intra-doc-crate/auxiliary/self.rs3
-rw-r--r--src/test/rustdoc/intra-doc-crate/self.rs3
-rw-r--r--src/test/rustdoc/intra-doc/non-path-primitives.rs11
-rw-r--r--src/test/rustdoc/intra-doc/primitive-disambiguators.rs4
-rw-r--r--src/test/rustdoc/macro_pub_in_module.rs82
-rw-r--r--src/test/rustdoc/macros.rs14
-rw-r--r--src/test/rustdoc/range-arg-pattern.rs5
-rw-r--r--src/test/ui/abi/issues/issue-22565-rust-call.rs26
-rw-r--r--src/test/ui/abi/issues/issue-22565-rust-call.stderr22
-rw-r--r--src/test/ui/ast-json/ast-json-noexpand-output.stdout2
-rw-r--r--src/test/ui/ast-json/ast-json-output.stdout2
-rw-r--r--src/test/ui/async-await/feature-async-closure.stderr1
-rw-r--r--src/test/ui/attributes/key-value-expansion-on-mac.rs15
-rw-r--r--src/test/ui/attributes/key-value-expansion-on-mac.stderr8
-rw-r--r--src/test/ui/check-doc-alias-attr-location.rs1
-rw-r--r--src/test/ui/check-doc-alias-attr-location.stderr8
-rw-r--r--src/test/ui/check-doc-alias-attr.rs1
-rw-r--r--src/test/ui/check-doc-alias-attr.stderr18
-rw-r--r--src/test/ui/codemap_tests/tab_3.stderr2
-rw-r--r--src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr2
-rw-r--r--src/test/ui/const-generics/const-param-before-other-params.min.stderr4
-rw-r--r--src/test/ui/const-generics/const-param-elided-lifetime.min.stderr10
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr4
-rw-r--r--src/test/ui/const-generics/different_byref.min.stderr2
-rw-r--r--src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr4
-rw-r--r--src/test/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr2
-rw-r--r--src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr2
-rw-r--r--src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr2
-rw-r--r--src/test/ui/const-generics/issues/issue-62878.min.stderr2
-rw-r--r--src/test/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr2
-rw-r--r--src/test/ui/const-generics/issues/issue-68615-adt.min.stderr2
-rw-r--r--src/test/ui/const-generics/issues/issue-68615-array.min.stderr2
-rw-r--r--src/test/ui/const-generics/issues/issue-71169.min.stderr2
-rw-r--r--src/test/ui/const-generics/issues/issue-73491.min.stderr2
-rw-r--r--src/test/ui/const-generics/issues/issue-74101.min.stderr4
-rw-r--r--src/test/ui/const-generics/issues/issue-74255.min.stderr2
-rw-r--r--src/test/ui/const-generics/issues/issue-74950.min.stderr10
-rw-r--r--src/test/ui/const-generics/issues/issue-75047.min.stderr2
-rw-r--r--src/test/ui/const-generics/min_const_generics/complex-types.stderr14
-rw-r--r--src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.stderr2
-rw-r--r--src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr2
-rw-r--r--src/test/ui/const-generics/nested-type.min.stderr2
-rw-r--r--src/test/ui/const-generics/slice-const-param-mismatch.min.stderr4
-rw-r--r--src/test/ui/const-generics/slice-const-param.min.stderr4
-rw-r--r--src/test/ui/const-generics/std/const-generics-range.min.stderr12
-rw-r--r--src/test/ui/const-generics/suggest_const_for_array.rs10
-rw-r--r--src/test/ui/const-generics/suggest_const_for_array.stderr15
-rw-r--r--src/test/ui/const-generics/type-dependent/issue-71348.min.stderr4
-rw-r--r--src/test/ui/consts/const-address-of-interior-mut.stderr22
-rw-r--r--src/test/ui/consts/const-multi-ref.rs2
-rw-r--r--src/test/ui/consts/const-multi-ref.stderr9
-rw-r--r--src/test/ui/consts/partial_qualif.rs2
-rw-r--r--src/test/ui/consts/partial_qualif.stderr4
-rw-r--r--src/test/ui/consts/promotion.rs15
-rw-r--r--src/test/ui/consts/qualif_overwrite.rs2
-rw-r--r--src/test/ui/consts/qualif_overwrite.stderr4
-rw-r--r--src/test/ui/consts/qualif_overwrite_2.rs2
-rw-r--r--src/test/ui/consts/qualif_overwrite_2.stderr4
-rw-r--r--src/test/ui/consts/std/cell.rs30
-rw-r--r--src/test/ui/consts/std/cell.stderr27
-rw-r--r--src/test/ui/doc-alias-crate-level.rs2
-rw-r--r--src/test/ui/doc-alias-crate-level.stderr4
-rw-r--r--src/test/ui/doc-alias-same-name.rs4
-rw-r--r--src/test/ui/doc-alias-same-name.stderr8
-rw-r--r--src/test/ui/error-codes/E0435.fixed6
-rw-r--r--src/test/ui/error-codes/E0435.rs4
-rw-r--r--src/test/ui/error-codes/E0435.stderr4
-rw-r--r--src/test/ui/error-codes/E0492.rs5
-rw-r--r--src/test/ui/error-codes/E0492.stderr18
-rw-r--r--src/test/ui/feature-gate/feature-gate-const_refs_to_cell.rs12
-rw-r--r--src/test/ui/feature-gates/feature-gate-const_generics.stderr2
-rw-r--r--src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr12
-rw-r--r--src/test/ui/feature-gates/issue-43106-gating-of-macro_use.stderr12
-rw-r--r--src/test/ui/impl-trait/bindings.stderr16
-rw-r--r--src/test/ui/issues/issue-17718-const-borrow.rs6
-rw-r--r--src/test/ui/issues/issue-17718-const-borrow.stderr12
-rw-r--r--src/test/ui/issues/issue-27433.fixed7
-rw-r--r--src/test/ui/issues/issue-27433.rs2
-rw-r--r--src/test/ui/issues/issue-27433.stderr6
-rw-r--r--src/test/ui/issues/issue-34721.stderr2
-rw-r--r--src/test/ui/issues/issue-3521-2.fixed9
-rw-r--r--src/test/ui/issues/issue-3521-2.rs1
-rw-r--r--src/test/ui/issues/issue-3521-2.stderr6
-rw-r--r--src/test/ui/issues/issue-3521.fixed13
-rw-r--r--src/test/ui/issues/issue-3521.rs4
-rw-r--r--src/test/ui/issues/issue-3521.stderr5
-rw-r--r--src/test/ui/issues/issue-3668-2.fixed8
-rw-r--r--src/test/ui/issues/issue-3668-2.rs2
-rw-r--r--src/test/ui/issues/issue-3668-2.stderr6
-rw-r--r--src/test/ui/issues/issue-3668.stderr4
-rw-r--r--src/test/ui/issues/issue-42060.stderr4
-rw-r--r--src/test/ui/issues/issue-44239.fixed11
-rw-r--r--src/test/ui/issues/issue-44239.rs4
-rw-r--r--src/test/ui/issues/issue-44239.stderr5
-rw-r--r--src/test/ui/issues/issue-61108.stderr2
-rw-r--r--src/test/ui/issues/issue-64559.stderr2
-rw-r--r--src/test/ui/issues/issue-80607.rs10
-rw-r--r--src/test/ui/issues/issue-80607.stderr14
-rw-r--r--src/test/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.rs19
-rw-r--r--src/test/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.stderr67
-rw-r--r--src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.rs21
-rw-r--r--src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.stderr2
-rw-r--r--src/test/ui/moves/move-fn-self-receiver.rs5
-rw-r--r--src/test/ui/moves/move-fn-self-receiver.stderr23
-rw-r--r--src/test/ui/moves/moves-based-on-type-access-to-field.stderr2
-rw-r--r--src/test/ui/moves/moves-based-on-type-exprs.stderr4
-rw-r--r--src/test/ui/no-patterns-in-args-2.stderr2
-rw-r--r--src/test/ui/non-constant-expr-for-arr-len.stderr4
-rw-r--r--src/test/ui/overloaded-calls-nontuple.rs4
-rw-r--r--src/test/ui/overloaded-calls-nontuple.stderr4
-rw-r--r--src/test/ui/panic-handler/weak-lang-item.stderr4
-rw-r--r--src/test/ui/parser/block-no-opening-brace.rs2
-rw-r--r--src/test/ui/parser/block-no-opening-brace.stderr12
-rw-r--r--src/test/ui/parser/import-from-path.stderr2
-rw-r--r--src/test/ui/parser/import-from-rename.stderr2
-rw-r--r--src/test/ui/parser/import-glob-path.stderr2
-rw-r--r--src/test/ui/parser/import-glob-rename.stderr2
-rw-r--r--src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr1
-rw-r--r--src/test/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs11
-rw-r--r--src/test/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr16
-rw-r--r--src/test/ui/proc-macro/issue-75930-derive-cfg.stdout256
-rw-r--r--src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout18
-rw-r--r--src/test/ui/proc-macro/issue-80760-empty-stmt.rs26
-rw-r--r--src/test/ui/proc-macro/issue-80760-empty-stmt.stdout14
-rw-r--r--src/test/ui/repeat_count.stderr2
-rw-r--r--src/test/ui/sanitize/unsupported-target.stderr2
-rw-r--r--src/test/ui/suggestions/borrow-for-loop-head.stderr8
-rw-r--r--src/test/ui/terminal-width/tabs-trimming.rs13
-rw-r--r--src/test/ui/terminal-width/tabs-trimming.stderr12
-rw-r--r--src/test/ui/type/type-dependent-def-issue-49241.stderr4
-rw-r--r--src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr1
-rw-r--r--src/test/ui/unsafe/ranged_ints3_const.rs4
-rw-r--r--src/test/ui/unsafe/ranged_ints3_const.stderr12
-rw-r--r--src/test/ui/unsized-locals/borrow-after-move.stderr2
-rw-r--r--src/test/ui/unsized-locals/double-move.stderr2
-rw-r--r--src/test/ui/use/use-after-move-self-based-on-type.stderr2
-rw-r--r--src/test/ui/use/use-after-move-self.stderr2
-rw-r--r--src/test/ui/walk-struct-literal-with.stderr2
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/.github/ISSUE_TEMPLATE/false_negative.md35
-rw-r--r--src/tools/clippy/.github/ISSUE_TEMPLATE/false_positive.md35
-rw-r--r--src/tools/clippy/.github/workflows/clippy.yml3
-rw-r--r--src/tools/clippy/CHANGELOG.md1
-rw-r--r--src/tools/clippy/Cargo.toml4
-rw-r--r--src/tools/clippy/README.md43
-rw-r--r--src/tools/clippy/clippy_dev/src/ra_setup.rs4
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_lints/src/default.rs188
-rw-r--r--src/tools/clippy/clippy_lints/src/from_over_into.rs83
-rw-r--r--src/tools/clippy/clippy_lints/src/large_enum_variant.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/macro_use.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_async_fn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/map_err_ignore.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs60
-rw-r--r--src/tools/clippy/clippy_lints/src/single_component_path_imports.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_unit.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/ast_utils.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/mod.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/ptr.rs1
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/macro_rules.rs10
-rw-r--r--src/tools/clippy/tests/ui/field_reassign_with_default.rs12
-rw-r--r--src/tools/clippy/tests/ui/field_reassign_with_default.stderr4
-rw-r--r--src/tools/clippy/tests/ui/from_over_into.rs21
-rw-r--r--src/tools/clippy/tests/ui/from_over_into.stderr15
-rw-r--r--src/tools/clippy/tests/ui/large_enum_variant.rs9
-rw-r--r--src/tools/clippy/tests/ui/large_enum_variant.stderr18
-rw-r--r--src/tools/clippy/tests/ui/map_err.stderr2
-rw-r--r--src/tools/clippy/tests/ui/min_rust_version_attr.rs8
-rw-r--r--src/tools/clippy/tests/ui/min_rust_version_attr.stderr8
-rw-r--r--src/tools/clippy/tests/ui/ptr_arg.rs41
-rw-r--r--src/tools/clippy/tests/ui/ptr_arg.stderr102
-rw-r--r--src/tools/clippy/tests/ui/unused_unit.fixed1
-rw-r--r--src/tools/clippy/tests/ui/unused_unit.rs1
-rw-r--r--src/tools/clippy/tests/ui/unused_unit.stderr38
-rw-r--r--src/tools/clippy/tests/versioncheck.rs54
-rw-r--r--src/tools/clippy/util/gh-pages/index.html54
-rw-r--r--src/tools/compiletest/src/util.rs10
m---------src/tools/miri16
-rw-r--r--src/tools/rustbook/Cargo.toml2
459 files changed, 5709 insertions, 3181 deletions
diff --git a/.github/ISSUE_TEMPLATE/library_tracking_issue.md b/.github/ISSUE_TEMPLATE/library_tracking_issue.md
index 3e42594c828..cbc4465fcfe 100644
--- a/.github/ISSUE_TEMPLATE/library_tracking_issue.md
+++ b/.github/ISSUE_TEMPLATE/library_tracking_issue.md
@@ -33,21 +33,41 @@ For most library features, it'd be useful to include a summarized version of the
 -->
 
 ```rust
-...
+// core::magic
+
+pub struct Magic;
+
+impl Magic {
+    pub fn magic(self);
+}
 ```
 
 ### Steps / History
 
 <!--
-In the simplest case, this is a PR implementing the feature followed by a PR
-that stabilises the feature. However it's not uncommon for the feature to be
-changed before stabilization. For larger features, the implementation could be
-split up in multiple steps.
+For larger features, more steps might be involved.
+If the feature is changed later, please add those PRs here as well.
 -->
 
-- [ ] Implementation: ...
+- [ ] Implementation: #...
+- [ ] Final commenting period (FCP)
 - [ ] Stabilization PR
 
+<!--
+Once the feature has gone through a few release cycles and there are no
+unresolved questions left, the feature might be ready for stabilization.
+
+If this feature didn't go through the RFC process, a final commenting period
+(FCP) is always needed before stabilization. This works as follows:
+
+A library team member can kick off the stabilization process, at which point
+the rfcbot will ask all the team members to verify they agree with
+stabilization. Once enough members agree and there are no concerns, the final
+commenting period begins: this issue will be marked as such and will be listed
+in the next This Week in Rust newsletter. If no blocking concerns are raised in
+that period of 10 days, a stabilzation PR can be opened by anyone.
+-->
+
 ### Unresolved Questions
 
 <!--
diff --git a/Cargo.lock b/Cargo.lock
index 4676e4127e8..322b1632031 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -295,7 +295,7 @@ checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da"
 
 [[package]]
 name = "cargo"
-version = "0.51.0"
+version = "0.52.0"
 dependencies = [
  "anyhow",
  "atty",
@@ -568,7 +568,7 @@ dependencies = [
 
 [[package]]
 name = "clippy"
-version = "0.0.212"
+version = "0.1.51"
 dependencies = [
  "cargo_metadata 0.12.0",
  "clippy-mini-macro-test",
@@ -589,7 +589,7 @@ version = "0.2.0"
 
 [[package]]
 name = "clippy_lints"
-version = "0.0.212"
+version = "0.1.51"
 dependencies = [
  "cargo_metadata 0.12.0",
  "if_chain",
@@ -666,9 +666,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.36"
+version = "0.1.39"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7cd0782e0a7da7598164153173e5a5d4d9b1da094473c98dce0ff91406112369"
+checksum = "3748f82c7d366a0b4950257d19db685d4958d2fa27c6d164a3f069fec42b748b"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
@@ -1973,9 +1973,9 @@ dependencies = [
 
 [[package]]
 name = "mdbook"
-version = "0.4.3"
+version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29be448fcafb00c5a8966c4020c2a5ffbbc333e5b96d0bb5ef54b5bd0524d9ff"
+checksum = "21251d3eb9ca5e8ac5b73384ddaa483a9bbc7d7dcd656b1fa8f266634810334a"
 dependencies = [
  "ammonia",
  "anyhow",
@@ -3745,6 +3745,7 @@ version = "0.0.0"
 dependencies = [
  "rustc_ast",
  "rustc_data_structures",
+ "rustc_feature",
  "rustc_index",
  "rustc_macros",
  "rustc_serialize",
@@ -5343,7 +5344,7 @@ dependencies = [
  "chrono",
  "lazy_static",
  "matchers",
- "parking_lot 0.9.0",
+ "parking_lot 0.11.0",
  "regex",
  "serde",
  "serde_json",
diff --git a/RELEASES.md b/RELEASES.md
index 8f04980e390..4409b6ad7b1 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -45,7 +45,6 @@ Libraries
 
 - [`RangeInclusive` now checks for exhaustion when calling `contains` and indexing.][78109]
 - [`ToString::to_string` now no longer shrinks the internal buffer in the default implementation.][77997]
-- [`ops::{Index, IndexMut}` are now implemented for fixed sized arrays of any length.][74989]
 
 Stabilized APIs
 ---------------
@@ -110,7 +109,6 @@ related tools.
 [76199]: https://github.com/rust-lang/rust/pull/76199
 [76119]: https://github.com/rust-lang/rust/pull/76119
 [75914]: https://github.com/rust-lang/rust/pull/75914
-[74989]: https://github.com/rust-lang/rust/pull/74989
 [79004]: https://github.com/rust-lang/rust/pull/79004
 [78676]: https://github.com/rust-lang/rust/pull/78676
 [79904]: https://github.com/rust-lang/rust/issues/79904
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 8167bde0322..8601da6fa06 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -23,8 +23,8 @@ pub use GenericArgs::*;
 pub use UnsafeSource::*;
 
 use crate::ptr::P;
-use crate::token::{self, CommentKind, DelimToken};
-use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream};
+use crate::token::{self, CommentKind, DelimToken, Token};
+use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream, TokenTree};
 
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -433,9 +433,9 @@ pub enum WherePredicate {
 impl WherePredicate {
     pub fn span(&self) -> Span {
         match self {
-            &WherePredicate::BoundPredicate(ref p) => p.span,
-            &WherePredicate::RegionPredicate(ref p) => p.span,
-            &WherePredicate::EqPredicate(ref p) => p.span,
+            WherePredicate::BoundPredicate(p) => p.span,
+            WherePredicate::RegionPredicate(p) => p.span,
+            WherePredicate::EqPredicate(p) => p.span,
         }
     }
 }
@@ -1464,8 +1464,8 @@ pub enum MacArgs {
     Eq(
         /// Span of the `=` token.
         Span,
-        /// Token stream of the "value".
-        TokenStream,
+        /// "value" as a nonterminal token.
+        Token,
     ),
 }
 
@@ -1478,10 +1478,10 @@ impl MacArgs {
     }
 
     pub fn span(&self) -> Option<Span> {
-        match *self {
+        match self {
             MacArgs::Empty => None,
             MacArgs::Delimited(dspan, ..) => Some(dspan.entire()),
-            MacArgs::Eq(eq_span, ref tokens) => Some(eq_span.to(tokens.span().unwrap_or(eq_span))),
+            MacArgs::Eq(eq_span, token) => Some(eq_span.to(token.span)),
         }
     }
 
@@ -1490,7 +1490,8 @@ impl MacArgs {
     pub fn inner_tokens(&self) -> TokenStream {
         match self {
             MacArgs::Empty => TokenStream::default(),
-            MacArgs::Delimited(.., tokens) | MacArgs::Eq(.., tokens) => tokens.clone(),
+            MacArgs::Delimited(.., tokens) => tokens.clone(),
+            MacArgs::Eq(.., token) => TokenTree::Token(token.clone()).into(),
         }
     }
 
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 726ae5e51f7..6a54cb4766b 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -476,7 +476,7 @@ impl MetaItemKind {
     pub fn mac_args(&self, span: Span) -> MacArgs {
         match self {
             MetaItemKind::Word => MacArgs::Empty,
-            MetaItemKind::NameValue(lit) => MacArgs::Eq(span, lit.token_tree().into()),
+            MetaItemKind::NameValue(lit) => MacArgs::Eq(span, lit.to_token()),
             MetaItemKind::List(list) => {
                 let mut tts = Vec::new();
                 for (i, item) in list.iter().enumerate() {
@@ -498,7 +498,10 @@ impl MetaItemKind {
         match *self {
             MetaItemKind::Word => vec![],
             MetaItemKind::NameValue(ref lit) => {
-                vec![TokenTree::token(token::Eq, span).into(), lit.token_tree().into()]
+                vec![
+                    TokenTree::token(token::Eq, span).into(),
+                    TokenTree::Token(lit.to_token()).into(),
+                ]
             }
             MetaItemKind::List(ref list) => {
                 let mut tokens = Vec::new();
@@ -554,10 +557,7 @@ impl MetaItemKind {
                 MetaItemKind::list_from_tokens(tokens.clone())
             }
             MacArgs::Delimited(..) => None,
-            MacArgs::Eq(_, tokens) => {
-                assert!(tokens.len() == 1);
-                MetaItemKind::name_value_from_tokens(&mut tokens.trees())
-            }
+            MacArgs::Eq(_, token) => Lit::from_token(token).ok().map(MetaItemKind::NameValue),
             MacArgs::Empty => Some(MetaItemKind::Word),
         }
     }
@@ -592,7 +592,7 @@ impl NestedMetaItem {
     fn token_trees_and_spacings(&self) -> Vec<TreeAndSpacing> {
         match *self {
             NestedMetaItem::MetaItem(ref item) => item.token_trees_and_spacings(),
-            NestedMetaItem::Literal(ref lit) => vec![lit.token_tree().into()],
+            NestedMetaItem::Literal(ref lit) => vec![TokenTree::Token(lit.to_token()).into()],
         }
     }
 
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 97966cc3260..575552c4dce 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -365,18 +365,16 @@ pub fn visit_mac_args<T: MutVisitor>(args: &mut MacArgs, vis: &mut T) {
             visit_delim_span(dspan, vis);
             visit_tts(tokens, vis);
         }
-        MacArgs::Eq(eq_span, tokens) => {
+        MacArgs::Eq(eq_span, token) => {
             vis.visit_span(eq_span);
-            visit_tts(tokens, vis);
-            // The value in `#[key = VALUE]` must be visited as an expression for backward
-            // compatibility, so that macros can be expanded in that position.
-            if !vis.token_visiting_enabled() {
-                match Lrc::make_mut(&mut tokens.0).get_mut(0) {
-                    Some((TokenTree::Token(token), _spacing)) => match &mut token.kind {
-                        token::Interpolated(nt) => match Lrc::make_mut(nt) {
-                            token::NtExpr(expr) => vis.visit_expr(expr),
-                            t => panic!("unexpected token in key-value attribute: {:?}", t),
-                        },
+            if vis.token_visiting_enabled() {
+                visit_token(token, vis);
+            } else {
+                // The value in `#[key = VALUE]` must be visited as an expression for backward
+                // compatibility, so that macros can be expanded in that position.
+                match &mut token.kind {
+                    token::Interpolated(nt) => match Lrc::make_mut(nt) {
+                        token::NtExpr(expr) => vis.visit_expr(expr),
                         t => panic!("unexpected token in key-value attribute: {:?}", t),
                     },
                     t => panic!("unexpected token in key-value attribute: {:?}", t),
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index b311f9fdcb9..90bfb01d6c7 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -771,7 +771,7 @@ impl fmt::Display for NonterminalKind {
 }
 
 impl Nonterminal {
-    fn span(&self) -> Span {
+    pub fn span(&self) -> Span {
         match self {
             NtItem(item) => item.span,
             NtBlock(block) => block.span,
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index 0550f53a96f..00354b42ebb 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -1,15 +1,15 @@
 //! # Token Streams
 //!
 //! `TokenStream`s represent syntactic objects before they are converted into ASTs.
-//! A `TokenStream` is, roughly speaking, a sequence (eg stream) of `TokenTree`s,
-//! which are themselves a single `Token` or a `Delimited` subsequence of tokens.
+//! A `TokenStream` is, roughly speaking, a sequence of [`TokenTree`]s,
+//! which are themselves a single [`Token`] or a `Delimited` subsequence of tokens.
 //!
 //! ## Ownership
 //!
 //! `TokenStream`s are persistent data structures constructed as ropes with reference
 //! counted-children. In general, this means that calling an operation on a `TokenStream`
 //! (such as `slice`) produces an entirely new `TokenStream` from the borrowed reference to
-//! the original. This essentially coerces `TokenStream`s into 'views' of their subparts,
+//! the original. This essentially coerces `TokenStream`s into "views" of their subparts,
 //! and a borrowed `TokenStream` is sufficient to build an owned `TokenStream` without taking
 //! ownership of the original.
 
@@ -24,9 +24,9 @@ use smallvec::{smallvec, SmallVec};
 
 use std::{fmt, iter, mem};
 
-/// When the main rust parser encounters a syntax-extension invocation, it
-/// parses the arguments to the invocation as a token-tree. This is a very
-/// loose structure, such that all sorts of different AST-fragments can
+/// When the main Rust parser encounters a syntax-extension invocation, it
+/// parses the arguments to the invocation as a token tree. This is a very
+/// loose structure, such that all sorts of different AST fragments can
 /// be passed to syntax extensions using a uniform type.
 ///
 /// If the syntax extension is an MBE macro, it will attempt to match its
@@ -38,9 +38,9 @@ use std::{fmt, iter, mem};
 /// Nothing special happens to misnamed or misplaced `SubstNt`s.
 #[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
 pub enum TokenTree {
-    /// A single token
+    /// A single token.
     Token(Token),
-    /// A delimited sequence of token trees
+    /// A delimited sequence of token trees.
     Delimited(DelimSpan, DelimToken, TokenStream),
 }
 
@@ -62,7 +62,7 @@ where
 }
 
 impl TokenTree {
-    /// Checks if this TokenTree is equal to the other, regardless of span information.
+    /// Checks if this `TokenTree` is equal to the other, regardless of span information.
     pub fn eq_unspanned(&self, other: &TokenTree) -> bool {
         match (self, other) {
             (TokenTree::Token(token), TokenTree::Token(token2)) => token.kind == token2.kind,
@@ -73,7 +73,7 @@ impl TokenTree {
         }
     }
 
-    /// Retrieves the TokenTree's span.
+    /// Retrieves the `TokenTree`'s span.
     pub fn span(&self) -> Span {
         match self {
             TokenTree::Token(token) => token.span,
@@ -140,7 +140,7 @@ impl CreateTokenStream for TokenStream {
     }
 }
 
-/// A lazy version of `TokenStream`, which defers creation
+/// A lazy version of [`TokenStream`], which defers creation
 /// of an actual `TokenStream` until it is needed.
 /// `Box` is here only to reduce the structure size.
 #[derive(Clone)]
@@ -188,11 +188,12 @@ impl<CTX> HashStable<CTX> for LazyTokenStream {
     }
 }
 
-/// A `TokenStream` is an abstract sequence of tokens, organized into `TokenTree`s.
+/// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s.
 ///
 /// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s
 /// instead of a representation of the abstract syntax tree.
-/// Today's `TokenTree`s can still contain AST via `token::Interpolated` for back-compat.
+/// Today's `TokenTree`s can still contain AST via `token::Interpolated` for
+/// backwards compatability.
 #[derive(Clone, Debug, Default, Encodable, Decodable)]
 pub struct TokenStream(pub(crate) Lrc<Vec<TreeAndSpacing>>);
 
@@ -429,7 +430,7 @@ impl TokenStreamBuilder {
     }
 }
 
-/// By-reference iterator over a `TokenStream`.
+/// By-reference iterator over a [`TokenStream`].
 #[derive(Clone)]
 pub struct CursorRef<'t> {
     stream: &'t TokenStream,
@@ -457,8 +458,8 @@ impl<'t> Iterator for CursorRef<'t> {
     }
 }
 
-/// Owning by-value iterator over a `TokenStream`.
-/// FIXME: Many uses of this can be replaced with by-reference iterator to avoid clones.
+/// Owning by-value iterator over a [`TokenStream`].
+// FIXME: Many uses of this can be replaced with by-reference iterator to avoid clones.
 #[derive(Clone)]
 pub struct Cursor {
     pub stream: TokenStream,
diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs
index f6f1ad0a9c3..106ffb2a0fd 100644
--- a/compiler/rustc_ast/src/util/literal.rs
+++ b/compiler/rustc_ast/src/util/literal.rs
@@ -2,7 +2,6 @@
 
 use crate::ast::{self, Lit, LitKind};
 use crate::token::{self, Token};
-use crate::tokenstream::TokenTree;
 
 use rustc_lexer::unescape::{unescape_byte, unescape_char};
 use rustc_lexer::unescape::{unescape_byte_literal, unescape_literal, Mode};
@@ -225,13 +224,13 @@ impl Lit {
         Lit { token: kind.to_lit_token(), kind, span }
     }
 
-    /// Losslessly convert an AST literal into a token stream.
-    pub fn token_tree(&self) -> TokenTree {
-        let token = match self.token.kind {
+    /// Losslessly convert an AST literal into a token.
+    pub fn to_token(&self) -> Token {
+        let kind = match self.token.kind {
             token::Bool => token::Ident(self.token.symbol, false),
             _ => token::Literal(self.token),
         };
-        TokenTree::token(token, self.span)
+        Token::new(kind, self.span)
     }
 }
 
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index a696626f8c4..2ba1c49edfa 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -15,7 +15,6 @@
 
 use crate::ast::*;
 use crate::token;
-use crate::tokenstream::TokenTree;
 
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::Span;
@@ -905,12 +904,9 @@ pub fn walk_mac_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a MacArgs) {
         MacArgs::Delimited(_dspan, _delim, _tokens) => {}
         // The value in `#[key = VALUE]` must be visited as an expression for backward
         // compatibility, so that macros can be expanded in that position.
-        MacArgs::Eq(_eq_span, tokens) => match tokens.trees_ref().next() {
-            Some(TokenTree::Token(token)) => match &token.kind {
-                token::Interpolated(nt) => match &**nt {
-                    token::NtExpr(expr) => visitor.visit_expr(expr),
-                    t => panic!("unexpected token in key-value attribute: {:?}", t),
-                },
+        MacArgs::Eq(_eq_span, token) => match &token.kind {
+            token::Interpolated(nt) => match &**nt {
+                token::NtExpr(expr) => visitor.visit_expr(expr),
                 t => panic!("unexpected token in key-value attribute: {:?}", t),
             },
             t => panic!("unexpected token in key-value attribute: {:?}", t),
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index f81dc39842c..89557c29dd1 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -57,7 +57,7 @@ use rustc_session::lint::{builtin::BARE_TRAIT_OBJECTS, BuiltinLintDiagnostics, L
 use rustc_session::parse::ParseSess;
 use rustc_session::Session;
 use rustc_span::hygiene::ExpnId;
-use rustc_span::source_map::{respan, DesugaringKind, ExpnData, ExpnKind};
+use rustc_span::source_map::{respan, DesugaringKind};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
 
@@ -206,8 +206,7 @@ pub trait ResolverAstLowering {
     ) -> LocalDefId;
 }
 
-type NtToTokenstream =
-    fn(&Nonterminal, &ParseSess, Span, CanSynthesizeMissingTokens) -> TokenStream;
+type NtToTokenstream = fn(&Nonterminal, &ParseSess, CanSynthesizeMissingTokens) -> TokenStream;
 
 /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
 /// and if so, what meaning it has.
@@ -417,12 +416,7 @@ impl<'a> TokenStreamLowering<'a> {
     fn lower_token(&mut self, token: Token) -> TokenStream {
         match token.kind {
             token::Interpolated(nt) => {
-                let tts = (self.nt_to_tokenstream)(
-                    &nt,
-                    self.parse_sess,
-                    token.span,
-                    self.synthesize_tokens,
-                );
+                let tts = (self.nt_to_tokenstream)(&nt, self.parse_sess, self.synthesize_tokens);
                 TokenTree::Delimited(
                     DelimSpan::from_single(token.span),
                     DelimToken::NoDelim,
@@ -743,10 +737,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         span: Span,
         allow_internal_unstable: Option<Lrc<[Symbol]>>,
     ) -> Span {
-        span.fresh_expansion(ExpnData {
-            allow_internal_unstable,
-            ..ExpnData::default(ExpnKind::Desugaring(reason), span, self.sess.edition(), None)
-        })
+        span.mark_with_reason(allow_internal_unstable, reason, self.sess.edition())
     }
 
     fn with_anonymous_lifetime_mode<R>(
@@ -1022,10 +1013,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             // This is an inert key-value attribute - it will never be visible to macros
             // after it gets lowered to HIR. Therefore, we can synthesize tokens with fake
             // spans to handle nonterminals in `#[doc]` (e.g. `#[doc = $e]`).
-            MacArgs::Eq(eq_span, ref tokens) => MacArgs::Eq(
-                eq_span,
-                self.lower_token_stream(tokens.clone(), CanSynthesizeMissingTokens::Yes),
-            ),
+            MacArgs::Eq(eq_span, ref token) => {
+                // In valid code the value is always representable as a single literal token.
+                fn unwrap_single_token(sess: &Session, tokens: TokenStream, span: Span) -> Token {
+                    if tokens.len() != 1 {
+                        sess.diagnostic()
+                            .delay_span_bug(span, "multiple tokens in key-value attribute's value");
+                    }
+                    match tokens.into_trees().next() {
+                        Some(TokenTree::Token(token)) => token,
+                        Some(TokenTree::Delimited(_, delim, tokens)) => {
+                            if delim != token::NoDelim {
+                                sess.diagnostic().delay_span_bug(
+                                    span,
+                                    "unexpected delimiter in key-value attribute's value",
+                                )
+                            }
+                            unwrap_single_token(sess, tokens, span)
+                        }
+                        None => Token::dummy(),
+                    }
+                }
+
+                let tokens = TokenStreamLowering {
+                    parse_sess: &self.sess.parse_sess,
+                    synthesize_tokens: CanSynthesizeMissingTokens::Yes,
+                    nt_to_tokenstream: self.nt_to_tokenstream,
+                }
+                .lower_token(token.clone());
+                MacArgs::Eq(eq_span, unwrap_single_token(self.sess, tokens, token.span))
+            }
         }
     }
 
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index e172f9d71ff..baeadb216dc 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -16,7 +16,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{error_code, pluralize, struct_span_err, Applicability};
 use rustc_parse::validate_attr;
 use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY;
-use rustc_session::lint::LintBuffer;
+use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::Session;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Span;
@@ -213,14 +213,14 @@ impl<'a> AstValidator<'a> {
         err.emit();
     }
 
-    fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, bool)) {
+    fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
         for Param { pat, .. } in &decl.inputs {
             match pat.kind {
                 PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, None) | PatKind::Wild => {}
-                PatKind::Ident(BindingMode::ByValue(Mutability::Mut), _, None) => {
-                    report_err(pat.span, true)
+                PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ident, None) => {
+                    report_err(pat.span, Some(ident), true)
                 }
-                _ => report_err(pat.span, false),
+                _ => report_err(pat.span, None, false),
             }
         }
     }
@@ -834,7 +834,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         match ty.kind {
             TyKind::BareFn(ref bfty) => {
                 self.check_fn_decl(&bfty.decl, SelfSemantic::No);
-                Self::check_decl_no_pat(&bfty.decl, |span, _| {
+                Self::check_decl_no_pat(&bfty.decl, |span, _, _| {
                     struct_span_err!(
                         self.session,
                         span,
@@ -1212,11 +1212,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
     }
 
     fn visit_pat(&mut self, pat: &'a Pat) {
-        match pat.kind {
-            PatKind::Lit(ref expr) => {
+        match &pat.kind {
+            PatKind::Lit(expr) => {
                 self.check_expr_within_pat(expr, false);
             }
-            PatKind::Range(ref start, ref end, _) => {
+            PatKind::Range(start, end, _) => {
                 if let Some(expr) = start {
                     self.check_expr_within_pat(expr, true);
                 }
@@ -1289,7 +1289,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
 
         // Functions without bodies cannot have patterns.
         if let FnKind::Fn(ctxt, _, sig, _, None) = fk {
-            Self::check_decl_no_pat(&sig.decl, |span, mut_ident| {
+            Self::check_decl_no_pat(&sig.decl, |span, ident, mut_ident| {
                 let (code, msg, label) = match ctxt {
                     FnCtxt::Foreign => (
                         error_code!(E0130),
@@ -1303,7 +1303,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     ),
                 };
                 if mut_ident && matches!(ctxt, FnCtxt::Assoc(_)) {
-                    self.lint_buffer.buffer_lint(PATTERNS_IN_FNS_WITHOUT_BODY, id, span, msg);
+                    if let Some(ident) = ident {
+                        let diag = BuiltinLintDiagnostics::PatternsInFnsWithoutBody(span, ident);
+                        self.lint_buffer.buffer_lint_with_diagnostic(
+                            PATTERNS_IN_FNS_WITHOUT_BODY,
+                            id,
+                            span,
+                            msg,
+                            diag,
+                        )
+                    }
                 } else {
                     self.err_handler()
                         .struct_span_err(span, msg)
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 435f32535b6..d65bc820f8f 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -14,6 +14,17 @@ use rustc_span::Span;
 use tracing::debug;
 
 macro_rules! gate_feature_fn {
+    ($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
+        let (visitor, has_feature, span, name, explain, help) =
+            (&*$visitor, $has_feature, $span, $name, $explain, $help);
+        let has_feature: bool = has_feature(visitor.features);
+        debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
+        if !has_feature && !span.allows_unstable($name) {
+            feature_err_issue(&visitor.sess.parse_sess, name, span, GateIssue::Language, explain)
+                .help(help)
+                .emit();
+        }
+    }};
     ($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
         let (visitor, has_feature, span, name, explain) =
             (&*$visitor, $has_feature, $span, $name, $explain);
@@ -27,6 +38,9 @@ macro_rules! gate_feature_fn {
 }
 
 macro_rules! gate_feature_post {
+    ($visitor: expr, $feature: ident, $span: expr, $explain: expr, $help: expr) => {
+        gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain, $help)
+    };
     ($visitor: expr, $feature: ident, $span: expr, $explain: expr) => {
         gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
     };
@@ -597,6 +611,13 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
 
     let spans = sess.parse_sess.gated_spans.spans.borrow();
     macro_rules! gate_all {
+        ($gate:ident, $msg:literal, $help:literal) => {
+            if let Some(spans) = spans.get(&sym::$gate) {
+                for span in spans {
+                    gate_feature_post!(&visitor, $gate, *span, $msg, $help);
+                }
+            }
+        };
         ($gate:ident, $msg:literal) => {
             if let Some(spans) = spans.get(&sym::$gate) {
                 for span in spans {
@@ -607,7 +628,11 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
     }
     gate_all!(if_let_guard, "`if let` guards are experimental");
     gate_all!(let_chains, "`let` expressions in this position are experimental");
-    gate_all!(async_closure, "async closures are unstable");
+    gate_all!(
+        async_closure,
+        "async closures are unstable",
+        "to use an async block, remove the `||`: `async {`"
+    );
     gate_all!(generators, "yield syntax is experimental");
     gate_all!(or_patterns, "or-patterns syntax is experimental");
     gate_all!(raw_ref_op, "raw address of syntax is experimental");
diff --git a/compiler/rustc_ast_pretty/src/pprust/mod.rs b/compiler/rustc_ast_pretty/src/pprust/mod.rs
index b34ea41ab55..b88699f6ee1 100644
--- a/compiler/rustc_ast_pretty/src/pprust/mod.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/mod.rs
@@ -8,11 +8,6 @@ use rustc_ast as ast;
 use rustc_ast::token::{Nonterminal, Token, TokenKind};
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
 
-pub fn nonterminal_to_string_no_extra_parens(nt: &Nonterminal) -> String {
-    let state = State::without_insert_extra_parens();
-    state.nonterminal_to_string(nt)
-}
-
 pub fn nonterminal_to_string(nt: &Nonterminal) -> String {
     State::new().nonterminal_to_string(nt)
 }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index bdd378b34e1..2c8caf68f00 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -88,13 +88,6 @@ pub struct State<'a> {
     comments: Option<Comments<'a>>,
     ann: &'a (dyn PpAnn + 'a),
     is_expanded: bool,
-    // If `true`, additional parenthesis (separate from `ExprKind::Paren`)
-    // are inserted to ensure that proper precedence is preserved
-    // in the pretty-printed output.
-    //
-    // This is usually `true`, except when performing the pretty-print/reparse
-    // check in `nt_to_tokenstream`
-    insert_extra_parens: bool,
 }
 
 crate const INDENT_UNIT: usize = 4;
@@ -115,7 +108,6 @@ pub fn print_crate<'a>(
         comments: Some(Comments::new(sm, filename, input)),
         ann,
         is_expanded,
-        insert_extra_parens: true,
     };
 
     if is_expanded && !krate.attrs.iter().any(|attr| attr.has_name(sym::no_core)) {
@@ -235,7 +227,6 @@ impl std::ops::DerefMut for State<'_> {
 }
 
 pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::DerefMut {
-    fn insert_extra_parens(&self) -> bool;
     fn comments(&mut self) -> &mut Option<Comments<'a>>;
     fn print_ident(&mut self, ident: Ident);
     fn print_generic_args(&mut self, args: &ast::GenericArgs, colons_before_params: bool);
@@ -454,10 +445,11 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
             ),
             MacArgs::Empty | MacArgs::Eq(..) => {
                 self.print_path(&item.path, false, 0);
-                if let MacArgs::Eq(_, tokens) = &item.args {
+                if let MacArgs::Eq(_, token) = &item.args {
                     self.space();
                     self.word_space("=");
-                    self.print_tts(tokens, true);
+                    let token_str = self.token_to_string_ext(token, true);
+                    self.word(token_str);
                 }
             }
         }
@@ -819,16 +811,12 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
 
     fn to_string(&self, f: impl FnOnce(&mut State<'_>)) -> String {
         let mut printer = State::new();
-        printer.insert_extra_parens = self.insert_extra_parens();
         f(&mut printer);
         printer.s.eof()
     }
 }
 
 impl<'a> PrintState<'a> for State<'a> {
-    fn insert_extra_parens(&self) -> bool {
-        self.insert_extra_parens
-    }
     fn comments(&mut self) -> &mut Option<Comments<'a>> {
         &mut self.comments
     }
@@ -865,17 +853,7 @@ impl<'a> PrintState<'a> for State<'a> {
 
 impl<'a> State<'a> {
     pub fn new() -> State<'a> {
-        State {
-            s: pp::mk_printer(),
-            comments: None,
-            ann: &NoAnn,
-            is_expanded: false,
-            insert_extra_parens: true,
-        }
-    }
-
-    pub(super) fn without_insert_extra_parens() -> State<'a> {
-        State { insert_extra_parens: false, ..State::new() }
+        State { s: pp::mk_printer(), comments: None, ann: &NoAnn, is_expanded: false }
     }
 
     // Synthesizes a comment that was not textually present in the original source
@@ -1680,8 +1658,7 @@ impl<'a> State<'a> {
     }
 
     /// Prints `expr` or `(expr)` when `needs_par` holds.
-    fn print_expr_cond_paren(&mut self, expr: &ast::Expr, mut needs_par: bool) {
-        needs_par &= self.insert_extra_parens;
+    fn print_expr_cond_paren(&mut self, expr: &ast::Expr, needs_par: bool) {
         if needs_par {
             self.popen();
         }
@@ -2677,7 +2654,6 @@ impl<'a> State<'a> {
                     s.print_type_bounds(":", &param.bounds);
                     if let Some(ref _default) = default {
                         // FIXME(const_generics_defaults): print the `default` value here
-                        todo!();
                     }
                 }
             }
diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs
index 868f863b990..7114b987680 100644
--- a/compiler/rustc_builtin_macros/src/deriving/hash.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs
@@ -48,8 +48,8 @@ pub fn expand_deriving_hash(
 }
 
 fn hash_substructure(cx: &mut ExtCtxt<'_>, trait_span: Span, substr: &Substructure<'_>) -> P<Expr> {
-    let state_expr = match &substr.nonself_args {
-        &[o_f] => o_f,
+    let state_expr = match substr.nonself_args {
+        [o_f] => o_f,
         _ => cx.span_bug(trait_span, "incorrect number of arguments in `derive(Hash)`"),
     };
     let call_hash = |span, thing_expr| {
@@ -64,9 +64,9 @@ fn hash_substructure(cx: &mut ExtCtxt<'_>, trait_span: Span, substr: &Substructu
     };
     let mut stmts = Vec::new();
 
-    let fields = match *substr.fields {
-        Struct(_, ref fs) | EnumMatching(_, 1, .., ref fs) => fs,
-        EnumMatching(.., ref fs) => {
+    let fields = match substr.fields {
+        Struct(_, fs) | EnumMatching(_, 1, .., fs) => fs,
+        EnumMatching(.., fs) => {
             let variant_value = deriving::call_intrinsic(
                 cx,
                 trait_span,
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 97cadb913ca..635890644d0 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -14,10 +14,9 @@ extern crate proc_macro;
 
 use crate::deriving::*;
 
-use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtension, SyntaxExtensionKind};
+use rustc_expand::base::{MacroExpanderFn, ResolverExpand, SyntaxExtensionKind};
 use rustc_expand::proc_macro::BangProcMacro;
-use rustc_span::edition::Edition;
-use rustc_span::symbol::{sym, Ident};
+use rustc_span::symbol::sym;
 
 mod asm;
 mod assert;
@@ -44,13 +43,8 @@ pub mod proc_macro_harness;
 pub mod standard_library_imports;
 pub mod test_harness;
 
-pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand, edition: Edition) {
-    let mut register = |name, kind| {
-        resolver.register_builtin_macro(
-            Ident::with_dummy_span(name),
-            SyntaxExtension { is_builtin: true, ..SyntaxExtension::default(kind, edition) },
-        )
-    };
+pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
+    let mut register = |name, kind| resolver.register_builtin_macro(name, kind);
     macro register_bang($($name:ident: $f:expr,)*) {
         $(register(sym::$name, SyntaxExtensionKind::LegacyBang(Box::new($f as MacroExpanderFn)));)*
     }
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 230e11f274e..68f319ade1e 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -164,7 +164,8 @@ pub fn target_machine_factory(
 
     let code_model = to_llvm_code_model(sess.code_model());
 
-    let features = attributes::llvm_target_features(sess).collect::<Vec<_>>();
+    let mut features = llvm_util::handle_native_features(sess);
+    features.extend(attributes::llvm_target_features(sess).map(|s| s.to_owned()));
     let mut singlethread = sess.target.singlethread;
 
     // On the wasm target once the `atomics` feature is enabled that means that
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 707aaa2b53f..e359d9f8c9c 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1708,6 +1708,10 @@ extern "C" {
         PM: &PassManager<'_>,
     );
 
+    pub fn LLVMGetHostCPUFeatures() -> *mut c_char;
+
+    pub fn LLVMDisposeMessage(message: *mut c_char);
+
     // Stuff that's in llvm-wrapper/ because it's not upstream yet.
 
     /// Opens an object file.
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index a3139ce5a34..a9d57ea8b8a 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -8,7 +8,7 @@ use rustc_session::config::PrintRequest;
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::{MergeFunctions, PanicStrategy};
-use std::ffi::CString;
+use std::ffi::{CStr, CString};
 
 use std::slice;
 use std::str;
@@ -221,6 +221,37 @@ pub fn target_cpu(sess: &Session) -> &str {
     handle_native(name)
 }
 
+pub fn handle_native_features(sess: &Session) -> Vec<String> {
+    match sess.opts.cg.target_cpu {
+        Some(ref s) => {
+            if s != "native" {
+                return vec![];
+            }
+
+            let features_string = unsafe {
+                let ptr = llvm::LLVMGetHostCPUFeatures();
+                let features_string = if !ptr.is_null() {
+                    CStr::from_ptr(ptr)
+                        .to_str()
+                        .unwrap_or_else(|e| {
+                            bug!("LLVM returned a non-utf8 features string: {}", e);
+                        })
+                        .to_owned()
+                } else {
+                    bug!("could not allocate host CPU features, LLVM returned a `null` string");
+                };
+
+                llvm::LLVMDisposeMessage(ptr);
+
+                features_string
+            };
+
+            features_string.split(",").map(|s| s.to_owned()).collect()
+        }
+        None => vec![],
+    }
+}
+
 pub fn tune_cpu(sess: &Session) -> Option<&str> {
     match sess.opts.debugging_opts.tune_cpu {
         Some(ref s) => Some(handle_native(&**s)),
diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs
index 3fc56eecdd0..07fde27b5a3 100644
--- a/compiler/rustc_codegen_llvm/src/va_arg.rs
+++ b/compiler/rustc_codegen_llvm/src/va_arg.rs
@@ -9,7 +9,7 @@ use rustc_codegen_ssa::{
 };
 use rustc_middle::ty::layout::HasTyCtxt;
 use rustc_middle::ty::Ty;
-use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size};
+use rustc_target::abi::{Align, Endian, HasDataLayout, LayoutOf, Size};
 
 fn round_pointer_up_to_alignment(
     bx: &mut Builder<'a, 'll, 'tcx>,
@@ -52,7 +52,7 @@ fn emit_direct_ptr_va_arg(
     let next = bx.inbounds_gep(addr, &[full_direct_size]);
     bx.store(next, va_list_addr, bx.tcx().data_layout.pointer_align.abi);
 
-    if size.bytes() < slot_size.bytes() && &*bx.tcx().sess.target.endian == "big" {
+    if size.bytes() < slot_size.bytes() && bx.tcx().sess.target.endian == Endian::Big {
         let adjusted_size = bx.cx().const_i32((slot_size.bytes() - size.bytes()) as i32);
         let adjusted = bx.inbounds_gep(addr, &[adjusted_size]);
         (bx.bitcast(adjusted, bx.cx().type_ptr_to(llty)), addr_align)
@@ -105,7 +105,7 @@ fn emit_aapcs_va_arg(
     let mut end = bx.build_sibling_block("va_arg.end");
     let zero = bx.const_i32(0);
     let offset_align = Align::from_bytes(4).unwrap();
-    assert!(&*bx.tcx().sess.target.endian == "little");
+    assert_eq!(bx.tcx().sess.target.endian, Endian::Little);
 
     let gr_type = target_ty.is_any_ptr() || target_ty.is_integral();
     let (reg_off, reg_top_index, slot_size) = if gr_type {
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index a3a2ef04175..728795cf50b 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -895,7 +895,7 @@ fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) {
         .unwrap_or_default();
 
     match sess.opts.target_triple.triple() {
-        "x86_64-apple-darwin" => {
+        "aarch64-apple-darwin" | "x86_64-apple-darwin" => {
             // On Apple platforms, the sanitizer is always built as a dylib, and
             // LLVM will link to `@rpath/*.dylib`, so we need to specify an
             // rpath to the library as well (the rpath should be absolute, see
@@ -1276,6 +1276,7 @@ fn exec_linker(
 
 fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind {
     let kind = match (crate_type, sess.crt_static(Some(crate_type)), sess.relocation_model()) {
+        (CrateType::Executable, _, _) if sess.is_wasi_reactor() => LinkOutputKind::WasiReactorExe,
         (CrateType::Executable, false, RelocModel::Pic) => LinkOutputKind::DynamicPicExe,
         (CrateType::Executable, false, _) => LinkOutputKind::DynamicNoPicExe,
         (CrateType::Executable, true, RelocModel::Pic) => LinkOutputKind::StaticPicExe,
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 3df956c465e..bb35e7ec894 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -314,6 +314,10 @@ impl<'a> Linker for GccLinker<'a> {
                 self.cmd.arg("-static");
                 self.build_dylib(out_filename);
             }
+            LinkOutputKind::WasiReactorExe => {
+                self.linker_arg("--entry");
+                self.linker_arg("_initialize");
+            }
         }
         // VxWorks compiler driver introduced `--static-crt` flag specifically for rustc,
         // it switches linking for libc and similar system libraries to static without using
@@ -662,6 +666,9 @@ impl<'a> Linker for MsvcLinker<'a> {
                 arg.push(out_filename.with_extension("dll.lib"));
                 self.cmd.arg(arg);
             }
+            LinkOutputKind::WasiReactorExe => {
+                panic!("can't link as reactor on non-wasi target");
+            }
         }
     }
 
@@ -1085,6 +1092,10 @@ impl<'a> Linker for WasmLd<'a> {
             LinkOutputKind::DynamicDylib | LinkOutputKind::StaticDylib => {
                 self.cmd.arg("--no-entry");
             }
+            LinkOutputKind::WasiReactorExe => {
+                self.cmd.arg("--entry");
+                self.cmd.arg("_initialize");
+            }
         }
     }
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index 57e49ba8d1a..b1e372afc65 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -104,7 +104,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
     ) {
         let cx = self.fx.cx;
 
-        if let &[ref proj_base @ .., elem] = place_ref.projection {
+        if let Some((place_base, elem)) = place_ref.last_projection() {
             let mut base_context = if context.is_mutating_use() {
                 PlaceContext::MutatingUse(MutatingUseContext::Projection)
             } else {
@@ -119,8 +119,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
                 )
             );
             if is_consume {
-                let base_ty =
-                    mir::Place::ty_from(place_ref.local, proj_base, self.fx.mir, cx.tcx());
+                let base_ty = mir::PlaceRef::ty(&place_base, self.fx.mir, cx.tcx());
                 let base_ty = self.fx.monomorphize(base_ty);
 
                 // ZSTs don't require any actual memory access.
@@ -175,11 +174,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
                 base_context = context;
             }
 
-            self.process_place(
-                &mir::PlaceRef { local: place_ref.local, projection: proj_base },
-                base_context,
-                location,
-            );
+            self.process_place(&place_base, base_context, location);
             // HACK(eddyb) this emulates the old `visit_projection_elem`, this
             // entire `visit_place`-like `process_place` method should be rewritten,
             // now that we have moved to the "slice of projections" representation.
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index e4f4c884470..958e4ebd078 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -178,16 +178,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         // Get the alignment of the field
         let (_, unsized_align) = glue::size_and_align_of_dst(bx, field.ty, meta);
 
-        // Bump the unaligned offset up to the appropriate alignment using the
-        // following expression:
-        //
-        //     (unaligned offset + (align - 1)) & -align
-
-        // Calculate offset.
-        let align_sub_1 = bx.sub(unsized_align, bx.cx().const_usize(1u64));
-        let and_lhs = bx.add(unaligned_offset, align_sub_1);
-        let and_rhs = bx.neg(unsized_align);
-        let offset = bx.and(and_lhs, and_rhs);
+        // Bump the unaligned offset up to the appropriate alignment
+        let offset = round_up_const_value_to_alignment(bx, unaligned_offset, unsized_align);
 
         debug!("struct_field_ptr: DST field offset: {:?}", offset);
 
@@ -514,7 +506,49 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
     pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'tcx>) -> Ty<'tcx> {
         let tcx = self.cx.tcx();
-        let place_ty = mir::Place::ty_from(place_ref.local, place_ref.projection, self.mir, tcx);
+        let place_ty = mir::PlaceRef::ty(&place_ref, self.mir, tcx);
         self.monomorphize(place_ty.ty)
     }
 }
+
+fn round_up_const_value_to_alignment<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
+    bx: &mut Bx,
+    value: Bx::Value,
+    align: Bx::Value,
+) -> Bx::Value {
+    // In pseudo code:
+    //
+    //     if value & (align - 1) == 0 {
+    //         value
+    //     } else {
+    //         (value & !(align - 1)) + align
+    //     }
+    //
+    // Usually this is written without branches as
+    //
+    //     (value + align - 1) & !(align - 1)
+    //
+    // But this formula cannot take advantage of constant `value`. E.g. if `value` is known
+    // at compile time to be `1`, this expression should be optimized to `align`. However,
+    // optimization only holds if `align` is a power of two. Since the optimizer doesn't know
+    // that `align` is a power of two, it cannot perform this optimization.
+    //
+    // Instead we use
+    //
+    //     value + (-value & (align - 1))
+    //
+    // Since `align` is used only once, the expression can be optimized. For `value = 0`
+    // its optimized to `0` even in debug mode.
+    //
+    // NB: The previous version of this code used
+    //
+    //     (value + align - 1) & -align
+    //
+    // Even though `-align == !(align - 1)`, LLVM failed to optimize this even for
+    // `value = 0`. Bug report: https://bugs.llvm.org/show_bug.cgi?id=48559
+    let one = bx.const_usize(1);
+    let align_minus_1 = bx.sub(align, one);
+    let neg_value = bx.neg(value);
+    let offset = bx.and(neg_value, align_minus_1);
+    bx.add(value, offset)
+}
diff --git a/compiler/rustc_data_structures/src/fingerprint.rs b/compiler/rustc_data_structures/src/fingerprint.rs
index 01efcaf6f44..8afe94ac8db 100644
--- a/compiler/rustc_data_structures/src/fingerprint.rs
+++ b/compiler/rustc_data_structures/src/fingerprint.rs
@@ -4,7 +4,7 @@ use rustc_serialize::{
     Decodable, Encodable,
 };
 use std::hash::{Hash, Hasher};
-use std::mem;
+use std::mem::{self, MaybeUninit};
 
 #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy)]
 pub struct Fingerprint(u64, u64);
@@ -61,7 +61,7 @@ impl Fingerprint {
     }
 
     pub fn decode_opaque(decoder: &mut opaque::Decoder<'_>) -> Result<Fingerprint, String> {
-        let mut bytes = [0; 16];
+        let mut bytes: [MaybeUninit<u8>; 16] = MaybeUninit::uninit_array();
 
         decoder.read_raw_bytes(&mut bytes)?;
 
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index d57ab2433ad..c2a0d8ef7ea 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -566,6 +566,25 @@ fn stdout_isatty() -> bool {
     }
 }
 
+// FIXME remove these and use winapi 0.3 instead
+#[cfg(unix)]
+fn stderr_isatty() -> bool {
+    unsafe { libc::isatty(libc::STDERR_FILENO) != 0 }
+}
+
+#[cfg(windows)]
+fn stderr_isatty() -> bool {
+    use winapi::um::consoleapi::GetConsoleMode;
+    use winapi::um::processenv::GetStdHandle;
+    use winapi::um::winbase::STD_ERROR_HANDLE;
+
+    unsafe {
+        let handle = GetStdHandle(STD_ERROR_HANDLE);
+        let mut out = 0;
+        GetConsoleMode(handle, &mut out) != 0
+    }
+}
+
 fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
     let normalised =
         if code.starts_with('E') { code.to_string() } else { format!("E{0:0>4}", code) };
@@ -1290,7 +1309,7 @@ pub fn init_env_logger(env: &str) {
         Ok(value) => match value.as_ref() {
             "always" => true,
             "never" => false,
-            "auto" => stdout_isatty(),
+            "auto" => stderr_isatty(),
             _ => early_error(
                 ErrorOutputType::default(),
                 &format!(
@@ -1299,7 +1318,7 @@ pub fn init_env_logger(env: &str) {
                 ),
             ),
         },
-        Err(std::env::VarError::NotPresent) => stdout_isatty(),
+        Err(std::env::VarError::NotPresent) => stderr_isatty(),
         Err(std::env::VarError::NotUnicode(_value)) => early_error(
             ErrorOutputType::default(),
             "non-Unicode log color value: expected one of always, never, or auto",
diff --git a/compiler/rustc_error_codes/src/error_codes/E0435.md b/compiler/rustc_error_codes/src/error_codes/E0435.md
index 424e5ce1e2e..798a20d48b6 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0435.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0435.md
@@ -7,6 +7,12 @@ let foo = 42;
 let a: [u8; foo]; // error: attempt to use a non-constant value in a constant
 ```
 
+'constant' means 'a compile-time value'.
+
+More details can be found in the [Variables and Mutability] section of the book.
+
+[Variables and Mutability]: https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants
+
 To fix this error, please replace the value with a constant. Example:
 
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0492.md b/compiler/rustc_error_codes/src/error_codes/E0492.md
index 1caa59999ae..79e7c069a91 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0492.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0492.md
@@ -6,7 +6,7 @@ Erroneous code example:
 use std::sync::atomic::AtomicUsize;
 
 const A: AtomicUsize = AtomicUsize::new(0);
-static B: &'static AtomicUsize = &A;
+const B: &'static AtomicUsize = &A;
 // error: cannot borrow a constant which may contain interior mutability,
 //        create a static instead
 ```
@@ -18,7 +18,7 @@ can't be changed via a shared `&` pointer, but interior mutability would allow
 it. That is, a constant value could be mutated. On the other hand, a `static` is
 explicitly a single memory location, which can be mutated at will.
 
-So, in order to solve this error, either use statics which are `Sync`:
+So, in order to solve this error, use statics which are `Sync`:
 
 ```
 use std::sync::atomic::AtomicUsize;
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 32104e6f00d..00882bb287a 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -644,6 +644,8 @@ impl EmitterWriter {
         code_offset: usize,
         margin: Margin,
     ) {
+        // Tabs are assumed to have been replaced by spaces in calling code.
+        assert!(!source_string.contains('\t'));
         let line_len = source_string.len();
         // Create the source line we will highlight.
         let left = margin.left(line_len);
@@ -707,7 +709,7 @@ impl EmitterWriter {
         }
 
         let source_string = match file.get_line(line.line_index - 1) {
-            Some(s) => s,
+            Some(s) => replace_tabs(&*s),
             None => return Vec::new(),
         };
 
@@ -1376,8 +1378,17 @@ impl EmitterWriter {
                     let file = annotated_file.file.clone();
                     let line = &annotated_file.lines[line_idx];
                     if let Some(source_string) = file.get_line(line.line_index - 1) {
-                        let leading_whitespace =
-                            source_string.chars().take_while(|c| c.is_whitespace()).count();
+                        let leading_whitespace = source_string
+                            .chars()
+                            .take_while(|c| c.is_whitespace())
+                            .map(|c| {
+                                match c {
+                                    // Tabs are displayed as 4 spaces
+                                    '\t' => 4,
+                                    _ => 1,
+                                }
+                            })
+                            .sum();
                         if source_string.chars().any(|c| !c.is_whitespace()) {
                             whitespace_margin = min(whitespace_margin, leading_whitespace);
                         }
@@ -1502,7 +1513,7 @@ impl EmitterWriter {
 
                             self.draw_line(
                                 &mut buffer,
-                                &unannotated_line,
+                                &replace_tabs(&unannotated_line),
                                 annotated_file.lines[line_idx + 1].line_index - 1,
                                 last_buffer_line_num,
                                 width_offset,
@@ -1598,7 +1609,7 @@ impl EmitterWriter {
                 );
                 // print the suggestion
                 draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
-                buffer.append(row_num, line, Style::NoStyle);
+                buffer.append(row_num, &replace_tabs(line), Style::NoStyle);
                 row_num += 1;
             }
 
@@ -1930,6 +1941,10 @@ impl FileWithAnnotatedLines {
     }
 }
 
+fn replace_tabs(str: &str) -> String {
+    str.replace('\t', "    ")
+}
+
 fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) {
     buffer.puts(line, col, "| ", Style::LineNumber);
 }
diff --git a/compiler/rustc_errors/src/styled_buffer.rs b/compiler/rustc_errors/src/styled_buffer.rs
index f2d255d7d95..a4dd0f391bd 100644
--- a/compiler/rustc_errors/src/styled_buffer.rs
+++ b/compiler/rustc_errors/src/styled_buffer.rs
@@ -13,34 +13,13 @@ impl StyledBuffer {
         StyledBuffer { text: vec![], styles: vec![] }
     }
 
-    fn replace_tabs(&mut self) {
-        for (line_pos, line) in self.text.iter_mut().enumerate() {
-            let mut tab_pos = vec![];
-            for (pos, c) in line.iter().enumerate() {
-                if *c == '\t' {
-                    tab_pos.push(pos);
-                }
-            }
-            // start with the tabs at the end of the line to replace them with 4 space chars
-            for pos in tab_pos.iter().rev() {
-                assert_eq!(line.remove(*pos), '\t');
-                // fix the position of the style to match up after replacing the tabs
-                let s = self.styles[line_pos].remove(*pos);
-                for _ in 0..4 {
-                    line.insert(*pos, ' ');
-                    self.styles[line_pos].insert(*pos, s);
-                }
-            }
-        }
-    }
+    pub fn render(&self) -> Vec<Vec<StyledString>> {
+        // Tabs are assumed to have been replaced by spaces in calling code.
+        assert!(self.text.iter().all(|r| !r.contains(&'\t')));
 
-    pub fn render(&mut self) -> Vec<Vec<StyledString>> {
         let mut output: Vec<Vec<StyledString>> = vec![];
         let mut styled_vec: Vec<StyledString> = vec![];
 
-        // before we render, replace tabs with spaces
-        self.replace_tabs();
-
         for (row, row_style) in self.text.iter().zip(&self.styles) {
             let mut current_style = Style::NoStyle;
             let mut current_text = String::new();
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 774a0764d11..2f43940a9dc 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -12,7 +12,7 @@ use rustc_data_structures::sync::{self, Lrc};
 use rustc_errors::{DiagnosticBuilder, ErrorReported};
 use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS};
 use rustc_session::{parse::ParseSess, Limit, Session};
-use rustc_span::def_id::{DefId, LOCAL_CRATE};
+use rustc_span::def_id::DefId;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
 use rustc_span::source_map::SourceMap;
@@ -141,7 +141,7 @@ impl Annotatable {
     }
 
     crate fn into_tokens(self, sess: &ParseSess) -> TokenStream {
-        nt_to_tokenstream(&self.into_nonterminal(), sess, DUMMY_SP, CanSynthesizeMissingTokens::No)
+        nt_to_tokenstream(&self.into_nonterminal(), sess, CanSynthesizeMissingTokens::No)
     }
 
     pub fn expect_item(self) -> P<ast::Item> {
@@ -728,9 +728,7 @@ pub struct SyntaxExtension {
     pub edition: Edition,
     /// Built-in macros have a couple of special properties like availability
     /// in `#[no_implicit_prelude]` modules, so we have to keep this flag.
-    pub is_builtin: bool,
-    /// We have to identify macros providing a `Copy` impl early for compatibility reasons.
-    pub is_derive_copy: bool,
+    pub builtin_name: Option<Symbol>,
 }
 
 impl SyntaxExtension {
@@ -758,8 +756,7 @@ impl SyntaxExtension {
             deprecation: None,
             helper_attrs: Vec::new(),
             edition,
-            is_builtin: false,
-            is_derive_copy: false,
+            builtin_name: None,
             kind,
         }
     }
@@ -785,7 +782,9 @@ impl SyntaxExtension {
             }
         }
 
-        let is_builtin = sess.contains_name(attrs, sym::rustc_builtin_macro);
+        let builtin_name = sess
+            .find_by_name(attrs, sym::rustc_builtin_macro)
+            .map(|a| a.value_str().unwrap_or(name));
         let (stability, const_stability) = attr::find_stability(&sess, attrs, span);
         if const_stability.is_some() {
             sess.parse_sess
@@ -803,8 +802,7 @@ impl SyntaxExtension {
             deprecation: attr::find_deprecation(&sess, attrs).map(|(d, _)| d),
             helper_attrs,
             edition,
-            is_builtin,
-            is_derive_copy: is_builtin && name == sym::Copy,
+            builtin_name,
         }
     }
 
@@ -842,19 +840,17 @@ impl SyntaxExtension {
         descr: Symbol,
         macro_def_id: Option<DefId>,
     ) -> ExpnData {
-        ExpnData {
-            kind: ExpnKind::Macro(self.macro_kind(), descr),
+        ExpnData::new(
+            ExpnKind::Macro(self.macro_kind(), descr),
             parent,
             call_site,
-            def_site: self.span,
-            allow_internal_unstable: self.allow_internal_unstable.clone(),
-            allow_internal_unsafe: self.allow_internal_unsafe,
-            local_inner_macros: self.local_inner_macros,
-            edition: self.edition,
+            self.span,
+            self.allow_internal_unstable.clone(),
+            self.allow_internal_unsafe,
+            self.local_inner_macros,
+            self.edition,
             macro_def_id,
-            krate: LOCAL_CRATE,
-            orig_id: None,
-        }
+        )
     }
 }
 
@@ -872,7 +868,7 @@ pub trait ResolverExpand {
 
     fn resolve_dollar_crates(&mut self);
     fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment);
-    fn register_builtin_macro(&mut self, ident: Ident, ext: SyntaxExtension);
+    fn register_builtin_macro(&mut self, name: Symbol, ext: SyntaxExtensionKind);
 
     fn expansion_for_ast_pass(
         &mut self,
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 5d40d478b96..16913dbb1ab 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -743,7 +743,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                         AttrStyle::Inner => rustc_parse::fake_token_stream(
                             &self.cx.sess.parse_sess,
                             &item.into_nonterminal(),
-                            span,
                         ),
                     };
                     let attr_item = attr.unwrap_normal_item();
@@ -1020,15 +1019,16 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
         // with exception of the derive container case which is not resolved and can get
         // its expansion data immediately.
         let expn_data = match &kind {
-            InvocationKind::DeriveContainer { item, .. } => Some(ExpnData {
-                parent: self.cx.current_expansion.id,
-                ..ExpnData::default(
+            InvocationKind::DeriveContainer { item, .. } => {
+                let mut expn_data = ExpnData::default(
                     ExpnKind::Macro(MacroKind::Attr, sym::derive),
                     item.span(),
                     self.cx.sess.parse_sess.edition,
                     None,
-                )
-            }),
+                );
+                expn_data.parent = self.cx.current_expansion.id;
+                Some(expn_data)
+            }
             _ => None,
         };
         let expn_id = ExpnId::fresh(expn_data);
@@ -1543,13 +1543,8 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
     }
 
     fn visit_item_kind(&mut self, item: &mut ast::ItemKind) {
-        match item {
-            ast::ItemKind::MacroDef(..) => {}
-            _ => {
-                self.cfg.configure_item_kind(item);
-                noop_visit_item_kind(item, self);
-            }
-        }
+        self.cfg.configure_item_kind(item);
+        noop_visit_item_kind(item, self);
     }
 
     fn flat_map_generic_param(
diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs
index ce19e813bb3..d040539cd7e 100644
--- a/compiler/rustc_expand/src/placeholders.rs
+++ b/compiler/rustc_expand/src/placeholders.rs
@@ -258,12 +258,9 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
 
     fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
         match item.kind {
-            ast::ItemKind::MacCall(_) => return self.remove(item.id).make_items(),
-            ast::ItemKind::MacroDef(_) => return smallvec![item],
-            _ => {}
+            ast::ItemKind::MacCall(_) => self.remove(item.id).make_items(),
+            _ => noop_flat_map_item(item, self),
         }
-
-        noop_flat_map_item(item, self)
     }
 
     fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs
index e8e098b6212..02129e9b5e5 100644
--- a/compiler/rustc_expand/src/proc_macro.rs
+++ b/compiler/rustc_expand/src/proc_macro.rs
@@ -94,12 +94,7 @@ impl MultiItemModifier for ProcMacroDerive {
         let input = if item.pretty_printing_compatibility_hack() {
             TokenTree::token(token::Interpolated(Lrc::new(item)), DUMMY_SP).into()
         } else {
-            nt_to_tokenstream(
-                &item,
-                &ecx.sess.parse_sess,
-                DUMMY_SP,
-                CanSynthesizeMissingTokens::Yes,
-            )
+            nt_to_tokenstream(&item, &ecx.sess.parse_sess, CanSynthesizeMissingTokens::Yes)
         };
 
         let server = proc_macro_server::Rustc::new(ecx);
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 02ae842675f..b6195d3bbc4 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -179,7 +179,7 @@ impl FromInternal<(TreeAndSpacing, &'_ ParseSess, &'_ mut Vec<Self>)>
                 {
                     TokenTree::Ident(Ident::new(sess, name.name, is_raw, name.span))
                 } else {
-                    let stream = nt_to_tokenstream(&nt, sess, span, CanSynthesizeMissingTokens::No);
+                    let stream = nt_to_tokenstream(&nt, sess, CanSynthesizeMissingTokens::No);
                     TokenTree::Group(Group {
                         delimiter: Delimiter::None,
                         stream,
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 252e96b47c6..3b54ffbc3f0 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -626,6 +626,9 @@ declare_features! (
     /// Allows const generics to have default values (e.g. `struct Foo<const N: usize = 3>(...);`).
     (active, const_generics_defaults, "1.51.0", Some(44580), None),
 
+    /// Allows references to types with interior mutability within constants
+    (active, const_refs_to_cell, "1.51.0", Some(80384), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index fa8edba629e..3ed5320da73 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -442,7 +442,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // Internal attributes, Macro related:
     // ==========================================================================
 
-    rustc_attr!(rustc_builtin_macro, AssumedUsed, template!(Word), IMPL_DETAIL),
+    rustc_attr!(rustc_builtin_macro, AssumedUsed, template!(Word, NameValueStr: "name"), IMPL_DETAIL),
     rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), INTERNAL_UNSTABLE),
     rustc_attr!(
         rustc_macro_transparency, AssumedUsed,
diff --git a/compiler/rustc_fs_util/src/lib.rs b/compiler/rustc_fs_util/src/lib.rs
index 7742961e65d..87e97c746ef 100644
--- a/compiler/rustc_fs_util/src/lib.rs
+++ b/compiler/rustc_fs_util/src/lib.rs
@@ -62,8 +62,10 @@ pub enum LinkOrCopy {
 pub fn link_or_copy<P: AsRef<Path>, Q: AsRef<Path>>(p: P, q: Q) -> io::Result<LinkOrCopy> {
     let p = p.as_ref();
     let q = q.as_ref();
-    if q.exists() {
-        fs::remove_file(&q)?;
+    match fs::remove_file(&q) {
+        Ok(()) => (),
+        Err(err) if err.kind() == io::ErrorKind::NotFound => (),
+        Err(err) => return Err(err),
     }
 
     match fs::hard_link(p, q) {
diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml
index b24c208c76a..c14165454ed 100644
--- a/compiler/rustc_hir/Cargo.toml
+++ b/compiler/rustc_hir/Cargo.toml
@@ -9,6 +9,7 @@ doctest = false
 
 [dependencies]
 rustc_target = { path = "../rustc_target" }
+rustc_feature = { path = "../rustc_feature" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_index = { path = "../rustc_index" }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index ebeb1bae2a3..acd254ae85c 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -290,6 +290,14 @@ impl GenericArg<'_> {
             GenericArg::Const(_) => "const",
         }
     }
+
+    pub fn to_ord(&self, feats: &rustc_feature::Features) -> ast::ParamKindOrd {
+        match self {
+            GenericArg::Lifetime(_) => ast::ParamKindOrd::Lifetime,
+            GenericArg::Type(_) => ast::ParamKindOrd::Type,
+            GenericArg::Const(_) => ast::ParamKindOrd::Const { unordered: feats.const_generics },
+        }
+    }
 }
 
 #[derive(Debug, HashStable_Generic)]
@@ -378,9 +386,9 @@ impl GenericBound<'_> {
 
     pub fn span(&self) -> Span {
         match self {
-            &GenericBound::Trait(ref t, ..) => t.span,
-            &GenericBound::LangItemTrait(_, span, ..) => span,
-            &GenericBound::Outlives(ref l) => l.span,
+            GenericBound::Trait(t, ..) => t.span,
+            GenericBound::LangItemTrait(_, span, ..) => *span,
+            GenericBound::Outlives(l) => l.span,
         }
     }
 }
@@ -538,9 +546,9 @@ pub enum WherePredicate<'hir> {
 impl WherePredicate<'_> {
     pub fn span(&self) -> Span {
         match self {
-            &WherePredicate::BoundPredicate(ref p) => p.span,
-            &WherePredicate::RegionPredicate(ref p) => p.span,
-            &WherePredicate::EqPredicate(ref p) => p.span,
+            WherePredicate::BoundPredicate(p) => p.span,
+            WherePredicate::RegionPredicate(p) => p.span,
+            WherePredicate::EqPredicate(p) => p.span,
         }
     }
 }
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 87a2434152f..b0e82214cf9 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -896,8 +896,8 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>(
     visitor: &mut V,
     predicate: &'v WherePredicate<'v>,
 ) {
-    match predicate {
-        &WherePredicate::BoundPredicate(WhereBoundPredicate {
+    match *predicate {
+        WherePredicate::BoundPredicate(WhereBoundPredicate {
             ref bounded_ty,
             bounds,
             bound_generic_params,
@@ -907,11 +907,11 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>(
             walk_list!(visitor, visit_param_bound, bounds);
             walk_list!(visitor, visit_generic_param, bound_generic_params);
         }
-        &WherePredicate::RegionPredicate(WhereRegionPredicate { ref lifetime, bounds, .. }) => {
+        WherePredicate::RegionPredicate(WhereRegionPredicate { ref lifetime, bounds, .. }) => {
             visitor.visit_lifetime(lifetime);
             walk_list!(visitor, visit_param_bound, bounds);
         }
-        &WherePredicate::EqPredicate(WhereEqPredicate {
+        WherePredicate::EqPredicate(WhereEqPredicate {
             hir_id, ref lhs_ty, ref rhs_ty, ..
         }) => {
             visitor.visit_id(hir_id);
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 85bc38daa3d..a9aa192bbcc 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -138,9 +138,6 @@ impl std::ops::DerefMut for State<'_> {
 }
 
 impl<'a> PrintState<'a> for State<'a> {
-    fn insert_extra_parens(&self) -> bool {
-        true
-    }
     fn comments(&mut self) -> &mut Option<Comments<'a>> {
         &mut self.comments
     }
@@ -2210,7 +2207,6 @@ impl<'a> State<'a> {
                 self.print_type(ty);
                 if let Some(ref _default) = default {
                     // FIXME(const_generics_defaults): print the `default` value here
-                    todo!();
                 }
             }
         }
@@ -2234,19 +2230,19 @@ impl<'a> State<'a> {
             }
 
             match predicate {
-                &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
-                    ref bound_generic_params,
-                    ref bounded_ty,
+                hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
+                    bound_generic_params,
+                    bounded_ty,
                     bounds,
                     ..
                 }) => {
                     self.print_formal_generic_params(bound_generic_params);
                     self.print_type(&bounded_ty);
-                    self.print_bounds(":", bounds);
+                    self.print_bounds(":", *bounds);
                 }
-                &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
-                    ref lifetime,
-                    ref bounds,
+                hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
+                    lifetime,
+                    bounds,
                     ..
                 }) => {
                     self.print_lifetime(lifetime);
@@ -2265,10 +2261,8 @@ impl<'a> State<'a> {
                         }
                     }
                 }
-                &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
-                    ref lhs_ty,
-                    ref rhs_ty,
-                    ..
+                hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
+                    lhs_ty, rhs_ty, ..
                 }) => {
                     self.print_type(lhs_ty);
                     self.s.space();
diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs
index 9b4388c911f..f39a92b9a32 100644
--- a/compiler/rustc_incremental/src/assert_dep_graph.rs
+++ b/compiler/rustc_incremental/src/assert_dep_graph.rs
@@ -310,13 +310,13 @@ fn filter_nodes<'q>(
     sources: &Option<FxHashSet<&'q DepNode>>,
     targets: &Option<FxHashSet<&'q DepNode>>,
 ) -> FxHashSet<&'q DepNode> {
-    if let &Some(ref sources) = sources {
-        if let &Some(ref targets) = targets {
+    if let Some(sources) = sources {
+        if let Some(targets) = targets {
             walk_between(query, sources, targets)
         } else {
             walk_nodes(query, sources, OUTGOING)
         }
-    } else if let &Some(ref targets) = targets {
+    } else if let Some(targets) = targets {
         walk_nodes(query, targets, INCOMING)
     } else {
         query.nodes().into_iter().collect()
diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs
index e185ee24d17..c86122f8939 100644
--- a/compiler/rustc_incremental/src/persist/file_format.rs
+++ b/compiler/rustc_incremental/src/persist/file_format.rs
@@ -52,11 +52,11 @@ pub fn read_file(
     path: &Path,
     nightly_build: bool,
 ) -> io::Result<Option<(Vec<u8>, usize)>> {
-    if !path.exists() {
-        return Ok(None);
-    }
-
-    let data = fs::read(path)?;
+    let data = match fs::read(path) {
+        Ok(data) => data,
+        Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(None),
+        Err(err) => return Err(err),
+    };
 
     let mut file = io::Cursor::new(data);
 
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index 9fdf0a56d9d..7a1976bed4b 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -922,22 +922,24 @@ fn all_except_most_recent(
 /// before passing it to std::fs::remove_dir_all(). This will convert the path
 /// into the '\\?\' format, which supports much longer paths.
 fn safe_remove_dir_all(p: &Path) -> io::Result<()> {
-    if p.exists() {
-        let canonicalized = p.canonicalize()?;
-        std_fs::remove_dir_all(canonicalized)
-    } else {
-        Ok(())
-    }
+    let canonicalized = match std_fs::canonicalize(p) {
+        Ok(canonicalized) => canonicalized,
+        Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(()),
+        Err(err) => return Err(err),
+    };
+
+    std_fs::remove_dir_all(canonicalized)
 }
 
 fn safe_remove_file(p: &Path) -> io::Result<()> {
-    if p.exists() {
-        let canonicalized = p.canonicalize()?;
-        match std_fs::remove_file(canonicalized) {
-            Err(ref err) if err.kind() == io::ErrorKind::NotFound => Ok(()),
-            result => result,
-        }
-    } else {
-        Ok(())
+    let canonicalized = match std_fs::canonicalize(p) {
+        Ok(canonicalized) => canonicalized,
+        Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(()),
+        Err(err) => return Err(err),
+    };
+
+    match std_fs::remove_file(canonicalized) {
+        Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(()),
+        result => result,
     }
 }
diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs
index 102a77e8e79..2169f5a89e1 100644
--- a/compiler/rustc_incremental/src/persist/save.rs
+++ b/compiler/rustc_incremental/src/persist/save.rs
@@ -6,6 +6,7 @@ use rustc_serialize::opaque::Encoder;
 use rustc_serialize::Encodable as RustcEncodable;
 use rustc_session::Session;
 use std::fs;
+use std::io;
 use std::path::PathBuf;
 
 use super::data::*;
@@ -101,19 +102,18 @@ where
     // Note: It's important that we actually delete the old file and not just
     // truncate and overwrite it, since it might be a shared hard-link, the
     // underlying data of which we don't want to modify
-    if path_buf.exists() {
-        match fs::remove_file(&path_buf) {
-            Ok(()) => {
-                debug!("save: remove old file");
-            }
-            Err(err) => {
-                sess.err(&format!(
-                    "unable to delete old dep-graph at `{}`: {}",
-                    path_buf.display(),
-                    err
-                ));
-                return;
-            }
+    match fs::remove_file(&path_buf) {
+        Ok(()) => {
+            debug!("save: remove old file");
+        }
+        Err(err) if err.kind() == io::ErrorKind::NotFound => (),
+        Err(err) => {
+            sess.err(&format!(
+                "unable to delete old dep-graph at `{}`: {}",
+                path_buf.display(),
+                err
+            ));
+            return;
         }
     }
 
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 14a56119f21..d1d6cb43fc7 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -915,7 +915,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
                 return Some(());
             }
-            if let &ty::Adt(def, _) = ta.kind() {
+            if let ty::Adt(def, _) = ta.kind() {
                 let path_ = self.tcx.def_path_str(def.did);
                 if path_ == other_path {
                     self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index 373f0a602c0..e097264ec8a 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -43,22 +43,18 @@ impl<'a, 'tcx> FindHirNodeVisitor<'a, 'tcx> {
     }
 
     fn node_ty_contains_target(&mut self, hir_id: HirId) -> Option<Ty<'tcx>> {
-        let ty_opt = self
-            .infcx
+        self.infcx
             .in_progress_typeck_results
-            .and_then(|typeck_results| typeck_results.borrow().node_type_opt(hir_id));
-        match ty_opt {
-            Some(ty) => {
-                let ty = self.infcx.resolve_vars_if_possible(ty);
-                if ty.walk().any(|inner| {
+            .and_then(|typeck_results| typeck_results.borrow().node_type_opt(hir_id))
+            .map(|ty| self.infcx.resolve_vars_if_possible(ty))
+            .filter(|ty| {
+                ty.walk().any(|inner| {
                     inner == self.target
                         || match (inner.unpack(), self.target.unpack()) {
                             (GenericArgKind::Type(inner_ty), GenericArgKind::Type(target_ty)) => {
+                                use ty::{Infer, TyVar};
                                 match (inner_ty.kind(), target_ty.kind()) {
-                                    (
-                                        &ty::Infer(ty::TyVar(a_vid)),
-                                        &ty::Infer(ty::TyVar(b_vid)),
-                                    ) => self
+                                    (&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => self
                                         .infcx
                                         .inner
                                         .borrow_mut()
@@ -69,14 +65,8 @@ impl<'a, 'tcx> FindHirNodeVisitor<'a, 'tcx> {
                             }
                             _ => false,
                         }
-                }) {
-                    Some(ty)
-                } else {
-                    None
-                }
-            }
-            None => None,
-        }
+                })
+            })
     }
 }
 
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 461ee085922..b67704119bc 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -236,7 +236,7 @@ fn configure_and_expand_inner<'a>(
     pre_expansion_lint(sess, lint_store, &krate);
 
     let mut resolver = Resolver::new(sess, &krate, crate_name, metadata_loader, &resolver_arenas);
-    rustc_builtin_macros::register_builtin_macros(&mut resolver, sess.edition());
+    rustc_builtin_macros::register_builtin_macros(&mut resolver);
 
     krate = sess.time("crate_injection", || {
         let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| Symbol::intern(s));
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 3e94f163773..55d521a9b5f 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -7,7 +7,7 @@ use rustc_session::config::{build_configuration, build_session_options, to_crate
 use rustc_session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes};
 use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath};
 use rustc_session::config::{
-    Externs, OutputType, OutputTypes, SanitizerSet, SymbolManglingVersion,
+    Externs, OutputType, OutputTypes, SanitizerSet, SymbolManglingVersion, WasiExecModel,
 };
 use rustc_session::lint::Level;
 use rustc_session::search_paths::SearchPath;
@@ -597,6 +597,7 @@ fn test_debugging_options_tracking_hash() {
     tracked!(unleash_the_miri_inside_of_you, true);
     tracked!(use_ctors_section, Some(true));
     tracked!(verify_llvm_ir, true);
+    tracked!(wasi_exec_model, Some(WasiExecModel::Reactor));
 }
 
 #[test]
diff --git a/compiler/rustc_lexer/src/cursor.rs b/compiler/rustc_lexer/src/cursor.rs
index c0045d3f79b..297f3d19ca1 100644
--- a/compiler/rustc_lexer/src/cursor.rs
+++ b/compiler/rustc_lexer/src/cursor.rs
@@ -33,7 +33,7 @@ impl<'a> Cursor<'a> {
 
         #[cfg(not(debug_assertions))]
         {
-            '\0'
+            EOF_CHAR
         }
     }
 
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index a8371274f61..374bd6d0d79 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -938,8 +938,8 @@ impl EarlyLintPass for DeprecatedAttr {
             if attr.ident().map(|ident| ident.name) == Some(n) {
                 if let &AttributeGate::Gated(
                     Stability::Deprecated(link, suggestion),
-                    ref name,
-                    ref reason,
+                    name,
+                    reason,
                     _,
                 ) = g
                 {
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index c82fe50af87..f4740be34cb 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -597,6 +597,9 @@ pub trait LintContext: Sized {
                     db.help("to document an item produced by a macro, \
                                   the macro must produce the documentation as part of its expansion");
                 }
+                BuiltinLintDiagnostics::PatternsInFnsWithoutBody(span, ident) => {
+                    db.span_suggestion(span, "remove `mut` from the parameter", ident.to_string(), Applicability::MachineApplicable);
+                }
             }
             // Rewrap `db`, and pass control to the user.
             decorate(LintDiagnosticBuilder::new(db));
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 6d61b86f32e..ebd6190dc74 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -275,10 +275,25 @@ impl NonSnakeCase {
                     // We have a valid span in almost all cases, but we don't have one when linting a crate
                     // name provided via the command line.
                     if !ident.span.is_dummy() {
+                        let sc_ident = Ident::from_str_and_span(&sc, ident.span);
+                        let (message, suggestion) = if sc_ident.is_reserved() {
+                            // We shouldn't suggest a reserved identifier to fix non-snake-case identifiers.
+                            // Instead, recommend renaming the identifier entirely or, if permitted,
+                            // escaping it to create a raw identifier.
+                            if sc_ident.name.can_be_raw() {
+                                ("rename the identifier or convert it to a snake case raw identifier", sc_ident.to_string())
+                            } else {
+                                err.note(&format!("`{}` cannot be used as a raw identifier", sc));
+                                ("rename the identifier", String::new())
+                            }
+                        } else {
+                            ("convert the identifier to snake case", sc)
+                        };
+
                         err.span_suggestion(
                             ident.span,
-                            "convert the identifier to snake case",
-                            sc,
+                            message,
+                            suggestion,
                             Applicability::MaybeIncorrect,
                         );
                     } else {
@@ -397,7 +412,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
     }
 
     fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) {
-        if let &PatKind::Binding(_, hid, ident, _) = &p.kind {
+        if let PatKind::Binding(_, hid, ident, _) = p.kind {
             if let hir::Node::Pat(parent_pat) = cx.tcx.hir().get(cx.tcx.hir().get_parent_node(hid))
             {
                 if let PatKind::Struct(_, field_pats, _) = &parent_pat.kind {
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 5e1f94c071c..35915dc7a97 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -862,11 +862,11 @@ impl EarlyLintPass for UnusedParens {
     }
 
     fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
-        if let &ast::TyKind::Paren(ref r) = &ty.kind {
+        if let ast::TyKind::Paren(r) = &ty.kind {
             match &r.kind {
-                &ast::TyKind::TraitObject(..) => {}
-                &ast::TyKind::ImplTrait(_, ref bounds) if bounds.len() > 1 => {}
-                &ast::TyKind::Array(_, ref len) => {
+                ast::TyKind::TraitObject(..) => {}
+                ast::TyKind::ImplTrait(_, bounds) if bounds.len() > 1 => {}
+                ast::TyKind::Array(_, len) => {
                     self.check_unused_delims_expr(
                         cx,
                         &len.value,
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 1c692d4f207..f90fc7fc9ab 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -221,14 +221,10 @@ declare_lint! {
     ///
     /// ### Explanation
     ///
-    /// This lint detects code that is very likely incorrect. When possible,
-    /// the compiler will attempt to detect situations where code can be
-    /// evaluated at compile-time to generate more efficient code. While
-    /// evaluating such code, if it detects that the code will unconditionally
-    /// panic, this usually indicates that it is doing something incorrectly.
-    /// If this lint is allowed, then the code will not be evaluated at
-    /// compile-time, and instead continue to generate code to evaluate at
-    /// runtime, which may panic during runtime.
+    /// This lint detects code that is very likely incorrect because it will
+    /// always panic, such as division by zero and out-of-bounds array
+    /// accesses. Consider adjusting your code if this is a bug, or using the
+    /// `panic!` or `unreachable!` macro instead in case the panic is intended.
     pub UNCONDITIONAL_PANIC,
     Deny,
     "operation will cause a panic at runtime"
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index aec0fc253ca..2bfc6a85576 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -253,6 +253,7 @@ pub enum BuiltinLintDiagnostics {
     RedundantImport(Vec<(Span, bool)>, Ident),
     DeprecatedMacro(Option<Symbol>, Span),
     UnusedDocComment(Span),
+    PatternsInFnsWithoutBody(Span, Ident),
 }
 
 /// Lints that are buffered up early on in the `Session` before the
diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs
index dbeb3c75504..72bd4804e98 100644
--- a/compiler/rustc_macros/src/serialize.rs
+++ b/compiler/rustc_macros/src/serialize.rs
@@ -203,7 +203,7 @@ fn encodable_body(
                                 #field_name,
                                 #field_idx,
                                 |__encoder|
-                                ::rustc_serialize::Encodable::encode(#bind_ident, __encoder),
+                                ::rustc_serialize::Encodable::<#encoder_ty>::encode(#bind_ident, __encoder),
                             ) {
                                 ::std::result::Result::Ok(()) => (),
                                 ::std::result::Result::Err(__err)
@@ -237,7 +237,7 @@ fn encodable_body(
                                 __encoder,
                                 #field_idx,
                                 |__encoder|
-                                ::rustc_serialize::Encodable::encode(#bind_ident, __encoder),
+                                ::rustc_serialize::Encodable::<#encoder_ty>::encode(#bind_ident, __encoder),
                             ) {
                                 ::std::result::Result::Ok(()) => (),
                                 ::std::result::Result::Err(__err)
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 744fdc83a91..5b33678b25a 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -192,13 +192,13 @@ impl Collector<'tcx> {
     fn process_command_line(&mut self) {
         // First, check for errors
         let mut renames = FxHashSet::default();
-        for &(ref name, ref new_name, _) in &self.tcx.sess.opts.libs {
-            if let &Some(ref new_name) = new_name {
+        for (name, new_name, _) in &self.tcx.sess.opts.libs {
+            if let Some(ref new_name) = new_name {
                 let any_duplicate = self
                     .libs
                     .iter()
                     .filter_map(|lib| lib.name.as_ref())
-                    .any(|n| n.as_str() == *name);
+                    .any(|n| &n.as_str() == name);
                 if new_name.is_empty() {
                     self.tcx.sess.err(&format!(
                         "an empty renaming target was specified for library `{}`",
@@ -240,7 +240,7 @@ impl Collector<'tcx> {
                             if kind != NativeLibKind::Unspecified {
                                 lib.kind = kind;
                             }
-                            if let &Some(ref new_name) = new_name {
+                            if let Some(new_name) = new_name {
                                 lib.name = Some(Symbol::intern(new_name));
                             }
                             return true;
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 43f7b2a9928..6e381fd2965 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -11,6 +11,7 @@ use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{AtomicCell, Lock, LockGuard, Lrc, OnceCell};
+use rustc_data_structures::unhash::UnhashMap;
 use rustc_errors::ErrorReported;
 use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
 use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, ProcMacroDerive};
@@ -80,7 +81,7 @@ crate struct CrateMetadata {
     /// For every definition in this crate, maps its `DefPathHash` to its
     /// `DefIndex`. See `raw_def_id_to_def_id` for more details about how
     /// this is used.
-    def_path_hash_map: OnceCell<FxHashMap<DefPathHash, DefIndex>>,
+    def_path_hash_map: OnceCell<UnhashMap<DefPathHash, DefIndex>>,
     /// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
     alloc_decoding_state: AllocDecodingState,
     /// The `DepNodeIndex` of the `DepNode` representing this upstream crate.
@@ -1055,19 +1056,15 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
 
         // Iterate over all children.
         let macros_only = self.dep_kind.lock().macros_only();
-        let children = self.root.tables.children.get(self, id).unwrap_or_else(Lazy::empty);
-        for child_index in children.decode((self, sess)) {
-            if macros_only {
-                continue;
-            }
-
-            // Get the item.
-            if let Some(child_kind) = self.maybe_kind(child_index) {
-                match child_kind {
-                    EntryKind::MacroDef(..) => {}
-                    _ if macros_only => continue,
-                    _ => {}
-                }
+        if !macros_only {
+            let children = self.root.tables.children.get(self, id).unwrap_or_else(Lazy::empty);
+
+            for child_index in children.decode((self, sess)) {
+                // Get the item.
+                let child_kind = match self.maybe_kind(child_index) {
+                    Some(child_kind) => child_kind,
+                    None => continue,
+                };
 
                 // Hand off the item to the callback.
                 match child_kind {
@@ -1102,8 +1099,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                 }
 
                 let def_key = self.def_key(child_index);
-                let span = self.get_span(child_index, sess);
                 if def_key.disambiguated_data.data.get_opt_name().is_some() {
+                    let span = self.get_span(child_index, sess);
                     let kind = self.def_kind(child_index);
                     let ident = self.item_ident(child_index, sess);
                     let vis = self.get_visibility(child_index);
@@ -1137,9 +1134,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
                                 // within the crate. We only need this for fictive constructors,
                                 // for other constructors correct visibilities
                                 // were already encoded in metadata.
-                                let attrs: Vec<_> =
-                                    self.get_item_attrs(def_id.index, sess).collect();
-                                if sess.contains_name(&attrs, sym::non_exhaustive) {
+                                let mut attrs = self.get_item_attrs(def_id.index, sess);
+                                if attrs.any(|item| item.has_name(sym::non_exhaustive)) {
                                     let crate_def_id = self.local_def_id(CRATE_DEF_INDEX);
                                     vis = ty::Visibility::Restricted(crate_def_id);
                                 }
@@ -1345,15 +1341,14 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             return &[];
         }
 
-        // Do a reverse lookup beforehand to avoid touching the crate_num
-        // hash map in the loop below.
-        let filter = match filter.map(|def_id| self.reverse_translate_def_id(def_id)) {
-            Some(Some(def_id)) => Some((def_id.krate.as_u32(), def_id.index)),
-            Some(None) => return &[],
-            None => None,
-        };
+        if let Some(def_id) = filter {
+            // Do a reverse lookup beforehand to avoid touching the crate_num
+            // hash map in the loop below.
+            let filter = match self.reverse_translate_def_id(def_id) {
+                Some(def_id) => (def_id.krate.as_u32(), def_id.index),
+                None => return &[],
+            };
 
-        if let Some(filter) = filter {
             if let Some(impls) = self.trait_impls.get(&filter) {
                 tcx.arena.alloc_from_iter(
                     impls.decode(self).map(|(idx, simplified_self_ty)| {
@@ -1560,7 +1555,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         // stored in this crate.
         let map = self.cdata.def_path_hash_map.get_or_init(|| {
             let end_id = self.root.tables.def_path_hashes.size() as u32;
-            let mut map = FxHashMap::with_capacity_and_hasher(end_id as usize, Default::default());
+            let mut map = UnhashMap::with_capacity_and_hasher(end_id as usize, Default::default());
             for i in 0..end_id {
                 let def_index = DefIndex::from_u32(i);
                 // There may be gaps in the encoded table if we're decoding a proc-macro crate
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index ac6ceafaba8..f6ae8275a8f 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -694,7 +694,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             println!("       lang item bytes: {}", lang_item_bytes);
             println!(" diagnostic item bytes: {}", diagnostic_item_bytes);
             println!("          native bytes: {}", native_lib_bytes);
-            println!("         source_map bytes: {}", source_map_bytes);
+            println!("      source_map bytes: {}", source_map_bytes);
             println!("            impl bytes: {}", impl_bytes);
             println!("    exp. symbols bytes: {}", exported_symbols_bytes);
             println!("  def-path table bytes: {}", def_path_table_bytes);
diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs
index d954c8ab5fb..b775846bba4 100644
--- a/compiler/rustc_middle/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs
@@ -29,8 +29,8 @@
 //!   contained no `DefId` for thing that had been removed.
 //!
 //! `DepNode` definition happens in the `define_dep_nodes!()` macro. This macro
-//! defines the `DepKind` enum and a corresponding `DepConstructor` enum. The
-//! `DepConstructor` enum links a `DepKind` to the parameters that are needed at
+//! defines the `DepKind` enum and a corresponding `dep_constructor` module. The
+//! `dep_constructor` module links a `DepKind` to the parameters that are needed at
 //! runtime in order to construct a valid `DepNode` fingerprint.
 //!
 //! Because the macro sees what parameters a given `DepKind` requires, it can
@@ -44,7 +44,7 @@
 //!   `DefId` it was computed from. In other cases, too much information gets
 //!   lost during fingerprint computation.
 //!
-//! The `DepConstructor` enum, together with `DepNode::new()`, ensures that only
+//! The `dep_constructor` module, together with `DepNode::new()`, ensures that only
 //! valid `DepNode` instances can be constructed. For example, the API does not
 //! allow for constructing parameterless `DepNode`s with anything other
 //! than a zeroed out fingerprint. More generally speaking, it relieves the
@@ -66,10 +66,104 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX};
 use rustc_hir::definitions::DefPathHash;
 use rustc_hir::HirId;
 use rustc_span::symbol::Symbol;
+use rustc_span::DUMMY_SP;
 use std::hash::Hash;
 
 pub use rustc_query_system::dep_graph::{DepContext, DepNodeParams};
 
+/// This struct stores metadata about each DepKind.
+///
+/// Information is retrieved by indexing the `DEP_KINDS` array using the integer value
+/// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual
+/// jump table instead of large matches.
+pub struct DepKindStruct {
+    /// Whether the DepNode has parameters (query keys).
+    pub(super) has_params: bool,
+
+    /// Anonymous queries cannot be replayed from one compiler invocation to the next.
+    /// When their result is needed, it is recomputed. They are useful for fine-grained
+    /// dependency tracking, and caching within one compiler invocation.
+    pub(super) is_anon: bool,
+
+    /// Eval-always queries do not track their dependencies, and are always recomputed, even if
+    /// their inputs have not changed since the last compiler invocation. The result is still
+    /// cached within one compiler invocation.
+    pub(super) is_eval_always: bool,
+
+    /// Whether the query key can be recovered from the hashed fingerprint.
+    /// See [DepNodeParams] trait for the behaviour of each key type.
+    // FIXME: Make this a simple boolean once DepNodeParams::can_reconstruct_query_key
+    // can be made a specialized associated const.
+    can_reconstruct_query_key: fn() -> bool,
+
+    /// The red/green evaluation system will try to mark a specific DepNode in the
+    /// dependency graph as green by recursively trying to mark the dependencies of
+    /// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
+    /// where we don't know if it is red or green and we therefore actually have
+    /// to recompute its value in order to find out. Since the only piece of
+    /// information that we have at that point is the `DepNode` we are trying to
+    /// re-evaluate, we need some way to re-run a query from just that. This is what
+    /// `force_from_dep_node()` implements.
+    ///
+    /// In the general case, a `DepNode` consists of a `DepKind` and an opaque
+    /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
+    /// is usually constructed by computing a stable hash of the query-key that the
+    /// `DepNode` corresponds to. Consequently, it is not in general possible to go
+    /// back from hash to query-key (since hash functions are not reversible). For
+    /// this reason `force_from_dep_node()` is expected to fail from time to time
+    /// because we just cannot find out, from the `DepNode` alone, what the
+    /// corresponding query-key is and therefore cannot re-run the query.
+    ///
+    /// The system deals with this case letting `try_mark_green` fail which forces
+    /// the root query to be re-evaluated.
+    ///
+    /// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
+    /// Fortunately, we can use some contextual information that will allow us to
+    /// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
+    /// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
+    /// valid `DefPathHash`. Since we also always build a huge table that maps every
+    /// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
+    /// everything we need to re-run the query.
+    ///
+    /// Take the `mir_promoted` query as an example. Like many other queries, it
+    /// just has a single parameter: the `DefId` of the item it will compute the
+    /// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
+    /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
+    /// is actually a `DefPathHash`, and can therefore just look up the corresponding
+    /// `DefId` in `tcx.def_path_hash_to_def_id`.
+    ///
+    /// When you implement a new query, it will likely have a corresponding new
+    /// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As
+    /// a rule of thumb, if your query takes a `DefId` or `LocalDefId` as sole parameter,
+    /// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
+    /// add it to the "We don't have enough information to reconstruct..." group in
+    /// the match below.
+    pub(super) force_from_dep_node: fn(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool,
+
+    /// Invoke a query to put the on-disk cached value in memory.
+    pub(super) try_load_from_on_disk_cache: fn(TyCtxt<'_>, &DepNode),
+}
+
+impl std::ops::Deref for DepKind {
+    type Target = DepKindStruct;
+    fn deref(&self) -> &DepKindStruct {
+        &DEP_KINDS[*self as usize]
+    }
+}
+
+impl DepKind {
+    #[inline(always)]
+    pub fn can_reconstruct_query_key(&self) -> bool {
+        // Only fetch the DepKindStruct once.
+        let data: &DepKindStruct = &**self;
+        if data.is_anon {
+            return false;
+        }
+
+        (data.can_reconstruct_query_key)()
+    }
+}
+
 // erase!() just makes tokens go away. It's used to specify which macro argument
 // is repeated (i.e., which sub-expression of the macro we are in) but don't need
 // to actually use any of the arguments.
@@ -103,6 +197,131 @@ macro_rules! contains_eval_always_attr {
     ($($attr:ident $(($($attr_args:tt)*))* ),*) => ({$(is_eval_always_attr!($attr) | )* false});
 }
 
+#[allow(non_upper_case_globals)]
+pub mod dep_kind {
+    use super::*;
+    use crate::ty::query::{queries, query_keys};
+    use rustc_query_system::query::{force_query, QueryDescription};
+
+    // We use this for most things when incr. comp. is turned off.
+    pub const Null: DepKindStruct = DepKindStruct {
+        has_params: false,
+        is_anon: false,
+        is_eval_always: false,
+
+        can_reconstruct_query_key: || true,
+        force_from_dep_node: |_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node),
+        try_load_from_on_disk_cache: |_, _| {},
+    };
+
+    // Represents metadata from an extern crate.
+    pub const CrateMetadata: DepKindStruct = DepKindStruct {
+        has_params: true,
+        is_anon: false,
+        is_eval_always: true,
+
+        can_reconstruct_query_key: || true,
+        force_from_dep_node: |_, dep_node| bug!("force_from_dep_node: encountered {:?}", dep_node),
+        try_load_from_on_disk_cache: |_, _| {},
+    };
+
+    pub const TraitSelect: DepKindStruct = DepKindStruct {
+        has_params: false,
+        is_anon: true,
+        is_eval_always: false,
+
+        can_reconstruct_query_key: || true,
+        force_from_dep_node: |_, _| false,
+        try_load_from_on_disk_cache: |_, _| {},
+    };
+
+    pub const CompileCodegenUnit: DepKindStruct = DepKindStruct {
+        has_params: true,
+        is_anon: false,
+        is_eval_always: false,
+
+        can_reconstruct_query_key: || false,
+        force_from_dep_node: |_, _| false,
+        try_load_from_on_disk_cache: |_, _| {},
+    };
+
+    macro_rules! define_query_dep_kinds {
+        ($(
+            [$($attrs:tt)*]
+            $variant:ident $(( $tuple_arg_ty:ty $(,)? ))*
+        ,)*) => (
+            $(pub const $variant: DepKindStruct = {
+                const has_params: bool = $({ erase!($tuple_arg_ty); true } |)* false;
+                const is_anon: bool = contains_anon_attr!($($attrs)*);
+                const is_eval_always: bool = contains_eval_always_attr!($($attrs)*);
+
+                #[inline(always)]
+                fn can_reconstruct_query_key() -> bool {
+                    <query_keys::$variant<'_> as DepNodeParams<TyCtxt<'_>>>
+                        ::can_reconstruct_query_key()
+                }
+
+                fn recover<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<query_keys::$variant<'tcx>> {
+                    <query_keys::$variant<'_> as DepNodeParams<TyCtxt<'_>>>::recover(tcx, dep_node)
+                }
+
+                fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool {
+                    if is_anon {
+                        return false;
+                    }
+
+                    if !can_reconstruct_query_key() {
+                        return false;
+                    }
+
+                    if let Some(key) = recover(tcx, dep_node) {
+                        force_query::<queries::$variant<'_>, _>(
+                            tcx,
+                            key,
+                            DUMMY_SP,
+                            *dep_node
+                        );
+                        return true;
+                    }
+
+                    false
+                }
+
+                fn try_load_from_on_disk_cache(tcx: TyCtxt<'_>, dep_node: &DepNode) {
+                    if is_anon {
+                        return
+                    }
+
+                    if !can_reconstruct_query_key() {
+                        return
+                    }
+
+                    debug_assert!(tcx.dep_graph
+                                     .node_color(dep_node)
+                                     .map(|c| c.is_green())
+                                     .unwrap_or(false));
+
+                    let key = recover(tcx, dep_node).unwrap_or_else(|| panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash));
+                    if queries::$variant::cache_on_disk(tcx, &key, None) {
+                        let _ = tcx.$variant(key);
+                    }
+                }
+
+                DepKindStruct {
+                    has_params,
+                    is_anon,
+                    is_eval_always,
+                    can_reconstruct_query_key,
+                    force_from_dep_node,
+                    try_load_from_on_disk_cache,
+                }
+            };)*
+        );
+    }
+
+    rustc_dep_node_append!([define_query_dep_kinds!][]);
+}
+
 macro_rules! define_dep_nodes {
     (<$tcx:tt>
     $(
@@ -110,72 +329,19 @@ macro_rules! define_dep_nodes {
         $variant:ident $(( $tuple_arg_ty:ty $(,)? ))*
       ,)*
     ) => (
-        #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
+        static DEP_KINDS: &[DepKindStruct] = &[ $(dep_kind::$variant),* ];
+
+        /// This enum serves as an index into the `DEP_KINDS` array.
+        #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
         #[allow(non_camel_case_types)]
         pub enum DepKind {
             $($variant),*
         }
 
-        impl DepKind {
-            #[allow(unreachable_code)]
-            pub fn can_reconstruct_query_key<$tcx>(&self) -> bool {
-                match *self {
-                    $(
-                        DepKind :: $variant => {
-                            if contains_anon_attr!($($attrs)*) {
-                                return false;
-                            }
-
-                            // tuple args
-                            $({
-                                return <$tuple_arg_ty as DepNodeParams<TyCtxt<'_>>>
-                                    ::can_reconstruct_query_key();
-                            })*
-
-                            true
-                        }
-                    )*
-                }
-            }
-
-            pub fn is_anon(&self) -> bool {
-                match *self {
-                    $(
-                        DepKind :: $variant => { contains_anon_attr!($($attrs)*) }
-                    )*
-                }
-            }
-
-            pub fn is_eval_always(&self) -> bool {
-                match *self {
-                    $(
-                        DepKind :: $variant => { contains_eval_always_attr!($($attrs)*) }
-                    )*
-                }
-            }
-
-            #[allow(unreachable_code)]
-            pub fn has_params(&self) -> bool {
-                match *self {
-                    $(
-                        DepKind :: $variant => {
-                            // tuple args
-                            $({
-                                erase!($tuple_arg_ty);
-                                return true;
-                            })*
-
-                            false
-                        }
-                    )*
-                }
-            }
-        }
-
-        pub struct DepConstructor;
-
         #[allow(non_camel_case_types)]
-        impl DepConstructor {
+        pub mod dep_constructor {
+            use super::*;
+
             $(
                 #[inline(always)]
                 #[allow(unreachable_code, non_snake_case)]
@@ -191,101 +357,10 @@ macro_rules! define_dep_nodes {
             )*
         }
 
-        pub type DepNode = rustc_query_system::dep_graph::DepNode<DepKind>;
-
-        // We keep a lot of `DepNode`s in memory during compilation. It's not
-        // required that their size stay the same, but we don't want to change
-        // it inadvertently. This assert just ensures we're aware of any change.
-        #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-        static_assert_size!(DepNode, 17);
-
-        #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
-        static_assert_size!(DepNode, 24);
-
-        pub trait DepNodeExt: Sized {
-            /// Construct a DepNode from the given DepKind and DefPathHash. This
-            /// method will assert that the given DepKind actually requires a
-            /// single DefId/DefPathHash parameter.
-            fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> Self;
-
-            /// Extracts the DefId corresponding to this DepNode. This will work
-            /// if two conditions are met:
-            ///
-            /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and
-            /// 2. the item that the DefPath refers to exists in the current tcx.
-            ///
-            /// Condition (1) is determined by the DepKind variant of the
-            /// DepNode. Condition (2) might not be fulfilled if a DepNode
-            /// refers to something from the previous compilation session that
-            /// has been removed.
-            fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId>;
-
-            /// Used in testing
-            fn from_label_string(label: &str, def_path_hash: DefPathHash)
-                -> Result<Self, ()>;
-
-            /// Used in testing
-            fn has_label_string(label: &str) -> bool;
-        }
-
-        impl DepNodeExt for DepNode {
-            /// Construct a DepNode from the given DepKind and DefPathHash. This
-            /// method will assert that the given DepKind actually requires a
-            /// single DefId/DefPathHash parameter.
-            fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> DepNode {
-                debug_assert!(kind.can_reconstruct_query_key() && kind.has_params());
-                DepNode {
-                    kind,
-                    hash: def_path_hash.0.into(),
-                }
-            }
-
-            /// Extracts the DefId corresponding to this DepNode. This will work
-            /// if two conditions are met:
-            ///
-            /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and
-            /// 2. the item that the DefPath refers to exists in the current tcx.
-            ///
-            /// Condition (1) is determined by the DepKind variant of the
-            /// DepNode. Condition (2) might not be fulfilled if a DepNode
-            /// refers to something from the previous compilation session that
-            /// has been removed.
-            fn extract_def_id(&self, tcx: TyCtxt<'tcx>) -> Option<DefId> {
-                if self.kind.can_reconstruct_query_key() {
-                    tcx.queries.on_disk_cache.as_ref()?.def_path_hash_to_def_id(tcx, DefPathHash(self.hash.into()))
-                } else {
-                    None
-                }
-            }
-
-            /// Used in testing
-            fn from_label_string(label: &str, def_path_hash: DefPathHash) -> Result<DepNode, ()> {
-                let kind = match label {
-                    $(
-                        stringify!($variant) => DepKind::$variant,
-                    )*
-                    _ => return Err(()),
-                };
-
-                if !kind.can_reconstruct_query_key() {
-                    return Err(());
-                }
-
-                if kind.has_params() {
-                    Ok(DepNode::from_def_path_hash(def_path_hash, kind))
-                } else {
-                    Ok(DepNode::new_no_params(kind))
-                }
-            }
-
-            /// Used in testing
-            fn has_label_string(label: &str) -> bool {
-                match label {
-                    $(
-                        stringify!($variant) => true,
-                    )*
-                    _ => false,
-                }
+        fn dep_kind_from_label_string(label: &str) -> Result<DepKind, ()> {
+            match label {
+                $(stringify!($variant) => Ok(DepKind::$variant),)*
+                _ => Err(()),
             }
         }
 
@@ -312,8 +387,110 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
     [] CompileCodegenUnit(Symbol),
 ]);
 
+pub type DepNode = rustc_query_system::dep_graph::DepNode<DepKind>;
+
+// We keep a lot of `DepNode`s in memory during compilation. It's not
+// required that their size stay the same, but we don't want to change
+// it inadvertently. This assert just ensures we're aware of any change.
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+static_assert_size!(DepNode, 17);
+
+#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
+static_assert_size!(DepNode, 24);
+
+pub trait DepNodeExt: Sized {
+    /// Construct a DepNode from the given DepKind and DefPathHash. This
+    /// method will assert that the given DepKind actually requires a
+    /// single DefId/DefPathHash parameter.
+    fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> Self;
+
+    /// Extracts the DefId corresponding to this DepNode. This will work
+    /// if two conditions are met:
+    ///
+    /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and
+    /// 2. the item that the DefPath refers to exists in the current tcx.
+    ///
+    /// Condition (1) is determined by the DepKind variant of the
+    /// DepNode. Condition (2) might not be fulfilled if a DepNode
+    /// refers to something from the previous compilation session that
+    /// has been removed.
+    fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId>;
+
+    /// Used in testing
+    fn from_label_string(label: &str, def_path_hash: DefPathHash) -> Result<Self, ()>;
+
+    /// Used in testing
+    fn has_label_string(label: &str) -> bool;
+}
+
+impl DepNodeExt for DepNode {
+    /// Construct a DepNode from the given DepKind and DefPathHash. This
+    /// method will assert that the given DepKind actually requires a
+    /// single DefId/DefPathHash parameter.
+    fn from_def_path_hash(def_path_hash: DefPathHash, kind: DepKind) -> DepNode {
+        debug_assert!(kind.can_reconstruct_query_key() && kind.has_params);
+        DepNode { kind, hash: def_path_hash.0.into() }
+    }
+
+    /// Extracts the DefId corresponding to this DepNode. This will work
+    /// if two conditions are met:
+    ///
+    /// 1. The Fingerprint of the DepNode actually is a DefPathHash, and
+    /// 2. the item that the DefPath refers to exists in the current tcx.
+    ///
+    /// Condition (1) is determined by the DepKind variant of the
+    /// DepNode. Condition (2) might not be fulfilled if a DepNode
+    /// refers to something from the previous compilation session that
+    /// has been removed.
+    fn extract_def_id(&self, tcx: TyCtxt<'tcx>) -> Option<DefId> {
+        if self.kind.can_reconstruct_query_key() {
+            tcx.queries
+                .on_disk_cache
+                .as_ref()?
+                .def_path_hash_to_def_id(tcx, DefPathHash(self.hash.into()))
+        } else {
+            None
+        }
+    }
+
+    /// Used in testing
+    fn from_label_string(label: &str, def_path_hash: DefPathHash) -> Result<DepNode, ()> {
+        let kind = dep_kind_from_label_string(label)?;
+
+        if !kind.can_reconstruct_query_key() {
+            return Err(());
+        }
+
+        if kind.has_params {
+            Ok(DepNode::from_def_path_hash(def_path_hash, kind))
+        } else {
+            Ok(DepNode::new_no_params(kind))
+        }
+    }
+
+    /// Used in testing
+    fn has_label_string(label: &str) -> bool {
+        dep_kind_from_label_string(label).is_ok()
+    }
+}
+
+impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for () {
+    #[inline(always)]
+    fn can_reconstruct_query_key() -> bool {
+        true
+    }
+
+    fn to_fingerprint(&self, _: TyCtxt<'tcx>) -> Fingerprint {
+        Fingerprint::ZERO
+    }
+
+    fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option<Self> {
+        Some(())
+    }
+}
+
 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for DefId {
-    #[inline]
+    #[inline(always)]
     fn can_reconstruct_query_key() -> bool {
         true
     }
@@ -342,7 +519,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for DefId {
 }
 
 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalDefId {
-    #[inline]
+    #[inline(always)]
     fn can_reconstruct_query_key() -> bool {
         true
     }
@@ -361,7 +538,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalDefId {
 }
 
 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum {
-    #[inline]
+    #[inline(always)]
     fn can_reconstruct_query_key() -> bool {
         true
     }
@@ -381,7 +558,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum {
 }
 
 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) {
-    #[inline]
+    #[inline(always)]
     fn can_reconstruct_query_key() -> bool {
         false
     }
@@ -406,7 +583,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) {
 }
 
 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
-    #[inline]
+    #[inline(always)]
     fn can_reconstruct_query_key() -> bool {
         false
     }
diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs
index 728bfef9f46..22e9cc1cd3e 100644
--- a/compiler/rustc_middle/src/dep_graph/mod.rs
+++ b/compiler/rustc_middle/src/dep_graph/mod.rs
@@ -1,5 +1,4 @@
 use crate::ich::StableHashingContext;
-use crate::ty::query::try_load_from_on_disk_cache;
 use crate::ty::{self, TyCtxt};
 use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::sync::Lock;
@@ -9,13 +8,12 @@ use rustc_hir::def_id::LocalDefId;
 
 mod dep_node;
 
-pub(crate) use rustc_query_system::dep_graph::DepNodeParams;
 pub use rustc_query_system::dep_graph::{
     debug, hash_result, DepContext, DepNodeColor, DepNodeIndex, SerializedDepNodeIndex,
     WorkProduct, WorkProductId,
 };
 
-pub use dep_node::{label_strs, DepConstructor, DepKind, DepNode, DepNodeExt};
+pub use dep_node::{dep_constructor, label_strs, DepKind, DepNode, DepNodeExt};
 
 pub type DepGraph = rustc_query_system::dep_graph::DepGraph<DepKind>;
 pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps<DepKind>;
@@ -26,18 +24,25 @@ pub type SerializedDepGraph = rustc_query_system::dep_graph::SerializedDepGraph<
 impl rustc_query_system::dep_graph::DepKind for DepKind {
     const NULL: Self = DepKind::Null;
 
+    #[inline(always)]
+    fn can_reconstruct_query_key(&self) -> bool {
+        DepKind::can_reconstruct_query_key(self)
+    }
+
+    #[inline(always)]
     fn is_eval_always(&self) -> bool {
-        DepKind::is_eval_always(self)
+        self.is_eval_always
     }
 
+    #[inline(always)]
     fn has_params(&self) -> bool {
-        DepKind::has_params(self)
+        self.has_params
     }
 
     fn debug_node(node: &DepNode, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         write!(f, "{:?}", node.kind)?;
 
-        if !node.kind.has_params() && !node.kind.is_anon() {
+        if !node.kind.has_params && !node.kind.is_anon {
             return Ok(());
         }
 
@@ -81,10 +86,6 @@ impl rustc_query_system::dep_graph::DepKind for DepKind {
             op(icx.task_deps)
         })
     }
-
-    fn can_reconstruct_query_key(&self) -> bool {
-        DepKind::can_reconstruct_query_key(self)
-    }
 }
 
 impl<'tcx> DepContext for TyCtxt<'tcx> {
@@ -153,7 +154,26 @@ impl<'tcx> DepContext for TyCtxt<'tcx> {
         }
 
         debug!("try_force_from_dep_node({:?}) --- trying to force", dep_node);
-        ty::query::force_from_dep_node(*self, dep_node)
+
+        // We must avoid ever having to call `force_from_dep_node()` for a
+        // `DepNode::codegen_unit`:
+        // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
+        // would always end up having to evaluate the first caller of the
+        // `codegen_unit` query that *is* reconstructible. This might very well be
+        // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
+        // to re-trigger calling the `codegen_unit` query with the right key. At
+        // that point we would already have re-done all the work we are trying to
+        // avoid doing in the first place.
+        // The solution is simple: Just explicitly call the `codegen_unit` query for
+        // each CGU, right after partitioning. This way `try_mark_green` will always
+        // hit the cache instead of having to go through `force_from_dep_node`.
+        // This assertion makes sure, we actually keep applying the solution above.
+        debug_assert!(
+            dep_node.kind != DepKind::codegen_unit,
+            "calling force_from_dep_node() on DepKind::codegen_unit"
+        );
+
+        (dep_node.kind.force_from_dep_node)(*self, dep_node)
     }
 
     fn has_errors_or_delayed_span_bugs(&self) -> bool {
@@ -166,7 +186,7 @@ impl<'tcx> DepContext for TyCtxt<'tcx> {
 
     // Interactions with on_disk_cache
     fn try_load_from_on_disk_cache(&self, dep_node: &DepNode) {
-        try_load_from_on_disk_cache(*self, dep_node)
+        (dep_node.kind.try_load_from_on_disk_cache)(*self, dep_node)
     }
 
     fn load_diagnostics(&self, prev_dep_node_index: SerializedDepNodeIndex) -> Vec<Diagnostic> {
diff --git a/compiler/rustc_middle/src/hir/map/collector.rs b/compiler/rustc_middle/src/hir/map/collector.rs
index 82cfca4f171..872fcb0f581 100644
--- a/compiler/rustc_middle/src/hir/map/collector.rs
+++ b/compiler/rustc_middle/src/hir/map/collector.rs
@@ -529,13 +529,22 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     }
 
     fn visit_macro_def(&mut self, macro_def: &'hir MacroDef<'hir>) {
-        self.with_dep_node_owner(macro_def.hir_id.owner, macro_def, |this, hash| {
-            this.insert_with_hash(
-                macro_def.span,
-                macro_def.hir_id,
-                Node::MacroDef(macro_def),
-                hash,
-            );
+        // Exported macros are visited directly from the crate root,
+        // so they do not have `parent_node` set.
+        // Find the correct enclosing module from their DefKey.
+        let def_key = self.definitions.def_key(macro_def.hir_id.owner);
+        let parent = def_key.parent.map_or(hir::CRATE_HIR_ID, |local_def_index| {
+            self.definitions.local_def_id_to_hir_id(LocalDefId { local_def_index })
+        });
+        self.with_parent(parent, |this| {
+            this.with_dep_node_owner(macro_def.hir_id.owner, macro_def, |this, hash| {
+                this.insert_with_hash(
+                    macro_def.span,
+                    macro_def.hir_id,
+                    Node::MacroDef(macro_def),
+                    hash,
+                );
+            })
         });
     }
 
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 09d5b102103..eb6aded9cb3 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -31,7 +31,7 @@ pub struct Entry<'hir> {
 impl<'hir> Entry<'hir> {
     fn parent_node(self) -> Option<HirId> {
         match self.node {
-            Node::Crate(_) | Node::MacroDef(_) => None,
+            Node::Crate(_) => None,
             _ => Some(self.parent),
         }
     }
@@ -710,15 +710,10 @@ impl<'hir> Map<'hir> {
         let mut scope = id;
         loop {
             scope = self.get_enclosing_scope(scope).unwrap_or(CRATE_HIR_ID);
-            if scope == CRATE_HIR_ID {
-                return CRATE_HIR_ID;
-            }
-            match self.get(scope) {
-                Node::Block(_) => {}
-                _ => break,
+            if scope == CRATE_HIR_ID || !matches!(self.get(scope), Node::Block(_)) {
+                return scope;
             }
         }
-        scope
     }
 
     pub fn get_parent_did(&self, id: HirId) -> LocalDefId {
diff --git a/compiler/rustc_middle/src/ich/hcx.rs b/compiler/rustc_middle/src/ich/hcx.rs
index 084fe4cfa16..addcb7a14e3 100644
--- a/compiler/rustc_middle/src/ich/hcx.rs
+++ b/compiler/rustc_middle/src/ich/hcx.rs
@@ -12,7 +12,7 @@ use rustc_hir::definitions::{DefPathHash, Definitions};
 use rustc_session::Session;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::Symbol;
-use rustc_span::{BytePos, CachingSourceMapView, SourceFile};
+use rustc_span::{BytePos, CachingSourceMapView, SourceFile, SpanData};
 
 use rustc_span::def_id::{CrateNum, CRATE_DEF_INDEX};
 use smallvec::SmallVec;
@@ -248,6 +248,13 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
     ) -> Option<(Lrc<SourceFile>, usize, BytePos)> {
         self.source_map().byte_pos_to_line_and_col(byte)
     }
+
+    fn span_data_to_lines_and_cols(
+        &mut self,
+        span: &SpanData,
+    ) -> Option<(Lrc<SourceFile>, usize, BytePos, usize, BytePos)> {
+        self.source_map().span_data_to_lines_and_cols(span)
+    }
 }
 
 pub fn hash_stable_trait_impls<'a>(
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index a69555fd1a8..fab2f2c97e4 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1745,18 +1745,14 @@ impl<'tcx> Place<'tcx> {
 
     /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
     /// a single deref of a local.
-    //
-    // FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
+    #[inline(always)]
     pub fn local_or_deref_local(&self) -> Option<Local> {
-        match self.as_ref() {
-            PlaceRef { local, projection: [] }
-            | PlaceRef { local, projection: [ProjectionElem::Deref] } => Some(local),
-            _ => None,
-        }
+        self.as_ref().local_or_deref_local()
     }
 
     /// If this place represents a local variable like `_X` with no
     /// projections, return `Some(_X)`.
+    #[inline(always)]
     pub fn as_local(&self) -> Option<Local> {
         self.as_ref().as_local()
     }
@@ -1770,6 +1766,7 @@ impl<'tcx> Place<'tcx> {
     /// As a concrete example, given the place a.b.c, this would yield:
     /// - (a, .b)
     /// - (a.b, .c)
+    ///
     /// Given a place without projections, the iterator is empty.
     pub fn iter_projections(
         self,
@@ -1790,8 +1787,6 @@ impl From<Local> for Place<'_> {
 impl<'tcx> PlaceRef<'tcx> {
     /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or
     /// a single deref of a local.
-    //
-    // FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
     pub fn local_or_deref_local(&self) -> Option<Local> {
         match *self {
             PlaceRef { local, projection: [] }
@@ -1808,6 +1803,14 @@ impl<'tcx> PlaceRef<'tcx> {
             _ => None,
         }
     }
+
+    pub fn last_projection(&self) -> Option<(PlaceRef<'tcx>, PlaceElem<'tcx>)> {
+        if let &[ref proj_base @ .., elem] = self.projection {
+            Some((PlaceRef { local: self.local, projection: proj_base }, elem))
+        } else {
+            None
+        }
+    }
 }
 
 impl Debug for Place<'_> {
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 1e70f760504..698c2521596 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -1,7 +1,6 @@
-use crate::dep_graph::{DepConstructor, DepNode, WorkProduct, WorkProductId};
+use crate::dep_graph::{dep_constructor, DepNode, WorkProduct, WorkProductId};
 use crate::ich::{NodeIdHashingMode, StableHashingContext};
 use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt};
-use rustc_attr::InlineAttr;
 use rustc_data_structures::base_n;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
@@ -79,14 +78,6 @@ impl<'tcx> MonoItem<'tcx> {
     }
 
     pub fn instantiation_mode(&self, tcx: TyCtxt<'tcx>) -> InstantiationMode {
-        let generate_cgu_internal_copies = tcx
-            .sess
-            .opts
-            .debugging_opts
-            .inline_in_all_cgus
-            .unwrap_or_else(|| tcx.sess.opts.optimize != OptLevel::No)
-            && !tcx.sess.link_dead_code();
-
         match *self {
             MonoItem::Fn(ref instance) => {
                 let entry_def_id = tcx.entry_fn(LOCAL_CRATE).map(|(id, _)| id);
@@ -99,21 +90,26 @@ impl<'tcx> MonoItem<'tcx> {
                     return InstantiationMode::GloballyShared { may_conflict: false };
                 }
 
+                let generate_cgu_internal_copies = tcx
+                    .sess
+                    .opts
+                    .debugging_opts
+                    .inline_in_all_cgus
+                    .unwrap_or_else(|| tcx.sess.opts.optimize != OptLevel::No)
+                    && !tcx.sess.link_dead_code();
+
                 // At this point we don't have explicit linkage and we're an
-                // inlined function. If we're inlining into all CGUs then we'll
-                // be creating a local copy per CGU.
+                // inlined function. If we should generate local copies for each CGU,
+                // then return `LocalCopy`, otherwise we'll just generate one copy
+                // and share it with all CGUs in this crate.
                 if generate_cgu_internal_copies {
-                    return InstantiationMode::LocalCopy;
-                }
-
-                // Finally, if this is `#[inline(always)]` we're sure to respect
-                // that with an inline copy per CGU, but otherwise we'll be
-                // creating one copy of this `#[inline]` function which may
-                // conflict with upstream crates as it could be an exported
-                // symbol.
-                match tcx.codegen_fn_attrs(instance.def_id()).inline {
-                    InlineAttr::Always => InstantiationMode::LocalCopy,
-                    _ => InstantiationMode::GloballyShared { may_conflict: true },
+                    InstantiationMode::LocalCopy
+                } else {
+                    // Finally, if we've reached this point, then we should optimize for
+                    // compilation speed. In that regard, we will ignore any `#[inline]`
+                    // annotations on the function and simply codegen it as usual. This could
+                    // conflict with upstream crates as it could be an exported symbol.
+                    InstantiationMode::GloballyShared { may_conflict: true }
                 }
             }
             MonoItem::Static(..) | MonoItem::GlobalAsm(..) => {
@@ -362,7 +358,7 @@ impl<'tcx> CodegenUnit<'tcx> {
     }
 
     pub fn codegen_dep_node(&self, tcx: TyCtxt<'tcx>) -> DepNode {
-        DepConstructor::CompileCodegenUnit(tcx, self.name())
+        dep_constructor::CompileCodegenUnit(tcx, self.name())
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 65703d04c70..3adcdbe591f 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -245,8 +245,8 @@ pub fn suggest_constraining_type_param(
                 }
             }
 
-            match &param_spans[..] {
-                &[&param_span] => suggest_restrict(param_span.shrink_to_hi()),
+            match param_spans[..] {
+                [&param_span] => suggest_restrict(param_span.shrink_to_hi()),
                 _ => {
                     err.span_suggestion_verbose(
                         generics.where_clause.tail_span_for_suggestion(),
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 1fe1400fabe..863423b91a6 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -801,6 +801,15 @@ impl GenericParamDefKind {
             GenericParamDefKind::Const => "constant",
         }
     }
+    pub fn to_ord(&self, tcx: TyCtxt<'_>) -> ast::ParamKindOrd {
+        match self {
+            GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime,
+            GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type,
+            GenericParamDefKind::Const => {
+                ast::ParamKindOrd::Const { unordered: tcx.features().const_generics }
+            }
+        }
+    }
 }
 
 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
@@ -2888,19 +2897,11 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     pub fn opt_associated_item(self, def_id: DefId) -> Option<&'tcx AssocItem> {
-        let is_associated_item = if let Some(def_id) = def_id.as_local() {
-            matches!(
-                self.hir().get(self.hir().local_def_id_to_hir_id(def_id)),
-                Node::TraitItem(_) | Node::ImplItem(_)
-            )
+        if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) {
+            Some(self.associated_item(def_id))
         } else {
-            matches!(
-                self.def_kind(def_id),
-                DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy
-            )
-        };
-
-        is_associated_item.then(|| self.associated_item(def_id))
+            None
+        }
     }
 
     pub fn field_index(self, hir_id: hir::HirId, typeck_results: &TypeckResults<'_>) -> usize {
diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query/mod.rs
index b269dd09b72..acfa58e511e 100644
--- a/compiler/rustc_middle/src/ty/query/mod.rs
+++ b/compiler/rustc_middle/src/ty/query/mod.rs
@@ -1,4 +1,4 @@
-use crate::dep_graph::{self, DepKind, DepNode, DepNodeParams};
+use crate::dep_graph;
 use crate::hir::exports::Export;
 use crate::hir::map;
 use crate::infer::canonical::{self, Canonical};
@@ -103,138 +103,6 @@ pub use self::profiling_support::{IntoSelfProfilingString, QueryKeyStringBuilder
 
 rustc_query_append! { [define_queries!][<'tcx>] }
 
-/// The red/green evaluation system will try to mark a specific DepNode in the
-/// dependency graph as green by recursively trying to mark the dependencies of
-/// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
-/// where we don't know if it is red or green and we therefore actually have
-/// to recompute its value in order to find out. Since the only piece of
-/// information that we have at that point is the `DepNode` we are trying to
-/// re-evaluate, we need some way to re-run a query from just that. This is what
-/// `force_from_dep_node()` implements.
-///
-/// In the general case, a `DepNode` consists of a `DepKind` and an opaque
-/// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
-/// is usually constructed by computing a stable hash of the query-key that the
-/// `DepNode` corresponds to. Consequently, it is not in general possible to go
-/// back from hash to query-key (since hash functions are not reversible). For
-/// this reason `force_from_dep_node()` is expected to fail from time to time
-/// because we just cannot find out, from the `DepNode` alone, what the
-/// corresponding query-key is and therefore cannot re-run the query.
-///
-/// The system deals with this case letting `try_mark_green` fail which forces
-/// the root query to be re-evaluated.
-///
-/// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
-/// Fortunately, we can use some contextual information that will allow us to
-/// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
-/// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
-/// valid `DefPathHash`. Since we also always build a huge table that maps every
-/// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
-/// everything we need to re-run the query.
-///
-/// Take the `mir_promoted` query as an example. Like many other queries, it
-/// just has a single parameter: the `DefId` of the item it will compute the
-/// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
-/// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
-/// is actually a `DefPathHash`, and can therefore just look up the corresponding
-/// `DefId` in `tcx.def_path_hash_to_def_id`.
-///
-/// When you implement a new query, it will likely have a corresponding new
-/// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As
-/// a rule of thumb, if your query takes a `DefId` or `LocalDefId` as sole parameter,
-/// then `force_from_dep_node()` should not fail for it. Otherwise, you can just
-/// add it to the "We don't have enough information to reconstruct..." group in
-/// the match below.
-pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool {
-    // We must avoid ever having to call `force_from_dep_node()` for a
-    // `DepNode::codegen_unit`:
-    // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
-    // would always end up having to evaluate the first caller of the
-    // `codegen_unit` query that *is* reconstructible. This might very well be
-    // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
-    // to re-trigger calling the `codegen_unit` query with the right key. At
-    // that point we would already have re-done all the work we are trying to
-    // avoid doing in the first place.
-    // The solution is simple: Just explicitly call the `codegen_unit` query for
-    // each CGU, right after partitioning. This way `try_mark_green` will always
-    // hit the cache instead of having to go through `force_from_dep_node`.
-    // This assertion makes sure, we actually keep applying the solution above.
-    debug_assert!(
-        dep_node.kind != DepKind::codegen_unit,
-        "calling force_from_dep_node() on DepKind::codegen_unit"
-    );
-
-    if !dep_node.kind.can_reconstruct_query_key() {
-        return false;
-    }
-
-    macro_rules! force_from_dep_node {
-        ($($(#[$attr:meta])* [$($modifiers:tt)*] $name:ident($K:ty),)*) => {
-            match dep_node.kind {
-                // These are inputs that are expected to be pre-allocated and that
-                // should therefore always be red or green already.
-                DepKind::CrateMetadata |
-
-                // These are anonymous nodes.
-                DepKind::TraitSelect |
-
-                // We don't have enough information to reconstruct the query key of
-                // these.
-                DepKind::CompileCodegenUnit |
-
-                // Forcing this makes no sense.
-                DepKind::Null => {
-                    bug!("force_from_dep_node: encountered {:?}", dep_node)
-                }
-
-                $(DepKind::$name => {
-                    debug_assert!(<$K as DepNodeParams<TyCtxt<'_>>>::can_reconstruct_query_key());
-
-                    if let Some(key) = <$K as DepNodeParams<TyCtxt<'_>>>::recover(tcx, dep_node) {
-                        force_query::<queries::$name<'_>, _>(
-                            tcx,
-                            key,
-                            DUMMY_SP,
-                            *dep_node
-                        );
-                        return true;
-                    }
-                })*
-            }
-        }
-    }
-
-    rustc_dep_node_append! { [force_from_dep_node!][] }
-
-    false
-}
-
-pub(crate) fn try_load_from_on_disk_cache<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) {
-    macro_rules! try_load_from_on_disk_cache {
-        ($($name:ident,)*) => {
-            match dep_node.kind {
-                $(DepKind::$name => {
-                    if <query_keys::$name<'tcx> as DepNodeParams<TyCtxt<'_>>>::can_reconstruct_query_key() {
-                        debug_assert!(tcx.dep_graph
-                                         .node_color(dep_node)
-                                         .map(|c| c.is_green())
-                                         .unwrap_or(false));
-
-                        let key = <query_keys::$name<'tcx> as DepNodeParams<TyCtxt<'_>>>::recover(tcx, dep_node).unwrap_or_else(|| panic!("Failed to recover key for {:?} with hash {}", dep_node, dep_node.hash));
-                        if queries::$name::cache_on_disk(tcx, &key, None) {
-                            let _ = tcx.$name(key);
-                        }
-                    }
-                })*
-
-                _ => (),
-            }
-        }
-    }
-
-    rustc_cached_queries!(try_load_from_on_disk_cache!);
-}
-
 mod sealed {
     use super::{DefId, LocalDefId};
 
diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
index 8a1165bbd64..eb4f1b958be 100644
--- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
@@ -8,6 +8,7 @@ use rustc_data_structures::fingerprint::{Fingerprint, FingerprintDecoder, Finger
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, OnceCell};
 use rustc_data_structures::thin_vec::ThinVec;
+use rustc_data_structures::unhash::UnhashMap;
 use rustc_errors::Diagnostic;
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathHash;
@@ -87,7 +88,7 @@ pub struct OnDiskCache<'sess> {
     // compilation session. This is used as an initial 'guess' when
     // we try to map a `DefPathHash` to its `DefId` in the current compilation
     // session.
-    foreign_def_path_hashes: FxHashMap<DefPathHash, RawDefId>,
+    foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
 
     // The *next* compilation sessison's `foreign_def_path_hashes` - at
     // the end of our current compilation session, this will get written
@@ -95,19 +96,19 @@ pub struct OnDiskCache<'sess> {
     // will become `foreign_def_path_hashes` of the next compilation session.
     // This stores any `DefPathHash` that we may need to map to a `DefId`
     // during the next compilation session.
-    latest_foreign_def_path_hashes: Lock<FxHashMap<DefPathHash, RawDefId>>,
+    latest_foreign_def_path_hashes: Lock<UnhashMap<DefPathHash, RawDefId>>,
 
     // Maps `DefPathHashes` to their corresponding `LocalDefId`s for all
     // local items in the current compilation session. This is only populated
     // when we are in incremental mode and have loaded a pre-existing cache
     // from disk, since this map is only used when deserializing a `DefPathHash`
     // from the incremental cache.
-    local_def_path_hash_to_def_id: FxHashMap<DefPathHash, LocalDefId>,
+    local_def_path_hash_to_def_id: UnhashMap<DefPathHash, LocalDefId>,
     // Caches all lookups of `DefPathHashes`, both for local and foreign
     // definitions. A definition from the previous compilation session
     // may no longer exist in the current compilation session, so
     // we use `Option<DefId>` so that we can cache a lookup failure.
-    def_path_hash_to_def_id_cache: Lock<FxHashMap<DefPathHash, Option<DefId>>>,
+    def_path_hash_to_def_id_cache: Lock<UnhashMap<DefPathHash, Option<DefId>>>,
 }
 
 // This type is used only for serialization and deserialization.
@@ -123,7 +124,7 @@ struct Footer {
     syntax_contexts: FxHashMap<u32, AbsoluteBytePos>,
     // See `OnDiskCache.expn_data`
     expn_data: FxHashMap<u32, AbsoluteBytePos>,
-    foreign_def_path_hashes: FxHashMap<DefPathHash, RawDefId>,
+    foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
 }
 
 type EncodedQueryResultIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
@@ -160,8 +161,8 @@ crate struct RawDefId {
     pub index: u32,
 }
 
-fn make_local_def_path_hash_map(definitions: &Definitions) -> FxHashMap<DefPathHash, LocalDefId> {
-    FxHashMap::from_iter(
+fn make_local_def_path_hash_map(definitions: &Definitions) -> UnhashMap<DefPathHash, LocalDefId> {
+    UnhashMap::from_iter(
         definitions
             .def_path_table()
             .all_def_path_hashes_and_def_ids(LOCAL_CRATE)
@@ -807,6 +808,15 @@ impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> {
 
 crate::implement_ty_decoder!(CacheDecoder<'a, 'tcx>);
 
+// This ensures that the `Decodable<opaque::Decoder>::decode` specialization for `Vec<u8>` is used
+// when a `CacheDecoder` is passed to `Decodable::decode`. Unfortunately, we have to manually opt
+// into specializations this way, given how `CacheDecoder` and the decoding traits currently work.
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Vec<u8> {
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        Decodable::decode(&mut d.opaque)
+    }
+}
+
 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for SyntaxContext {
     fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
         let syntax_contexts = decoder.syntax_contexts;
@@ -964,7 +974,7 @@ struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> {
     source_map: CachingSourceMapView<'tcx>,
     file_to_file_index: FxHashMap<*const SourceFile, SourceFileIndex>,
     hygiene_context: &'a HygieneEncodeContext,
-    latest_foreign_def_path_hashes: FxHashMap<DefPathHash, RawDefId>,
+    latest_foreign_def_path_hashes: UnhashMap<DefPathHash, RawDefId>,
 }
 
 impl<'a, 'tcx, E> CacheEncoder<'a, 'tcx, E>
@@ -1149,6 +1159,16 @@ where
     }
 }
 
+// This ensures that the `Encodable<opaque::Encoder>::encode` specialization for byte slices
+// is used when a `CacheEncoder` having an `opaque::Encoder` is passed to `Encodable::encode`.
+// Unfortunately, we have to manually opt into specializations this way, given how `CacheEncoder`
+// and the encoding traits currently work.
+impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx, opaque::Encoder>> for [u8] {
+    fn encode(&self, e: &mut CacheEncoder<'a, 'tcx, opaque::Encoder>) -> opaque::EncodeResult {
+        self.encode(e.encoder)
+    }
+}
+
 // An integer that will always encode to 8 bytes.
 struct IntEncodedWithFixedSize(u64);
 
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
index 1474c7abfad..db02ee67910 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
@@ -151,95 +151,88 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
                 let move_msg = if move_spans.for_closure() { " into closure" } else { "" };
 
+                let loop_message = if location == move_out.source || move_site.traversed_back_edge {
+                    ", in previous iteration of loop"
+                } else {
+                    ""
+                };
+
                 if location == move_out.source {
-                    err.span_label(
-                        span,
-                        format!(
-                            "value {}moved{} here, in previous iteration of loop",
-                            partially_str, move_msg
-                        ),
-                    );
                     is_loop_move = true;
-                } else if move_site.traversed_back_edge {
-                    err.span_label(
-                        move_span,
-                        format!(
-                            "value {}moved{} here, in previous iteration of loop",
-                            partially_str, move_msg
-                        ),
-                    );
-                } else {
-                    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 => {
+                }
+
+                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, partially_str, loop_message
+                                ),
+                            );
+                            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, partially_str, loop_message
+                                ),
+                            );
+                            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 call",
-                                        place_name, partially_str
+                                        "{} {}moved due to this implicit call to `.into_iter()`{}",
+                                        place_name, partially_str, loop_message
                                     ),
                                 );
-                                err.span_note(
-                                    var_span,
-                                    "this value implements `FnOnce`, which causes it to be moved when called",
-                                );
-                            }
-                            FnSelfUseKind::Operator { self_arg } => {
+                            } else {
                                 err.span_label(
                                     fn_call_span,
                                     &format!(
-                                        "{} {}moved due to usage in operator",
-                                        place_name, partially_str
+                                        "{} {}moved due to this method call{}",
+                                        place_name, partially_str, loop_message
                                     ),
                                 );
-                                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, partially_str
-                                        ),
-                                    );
-                                } else {
-                                    err.span_label(
-                                        fn_call_span,
-                                        &format!(
-                                            "{} {}moved due to this method call",
-                                            place_name, partially_str
-                                        ),
-                                    );
-                                }
-                                // 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)
-                                    );
-                                }
+                            // 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 takes ownership of the receiver `self`, which moves {}", place_name)
+                                );
                             }
-                            // Deref::deref takes &self, which cannot cause a move
-                            FnSelfUseKind::DerefCoercion { .. } => unreachable!(),
                         }
-                    } else {
-                        err.span_label(
-                            move_span,
-                            format!("value {}moved{} here", partially_str, move_msg),
-                        );
+                        // Deref::deref takes &self, which cannot cause a move
+                        FnSelfUseKind::DerefCoercion { .. } => unreachable!(),
+                    }
+                } else {
+                    err.span_label(
+                        move_span,
+                        format!("value {}moved{} here{}", partially_str, move_msg, loop_message),
+                    );
+                    // If the move error occurs due to a loop, don't show
+                    // another message for the same span
+                    if loop_message.is_empty() {
                         move_spans.var_span_label(
                             &mut err,
                             format!(
@@ -250,6 +243,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         );
                     }
                 }
+
                 if let UseSpans::PatUse(span) = move_spans {
                     err.span_suggestion_verbose(
                         span.shrink_to_lo(),
@@ -293,9 +287,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 );
             }
 
-            let ty =
-                Place::ty_from(used_place.local, used_place.projection, self.body, self.infcx.tcx)
-                    .ty;
+            let ty = PlaceRef::ty(&used_place, self.body, self.infcx.tcx).ty;
             let needs_note = match ty.kind() {
                 ty::Closure(id, _) => {
                     let tables = self.infcx.tcx.typeck(id.expect_local());
@@ -732,8 +724,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     ) -> (String, String, String, String) {
         // Define a small closure that we can use to check if the type of a place
         // is a union.
-        let union_ty = |place_base, place_projection| {
-            let ty = Place::ty_from(place_base, place_projection, self.body, self.infcx.tcx).ty;
+        let union_ty = |place_base| {
+            let ty = PlaceRef::ty(&place_base, self.body, self.infcx.tcx).ty;
             ty.ty_adt_def().filter(|adt| adt.is_union()).map(|_| ty)
         };
 
@@ -751,15 +743,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 // field access to a union. If we find that, then we will keep the place of the
                 // union being accessed and the field that was being accessed so we can check the
                 // second borrowed place for the same union and a access to a different field.
-                let Place { local, projection } = first_borrowed_place;
-
-                let mut cursor = projection.as_ref();
-                while let [proj_base @ .., elem] = cursor {
-                    cursor = proj_base;
-
+                for (place_base, elem) in first_borrowed_place.iter_projections().rev() {
                     match elem {
-                        ProjectionElem::Field(field, _) if union_ty(local, proj_base).is_some() => {
-                            return Some((PlaceRef { local, projection: proj_base }, field));
+                        ProjectionElem::Field(field, _) if union_ty(place_base).is_some() => {
+                            return Some((place_base, field));
                         }
                         _ => {}
                     }
@@ -769,23 +756,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             .and_then(|(target_base, target_field)| {
                 // With the place of a union and a field access into it, we traverse the second
                 // borrowed place and look for a access to a different field of the same union.
-                let Place { local, ref projection } = second_borrowed_place;
-
-                let mut cursor = &projection[..];
-                while let [proj_base @ .., elem] = cursor {
-                    cursor = proj_base;
-
+                for (place_base, elem) in second_borrowed_place.iter_projections().rev() {
                     if let ProjectionElem::Field(field, _) = elem {
-                        if let Some(union_ty) = union_ty(local, proj_base) {
-                            if field != target_field
-                                && local == target_base.local
-                                && proj_base == target_base.projection
-                            {
+                        if let Some(union_ty) = union_ty(place_base) {
+                            if field != target_field && place_base == target_base {
                                 return Some((
-                                    self.describe_any_place(PlaceRef {
-                                        local,
-                                        projection: proj_base,
-                                    }),
+                                    self.describe_any_place(place_base),
                                     self.describe_any_place(first_borrowed_place.as_ref()),
                                     self.describe_any_place(second_borrowed_place.as_ref()),
                                     union_ty.to_string(),
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs
index b1cebbd1f38..350e0d045fa 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs
@@ -302,7 +302,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             .find_map(|p| self.is_upvar_field_projection(p));
 
         let deref_base = match deref_target_place.projection.as_ref() {
-            &[ref proj_base @ .., ProjectionElem::Deref] => {
+            [proj_base @ .., ProjectionElem::Deref] => {
                 PlaceRef { local: deref_target_place.local, projection: &proj_base }
             }
             _ => bug!("deref_target_place is not a deref projection"),
diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs
index 44044d55532..006e05072a7 100644
--- a/compiler/rustc_mir/src/borrow_check/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/mod.rs
@@ -1740,20 +1740,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
         self.check_if_full_path_is_moved(location, desired_action, place_span, flow_state);
 
-        if let [base_proj @ .., ProjectionElem::Subslice { from, to, from_end: false }] =
-            place_span.0.projection
+        if let Some((place_base, ProjectionElem::Subslice { from, to, from_end: false })) =
+            place_span.0.last_projection()
         {
-            let place_ty =
-                Place::ty_from(place_span.0.local, base_proj, self.body(), self.infcx.tcx);
+            let place_ty = PlaceRef::ty(&place_base, self.body(), self.infcx.tcx);
             if let ty::Array(..) = place_ty.ty.kind() {
-                let array_place = PlaceRef { local: place_span.0.local, projection: base_proj };
                 self.check_if_subslice_element_is_moved(
                     location,
                     desired_action,
-                    (array_place, place_span.1),
+                    (place_base, place_span.1),
                     maybe_uninits,
-                    *from,
-                    *to,
+                    from,
+                    to,
                 );
                 return;
             }
@@ -1825,10 +1823,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         debug!("check_if_assigned_path_is_moved place: {:?}", place);
 
         // None case => assigning to `x` does not require `x` be initialized.
-        let mut cursor = &*place.projection.as_ref();
-        while let [proj_base @ .., elem] = cursor {
-            cursor = proj_base;
-
+        for (place_base, elem) in place.iter_projections().rev() {
             match elem {
                 ProjectionElem::Index(_/*operand*/) |
                 ProjectionElem::ConstantIndex { .. } |
@@ -1843,10 +1838,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 ProjectionElem::Deref => {
                     self.check_if_full_path_is_moved(
                         location, InitializationRequiringAction::Use,
-                        (PlaceRef {
-                            local: place.local,
-                            projection: proj_base,
-                        }, span), flow_state);
+                        (place_base, span), flow_state);
                     // (base initialized; no need to
                     // recur further)
                     break;
@@ -1862,15 +1854,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     // assigning to `P.f` requires `P` itself
                     // be already initialized
                     let tcx = self.infcx.tcx;
-                    let base_ty = Place::ty_from(place.local, proj_base, self.body(), tcx).ty;
+                    let base_ty = PlaceRef::ty(&place_base, self.body(), tcx).ty;
                     match base_ty.kind() {
                         ty::Adt(def, _) if def.has_dtor(tcx) => {
                             self.check_if_path_or_subpath_is_moved(
                                 location, InitializationRequiringAction::Assignment,
-                                (PlaceRef {
-                                    local: place.local,
-                                    projection: proj_base,
-                                }, span), flow_state);
+                                (place_base, span), flow_state);
 
                             // (base initialized; no need to
                             // recur further)
@@ -1880,10 +1869,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                         // Once `let s; s.x = V; read(s.x);`,
                         // is allowed, remove this match arm.
                         ty::Adt(..) | ty::Tuple(..) => {
-                            check_parent_of_field(self, location, PlaceRef {
-                                local: place.local,
-                                projection: proj_base,
-                            }, span, flow_state);
+                            check_parent_of_field(self, location, place_base, span, flow_state);
 
                             // rust-lang/rust#21232, #54499, #54986: during period where we reject
                             // partial initialization, do not complain about unnecessary `mut` on
@@ -1965,9 +1951,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 // no move out from an earlier location) then this is an attempt at initialization
                 // of the union - we should error in that case.
                 let tcx = this.infcx.tcx;
-                if let ty::Adt(def, _) =
-                    Place::ty_from(base.local, base.projection, this.body(), tcx).ty.kind()
-                {
+                if let ty::Adt(def, _) = PlaceRef::ty(&base, this.body(), tcx).ty.kind() {
                     if def.is_union() {
                         if this.move_data.path_map[mpi].iter().any(|moi| {
                             this.move_data.moves[*moi].source.is_predecessor_of(location, this.body)
@@ -2162,9 +2146,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         place: PlaceRef<'tcx>,
         is_local_mutation_allowed: LocalMutationIsAllowed,
     ) -> Result<RootPlace<'tcx>, PlaceRef<'tcx>> {
-        match place {
-            PlaceRef { local, projection: [] } => {
-                let local = &self.body.local_decls[local];
+        match place.last_projection() {
+            None => {
+                let local = &self.body.local_decls[place.local];
                 match local.mutability {
                     Mutability::Not => match is_local_mutation_allowed {
                         LocalMutationIsAllowed::Yes => Ok(RootPlace {
@@ -2186,11 +2170,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     }),
                 }
             }
-            PlaceRef { local: _, projection: [proj_base @ .., elem] } => {
+            Some((place_base, elem)) => {
                 match elem {
                     ProjectionElem::Deref => {
-                        let base_ty =
-                            Place::ty_from(place.local, proj_base, self.body(), self.infcx.tcx).ty;
+                        let base_ty = PlaceRef::ty(&place_base, self.body(), self.infcx.tcx).ty;
 
                         // Check the kind of deref to decide
                         match base_ty.kind() {
@@ -2208,10 +2191,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                             _ => LocalMutationIsAllowed::Yes,
                                         };
 
-                                        self.is_mutable(
-                                            PlaceRef { local: place.local, projection: proj_base },
-                                            mode,
-                                        )
+                                        self.is_mutable(place_base, mode)
                                     }
                                 }
                             }
@@ -2229,10 +2209,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                 }
                             }
                             // `Box<T>` owns its content, so mutable if its location is mutable
-                            _ if base_ty.is_box() => self.is_mutable(
-                                PlaceRef { local: place.local, projection: proj_base },
-                                is_local_mutation_allowed,
-                            ),
+                            _ if base_ty.is_box() => {
+                                self.is_mutable(place_base, is_local_mutation_allowed)
+                            }
                             // Deref should only be for reference, pointers or boxes
                             _ => bug!("Deref of unexpected type: {:?}", base_ty),
                         }
@@ -2286,10 +2265,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                     //     });
                                     // }
                                     // ```
-                                    let _ = self.is_mutable(
-                                        PlaceRef { local: place.local, projection: proj_base },
-                                        is_local_mutation_allowed,
-                                    )?;
+                                    let _ =
+                                        self.is_mutable(place_base, is_local_mutation_allowed)?;
                                     Ok(RootPlace {
                                         place_local: place.local,
                                         place_projection: place.projection,
@@ -2298,10 +2275,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                                 }
                             }
                         } else {
-                            self.is_mutable(
-                                PlaceRef { local: place.local, projection: proj_base },
-                                is_local_mutation_allowed,
-                            )
+                            self.is_mutable(place_base, is_local_mutation_allowed)
                         }
                     }
                 }
diff --git a/compiler/rustc_mir/src/borrow_check/prefixes.rs b/compiler/rustc_mir/src/borrow_check/prefixes.rs
index 6c5d42296f7..cf04c55eb68 100644
--- a/compiler/rustc_mir/src/borrow_check/prefixes.rs
+++ b/compiler/rustc_mir/src/borrow_check/prefixes.rs
@@ -10,7 +10,7 @@
 use super::MirBorrowckCtxt;
 
 use rustc_hir as hir;
-use rustc_middle::mir::{Body, Place, PlaceRef, ProjectionElem};
+use rustc_middle::mir::{Body, PlaceRef, ProjectionElem};
 use rustc_middle::ty::{self, TyCtxt};
 
 pub trait IsPrefixOf<'tcx> {
@@ -67,24 +67,23 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
         // downcasts here, but may return a base of a downcast).
 
         'cursor: loop {
-            match &cursor {
-                PlaceRef { local: _, projection: [] } => {
+            match cursor.last_projection() {
+                None => {
                     self.next = None;
                     return Some(cursor);
                 }
-                PlaceRef { local: _, projection: [proj_base @ .., elem] } => {
+                Some((cursor_base, elem)) => {
                     match elem {
                         ProjectionElem::Field(_ /*field*/, _ /*ty*/) => {
                             // FIXME: add union handling
-                            self.next =
-                                Some(PlaceRef { local: cursor.local, projection: proj_base });
+                            self.next = Some(cursor_base);
                             return Some(cursor);
                         }
                         ProjectionElem::Downcast(..)
                         | ProjectionElem::Subslice { .. }
                         | ProjectionElem::ConstantIndex { .. }
                         | ProjectionElem::Index(_) => {
-                            cursor = PlaceRef { local: cursor.local, projection: proj_base };
+                            cursor = cursor_base;
                             continue 'cursor;
                         }
                         ProjectionElem::Deref => {
@@ -92,7 +91,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
                         }
                     }
 
-                    assert_eq!(*elem, ProjectionElem::Deref);
+                    assert_eq!(elem, ProjectionElem::Deref);
 
                     match self.kind {
                         PrefixSet::Shallow => {
@@ -105,8 +104,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
                         PrefixSet::All => {
                             // All prefixes: just blindly enqueue the base
                             // of the projection.
-                            self.next =
-                                Some(PlaceRef { local: cursor.local, projection: proj_base });
+                            self.next = Some(cursor_base);
                             return Some(cursor);
                         }
                         PrefixSet::Supporting => {
@@ -119,7 +117,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
                     // derefs, except we stop at the deref of a shared
                     // reference.
 
-                    let ty = Place::ty_from(cursor.local, proj_base, self.body, self.tcx).ty;
+                    let ty = PlaceRef::ty(&cursor_base, self.body, self.tcx).ty;
                     match ty.kind() {
                         ty::RawPtr(_) | ty::Ref(_ /*rgn*/, _ /*ty*/, hir::Mutability::Not) => {
                             // don't continue traversing over derefs of raw pointers or shared
@@ -129,14 +127,12 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
                         }
 
                         ty::Ref(_ /*rgn*/, _ /*ty*/, hir::Mutability::Mut) => {
-                            self.next =
-                                Some(PlaceRef { local: cursor.local, projection: proj_base });
+                            self.next = Some(cursor_base);
                             return Some(cursor);
                         }
 
                         ty::Adt(..) if ty.is_box() => {
-                            self.next =
-                                Some(PlaceRef { local: cursor.local, projection: proj_base });
+                            self.next = Some(cursor_base);
                             return Some(cursor);
                         }
 
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
index 42cd050abc5..5aad7523c89 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
@@ -1855,8 +1855,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     self.assert_iscleanup(body, block_data, unwind, true);
                 }
             }
-            TerminatorKind::InlineAsm { ref destination, .. } => {
-                if let &Some(target) = destination {
+            TerminatorKind::InlineAsm { destination, .. } => {
+                if let Some(target) = destination {
                     self.assert_iscleanup(body, block_data, target, is_cleanup);
                 }
             }
diff --git a/compiler/rustc_mir/src/const_eval/machine.rs b/compiler/rustc_mir/src/const_eval/machine.rs
index 72912dd76ff..02a9ec4df16 100644
--- a/compiler/rustc_mir/src/const_eval/machine.rs
+++ b/compiler/rustc_mir/src/const_eval/machine.rs
@@ -13,6 +13,7 @@ use rustc_middle::mir::AssertMessage;
 use rustc_session::Limit;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_target::abi::{Align, Size};
+use rustc_target::spec::abi::Abi;
 
 use crate::interpret::{
     self, compile_time_machine, AllocId, Allocation, Frame, ImmTy, InterpCx, InterpResult, Memory,
@@ -203,6 +204,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
     fn find_mir_or_eval_fn(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
+        _abi: Abi,
         args: &[OpTy<'tcx>],
         _ret: Option<(PlaceTy<'tcx>, mir::BasicBlock)>,
         _unwind: Option<mir::BasicBlock>, // unwinding is not supported in consts
diff --git a/compiler/rustc_mir/src/interpret/machine.rs b/compiler/rustc_mir/src/interpret/machine.rs
index f50cc6c16ea..a1a825b3268 100644
--- a/compiler/rustc_mir/src/interpret/machine.rs
+++ b/compiler/rustc_mir/src/interpret/machine.rs
@@ -10,6 +10,7 @@ use rustc_middle::mir;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::def_id::DefId;
 use rustc_target::abi::Size;
+use rustc_target::spec::abi::Abi;
 
 use super::{
     AllocId, Allocation, AllocationExtra, CheckInAllocMsg, Frame, ImmTy, InterpCx, InterpResult,
@@ -144,6 +145,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
     fn find_mir_or_eval_fn(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
+        abi: Abi,
         args: &[OpTy<'tcx, Self::PointerTag>],
         ret: Option<(PlaceTy<'tcx, Self::PointerTag>, mir::BasicBlock)>,
         unwind: Option<mir::BasicBlock>,
@@ -154,6 +156,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
     fn call_extra_fn(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         fn_val: Self::ExtraFnVal,
+        abi: Abi,
         args: &[OpTy<'tcx, Self::PointerTag>],
         ret: Option<(PlaceTy<'tcx, Self::PointerTag>, mir::BasicBlock)>,
         unwind: Option<mir::BasicBlock>,
@@ -405,6 +408,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
     fn call_extra_fn(
         _ecx: &mut InterpCx<$mir, $tcx, Self>,
         fn_val: !,
+        _abi: Abi,
         _args: &[OpTy<$tcx>],
         _ret: Option<(PlaceTy<$tcx>, mir::BasicBlock)>,
         _unwind: Option<mir::BasicBlock>,
diff --git a/compiler/rustc_mir/src/interpret/terminator.rs b/compiler/rustc_mir/src/interpret/terminator.rs
index a2931325a28..575667f9a95 100644
--- a/compiler/rustc_mir/src/interpret/terminator.rs
+++ b/compiler/rustc_mir/src/interpret/terminator.rs
@@ -219,7 +219,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let instance = match fn_val {
             FnVal::Instance(instance) => instance,
             FnVal::Other(extra) => {
-                return M::call_extra_fn(self, extra, args, ret, unwind);
+                return M::call_extra_fn(self, extra, caller_abi, args, ret, unwind);
             }
         };
 
@@ -264,10 +264,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             | ty::InstanceDef::CloneShim(..)
             | ty::InstanceDef::Item(_) => {
                 // We need MIR for this fn
-                let body = match M::find_mir_or_eval_fn(self, instance, args, ret, unwind)? {
-                    Some(body) => body,
-                    None => return Ok(()),
-                };
+                let body =
+                    match M::find_mir_or_eval_fn(self, instance, caller_abi, args, ret, unwind)? {
+                        Some(body) => body,
+                        None => return Ok(()),
+                    };
 
                 self.push_stack_frame(
                     instance,
diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs
index d2e65abfbc7..9e90a7519cf 100644
--- a/compiler/rustc_mir/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs
@@ -209,16 +209,61 @@ impl NonConstOp for LiveDrop {
 }
 
 #[derive(Debug)]
+/// A borrow of a type that contains an `UnsafeCell` somewhere. The borrow never escapes to
+/// the final value of the constant.
+pub struct TransientCellBorrow;
+impl NonConstOp for TransientCellBorrow {
+    fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
+        Status::Unstable(sym::const_refs_to_cell)
+    }
+    fn importance(&self) -> DiagnosticImportance {
+        // The cases that cannot possibly work will already emit a `CellBorrow`, so we should
+        // not additionally emit a feature gate error if activating the feature gate won't work.
+        DiagnosticImportance::Secondary
+    }
+    fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
+        feature_err(
+            &ccx.tcx.sess.parse_sess,
+            sym::const_refs_to_cell,
+            span,
+            "cannot borrow here, since the borrowed element may contain interior mutability",
+        )
+    }
+}
+
+#[derive(Debug)]
+/// A borrow of a type that contains an `UnsafeCell` somewhere. The borrow might escape to
+/// the final value of the constant, and thus we cannot allow this (for now). We may allow
+/// it in the future for static items.
 pub struct CellBorrow;
 impl NonConstOp for CellBorrow {
     fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
-        struct_span_err!(
+        let mut err = struct_span_err!(
             ccx.tcx.sess,
             span,
             E0492,
-            "cannot borrow a constant which may contain \
-            interior mutability, create a static instead"
-        )
+            "{}s cannot refer to interior mutable data",
+            ccx.const_kind(),
+        );
+        err.span_label(
+            span,
+            format!("this borrow of an interior mutable value may end up in the final value"),
+        );
+        if let hir::ConstContext::Static(_) = ccx.const_kind() {
+            err.help(
+                "to fix this, the value can be extracted to a separate \
+                `static` item and then referenced",
+            );
+        }
+        if ccx.tcx.sess.teach(&err.get_code().unwrap()) {
+            err.note(
+                "A constant containing interior mutable data behind a reference can allow you
+                 to modify that data. This would make multiple uses of a constant to be able to
+                 see different values and allow circumventing the `Send` and `Sync` requirements
+                 for shared mutable data, which is unsound.",
+            );
+        }
+        err
     }
 }
 
diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs
index 90688ebbd0a..d1c07d1051d 100644
--- a/compiler/rustc_mir/src/transform/check_consts/validation.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs
@@ -3,6 +3,7 @@
 use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorReported};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{self as hir, HirId, LangItem};
+use rustc_index::bit_set::BitSet;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
@@ -188,6 +189,9 @@ pub struct Validator<'mir, 'tcx> {
     /// The span of the current statement.
     span: Span,
 
+    /// A set that stores for each local whether it has a `StorageDead` for it somewhere.
+    local_has_storage_dead: Option<BitSet<Local>>,
+
     error_emitted: Option<ErrorReported>,
     secondary_errors: Vec<Diagnostic>,
 }
@@ -206,6 +210,7 @@ impl Validator<'mir, 'tcx> {
             span: ccx.body.span,
             ccx,
             qualifs: Default::default(),
+            local_has_storage_dead: None,
             error_emitted: None,
             secondary_errors: Vec::new(),
         }
@@ -282,6 +287,27 @@ impl Validator<'mir, 'tcx> {
         }
     }
 
+    fn local_has_storage_dead(&mut self, local: Local) -> bool {
+        let ccx = self.ccx;
+        self.local_has_storage_dead
+            .get_or_insert_with(|| {
+                struct StorageDeads {
+                    locals: BitSet<Local>,
+                }
+                impl Visitor<'tcx> for StorageDeads {
+                    fn visit_statement(&mut self, stmt: &Statement<'tcx>, _: Location) {
+                        if let StatementKind::StorageDead(l) = stmt.kind {
+                            self.locals.insert(l);
+                        }
+                    }
+                }
+                let mut v = StorageDeads { locals: BitSet::new_empty(ccx.body.local_decls.len()) };
+                v.visit_body(ccx.body);
+                v.locals
+            })
+            .contains(local)
+    }
+
     pub fn qualifs_in_return_place(&mut self) -> ConstQualifs {
         self.qualifs.in_return_place(self.ccx, self.error_emitted)
     }
@@ -556,7 +582,29 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
                 );
 
                 if borrowed_place_has_mut_interior {
-                    self.check_op(ops::CellBorrow);
+                    match self.const_kind() {
+                        // In a const fn all borrows are transient or point to the places given via
+                        // references in the arguments (so we already checked them with
+                        // TransientCellBorrow/CellBorrow as appropriate).
+                        // The borrow checker guarantees that no new non-transient borrows are created.
+                        // NOTE: Once we have heap allocations during CTFE we need to figure out
+                        // how to prevent `const fn` to create long-lived allocations that point
+                        // to (interior) mutable memory.
+                        hir::ConstContext::ConstFn => self.check_op(ops::TransientCellBorrow),
+                        _ => {
+                            // Locals with StorageDead are definitely not part of the final constant value, and
+                            // it is thus inherently safe to permit such locals to have their
+                            // address taken as we can't end up with a reference to them in the
+                            // final value.
+                            // Note: This is only sound if every local that has a `StorageDead` has a
+                            // `StorageDead` in every control flow path leading to a `return` terminator.
+                            if self.local_has_storage_dead(place.local) {
+                                self.check_op(ops::TransientCellBorrow);
+                            } else {
+                                self.check_op(ops::CellBorrow);
+                            }
+                        }
+                    }
                 }
             }
 
diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs
index 1d949e020ed..2d6d0adf3bc 100644
--- a/compiler/rustc_mir/src/transform/const_prop.rs
+++ b/compiler/rustc_mir/src/transform/const_prop.rs
@@ -25,6 +25,7 @@ use rustc_middle::ty::{
 use rustc_session::lint;
 use rustc_span::{def_id::DefId, Span};
 use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TargetDataLayout};
+use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
 
 use crate::const_eval::ConstEvalErr;
@@ -187,6 +188,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
     fn find_mir_or_eval_fn(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _instance: ty::Instance<'tcx>,
+        _abi: Abi,
         _args: &[OpTy<'tcx>],
         _ret: Option<(PlaceTy<'tcx>, BasicBlock)>,
         _unwind: Option<BasicBlock>,
diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs
index 6e7575c1d71..52350c5d078 100644
--- a/compiler/rustc_mir/src/transform/inline.rs
+++ b/compiler/rustc_mir/src/transform/inline.rs
@@ -41,6 +41,15 @@ impl<'tcx> MirPass<'tcx> for Inline {
             return;
         }
 
+        if tcx.sess.opts.debugging_opts.instrument_coverage {
+            // Since `Inline` happens after `InstrumentCoverage`, the function-specific coverage
+            // counters can be invalidated, such as by merging coverage counter statements from
+            // a pre-inlined function into a different function. This kind of change is invalid,
+            // so inlining must be skipped. Note: This check is performed here so inlining can
+            // be disabled without preventing other optimizations (regardless of `mir_opt_level`).
+            return;
+        }
+
         if inline(tcx, body) {
             debug!("running simplify cfg on {:?}", body.source);
             CfgSimplifier::new(body).simplify();
@@ -742,11 +751,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
     }
 
     fn visit_span(&mut self, span: &mut Span) {
+        let mut expn_data =
+            ExpnData::default(ExpnKind::Inlined, *span, self.tcx.sess.edition(), None);
+        expn_data.def_site = self.body_span;
         // Make sure that all spans track the fact that they were inlined.
-        *span = self.callsite_span.fresh_expansion(ExpnData {
-            def_site: self.body_span,
-            ..ExpnData::default(ExpnKind::Inlined, *span, self.tcx.sess.edition(), None)
-        });
+        *span = self.callsite_span.fresh_expansion(expn_data);
     }
 
     fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index db817b378f9..a70c1a28176 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -503,6 +503,11 @@ fn non_exhaustive_match<'p, 'tcx>(
             ));
         }
     }
+    if let ty::Ref(_, sub_ty, _) = scrut_ty.kind() {
+        if cx.tcx.is_ty_uninhabited_from(cx.module, sub_ty, cx.param_env) {
+            err.note("references are always considered inhabited");
+        }
+    }
     err.emit();
 }
 
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 9abffbacfc3..62fd6936d21 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -236,7 +236,6 @@ pub fn parse_in<'a, T>(
 pub fn nt_to_tokenstream(
     nt: &Nonterminal,
     sess: &ParseSess,
-    span: Span,
     synthesize_tokens: CanSynthesizeMissingTokens,
 ) -> TokenStream {
     // A `Nonterminal` is often a parsed AST item. At this point we now
@@ -256,11 +255,18 @@ pub fn nt_to_tokenstream(
         |tokens: Option<&LazyTokenStream>| tokens.as_ref().map(|t| t.create_token_stream());
 
     let tokens = match *nt {
-        Nonterminal::NtItem(ref item) => {
-            prepend_attrs(sess, &item.attrs, nt, span, item.tokens.as_ref())
-        }
+        Nonterminal::NtItem(ref item) => prepend_attrs(sess, &item.attrs, nt, item.tokens.as_ref()),
         Nonterminal::NtBlock(ref block) => convert_tokens(block.tokens.as_ref()),
-        Nonterminal::NtStmt(ref stmt) => prepend_attrs(sess, stmt.attrs(), nt, span, stmt.tokens()),
+        Nonterminal::NtStmt(ref stmt) => {
+            let do_prepend = |tokens| prepend_attrs(sess, stmt.attrs(), nt, tokens);
+            if let ast::StmtKind::Empty = stmt.kind {
+                let tokens: TokenStream =
+                    tokenstream::TokenTree::token(token::Semi, stmt.span).into();
+                do_prepend(Some(&LazyTokenStream::new(tokens)))
+            } else {
+                do_prepend(stmt.tokens())
+            }
+        }
         Nonterminal::NtPat(ref pat) => convert_tokens(pat.tokens.as_ref()),
         Nonterminal::NtTy(ref ty) => convert_tokens(ty.tokens.as_ref()),
         Nonterminal::NtIdent(ident, is_raw) => {
@@ -277,31 +283,29 @@ pub fn nt_to_tokenstream(
             if expr.tokens.is_none() {
                 debug!("missing tokens for expr {:?}", expr);
             }
-            prepend_attrs(sess, &expr.attrs, nt, span, expr.tokens.as_ref())
+            prepend_attrs(sess, &expr.attrs, nt, expr.tokens.as_ref())
         }
     };
 
     if let Some(tokens) = tokens {
         return tokens;
     } else if matches!(synthesize_tokens, CanSynthesizeMissingTokens::Yes) {
-        return fake_token_stream(sess, nt, span);
+        return fake_token_stream(sess, nt);
     } else {
-        let pretty = rustc_ast_pretty::pprust::nonterminal_to_string_no_extra_parens(&nt);
-        panic!("Missing tokens at {:?} for nt {:?}", span, pretty);
+        panic!("Missing tokens for nt {:?}", pprust::nonterminal_to_string(nt));
     }
 }
 
-pub fn fake_token_stream(sess: &ParseSess, nt: &Nonterminal, span: Span) -> TokenStream {
+pub fn fake_token_stream(sess: &ParseSess, nt: &Nonterminal) -> TokenStream {
     let source = pprust::nonterminal_to_string(nt);
     let filename = FileName::macro_expansion_source_code(&source);
-    parse_stream_from_source_str(filename, source, sess, Some(span))
+    parse_stream_from_source_str(filename, source, sess, Some(nt.span()))
 }
 
 fn prepend_attrs(
     sess: &ParseSess,
     attrs: &[ast::Attribute],
     nt: &Nonterminal,
-    span: Span,
     tokens: Option<&tokenstream::LazyTokenStream>,
 ) -> Option<tokenstream::TokenStream> {
     if attrs.is_empty() {
@@ -312,7 +316,7 @@ fn prepend_attrs(
         // FIXME: Correctly handle tokens for inner attributes.
         // For now, we fall back to reparsing the original AST node
         if attr.style == ast::AttrStyle::Inner {
-            return Some(fake_token_stream(sess, nt, span));
+            return Some(fake_token_stream(sess, nt));
         }
         builder.push(attr.tokens());
     }
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index d11db74a3bd..f4332e4548a 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1599,10 +1599,6 @@ impl<'a> Parser<'a> {
         } else {
             Async::No
         };
-        if let Async::Yes { span, .. } = asyncness {
-            // Feature-gate `async ||` closures.
-            self.sess.gated_spans.gate(sym::async_closure, span);
-        }
 
         let capture_clause = self.parse_capture_clause()?;
         let decl = self.parse_fn_block_decl()?;
@@ -1619,6 +1615,11 @@ impl<'a> Parser<'a> {
             }
         };
 
+        if let Async::Yes { span, .. } = asyncness {
+            // Feature-gate `async ||` closures.
+            self.sess.gated_spans.gate(sym::async_closure, span);
+        }
+
         Ok(self.mk_expr(
             lo.to(body.span),
             ExprKind::Closure(capture_clause, asyncness, movability, decl, body, lo.to(decl_hi)),
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index e49b1a54e9b..4fcc9edb7d9 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -220,7 +220,22 @@ impl<'a> Parser<'a> {
         let info = if self.eat_keyword(kw::Use) {
             // USE ITEM
             let tree = self.parse_use_tree()?;
-            self.expect_semi()?;
+
+            // If wildcard or glob-like brace syntax doesn't have `;`,
+            // the user may not know `*` or `{}` should be the last.
+            if let Err(mut e) = self.expect_semi() {
+                match tree.kind {
+                    UseTreeKind::Glob => {
+                        e.note("the wildcard token must be last on the path").emit();
+                    }
+                    UseTreeKind::Nested(..) => {
+                        e.note("glob-like brace syntax must be last on the path").emit();
+                    }
+                    _ => (),
+                }
+                return Err(e);
+            }
+
             (Ident::invalid(), ItemKind::Use(P(tree)))
         } else if self.check_fn_front_matter() {
             // FUNCTION ITEM
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 073e62c41d3..45964b1c988 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -983,8 +983,8 @@ impl<'a> Parser<'a> {
                         _ => self.sess.gated_spans.gate(sym::extended_key_value_attributes, span),
                     }
 
-                    let token = token::Interpolated(Lrc::new(token::NtExpr(expr)));
-                    MacArgs::Eq(eq_span, TokenTree::token(token, span).into())
+                    let token_kind = token::Interpolated(Lrc::new(token::NtExpr(expr)));
+                    MacArgs::Eq(eq_span, Token::new(token_kind, span))
                 } else {
                     MacArgs::Empty
                 }
@@ -1239,7 +1239,15 @@ impl<'a> Parser<'a> {
         f: impl FnOnce(&mut Self) -> PResult<'a, R>,
     ) -> PResult<'a, (R, Option<LazyTokenStream>)> {
         let start_token = (self.token.clone(), self.token_spacing);
-        let cursor_snapshot = self.token_cursor.clone();
+        let cursor_snapshot = TokenCursor {
+            frame: self.token_cursor.frame.clone(),
+            // We only ever capture tokens within our current frame,
+            // so we can just use an empty frame stack
+            stack: vec![],
+            desugar_doc_comments: self.token_cursor.desugar_doc_comments,
+            num_next_calls: self.token_cursor.num_next_calls,
+            append_unglued_token: self.token_cursor.append_unglued_token.clone(),
+        };
 
         let ret = f(self)?;
 
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index f4bb9610940..21372725a68 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -2,7 +2,7 @@
 
 use crate::parse_in;
 
-use rustc_ast::tokenstream::DelimSpan;
+use rustc_ast::tokenstream::{DelimSpan, TokenTree};
 use rustc_ast::{self as ast, Attribute, MacArgs, MacDelimiter, MetaItem, MetaItemKind};
 use rustc_errors::{Applicability, PResult};
 use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP};
@@ -45,7 +45,8 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta
         kind: match &item.args {
             MacArgs::Empty => MetaItemKind::Word,
             MacArgs::Eq(_, t) => {
-                let v = parse_in(sess, t.clone(), "name value", |p| p.parse_unsuffixed_lit())?;
+                let t = TokenTree::Token(t.clone()).into();
+                let v = parse_in(sess, t, "name value", |p| p.parse_unsuffixed_lit())?;
                 MetaItemKind::NameValue(v)
             }
             MacArgs::Delimited(dspan, delim, t) => {
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index aeaa862f5fd..a6a61ffc5da 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -310,7 +310,7 @@ impl CheckAttrVisitor<'tcx> {
                 .sess
                 .struct_span_err(
                     meta.name_value_literal_span().unwrap_or_else(|| meta.span()),
-                    &format!("{:?} character isn't allowed in `#[doc(alias = \"...\")]`", c,),
+                    &format!("{:?} character isn't allowed in `#[doc(alias = \"...\")]`", c),
                 )
                 .emit();
             return false;
@@ -358,6 +358,17 @@ impl CheckAttrVisitor<'tcx> {
                 .emit();
             return false;
         }
+        let item_name = self.tcx.hir().name(hir_id);
+        if &*item_name.as_str() == doc_alias {
+            self.tcx
+                .sess
+                .struct_span_err(
+                    meta.span(),
+                    &format!("`#[doc(alias = \"...\")]` is the same as the item's name"),
+                )
+                .emit();
+            return false;
+        }
         true
     }
 
diff --git a/compiler/rustc_passes/src/intrinsicck.rs b/compiler/rustc_passes/src/intrinsicck.rs
index 711e8e87c6c..ee90e9c54f6 100644
--- a/compiler/rustc_passes/src/intrinsicck.rs
+++ b/compiler/rustc_passes/src/intrinsicck.rs
@@ -78,7 +78,7 @@ impl ExprVisitor<'tcx> {
                 return;
             }
 
-            // Special-case transmutting from `typeof(function)` and
+            // Special-case transmuting from `typeof(function)` and
             // `Option<typeof(function)>` to present a clearer error.
             let from = unpack_option_like(self.tcx, from);
             if let (&ty::FnDef(..), SizeSkeleton::Known(size_to)) = (from.kind(), sk_to) {
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index 5b50ef8627b..788f1df328c 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -149,7 +149,7 @@ impl<'tcx> Visitor<'tcx> for CheckParameters<'tcx> {
 fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, hir_id: HirId, body: &'tcx hir::Body<'tcx>, fn_span: Span) {
     let mut this = CheckInlineAssembly { tcx, items: Vec::new() };
     this.visit_body(body);
-    if let &[(ItemKind::Asm, _)] = &this.items[..] {
+    if let [(ItemKind::Asm, _)] = this.items[..] {
         // Ok.
     } else {
         tcx.struct_span_lint_hir(UNSUPPORTED_NAKED_FUNCTIONS, hir_id, fn_span, |lint| {
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 1bcfdf0faf6..c2db2c82fa1 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -832,10 +832,15 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> {
     }
 
     fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) {
+        // Non-opaque macros cannot make other items more accessible than they already are.
         if attr::find_transparency(&self.tcx.sess, &md.attrs, md.ast.macro_rules).0
             != Transparency::Opaque
         {
-            self.update(md.hir_id, Some(AccessLevel::Public));
+            // `#[macro_export]`-ed `macro_rules!` are `Public` since they
+            // ignore their containing path to always appear at the crate root.
+            if md.ast.macro_rules {
+                self.update(md.hir_id, Some(AccessLevel::Public));
+            }
             return;
         }
 
diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs
index ff52fdab19c..64aba870502 100644
--- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs
@@ -153,12 +153,6 @@ where
     }
 }
 
-impl<Ctxt: DepContext> DepNodeParams<Ctxt> for () {
-    fn to_fingerprint(&self, _: Ctxt) -> Fingerprint {
-        Fingerprint::ZERO
-    }
-}
-
 /// A "work product" corresponds to a `.o` (or other) file that we
 /// save in between runs. These IDs do not have a `DefId` but rather
 /// some independent path or string that persists between runs without
diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs
index da0b5aad6c8..b1c901633a7 100644
--- a/compiler/rustc_query_system/src/dep_graph/mod.rs
+++ b/compiler/rustc_query_system/src/dep_graph/mod.rs
@@ -61,7 +61,7 @@ pub trait DepContext: Copy {
 }
 
 /// Describe the different families of dependency nodes.
-pub trait DepKind: Copy + fmt::Debug + Eq + Ord + Hash {
+pub trait DepKind: Copy + fmt::Debug + Eq + Hash {
     const NULL: Self;
 
     /// Return whether this kind always require evaluation.
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 426f5bb41d6..d17af6120c7 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -566,7 +566,6 @@ fn incremental_verify_ich<CTX, K, V>(
     assert!(new_hash == old_hash, "found unstable fingerprints for {:?}", dep_node,);
 }
 
-#[inline(always)]
 fn force_query_with_job<C, CTX>(
     tcx: CTX,
     key: C::Key,
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index c5f783e84a9..e96fc185b7e 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -96,7 +96,7 @@ impl<'a> Resolver<'a> {
 
     /// Walks up the tree of definitions starting at `def_id`,
     /// stopping at the first `DefKind::Mod` encountered
-    fn nearest_mod_parent(&mut self, def_id: DefId) -> Module<'a> {
+    fn nearest_parent_mod(&mut self, def_id: DefId) -> Module<'a> {
         let def_key = self.cstore().def_key(def_id);
 
         let mut parent_id = DefId {
@@ -137,7 +137,7 @@ impl<'a> Resolver<'a> {
                 .get_opt_name()
                 .expect("given a DefId that wasn't a module");
 
-            let parent = Some(self.nearest_mod_parent(def_id));
+            let parent = Some(self.nearest_parent_mod(def_id));
             (name, parent)
         };
 
@@ -179,7 +179,7 @@ impl<'a> Resolver<'a> {
             // so this hopefully won't be a problem.
             //
             // See https://github.com/rust-lang/rust/pull/77984#issuecomment-712445508
-            self.nearest_mod_parent(def_id)
+            self.nearest_parent_mod(def_id)
         }
     }
 
@@ -266,7 +266,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 } else {
                     // If it's not in an enum, its visibility is restricted to the `mod` item
                     // that it's defined in.
-                    Ok(ty::Visibility::Restricted(self.parent_scope.module.normal_ancestor_id))
+                    Ok(ty::Visibility::Restricted(self.parent_scope.module.nearest_parent_mod))
                 }
             }
             ast::VisibilityKind::Restricted { ref path, id, .. } => {
@@ -803,7 +803,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 let module = self.r.new_module(
                     parent,
                     module_kind,
-                    parent.normal_ancestor_id,
+                    parent.nearest_parent_mod,
                     expansion,
                     item.span,
                 );
@@ -878,7 +878,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 let module = self.r.new_module(
                     parent,
                     module_kind,
-                    parent.normal_ancestor_id,
+                    parent.nearest_parent_mod,
                     expansion,
                     item.span,
                 );
@@ -921,7 +921,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
             let module = self.r.new_module(
                 parent,
                 ModuleKind::Block(block.id),
-                parent.normal_ancestor_id,
+                parent.nearest_parent_mod,
                 expansion,
                 block.span,
             );
@@ -1298,26 +1298,31 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
     method!(visit_ty: ast::Ty, ast::TyKind::MacCall, walk_ty);
 
     fn visit_item(&mut self, item: &'b Item) {
-        let macro_use = match item.kind {
+        let orig_module_scope = self.parent_scope.module;
+        self.parent_scope.macro_rules = match item.kind {
             ItemKind::MacroDef(..) => {
-                self.parent_scope.macro_rules = self.define_macro(item);
-                return;
+                let macro_rules_scope = self.define_macro(item);
+                visit::walk_item(self, item);
+                macro_rules_scope
             }
             ItemKind::MacCall(..) => {
-                self.parent_scope.macro_rules = self.visit_invoc_in_module(item.id);
-                return;
+                let macro_rules_scope = self.visit_invoc_in_module(item.id);
+                visit::walk_item(self, item);
+                macro_rules_scope
+            }
+            _ => {
+                let orig_macro_rules_scope = self.parent_scope.macro_rules;
+                self.build_reduced_graph_for_item(item);
+                visit::walk_item(self, item);
+                match item.kind {
+                    ItemKind::Mod(..) if self.contains_macro_use(&item.attrs) => {
+                        self.parent_scope.macro_rules
+                    }
+                    _ => orig_macro_rules_scope,
+                }
             }
-            ItemKind::Mod(..) => self.contains_macro_use(&item.attrs),
-            _ => false,
         };
-        let orig_current_module = self.parent_scope.module;
-        let orig_current_macro_rules_scope = self.parent_scope.macro_rules;
-        self.build_reduced_graph_for_item(item);
-        visit::walk_item(self, item);
-        self.parent_scope.module = orig_current_module;
-        if !macro_use {
-            self.parent_scope.macro_rules = orig_current_macro_rules_scope;
-        }
+        self.parent_scope.module = orig_module_scope;
     }
 
     fn visit_stmt(&mut self, stmt: &'b ast::Stmt) {
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 48bce884394..727d6ab53d8 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -91,7 +91,10 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
                 DefPathData::ValueNs(i.ident.name)
             }
             ItemKind::MacroDef(..) => DefPathData::MacroNs(i.ident.name),
-            ItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
+            ItemKind::MacCall(..) => {
+                visit::walk_item(self, i);
+                return self.visit_macro_invoc(i.id);
+            }
             ItemKind::GlobalAsm(..) => DefPathData::Misc,
             ItemKind::Use(..) => {
                 return visit::walk_item(self, i);
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 809de9beff6..4f8047ac2df 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -398,14 +398,30 @@ impl<'a> Resolver<'a> {
                 err.help("use the `|| { ... }` closure form instead");
                 err
             }
-            ResolutionError::AttemptToUseNonConstantValueInConstant => {
+            ResolutionError::AttemptToUseNonConstantValueInConstant(ident, sugg, current) => {
                 let mut err = struct_span_err!(
                     self.session,
                     span,
                     E0435,
                     "attempt to use a non-constant value in a constant"
                 );
-                err.span_label(span, "non-constant value");
+                // let foo =...
+                //     ^^^ given this Span
+                // ------- get this Span to have an applicable suggestion
+                let sp =
+                    self.session.source_map().span_extend_to_prev_str(ident.span, current, true);
+                if sp.lo().0 == 0 {
+                    err.span_label(ident.span, &format!("this would need to be a `{}`", sugg));
+                } else {
+                    let sp = sp.with_lo(BytePos(sp.lo().0 - current.len() as u32));
+                    err.span_suggestion(
+                        sp,
+                        &format!("consider using `{}` instead of `{}`", sugg, current),
+                        format!("{} {}", sugg, ident),
+                        Applicability::MaybeIncorrect,
+                    );
+                    err.span_label(span, "non-constant value");
+                }
                 err
             }
             ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, name, binding) => {
@@ -595,7 +611,8 @@ impl<'a> Resolver<'a> {
         filter_fn: &impl Fn(Res) -> bool,
     ) -> Option<TypoSuggestion> {
         let mut suggestions = Vec::new();
-        self.visit_scopes(scope_set, parent_scope, ident, |this, scope, use_prelude, _| {
+        let ctxt = ident.span.ctxt();
+        self.visit_scopes(scope_set, parent_scope, ctxt, |this, scope, use_prelude, _| {
             match scope {
                 Scope::DeriveHelpers(expn_id) => {
                     let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index fbe99a31150..8544e1d8ee5 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -92,6 +92,12 @@ crate enum HasGenericParams {
     No,
 }
 
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+crate enum ConstantItemKind {
+    Const,
+    Static,
+}
+
 /// The rib kind restricts certain accesses,
 /// e.g. to a `Res::Local` of an outer item.
 #[derive(Copy, Clone, Debug)]
@@ -119,7 +125,7 @@ crate enum RibKind<'a> {
     ///
     /// The `bool` indicates if this constant may reference generic parameters
     /// and is used to only allow generic parameters to be used in trivial constant expressions.
-    ConstantItemRibKind(bool),
+    ConstantItemRibKind(bool, Option<(Ident, ConstantItemKind)>),
 
     /// We passed through a module.
     ModuleRibKind(Module<'a>),
@@ -145,7 +151,7 @@ impl RibKind<'_> {
             NormalRibKind
             | ClosureOrAsyncRibKind
             | FnItemRibKind
-            | ConstantItemRibKind(_)
+            | ConstantItemRibKind(..)
             | ModuleRibKind(_)
             | MacroDefinition(_)
             | ConstParamTyRibKind => false,
@@ -262,52 +268,60 @@ impl<'a> PathSource<'a> {
 
     crate fn is_expected(self, res: Res) -> bool {
         match self {
-            PathSource::Type => matches!(res, Res::Def(
+            PathSource::Type => matches!(
+                res,
+                Res::Def(
                     DefKind::Struct
-                    | DefKind::Union
-                    | DefKind::Enum
-                    | DefKind::Trait
-                    | DefKind::TraitAlias
-                    | DefKind::TyAlias
-                    | DefKind::AssocTy
-                    | DefKind::TyParam
-                    | DefKind::OpaqueTy
-                    | DefKind::ForeignTy,
+                        | DefKind::Union
+                        | DefKind::Enum
+                        | DefKind::Trait
+                        | DefKind::TraitAlias
+                        | DefKind::TyAlias
+                        | DefKind::AssocTy
+                        | DefKind::TyParam
+                        | DefKind::OpaqueTy
+                        | DefKind::ForeignTy,
                     _,
-                )
-                | Res::PrimTy(..)
-                | Res::SelfTy(..)),
+                ) | Res::PrimTy(..)
+                    | Res::SelfTy(..)
+            ),
             PathSource::Trait(AliasPossibility::No) => matches!(res, Res::Def(DefKind::Trait, _)),
             PathSource::Trait(AliasPossibility::Maybe) => {
                 matches!(res, Res::Def(DefKind::Trait | DefKind::TraitAlias, _))
             }
-            PathSource::Expr(..) => matches!(res, Res::Def(
+            PathSource::Expr(..) => matches!(
+                res,
+                Res::Def(
                     DefKind::Ctor(_, CtorKind::Const | CtorKind::Fn)
-                    | DefKind::Const
-                    | DefKind::Static
-                    | DefKind::Fn
-                    | DefKind::AssocFn
-                    | DefKind::AssocConst
-                    | DefKind::ConstParam,
+                        | DefKind::Const
+                        | DefKind::Static
+                        | DefKind::Fn
+                        | DefKind::AssocFn
+                        | DefKind::AssocConst
+                        | DefKind::ConstParam,
                     _,
-                )
-                | Res::Local(..)
-                | Res::SelfCtor(..)),
-            PathSource::Pat => matches!(res, Res::Def(
+                ) | Res::Local(..)
+                    | Res::SelfCtor(..)
+            ),
+            PathSource::Pat => matches!(
+                res,
+                Res::Def(
                     DefKind::Ctor(_, CtorKind::Const) | DefKind::Const | DefKind::AssocConst,
                     _,
-                )
-                | Res::SelfCtor(..)),
+                ) | Res::SelfCtor(..)
+            ),
             PathSource::TupleStruct(..) => res.expected_in_tuple_struct_pat(),
-            PathSource::Struct => matches!(res, Res::Def(
+            PathSource::Struct => matches!(
+                res,
+                Res::Def(
                     DefKind::Struct
-                    | DefKind::Union
-                    | DefKind::Variant
-                    | DefKind::TyAlias
-                    | DefKind::AssocTy,
+                        | DefKind::Union
+                        | DefKind::Variant
+                        | DefKind::TyAlias
+                        | DefKind::AssocTy,
                     _,
-                )
-                | Res::SelfTy(..)),
+                ) | Res::SelfTy(..)
+            ),
             PathSource::TraitItem(ns) => match res {
                 Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) if ns == ValueNS => true,
                 Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true,
@@ -634,7 +648,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                             // Note that we might not be inside of an repeat expression here,
                             // but considering that `IsRepeatExpr` is only relevant for
                             // non-trivial constants this is doesn't matter.
-                            self.with_constant_rib(IsRepeatExpr::No, true, |this| {
+                            self.with_constant_rib(IsRepeatExpr::No, true, None, |this| {
                                 this.smart_resolve_path(
                                     ty.id,
                                     qself.as_ref(),
@@ -843,7 +857,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 | ClosureOrAsyncRibKind
                 | FnItemRibKind
                 | ItemRibKind(..)
-                | ConstantItemRibKind(_)
+                | ConstantItemRibKind(..)
                 | ModuleRibKind(..)
                 | ForwardTyParamBanRibKind
                 | ConstParamTyRibKind => {
@@ -970,6 +984,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                             this.with_constant_rib(
                                                 IsRepeatExpr::No,
                                                 true,
+                                                None,
                                                 |this| this.visit_expr(expr),
                                             );
                                         }
@@ -1012,11 +1027,19 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 self.with_item_rib(HasGenericParams::No, |this| {
                     this.visit_ty(ty);
                     if let Some(expr) = expr {
+                        let constant_item_kind = match item.kind {
+                            ItemKind::Const(..) => ConstantItemKind::Const,
+                            ItemKind::Static(..) => ConstantItemKind::Static,
+                            _ => unreachable!(),
+                        };
                         // We already forbid generic params because of the above item rib,
                         // so it doesn't matter whether this is a trivial constant.
-                        this.with_constant_rib(IsRepeatExpr::No, true, |this| {
-                            this.visit_expr(expr)
-                        });
+                        this.with_constant_rib(
+                            IsRepeatExpr::No,
+                            true,
+                            Some((item.ident, constant_item_kind)),
+                            |this| this.visit_expr(expr),
+                        );
                     }
                 });
             }
@@ -1118,15 +1141,16 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         &mut self,
         is_repeat: IsRepeatExpr,
         is_trivial: bool,
+        item: Option<(Ident, ConstantItemKind)>,
         f: impl FnOnce(&mut Self),
     ) {
         debug!("with_constant_rib: is_repeat={:?} is_trivial={}", is_repeat, is_trivial);
-        self.with_rib(ValueNS, ConstantItemRibKind(is_trivial), |this| {
+        self.with_rib(ValueNS, ConstantItemRibKind(is_trivial, item), |this| {
             this.with_rib(
                 TypeNS,
-                ConstantItemRibKind(is_repeat == IsRepeatExpr::Yes || is_trivial),
+                ConstantItemRibKind(is_repeat == IsRepeatExpr::Yes || is_trivial, item),
                 |this| {
-                    this.with_label_rib(ConstantItemRibKind(is_trivial), f);
+                    this.with_label_rib(ConstantItemRibKind(is_trivial, item), f);
                 },
             )
         });
@@ -1266,6 +1290,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                             this.with_constant_rib(
                                                 IsRepeatExpr::No,
                                                 true,
+                                                None,
                                                 |this| {
                                                     visit::walk_assoc_item(
                                                         this,
@@ -1775,7 +1800,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
             if this.should_report_errs() {
                 let (err, candidates) = this.smart_resolve_report_errors(path, span, source, res);
 
-                let def_id = this.parent_scope.module.normal_ancestor_id;
+                let def_id = this.parent_scope.module.nearest_parent_mod;
                 let instead = res.is_some();
                 let suggestion =
                     if res.is_none() { this.report_missing_type_error(path) } else { None };
@@ -1843,7 +1868,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
 
             drop(parent_err);
 
-            let def_id = this.parent_scope.module.normal_ancestor_id;
+            let def_id = this.parent_scope.module.nearest_parent_mod;
 
             if this.should_report_errs() {
                 this.r.use_injections.push(UseError {
@@ -2200,6 +2225,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         self.with_constant_rib(
             is_repeat,
             constant.value.is_potential_trivial_const_param(),
+            None,
             |this| {
                 visit::walk_anon_const(this, constant);
             },
@@ -2397,8 +2423,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 &mut found_traits,
                 &self.parent_scope,
             );
-            search_module =
-                unwrap_or!(self.r.hygienic_lexical_parent(search_module, &mut ident.span), break);
+            let mut span_data = ident.span.data();
+            search_module = unwrap_or!(
+                self.r.hygienic_lexical_parent(search_module, &mut span_data.ctxt),
+                break
+            );
+            ident.span = span_data.span();
         }
 
         if let Some(prelude) = self.r.prelude {
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 0de732b2cf9..fb364053e24 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -33,7 +33,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_data_structures::ptr_key::PtrKey;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
-use rustc_expand::base::SyntaxExtension;
+use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
 use rustc_hir::def::Namespace::*;
 use rustc_hir::def::{self, CtorOf, DefKind, NonMacroAttrKind, PartialRes};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX};
@@ -50,6 +50,7 @@ use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
 use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::Session;
+use rustc_span::edition::Edition;
 use rustc_span::hygiene::{ExpnId, ExpnKind, MacroKind, SyntaxContext, Transparency};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -64,7 +65,7 @@ use tracing::debug;
 use diagnostics::{extend_span_to_previous_binding, find_span_of_binding_until_next_binding};
 use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion};
 use imports::{Import, ImportKind, ImportResolver, NameResolution};
-use late::{HasGenericParams, PathSource, Rib, RibKind::*};
+use late::{ConstantItemKind, HasGenericParams, PathSource, Rib, RibKind::*};
 use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
 
 type Res = def::Res<NodeId>;
@@ -210,7 +211,11 @@ enum ResolutionError<'a> {
     /// Error E0434: can't capture dynamic environment in a fn item.
     CannotCaptureDynamicEnvironmentInFnItem,
     /// Error E0435: attempt to use a non-constant value in a constant.
-    AttemptToUseNonConstantValueInConstant,
+    AttemptToUseNonConstantValueInConstant(
+        Ident,
+        /* suggestion */ &'static str,
+        /* current */ &'static str,
+    ),
     /// Error E0530: `X` bindings cannot shadow `Y`s.
     BindingShadowsSomethingUnacceptable(&'static str, Symbol, &'a NameBinding<'a>),
     /// Error E0128: type parameters with a default cannot use forward-declared identifiers.
@@ -422,7 +427,9 @@ enum ModuleKind {
     ///
     /// This could be:
     ///
-    /// * A normal module ‒ either `mod from_file;` or `mod from_block { }`.
+    /// * A normal module – either `mod from_file;` or `mod from_block { }` –
+    ///   or the crate root (which is conceptually a top-level module).
+    ///   Note that the crate root's [name][Self::name] will be [`kw::Empty`].
     /// * A trait or an enum (it implicitly contains associated types, methods and variant
     ///   constructors).
     Def(DefKind, DefId, Symbol),
@@ -456,28 +463,42 @@ struct BindingKey {
 type Resolutions<'a> = RefCell<FxIndexMap<BindingKey, &'a RefCell<NameResolution<'a>>>>;
 
 /// One node in the tree of modules.
+///
+/// Note that a "module" in resolve is broader than a `mod` that you declare in Rust code. It may be one of these:
+///
+/// * `mod`
+/// * crate root (aka, top-level anonymous module)
+/// * `enum`
+/// * `trait`
+/// * curly-braced block with statements
+///
+/// You can use [`ModuleData::kind`] to determine the kind of module this is.
 pub struct ModuleData<'a> {
+    /// The direct parent module (it may not be a `mod`, however).
     parent: Option<Module<'a>>,
+    /// What kind of module this is, because this may not be a `mod`.
     kind: ModuleKind,
 
-    // The def id of the closest normal module (`mod`) ancestor (including this module).
-    normal_ancestor_id: DefId,
+    /// The [`DefId`] of the nearest `mod` item ancestor (which may be this module).
+    /// This may be the crate root.
+    nearest_parent_mod: DefId,
 
-    // Mapping between names and their (possibly in-progress) resolutions in this module.
-    // Resolutions in modules from other crates are not populated until accessed.
+    /// Mapping between names and their (possibly in-progress) resolutions in this module.
+    /// Resolutions in modules from other crates are not populated until accessed.
     lazy_resolutions: Resolutions<'a>,
-    // True if this is a module from other crate that needs to be populated on access.
+    /// True if this is a module from other crate that needs to be populated on access.
     populate_on_access: Cell<bool>,
 
-    // Macro invocations that can expand into items in this module.
+    /// Macro invocations that can expand into items in this module.
     unexpanded_invocations: RefCell<FxHashSet<ExpnId>>,
 
+    /// Whether `#[no_implicit_prelude]` is active.
     no_implicit_prelude: bool,
 
     glob_importers: RefCell<Vec<&'a Import<'a>>>,
     globs: RefCell<Vec<&'a Import<'a>>>,
 
-    // Used to memoize the traits in this module for faster searches through all traits in scope.
+    /// Used to memoize the traits in this module for faster searches through all traits in scope.
     traits: RefCell<Option<Box<[(Ident, &'a NameBinding<'a>)]>>>,
 
     /// Span of the module itself. Used for error reporting.
@@ -492,16 +513,16 @@ impl<'a> ModuleData<'a> {
     fn new(
         parent: Option<Module<'a>>,
         kind: ModuleKind,
-        normal_ancestor_id: DefId,
+        nearest_parent_mod: DefId,
         expansion: ExpnId,
         span: Span,
     ) -> Self {
         ModuleData {
             parent,
             kind,
-            normal_ancestor_id,
+            nearest_parent_mod,
             lazy_resolutions: Default::default(),
-            populate_on_access: Cell::new(!normal_ancestor_id.is_local()),
+            populate_on_access: Cell::new(!nearest_parent_mod.is_local()),
             unexpanded_invocations: Default::default(),
             no_implicit_prelude: false,
             glob_importers: RefCell::new(Vec::new()),
@@ -743,10 +764,13 @@ impl<'a> NameBinding<'a> {
     }
 
     fn is_variant(&self) -> bool {
-        matches!(self.kind, NameBindingKind::Res(
+        matches!(
+            self.kind,
+            NameBindingKind::Res(
                 Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Variant, ..), _),
                 _,
-            ))
+            )
+        )
     }
 
     fn is_extern_crate(&self) -> bool {
@@ -850,7 +874,7 @@ pub struct ExternPreludeEntry<'a> {
 
 /// Used for better errors for E0773
 enum BuiltinMacroState {
-    NotYetSeen(SyntaxExtension),
+    NotYetSeen(SyntaxExtensionKind),
     AlreadySeen(Span),
 }
 
@@ -1427,7 +1451,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn is_builtin_macro(&mut self, res: Res) -> bool {
-        self.get_macro(res).map_or(false, |ext| ext.is_builtin)
+        self.get_macro(res).map_or(false, |ext| ext.builtin_name.is_some())
     }
 
     fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId {
@@ -1519,11 +1543,11 @@ impl<'a> Resolver<'a> {
         &self,
         parent: Module<'a>,
         kind: ModuleKind,
-        normal_ancestor_id: DefId,
+        nearest_parent_mod: DefId,
         expn_id: ExpnId,
         span: Span,
     ) -> Module<'a> {
-        let module = ModuleData::new(Some(parent), kind, normal_ancestor_id, expn_id, span);
+        let module = ModuleData::new(Some(parent), kind, nearest_parent_mod, expn_id, span);
         self.arenas.alloc_module(module)
     }
 
@@ -1610,8 +1634,13 @@ impl<'a> Resolver<'a> {
         &mut self,
         scope_set: ScopeSet,
         parent_scope: &ParentScope<'a>,
-        ident: Ident,
-        mut visitor: impl FnMut(&mut Self, Scope<'a>, /*use_prelude*/ bool, Ident) -> Option<T>,
+        ctxt: SyntaxContext,
+        mut visitor: impl FnMut(
+            &mut Self,
+            Scope<'a>,
+            /*use_prelude*/ bool,
+            SyntaxContext,
+        ) -> Option<T>,
     ) -> Option<T> {
         // General principles:
         // 1. Not controlled (user-defined) names should have higher priority than controlled names
@@ -1654,7 +1683,7 @@ impl<'a> Resolver<'a> {
         // 4c. Standard library prelude (de-facto closed, controlled).
         // 6. Language prelude: builtin attributes (closed, controlled).
 
-        let rust_2015 = ident.span.rust_2015();
+        let rust_2015 = ctxt.edition() == Edition::Edition2015;
         let (ns, macro_kind, is_absolute_path) = match scope_set {
             ScopeSet::All(ns, _) => (ns, None, false),
             ScopeSet::AbsolutePath(ns) => (ns, None, true),
@@ -1667,7 +1696,7 @@ impl<'a> Resolver<'a> {
             TypeNS | ValueNS => Scope::Module(module),
             MacroNS => Scope::DeriveHelpers(parent_scope.expansion),
         };
-        let mut ident = ident.normalize_to_macros_2_0();
+        let mut ctxt = ctxt.normalize_to_macros_2_0();
         let mut use_prelude = !module.no_implicit_prelude;
 
         loop {
@@ -1703,7 +1732,7 @@ impl<'a> Resolver<'a> {
             };
 
             if visit {
-                if let break_result @ Some(..) = visitor(self, scope, use_prelude, ident) {
+                if let break_result @ Some(..) = visitor(self, scope, use_prelude, ctxt) {
                     return break_result;
                 }
             }
@@ -1733,17 +1762,17 @@ impl<'a> Resolver<'a> {
                 },
                 Scope::CrateRoot => match ns {
                     TypeNS => {
-                        ident.span.adjust(ExpnId::root());
+                        ctxt.adjust(ExpnId::root());
                         Scope::ExternPrelude
                     }
                     ValueNS | MacroNS => break,
                 },
                 Scope::Module(module) => {
                     use_prelude = !module.no_implicit_prelude;
-                    match self.hygienic_lexical_parent(module, &mut ident.span) {
+                    match self.hygienic_lexical_parent(module, &mut ctxt) {
                         Some(parent_module) => Scope::Module(parent_module),
                         None => {
-                            ident.span.adjust(ExpnId::root());
+                            ctxt.adjust(ExpnId::root());
                             match ns {
                                 TypeNS => Scope::ExternPrelude,
                                 ValueNS => Scope::StdLibPrelude,
@@ -1821,14 +1850,16 @@ impl<'a> Resolver<'a> {
             // Use the rib kind to determine whether we are resolving parameters
             // (macro 2.0 hygiene) or local variables (`macro_rules` hygiene).
             let rib_ident = if ribs[i].kind.contains_params() { normalized_ident } else { ident };
-            if let Some(res) = ribs[i].bindings.get(&rib_ident).cloned() {
+            if let Some((original_rib_ident_def, res)) = ribs[i].bindings.get_key_value(&rib_ident)
+            {
                 // The ident resolves to a type parameter or local variable.
                 return Some(LexicalScopeBinding::Res(self.validate_res_from_ribs(
                     i,
                     rib_ident,
-                    res,
+                    *res,
                     record_used,
                     path_span,
+                    *original_rib_ident_def,
                     ribs,
                 )));
             }
@@ -1866,16 +1897,18 @@ impl<'a> Resolver<'a> {
         ident = normalized_ident;
         let mut poisoned = None;
         loop {
+            let mut span_data = ident.span.data();
             let opt_module = if let Some(node_id) = record_used_id {
                 self.hygienic_lexical_parent_with_compatibility_fallback(
                     module,
-                    &mut ident.span,
+                    &mut span_data.ctxt,
                     node_id,
                     &mut poisoned,
                 )
             } else {
-                self.hygienic_lexical_parent(module, &mut ident.span)
+                self.hygienic_lexical_parent(module, &mut span_data.ctxt)
             };
+            ident.span = span_data.span();
             module = unwrap_or!(opt_module, break);
             let adjusted_parent_scope = &ParentScope { module, ..*parent_scope };
             let result = self.resolve_ident_in_module_unadjusted(
@@ -1949,10 +1982,10 @@ impl<'a> Resolver<'a> {
     fn hygienic_lexical_parent(
         &mut self,
         module: Module<'a>,
-        span: &mut Span,
+        ctxt: &mut SyntaxContext,
     ) -> Option<Module<'a>> {
-        if !module.expansion.outer_expn_is_descendant_of(span.ctxt()) {
-            return Some(self.macro_def_scope(span.remove_mark()));
+        if !module.expansion.outer_expn_is_descendant_of(*ctxt) {
+            return Some(self.macro_def_scope(ctxt.remove_mark()));
         }
 
         if let ModuleKind::Block(..) = module.kind {
@@ -1965,11 +1998,11 @@ impl<'a> Resolver<'a> {
     fn hygienic_lexical_parent_with_compatibility_fallback(
         &mut self,
         module: Module<'a>,
-        span: &mut Span,
+        ctxt: &mut SyntaxContext,
         node_id: NodeId,
         poisoned: &mut Option<NodeId>,
     ) -> Option<Module<'a>> {
-        if let module @ Some(..) = self.hygienic_lexical_parent(module, span) {
+        if let module @ Some(..) = self.hygienic_lexical_parent(module, ctxt) {
             return module;
         }
 
@@ -1992,9 +2025,9 @@ impl<'a> Resolver<'a> {
                 // The macro is a proc macro derive
                 if let Some(def_id) = module.expansion.expn_data().macro_def_id {
                     let ext = self.get_macro_by_def_id(def_id);
-                    if !ext.is_builtin
+                    if ext.builtin_name.is_none()
                         && ext.macro_kind() == MacroKind::Derive
-                        && parent.expansion.outer_expn_is_descendant_of(span.ctxt())
+                        && parent.expansion.outer_expn_is_descendant_of(*ctxt)
                     {
                         *poisoned = Some(node_id);
                         return module.parent;
@@ -2116,7 +2149,7 @@ impl<'a> Resolver<'a> {
                 return self.graph_root;
             }
         };
-        let module = self.get_module(DefId { index: CRATE_DEF_INDEX, ..module.normal_ancestor_id });
+        let module = self.get_module(DefId { index: CRATE_DEF_INDEX, ..module.nearest_parent_mod });
         debug!(
             "resolve_crate_root({:?}): got module {:?} ({:?}) (ident.span = {:?})",
             ident,
@@ -2128,10 +2161,10 @@ impl<'a> Resolver<'a> {
     }
 
     fn resolve_self(&mut self, ctxt: &mut SyntaxContext, module: Module<'a>) -> Module<'a> {
-        let mut module = self.get_module(module.normal_ancestor_id);
+        let mut module = self.get_module(module.nearest_parent_mod);
         while module.span.ctxt().normalize_to_macros_2_0() != *ctxt {
             let parent = module.parent.unwrap_or_else(|| self.macro_def_scope(ctxt.remove_mark()));
-            module = self.get_module(parent.normal_ancestor_id);
+            module = self.get_module(parent.nearest_parent_mod);
         }
         module
     }
@@ -2540,6 +2573,7 @@ impl<'a> Resolver<'a> {
         mut res: Res,
         record_used: bool,
         span: Span,
+        original_rib_ident_def: Ident,
         all_ribs: &[Rib<'a>],
     ) -> Res {
         const CG_BUG_STR: &str = "min_const_generics resolve check didn't stop compilation";
@@ -2586,10 +2620,32 @@ impl<'a> Resolver<'a> {
                                 res_err = Some(CannotCaptureDynamicEnvironmentInFnItem);
                             }
                         }
-                        ConstantItemRibKind(_) => {
+                        ConstantItemRibKind(_, item) => {
                             // Still doesn't deal with upvars
                             if record_used {
-                                self.report_error(span, AttemptToUseNonConstantValueInConstant);
+                                let (span, resolution_error) =
+                                    if let Some((ident, constant_item_kind)) = item {
+                                        let kind_str = match constant_item_kind {
+                                            ConstantItemKind::Const => "const",
+                                            ConstantItemKind::Static => "static",
+                                        };
+                                        (
+                                            span,
+                                            AttemptToUseNonConstantValueInConstant(
+                                                ident, "let", kind_str,
+                                            ),
+                                        )
+                                    } else {
+                                        (
+                                            rib_ident.span,
+                                            AttemptToUseNonConstantValueInConstant(
+                                                original_rib_ident_def,
+                                                "const",
+                                                "let",
+                                            ),
+                                        )
+                                    };
+                                self.report_error(span, resolution_error);
                             }
                             return Res::Err;
                         }
@@ -2625,7 +2681,7 @@ impl<'a> Resolver<'a> {
                             in_ty_param_default = true;
                             continue;
                         }
-                        ConstantItemRibKind(trivial) => {
+                        ConstantItemRibKind(trivial, _) => {
                             let features = self.session.features_untracked();
                             // HACK(min_const_generics): We currently only allow `N` or `{ N }`.
                             if !(trivial
@@ -2718,7 +2774,7 @@ impl<'a> Resolver<'a> {
                             in_ty_param_default = true;
                             continue;
                         }
-                        ConstantItemRibKind(trivial) => {
+                        ConstantItemRibKind(trivial, _) => {
                             let features = self.session.features_untracked();
                             // HACK(min_const_generics): We currently only allow `N` or `{ N }`.
                             if !(trivial
@@ -2793,7 +2849,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool {
-        vis.is_accessible_from(module.normal_ancestor_id, self)
+        vis.is_accessible_from(module.nearest_parent_mod, self)
     }
 
     fn set_binding_parent_module(&mut self, binding: &'a NameBinding<'a>, module: Module<'a>) {
@@ -2817,7 +2873,7 @@ impl<'a> Resolver<'a> {
             self.binding_parent_modules.get(&PtrKey(modularized)),
         ) {
             (Some(macro_rules), Some(modularized)) => {
-                macro_rules.normal_ancestor_id == modularized.normal_ancestor_id
+                macro_rules.nearest_parent_mod == modularized.nearest_parent_mod
                     && modularized.is_ancestor_of(macro_rules)
             }
             _ => false,
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 5ad7c83ca36..5c74094ecd3 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -14,7 +14,8 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::ptr_key::PtrKey;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::struct_span_err;
-use rustc_expand::base::{Indeterminate, InvocationRes, ResolverExpand, SyntaxExtension};
+use rustc_expand::base::{Indeterminate, InvocationRes, ResolverExpand};
+use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
 use rustc_expand::compile_declarative_macro;
 use rustc_expand::expand::{AstFragment, Invocation, InvocationKind};
 use rustc_feature::is_builtin_attr_name;
@@ -176,10 +177,11 @@ impl<'a> ResolverExpand for Resolver<'a> {
         parent_scope.module.unexpanded_invocations.borrow_mut().remove(&expansion);
     }
 
-    fn register_builtin_macro(&mut self, ident: Ident, ext: SyntaxExtension) {
-        if self.builtin_macros.insert(ident.name, BuiltinMacroState::NotYetSeen(ext)).is_some() {
+    fn register_builtin_macro(&mut self, name: Symbol, ext: SyntaxExtensionKind) {
+        if self.builtin_macros.insert(name, BuiltinMacroState::NotYetSeen(ext)).is_some() {
             self.session
-                .span_err(ident.span, &format!("built-in macro `{}` was already defined", ident));
+                .diagnostic()
+                .bug(&format!("built-in macro `{}` was already registered", name));
         }
     }
 
@@ -285,7 +287,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
                                 helper_attrs.extend(
                                     ext.helper_attrs.iter().map(|name| Ident::new(*name, span)),
                                 );
-                                if ext.is_derive_copy {
+                                if ext.builtin_name == Some(sym::Copy) {
                                     self.containers_deriving_copy.insert(invoc_id);
                                 }
                                 ext
@@ -328,7 +330,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
             if after_derive {
                 self.session.span_err(span, "macro attributes must be placed before `#[derive]`");
             }
-            let normal_module_def_id = self.macro_def_scope(invoc_id).normal_ancestor_id;
+            let normal_module_def_id = self.macro_def_scope(invoc_id).nearest_parent_mod;
             self.definitions.add_parent_module_of_macro_def(invoc_id, normal_module_def_id);
         }
 
@@ -618,8 +620,9 @@ impl<'a> Resolver<'a> {
         let break_result = self.visit_scopes(
             scope_set,
             parent_scope,
-            orig_ident,
-            |this, scope, use_prelude, ident| {
+            orig_ident.span.ctxt(),
+            |this, scope, use_prelude, ctxt| {
+                let ident = Ident::new(orig_ident.name, orig_ident.span.with_ctxt(ctxt));
                 let ok = |res, span, arenas| {
                     Ok((
                         (res, ty::Visibility::Public, span, ExpnId::root()).to_name_binding(arenas),
@@ -1089,14 +1092,14 @@ impl<'a> Resolver<'a> {
             edition,
         );
 
-        if result.is_builtin {
+        if let Some(builtin_name) = result.builtin_name {
             // The macro was marked with `#[rustc_builtin_macro]`.
-            if let Some(builtin_macro) = self.builtin_macros.get_mut(&item.ident.name) {
+            if let Some(builtin_macro) = self.builtin_macros.get_mut(&builtin_name) {
                 // The macro is a built-in, replace its expander function
                 // while still taking everything else from the source code.
                 // If we already loaded this builtin macro, give a better error message than 'no such builtin macro'.
                 match mem::replace(builtin_macro, BuiltinMacroState::AlreadySeen(item.span)) {
-                    BuiltinMacroState::NotYetSeen(ext) => result.kind = ext.kind,
+                    BuiltinMacroState::NotYetSeen(ext) => result.kind = ext,
                     BuiltinMacroState::AlreadySeen(span) => {
                         struct_span_err!(
                             self.session,
diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs
index 987badcedde..617a28ed519 100644
--- a/compiler/rustc_save_analysis/src/dump_visitor.rs
+++ b/compiler/rustc_save_analysis/src/dump_visitor.rs
@@ -582,7 +582,7 @@ impl<'tcx> DumpVisitor<'tcx> {
                 }
                 ref v => {
                     let mut value = format!("{}::{}", enum_data.name, name);
-                    if let &hir::VariantData::Tuple(ref fields, _) = v {
+                    if let hir::VariantData::Tuple(fields, _) = v {
                         value.push('(');
                         value.push_str(
                             &fields
@@ -653,7 +653,7 @@ impl<'tcx> DumpVisitor<'tcx> {
         let map = &self.tcx.hir();
         self.nest_typeck_results(map.local_def_id(item.hir_id), |v| {
             v.visit_ty(&typ);
-            if let &Some(ref trait_ref) = trait_ref {
+            if let Some(trait_ref) = trait_ref {
                 v.process_path(trait_ref.hir_ref_id, &hir::QPath::Resolved(None, &trait_ref.path));
             }
             v.process_generic_params(generics, "", item.hir_id);
@@ -1082,7 +1082,7 @@ impl<'tcx> DumpVisitor<'tcx> {
                     );
                 }
 
-                if let &Some(ref default_ty) = default_ty {
+                if let Some(default_ty) = default_ty {
                     self.visit_ty(default_ty)
                 }
             }
diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs
index e7d1c9d3bbe..ab3da270fe6 100644
--- a/compiler/rustc_save_analysis/src/sig.rs
+++ b/compiler/rustc_save_analysis/src/sig.rs
@@ -619,7 +619,6 @@ impl<'hir> Sig for hir::Generics<'hir> {
                 param_text.push_str(&ty_to_string(&ty));
                 if let Some(ref _default) = default {
                     // FIXME(const_generics_defaults): push the `default` value here
-                    todo!();
                 }
             }
             if !param.bounds.is_empty() {
diff --git a/compiler/rustc_serialize/src/collection_impls.rs b/compiler/rustc_serialize/src/collection_impls.rs
index 3d274cb0150..ae6d27e037b 100644
--- a/compiler/rustc_serialize/src/collection_impls.rs
+++ b/compiler/rustc_serialize/src/collection_impls.rs
@@ -11,12 +11,8 @@ use smallvec::{Array, SmallVec};
 
 impl<S: Encoder, A: Array<Item: Encodable<S>>> Encodable<S> for SmallVec<A> {
     fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_seq(self.len(), |s| {
-            for (i, e) in self.iter().enumerate() {
-                s.emit_seq_elt(i, |s| e.encode(s))?;
-            }
-            Ok(())
-        })
+        let slice: &[A::Item] = self;
+        slice.encode(s)
     }
 }
 
@@ -292,46 +288,28 @@ where
 
 impl<E: Encoder, T: Encodable<E>> Encodable<E> for Rc<[T]> {
     fn encode(&self, s: &mut E) -> Result<(), E::Error> {
-        s.emit_seq(self.len(), |s| {
-            for (index, e) in self.iter().enumerate() {
-                s.emit_seq_elt(index, |s| e.encode(s))?;
-            }
-            Ok(())
-        })
+        let slice: &[T] = self;
+        slice.encode(s)
     }
 }
 
 impl<D: Decoder, T: Decodable<D>> Decodable<D> for Rc<[T]> {
     fn decode(d: &mut D) -> Result<Rc<[T]>, D::Error> {
-        d.read_seq(|d, len| {
-            let mut vec = Vec::with_capacity(len);
-            for index in 0..len {
-                vec.push(d.read_seq_elt(index, |d| Decodable::decode(d))?);
-            }
-            Ok(vec.into())
-        })
+        let vec: Vec<T> = Decodable::decode(d)?;
+        Ok(vec.into())
     }
 }
 
 impl<E: Encoder, T: Encodable<E>> Encodable<E> for Arc<[T]> {
     fn encode(&self, s: &mut E) -> Result<(), E::Error> {
-        s.emit_seq(self.len(), |s| {
-            for (index, e) in self.iter().enumerate() {
-                s.emit_seq_elt(index, |s| e.encode(s))?;
-            }
-            Ok(())
-        })
+        let slice: &[T] = self;
+        slice.encode(s)
     }
 }
 
 impl<D: Decoder, T: Decodable<D>> Decodable<D> for Arc<[T]> {
     fn decode(d: &mut D) -> Result<Arc<[T]>, D::Error> {
-        d.read_seq(|d, len| {
-            let mut vec = Vec::with_capacity(len);
-            for index in 0..len {
-                vec.push(d.read_seq_elt(index, |d| Decodable::decode(d))?);
-            }
-            Ok(vec.into())
-        })
+        let vec: Vec<T> = Decodable::decode(d)?;
+        Ok(vec.into())
     }
 }
diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs
index ac1cdc6ad45..f58ed14d997 100644
--- a/compiler/rustc_serialize/src/lib.rs
+++ b/compiler/rustc_serialize/src/lib.rs
@@ -14,6 +14,8 @@ Core encoding and decoding interfaces.
 #![feature(nll)]
 #![feature(associated_type_bounds)]
 #![cfg_attr(bootstrap, feature(min_const_generics))]
+#![feature(min_specialization)]
+#![feature(vec_spare_capacity)]
 #![cfg_attr(test, feature(test))]
 #![allow(rustc::internal)]
 
diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs
index 8b79c93e760..673742df7f0 100644
--- a/compiler/rustc_serialize/src/opaque.rs
+++ b/compiler/rustc_serialize/src/opaque.rs
@@ -1,6 +1,8 @@
 use crate::leb128::{self, read_signed_leb128, write_signed_leb128};
 use crate::serialize;
 use std::borrow::Cow;
+use std::mem::MaybeUninit;
+use std::ptr;
 
 // -----------------------------------------------------------------------------
 // Encoder
@@ -179,11 +181,19 @@ impl<'a> Decoder<'a> {
     }
 
     #[inline]
-    pub fn read_raw_bytes(&mut self, s: &mut [u8]) -> Result<(), String> {
+    pub fn read_raw_bytes(&mut self, s: &mut [MaybeUninit<u8>]) -> Result<(), String> {
         let start = self.position;
         let end = start + s.len();
+        assert!(end <= self.data.len());
 
-        s.copy_from_slice(&self.data[start..end]);
+        // SAFETY: Both `src` and `dst` point to at least `s.len()` elements:
+        // `src` points to at least `s.len()` elements by above assert, and
+        // `dst` points to `s.len()` elements by derivation from `s`.
+        unsafe {
+            let src = self.data.as_ptr().add(start);
+            let dst = s.as_mut_ptr() as *mut u8;
+            ptr::copy_nonoverlapping(src, dst, s.len());
+        }
 
         self.position = end;
 
@@ -316,3 +326,36 @@ impl<'a> serialize::Decoder for Decoder<'a> {
         err.to_string()
     }
 }
+
+// Specializations for contiguous byte sequences follow. The default implementations for slices
+// encode and decode each element individually. This isn't necessary for `u8` slices when using
+// opaque encoders and decoders, because each `u8` is unchanged by encoding and decoding.
+// Therefore, we can use more efficient implementations that process the entire sequence at once.
+
+// Specialize encoding byte slices. This specialization also applies to encoding `Vec<u8>`s, etc.,
+// since the default implementations call `encode` on their slices internally.
+impl serialize::Encodable<Encoder> for [u8] {
+    fn encode(&self, e: &mut Encoder) -> EncodeResult {
+        serialize::Encoder::emit_usize(e, self.len())?;
+        e.emit_raw_bytes(self);
+        Ok(())
+    }
+}
+
+// Specialize decoding `Vec<u8>`. This specialization also applies to decoding `Box<[u8]>`s, etc.,
+// since the default implementations call `decode` to produce a `Vec<u8>` internally.
+impl<'a> serialize::Decodable<Decoder<'a>> for Vec<u8> {
+    fn decode(d: &mut Decoder<'a>) -> Result<Self, String> {
+        let len = serialize::Decoder::read_usize(d)?;
+
+        let mut v = Vec::with_capacity(len);
+        let buf = &mut v.spare_capacity_mut()[..len];
+        d.read_raw_bytes(buf)?;
+
+        unsafe {
+            v.set_len(len);
+        }
+
+        Ok(v)
+    }
+}
diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs
index aa305f3c7fc..47aad5b88c6 100644
--- a/compiler/rustc_serialize/src/serialize.rs
+++ b/compiler/rustc_serialize/src/serialize.rs
@@ -527,7 +527,7 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Rc<T> {
 }
 
 impl<S: Encoder, T: Encodable<S>> Encodable<S> for [T] {
-    fn encode(&self, s: &mut S) -> Result<(), S::Error> {
+    default fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_seq(self.len(), |s| {
             for (i, e) in self.iter().enumerate() {
                 s.emit_seq_elt(i, |s| e.encode(s))?
@@ -545,7 +545,7 @@ impl<S: Encoder, T: Encodable<S>> Encodable<S> for Vec<T> {
 }
 
 impl<D: Decoder, T: Decodable<D>> Decodable<D> for Vec<T> {
-    fn decode(d: &mut D) -> Result<Vec<T>, D::Error> {
+    default fn decode(d: &mut D) -> Result<Vec<T>, D::Error> {
         d.read_seq(|d, len| {
             let mut v = Vec::with_capacity(len);
             for i in 0..len {
@@ -591,13 +591,8 @@ where
     [T]: ToOwned<Owned = Vec<T>>,
 {
     fn decode(d: &mut D) -> Result<Cow<'static, [T]>, D::Error> {
-        d.read_seq(|d, len| {
-            let mut v = Vec::with_capacity(len);
-            for i in 0..len {
-                v.push(d.read_seq_elt(i, |d| Decodable::decode(d))?);
-            }
-            Ok(Cow::Owned(v))
-        })
+        let v: Vec<T> = Decodable::decode(d)?;
+        Ok(Cow::Owned(v))
     }
 }
 
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 62859f4bef4..0cafdec1495 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -819,7 +819,7 @@ pub fn default_configuration(sess: &Session) -> CrateConfig {
         }
     }
     ret.insert((sym::target_arch, Some(Symbol::intern(arch))));
-    ret.insert((sym::target_endian, Some(Symbol::intern(end))));
+    ret.insert((sym::target_endian, Some(Symbol::intern(end.as_str()))));
     ret.insert((sym::target_pointer_width, Some(Symbol::intern(&wordsz))));
     ret.insert((sym::target_env, Some(Symbol::intern(env))));
     ret.insert((sym::target_vendor, Some(Symbol::intern(vendor))));
@@ -1829,11 +1829,17 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         }
 
         if debugging_opts.mir_opt_level > 1 {
+            // Functions inlined during MIR transform can, at best, make it impossible to
+            // effectively cover inlined functions, and, at worst, break coverage map generation
+            // during LLVM codegen. For example, function counter IDs are only unique within a
+            // function. Inlining after these counters are injected can produce duplicate counters,
+            // resulting in an invalid coverage map (and ICE); so this option combination is not
+            // allowed.
             early_warn(
                 error_format,
                 &format!(
-                    "`-Z mir-opt-level={}` (any level > 1) enables function inlining, which \
-                    limits the effectiveness of `-Z instrument-coverage`.",
+                    "`-Z mir-opt-level={}` (or any level > 1) enables function inlining, which \
+                    is incompatible with `-Z instrument-coverage`. Inlining will be disabled.",
                     debugging_opts.mir_opt_level,
                 ),
             );
@@ -2166,6 +2172,7 @@ crate mod dep_tracking {
         SymbolManglingVersion, TrimmedDefPaths,
     };
     use crate::lint;
+    use crate::options::WasiExecModel;
     use crate::utils::NativeLibKind;
     use rustc_feature::UnstableFeatures;
     use rustc_span::edition::Edition;
@@ -2221,6 +2228,7 @@ crate mod dep_tracking {
     impl_dep_tracking_hash_via_hash!(Option<RelocModel>);
     impl_dep_tracking_hash_via_hash!(Option<CodeModel>);
     impl_dep_tracking_hash_via_hash!(Option<TlsModel>);
+    impl_dep_tracking_hash_via_hash!(Option<WasiExecModel>);
     impl_dep_tracking_hash_via_hash!(Option<PanicStrategy>);
     impl_dep_tracking_hash_via_hash!(Option<RelroLevel>);
     impl_dep_tracking_hash_via_hash!(Option<lint::Level>);
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 81f79f4b0e0..30af65e49a0 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -279,6 +279,7 @@ macro_rules! options {
         pub const parse_tls_model: &str =
             "one of supported TLS models (`rustc --print tls-models`)";
         pub const parse_target_feature: &str = parse_string;
+        pub const parse_wasi_exec_model: &str = "either `command` or `reactor`";
     }
 
     #[allow(dead_code)]
@@ -722,6 +723,15 @@ macro_rules! options {
                 None => false,
             }
         }
+
+        fn parse_wasi_exec_model(slot: &mut Option<WasiExecModel>, v: Option<&str>) -> bool {
+            match v {
+                Some("command")  => *slot = Some(WasiExecModel::Command),
+                Some("reactor") => *slot = Some(WasiExecModel::Reactor),
+                _ => return false,
+            }
+            true
+        }
     }
 ) }
 
@@ -1166,9 +1176,17 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "in general, enable more debug printouts (default: no)"),
     verify_llvm_ir: bool = (false, parse_bool, [TRACKED],
         "verify LLVM IR (default: no)"),
+    wasi_exec_model: Option<WasiExecModel> = (None, parse_wasi_exec_model, [TRACKED],
+        "whether to build a wasi command or reactor"),
 
     // This list is in alphabetical order.
     //
     // If you add a new option, please update:
-    // - src/librustc_interface/tests.rs
+    // - compiler/rustc_interface/src/tests.rs
+}
+
+#[derive(Clone, Hash)]
+pub enum WasiExecModel {
+    Command,
+    Reactor,
 }
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 3a420f5f9de..1f9a1af0f68 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -796,6 +796,14 @@ impl Session {
         self.opts.debugging_opts.tls_model.unwrap_or(self.target.tls_model)
     }
 
+    pub fn is_wasi_reactor(&self) -> bool {
+        self.target.options.os == "wasi"
+            && matches!(
+                self.opts.debugging_opts.wasi_exec_model,
+                Some(config::WasiExecModel::Reactor)
+            )
+    }
+
     pub fn must_not_eliminate_frame_pointers(&self) -> bool {
         // "mcount" function relies on stack pointer.
         // See <https://sourceware.org/binutils/docs/gprof/Implementation.html>.
@@ -1522,6 +1530,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
     }
 
     const ASAN_SUPPORTED_TARGETS: &[&str] = &[
+        "aarch64-apple-darwin",
         "aarch64-fuchsia",
         "aarch64-unknown-linux-gnu",
         "x86_64-apple-darwin",
@@ -1529,11 +1538,16 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
         "x86_64-unknown-freebsd",
         "x86_64-unknown-linux-gnu",
     ];
-    const LSAN_SUPPORTED_TARGETS: &[&str] =
-        &["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
+    const LSAN_SUPPORTED_TARGETS: &[&str] = &[
+        "aarch64-apple-darwin",
+        "aarch64-unknown-linux-gnu",
+        "x86_64-apple-darwin",
+        "x86_64-unknown-linux-gnu",
+    ];
     const MSAN_SUPPORTED_TARGETS: &[&str] =
         &["aarch64-unknown-linux-gnu", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu"];
     const TSAN_SUPPORTED_TARGETS: &[&str] = &[
+        "aarch64-apple-darwin",
         "aarch64-unknown-linux-gnu",
         "x86_64-apple-darwin",
         "x86_64-unknown-freebsd",
diff --git a/compiler/rustc_span/src/caching_source_map_view.rs b/compiler/rustc_span/src/caching_source_map_view.rs
index 15dd00fb483..8e21b9ff44a 100644
--- a/compiler/rustc_span/src/caching_source_map_view.rs
+++ b/compiler/rustc_span/src/caching_source_map_view.rs
@@ -1,5 +1,5 @@
 use crate::source_map::SourceMap;
-use crate::{BytePos, SourceFile};
+use crate::{BytePos, SourceFile, SpanData};
 use rustc_data_structures::sync::Lrc;
 use std::ops::Range;
 
@@ -24,6 +24,32 @@ struct CacheEntry {
     file_index: usize,
 }
 
+impl CacheEntry {
+    #[inline]
+    fn update(
+        &mut self,
+        new_file_and_idx: Option<(Lrc<SourceFile>, usize)>,
+        pos: BytePos,
+        time_stamp: usize,
+    ) {
+        if let Some((file, file_idx)) = new_file_and_idx {
+            self.file = file;
+            self.file_index = file_idx;
+        }
+
+        let line_index = self.file.lookup_line(pos).unwrap();
+        let line_bounds = self.file.line_bounds(line_index);
+        self.line_number = line_index + 1;
+        self.line = line_bounds;
+        self.touch(time_stamp);
+    }
+
+    #[inline]
+    fn touch(&mut self, time_stamp: usize) {
+        self.time_stamp = time_stamp;
+    }
+}
+
 #[derive(Clone)]
 pub struct CachingSourceMapView<'sm> {
     source_map: &'sm SourceMap,
@@ -57,59 +83,202 @@ impl<'sm> CachingSourceMapView<'sm> {
         self.time_stamp += 1;
 
         // Check if the position is in one of the cached lines
-        for cache_entry in self.line_cache.iter_mut() {
-            if cache_entry.line.contains(&pos) {
-                cache_entry.time_stamp = self.time_stamp;
+        let cache_idx = self.cache_entry_index(pos);
+        if cache_idx != -1 {
+            let cache_entry = &mut self.line_cache[cache_idx as usize];
+            cache_entry.touch(self.time_stamp);
 
-                return Some((
-                    cache_entry.file.clone(),
-                    cache_entry.line_number,
-                    pos - cache_entry.line.start,
-                ));
-            }
+            return Some((
+                cache_entry.file.clone(),
+                cache_entry.line_number,
+                pos - cache_entry.line.start,
+            ));
         }
 
         // No cache hit ...
-        let mut oldest = 0;
-        for index in 1..self.line_cache.len() {
-            if self.line_cache[index].time_stamp < self.line_cache[oldest].time_stamp {
-                oldest = index;
-            }
-        }
+        let oldest = self.oldest_cache_entry_index();
+
+        // If the entry doesn't point to the correct file, get the new file and index.
+        let new_file_and_idx = if !file_contains(&self.line_cache[oldest].file, pos) {
+            Some(self.file_for_position(pos)?)
+        } else {
+            None
+        };
 
         let cache_entry = &mut self.line_cache[oldest];
+        cache_entry.update(new_file_and_idx, pos, self.time_stamp);
 
-        // If the entry doesn't point to the correct file, fix it up
-        if !file_contains(&cache_entry.file, pos) {
-            let file_valid;
-            if self.source_map.files().len() > 0 {
-                let file_index = self.source_map.lookup_source_file_idx(pos);
-                let file = self.source_map.files()[file_index].clone();
-
-                if file_contains(&file, pos) {
-                    cache_entry.file = file;
-                    cache_entry.file_index = file_index;
-                    file_valid = true;
-                } else {
-                    file_valid = false;
+        Some((cache_entry.file.clone(), cache_entry.line_number, pos - cache_entry.line.start))
+    }
+
+    pub fn span_data_to_lines_and_cols(
+        &mut self,
+        span_data: &SpanData,
+    ) -> Option<(Lrc<SourceFile>, usize, BytePos, usize, BytePos)> {
+        self.time_stamp += 1;
+
+        // Check if lo and hi are in the cached lines.
+        let lo_cache_idx = self.cache_entry_index(span_data.lo);
+        let hi_cache_idx = self.cache_entry_index(span_data.hi);
+
+        if lo_cache_idx != -1 && hi_cache_idx != -1 {
+            // Cache hit for span lo and hi. Check if they belong to the same file.
+            let result = {
+                let lo = &self.line_cache[lo_cache_idx as usize];
+                let hi = &self.line_cache[hi_cache_idx as usize];
+
+                if lo.file_index != hi.file_index {
+                    return None;
                 }
-            } else {
-                file_valid = false;
+
+                (
+                    lo.file.clone(),
+                    lo.line_number,
+                    span_data.lo - lo.line.start,
+                    hi.line_number,
+                    span_data.hi - hi.line.start,
+                )
+            };
+
+            self.line_cache[lo_cache_idx as usize].touch(self.time_stamp);
+            self.line_cache[hi_cache_idx as usize].touch(self.time_stamp);
+
+            return Some(result);
+        }
+
+        // No cache hit or cache hit for only one of span lo and hi.
+        let oldest = if lo_cache_idx != -1 || hi_cache_idx != -1 {
+            let avoid_idx = if lo_cache_idx != -1 { lo_cache_idx } else { hi_cache_idx };
+            self.oldest_cache_entry_index_avoid(avoid_idx as usize)
+        } else {
+            self.oldest_cache_entry_index()
+        };
+
+        // If the entry doesn't point to the correct file, get the new file and index.
+        // Return early if the file containing beginning of span doesn't contain end of span.
+        let new_file_and_idx = if !file_contains(&self.line_cache[oldest].file, span_data.lo) {
+            let new_file_and_idx = self.file_for_position(span_data.lo)?;
+            if !file_contains(&new_file_and_idx.0, span_data.hi) {
+                return None;
             }
 
-            if !file_valid {
+            Some(new_file_and_idx)
+        } else {
+            let file = &self.line_cache[oldest].file;
+            if !file_contains(&file, span_data.hi) {
                 return None;
             }
+
+            None
+        };
+
+        // Update the cache entries.
+        let (lo_idx, hi_idx) = match (lo_cache_idx, hi_cache_idx) {
+            // Oldest cache entry is for span_data.lo line.
+            (-1, -1) => {
+                let lo = &mut self.line_cache[oldest];
+                lo.update(new_file_and_idx, span_data.lo, self.time_stamp);
+
+                if !lo.line.contains(&span_data.hi) {
+                    let new_file_and_idx = Some((lo.file.clone(), lo.file_index));
+                    let next_oldest = self.oldest_cache_entry_index_avoid(oldest);
+                    let hi = &mut self.line_cache[next_oldest];
+                    hi.update(new_file_and_idx, span_data.hi, self.time_stamp);
+                    (oldest, next_oldest)
+                } else {
+                    (oldest, oldest)
+                }
+            }
+            // Oldest cache entry is for span_data.lo line.
+            (-1, _) => {
+                let lo = &mut self.line_cache[oldest];
+                lo.update(new_file_and_idx, span_data.lo, self.time_stamp);
+                let hi = &mut self.line_cache[hi_cache_idx as usize];
+                hi.touch(self.time_stamp);
+                (oldest, hi_cache_idx as usize)
+            }
+            // Oldest cache entry is for span_data.hi line.
+            (_, -1) => {
+                let hi = &mut self.line_cache[oldest];
+                hi.update(new_file_and_idx, span_data.hi, self.time_stamp);
+                let lo = &mut self.line_cache[lo_cache_idx as usize];
+                lo.touch(self.time_stamp);
+                (lo_cache_idx as usize, oldest)
+            }
+            _ => {
+                panic!();
+            }
+        };
+
+        let lo = &self.line_cache[lo_idx];
+        let hi = &self.line_cache[hi_idx];
+
+        // Span lo and hi may equal line end when last line doesn't
+        // end in newline, hence the inclusive upper bounds below.
+        debug_assert!(span_data.lo >= lo.line.start);
+        debug_assert!(span_data.lo <= lo.line.end);
+        debug_assert!(span_data.hi >= hi.line.start);
+        debug_assert!(span_data.hi <= hi.line.end);
+        debug_assert!(lo.file.contains(span_data.lo));
+        debug_assert!(lo.file.contains(span_data.hi));
+        debug_assert_eq!(lo.file_index, hi.file_index);
+
+        Some((
+            lo.file.clone(),
+            lo.line_number,
+            span_data.lo - lo.line.start,
+            hi.line_number,
+            span_data.hi - hi.line.start,
+        ))
+    }
+
+    fn cache_entry_index(&self, pos: BytePos) -> isize {
+        for (idx, cache_entry) in self.line_cache.iter().enumerate() {
+            if cache_entry.line.contains(&pos) {
+                return idx as isize;
+            }
+        }
+
+        -1
+    }
+
+    fn oldest_cache_entry_index(&self) -> usize {
+        let mut oldest = 0;
+
+        for idx in 1..self.line_cache.len() {
+            if self.line_cache[idx].time_stamp < self.line_cache[oldest].time_stamp {
+                oldest = idx;
+            }
         }
 
-        let line_index = cache_entry.file.lookup_line(pos).unwrap();
-        let line_bounds = cache_entry.file.line_bounds(line_index);
+        oldest
+    }
 
-        cache_entry.line_number = line_index + 1;
-        cache_entry.line = line_bounds;
-        cache_entry.time_stamp = self.time_stamp;
+    fn oldest_cache_entry_index_avoid(&self, avoid_idx: usize) -> usize {
+        let mut oldest = if avoid_idx != 0 { 0 } else { 1 };
 
-        Some((cache_entry.file.clone(), cache_entry.line_number, pos - cache_entry.line.start))
+        for idx in 0..self.line_cache.len() {
+            if idx != avoid_idx
+                && self.line_cache[idx].time_stamp < self.line_cache[oldest].time_stamp
+            {
+                oldest = idx;
+            }
+        }
+
+        oldest
+    }
+
+    fn file_for_position(&self, pos: BytePos) -> Option<(Lrc<SourceFile>, usize)> {
+        if !self.source_map.files().is_empty() {
+            let file_idx = self.source_map.lookup_source_file_idx(pos);
+            let file = &self.source_map.files()[file_idx];
+
+            if file_contains(file, pos) {
+                return Some((file.clone(), file_idx));
+            }
+        }
+
+        None
     }
 }
 
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index fdc0d225bb8..1fb5642912f 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -622,6 +622,10 @@ impl SyntaxContext {
     pub fn dollar_crate_name(self) -> Symbol {
         HygieneData::with(|data| data.syntax_context_data[self.0 as usize].dollar_crate_name)
     }
+
+    pub fn edition(self) -> Edition {
+        self.outer_expn_data().edition
+    }
 }
 
 impl fmt::Debug for SyntaxContext {
@@ -650,6 +654,20 @@ impl Span {
             self.with_ctxt(data.apply_mark(SyntaxContext::root(), expn_id, transparency))
         })
     }
+
+    /// Reuses the span but adds information like the kind of the desugaring and features that are
+    /// allowed inside this span.
+    pub fn mark_with_reason(
+        self,
+        allow_internal_unstable: Option<Lrc<[Symbol]>>,
+        reason: DesugaringKind,
+        edition: Edition,
+    ) -> Span {
+        self.fresh_expansion(ExpnData {
+            allow_internal_unstable,
+            ..ExpnData::default(ExpnKind::Desugaring(reason), self, edition, None)
+        })
+    }
 }
 
 /// A subset of properties from both macro definition and macro call available through global data.
@@ -699,7 +717,7 @@ pub struct ExpnData {
     /// created locally - when our serialized metadata is decoded,
     /// foreign `ExpnId`s will have their `ExpnData` looked up
     /// from the crate specified by `Crate
-    pub krate: CrateNum,
+    krate: CrateNum,
     /// The raw that this `ExpnData` had in its original crate.
     /// An `ExpnData` can be created before being assigned an `ExpnId`,
     /// so this might be `None` until `set_expn_data` is called
@@ -707,13 +725,39 @@ pub struct ExpnData {
     // two `ExpnData`s that differ only in their `orig_id` should
     // be considered equivalent.
     #[stable_hasher(ignore)]
-    pub orig_id: Option<u32>,
+    orig_id: Option<u32>,
 }
 
 // This would require special handling of `orig_id` and `parent`
 impl !PartialEq for ExpnData {}
 
 impl ExpnData {
+    pub fn new(
+        kind: ExpnKind,
+        parent: ExpnId,
+        call_site: Span,
+        def_site: Span,
+        allow_internal_unstable: Option<Lrc<[Symbol]>>,
+        allow_internal_unsafe: bool,
+        local_inner_macros: bool,
+        edition: Edition,
+        macro_def_id: Option<DefId>,
+    ) -> ExpnData {
+        ExpnData {
+            kind,
+            parent,
+            call_site,
+            def_site,
+            allow_internal_unstable,
+            allow_internal_unsafe,
+            local_inner_macros,
+            edition,
+            macro_def_id,
+            krate: LOCAL_CRATE,
+            orig_id: None,
+        }
+    }
+
     /// Constructs expansion data with default properties.
     pub fn default(
         kind: ExpnKind,
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 99f01062545..f0f9f940446 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -301,6 +301,10 @@ pub struct SpanData {
 
 impl SpanData {
     #[inline]
+    pub fn span(&self) -> Span {
+        Span::new(self.lo, self.hi, self.ctxt)
+    }
+    #[inline]
     pub fn with_lo(&self, lo: BytePos) -> Span {
         Span::new(lo, self.hi, self.ctxt)
     }
@@ -468,7 +472,7 @@ impl Span {
 
     /// Edition of the crate from which this span came.
     pub fn edition(self) -> edition::Edition {
-        self.ctxt().outer_expn_data().edition
+        self.ctxt().edition()
     }
 
     #[inline]
@@ -1867,6 +1871,10 @@ pub trait HashStableContext {
         &mut self,
         byte: BytePos,
     ) -> Option<(Lrc<SourceFile>, usize, BytePos)>;
+    fn span_data_to_lines_and_cols(
+        &mut self,
+        span: &SpanData,
+    ) -> Option<(Lrc<SourceFile>, usize, BytePos, usize, BytePos)>;
 }
 
 impl<CTX> HashStable<CTX> for Span
@@ -1900,22 +1908,8 @@ where
         // position that belongs to it, as opposed to hashing the first
         // position past it.
         let span = self.data();
-        let (file_lo, line_lo, col_lo) = match ctx.byte_pos_to_line_and_col(span.lo) {
-            Some(pos) => pos,
-            None => {
-                Hash::hash(&TAG_INVALID_SPAN, hasher);
-                span.ctxt.hash_stable(ctx, hasher);
-                return;
-            }
-        };
-
-        if !file_lo.contains(span.hi) {
-            Hash::hash(&TAG_INVALID_SPAN, hasher);
-            span.ctxt.hash_stable(ctx, hasher);
-            return;
-        }
-
-        let (_, line_hi, col_hi) = match ctx.byte_pos_to_line_and_col(span.hi) {
+        let (file, line_lo, col_lo, line_hi, col_hi) = match ctx.span_data_to_lines_and_cols(&span)
+        {
             Some(pos) => pos,
             None => {
                 Hash::hash(&TAG_INVALID_SPAN, hasher);
@@ -1927,7 +1921,7 @@ where
         Hash::hash(&TAG_VALID_SPAN, hasher);
         // We truncate the stable ID hash and line and column numbers. The chances
         // of causing a collision this way should be minimal.
-        Hash::hash(&(file_lo.name_hash as u64), hasher);
+        Hash::hash(&(file.name_hash as u64), hasher);
 
         // Hash both the length and the end location (line/column) of a span. If we
         // hash only the length, for example, then two otherwise equal spans with
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index fefc0cb48dd..6635d44496c 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -671,7 +671,9 @@ impl SourceMap {
             let pat = pat.to_owned() + ws;
             if let Ok(prev_source) = self.span_to_prev_source(sp) {
                 let prev_source = prev_source.rsplit(&pat).next().unwrap_or("").trim_start();
-                if !prev_source.is_empty() && (!prev_source.contains('\n') || accept_newlines) {
+                if prev_source.is_empty() && sp.lo().0 != 0 {
+                    return sp.with_lo(BytePos(sp.lo().0 - 1));
+                } else if !prev_source.contains('\n') || accept_newlines {
                     return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32));
                 }
             }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 64b50a9b70a..b6cf584d875 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -381,6 +381,7 @@ symbols! {
         const_ptr,
         const_raw_ptr_deref,
         const_raw_ptr_to_usize_cast,
+        const_refs_to_cell,
         const_slice_ptr,
         const_trait_bound_opt_out,
         const_trait_impl,
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 6356a7e7832..b0d5f340902 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -56,7 +56,15 @@ pub(super) fn mangle(
     let hash = get_symbol_hash(tcx, instance, instance_ty, instantiating_crate);
 
     let mut printer = SymbolPrinter { tcx, path: SymbolPath::new(), keep_within_component: false }
-        .print_def_path(def_id, &[])
+        .print_def_path(
+            def_id,
+            if let ty::InstanceDef::DropGlue(_, _) = instance.def {
+                // Add the name of the dropped type to the symbol name
+                &*instance.substs
+            } else {
+                &[]
+            },
+        )
         .unwrap();
 
     if let ty::InstanceDef::VtableShim(..) = instance.def {
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 5de9a8dfa7a..a9e595d11e7 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -605,10 +605,11 @@ impl<'a, Ty> FnAbi<'a, Ty> {
             "nvptx64" => nvptx64::compute_abi_info(self),
             "hexagon" => hexagon::compute_abi_info(self),
             "riscv32" | "riscv64" => riscv::compute_abi_info(cx, self),
-            "wasm32" if cx.target_spec().os != "emscripten" => {
-                wasm32_bindgen_compat::compute_abi_info(self)
-            }
-            "wasm32" | "asmjs" => wasm32::compute_abi_info(cx, self),
+            "wasm32" => match cx.target_spec().os.as_str() {
+                "emscripten" | "wasi" => wasm32::compute_abi_info(cx, self),
+                _ => wasm32_bindgen_compat::compute_abi_info(self),
+            },
+            "asmjs" => wasm32::compute_abi_info(cx, self),
             a => return Err(format!("unrecognized arch \"{}\" in target specification", a)),
         }
 
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index a43080b09e9..93868bed9b9 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -4,11 +4,14 @@ pub use Primitive::*;
 use crate::spec::Target;
 
 use std::convert::{TryFrom, TryInto};
+use std::fmt;
 use std::num::NonZeroUsize;
 use std::ops::{Add, AddAssign, Deref, Mul, Range, RangeInclusive, Sub};
+use std::str::FromStr;
 
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable_Generic;
+use rustc_serialize::json::{Json, ToJson};
 use rustc_span::Span;
 
 pub mod call;
@@ -152,22 +155,19 @@ impl TargetDataLayout {
         }
 
         // Perform consistency checks against the Target information.
-        let endian_str = match dl.endian {
-            Endian::Little => "little",
-            Endian::Big => "big",
-        };
-        if endian_str != target.endian {
+        if dl.endian != target.endian {
             return Err(format!(
                 "inconsistent target specification: \"data-layout\" claims \
-                                architecture is {}-endian, while \"target-endian\" is `{}`",
-                endian_str, target.endian
+                 architecture is {}-endian, while \"target-endian\" is `{}`",
+                dl.endian.as_str(),
+                target.endian.as_str(),
             ));
         }
 
         if dl.pointer_size.bits() != target.pointer_width.into() {
             return Err(format!(
                 "inconsistent target specification: \"data-layout\" claims \
-                                pointers are {}-bit, while \"target-pointer-width\" is `{}`",
+                 pointers are {}-bit, while \"target-pointer-width\" is `{}`",
                 dl.pointer_size.bits(),
                 target.pointer_width
             ));
@@ -234,26 +234,75 @@ pub enum Endian {
     Big,
 }
 
+impl Endian {
+    pub fn as_str(&self) -> &'static str {
+        match self {
+            Self::Little => "little",
+            Self::Big => "big",
+        }
+    }
+}
+
+impl fmt::Debug for Endian {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str(self.as_str())
+    }
+}
+
+impl FromStr for Endian {
+    type Err = String;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "little" => Ok(Self::Little),
+            "big" => Ok(Self::Big),
+            _ => Err(format!(r#"unknown endian: "{}""#, s)),
+        }
+    }
+}
+
+impl ToJson for Endian {
+    fn to_json(&self) -> Json {
+        self.as_str().to_json()
+    }
+}
+
 /// Size of a type in bytes.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)]
 #[derive(HashStable_Generic)]
 pub struct Size {
+    // The top 3 bits are ALWAYS zero.
     raw: u64,
 }
 
 impl Size {
     pub const ZERO: Size = Size { raw: 0 };
 
-    #[inline]
+    /// Rounds `bits` up to the next-higher byte boundary, if `bits` is
+    /// is not aligned.
     pub fn from_bits(bits: impl TryInto<u64>) -> Size {
         let bits = bits.try_into().ok().unwrap();
+
+        #[cold]
+        fn overflow(bits: u64) -> ! {
+            panic!("Size::from_bits({}) has overflowed", bits);
+        }
+
+        // This is the largest value of `bits` that does not cause overflow
+        // during rounding, and guarantees that the resulting number of bytes
+        // cannot cause overflow when multiplied by 8.
+        if bits > 0xffff_ffff_ffff_fff8 {
+            overflow(bits);
+        }
+
         // Avoid potential overflow from `bits + 7`.
-        Size::from_bytes(bits / 8 + ((bits % 8) + 7) / 8)
+        Size { raw: bits / 8 + ((bits % 8) + 7) / 8 }
     }
 
     #[inline]
     pub fn from_bytes(bytes: impl TryInto<u64>) -> Size {
-        Size { raw: bytes.try_into().ok().unwrap() }
+        let bytes: u64 = bytes.try_into().ok().unwrap();
+        Size { raw: bytes }
     }
 
     #[inline]
@@ -268,9 +317,7 @@ impl Size {
 
     #[inline]
     pub fn bits(self) -> u64 {
-        self.bytes().checked_mul(8).unwrap_or_else(|| {
-            panic!("Size::bits: {} bytes in bits doesn't fit in u64", self.bytes())
-        })
+        self.raw << 3
     }
 
     #[inline]
diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
index c6586b79b87..255740cb9c0 100644
--- a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
@@ -1,5 +1,6 @@
 // Targets the Big endian Cortex-R4/R5 processor (ARMv7-R)
 
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
 use crate::spec::{Target, TargetOptions};
 
@@ -11,7 +12,7 @@ pub fn target() -> Target {
         arch: "arm".to_string(),
 
         options: TargetOptions {
-            endian: "big".to_string(),
+            endian: Endian::Big,
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
             executables: true,
             linker: Some("rust-lld".to_owned()),
diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
index e3d4397f612..eb82e4d17b0 100644
--- a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
@@ -1,5 +1,6 @@
 // Targets the Cortex-R4F/R5F processor (ARMv7-R)
 
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
 use crate::spec::{Target, TargetOptions};
 
@@ -11,7 +12,7 @@ pub fn target() -> Target {
         arch: "arm".to_string(),
 
         options: TargetOptions {
-            endian: "big".to_string(),
+            endian: Endian::Big,
             linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
             executables: true,
             linker: Some("rust-lld".to_owned()),
diff --git a/compiler/rustc_target/src/spec/crt_objects.rs b/compiler/rustc_target/src/spec/crt_objects.rs
index 76c0bf419e8..32da16a2d8c 100644
--- a/compiler/rustc_target/src/spec/crt_objects.rs
+++ b/compiler/rustc_target/src/spec/crt_objects.rs
@@ -5,15 +5,16 @@
 //! The `crtx` ones are generally distributed with libc and the `begin/end` ones with gcc.
 //! See <https://dev.gentoo.org/~vapier/crt.txt> for some more details.
 //!
-//! | Pre-link CRT objects | glibc                  | musl                   | bionic           | mingw             | wasi |
-//! |----------------------|------------------------|------------------------|------------------|-------------------|------|
-//! | dynamic-nopic-exe    | crt1, crti, crtbegin   | crt1, crti, crtbegin   | crtbegin_dynamic | crt2, crtbegin    | crt1 |
-//! | dynamic-pic-exe      | Scrt1, crti, crtbeginS | Scrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin    | crt1 |
-//! | static-nopic-exe     | crt1, crti, crtbeginT  | crt1, crti, crtbegin   | crtbegin_static  | crt2, crtbegin    | crt1 |
-//! | static-pic-exe       | rcrt1, crti, crtbeginS | rcrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin    | crt1 |
-//! | dynamic-dylib        | crti, crtbeginS        | crti, crtbeginS        | crtbegin_so      | dllcrt2, crtbegin | -    |
-//! | static-dylib (gcc)   | crti, crtbeginT        | crti, crtbeginS        | crtbegin_so      | dllcrt2, crtbegin | -    |
-//! | static-dylib (clang) | crti, crtbeginT        | N/A                    | crtbegin_static  | dllcrt2, crtbegin | -    |
+//! | Pre-link CRT objects | glibc                  | musl                   | bionic           | mingw             | wasi         |
+//! |----------------------|------------------------|------------------------|------------------|-------------------|--------------|
+//! | dynamic-nopic-exe    | crt1, crti, crtbegin   | crt1, crti, crtbegin   | crtbegin_dynamic | crt2, crtbegin    | crt1         |
+//! | dynamic-pic-exe      | Scrt1, crti, crtbeginS | Scrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin    | crt1         |
+//! | static-nopic-exe     | crt1, crti, crtbeginT  | crt1, crti, crtbegin   | crtbegin_static  | crt2, crtbegin    | crt1         |
+//! | static-pic-exe       | rcrt1, crti, crtbeginS | rcrt1, crti, crtbeginS | crtbegin_dynamic | crt2, crtbegin    | crt1         |
+//! | dynamic-dylib        | crti, crtbeginS        | crti, crtbeginS        | crtbegin_so      | dllcrt2, crtbegin | -            |
+//! | static-dylib (gcc)   | crti, crtbeginT        | crti, crtbeginS        | crtbegin_so      | dllcrt2, crtbegin | -            |
+//! | static-dylib (clang) | crti, crtbeginT        | N/A                    | crtbegin_static  | dllcrt2, crtbegin | -            |
+//! | wasi-reactor-exe     | N/A                    | N/A                    | N/A              | N/A               | crt1-reactor |
 //!
 //! | Post-link CRT objects | glibc         | musl          | bionic         | mingw  | wasi |
 //! |-----------------------|---------------|---------------|----------------|--------|------|
@@ -105,6 +106,7 @@ pub(super) fn pre_wasi_fallback() -> CrtObjects {
         (LinkOutputKind::DynamicPicExe, &["crt1.o"]),
         (LinkOutputKind::StaticNoPicExe, &["crt1.o"]),
         (LinkOutputKind::StaticPicExe, &["crt1.o"]),
+        (LinkOutputKind::WasiReactorExe, &["crt1-reactor.o"]),
     ])
 }
 
diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs
index daa0d9da172..53398539ac2 100644
--- a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -7,7 +8,7 @@ pub fn target() -> Target {
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
         arch: "mips64".to_string(),
         options: TargetOptions {
-            endian: "big".to_string(),
+            endian: Endian::Big,
             // NOTE(mips64r2) matches C toolchain
             cpu: "mips64r2".to_string(),
             features: "+mips64r2".to_string(),
diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs
index db8d0c04e6f..329fbd22721 100644
--- a/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs
+++ b/compiler/rustc_target/src/spec/mips64_unknown_linux_muslabi64.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -11,6 +12,6 @@ pub fn target() -> Target {
         pointer_width: 64,
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
         arch: "mips64".to_string(),
-        options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base },
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs
index a7ec1f19c9d..b41b28cbc87 100644
--- a/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/mips_unknown_linux_gnu.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -7,7 +8,7 @@ pub fn target() -> Target {
         data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
         arch: "mips".to_string(),
         options: TargetOptions {
-            endian: "big".to_string(),
+            endian: Endian::Big,
             cpu: "mips32r2".to_string(),
             features: "+mips32r2,+fpxx,+nooddspreg".to_string(),
             max_atomic_width: Some(32),
diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs
index 1ebe577bc1c..3713af43d73 100644
--- a/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/mips_unknown_linux_musl.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -11,6 +12,6 @@ pub fn target() -> Target {
         pointer_width: 32,
         data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
         arch: "mips".to_string(),
-        options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base },
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs
index 2123d5e1a0f..042ec9140fa 100644
--- a/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs
+++ b/compiler/rustc_target/src/spec/mips_unknown_linux_uclibc.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -7,7 +8,7 @@ pub fn target() -> Target {
         data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
         arch: "mips".to_string(),
         options: TargetOptions {
-            endian: "big".to_string(),
+            endian: Endian::Big,
             cpu: "mips32r2".to_string(),
             features: "+mips32r2,+soft-float".to_string(),
             max_atomic_width: Some(32),
diff --git a/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs
index 11b3734a105..a81c90fe0cd 100644
--- a/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/mipsisa32r6_unknown_linux_gnu.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -7,7 +8,7 @@ pub fn target() -> Target {
         data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
         arch: "mips".to_string(),
         options: TargetOptions {
-            endian: "big".to_string(),
+            endian: Endian::Big,
             cpu: "mips32r6".to_string(),
             features: "+mips32r6".to_string(),
             max_atomic_width: Some(32),
diff --git a/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs
index 6282c9e1d54..3bf837fbb41 100644
--- a/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/mipsisa64r6_unknown_linux_gnuabi64.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -7,7 +8,7 @@ pub fn target() -> Target {
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
         arch: "mips64".to_string(),
         options: TargetOptions {
-            endian: "big".to_string(),
+            endian: Endian::Big,
             // NOTE(mips64r6) matches C toolchain
             cpu: "mips64r6".to_string(),
             features: "+mips64r6".to_string(),
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 8d72df6850f..d283c254886 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -34,6 +34,7 @@
 //! the target's settings, though `target-feature` and `link-args` will *add*
 //! to the list specified by the target, rather than replace.
 
+use crate::abi::Endian;
 use crate::spec::abi::{lookup as lookup_abi, Abi};
 use crate::spec::crt_objects::{CrtObjects, CrtObjectsFallback};
 use rustc_serialize::json::{Json, ToJson};
@@ -407,6 +408,8 @@ pub enum LinkOutputKind {
     DynamicDylib,
     /// Dynamic library with bundled libc ("statically linked").
     StaticDylib,
+    /// WASI module with a lifetime past the _initialize entry point
+    WasiReactorExe,
 }
 
 impl LinkOutputKind {
@@ -418,6 +421,7 @@ impl LinkOutputKind {
             LinkOutputKind::StaticPicExe => "static-pic-exe",
             LinkOutputKind::DynamicDylib => "dynamic-dylib",
             LinkOutputKind::StaticDylib => "static-dylib",
+            LinkOutputKind::WasiReactorExe => "wasi-reactor-exe",
         }
     }
 
@@ -429,6 +433,7 @@ impl LinkOutputKind {
             "static-pic-exe" => LinkOutputKind::StaticPicExe,
             "dynamic-dylib" => LinkOutputKind::DynamicDylib,
             "static-dylib" => LinkOutputKind::StaticDylib,
+            "wasi-reactor-exe" => LinkOutputKind::WasiReactorExe,
             _ => return None,
         })
     }
@@ -705,8 +710,8 @@ pub struct TargetOptions {
     /// Whether the target is built-in or loaded from a custom target specification.
     pub is_builtin: bool,
 
-    /// String to use as the `target_endian` `cfg` variable. Defaults to "little".
-    pub endian: String,
+    /// Used as the `target_endian` `cfg` variable. Defaults to little endian.
+    pub endian: Endian,
     /// Width of c_int type. Defaults to "32".
     pub c_int_width: String,
     /// OS name to use for conditional compilation (`target_os`). Defaults to "none".
@@ -1010,7 +1015,7 @@ impl Default for TargetOptions {
     fn default() -> TargetOptions {
         TargetOptions {
             is_builtin: false,
-            endian: "little".to_string(),
+            endian: Endian::Little,
             c_int_width: "32".to_string(),
             os: "none".to_string(),
             env: String::new(),
@@ -1377,7 +1382,7 @@ impl Target {
                         let kind = LinkOutputKind::from_str(&k).ok_or_else(|| {
                             format!("{}: '{}' is not a valid value for CRT object kind. \
                                      Use '(dynamic,static)-(nopic,pic)-exe' or \
-                                     '(dynamic,static)-dylib'", name, k)
+                                     '(dynamic,static)-dylib' or 'wasi-reactor-exe'", name, k)
                         })?;
 
                         let v = v.as_array().ok_or_else(||
@@ -1439,8 +1444,10 @@ impl Target {
             } );
         }
 
+        if let Some(s) = obj.find("target-endian").and_then(Json::as_string) {
+            base.endian = s.parse()?;
+        }
         key!(is_builtin, bool);
-        key!(endian = "target-endian");
         key!(c_int_width = "target-c-int-width");
         key!(os);
         key!(env);
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs
index 626865aa242..3dddeb1129c 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -11,6 +12,6 @@ pub fn target() -> Target {
         pointer_width: 64,
         data_layout: "E-m:e-i64:64-n32:64".to_string(),
         arch: "powerpc64".to_string(),
-        options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base },
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
index 03322818d33..751022c124b 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, RelroLevel, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -15,6 +16,6 @@ pub fn target() -> Target {
         pointer_width: 64,
         data_layout: "E-m:e-i64:64-n32:64".to_string(),
         arch: "powerpc64".to_string(),
-        options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base },
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
index 231539756f3..546dfbab6c7 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -11,6 +12,6 @@ pub fn target() -> Target {
         pointer_width: 64,
         data_layout: "E-m:e-i64:64-n32:64".to_string(),
         arch: "powerpc64".to_string(),
-        options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base },
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
index 1c83e3e64d4..bb55872109c 100644
--- a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -11,6 +12,6 @@ pub fn target() -> Target {
         pointer_width: 64,
         data_layout: "E-m:e-i64:64-n32:64".to_string(),
         arch: "powerpc64".to_string(),
-        options: TargetOptions { endian: "big".to_string(), ..base },
+        options: TargetOptions { endian: Endian::Big, ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs
index 3a9271247b0..70dd0b2aee6 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -10,6 +11,6 @@ pub fn target() -> Target {
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
         arch: "powerpc".to_string(),
-        options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base },
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
index 105a0b21aaf..66118b74955 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -10,6 +11,6 @@ pub fn target() -> Target {
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
         arch: "powerpc".to_string(),
-        options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base },
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs
index 49d32944789..679a3a2f6aa 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -10,6 +11,6 @@ pub fn target() -> Target {
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
         arch: "powerpc".to_string(),
-        options: TargetOptions { endian: "big".to_string(), mcount: "_mcount".to_string(), ..base },
+        options: TargetOptions { endian: Endian::Big, mcount: "_mcount".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs
index 387d6cdc456..1245098329a 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -10,10 +11,6 @@ pub fn target() -> Target {
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
         arch: "powerpc".to_string(),
-        options: TargetOptions {
-            endian: "big".to_string(),
-            mcount: "__mcount".to_string(),
-            ..base
-        },
+        options: TargetOptions { endian: Endian::Big, mcount: "__mcount".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs
index 20ffa07b997..bb943a8825c 100644
--- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -11,10 +12,6 @@ pub fn target() -> Target {
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
         arch: "powerpc".to_string(),
-        options: TargetOptions {
-            endian: "big".to_string(),
-            features: "+secure-plt".to_string(),
-            ..base
-        },
+        options: TargetOptions { endian: Endian::Big, features: "+secure-plt".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs
index 0e713fccd23..4b4f118ba49 100644
--- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs
+++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -12,7 +13,7 @@ pub fn target() -> Target {
         data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
         arch: "powerpc".to_string(),
         options: TargetOptions {
-            endian: "big".to_string(),
+            endian: Endian::Big,
             // feature msync would disable instruction 'fsync' which is not supported by fsl_p1p2
             features: "+secure-plt,+msync".to_string(),
             ..base
diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
index d6e8e6ee220..4eeea9bedfb 100644
--- a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
@@ -1,8 +1,9 @@
+use crate::abi::Endian;
 use crate::spec::Target;
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
-    base.endian = "big".to_string();
+    base.endian = Endian::Big;
     // z10 is the oldest CPU supported by LLVM
     base.cpu = "z10".to_string();
     // FIXME: The data_layout string below and the ABI implementation in
diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs
index e9b5520ac3d..e1aa48872b9 100644
--- a/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/sparc64_unknown_linux_gnu.rs
@@ -1,8 +1,9 @@
+use crate::abi::Endian;
 use crate::spec::Target;
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
-    base.endian = "big".to_string();
+    base.endian = Endian::Big;
     base.cpu = "v9".to_string();
     base.max_atomic_width = Some(64);
 
diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs
index c8e90f832d0..7d685c83100 100644
--- a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs
@@ -1,3 +1,4 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -11,10 +12,6 @@ pub fn target() -> Target {
         pointer_width: 64,
         data_layout: "E-m:e-i64:64-n32:64-S128".to_string(),
         arch: "sparc64".to_string(),
-        options: TargetOptions {
-            endian: "big".to_string(),
-            mcount: "__mcount".to_string(),
-            ..base
-        },
+        options: TargetOptions { endian: Endian::Big, mcount: "__mcount".to_string(), ..base },
     }
 }
diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs
index 630ce6123f9..63b13fad4f7 100644
--- a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs
@@ -1,8 +1,9 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target};
 
 pub fn target() -> Target {
     let mut base = super::openbsd_base::opts();
-    base.endian = "big".to_string();
+    base.endian = Endian::Big;
     base.cpu = "v9".to_string();
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
     base.max_atomic_width = Some(64);
diff --git a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs
index aae186b2293..9e8fbff81c5 100644
--- a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs
@@ -1,8 +1,9 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target};
 
 pub fn target() -> Target {
     let mut base = super::linux_gnu_base::opts();
-    base.endian = "big".to_string();
+    base.endian = Endian::Big;
     base.cpu = "v9".to_string();
     base.max_atomic_width = Some(64);
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mv8plus".to_string());
diff --git a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs b/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs
index 5f99e0b14f9..9ac56cae916 100644
--- a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs
+++ b/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs
@@ -1,8 +1,9 @@
+use crate::abi::Endian;
 use crate::spec::{LinkerFlavor, Target};
 
 pub fn target() -> Target {
     let mut base = super::solaris_base::opts();
-    base.endian = "big".to_string();
+    base.endian = Endian::Big;
     base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m64".to_string()]);
     // llvm calls this "v9"
     base.cpu = "v9".to_string();
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index fc6a9a7f209..d677103df1f 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -305,8 +305,8 @@ impl AutoTraitFinder<'tcx> {
                 infcx.resolve_vars_if_possible(Obligation::new(dummy_cause.clone(), new_env, pred));
             let result = select.select(&obligation);
 
-            match &result {
-                &Ok(Some(ref impl_source)) => {
+            match result {
+                Ok(Some(ref impl_source)) => {
                     // If we see an explicit negative impl (e.g., `impl !Send for MyStruct`),
                     // we immediately bail out, since it's impossible for us to continue.
 
@@ -339,8 +339,8 @@ impl AutoTraitFinder<'tcx> {
                         return None;
                     }
                 }
-                &Ok(None) => {}
-                &Err(SelectionError::Unimplemented) => {
+                Ok(None) => {}
+                Err(SelectionError::Unimplemented) => {
                     if self.is_param_no_infer(pred.skip_binder().trait_ref.substs) {
                         already_visited.remove(&pred);
                         self.add_user_pred(
@@ -863,7 +863,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, 'tcx> {
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         (match r {
-            &ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(),
+            ty::ReVar(vid) => self.vid_to_region.get(vid).cloned(),
             _ => None,
         })
         .unwrap_or_else(|| r.super_fold_with(self))
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 1d82e732907..a439bb892f8 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1368,7 +1368,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
         code: &ObligationCauseCode<'tcx>,
     ) -> Option<(String, Option<Span>)> {
         match code {
-            &ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
+            ObligationCauseCode::BuiltinDerivedObligation(data) => {
                 let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_ref);
                 match self.get_parent_trait_ref(&data.parent_code) {
                     Some(t) => Some(t),
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index a8f81445b03..8ca540fc893 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -69,16 +69,16 @@ impl IntercrateAmbiguityCause {
 
     pub fn intercrate_ambiguity_hint(&self) -> String {
         match self {
-            &IntercrateAmbiguityCause::DownstreamCrate { ref trait_desc, ref self_desc } => {
-                let self_desc = if let &Some(ref ty) = self_desc {
+            IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc } => {
+                let self_desc = if let Some(ty) = self_desc {
                     format!(" for type `{}`", ty)
                 } else {
                     String::new()
                 };
                 format!("downstream crates may implement trait `{}`{}", trait_desc, self_desc)
             }
-            &IntercrateAmbiguityCause::UpstreamCrateUpdate { ref trait_desc, ref self_desc } => {
-                let self_desc = if let &Some(ref ty) = self_desc {
+            IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_desc, self_desc } => {
+                let self_desc = if let Some(ty) = self_desc {
                     format!(" for type `{}`", ty)
                 } else {
                     String::new()
@@ -89,7 +89,7 @@ impl IntercrateAmbiguityCause {
                     trait_desc, self_desc
                 )
             }
-            &IntercrateAmbiguityCause::ReservationImpl { ref message } => message.clone(),
+            IntercrateAmbiguityCause::ReservationImpl { message } => message.clone(),
         }
     }
 }
diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs
index a3a2b8967c6..1100401ed12 100644
--- a/compiler/rustc_typeck/src/astconv/generics.rs
+++ b/compiler/rustc_typeck/src/astconv/generics.rs
@@ -11,7 +11,7 @@ use rustc_hir::GenericArg;
 use rustc_middle::ty::{
     self, subst, subst::SubstsRef, GenericParamDef, GenericParamDefKind, Ty, TyCtxt,
 };
-use rustc_session::{lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS, Session};
+use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS;
 use rustc_span::{symbol::kw, MultiSpan, Span};
 
 use smallvec::SmallVec;
@@ -20,62 +20,72 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     /// Report an error that a generic argument did not match the generic parameter that was
     /// expected.
     fn generic_arg_mismatch_err(
-        sess: &Session,
+        tcx: TyCtxt<'_>,
         arg: &GenericArg<'_>,
-        kind: &'static str,
+        param: &GenericParamDef,
         possible_ordering_error: bool,
         help: Option<&str>,
     ) {
+        let sess = tcx.sess;
         let mut err = struct_span_err!(
             sess,
             arg.span(),
             E0747,
             "{} provided when a {} was expected",
             arg.descr(),
-            kind,
+            param.kind.descr(),
         );
 
-        let unordered = sess.features_untracked().const_generics;
-        let kind_ord = match kind {
-            "lifetime" => ParamKindOrd::Lifetime,
-            "type" => ParamKindOrd::Type,
-            "constant" => ParamKindOrd::Const { unordered },
-            // It's more concise to match on the string representation, though it means
-            // the match is non-exhaustive.
-            _ => bug!("invalid generic parameter kind {}", kind),
-        };
-
-        if let ParamKindOrd::Const { .. } = kind_ord {
+        if let GenericParamDefKind::Const { .. } = param.kind {
             if let GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. }) = arg {
                 err.help("const arguments cannot yet be inferred with `_`");
             }
         }
 
-        let arg_ord = match arg {
-            GenericArg::Lifetime(_) => ParamKindOrd::Lifetime,
-            GenericArg::Type(_) => ParamKindOrd::Type,
-            GenericArg::Const(_) => ParamKindOrd::Const { unordered },
-        };
-
-        if matches!(arg, GenericArg::Type(hir::Ty { kind: hir::TyKind::Path { .. }, .. }))
-            && matches!(kind_ord, ParamKindOrd::Const { .. })
-        {
-            let suggestions = vec![
-                (arg.span().shrink_to_lo(), String::from("{ ")),
-                (arg.span().shrink_to_hi(), String::from(" }")),
-            ];
-            err.multipart_suggestion(
-                "if this generic argument was intended as a const parameter, \
+        // Specific suggestion set for diagnostics
+        match (arg, &param.kind) {
+            (
+                GenericArg::Type(hir::Ty { kind: hir::TyKind::Path { .. }, .. }),
+                GenericParamDefKind::Const { .. },
+            ) => {
+                let suggestions = vec![
+                    (arg.span().shrink_to_lo(), String::from("{ ")),
+                    (arg.span().shrink_to_hi(), String::from(" }")),
+                ];
+                err.multipart_suggestion(
+                    "if this generic argument was intended as a const parameter, \
                 try surrounding it with braces:",
-                suggestions,
-                Applicability::MaybeIncorrect,
-            );
+                    suggestions,
+                    Applicability::MaybeIncorrect,
+                );
+            }
+            (
+                GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
+                GenericParamDefKind::Const { .. },
+            ) if tcx.type_of(param.def_id) == tcx.types.usize => {
+                let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id));
+                if let Ok(snippet) = snippet {
+                    err.span_suggestion(
+                        arg.span(),
+                        "array type provided where a `usize` was expected, try",
+                        format!("{{ {} }}", snippet),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+            }
+            _ => {}
         }
 
+        let kind_ord = param.kind.to_ord(tcx);
+        let arg_ord = arg.to_ord(&tcx.features());
+
         // This note is only true when generic parameters are strictly ordered by their kind.
         if possible_ordering_error && kind_ord.cmp(&arg_ord) != core::cmp::Ordering::Equal {
-            let (first, last) =
-                if kind_ord < arg_ord { (kind, arg.descr()) } else { (arg.descr(), kind) };
+            let (first, last) = if kind_ord < arg_ord {
+                (param.kind.descr(), arg.descr())
+            } else {
+                (arg.descr(), param.kind.descr())
+            };
             err.note(&format!("{} arguments must be provided before {} arguments", first, last));
             if let Some(help) = help {
                 err.help(help);
@@ -203,7 +213,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                 // We expected a lifetime argument, but got a type or const
                                 // argument. That means we're inferring the lifetimes.
                                 substs.push(ctx.inferred_kind(None, param, infer_args));
-                                force_infer_lt = Some(arg);
+                                force_infer_lt = Some((arg, param));
                                 params.next();
                             }
                             (GenericArg::Lifetime(_), _, ExplicitLateBound::Yes) => {
@@ -213,7 +223,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                 // ignore it.
                                 args.next();
                             }
-                            (_, kind, _) => {
+                            (_, _, _) => {
                                 // We expected one kind of parameter, but the user provided
                                 // another. This is an error. However, if we already know that
                                 // the arguments don't match up with the parameters, we won't issue
@@ -256,9 +266,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                     param_types_present.dedup();
 
                                     Self::generic_arg_mismatch_err(
-                                        tcx.sess,
+                                        tcx,
                                         arg,
-                                        kind.descr(),
+                                        param,
                                         !args_iter.clone().is_sorted_by_key(|arg| match arg {
                                             GenericArg::Lifetime(_) => ParamKindOrd::Lifetime,
                                             GenericArg::Type(_) => ParamKindOrd::Type,
@@ -315,9 +325,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         {
                             let kind = arg.descr();
                             assert_eq!(kind, "lifetime");
-                            let provided =
+                            let (provided_arg, param) =
                                 force_infer_lt.expect("lifetimes ought to have been inferred");
-                            Self::generic_arg_mismatch_err(tcx.sess, provided, kind, false, None);
+                            Self::generic_arg_mismatch_err(tcx, provided_arg, param, false, None);
                         }
 
                         break;
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 9a2210e4f0e..878993d512c 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -770,7 +770,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         // Try to find an unbound in bounds.
         let mut unbound = None;
         for ab in ast_bounds {
-            if let &hir::GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = ab {
+            if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab {
                 if unbound.is_none() {
                     unbound = Some(&ptr.trait_ref);
                 } else {
diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs
index 22e287320d8..116b079e742 100644
--- a/compiler/rustc_typeck/src/check/callee.rs
+++ b/compiler/rustc_typeck/src/check/callee.rs
@@ -290,16 +290,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ty::FnPtr(sig) => (sig, None),
             ref t => {
                 let mut unit_variant = None;
-                if let &ty::Adt(adt_def, ..) = t {
+                if let ty::Adt(adt_def, ..) = t {
                     if adt_def.is_enum() {
-                        if let hir::ExprKind::Call(ref expr, _) = call_expr.kind {
+                        if let hir::ExprKind::Call(expr, _) = call_expr.kind {
                             unit_variant =
                                 self.tcx.sess.source_map().span_to_snippet(expr.span).ok();
                         }
                     }
                 }
 
-                if let hir::ExprKind::Call(ref callee, _) = call_expr.kind {
+                if let hir::ExprKind::Call(callee, _) = call_expr.kind {
                     let mut err = type_error_struct!(
                         self.tcx.sess,
                         callee.span,
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 9c60e8933d4..9bb4c9b3719 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -103,13 +103,17 @@ pub(super) fn check_fn<'a, 'tcx>(
                 Node::ImplItem(hir::ImplItem {
                     kind: hir::ImplItemKind::Fn(header, ..), ..
                 }) => Some(header),
+                Node::TraitItem(hir::TraitItem {
+                    kind: hir::TraitItemKind::Fn(header, ..),
+                    ..
+                }) => Some(header),
                 // Closures are RustCall, but they tuple their arguments, so shouldn't be checked
                 Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => None,
                 node => bug!("Item being checked wasn't a function/closure: {:?}", node),
             };
 
             if let Some(header) = item {
-                tcx.sess.span_err(header.span, "A function with the \"rust-call\" ABI must take a single non-self argument that is a tuple")
+                tcx.sess.span_err(header.span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple")
             }
         };
 
diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs
index 0f5f0ab0260..67ec739d861 100644
--- a/compiler/rustc_typeck/src/check/coercion.rs
+++ b/compiler/rustc_typeck/src/check/coercion.rs
@@ -926,11 +926,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     false
                 }
             };
-            if is_capturing_closure(&prev_ty.kind()) || is_capturing_closure(&new_ty.kind()) {
+            if is_capturing_closure(prev_ty.kind()) || is_capturing_closure(new_ty.kind()) {
                 (None, None)
             } else {
-                match (&prev_ty.kind(), &new_ty.kind()) {
-                    (&ty::FnDef(..), &ty::FnDef(..)) => {
+                match (prev_ty.kind(), new_ty.kind()) {
+                    (ty::FnDef(..), ty::FnDef(..)) => {
                         // Don't reify if the function types have a LUB, i.e., they
                         // are the same function and their parameters have a LUB.
                         match self
@@ -943,21 +943,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             }
                         }
                     }
-                    (&ty::Closure(_, substs), &ty::FnDef(..)) => {
+                    (ty::Closure(_, substs), ty::FnDef(..)) => {
                         let b_sig = new_ty.fn_sig(self.tcx);
                         let a_sig = self
                             .tcx
                             .signature_unclosure(substs.as_closure().sig(), b_sig.unsafety());
                         (Some(a_sig), Some(b_sig))
                     }
-                    (&ty::FnDef(..), &ty::Closure(_, substs)) => {
+                    (ty::FnDef(..), ty::Closure(_, substs)) => {
                         let a_sig = prev_ty.fn_sig(self.tcx);
                         let b_sig = self
                             .tcx
                             .signature_unclosure(substs.as_closure().sig(), a_sig.unsafety());
                         (Some(a_sig), Some(b_sig))
                     }
-                    (&ty::Closure(_, substs_a), &ty::Closure(_, substs_b)) => (
+                    (ty::Closure(_, substs_a), ty::Closure(_, substs_b)) => (
                         Some(self.tcx.signature_unclosure(
                             substs_a.as_closure().sig(),
                             hir::Unsafety::Normal,
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index 8197d02ec59..d76a80d5a39 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -1125,7 +1125,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             fields,
             base_expr.is_none(),
         );
-        if let &Some(ref base_expr) = base_expr {
+        if let Some(base_expr) = base_expr {
             // If check_expr_struct_fields hit an error, do not attempt to populate
             // the fields with the base_expr. This could cause us to hit errors later
             // when certain fields are assumed to exist that in fact do not.
@@ -1182,8 +1182,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // re-link the regions that EIfEO can erase.
         self.demand_eqtype(span, adt_ty_hint, adt_ty);
 
-        let (substs, adt_kind, kind_name) = match &adt_ty.kind() {
-            &ty::Adt(adt, substs) => (substs, adt.adt_kind(), adt.variant_descr()),
+        let (substs, adt_kind, kind_name) = match adt_ty.kind() {
+            ty::Adt(adt, substs) => (substs, adt.adt_kind(), adt.variant_descr()),
             _ => span_bug!(span, "non-ADT passed to check_expr_struct_fields"),
         };
 
@@ -1381,19 +1381,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ty,
         );
         match variant.ctor_kind {
-            CtorKind::Fn => {
-                err.span_label(variant.ident.span, format!("`{adt}` defined here", adt = ty));
-                err.span_label(field.ident.span, "field does not exist");
-                err.span_label(
-                    ty_span,
-                    format!(
-                        "`{adt}` is a tuple {kind_name}, \
-                         use the appropriate syntax: `{adt}(/* fields */)`",
-                        adt = ty,
-                        kind_name = kind_name
-                    ),
-                );
-            }
+            CtorKind::Fn => match ty.kind() {
+                ty::Adt(adt, ..) if adt.is_enum() => {
+                    err.span_label(
+                        variant.ident.span,
+                        format!(
+                            "`{adt}::{variant}` defined here",
+                            adt = ty,
+                            variant = variant.ident,
+                        ),
+                    );
+                    err.span_label(field.ident.span, "field does not exist");
+                    err.span_label(
+                        ty_span,
+                        format!(
+                            "`{adt}::{variant}` is a tuple {kind_name}, \
+                             use the appropriate syntax: `{adt}::{variant}(/* fields */)`",
+                            adt = ty,
+                            variant = variant.ident,
+                            kind_name = kind_name
+                        ),
+                    );
+                }
+                _ => {
+                    err.span_label(variant.ident.span, format!("`{adt}` defined here", adt = ty));
+                    err.span_label(field.ident.span, "field does not exist");
+                    err.span_label(
+                        ty_span,
+                        format!(
+                            "`{adt}` is a tuple {kind_name}, \
+                                 use the appropriate syntax: `{adt}(/* fields */)`",
+                            adt = ty,
+                            kind_name = kind_name
+                        ),
+                    );
+                }
+            },
             _ => {
                 // prevent all specified fields from being suggested
                 let skip_fields = skip_fields.iter().map(|ref x| x.ident.name);
diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs
index 673dec6c7f9..e4e6cf73c7e 100644
--- a/compiler/rustc_typeck/src/check/intrinsic.rs
+++ b/compiler/rustc_typeck/src/check/intrinsic.rs
@@ -63,8 +63,6 @@ pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
         | sym::min_align_of
         | sym::needs_drop
         | sym::caller_location
-        | sym::size_of_val
-        | sym::min_align_of_val
         | sym::add_with_overflow
         | sym::sub_with_overflow
         | sym::mul_with_overflow
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index 3bf41981ef6..5cfd78ebeac 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -333,7 +333,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             }
                             ExprKind::Path(ref qpath) => {
                                 // local binding
-                                if let &QPath::Resolved(_, ref path) = &qpath {
+                                if let QPath::Resolved(_, path) = qpath {
                                     if let hir::def::Res::Local(hir_id) = path.res {
                                         let span = tcx.hir().span(hir_id);
                                         let snippet = tcx.sess.source_map().span_to_snippet(span);
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index ab41ff372e2..d81d83f60bd 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -330,7 +330,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
                             ),
                         )
                         .note("the only supported types are integers, `bool` and `char`")
-                        .help("more complex types are supported with `#[feature(const_generics)]`")
+                        .help("more complex types are supported with `#![feature(const_generics)]`")
                         .emit()
                 }
             };
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 2ebb1a3be4e..ae97fa3f7e4 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -1920,7 +1920,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
     let where_clause = &ast_generics.where_clause;
     for predicate in where_clause.predicates {
         match predicate {
-            &hir::WherePredicate::BoundPredicate(ref bound_pred) => {
+            hir::WherePredicate::BoundPredicate(bound_pred) => {
                 let ty = icx.to_ty(&bound_pred.bounded_ty);
 
                 // Keep the type around in a dummy predicate, in case of no bounds.
@@ -1949,7 +1949,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
 
                 for bound in bound_pred.bounds.iter() {
                     match bound {
-                        &hir::GenericBound::Trait(ref poly_trait_ref, modifier) => {
+                        hir::GenericBound::Trait(poly_trait_ref, modifier) => {
                             let constness = match modifier {
                                 hir::TraitBoundModifier::MaybeConst => hir::Constness::NotConst,
                                 hir::TraitBoundModifier::None => constness,
@@ -1959,7 +1959,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                             let mut bounds = Bounds::default();
                             let _ = AstConv::instantiate_poly_trait_ref(
                                 &icx,
-                                poly_trait_ref,
+                                &poly_trait_ref,
                                 constness,
                                 ty,
                                 &mut bounds,
@@ -1981,7 +1981,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                             predicates.extend(bounds.predicates(tcx, ty));
                         }
 
-                        &hir::GenericBound::Outlives(ref lifetime) => {
+                        hir::GenericBound::Outlives(lifetime) => {
                             let region = AstConv::ast_region_to_region(&icx, lifetime, None);
                             predicates.insert((
                                 ty::Binder::bind(ty::PredicateAtom::TypeOutlives(
@@ -1995,7 +1995,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                 }
             }
 
-            &hir::WherePredicate::RegionPredicate(ref region_pred) => {
+            hir::WherePredicate::RegionPredicate(region_pred) => {
                 let r1 = AstConv::ast_region_to_region(&icx, &region_pred.lifetime, None);
                 predicates.extend(region_pred.bounds.iter().map(|bound| {
                     let (r2, span) = match bound {
@@ -2011,7 +2011,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
                 }))
             }
 
-            &hir::WherePredicate::EqPredicate(..) => {
+            hir::WherePredicate::EqPredicate(..) => {
                 // FIXME(#20041)
             }
         }
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index eff197d9988..d95b5b7f17f 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -8,7 +8,7 @@ edition = "2018"
 
 [dependencies]
 core = { path = "../core" }
-compiler_builtins = { version = "0.1.10", features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "0.1.39", features = ['rustc-dep-of-std'] }
 
 [dev-dependencies]
 rand = "0.7"
@@ -31,5 +31,5 @@ harness = false
 [features]
 compiler-builtins-mem = ['compiler_builtins/mem']
 compiler-builtins-c = ["compiler_builtins/c"]
-compiler-builtins-asm = ["compiler_builtins/asm"]
+compiler-builtins-no-asm = ["compiler_builtins/no-asm"]
 compiler-builtins-mangled-names = ["compiler_builtins/mangled-names"]
diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs
index f801c1ac75b..adf996fc782 100644
--- a/library/alloc/src/borrow.rs
+++ b/library/alloc/src/borrow.rs
@@ -103,6 +103,11 @@ where
 /// is desired, `to_mut` will obtain a mutable reference to an owned
 /// value, cloning if necessary.
 ///
+/// If you need reference-counting pointers, note that
+/// [`Rc::make_mut`][crate::rc::Rc::make_mut] and
+/// [`Arc::make_mut`][crate::sync::Arc::make_mut] can provide clone-on-write
+/// functionality as well.
+///
 /// # Examples
 ///
 /// ```
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 8eb2caa60b1..33b812ec59f 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -126,9 +126,7 @@
 //!
 //! [ucg#198]: https://github.com/rust-lang/unsafe-code-guidelines/issues/198
 //! [dereferencing]: core::ops::Deref
-//! [`Box<T>`]: Box
 //! [`Box::<T>::from_raw(value)`]: Box::from_raw
-//! [`Box::<T>::into_raw`]: Box::into_raw
 //! [`Global`]: crate::alloc::Global
 //! [`Layout`]: crate::alloc::Layout
 //! [`Layout::for_value(&*value)`]: crate::alloc::Layout::for_value
diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs
index b3641a7a0c6..bef6850f06f 100644
--- a/library/alloc/src/collections/btree/node.rs
+++ b/library/alloc/src/collections/btree/node.rs
@@ -1124,21 +1124,20 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>
     /// by taking care of leaf data.
     fn split_leaf_data(&mut self, new_node: &mut LeafNode<K, V>) -> (K, V) {
         debug_assert!(self.idx < self.node.len());
-        let new_len = self.node.len() - self.idx - 1;
+        let old_len = self.node.len();
+        let new_len = old_len - self.idx - 1;
         new_node.len = new_len as u16;
         unsafe {
             let k = self.node.key_area_mut(self.idx).assume_init_read();
             let v = self.node.val_area_mut(self.idx).assume_init_read();
 
-            ptr::copy_nonoverlapping(
-                self.node.key_area_mut(self.idx + 1..).as_ptr(),
-                new_node.keys.as_mut_ptr(),
-                new_len,
+            move_to_slice(
+                self.node.key_area_mut(self.idx + 1..old_len),
+                &mut new_node.keys[..new_len],
             );
-            ptr::copy_nonoverlapping(
-                self.node.val_area_mut(self.idx + 1..).as_ptr(),
-                new_node.vals.as_mut_ptr(),
-                new_len,
+            move_to_slice(
+                self.node.val_area_mut(self.idx + 1..old_len),
+                &mut new_node.vals[..new_len],
             );
 
             *self.node.len_mut() = self.idx as u16;
@@ -1190,20 +1189,20 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>,
     /// - All the edges and key-value pairs to the right of this handle are put into
     ///   a newly allocated node.
     pub fn split(mut self) -> SplitResult<'a, K, V, marker::Internal> {
+        let old_len = self.node.len();
         unsafe {
             let mut new_node = Box::new(InternalNode::new());
             let kv = self.split_leaf_data(&mut new_node.data);
             let new_len = usize::from(new_node.data.len);
-            ptr::copy_nonoverlapping(
-                self.node.edge_area_mut(self.idx + 1..).as_ptr(),
-                new_node.edges.as_mut_ptr(),
-                new_len + 1,
+            move_to_slice(
+                self.node.edge_area_mut(self.idx + 1..old_len + 1),
+                &mut new_node.edges[..new_len + 1],
             );
 
             let height = self.node.height;
             let mut right = NodeRef::from_new_internal(new_node, height);
 
-            right.borrow_mut().correct_childrens_parent_links(0..=new_len);
+            right.borrow_mut().correct_childrens_parent_links(0..new_len + 1);
 
             SplitResult { left: self.node, kv, right }
         }
@@ -1323,18 +1322,16 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> {
 
             let parent_key = slice_remove(parent_node.key_area_mut(..old_parent_len), parent_idx);
             left_node.key_area_mut(old_left_len).write(parent_key);
-            ptr::copy_nonoverlapping(
-                right_node.key_area_mut(..).as_ptr(),
-                left_node.key_area_mut(old_left_len + 1..).as_mut_ptr(),
-                right_len,
+            move_to_slice(
+                right_node.key_area_mut(..right_len),
+                left_node.key_area_mut(old_left_len + 1..new_left_len),
             );
 
             let parent_val = slice_remove(parent_node.val_area_mut(..old_parent_len), parent_idx);
             left_node.val_area_mut(old_left_len).write(parent_val);
-            ptr::copy_nonoverlapping(
-                right_node.val_area_mut(..).as_ptr(),
-                left_node.val_area_mut(old_left_len + 1..).as_mut_ptr(),
-                right_len,
+            move_to_slice(
+                right_node.val_area_mut(..right_len),
+                left_node.val_area_mut(old_left_len + 1..new_left_len),
             );
 
             slice_remove(&mut parent_node.edge_area_mut(..old_parent_len + 1), parent_idx + 1);
@@ -1346,10 +1343,9 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> {
                 // of the node of this edge, thus above zero, so they are internal.
                 let mut left_node = left_node.reborrow_mut().cast_to_internal_unchecked();
                 let mut right_node = right_node.cast_to_internal_unchecked();
-                ptr::copy_nonoverlapping(
-                    right_node.edge_area_mut(..).as_ptr(),
-                    left_node.edge_area_mut(old_left_len + 1..).as_mut_ptr(),
-                    right_len + 1,
+                move_to_slice(
+                    right_node.edge_area_mut(..right_len + 1),
+                    left_node.edge_area_mut(old_left_len + 1..new_left_len + 1),
                 );
 
                 left_node.correct_childrens_parent_links(old_left_len + 1..new_left_len + 1);
@@ -1741,5 +1737,15 @@ unsafe fn slice_remove<T>(slice: &mut [MaybeUninit<T>], idx: usize) -> T {
     }
 }
 
+/// Moves all values from a slice of initialized elements to a slice
+/// of uninitialized elements, leaving behind `src` as all uninitialized.
+/// Works like `dst.copy_from_slice(src)` but does not require `T` to be `Copy`.
+fn move_to_slice<T>(src: &mut [MaybeUninit<T>], dst: &mut [MaybeUninit<T>]) {
+    assert!(src.len() == dst.len());
+    unsafe {
+        ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), src.len());
+    }
+}
+
 #[cfg(test)]
 mod tests;
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index e6db66ac571..cfad111aa54 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -70,7 +70,6 @@
 #![warn(missing_docs)]
 #![warn(missing_debug_implementations)]
 #![allow(explicit_outlives_requirements)]
-#![allow(incomplete_features)]
 #![deny(unsafe_op_in_unsafe_fn)]
 #![feature(rustc_allow_const_fn_unstable)]
 #![cfg_attr(not(test), feature(generator_trait))]
@@ -90,7 +89,6 @@
 #![feature(coerce_unsized)]
 #![feature(const_btree_new)]
 #![feature(const_fn)]
-#![feature(const_generics)]
 #![feature(const_in_array_repeat_expressions)]
 #![feature(cow_is_borrowed)]
 #![feature(const_cow_is_borrowed)]
@@ -120,6 +118,7 @@
 #![feature(raw_ref_op)]
 #![feature(rustc_attrs)]
 #![feature(receiver_trait)]
+#![cfg_attr(bootstrap, feature(min_const_generics))]
 #![feature(min_specialization)]
 #![feature(slice_ptr_get)]
 #![feature(slice_ptr_len)]
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 3115cc3d002..8183a582d33 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -238,6 +238,7 @@
 //! [downgrade]: Rc::downgrade
 //! [upgrade]: Weak::upgrade
 //! [mutability]: core::cell#introducing-mutability-inside-of-something-immutable
+//! [fully qualified syntax]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
index 578eca7d893..70e0c7dba5e 100644
--- a/library/alloc/src/str.rs
+++ b/library/alloc/src/str.rs
@@ -451,8 +451,6 @@ impl str {
 
     /// Converts a [`Box<str>`] into a [`String`] without copying or allocating.
     ///
-    /// [`Box<str>`]: Box
-    ///
     /// # Examples
     ///
     /// Basic usage:
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 2a83eb33fe3..1ca194c3361 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -990,6 +990,9 @@ impl<T, A: Allocator> Vec<T, A> {
         //   such that no value will be dropped twice in case `drop_in_place`
         //   were to panic once (if it panics twice, the program aborts).
         unsafe {
+            // Note: It's intentional that this is `>` and not `>=`.
+            //       Changing it to `>=` has negative performance
+            //       implications in some cases. See #78884 for more.
             if len > self.len {
                 return;
             }
diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs
index 57c6624b64f..c572c66ce32 100644
--- a/library/core/src/alloc/layout.rs
+++ b/library/core/src/alloc/layout.rs
@@ -4,6 +4,12 @@ use crate::mem;
 use crate::num::NonZeroUsize;
 use crate::ptr::NonNull;
 
+// While this function is used in one place and its implementation
+// could be inlined, the previous attempts to do so made rustc
+// slower:
+//
+// * https://github.com/rust-lang/rust/pull/72189
+// * https://github.com/rust-lang/rust/pull/79827
 const fn size_align<T>() -> (usize, usize) {
     (mem::size_of::<T>(), mem::align_of::<T>())
 }
diff --git a/library/core/src/any.rs b/library/core/src/any.rs
index d1951fbbf10..eef8f2046d3 100644
--- a/library/core/src/any.rs
+++ b/library/core/src/any.rs
@@ -14,6 +14,29 @@
 //!
 //! [`Box`]: ../../std/boxed/struct.Box.html
 //!
+//! # Smart pointers and `dyn Any`
+//!
+//! One piece of behavior to keep in mind when using `Any` as a trait object,
+//! especially with types like `Box<dyn Any>` or `Arc<dyn Any>`, is that simply
+//! calling `.type_id()` on the value will produce the `TypeId` of the
+//! *container*, not the underlying trait object. This can be avoided by
+//! converting the smart pointer into a `&dyn Any` instead, which will return
+//! the object's `TypeId`. For example:
+//!
+//! ```
+//! use std::any::{Any, TypeId};
+//!
+//! let boxed: Box<dyn Any> = Box::new(3_i32);
+//!
+//! // You're more likely to want this:
+//! let actual_id = (&*boxed).type_id();
+//! // ... than this:
+//! let boxed_id = boxed.type_id();
+//!
+//! assert_eq!(actual_id, TypeId::of::<i32>());
+//! assert_eq!(boxed_id, TypeId::of::<Box<dyn Any>>());
+//! ```
+//!
 //! # Examples
 //!
 //! Consider a situation where we want to log out a value passed to a function.
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index 71548bec7aa..85b1a47f4a9 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -12,6 +12,7 @@ use crate::convert::{Infallible, TryFrom};
 use crate::fmt;
 use crate::hash::{self, Hash};
 use crate::marker::Unsize;
+use crate::mem::MaybeUninit;
 use crate::ops::{Index, IndexMut};
 use crate::slice::{Iter, IterMut};
 
@@ -429,7 +430,6 @@ impl<T, const N: usize> [T; N] {
     where
         F: FnMut(T) -> U,
     {
-        use crate::mem::MaybeUninit;
         struct Guard<T, const N: usize> {
             dst: *mut T,
             initialized: usize,
@@ -481,8 +481,6 @@ impl<T, const N: usize> [T; N] {
     /// ```
     #[unstable(feature = "array_zip", issue = "80094")]
     pub fn zip<U>(self, rhs: [U; N]) -> [(T, U); N] {
-        use crate::mem::MaybeUninit;
-
         let mut dst = MaybeUninit::uninit_array::<N>();
         for (i, (lhs, rhs)) in IntoIter::new(self).zip(IntoIter::new(rhs)).enumerate() {
             dst[i].write((lhs, rhs));
@@ -506,4 +504,75 @@ impl<T, const N: usize> [T; N] {
     pub fn as_mut_slice(&mut self) -> &mut [T] {
         self
     }
+
+    /// Borrows each element and returns an array of references with the same
+    /// size as `self`.
+    ///
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(array_methods)]
+    ///
+    /// let floats = [3.1, 2.7, -1.0];
+    /// let float_refs: [&f64; 3] = floats.each_ref();
+    /// assert_eq!(float_refs, [&3.1, &2.7, &-1.0]);
+    /// ```
+    ///
+    /// This method is particularly useful if combined with other methods, like
+    /// [`map`](#method.map). This way, you can can avoid moving the original
+    /// array if its elements are not `Copy`.
+    ///
+    /// ```
+    /// #![feature(array_methods, array_map)]
+    ///
+    /// let strings = ["Ferris".to_string(), "♥".to_string(), "Rust".to_string()];
+    /// let is_ascii = strings.each_ref().map(|s| s.is_ascii());
+    /// assert_eq!(is_ascii, [true, false, true]);
+    ///
+    /// // We can still access the original array: it has not been moved.
+    /// assert_eq!(strings.len(), 3);
+    /// ```
+    #[unstable(feature = "array_methods", issue = "76118")]
+    pub fn each_ref(&self) -> [&T; N] {
+        // Unlike in `map`, we don't need a guard here, as dropping a reference
+        // is a noop.
+        let mut out = MaybeUninit::uninit_array::<N>();
+        for (src, dst) in self.iter().zip(&mut out) {
+            dst.write(src);
+        }
+
+        // SAFETY: All elements of `dst` are properly initialized and
+        // `MaybeUninit<T>` has the same layout as `T`, so this cast is valid.
+        unsafe { (&mut out as *mut _ as *mut [&T; N]).read() }
+    }
+
+    /// Borrows each element mutably and returns an array of mutable references
+    /// with the same size as `self`.
+    ///
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(array_methods)]
+    ///
+    /// let mut floats = [3.1, 2.7, -1.0];
+    /// let float_refs: [&mut f64; 3] = floats.each_mut();
+    /// *float_refs[0] = 0.0;
+    /// assert_eq!(float_refs, [&mut 0.0, &mut 2.7, &mut -1.0]);
+    /// assert_eq!(floats, [0.0, 2.7, -1.0]);
+    /// ```
+    #[unstable(feature = "array_methods", issue = "76118")]
+    pub fn each_mut(&mut self) -> [&mut T; N] {
+        // Unlike in `map`, we don't need a guard here, as dropping a reference
+        // is a noop.
+        let mut out = MaybeUninit::uninit_array::<N>();
+        for (src, dst) in self.iter_mut().zip(&mut out) {
+            dst.write(src);
+        }
+
+        // SAFETY: All elements of `dst` are properly initialized and
+        // `MaybeUninit<T>` has the same layout as `T`, so this cast is valid.
+        unsafe { (&mut out as *mut _ as *mut [&mut T; N]).read() }
+    }
 }
diff --git a/library/core/src/borrow.rs b/library/core/src/borrow.rs
index 6f5a6aa7c79..c9040cd0a16 100644
--- a/library/core/src/borrow.rs
+++ b/library/core/src/borrow.rs
@@ -40,7 +40,6 @@
 /// provide a reference to related type `T`, it is often better to use
 /// [`AsRef<T>`] as more types can safely implement it.
 ///
-/// [`BorrowMut<T>`]: BorrowMut
 /// [`Box<T>`]: ../../std/boxed/struct.Box.html
 /// [`Mutex<T>`]: ../../std/sync/struct.Mutex.html
 /// [`Rc<T>`]: ../../std/rc/struct.Rc.html
@@ -183,8 +182,6 @@ pub trait Borrow<Borrowed: ?Sized> {
 /// As a companion to [`Borrow<T>`] this trait allows a type to borrow as
 /// an underlying type by providing a mutable reference. See [`Borrow<T>`]
 /// for more information on borrowing as another type.
-///
-/// [`Borrow<T>`]: Borrow
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> {
     /// Mutably borrows from an owned value.
diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs
index de05a8c82e8..7a0ec32cc61 100644
--- a/library/core/src/char/convert.rs
+++ b/library/core/src/char/convert.rs
@@ -113,6 +113,48 @@ impl From<char> for u32 {
     }
 }
 
+#[stable(feature = "more_char_conversions", since = "1.51.0")]
+impl From<char> for u64 {
+    /// Converts a [`char`] into a [`u64`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::mem;
+    ///
+    /// let c = '👤';
+    /// let u = u64::from(c);
+    /// assert!(8 == mem::size_of_val(&u))
+    /// ```
+    #[inline]
+    fn from(c: char) -> Self {
+        // The char is casted to the value of the code point, then zero-extended to 64 bit.
+        // See [https://doc.rust-lang.org/reference/expressions/operator-expr.html#semantics]
+        c as u64
+    }
+}
+
+#[stable(feature = "more_char_conversions", since = "1.51.0")]
+impl From<char> for u128 {
+    /// Converts a [`char`] into a [`u128`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::mem;
+    ///
+    /// let c = '⚙';
+    /// let u = u128::from(c);
+    /// assert!(16 == mem::size_of_val(&u))
+    /// ```
+    #[inline]
+    fn from(c: char) -> Self {
+        // The char is casted to the value of the code point, then zero-extended to 128 bit.
+        // See [https://doc.rust-lang.org/reference/expressions/operator-expr.html#semantics]
+        c as u128
+    }
+}
+
 /// Maps a byte in 0x00..=0xFF to a `char` whose code point has the same value, in U+0000..=U+00FF.
 ///
 /// Unicode is designed such that this effectively decodes bytes
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 0c459a820c6..38c6bfb0ef3 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -29,7 +29,7 @@ use self::Ordering::*;
 ///
 /// This trait allows for partial equality, for types that do not have a full
 /// equivalence relation. For example, in floating point numbers `NaN != NaN`,
-/// so floating point types implement `PartialEq` but not [`Eq`].
+/// so floating point types implement `PartialEq` but not [`trait@Eq`].
 ///
 /// Formally, the equality must be (for all `a`, `b` and `c`):
 ///
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index 3f7110b34cc..041f40f2cbc 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -135,8 +135,6 @@ pub const fn identity<T>(x: T) -> T {
 /// Since both [`String`] and [`&str`] implement `AsRef<str>` we can accept both as input argument.
 ///
 /// [`&str`]: primitive@str
-/// [`Option<T>`]: Option
-/// [`Result<T, E>`]: Result
 /// [`Borrow`]: crate::borrow::Borrow
 /// [`Eq`]: crate::cmp::Eq
 /// [`Ord`]: crate::cmp::Ord
@@ -169,9 +167,6 @@ pub trait AsRef<T: ?Sized> {
 /// **Note: This trait must not fail**. If the conversion can fail, use a
 /// dedicated method which returns an [`Option<T>`] or a [`Result<T, E>`].
 ///
-/// [`Option<T>`]: Option
-/// [`Result<T, E>`]: Result
-///
 /// # Generic Implementations
 ///
 /// - `AsMut` auto-dereferences if the inner type is a mutable reference
@@ -270,8 +265,6 @@ pub trait AsMut<T: ?Sized> {
 /// is_hello(s);
 /// ```
 ///
-/// [`Option<T>`]: Option
-/// [`Result<T, E>`]: Result
 /// [`String`]: ../../std/string/struct.String.html
 /// [`Vec`]: ../../std/vec/struct.Vec.html
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -359,8 +352,6 @@ pub trait Into<T>: Sized {
 /// }
 /// ```
 ///
-/// [`Option<T>`]: Option
-/// [`Result<T, E>`]: Result
 /// [`String`]: ../../std/string/struct.String.html
 /// [`from`]: From::from
 /// [book]: ../../book/ch09-00-error-handling.html
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 979a5f8cf50..313729581ac 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -91,7 +91,7 @@ pub const unsafe fn unreachable_unchecked() -> ! {
 /// };
 ///
 /// // Back on our current thread, we wait for the value to be set
-/// while live.load(Ordering::Acquire) {
+/// while !live.load(Ordering::Acquire) {
 ///     // The spin loop is a hint to the CPU that we're waiting, but probably
 ///     // not for very long
 ///     hint::spin_loop();
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 938dc214486..0130586b430 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -712,8 +712,8 @@ extern "rust-intrinsic" {
     /// [`std::process::abort`](../../std/process/fn.abort.html).
     pub fn abort() -> !;
 
-    /// Tells LLVM that this point in the code is not reachable, enabling
-    /// further optimizations.
+    /// Informs the optimizer that this point in the code is not reachable,
+    /// enabling further optimizations.
     ///
     /// N.B., this is very different from the `unreachable!()` macro: Unlike the
     /// macro, which panics when it is executed, it is *undefined behavior* to
@@ -1133,7 +1133,7 @@ extern "rust-intrinsic" {
     /// This intrinsic does not have a stable counterpart.
     pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: usize);
     /// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with
-    /// a size of `count` * `size_of::<T>()` and an alignment of
+    /// a size of `count * size_of::<T>()` and an alignment of
     /// `min_align_of::<T>()`
     ///
     /// The volatile parameter is set to `true`, so it will not be optimized out
@@ -1142,7 +1142,7 @@ extern "rust-intrinsic" {
     /// This intrinsic does not have a stable counterpart.
     pub fn volatile_copy_memory<T>(dst: *mut T, src: *const T, count: usize);
     /// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a
-    /// size of `count` * `size_of::<T>()` and an alignment of
+    /// size of `count * size_of::<T>()` and an alignment of
     /// `min_align_of::<T>()`.
     ///
     /// The volatile parameter is set to `true`, so it will not be optimized out
@@ -1588,7 +1588,7 @@ extern "rust-intrinsic" {
     pub fn exact_div<T: Copy>(x: T, y: T) -> T;
 
     /// Performs an unchecked division, resulting in undefined behavior
-    /// where y = 0 or x = `T::MIN` and y = -1
+    /// where `y == 0` or `x == T::MIN && y == -1`
     ///
     /// Safe wrappers for this intrinsic are available on the integer
     /// primitives via the `checked_div` method. For example,
@@ -1596,7 +1596,7 @@ extern "rust-intrinsic" {
     #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
     pub fn unchecked_div<T: Copy>(x: T, y: T) -> T;
     /// Returns the remainder of an unchecked division, resulting in
-    /// undefined behavior where y = 0 or x = `T::MIN` and y = -1
+    /// undefined behavior when `y == 0` or `x == T::MIN && y == -1`
     ///
     /// Safe wrappers for this intrinsic are available on the integer
     /// primitives via the `checked_rem` method. For example,
@@ -1605,7 +1605,7 @@ extern "rust-intrinsic" {
     pub fn unchecked_rem<T: Copy>(x: T, y: T) -> T;
 
     /// Performs an unchecked left shift, resulting in undefined behavior when
-    /// y < 0 or y >= N, where N is the width of T in bits.
+    /// `y < 0` or `y >= N`, where N is the width of T in bits.
     ///
     /// Safe wrappers for this intrinsic are available on the integer
     /// primitives via the `checked_shl` method. For example,
@@ -1613,7 +1613,7 @@ extern "rust-intrinsic" {
     #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")]
     pub fn unchecked_shl<T: Copy>(x: T, y: T) -> T;
     /// Performs an unchecked right shift, resulting in undefined behavior when
-    /// y < 0 or y >= N, where N is the width of T in bits.
+    /// `y < 0` or `y >= N`, where N is the width of T in bits.
     ///
     /// Safe wrappers for this intrinsic are available on the integer
     /// primitives via the `checked_shr` method. For example,
@@ -1680,14 +1680,14 @@ extern "rust-intrinsic" {
     #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
     pub fn wrapping_mul<T: Copy>(a: T, b: T) -> T;
 
-    /// Computes `a + b`, while saturating at numeric bounds.
+    /// Computes `a + b`, saturating at numeric bounds.
     ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `saturating_add` method. For example,
     /// [`u32::saturating_add`]
     #[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
     pub fn saturating_add<T: Copy>(a: T, b: T) -> T;
-    /// Computes `a - b`, while saturating at numeric bounds.
+    /// Computes `a - b`, saturating at numeric bounds.
     ///
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `saturating_sub` method. For example,
@@ -1696,14 +1696,14 @@ extern "rust-intrinsic" {
     pub fn saturating_sub<T: Copy>(a: T, b: T) -> T;
 
     /// Returns the value of the discriminant for the variant in 'v',
-    /// cast to a `u64`; if `T` has no discriminant, returns 0.
+    /// cast to a `u64`; if `T` has no discriminant, returns `0`.
     ///
     /// The stabilized version of this intrinsic is [`core::mem::discriminant`](crate::mem::discriminant).
     #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
     pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
 
     /// Returns the number of variants of the type `T` cast to a `usize`;
-    /// if `T` has no variants, returns 0. Uninhabited variants will be counted.
+    /// if `T` has no variants, returns `0`. Uninhabited variants will be counted.
     ///
     /// The to-be-stabilized version of this intrinsic is [`mem::variant_count`].
     #[rustc_const_unstable(feature = "variant_count", issue = "73662")]
@@ -1845,7 +1845,7 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -
 /// [`Vec::append`]: ../../std/vec/struct.Vec.html#method.append
 #[doc(alias = "memcpy")]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "none")]
+#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
 #[inline]
 pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
     extern "rust-intrinsic" {
@@ -1929,11 +1929,10 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
 /// ```
 #[doc(alias = "memmove")]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "none")]
+#[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
 #[inline]
 pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
     extern "rust-intrinsic" {
-        #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "none")]
         fn copy<T>(src: *const T, dst: *mut T, count: usize);
     }
 
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
index 8cd4c775231..5766fd3c887 100644
--- a/library/core/src/iter/adapters/zip.rs
+++ b/library/core/src/iter/adapters/zip.rs
@@ -397,7 +397,7 @@ impl<A: Debug + TrustedRandomAccess, B: Debug + TrustedRandomAccess> ZipFmt<A, B
 ///    only be called at most `self.size() - idx - 1` times.
 /// 4. After `get_unchecked` is called, then only the following methods will be
 ///    called on `self`:
-///     * `std::clone::Clone::clone`
+///     * `std::clone::Clone::clone()`
 ///     * `std::iter::Iterator::size_hint()`
 ///     * `std::iter::Iterator::next_back()`
 ///     * `std::iter::Iterator::__iterator_get_unchecked()`
diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs
index cd8ab11cb84..4321b2187e1 100644
--- a/library/core/src/iter/range.rs
+++ b/library/core/src/iter/range.rs
@@ -111,7 +111,7 @@ pub unsafe trait Step: Clone + PartialOrd + Sized {
         Step::forward(start, count)
     }
 
-    /// Returns the value that would be obtained by taking the *successor*
+    /// Returns the value that would be obtained by taking the *predecessor*
     /// of `self` `count` times.
     ///
     /// If this would overflow the range of values supported by `Self`, returns `None`.
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 633175702d8..0023de65d2b 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -805,8 +805,6 @@ pub trait Iterator {
     /// assert_eq!(iter.next(), Some(5));
     /// assert_eq!(iter.next(), None);
     /// ```
-    ///
-    /// [`Option<T>`]: Option
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 099b98b824d..df8d9ff371f 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -62,7 +62,6 @@
 #![warn(missing_docs)]
 #![warn(missing_debug_implementations)]
 #![allow(explicit_outlives_requirements)]
-#![allow(incomplete_features)]
 #![feature(rustc_allow_const_fn_unstable)]
 #![feature(allow_internal_unstable)]
 #![feature(arbitrary_self_types)]
@@ -89,7 +88,6 @@
 #![feature(const_impl_trait)]
 #![feature(const_fn_floating_point_arithmetic)]
 #![feature(const_fn_fn_ptr_basics)]
-#![feature(const_generics)]
 #![feature(const_option)]
 #![feature(const_precise_live_drops)]
 #![feature(const_ptr_offset)]
@@ -131,6 +129,7 @@
 #![feature(repr_simd, platform_intrinsics)]
 #![feature(rustc_attrs)]
 #![feature(simd_ffi)]
+#![cfg_attr(bootstrap, feature(min_const_generics))]
 #![feature(min_specialization)]
 #![feature(staged_api)]
 #![feature(std_internals)]
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 22e44a3c409..64cf5286eb1 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -4,6 +4,7 @@
 //! types, initializing and manipulating memory.
 
 #![stable(feature = "rust1", since = "1.0.0")]
+#![cfg_attr(bootstrap, allow(unused_unsafe))]
 
 use crate::clone;
 use crate::cmp;
@@ -333,7 +334,8 @@ pub const fn size_of<T>() -> usize {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")]
 pub const fn size_of_val<T: ?Sized>(val: &T) -> usize {
-    intrinsics::size_of_val(val)
+    // SAFETY: `val` is a reference, so it's a valid raw pointer
+    unsafe { intrinsics::size_of_val(val) }
 }
 
 /// Returns the size of the pointed-to value in bytes.
@@ -381,7 +383,8 @@ pub const fn size_of_val<T: ?Sized>(val: &T) -> usize {
 #[unstable(feature = "layout_for_ptr", issue = "69835")]
 #[rustc_const_unstable(feature = "const_size_of_val_raw", issue = "46571")]
 pub const unsafe fn size_of_val_raw<T: ?Sized>(val: *const T) -> usize {
-    intrinsics::size_of_val(val)
+    // SAFETY: the caller must provide a valid raw pointer
+    unsafe { intrinsics::size_of_val(val) }
 }
 
 /// Returns the [ABI]-required minimum alignment of a type.
@@ -425,7 +428,8 @@ pub fn min_align_of<T>() -> usize {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_deprecated(reason = "use `align_of_val` instead", since = "1.2.0")]
 pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
-    intrinsics::min_align_of_val(val)
+    // SAFETY: val is a reference, so it's a valid raw pointer
+    unsafe { intrinsics::min_align_of_val(val) }
 }
 
 /// Returns the [ABI]-required minimum alignment of a type.
@@ -469,7 +473,8 @@ pub const fn align_of<T>() -> usize {
 #[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")]
 #[allow(deprecated)]
 pub const fn align_of_val<T: ?Sized>(val: &T) -> usize {
-    intrinsics::min_align_of_val(val)
+    // SAFETY: val is a reference, so it's a valid raw pointer
+    unsafe { intrinsics::min_align_of_val(val) }
 }
 
 /// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to.
@@ -513,7 +518,8 @@ pub const fn align_of_val<T: ?Sized>(val: &T) -> usize {
 #[unstable(feature = "layout_for_ptr", issue = "69835")]
 #[rustc_const_unstable(feature = "const_align_of_val_raw", issue = "46571")]
 pub const unsafe fn align_of_val_raw<T: ?Sized>(val: *const T) -> usize {
-    intrinsics::min_align_of_val(val)
+    // SAFETY: the caller must provide a valid raw pointer
+    unsafe { intrinsics::min_align_of_val(val) }
 }
 
 /// Returns `true` if dropping values of type `T` matters.
@@ -650,7 +656,6 @@ pub unsafe fn zeroed<T>() -> T {
 /// (Notice that the rules around uninitialized integers are not finalized yet, but
 /// until they are, it is advisable to avoid them.)
 ///
-/// [`MaybeUninit<T>`]: MaybeUninit
 /// [uninit]: MaybeUninit::uninit
 /// [assume_init]: MaybeUninit::assume_init
 /// [inv]: MaybeUninit#initialization-invariant
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 1afa30f5843..0051c9eede0 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -512,7 +512,6 @@ impl<T> Option<T> {
     /// result of a function call, it is recommended to use [`ok_or_else`], which is
     /// lazily evaluated.
     ///
-    /// [`Result<T, E>`]: Result
     /// [`Ok(v)`]: Ok
     /// [`Err(err)`]: Err
     /// [`Some(v)`]: Some
@@ -539,7 +538,6 @@ impl<T> Option<T> {
     /// Transforms the `Option<T>` into a [`Result<T, E>`], mapping [`Some(v)`] to
     /// [`Ok(v)`] and [`None`] to [`Err(err())`].
     ///
-    /// [`Result<T, E>`]: Result
     /// [`Ok(v)`]: Ok
     /// [`Err(err())`]: Err
     /// [`Some(v)`]: Some
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 0b9c733f7fe..b2de0e16a17 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -349,7 +349,6 @@
 //! mutable reference even when you just have [`Pin`]`<&mut Self>` (such as in your own
 //! [`poll`] implementation).
 //!
-//! [`Pin<P>`]: Pin
 //! [`Deref`]: crate::ops::Deref
 //! [`DerefMut`]: crate::ops::DerefMut
 //! [`mem::swap`]: crate::mem::swap
@@ -364,7 +363,6 @@
 //! [`RefCell<T>`]: crate::cell::RefCell
 //! [`drop`]: Drop::drop
 //! [`VecDeque<T>`]: ../../std/collections/struct.VecDeque.html
-//! [`Option<T>`]: Option
 //! [`Some(v)`]: Some
 //! [`ptr::write`]: crate::ptr::write
 //! [`Future`]: crate::future::Future
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 0b4ca2b7214..d6d17625729 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -368,8 +368,6 @@ impl<T, E> Result<T, E> {
     /// Converts `self` into an [`Option<T>`], consuming `self`,
     /// and discarding the error, if any.
     ///
-    /// [`Option<T>`]: Option
-    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -395,8 +393,6 @@ impl<T, E> Result<T, E> {
     /// Converts `self` into an [`Option<E>`], consuming `self`,
     /// and discarding the success value, if any.
     ///
-    /// [`Option<E>`]: Option
-    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -1009,8 +1005,6 @@ impl<T: fmt::Debug, E> Result<T, E> {
     /// Panics if the value is an [`Ok`], with a custom panic message provided
     /// by the [`Ok`]'s value.
     ///
-    ///
-    ///
     /// # Examples
     ///
     /// ```{.should_panic}
diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index a367b4737db..769b673d80a 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -51,7 +51,7 @@ fn size_from_ptr<T>(_: *const T) -> usize {
 /// Basic usage:
 ///
 /// ```
-/// // First, we declare a type which has `iter` method to get the `Iter` struct (&[usize here]):
+/// // First, we declare a type which has `iter` method to get the `Iter` struct (`&[usize]` here):
 /// let slice = &[1, 2, 3];
 ///
 /// // Then, we iterate over it:
@@ -112,7 +112,7 @@ impl<'a, T> Iter<'a, T> {
     ///
     /// ```
     /// // First, we declare a type which has the `iter` method to get the `Iter`
-    /// // struct (&[usize here]):
+    /// // struct (`&[usize]` here):
     /// let slice = &[1, 2, 3];
     ///
     /// // Then, we get the iterator:
@@ -167,7 +167,7 @@ impl<T> AsRef<[T]> for Iter<'_, T> {
 ///
 /// ```
 /// // First, we declare a type which has `iter_mut` method to get the `IterMut`
-/// // struct (&[usize here]):
+/// // struct (`&[usize]` here):
 /// let mut slice = &mut [1, 2, 3];
 ///
 /// // Then, we iterate over it and increment each element value:
@@ -246,7 +246,7 @@ impl<'a, T> IterMut<'a, T> {
     ///
     /// ```
     /// // First, we declare a type which has `iter_mut` method to get the `IterMut`
-    /// // struct (&[usize here]):
+    /// // struct (`&[usize]` here):
     /// let mut slice = &mut [1, 2, 3];
     ///
     /// {
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 58bf74c8cf4..bd01271ec15 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -1872,19 +1872,24 @@ impl<T> [T] {
     /// # Examples
     ///
     /// ```
-    /// #![feature(slice_strip)]
     /// let v = &[10, 40, 30];
     /// assert_eq!(v.strip_prefix(&[10]), Some(&[40, 30][..]));
     /// assert_eq!(v.strip_prefix(&[10, 40]), Some(&[30][..]));
     /// assert_eq!(v.strip_prefix(&[50]), None);
     /// assert_eq!(v.strip_prefix(&[10, 50]), None);
+    ///
+    /// let prefix : &str = "he";
+    /// assert_eq!(b"hello".strip_prefix(prefix.as_bytes()),
+    ///            Some(b"llo".as_ref()));
     /// ```
     #[must_use = "returns the subslice without modifying the original"]
-    #[unstable(feature = "slice_strip", issue = "73413")]
-    pub fn strip_prefix(&self, prefix: &[T]) -> Option<&[T]>
+    #[stable(feature = "slice_strip", since = "1.50.0")]
+    pub fn strip_prefix<P: SlicePattern<Item = T> + ?Sized>(&self, prefix: &P) -> Option<&[T]>
     where
         T: PartialEq,
     {
+        // This function will need rewriting if and when SlicePattern becomes more sophisticated.
+        let prefix = prefix.as_slice();
         let n = prefix.len();
         if n <= self.len() {
             let (head, tail) = self.split_at(n);
@@ -1905,7 +1910,6 @@ impl<T> [T] {
     /// # Examples
     ///
     /// ```
-    /// #![feature(slice_strip)]
     /// let v = &[10, 40, 30];
     /// assert_eq!(v.strip_suffix(&[30]), Some(&[10, 40][..]));
     /// assert_eq!(v.strip_suffix(&[40, 30]), Some(&[10][..]));
@@ -1913,11 +1917,13 @@ impl<T> [T] {
     /// assert_eq!(v.strip_suffix(&[50, 30]), None);
     /// ```
     #[must_use = "returns the subslice without modifying the original"]
-    #[unstable(feature = "slice_strip", issue = "73413")]
-    pub fn strip_suffix(&self, suffix: &[T]) -> Option<&[T]>
+    #[stable(feature = "slice_strip", since = "1.50.0")]
+    pub fn strip_suffix<P: SlicePattern<Item = T> + ?Sized>(&self, suffix: &P) -> Option<&[T]>
     where
         T: PartialEq,
     {
+        // This function will need rewriting if and when SlicePattern becomes more sophisticated.
+        let suffix = suffix.as_slice();
         let (len, n) = (self.len(), suffix.len());
         if n <= len {
             let (head, tail) = self.split_at(len - n);
@@ -3310,3 +3316,35 @@ impl<T> Default for &mut [T] {
         &mut []
     }
 }
+
+#[unstable(feature = "slice_pattern", reason = "stopgap trait for slice patterns", issue = "56345")]
+/// Patterns in slices - currently, only used by `strip_prefix` and `strip_suffix`.  At a future
+/// point, we hope to generalise `core::str::Pattern` (which at the time of writing is limited to
+/// `str`) to slices, and then this trait will be replaced or abolished.
+pub trait SlicePattern {
+    /// The element type of the slice being matched on.
+    type Item;
+
+    /// Currently, the consumers of `SlicePattern` need a slice.
+    fn as_slice(&self) -> &[Self::Item];
+}
+
+#[stable(feature = "slice_strip", since = "1.50.0")]
+impl<T> SlicePattern for [T] {
+    type Item = T;
+
+    #[inline]
+    fn as_slice(&self) -> &[Self::Item] {
+        self
+    }
+}
+
+#[stable(feature = "slice_strip", since = "1.50.0")]
+impl<T, const N: usize> SlicePattern for [T; N] {
+    type Item = T;
+
+    #[inline]
+    fn as_slice(&self) -> &[Self::Item] {
+        self
+    }
+}
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index ba495a1a9fb..ae7892291ed 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -2175,7 +2175,7 @@ impl str {
     /// helps the inference algorithm understand specifically which type
     /// you're trying to parse into.
     ///
-    /// `parse` can parse any type that implements the [`FromStr`] trait.
+    /// `parse` can parse into any type that implements the [`FromStr`] trait.
 
     ///
     /// # Errors
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 71d00b5c087..1c738761e8a 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -17,7 +17,7 @@ panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core" }
 libc = { version = "0.2.79", default-features = false, features = ['rustc-dep-of-std'] }
-compiler_builtins = { version = "0.1.35" }
+compiler_builtins = { version = "0.1.39" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.9.0", default-features = false, features = ['rustc-dep-of-std'] }
@@ -60,7 +60,7 @@ panic-unwind = ["panic_unwind"]
 profiler = ["profiler_builtins"]
 compiler-builtins-c = ["alloc/compiler-builtins-c"]
 compiler-builtins-mem = ["alloc/compiler-builtins-mem"]
-compiler-builtins-asm = ["alloc/compiler-builtins-asm"]
+compiler-builtins-no-asm = ["alloc/compiler-builtins-no-asm"]
 compiler-builtins-mangled-names = ["alloc/compiler-builtins-mangled-names"]
 llvm-libunwind = ["unwind/llvm-libunwind"]
 system-llvm-libunwind = ["unwind/system-llvm-libunwind"]
diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs
index 8491ff40033..843ef09a584 100644
--- a/library/std/src/alloc.rs
+++ b/library/std/src/alloc.rs
@@ -166,8 +166,9 @@ impl System {
         match old_layout.size() {
             0 => self.alloc_impl(new_layout, zeroed),
 
-            // SAFETY: `new_size` is non-zero as `old_size` is greater than or equal to `new_size`
-            // as required by safety conditions. Other conditions must be upheld by the caller
+            // SAFETY: `new_size` is non-zero as `new_size` is greater than or equal to `old_size`
+            // as required by safety conditions and the `old_size == 0` case was handled in the
+            // previous match arm. Other conditions must be upheld by the caller
             old_size if old_layout.align() == new_layout.align() => unsafe {
                 let new_size = new_layout.size();
 
diff --git a/library/std/src/error.rs b/library/std/src/error.rs
index 0044e59d697..ca83c409822 100644
--- a/library/std/src/error.rs
+++ b/library/std/src/error.rs
@@ -42,8 +42,6 @@ use crate::string;
 /// via [`Error::source()`]. This makes it possible for the high-level
 /// module to provide its own errors while also revealing some of the
 /// implementation for debugging via `source` chains.
-///
-/// [`Result<T, E>`]: Result
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Error: Debug + Display {
     /// The lower-level source of this error, if any.
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index dfbf6c3f244..7ad9e446c59 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -240,7 +240,6 @@
 //!
 //! [`File`]: crate::fs::File
 //! [`TcpStream`]: crate::net::TcpStream
-//! [`Vec<T>`]: Vec
 //! [`io::stdout`]: stdout
 //! [`io::Result`]: self::Result
 //! [`?` operator]: ../../book/appendix-02-operators.html
@@ -1984,7 +1983,6 @@ pub trait BufRead: Read {
     /// also yielded an error.
     ///
     /// [`io::Result`]: self::Result
-    /// [`Vec<u8>`]: Vec
     /// [`read_until`]: BufRead::read_until
     ///
     /// # Examples
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 2c6f03fe224..15ef5d1619b 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -307,7 +307,6 @@
 #![feature(slice_internals)]
 #![feature(slice_ptr_get)]
 #![feature(slice_ptr_len)]
-#![feature(slice_strip)]
 #![feature(staged_api)]
 #![feature(std_internals)]
 #![feature(stdsimd)]
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 8a75c1d6058..243761e3897 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -1775,7 +1775,6 @@ impl Path {
     /// Any non-Unicode sequences are replaced with
     /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
     ///
-    /// [`Cow<str>`]: Cow
     /// [U+FFFD]: super::char::REPLACEMENT_CHARACTER
     ///
     /// # Examples
diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs
index 0fbd6b62f18..26302d0ecf2 100644
--- a/library/std/src/prelude/v1.rs
+++ b/library/std/src/prelude/v1.rs
@@ -41,17 +41,17 @@ pub use crate::result::Result::{self, Err, Ok};
 pub use core::prelude::v1::{
     asm, assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args,
     format_args_nl, global_asm, include, include_bytes, include_str, line, llvm_asm, log_syntax,
-    module_path, option_env, stringify, trace_macros,
+    module_path, option_env, stringify, trace_macros, Clone, Copy, Debug, Default, Eq, Hash, Ord,
+    PartialEq, PartialOrd,
 };
 
-// FIXME: Attribute and derive macros are not documented because for them rustdoc generates
+// FIXME: Attribute and internal derive macros are not documented because for them rustdoc generates
 // dead links which fail link checker testing.
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
 #[allow(deprecated)]
 #[doc(hidden)]
 pub use core::prelude::v1::{
-    bench, global_allocator, test, test_case, Clone, Copy, Debug, Default, Eq, Hash, Ord,
-    PartialEq, PartialOrd, RustcDecodable, RustcEncodable,
+    bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable,
 };
 
 #[unstable(
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index ec12e9f09d8..876b2b8a3f6 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -11,8 +11,9 @@
 /// `bool` implements various traits, such as [`BitAnd`], [`BitOr`], [`Not`], etc.,
 /// which allow us to perform boolean operations using `&`, `|` and `!`.
 ///
-/// `if` always demands a `bool` value. [`assert!`], which is an important macro in testing,
-/// checks whether an expression returns `true` and panics if it isn't.
+/// `if` requires a `bool` value as its conditional. [`assert!`], which is an
+/// important macro in testing, checks whether an expression is `true` and panics
+/// if it isn't.
 ///
 /// ```
 /// let bool_val = true & false | false;
@@ -25,7 +26,7 @@
 ///
 /// # Examples
 ///
-/// A trivial example of the usage of `bool`,
+/// A trivial example of the usage of `bool`:
 ///
 /// ```
 /// let praise_the_borrow_checker = true;
@@ -122,9 +123,9 @@ mod prim_bool {}
 /// `!`, if we have to call [`String::from_str`] for some reason the result will be a
 /// [`Result<String, !>`] which we can unpack like this:
 ///
-/// ```ignore (string-from-str-error-type-is-not-never-yet)
-/// #[feature(exhaustive_patterns)]
-/// // NOTE: this does not work today!
+/// ```
+/// #![feature(exhaustive_patterns)]
+/// use std::str::FromStr;
 /// let Ok(s) = String::from_str("hello");
 /// ```
 ///
@@ -184,9 +185,6 @@ mod prim_bool {}
 /// because `!` coerces to `Result<!, ConnectionError>` automatically.
 ///
 /// [`String::from_str`]: str::FromStr::from_str
-/// [`Result<String, !>`]: Result
-/// [`Result<T, !>`]: Result
-/// [`Result<!, E>`]: Result
 /// [`String`]: string::String
 /// [`FromStr`]: str::FromStr
 ///
diff --git a/library/std/src/sys_common/fs.rs b/library/std/src/sys_common/fs.rs
index e30e8018a31..6bdb26cd078 100644
--- a/library/std/src/sys_common/fs.rs
+++ b/library/std/src/sys_common/fs.rs
@@ -5,19 +5,21 @@ use crate::io::{self, Error, ErrorKind};
 use crate::path::Path;
 
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
-    if !from.is_file() {
+    let mut reader = fs::File::open(from)?;
+    let metadata = reader.metadata()?;
+
+    if !metadata.is_file() {
         return Err(Error::new(
             ErrorKind::InvalidInput,
             "the source path is not an existing regular file",
         ));
     }
 
-    let mut reader = fs::File::open(from)?;
     let mut writer = fs::File::create(to)?;
-    let perm = reader.metadata()?.permissions();
+    let perm = metadata.permissions();
 
     let ret = io::copy(&mut reader, &mut writer)?;
-    fs::set_permissions(to, perm)?;
+    writer.set_permissions(perm)?;
     Ok(ret)
 }
 
diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml
index d5804cc3dd8..226557430df 100644
--- a/library/test/Cargo.toml
+++ b/library/test/Cargo.toml
@@ -26,7 +26,7 @@ default = ["std_detect_file_io", "std_detect_dlsym_getauxval", "panic-unwind"]
 backtrace = ["std/backtrace"]
 compiler-builtins-c = ["std/compiler-builtins-c"]
 compiler-builtins-mem = ["std/compiler-builtins-mem"]
-compiler-builtins-asm = ["std/compiler-builtins-asm"]
+compiler-builtins-no-asm = ["std/compiler-builtins-no-asm"]
 compiler-builtins-mangled-names = ["std/compiler-builtins-mangled-names"]
 llvm-libunwind = ["std/llvm-libunwind"]
 system-llvm-libunwind = ["std/system-llvm-libunwind"]
diff --git a/library/unwind/build.rs b/library/unwind/build.rs
index fae760c4a4e..694e6b98c82 100644
--- a/library/unwind/build.rs
+++ b/library/unwind/build.rs
@@ -4,6 +4,10 @@ fn main() {
     println!("cargo:rerun-if-changed=build.rs");
     let target = env::var("TARGET").expect("TARGET was not set");
 
+    if cfg!(feature = "system-llvm-libunwind") {
+        return;
+    }
+
     if cfg!(feature = "llvm-libunwind")
         && ((target.contains("linux") && !target.contains("musl")) || target.contains("fuchsia"))
     {
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index b8bae69d063..6d2d7bbbef9 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -393,7 +393,7 @@ class RustBuild(object):
 
         if self.rustc().startswith(self.bin_root()) and \
                 (not os.path.exists(self.rustc()) or
-                 self.program_out_of_date(self.rustc_stamp())):
+                 self.program_out_of_date(self.rustc_stamp(), self.date)):
             if os.path.exists(self.bin_root()):
                 shutil.rmtree(self.bin_root())
             tarball_suffix = '.tar.xz' if support_xz() else '.tar.gz'
@@ -413,7 +413,7 @@ class RustBuild(object):
             lib_dir = "{}/lib".format(self.bin_root())
             for lib in os.listdir(lib_dir):
                 if lib.endswith(".so"):
-                    self.fix_bin_or_dylib("{}/{}".format(lib_dir, lib))
+                    self.fix_bin_or_dylib(os.path.join(lib_dir, lib), rpath_libz=True)
             with output(self.rustc_stamp()) as rust_stamp:
                 rust_stamp.write(self.date)
 
@@ -429,7 +429,7 @@ class RustBuild(object):
                 self.fix_bin_or_dylib("{}/bin/rustfmt".format(self.bin_root()))
                 self.fix_bin_or_dylib("{}/bin/cargo-fmt".format(self.bin_root()))
                 with output(self.rustfmt_stamp()) as rustfmt_stamp:
-                    rustfmt_stamp.write(self.date + self.rustfmt_channel)
+                    rustfmt_stamp.write(self.rustfmt_channel)
 
         if self.downloading_llvm():
             # We want the most recent LLVM submodule update to avoid downloading
@@ -451,12 +451,17 @@ class RustBuild(object):
                 "{}/src/bootstrap/download-ci-llvm-stamp".format(top_level),
             ]).decode(sys.getdefaultencoding()).strip()
             llvm_assertions = self.get_toml('assertions', 'llvm') == 'true'
+            llvm_root = self.llvm_root()
+            llvm_lib = os.path.join(llvm_root, "lib")
             if self.program_out_of_date(self.llvm_stamp(), llvm_sha + str(llvm_assertions)):
                 self._download_ci_llvm(llvm_sha, llvm_assertions)
                 for binary in ["llvm-config", "FileCheck"]:
-                    self.fix_bin_or_dylib("{}/bin/{}".format(self.llvm_root(), binary))
+                    self.fix_bin_or_dylib(os.path.join(llvm_root, "bin", binary), rpath_libz=True)
+                for lib in os.listdir(llvm_lib):
+                    if lib.endswith(".so"):
+                        self.fix_bin_or_dylib(os.path.join(llvm_lib, lib), rpath_libz=True)
                 with output(self.llvm_stamp()) as llvm_stamp:
-                    llvm_stamp.write(self.date + llvm_sha + str(llvm_assertions))
+                    llvm_stamp.write(llvm_sha + str(llvm_assertions))
 
     def downloading_llvm(self):
         opt = self.get_toml('download-ci-llvm', 'llvm')
@@ -487,7 +492,12 @@ class RustBuild(object):
         url = "https://ci-artifacts.rust-lang.org/rustc-builds/{}".format(llvm_sha)
         if llvm_assertions:
             url = url.replace('rustc-builds', 'rustc-builds-alt')
-        tarball_suffix = '.tar.xz' if support_xz() else '.tar.gz'
+        # ci-artifacts are only stored as .xz, not .gz
+        if not support_xz():
+            print("error: XZ support is required to download LLVM")
+            print("help: consider disabling `download-ci-llvm` or using python3")
+            exit(1)
+        tarball_suffix = '.tar.xz'
         filename = "rust-dev-nightly-" + self.build + tarball_suffix
         tarball = os.path.join(rustc_cache, filename)
         if not os.path.exists(tarball):
@@ -496,7 +506,7 @@ class RustBuild(object):
                 match="rust-dev",
                 verbose=self.verbose)
 
-    def fix_bin_or_dylib(self, fname):
+    def fix_bin_or_dylib(self, fname, rpath_libz=False):
         """Modifies the interpreter section of 'fname' to fix the dynamic linker,
         or the RPATH section, to fix the dynamic library search path
 
@@ -566,20 +576,22 @@ class RustBuild(object):
             self.nix_deps_dir = nix_deps_dir
 
         patchelf = "{}/patchelf/bin/patchelf".format(nix_deps_dir)
+        patchelf_args = []
 
-        if fname.endswith(".so"):
-            # Dynamic library, patch RPATH to point to system dependencies.
+        if rpath_libz:
+            # Patch RPATH to add `zlib` dependency that stems from LLVM
             dylib_deps = ["zlib"]
             rpath_entries = [
                 # Relative default, all binary and dynamic libraries we ship
                 # appear to have this (even when `../lib` is redundant).
                 "$ORIGIN/../lib",
             ] + ["{}/{}/lib".format(nix_deps_dir, dep) for dep in dylib_deps]
-            patchelf_args = ["--set-rpath", ":".join(rpath_entries)]
-        else:
+            patchelf_args += ["--set-rpath", ":".join(rpath_entries)]
+        if not fname.endswith(".so"):
+            # Finally, set the corret .interp for binaries
             bintools_dir = "{}/stdenv.cc.bintools".format(nix_deps_dir)
             with open("{}/nix-support/dynamic-linker".format(bintools_dir)) as dynamic_linker:
-                patchelf_args = ["--set-interpreter", dynamic_linker.read().rstrip()]
+                patchelf_args += ["--set-interpreter", dynamic_linker.read().rstrip()]
 
         try:
             subprocess.check_output([patchelf] + patchelf_args + [fname])
@@ -618,12 +630,12 @@ class RustBuild(object):
         return os.path.join(self.llvm_root(), '.llvm-stamp')
 
 
-    def program_out_of_date(self, stamp_path, extra=""):
+    def program_out_of_date(self, stamp_path, key):
         """Check if the given program stamp is out of date"""
         if not os.path.exists(stamp_path) or self.clean:
             return True
         with open(stamp_path, 'r') as stamp:
-            return (self.date + extra) != stamp.read()
+            return key != stamp.read()
 
     def bin_root(self):
         """Return the binary root directory
diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py
index 0e941e13676..61507114159 100644
--- a/src/bootstrap/bootstrap_test.py
+++ b/src/bootstrap/bootstrap_test.py
@@ -70,6 +70,7 @@ class ProgramOutOfDate(unittest.TestCase):
         self.build.build_dir = self.container
         self.rustc_stamp_path = os.path.join(self.container, "stage0",
                                              ".rustc-stamp")
+        self.key = self.build.date + str(None)
 
     def tearDown(self):
         rmtree(self.container)
@@ -78,19 +79,19 @@ class ProgramOutOfDate(unittest.TestCase):
         """Return True when the stamp file does not exists"""
         if os.path.exists(self.rustc_stamp_path):
             os.unlink(self.rustc_stamp_path)
-        self.assertTrue(self.build.program_out_of_date(self.rustc_stamp_path))
+        self.assertTrue(self.build.program_out_of_date(self.rustc_stamp_path, self.key))
 
     def test_dates_are_different(self):
         """Return True when the dates are different"""
         with open(self.rustc_stamp_path, "w") as rustc_stamp:
-            rustc_stamp.write("2017-06-14")
-        self.assertTrue(self.build.program_out_of_date(self.rustc_stamp_path))
+            rustc_stamp.write("2017-06-14None")
+        self.assertTrue(self.build.program_out_of_date(self.rustc_stamp_path, self.key))
 
     def test_same_dates(self):
         """Return False both dates match"""
         with open(self.rustc_stamp_path, "w") as rustc_stamp:
-            rustc_stamp.write("2017-06-15")
-        self.assertFalse(self.build.program_out_of_date(self.rustc_stamp_path))
+            rustc_stamp.write("2017-06-15None")
+        self.assertFalse(self.build.program_out_of_date(self.rustc_stamp_path, self.key))
 
 
 if __name__ == '__main__':
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index c2abb01fa8c..ec9ce4c820c 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -1534,7 +1534,7 @@ impl Rustflags {
     fn arg(&mut self, arg: &str) -> &mut Self {
         assert_eq!(arg.split(' ').count(), 1);
         if !self.0.is_empty() {
-            self.0.push_str(" ");
+            self.0.push(' ');
         }
         self.0.push_str(arg);
         self
diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs
index 2b82f6c30b2..6e65be93fec 100644
--- a/src/bootstrap/channel.rs
+++ b/src/bootstrap/channel.rs
@@ -74,9 +74,9 @@ impl GitInfo {
         if let Some(ref inner) = self.inner {
             version.push_str(" (");
             version.push_str(&inner.short_sha);
-            version.push_str(" ");
+            version.push(' ');
             version.push_str(&inner.commit_date);
-            version.push_str(")");
+            version.push(')');
         }
         version
     }
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index f65b2b2c79f..72a979338a5 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -21,6 +21,16 @@ fn args(builder: &Builder<'_>) -> Vec<String> {
     }
 
     if let Subcommand::Clippy { fix, .. } = builder.config.cmd {
+        // disable the most spammy clippy lints
+        let ignored_lints = vec![
+            "many_single_char_names", // there are a lot in stdarch
+            "collapsible_if",
+            "type_complexity",
+            "missing_safety_doc", // almost 3K warnings
+            "too_many_arguments",
+            "needless_lifetimes", // people want to keep the lifetimes
+            "wrong_self_convention",
+        ];
         let mut args = vec![];
         if fix {
             #[rustfmt::skip]
@@ -33,6 +43,7 @@ fn args(builder: &Builder<'_>) -> Vec<String> {
             ]));
         }
         args.extend(strings(&["--", "--cap-lints", "warn"]));
+        args.extend(ignored_lints.iter().map(|lint| format!("-Aclippy::{}", lint)));
         args
     } else {
         vec![]
diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs
index f83dfe8e635..9b9df36e7dc 100644
--- a/src/bootstrap/clean.rs
+++ b/src/bootstrap/clean.rs
@@ -21,6 +21,7 @@ pub fn clean(build: &Build, all: bool) {
     } else {
         rm_rf(&build.out.join("tmp"));
         rm_rf(&build.out.join("dist"));
+        rm_rf(&build.out.join("bootstrap"));
 
         for host in &build.hosts {
             let entries = match build.out.join(host.triple).read_dir() {
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 2707a640457..39700c087a2 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -188,14 +188,16 @@ fn copy_self_contained_objects(
         }
     } else if target.ends_with("-wasi") {
         let srcdir = builder.wasi_root(target).unwrap().join("lib/wasm32-wasi");
-        copy_and_stamp(
-            builder,
-            &libdir_self_contained,
-            &srcdir,
-            "crt1.o",
-            &mut target_deps,
-            DependencyType::TargetSelfContained,
-        );
+        for &obj in &["crt1.o", "crt1-reactor.o"] {
+            copy_and_stamp(
+                builder,
+                &libdir_self_contained,
+                &srcdir,
+                obj,
+                &mut target_deps,
+                DependencyType::TargetSelfContained,
+            );
+        }
     } else if target.contains("windows-gnu") {
         for obj in ["crt2.o", "dllcrt2.o"].iter() {
             let src = compiler_file(builder, builder.cc(target), target, obj);
@@ -356,15 +358,12 @@ fn copy_sanitizers(
         let dst = libdir.join(&runtime.name);
         builder.copy(&runtime.path, &dst);
 
-        if target == "x86_64-apple-darwin" {
-            // Update the library install name reflect the fact it has been renamed.
-            let status = Command::new("install_name_tool")
-                .arg("-id")
-                .arg(format!("@rpath/{}", runtime.name))
-                .arg(&dst)
-                .status()
-                .expect("failed to execute `install_name_tool`");
-            assert!(status.success());
+        if target == "x86_64-apple-darwin" || target == "aarch64-apple-darwin" {
+            // Update the library’s install name to reflect that it has has been renamed.
+            apple_darwin_update_library_name(&dst, &format!("@rpath/{}", &runtime.name));
+            // Upon renaming the install name, the code signature of the file will invalidate,
+            // so we will sign it again.
+            apple_darwin_sign_file(&dst);
         }
 
         target_deps.push(dst);
@@ -373,6 +372,27 @@ fn copy_sanitizers(
     target_deps
 }
 
+fn apple_darwin_update_library_name(library_path: &Path, new_name: &str) {
+    let status = Command::new("install_name_tool")
+        .arg("-id")
+        .arg(new_name)
+        .arg(library_path)
+        .status()
+        .expect("failed to execute `install_name_tool`");
+    assert!(status.success());
+}
+
+fn apple_darwin_sign_file(file_path: &Path) {
+    let status = Command::new("codesign")
+        .arg("-f") // Force to rewrite the existing signature
+        .arg("-s")
+        .arg("-")
+        .arg(file_path)
+        .status()
+        .expect("failed to execute `codesign`");
+    assert!(status.success());
+}
+
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct StartupObjects {
     pub compiler: Compiler,
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index daec1656b27..e2c2e19b0bc 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -1326,17 +1326,17 @@ impl Step for Extended {
         license += &builder.read(&builder.src.join("COPYRIGHT"));
         license += &builder.read(&builder.src.join("LICENSE-APACHE"));
         license += &builder.read(&builder.src.join("LICENSE-MIT"));
-        license.push_str("\n");
-        license.push_str("\n");
+        license.push('\n');
+        license.push('\n');
 
         let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18";
         let mut rtf = rtf.to_string();
-        rtf.push_str("\n");
+        rtf.push('\n');
         for line in license.lines() {
             rtf.push_str(line);
             rtf.push_str("\\line ");
         }
-        rtf.push_str("}");
+        rtf.push('}');
 
         fn filter(contents: &str, marker: &str) -> String {
             let start = format!("tool-{}-start", marker);
diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs
index 96164947943..fd0acc3a919 100644
--- a/src/bootstrap/install.rs
+++ b/src/bootstrap/install.rs
@@ -5,7 +5,7 @@
 
 use std::env;
 use std::fs;
-use std::path::{Component, Path, PathBuf};
+use std::path::{Component, PathBuf};
 use std::process::Command;
 
 use build_helper::t;
@@ -26,74 +26,63 @@ fn install_sh(
 ) {
     builder.info(&format!("Install {} stage{} ({:?})", package, stage, host));
 
-    let prefix_default = PathBuf::from("/usr/local");
-    let sysconfdir_default = PathBuf::from("/etc");
-    let datadir_default = PathBuf::from("share");
-    let docdir_default = datadir_default.join("doc/rust");
-    let libdir_default = PathBuf::from("lib");
-    let mandir_default = datadir_default.join("man");
-    let prefix = builder.config.prefix.as_ref().unwrap_or(&prefix_default);
-    let sysconfdir = builder.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default);
-    let datadir = builder.config.datadir.as_ref().unwrap_or(&datadir_default);
-    let docdir = builder.config.docdir.as_ref().unwrap_or(&docdir_default);
-    let bindir = &builder.config.bindir;
-    let libdir = builder.config.libdir.as_ref().unwrap_or(&libdir_default);
-    let mandir = builder.config.mandir.as_ref().unwrap_or(&mandir_default);
-
-    let sysconfdir = prefix.join(sysconfdir);
-    let datadir = prefix.join(datadir);
-    let docdir = prefix.join(docdir);
-    let bindir = prefix.join(bindir);
-    let libdir = prefix.join(libdir);
-    let mandir = prefix.join(mandir);
-
-    let destdir = env::var_os("DESTDIR").map(PathBuf::from);
-
-    let prefix = add_destdir(&prefix, &destdir);
-    let sysconfdir = add_destdir(&sysconfdir, &destdir);
-    let datadir = add_destdir(&datadir, &destdir);
-    let docdir = add_destdir(&docdir, &destdir);
-    let bindir = add_destdir(&bindir, &destdir);
-    let libdir = add_destdir(&libdir, &destdir);
-    let mandir = add_destdir(&mandir, &destdir);
-
-    let prefix = {
-        fs::create_dir_all(&prefix)
-            .unwrap_or_else(|err| panic!("could not create {}: {}", prefix.display(), err));
-        fs::canonicalize(&prefix)
-            .unwrap_or_else(|err| panic!("could not canonicalize {}: {}", prefix.display(), err))
-    };
+    let prefix = default_path(&builder.config.prefix, "/usr/local");
+    let sysconfdir = prefix.join(default_path(&builder.config.sysconfdir, "/etc"));
+    let datadir = prefix.join(default_path(&builder.config.datadir, "share"));
+    let docdir = prefix.join(default_path(&builder.config.docdir, "share/doc"));
+    let mandir = prefix.join(default_path(&builder.config.mandir, "share/man"));
+    let libdir = prefix.join(default_path(&builder.config.libdir, "lib"));
+    let bindir = prefix.join(&builder.config.bindir); // Default in config.rs
 
     let empty_dir = builder.out.join("tmp/empty_dir");
-
     t!(fs::create_dir_all(&empty_dir));
 
     let mut cmd = Command::new("sh");
     cmd.current_dir(&empty_dir)
         .arg(sanitize_sh(&tarball.decompressed_output().join("install.sh")))
-        .arg(format!("--prefix={}", sanitize_sh(&prefix)))
-        .arg(format!("--sysconfdir={}", sanitize_sh(&sysconfdir)))
-        .arg(format!("--datadir={}", sanitize_sh(&datadir)))
-        .arg(format!("--docdir={}", sanitize_sh(&docdir)))
-        .arg(format!("--bindir={}", sanitize_sh(&bindir)))
-        .arg(format!("--libdir={}", sanitize_sh(&libdir)))
-        .arg(format!("--mandir={}", sanitize_sh(&mandir)))
+        .arg(format!("--prefix={}", prepare_dir(prefix)))
+        .arg(format!("--sysconfdir={}", prepare_dir(sysconfdir)))
+        .arg(format!("--datadir={}", prepare_dir(datadir)))
+        .arg(format!("--docdir={}", prepare_dir(docdir)))
+        .arg(format!("--bindir={}", prepare_dir(bindir)))
+        .arg(format!("--libdir={}", prepare_dir(libdir)))
+        .arg(format!("--mandir={}", prepare_dir(mandir)))
         .arg("--disable-ldconfig");
     builder.run(&mut cmd);
     t!(fs::remove_dir_all(&empty_dir));
 }
 
-fn add_destdir(path: &Path, destdir: &Option<PathBuf>) -> PathBuf {
-    let mut ret = match *destdir {
-        Some(ref dest) => dest.clone(),
-        None => return path.to_path_buf(),
-    };
-    for part in path.components() {
-        if let Component::Normal(s) = part {
-            ret.push(s)
+fn default_path(config: &Option<PathBuf>, default: &str) -> PathBuf {
+    PathBuf::from(config.as_ref().cloned().unwrap_or_else(|| PathBuf::from(default)))
+}
+
+fn prepare_dir(mut path: PathBuf) -> String {
+    // The DESTDIR environment variable is a standard way to install software in a subdirectory
+    // while keeping the original directory structure, even if the prefix or other directories
+    // contain absolute paths.
+    //
+    // More information on the environment variable is available here:
+    // https://www.gnu.org/prep/standards/html_node/DESTDIR.html
+    if let Some(destdir) = env::var_os("DESTDIR").map(PathBuf::from) {
+        let without_destdir = path.clone();
+        path = destdir;
+        // Custom .join() which ignores disk roots.
+        for part in without_destdir.components() {
+            if let Component::Normal(s) = part {
+                path.push(s)
+            }
         }
     }
-    ret
+
+    // The installation command is not executed from the current directory, but from a temporary
+    // directory. To prevent relative paths from breaking this converts relative paths to absolute
+    // paths. std::fs::canonicalize is not used as that requires the path to actually be present.
+    if path.is_relative() {
+        path = std::env::current_dir().expect("failed to get the current directory").join(path);
+        assert!(path.is_absolute(), "could not make the path relative");
+    }
+
+    sanitize_sh(&path)
 }
 
 macro_rules! install {
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index a47ddfbcc1f..88fdcfa2d43 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -1083,7 +1083,7 @@ impl Build {
         if let Some(ref s) = self.config.description {
             version.push_str(" (");
             version.push_str(s);
-            version.push_str(")");
+            version.push(')');
         }
         version
     }
@@ -1144,7 +1144,7 @@ impl Build {
                     && (dep != "profiler_builtins"
                         || target
                             .map(|t| self.config.profiler_enabled(t))
-                            .unwrap_or(self.config.any_profiler_enabled()))
+                            .unwrap_or_else(|| self.config.any_profiler_enabled()))
                     && (dep != "rustc_codegen_llvm" || self.config.llvm_enabled())
                 {
                     list.push(*dep);
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index d716b23af60..6412df3fd90 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -802,6 +802,7 @@ fn supported_sanitizers(
     };
 
     match &*target.triple {
+        "aarch64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
         "aarch64-fuchsia" => common_libs("fuchsia", "aarch64", &["asan"]),
         "aarch64-unknown-linux-gnu" => {
             common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan"])
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index acb941d9540..08acc3d671f 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -163,7 +163,11 @@ pub fn check(build: &mut Build) {
             panic!("the iOS target is only supported on macOS");
         }
 
-        build.config.target_config.entry(*target).or_insert(Target::from_triple(&target.triple));
+        build
+            .config
+            .target_config
+            .entry(*target)
+            .or_insert_with(|| Target::from_triple(&target.triple));
 
         if target.contains("-none-") || target.contains("nvptx") {
             if build.no_std(*target) == Some(false) {
diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs
index 2d4484c562c..725147767db 100644
--- a/src/bootstrap/setup.rs
+++ b/src/bootstrap/setup.rs
@@ -89,7 +89,7 @@ pub fn setup(src_path: &Path, profile: Profile) {
         std::process::exit(1);
     }
 
-    let path = cfg_file.unwrap_or("config.toml".into());
+    let path = cfg_file.unwrap_or_else(|| "config.toml".into());
     let settings = format!(
         "# Includes one of the default files in src/bootstrap/defaults\n\
     profile = \"{}\"\n\
@@ -156,7 +156,7 @@ pub fn interactive_path() -> io::Result<Profile> {
         io::stdout().flush()?;
         let mut input = String::new();
         io::stdin().read_line(&mut input)?;
-        if input == "" {
+        if input.is_empty() {
             eprintln!("EOF on stdin, when expecting answer to question.  Giving up.");
             std::process::exit(1);
         }
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 33e252a63c9..2e8c574044e 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1126,7 +1126,19 @@ note: if you're sure you want to do this, please open an issue as to why. In the
                 Ok(path) => path,
                 Err(_) => p,
             })
-            .filter(|p| p.starts_with(suite_path) && (p.is_dir() || p.is_file()))
+            .filter(|p| p.starts_with(suite_path))
+            .filter(|p| {
+                let exists = p.is_dir() || p.is_file();
+                if !exists {
+                    if let Some(p) = p.to_str() {
+                        builder.info(&format!(
+                            "Warning: Skipping \"{}\": not a regular file or directory",
+                            p
+                        ));
+                    }
+                }
+                exists
+            })
             .filter_map(|p| {
                 // Since test suite paths are themselves directories, if we don't
                 // specify a directory or file, we'll get an empty string here
@@ -1135,7 +1147,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
                 // flag is respected, so providing an empty --test-args conflicts with
                 // any following it.
                 match p.strip_prefix(suite_path).ok().and_then(|p| p.to_str()) {
-                    Some(s) if s != "" => Some(s),
+                    Some(s) if !s.is_empty() => Some(s),
                     _ => None,
                 }
             })
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
index 93908e9190e..d03d5c75014 100644
--- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -31,7 +31,12 @@ with runtime flag `ASAN_OPTIONS=detect_leaks=1` on macOS.
 
 AddressSanitizer is supported on the following targets:
 
+* `aarch64-apple-darwin`
+* `aarch64-fuchsia`
+* `aarch64-unknown-linux-gnu`
 * `x86_64-apple-darwin`
+* `x86_64-fuchsia`
+* `x86_64-unknown-freebsd`
 * `x86_64-unknown-linux-gnu`
 
 AddressSanitizer works with non-instrumented code although it will impede its
@@ -169,10 +174,26 @@ Shadow byte legend (one shadow byte represents 8 application bytes):
 ==39249==ABORTING
 ```
 
+# LeakSanitizer
+
+LeakSanitizer is run-time memory leak detector.
+
+LeakSanitizer is supported on the following targets:
+
+* `aarch64-apple-darwin`
+* `aarch64-unknown-linux-gnu`
+* `x86_64-apple-darwin`
+* `x86_64-unknown-linux-gnu`
+
 # MemorySanitizer
 
-MemorySanitizer is detector of uninitialized reads. It is only supported on the
-`x86_64-unknown-linux-gnu` target.
+MemorySanitizer is detector of uninitialized reads.
+
+MemorySanitizer is supported on the following targets:
+
+* `aarch64-unknown-linux-gnu`
+* `x86_64-unknown-freebsd`
+* `x86_64-unknown-linux-gnu`
 
 MemorySanitizer requires all program code to be instrumented. C/C++ dependencies
 need to be recompiled using Clang with `-fsanitize=memory` option. Failing to
@@ -219,7 +240,10 @@ $ cargo run -Zbuild-std --target x86_64-unknown-linux-gnu
 ThreadSanitizer is a data race detection tool. It is supported on the following
 targets:
 
+* `aarch64-apple-darwin`
+* `aarch64-unknown-linux-gnu`
 * `x86_64-apple-darwin`
+* `x86_64-unknown-freebsd`
 * `x86_64-unknown-linux-gnu`
 
 To work correctly ThreadSanitizer needs to be "aware" of all synchronization
diff --git a/src/doc/unstable-book/src/compiler-flags/source-based-code-coverage.md b/src/doc/unstable-book/src/compiler-flags/source-based-code-coverage.md
index 98bcadd12ee..8aca0052147 100644
--- a/src/doc/unstable-book/src/compiler-flags/source-based-code-coverage.md
+++ b/src/doc/unstable-book/src/compiler-flags/source-based-code-coverage.md
@@ -123,7 +123,7 @@ The `rustup` option is guaranteed to install a compatible version of the LLVM to
 ```shell
 $ rustup component add llvm-tools-preview
 $ cargo install cargo-binutils
-$ cargo profdata -- --help  # note the additional "--" preceeding the tool-specific arguments
+$ cargo profdata -- --help  # note the additional "--" preceding the tool-specific arguments
 ```
 
 ## Creating coverage reports
diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py
index 440181a7611..2f7233685db 100644
--- a/src/etc/htmldocck.py
+++ b/src/etc/htmldocck.py
@@ -218,7 +218,7 @@ def concat_multi_lines(f):
 
 
 LINE_PATTERN = re.compile(r'''
-    (?<=(?<!\S)@)(?P<negated>!?)
+    (?<=(?<!\S))(?P<invalid>!?)@(?P<negated>!?)
     (?P<cmd>[A-Za-z]+(?:-[A-Za-z]+)*)
     (?P<args>.*)$
 ''', re.X | re.UNICODE)
@@ -233,6 +233,16 @@ def get_commands(template):
 
             negated = (m.group('negated') == '!')
             cmd = m.group('cmd')
+            if m.group('invalid') == '!':
+                print_err(
+                    lineno,
+                    line,
+                    'Invalid command: `!@{0}{1}`, (help: try with `@!{1}`)'.format(
+                        '!' if negated else '',
+                        cmd,
+                    ),
+                )
+                continue
             args = m.group('args')
             if args and not args[:1].isspace():
                 print_err(lineno, line, 'Invalid template syntax')
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 2a8b6a321f1..43fb53ba18f 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -84,14 +84,14 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                         new_generics
                     });
 
-                let polarity;
+                let negative_polarity;
                 let new_generics = match result {
                     AutoTraitResult::PositiveImpl(new_generics) => {
-                        polarity = None;
+                        negative_polarity = false;
                         new_generics
                     }
                     AutoTraitResult::NegativeImpl => {
-                        polarity = Some(ImplPolarity::Negative);
+                        negative_polarity = true;
 
                         // For negative impls, we use the generic params, but *not* the predicates,
                         // from the original type. Otherwise, the displayed impl appears to be a
@@ -130,7 +130,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                         trait_: Some(trait_ref.clean(self.cx).get_trait_type().unwrap()),
                         for_: ty.clean(self.cx),
                         items: Vec::new(),
-                        polarity,
+                        negative_polarity,
                         synthetic: true,
                         blanket_impl: None,
                     }),
@@ -351,8 +351,8 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                 if let Some(data) = ty_to_fn.get(&ty) {
                     let (poly_trait, output) =
                         (data.0.as_ref().expect("as_ref failed").clone(), data.1.as_ref().cloned());
-                    let new_ty = match &poly_trait.trait_ {
-                        &Type::ResolvedPath {
+                    let new_ty = match poly_trait.trait_ {
+                        Type::ResolvedPath {
                             ref path,
                             ref param_names,
                             ref did,
@@ -738,11 +738,11 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
     }
 
     fn is_fn_ty(&self, tcx: TyCtxt<'_>, ty: &Type) -> bool {
-        match &ty {
-            &&Type::ResolvedPath { ref did, .. } => {
-                *did == tcx.require_lang_item(LangItem::Fn, None)
-                    || *did == tcx.require_lang_item(LangItem::FnMut, None)
-                    || *did == tcx.require_lang_item(LangItem::FnOnce, None)
+        match ty {
+            &Type::ResolvedPath { did, .. } => {
+                did == tcx.require_lang_item(LangItem::Fn, None)
+                    || did == tcx.require_lang_item(LangItem::FnMut, None)
+                    || did == tcx.require_lang_item(LangItem::FnOnce, None)
             }
             _ => false,
         }
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index ba3eb007e38..f1c26feea46 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -131,7 +131,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                             .in_definition_order()
                             .collect::<Vec<_>>()
                             .clean(self.cx),
-                        polarity: None,
+                        negative_polarity: false,
                         synthetic: false,
                         blanket_impl: Some(trait_ref.self_ty().clean(self.cx)),
                     }),
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index 2f169d1d3f3..444b73246da 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -177,10 +177,7 @@ impl Cfg {
             Cfg::Any(ref sub_cfgs) | Cfg::All(ref sub_cfgs) => {
                 sub_cfgs.first().map(Cfg::should_capitalize_first_letter).unwrap_or(false)
             }
-            Cfg::Cfg(name, _) => match name {
-                sym::debug_assertions | sym::target_endian => true,
-                _ => false,
-            },
+            Cfg::Cfg(name, _) => name == sym::debug_assertions || name == sym::target_endian,
         }
     }
 
@@ -188,18 +185,13 @@ impl Cfg {
         match *self {
             Cfg::False | Cfg::True => false,
             Cfg::Any(..) | Cfg::All(..) | Cfg::Cfg(..) => true,
-            Cfg::Not(ref child) => match **child {
-                Cfg::Cfg(..) => true,
-                _ => false,
-            },
+            Cfg::Not(box Cfg::Cfg(..)) => true,
+            Cfg::Not(..) => false,
         }
     }
 
     fn should_use_with_in_description(&self) -> bool {
-        match *self {
-            Cfg::Cfg(name, _) if name == sym::target_feature => true,
-            _ => false,
-        }
+        matches!(self, Cfg::Cfg(sym::target_feature, _))
     }
 
     /// Attempt to simplify this cfg by assuming that `assume` is already known to be true, will
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index c168c56d30d..4c46771fd71 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -169,7 +169,17 @@ crate fn record_extern_fqn(cx: &DocContext<'_>, did: DefId, kind: clean::TypeKin
         if !s.is_empty() { Some(s) } else { None }
     });
     let fqn = if let clean::TypeKind::Macro = kind {
-        vec![crate_name, relative.last().expect("relative was empty")]
+        // Check to see if it is a macro 2.0 or built-in macro
+        if matches!(
+            cx.enter_resolver(|r| r.cstore().load_macro_untracked(did, cx.sess())),
+            LoadedMacro::MacroDef(def, _)
+                if matches!(&def.kind, ast::ItemKind::MacroDef(ast_def)
+                    if !ast_def.macro_rules)
+        ) {
+            once(crate_name).chain(relative).collect()
+        } else {
+            vec![crate_name, relative.last().expect("relative was empty")]
+        }
     } else {
         once(crate_name).chain(relative).collect()
     };
@@ -261,26 +271,12 @@ fn build_union(cx: &DocContext<'_>, did: DefId) -> clean::Union {
 
 fn build_type_alias(cx: &DocContext<'_>, did: DefId) -> clean::Typedef {
     let predicates = cx.tcx.explicit_predicates_of(did);
+    let type_ = cx.tcx.type_of(did).clean(cx);
 
     clean::Typedef {
-        type_: cx.tcx.type_of(did).clean(cx),
+        type_,
         generics: (cx.tcx.generics_of(did), predicates).clean(cx),
-        item_type: build_type_alias_type(cx, did),
-    }
-}
-
-fn build_type_alias_type(cx: &DocContext<'_>, did: DefId) -> Option<clean::Type> {
-    let type_ = cx.tcx.type_of(did).clean(cx);
-    type_.def_id().and_then(|did| build_ty(cx, did))
-}
-
-crate fn build_ty(cx: &DocContext<'_>, did: DefId) -> Option<clean::Type> {
-    match cx.tcx.def_kind(did) {
-        DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::Const | DefKind::Static => {
-            Some(cx.tcx.type_of(did).clean(cx))
-        }
-        DefKind::TyAlias => build_type_alias_type(cx, did),
-        _ => None,
+        item_type: None,
     }
 }
 
@@ -442,7 +438,7 @@ crate fn build_impl(
             trait_,
             for_,
             items: trait_items,
-            polarity: Some(polarity.clean(cx)),
+            negative_polarity: polarity.clean(cx),
             synthetic: false,
             blanket_impl: None,
         }),
@@ -455,60 +451,51 @@ crate fn build_impl(
 
 fn build_module(cx: &DocContext<'_>, did: DefId, visited: &mut FxHashSet<DefId>) -> clean::Module {
     let mut items = Vec::new();
-    fill_in(cx, did, &mut items, visited);
-    return clean::Module { items, is_crate: false };
-
-    fn fill_in(
-        cx: &DocContext<'_>,
-        did: DefId,
-        items: &mut Vec<clean::Item>,
-        visited: &mut FxHashSet<DefId>,
-    ) {
-        // If we're re-exporting a re-export it may actually re-export something in
-        // two namespaces, so the target may be listed twice. Make sure we only
-        // visit each node at most once.
-        for &item in cx.tcx.item_children(did).iter() {
-            if item.vis == ty::Visibility::Public {
-                if let Some(def_id) = item.res.mod_def_id() {
-                    if did == def_id || !visited.insert(def_id) {
-                        continue;
-                    }
+
+    // If we're re-exporting a re-export it may actually re-export something in
+    // two namespaces, so the target may be listed twice. Make sure we only
+    // visit each node at most once.
+    for &item in cx.tcx.item_children(did).iter() {
+        if item.vis == ty::Visibility::Public {
+            if let Some(def_id) = item.res.mod_def_id() {
+                if did == def_id || !visited.insert(def_id) {
+                    continue;
                 }
-                if let Res::PrimTy(p) = item.res {
-                    // Primitive types can't be inlined so generate an import instead.
-                    items.push(clean::Item {
-                        name: None,
-                        attrs: clean::Attributes::default(),
-                        source: clean::Span::dummy(),
-                        def_id: DefId::local(CRATE_DEF_INDEX),
-                        visibility: clean::Public,
-                        kind: box clean::ImportItem(clean::Import::new_simple(
-                            item.ident.name,
-                            clean::ImportSource {
-                                path: clean::Path {
-                                    global: false,
-                                    res: item.res,
-                                    segments: vec![clean::PathSegment {
-                                        name: clean::PrimitiveType::from(p).as_sym(),
-                                        args: clean::GenericArgs::AngleBracketed {
-                                            args: Vec::new(),
-                                            bindings: Vec::new(),
-                                        },
-                                    }],
-                                },
-                                did: None,
+            }
+            if let Res::PrimTy(p) = item.res {
+                // Primitive types can't be inlined so generate an import instead.
+                items.push(clean::Item {
+                    name: None,
+                    attrs: clean::Attributes::default(),
+                    source: clean::Span::dummy(),
+                    def_id: DefId::local(CRATE_DEF_INDEX),
+                    visibility: clean::Public,
+                    kind: box clean::ImportItem(clean::Import::new_simple(
+                        item.ident.name,
+                        clean::ImportSource {
+                            path: clean::Path {
+                                global: false,
+                                res: item.res,
+                                segments: vec![clean::PathSegment {
+                                    name: clean::PrimitiveType::from(p).as_sym(),
+                                    args: clean::GenericArgs::AngleBracketed {
+                                        args: Vec::new(),
+                                        bindings: Vec::new(),
+                                    },
+                                }],
                             },
-                            true,
-                        )),
-                    });
-                } else if let Some(i) =
-                    try_inline(cx, did, item.res, item.ident.name, None, visited)
-                {
-                    items.extend(i)
-                }
+                            did: None,
+                        },
+                        true,
+                    )),
+                });
+            } else if let Some(i) = try_inline(cx, did, item.res, item.ident.name, None, visited) {
+                items.extend(i)
             }
         }
     }
+
+    clean::Module { items, is_crate: false }
 }
 
 crate fn print_inlined_const(cx: &DocContext<'_>, did: DefId) -> String {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 2f430842f9d..14564e7f64a 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -640,10 +640,10 @@ impl Clean<Generics> for hir::Generics<'_> {
         ///
         /// [`lifetime_to_generic_param`]: rustc_ast_lowering::LoweringContext::lifetime_to_generic_param
         fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool {
-            match param.kind {
-                hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided } => true,
-                _ => false,
-            }
+            matches!(
+                param.kind,
+                hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided }
+            )
         }
 
         let impl_trait_params = self
@@ -801,7 +801,7 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx
 
         for (param, mut bounds) in impl_trait {
             // Move trait bounds to the front.
-            bounds.sort_by_key(|b| if let GenericBound::TraitBound(..) = b { false } else { true });
+            bounds.sort_by_key(|b| !matches!(b, GenericBound::TraitBound(..)));
 
             if let crate::core::ImplTraitParam::ParamIndex(idx) = param {
                 if let Some(proj) = impl_trait_proj.remove(&idx) {
@@ -942,7 +942,7 @@ impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], &'a [Ident]) {
                 .iter()
                 .enumerate()
                 .map(|(i, ty)| {
-                    let mut name = self.1.get(i).map(|ident| ident.name).unwrap_or(kw::Empty);
+                    let mut name = self.1.get(i).map_or(kw::Empty, |ident| ident.name);
                     if name.is_empty() {
                         name = kw::Underscore;
                     }
@@ -963,7 +963,7 @@ impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], hir::BodyId) {
                 .iter()
                 .enumerate()
                 .map(|(i, ty)| Argument {
-                    name: name_from_pat(&body.params[i].pat),
+                    name: Symbol::intern(&rustc_hir_pretty::param_to_string(&body.params[i])),
                     type_: ty.clean(cx),
                 })
                 .collect(),
@@ -1001,7 +1001,7 @@ impl<'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
                     .iter()
                     .map(|t| Argument {
                         type_: t.clean(cx),
-                        name: names.next().map(|i| i.name).unwrap_or(kw::Empty),
+                        name: names.next().map_or(kw::Empty, |i| i.name),
                     })
                     .collect(),
             },
@@ -1119,10 +1119,17 @@ impl Clean<Item> for hir::ImplItem<'_> {
                     }
                     MethodItem(m, Some(self.defaultness))
                 }
-                hir::ImplItemKind::TyAlias(ref ty) => {
-                    let type_ = ty.clean(cx);
-                    let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
-                    TypedefItem(Typedef { type_, generics: Generics::default(), item_type }, true)
+                hir::ImplItemKind::TyAlias(ref hir_ty) => {
+                    let type_ = hir_ty.clean(cx);
+                    let item_type = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx);
+                    TypedefItem(
+                        Typedef {
+                            type_,
+                            generics: Generics::default(),
+                            item_type: Some(item_type),
+                        },
+                        true,
+                    )
                 }
             };
             Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx)
@@ -1268,13 +1275,13 @@ impl Clean<Item> for ty::AssocItem {
 
                     AssocTypeItem(bounds, ty.clean(cx))
                 } else {
+                    // FIXME: when could this happen? ASsociated items in inherent impls?
                     let type_ = cx.tcx.type_of(self.def_id).clean(cx);
-                    let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
                     TypedefItem(
                         Typedef {
                             type_,
                             generics: Generics { params: Vec::new(), where_predicates: Vec::new() },
-                            item_type,
+                            item_type: None,
                         },
                         true,
                     )
@@ -1987,11 +1994,15 @@ impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Symbol>) {
                     bounds: ty.bounds.clean(cx),
                     generics: ty.generics.clean(cx),
                 }),
-                ItemKind::TyAlias(ty, ref generics) => {
-                    let rustdoc_ty = ty.clean(cx);
-                    let item_type = rustdoc_ty.def_id().and_then(|did| inline::build_ty(cx, did));
+                ItemKind::TyAlias(hir_ty, ref generics) => {
+                    let rustdoc_ty = hir_ty.clean(cx);
+                    let ty = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx);
                     TypedefItem(
-                        Typedef { type_: rustdoc_ty, generics: generics.clean(cx), item_type },
+                        Typedef {
+                            type_: rustdoc_ty,
+                            generics: generics.clean(cx),
+                            item_type: Some(ty),
+                        },
                         false,
                     )
                 }
@@ -2058,13 +2069,14 @@ impl Clean<Item> for hir::Variant<'_> {
     }
 }
 
-impl Clean<ImplPolarity> for ty::ImplPolarity {
-    fn clean(&self, _: &DocContext<'_>) -> ImplPolarity {
+impl Clean<bool> for ty::ImplPolarity {
+    /// Returns whether the impl has negative polarity.
+    fn clean(&self, _: &DocContext<'_>) -> bool {
         match self {
             &ty::ImplPolarity::Positive |
             // FIXME: do we want to do something else here?
-            &ty::ImplPolarity::Reservation => ImplPolarity::Positive,
-            &ty::ImplPolarity::Negative => ImplPolarity::Negative,
+            &ty::ImplPolarity::Reservation => false,
+            &ty::ImplPolarity::Negative => true,
         }
     }
 }
@@ -2105,7 +2117,7 @@ fn clean_impl(impl_: &hir::Item<'_>, cx: &DocContext<'_>) -> Vec<Item> {
             trait_,
             for_,
             items,
-            polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)),
+            negative_polarity: cx.tcx.impl_polarity(def_id).clean(cx),
             synthetic: false,
             blanket_impl: None,
         });
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 0d33bc9afd5..7e567bedc78 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -122,7 +122,7 @@ impl Item {
 
     /// Finds the `doc` attribute as a NameValue and returns the corresponding
     /// value found.
-    crate fn doc_value(&self) -> Option<&str> {
+    crate fn doc_value(&self) -> Option<String> {
         self.attrs.doc_value()
     }
 
@@ -175,11 +175,11 @@ impl Item {
     }
 
     crate fn is_crate(&self) -> bool {
-        match *self.kind {
+        matches!(
+            *self.kind,
             StrippedItem(box ModuleItem(Module { is_crate: true, .. }))
-            | ModuleItem(Module { is_crate: true, .. }) => true,
-            _ => false,
-        }
+                | ModuleItem(Module { is_crate: true, .. })
+        )
     }
     crate fn is_mod(&self) -> bool {
         self.type_() == ItemType::Module
@@ -293,7 +293,9 @@ impl Item {
         }
     }
 
-    /// See comments on next_def_id
+    /// See the documentation for [`next_def_id()`].
+    ///
+    /// [`next_def_id()`]: DocContext::next_def_id()
     crate fn is_fake(&self) -> bool {
         MAX_DEF_ID.with(|m| {
             m.borrow().get(&self.def_id.krate).map(|id| self.def_id >= *id).unwrap_or(false)
@@ -334,6 +336,10 @@ crate enum ItemKind {
     ProcMacroItem(ProcMacro),
     PrimitiveItem(PrimitiveType),
     AssocConstItem(Type, Option<String>),
+    /// An associated item in a trait or trait impl.
+    ///
+    /// The bounds may be non-empty if there is a `where` clause.
+    /// The `Option<Type>` is the default concrete type (e.g. `trait Trait { type Target = usize; }`)
     AssocTypeItem(Vec<GenericBound>, Option<Type>),
     /// An item that has been stripped by a rustdoc pass
     StrippedItem(Box<ItemKind>),
@@ -378,10 +384,7 @@ impl ItemKind {
     }
 
     crate fn is_type_alias(&self) -> bool {
-        match *self {
-            ItemKind::TypedefItem(_, _) | ItemKind::AssocTypeItem(_, _) => true,
-            _ => false,
-        }
+        matches!(self, ItemKind::TypedefItem(..) | ItemKind::AssocTypeItem(..))
     }
 }
 
@@ -474,11 +477,13 @@ crate struct DocFragment {
     /// This allows distinguishing between the original documentation and a pub re-export.
     /// If it is `None`, the item was not re-exported.
     crate parent_module: Option<DefId>,
-    crate doc: String,
+    crate doc: Symbol,
     crate kind: DocFragmentKind,
+    crate need_backline: bool,
+    crate indent: usize,
 }
 
-#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
 crate enum DocFragmentKind {
     /// A doc fragment created from a `///` or `//!` doc comment.
     SugaredDoc,
@@ -486,7 +491,33 @@ crate enum DocFragmentKind {
     RawDoc,
     /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
     /// given filename and the file contents.
-    Include { filename: String },
+    Include { filename: Symbol },
+}
+
+// The goal of this function is to apply the `DocFragment` transformations that are required when
+// transforming into the final markdown. So the transformations in here are:
+//
+// * Applying the computed indent to each lines in each doc fragment (a `DocFragment` can contain
+//   multiple lines in case of `#[doc = ""]`).
+// * Adding backlines between `DocFragment`s and adding an extra one if required (stored in the
+//   `need_backline` field).
+fn add_doc_fragment(out: &mut String, frag: &DocFragment) {
+    let s = frag.doc.as_str();
+    let mut iter = s.lines().peekable();
+    while let Some(line) = iter.next() {
+        if line.chars().any(|c| !c.is_whitespace()) {
+            assert!(line.len() >= frag.indent);
+            out.push_str(&line[frag.indent..]);
+        } else {
+            out.push_str(line);
+        }
+        if iter.peek().is_some() {
+            out.push('\n');
+        }
+    }
+    if frag.need_backline {
+        out.push('\n');
+    }
 }
 
 impl<'a> FromIterator<&'a DocFragment> for String {
@@ -494,11 +525,18 @@ impl<'a> FromIterator<&'a DocFragment> for String {
     where
         T: IntoIterator<Item = &'a DocFragment>,
     {
+        let mut prev_kind: Option<DocFragmentKind> = None;
         iter.into_iter().fold(String::new(), |mut acc, frag| {
-            if !acc.is_empty() {
+            if !acc.is_empty()
+                && prev_kind
+                    .take()
+                    .map(|p| matches!(p, DocFragmentKind::Include { .. }) && p != frag.kind)
+                    .unwrap_or(false)
+            {
                 acc.push('\n');
             }
-            acc.push_str(&frag.doc);
+            add_doc_fragment(&mut acc, &frag);
+            prev_kind = Some(frag.kind);
             acc
         })
     }
@@ -570,7 +608,7 @@ impl Attributes {
     /// Reads a `MetaItem` from within an attribute, looks for whether it is a
     /// `#[doc(include="file")]`, and returns the filename and contents of the file as loaded from
     /// its expansion.
-    crate fn extract_include(mi: &ast::MetaItem) -> Option<(String, String)> {
+    crate fn extract_include(mi: &ast::MetaItem) -> Option<(Symbol, Symbol)> {
         mi.meta_item_list().and_then(|list| {
             for meta in list {
                 if meta.has_name(sym::include) {
@@ -578,17 +616,17 @@ impl Attributes {
                     // `#[doc(include(file="filename", contents="file contents")]` so we need to
                     // look for that instead
                     return meta.meta_item_list().and_then(|list| {
-                        let mut filename: Option<String> = None;
-                        let mut contents: Option<String> = None;
+                        let mut filename: Option<Symbol> = None;
+                        let mut contents: Option<Symbol> = None;
 
                         for it in list {
                             if it.has_name(sym::file) {
                                 if let Some(name) = it.value_str() {
-                                    filename = Some(name.to_string());
+                                    filename = Some(name);
                                 }
                             } else if it.has_name(sym::contents) {
                                 if let Some(docs) = it.value_str() {
-                                    contents = Some(docs.to_string());
+                                    contents = Some(docs);
                                 }
                             }
                         }
@@ -627,15 +665,30 @@ impl Attributes {
         attrs: &[ast::Attribute],
         additional_attrs: Option<(&[ast::Attribute], DefId)>,
     ) -> Attributes {
-        let mut doc_strings = vec![];
+        let mut doc_strings: Vec<DocFragment> = vec![];
         let mut sp = None;
         let mut cfg = Cfg::True;
         let mut doc_line = 0;
 
+        fn update_need_backline(doc_strings: &mut Vec<DocFragment>, frag: &DocFragment) {
+            if let Some(prev) = doc_strings.last_mut() {
+                if matches!(prev.kind, DocFragmentKind::Include { .. })
+                    || prev.kind != frag.kind
+                    || prev.parent_module != frag.parent_module
+                {
+                    // add a newline for extra padding between segments
+                    prev.need_backline = prev.kind == DocFragmentKind::SugaredDoc
+                        || prev.kind == DocFragmentKind::RawDoc
+                } else {
+                    prev.need_backline = true;
+                }
+            }
+        }
+
         let clean_attr = |(attr, parent_module): (&ast::Attribute, _)| {
             if let Some(value) = attr.doc_str() {
                 trace!("got doc_str={:?}", value);
-                let value = beautify_doc_string(value).to_string();
+                let value = beautify_doc_string(value);
                 let kind = if attr.is_doc_comment() {
                     DocFragmentKind::SugaredDoc
                 } else {
@@ -643,14 +696,20 @@ impl Attributes {
                 };
 
                 let line = doc_line;
-                doc_line += value.lines().count();
-                doc_strings.push(DocFragment {
+                doc_line += value.as_str().lines().count();
+                let frag = DocFragment {
                     line,
                     span: attr.span,
                     doc: value,
                     kind,
                     parent_module,
-                });
+                    need_backline: false,
+                    indent: 0,
+                };
+
+                update_need_backline(&mut doc_strings, &frag);
+
+                doc_strings.push(frag);
 
                 if sp.is_none() {
                     sp = Some(attr.span);
@@ -668,14 +727,18 @@ impl Attributes {
                         } else if let Some((filename, contents)) = Attributes::extract_include(&mi)
                         {
                             let line = doc_line;
-                            doc_line += contents.lines().count();
-                            doc_strings.push(DocFragment {
+                            doc_line += contents.as_str().lines().count();
+                            let frag = DocFragment {
                                 line,
                                 span: attr.span,
                                 doc: contents,
                                 kind: DocFragmentKind::Include { filename },
-                                parent_module: parent_module,
-                            });
+                                parent_module,
+                                need_backline: false,
+                                indent: 0,
+                            };
+                            update_need_backline(&mut doc_strings, &frag);
+                            doc_strings.push(frag);
                         }
                     }
                 }
@@ -726,14 +789,41 @@ impl Attributes {
 
     /// Finds the `doc` attribute as a NameValue and returns the corresponding
     /// value found.
-    crate fn doc_value(&self) -> Option<&str> {
-        self.doc_strings.first().map(|s| s.doc.as_str())
+    crate fn doc_value(&self) -> Option<String> {
+        let mut iter = self.doc_strings.iter();
+
+        let ori = iter.next()?;
+        let mut out = String::new();
+        add_doc_fragment(&mut out, &ori);
+        while let Some(new_frag) = iter.next() {
+            if matches!(ori.kind, DocFragmentKind::Include { .. })
+                || new_frag.kind != ori.kind
+                || new_frag.parent_module != ori.parent_module
+            {
+                break;
+            }
+            add_doc_fragment(&mut out, &new_frag);
+        }
+        if out.is_empty() { None } else { Some(out) }
+    }
+
+    /// Return the doc-comments on this item, grouped by the module they came from.
+    ///
+    /// The module can be different if this is a re-export with added documentation.
+    crate fn collapsed_doc_value_by_module_level(&self) -> FxHashMap<Option<DefId>, String> {
+        let mut ret = FxHashMap::default();
+
+        for new_frag in self.doc_strings.iter() {
+            let out = ret.entry(new_frag.parent_module).or_default();
+            add_doc_fragment(out, &new_frag);
+        }
+        ret
     }
 
     /// Finds all `doc` attributes as NameValues and returns their corresponding values, joined
     /// with newlines.
     crate fn collapsed_doc_value(&self) -> Option<String> {
-        if !self.doc_strings.is_empty() { Some(self.doc_strings.iter().collect()) } else { None }
+        if self.doc_strings.is_empty() { None } else { Some(self.doc_strings.iter().collect()) }
     }
 
     /// Gets links as a vector
@@ -750,7 +840,7 @@ impl Attributes {
                     Some(did) => {
                         if let Some((mut href, ..)) = href(did) {
                             if let Some(ref fragment) = *fragment {
-                                href.push_str("#");
+                                href.push('#');
                                 href.push_str(fragment);
                             }
                             Some(RenderedLink {
@@ -945,10 +1035,7 @@ crate enum GenericParamDefKind {
 
 impl GenericParamDefKind {
     crate fn is_type(&self) -> bool {
-        match *self {
-            GenericParamDefKind::Type { .. } => true,
-            _ => false,
-        }
+        matches!(self, GenericParamDefKind::Type { .. })
     }
 
     // FIXME(eddyb) this either returns the default of a type parameter, or the
@@ -1141,6 +1228,7 @@ crate enum Type {
     BareFunction(Box<BareFunctionDecl>),
     Tuple(Vec<Type>),
     Slice(Box<Type>),
+    /// The `String` field is about the size or the constant representing the array's length.
     Array(Box<Type>, String),
     Never,
     RawPointer(Mutability, Box<Type>),
@@ -1292,15 +1380,12 @@ impl Type {
     }
 
     crate fn is_full_generic(&self) -> bool {
-        match *self {
-            Type::Generic(_) => true,
-            _ => false,
-        }
+        matches!(self, Type::Generic(_))
     }
 
     crate fn projection(&self) -> Option<(&Type, DefId, Symbol)> {
         let (self_, trait_, name) = match self {
-            QPath { ref self_type, ref trait_, name } => (self_type, trait_, name),
+            QPath { self_type, trait_, name } => (self_type, trait_, name),
             _ => return None,
         };
         let trait_did = match **trait_ {
@@ -1728,7 +1813,12 @@ crate struct PathSegment {
 crate struct Typedef {
     crate type_: Type,
     crate generics: Generics,
-    // Type of target item.
+    /// `type_` can come from either the HIR or from metadata. If it comes from HIR, it may be a type
+    /// alias instead of the final type. This will always have the final type, regardless of whether
+    /// `type_` came from HIR or from metadata.
+    ///
+    /// If `item_type.is_none()`, `type_` is guarenteed to come from metadata (and therefore hold the
+    /// final type).
     crate item_type: Option<Type>,
 }
 
@@ -1770,12 +1860,6 @@ crate struct Constant {
     crate is_literal: bool,
 }
 
-#[derive(Clone, PartialEq, Debug)]
-crate enum ImplPolarity {
-    Positive,
-    Negative,
-}
-
 #[derive(Clone, Debug)]
 crate struct Impl {
     crate unsafety: hir::Unsafety,
@@ -1784,7 +1868,7 @@ crate struct Impl {
     crate trait_: Option<Type>,
     crate for_: Type,
     crate items: Vec<Item>,
-    crate polarity: Option<ImplPolarity>,
+    crate negative_polarity: bool,
     crate synthetic: bool,
     crate blanket_impl: Option<Type>,
 }
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index d4482d6fa90..0f5495c8310 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -179,12 +179,12 @@ crate fn get_real_types(
     if arg.is_full_generic() {
         let arg_s = Symbol::intern(&arg.print().to_string());
         if let Some(where_pred) = generics.where_predicates.iter().find(|g| match g {
-            &WherePredicate::BoundPredicate { ref ty, .. } => ty.def_id() == arg.def_id(),
+            WherePredicate::BoundPredicate { ty, .. } => ty.def_id() == arg.def_id(),
             _ => false,
         }) {
             let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]);
             for bound in bounds.iter() {
-                if let GenericBound::TraitBound(ref poly_trait, _) = *bound {
+                if let GenericBound::TraitBound(poly_trait, _) = bound {
                     for x in poly_trait.generic_params.iter() {
                         if !x.is_type() {
                             continue;
@@ -314,25 +314,6 @@ crate fn strip_path(path: &Path) -> Path {
     Path { global: path.global, res: path.res, segments }
 }
 
-crate fn qpath_to_string(p: &hir::QPath<'_>) -> String {
-    let segments = match *p {
-        hir::QPath::Resolved(_, ref path) => &path.segments,
-        hir::QPath::TypeRelative(_, ref segment) => return segment.ident.to_string(),
-        hir::QPath::LangItem(lang_item, ..) => return lang_item.name().to_string(),
-    };
-
-    let mut s = String::new();
-    for (i, seg) in segments.iter().enumerate() {
-        if i > 0 {
-            s.push_str("::");
-        }
-        if seg.ident.name != kw::PathRoot {
-            s.push_str(&seg.ident.as_str());
-        }
-    }
-    s
-}
-
 crate fn build_deref_target_impls(cx: &DocContext<'_>, items: &[Item], ret: &mut Vec<Item>) {
     let tcx = cx.tcx;
 
@@ -376,57 +357,6 @@ impl ToSource for rustc_span::Span {
     }
 }
 
-crate fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
-    use rustc_hir::*;
-    debug!("trying to get a name from pattern: {:?}", p);
-
-    Symbol::intern(&match p.kind {
-        PatKind::Wild => return kw::Underscore,
-        PatKind::Binding(_, _, ident, _) => return ident.name,
-        PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
-        PatKind::Struct(ref name, ref fields, etc) => format!(
-            "{} {{ {}{} }}",
-            qpath_to_string(name),
-            fields
-                .iter()
-                .map(|fp| format!("{}: {}", fp.ident, name_from_pat(&fp.pat)))
-                .collect::<Vec<String>>()
-                .join(", "),
-            if etc { ", .." } else { "" }
-        ),
-        PatKind::Or(ref pats) => pats
-            .iter()
-            .map(|p| name_from_pat(&**p).to_string())
-            .collect::<Vec<String>>()
-            .join(" | "),
-        PatKind::Tuple(ref elts, _) => format!(
-            "({})",
-            elts.iter()
-                .map(|p| name_from_pat(&**p).to_string())
-                .collect::<Vec<String>>()
-                .join(", ")
-        ),
-        PatKind::Box(ref p) => return name_from_pat(&**p),
-        PatKind::Ref(ref p, _) => return name_from_pat(&**p),
-        PatKind::Lit(..) => {
-            warn!(
-                "tried to get argument name from PatKind::Lit, which is silly in function arguments"
-            );
-            return Symbol::intern("()");
-        }
-        PatKind::Range(..) => panic!(
-            "tried to get argument name from PatKind::Range, \
-             which is not allowed in function arguments"
-        ),
-        PatKind::Slice(ref begin, ref mid, ref end) => {
-            let begin = begin.iter().map(|p| name_from_pat(&**p).to_string());
-            let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter();
-            let end = end.iter().map(|p| name_from_pat(&**p).to_string());
-            format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", "))
-        }
-    })
-}
-
 crate fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String {
     match n.val {
         ty::ConstKind::Unevaluated(def, _, promoted) => {
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 2d58614b139..e43ea965c04 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -37,10 +37,7 @@ crate enum OutputFormat {
 
 impl OutputFormat {
     crate fn is_json(&self) -> bool {
-        match self {
-            OutputFormat::Json => true,
-            _ => false,
-        }
+        matches!(self, OutputFormat::Json)
     }
 }
 
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 7e85342ac7d..4db5a0bccc8 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -120,14 +120,20 @@ impl<'tcx> DocContext<'tcx> {
         r
     }
 
-    // This is an ugly hack, but it's the simplest way to handle synthetic impls without greatly
-    // refactoring either librustdoc or librustc_middle. In particular, allowing new DefIds to be
-    // registered after the AST is constructed would require storing the defid mapping in a
-    // RefCell, decreasing the performance for normal compilation for very little gain.
-    //
-    // Instead, we construct 'fake' def ids, which start immediately after the last DefId.
-    // In the Debug impl for clean::Item, we explicitly check for fake
-    // def ids, as we'll end up with a panic if we use the DefId Debug impl for fake DefIds
+    /// Create a new "fake" [`DefId`].
+    ///
+    /// This is an ugly hack, but it's the simplest way to handle synthetic impls without greatly
+    /// refactoring either rustdoc or [`rustc_middle`]. In particular, allowing new [`DefId`]s
+    /// to be registered after the AST is constructed would require storing the [`DefId`] mapping
+    /// in a [`RefCell`], decreasing the performance for normal compilation for very little gain.
+    ///
+    /// Instead, we construct "fake" [`DefId`]s, which start immediately after the last `DefId`.
+    /// In the [`Debug`] impl for [`clean::Item`], we explicitly check for fake `DefId`s,
+    /// as we'll end up with a panic if we use the `DefId` `Debug` impl for fake `DefId`s.
+    ///
+    /// [`RefCell`]: std::cell::RefCell
+    /// [`Debug`]: std::fmt::Debug
+    /// [`clean::Item`]: crate::clean::types::Item
     crate fn next_def_id(&self, crate_num: CrateNum) -> DefId {
         let start_def_id = {
             let num_def_ids = if crate_num == LOCAL_CRATE {
@@ -428,16 +434,15 @@ crate fn create_resolver<'a>(
         sess.time("load_extern_crates", || {
             for extern_name in &extern_names {
                 debug!("loading extern crate {}", extern_name);
-                resolver
+                if let Err(()) = resolver
                     .resolve_str_path_error(
                         DUMMY_SP,
                         extern_name,
                         TypeNS,
                         LocalDefId { local_def_index: CRATE_DEF_INDEX }.to_def_id(),
-                    )
-                    .unwrap_or_else(|()| {
-                        panic!("Unable to resolve external crate {}", extern_name)
-                    });
+                  ) {
+                    warn!("unable to resolve external crate {} (do you have an unused `--extern` crate?)", extern_name)
+                  }
             }
         });
     });
@@ -525,7 +530,7 @@ crate fn run_global_ctxt(
     let mut krate = tcx.sess.time("clean_crate", || clean::krate(&mut ctxt));
 
     if let Some(ref m) = krate.module {
-        if let None | Some("") = m.doc_value() {
+        if m.doc_value().map(|d| d.is_empty()).unwrap_or(true) {
             let help = "The following guide may be of use:\n\
                 https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html";
             tcx.struct_lint_node(
@@ -623,6 +628,9 @@ crate fn run_global_ctxt(
 
     ctxt.sess().abort_if_errors();
 
+    // The main crate doc comments are always collapsed.
+    krate.collapsed = true;
+
     (krate, ctxt.renderinfo.into_inner(), ctxt.render_options)
 }
 
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 02dd42ce0c1..09627be9701 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -636,15 +636,15 @@ fn partition_source(s: &str) -> (String, String, String) {
         match state {
             PartitionState::Attrs => {
                 before.push_str(line);
-                before.push_str("\n");
+                before.push('\n');
             }
             PartitionState::Crates => {
                 crates.push_str(line);
-                crates.push_str("\n");
+                crates.push('\n');
             }
             PartitionState::Other => {
                 after.push_str(line);
-                after.push_str("\n");
+                after.push('\n');
             }
         }
     }
@@ -987,7 +987,6 @@ impl<'a, 'hir, 'tcx> HirCollector<'a, 'hir, 'tcx> {
             self.collector.names.push(name);
         }
 
-        attrs.collapse_doc_comments();
         attrs.unindent_doc_comments();
         // The collapse-docs pass won't combine sugared/raw doc attributes, or included files with
         // anything else, this will combine them for us.
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index c39cc3ca397..4d45c8866a7 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -61,7 +61,7 @@ crate trait DocFolder: Sized {
                         j.fields = j.fields.into_iter().filter_map(|x| self.fold_item(x)).collect();
                         j.fields_stripped |= num_fields != j.fields.len()
                             || j.fields.iter().any(|f| f.is_stripped());
-                        VariantItem(Variant { kind: VariantKind::Struct(j), ..i2 })
+                        VariantItem(Variant { kind: VariantKind::Struct(j) })
                     }
                     _ => VariantItem(i2),
                 }
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index 899d61d8e43..c1f8b12cac4 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -316,7 +316,7 @@ impl DocFolder for Cache {
                             path: path.join("::"),
                             desc: item
                                 .doc_value()
-                                .map_or_else(|| String::new(), short_markdown_summary),
+                                .map_or_else(String::new, |x| short_markdown_summary(&x.as_str())),
                             parent,
                             parent_idx: None,
                             search_type: get_index_search_type(&item),
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 9b2fb8582f5..5c2adca3126 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -245,7 +245,7 @@ impl<'a> fmt::Display for WhereClause<'a> {
             }
 
             match pred {
-                &clean::WherePredicate::BoundPredicate { ref ty, ref bounds } => {
+                clean::WherePredicate::BoundPredicate { ty, bounds } => {
                     let bounds = bounds;
                     if f.alternate() {
                         clause.push_str(&format!(
@@ -261,7 +261,7 @@ impl<'a> fmt::Display for WhereClause<'a> {
                         ));
                     }
                 }
-                &clean::WherePredicate::RegionPredicate { ref lifetime, ref bounds } => {
+                clean::WherePredicate::RegionPredicate { lifetime, bounds } => {
                     clause.push_str(&format!(
                         "{}: {}",
                         lifetime.print(),
@@ -272,7 +272,7 @@ impl<'a> fmt::Display for WhereClause<'a> {
                             .join(" + ")
                     ));
                 }
-                &clean::WherePredicate::EqPredicate { ref lhs, ref rhs } => {
+                clean::WherePredicate::EqPredicate { lhs, rhs } => {
                     if f.alternate() {
                         clause.push_str(&format!("{:#} == {:#}", lhs.print(), rhs.print()));
                     } else {
@@ -376,8 +376,8 @@ impl clean::GenericBound {
 impl clean::GenericArgs {
     fn print(&self) -> impl fmt::Display + '_ {
         display_fn(move |f| {
-            match *self {
-                clean::GenericArgs::AngleBracketed { ref args, ref bindings } => {
+            match self {
+                clean::GenericArgs::AngleBracketed { args, bindings } => {
                     if !args.is_empty() || !bindings.is_empty() {
                         if f.alternate() {
                             f.write_str("<")?;
@@ -414,7 +414,7 @@ impl clean::GenericArgs {
                         }
                     }
                 }
-                clean::GenericArgs::Parenthesized { ref inputs, ref output } => {
+                clean::GenericArgs::Parenthesized { inputs, output } => {
                     f.write_str("(")?;
                     let mut comma = false;
                     for ty in inputs {
@@ -501,7 +501,7 @@ crate fn href(did: DefId) -> Option<(String, ItemType, Vec<String>)> {
     };
     for component in &fqp[..fqp.len() - 1] {
         url.push_str(component);
-        url.push_str("/");
+        url.push('/');
     }
     match shortty {
         ItemType::Module => {
@@ -510,7 +510,7 @@ crate fn href(did: DefId) -> Option<(String, ItemType, Vec<String>)> {
         }
         _ => {
             url.push_str(shortty.as_str());
-            url.push_str(".");
+            url.push('.');
             url.push_str(fqp.last().unwrap());
             url.push_str(".html");
         }
@@ -870,7 +870,7 @@ impl clean::Impl {
             }
 
             if let Some(ref ty) = self.trait_ {
-                if self.polarity == Some(clean::ImplPolarity::Negative) {
+                if self.negative_polarity {
                     write!(f, "!")?;
                 }
 
@@ -1021,7 +1021,7 @@ impl Function<'_> {
                 } else {
                     if i > 0 {
                         args.push_str(" <br>");
-                        args_plain.push_str(" ");
+                        args_plain.push(' ');
                     }
                     if !input.name.is_empty() {
                         args.push_str(&format!("{}: ", input.name));
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 20cf48915c3..33639055b59 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -25,6 +25,7 @@ use rustc_session::lint;
 use rustc_span::edition::Edition;
 use rustc_span::Span;
 use std::borrow::Cow;
+use std::cell::RefCell;
 use std::collections::VecDeque;
 use std::default::Default;
 use std::fmt::Write;
@@ -36,7 +37,9 @@ use crate::doctest;
 use crate::html::highlight;
 use crate::html::toc::TocBuilder;
 
-use pulldown_cmark::{html, BrokenLink, CodeBlockKind, CowStr, Event, Options, Parser, Tag};
+use pulldown_cmark::{
+    html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag,
+};
 
 #[cfg(test)]
 mod tests;
@@ -326,8 +329,6 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
     type Item = Event<'a>;
 
     fn next(&mut self) -> Option<Self::Item> {
-        use pulldown_cmark::LinkType;
-
         let mut event = self.inner.next();
 
         // Replace intra-doc links and remove disambiguators from shortcut links (`[fn@f]`).
@@ -414,11 +415,13 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
     }
 }
 
+type SpannedEvent<'a> = (Event<'a>, Range<usize>);
+
 /// Make headings links with anchor IDs and build up TOC.
 struct HeadingLinks<'a, 'b, 'ids, I> {
     inner: I,
     toc: Option<&'b mut TocBuilder>,
-    buf: VecDeque<Event<'a>>,
+    buf: VecDeque<SpannedEvent<'a>>,
     id_map: &'ids mut IdMap,
 }
 
@@ -428,8 +431,10 @@ impl<'a, 'b, 'ids, I> HeadingLinks<'a, 'b, 'ids, I> {
     }
 }
 
-impl<'a, 'b, 'ids, I: Iterator<Item = Event<'a>>> Iterator for HeadingLinks<'a, 'b, 'ids, I> {
-    type Item = Event<'a>;
+impl<'a, 'b, 'ids, I: Iterator<Item = SpannedEvent<'a>>> Iterator
+    for HeadingLinks<'a, 'b, 'ids, I>
+{
+    type Item = SpannedEvent<'a>;
 
     fn next(&mut self) -> Option<Self::Item> {
         if let Some(e) = self.buf.pop_front() {
@@ -437,31 +442,29 @@ impl<'a, 'b, 'ids, I: Iterator<Item = Event<'a>>> Iterator for HeadingLinks<'a,
         }
 
         let event = self.inner.next();
-        if let Some(Event::Start(Tag::Heading(level))) = event {
+        if let Some((Event::Start(Tag::Heading(level)), _)) = event {
             let mut id = String::new();
             for event in &mut self.inner {
-                match &event {
+                match &event.0 {
                     Event::End(Tag::Heading(..)) => break,
+                    Event::Start(Tag::Link(_, _, _)) | Event::End(Tag::Link(..)) => {}
                     Event::Text(text) | Event::Code(text) => {
                         id.extend(text.chars().filter_map(slugify));
+                        self.buf.push_back(event);
                     }
-                    _ => {}
-                }
-                match event {
-                    Event::Start(Tag::Link(_, _, _)) | Event::End(Tag::Link(..)) => {}
-                    event => self.buf.push_back(event),
+                    _ => self.buf.push_back(event),
                 }
             }
             let id = self.id_map.derive(id);
 
             if let Some(ref mut builder) = self.toc {
                 let mut html_header = String::new();
-                html::push_html(&mut html_header, self.buf.iter().cloned());
+                html::push_html(&mut html_header, self.buf.iter().map(|(ev, _)| ev.clone()));
                 let sec = builder.push(level as u32, html_header, id.clone());
-                self.buf.push_front(Event::Html(format!("{} ", sec).into()));
+                self.buf.push_front((Event::Html(format!("{} ", sec).into()), 0..0));
             }
 
-            self.buf.push_back(Event::Html(format!("</a></h{}>", level).into()));
+            self.buf.push_back((Event::Html(format!("</a></h{}>", level).into()), 0..0));
 
             let start_tags = format!(
                 "<h{level} id=\"{id}\" class=\"section-header\">\
@@ -469,7 +472,7 @@ impl<'a, 'b, 'ids, I: Iterator<Item = Event<'a>>> Iterator for HeadingLinks<'a,
                 id = id,
                 level = level
             );
-            return Some(Event::Html(start_tags.into()));
+            return Some((Event::Html(start_tags.into()), 0..0));
         }
         event
     }
@@ -489,15 +492,10 @@ impl<'a, I: Iterator<Item = Event<'a>>> SummaryLine<'a, I> {
 }
 
 fn check_if_allowed_tag(t: &Tag<'_>) -> bool {
-    match *t {
-        Tag::Paragraph
-        | Tag::Item
-        | Tag::Emphasis
-        | Tag::Strong
-        | Tag::Link(..)
-        | Tag::BlockQuote => true,
-        _ => false,
-    }
+    matches!(
+        t,
+        Tag::Paragraph | Tag::Item | Tag::Emphasis | Tag::Strong | Tag::Link(..) | Tag::BlockQuote
+    )
 }
 
 impl<'a, I: Iterator<Item = Event<'a>>> Iterator for SummaryLine<'a, I> {
@@ -560,23 +558,23 @@ impl<'a, I> Footnotes<'a, I> {
     }
 }
 
-impl<'a, I: Iterator<Item = Event<'a>>> Iterator for Footnotes<'a, I> {
-    type Item = Event<'a>;
+impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, I> {
+    type Item = SpannedEvent<'a>;
 
     fn next(&mut self) -> Option<Self::Item> {
         loop {
             match self.inner.next() {
-                Some(Event::FootnoteReference(ref reference)) => {
+                Some((Event::FootnoteReference(ref reference), range)) => {
                     let entry = self.get_entry(&reference);
                     let reference = format!(
                         "<sup id=\"fnref{0}\"><a href=\"#fn{0}\">{0}</a></sup>",
                         (*entry).1
                     );
-                    return Some(Event::Html(reference.into()));
+                    return Some((Event::Html(reference.into()), range));
                 }
-                Some(Event::Start(Tag::FootnoteDefinition(def))) => {
+                Some((Event::Start(Tag::FootnoteDefinition(def)), _)) => {
                     let mut content = Vec::new();
-                    for event in &mut self.inner {
+                    for (event, _) in &mut self.inner {
                         if let Event::End(Tag::FootnoteDefinition(..)) = event {
                             break;
                         }
@@ -607,7 +605,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for Footnotes<'a, I> {
                             ret.push_str("</li>");
                         }
                         ret.push_str("</ol></div>");
-                        return Some(Event::Html(ret.into()));
+                        return Some((Event::Html(ret.into()), 0..0));
                     } else {
                         return None;
                     }
@@ -917,13 +915,14 @@ impl Markdown<'_> {
         };
 
         let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut replacer));
+        let p = p.into_offset_iter();
 
         let mut s = String::with_capacity(md.len() * 3 / 2);
 
         let p = HeadingLinks::new(p, None, &mut ids);
-        let p = LinkReplacer::new(p, links);
-        let p = CodeBlocks::new(p, codes, edition, playground);
         let p = Footnotes::new(p);
+        let p = LinkReplacer::new(p.map(|(ev, _)| ev), links);
+        let p = CodeBlocks::new(p, codes, edition, playground);
         html::push_html(&mut s, p);
 
         s
@@ -934,7 +933,7 @@ impl MarkdownWithToc<'_> {
     crate fn into_string(self) -> String {
         let MarkdownWithToc(md, mut ids, codes, edition, playground) = self;
 
-        let p = Parser::new_ext(md, opts());
+        let p = Parser::new_ext(md, opts()).into_offset_iter();
 
         let mut s = String::with_capacity(md.len() * 3 / 2);
 
@@ -942,8 +941,8 @@ impl MarkdownWithToc<'_> {
 
         {
             let p = HeadingLinks::new(p, Some(&mut toc), &mut ids);
-            let p = CodeBlocks::new(p, codes, edition, playground);
             let p = Footnotes::new(p);
+            let p = CodeBlocks::new(p.map(|(ev, _)| ev), codes, edition, playground);
             html::push_html(&mut s, p);
         }
 
@@ -959,19 +958,19 @@ impl MarkdownHtml<'_> {
         if md.is_empty() {
             return String::new();
         }
-        let p = Parser::new_ext(md, opts());
+        let p = Parser::new_ext(md, opts()).into_offset_iter();
 
         // Treat inline HTML as plain text.
-        let p = p.map(|event| match event {
-            Event::Html(text) => Event::Text(text),
+        let p = p.map(|event| match event.0 {
+            Event::Html(text) => (Event::Text(text), event.1),
             _ => event,
         });
 
         let mut s = String::with_capacity(md.len() * 3 / 2);
 
         let p = HeadingLinks::new(p, None, &mut ids);
-        let p = CodeBlocks::new(p, codes, edition, playground);
         let p = Footnotes::new(p);
+        let p = CodeBlocks::new(p.map(|(ev, _)| ev), codes, edition, playground);
         html::push_html(&mut s, p);
 
         s
@@ -1124,56 +1123,75 @@ crate fn plain_text_summary(md: &str) -> String {
     s
 }
 
-crate fn markdown_links(md: &str) -> Vec<(String, Option<Range<usize>>)> {
+crate struct MarkdownLink {
+    pub kind: LinkType,
+    pub link: String,
+    pub range: Range<usize>,
+}
+
+crate fn markdown_links(md: &str) -> Vec<MarkdownLink> {
     if md.is_empty() {
         return vec![];
     }
 
-    let mut links = vec![];
-    let mut shortcut_links = vec![];
-
-    {
-        let locate = |s: &str| unsafe {
-            let s_start = s.as_ptr();
-            let s_end = s_start.add(s.len());
-            let md_start = md.as_ptr();
-            let md_end = md_start.add(md.len());
-            if md_start <= s_start && s_end <= md_end {
-                let start = s_start.offset_from(md_start) as usize;
-                let end = s_end.offset_from(md_start) as usize;
-                Some(start..end)
-            } else {
-                None
-            }
-        };
-
-        let mut push = |link: BrokenLink<'_>| {
-            // FIXME: use `link.span` instead of `locate`
-            // (doing it now includes the `[]` as well as the text)
-            shortcut_links.push((link.reference.to_owned(), locate(link.reference)));
-            None
-        };
-        let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut push));
-
-        // There's no need to thread an IdMap through to here because
-        // the IDs generated aren't going to be emitted anywhere.
-        let mut ids = IdMap::new();
-        let iter = Footnotes::new(HeadingLinks::new(p, None, &mut ids));
-
-        for ev in iter {
-            if let Event::Start(Tag::Link(_, dest, _)) = ev {
-                debug!("found link: {}", dest);
-                links.push(match dest {
-                    CowStr::Borrowed(s) => (s.to_owned(), locate(s)),
-                    s @ (CowStr::Boxed(..) | CowStr::Inlined(..)) => (s.into_string(), None),
-                });
-            }
+    let links = RefCell::new(vec![]);
+
+    // FIXME: remove this function once pulldown_cmark can provide spans for link definitions.
+    let locate = |s: &str, fallback: Range<usize>| unsafe {
+        let s_start = s.as_ptr();
+        let s_end = s_start.add(s.len());
+        let md_start = md.as_ptr();
+        let md_end = md_start.add(md.len());
+        if md_start <= s_start && s_end <= md_end {
+            let start = s_start.offset_from(md_start) as usize;
+            let end = s_end.offset_from(md_start) as usize;
+            start..end
+        } else {
+            fallback
+        }
+    };
+
+    let span_for_link = |link: &CowStr<'_>, span: Range<usize>| {
+        // For diagnostics, we want to underline the link's definition but `span` will point at
+        // where the link is used. This is a problem for reference-style links, where the definition
+        // is separate from the usage.
+        match link {
+            // `Borrowed` variant means the string (the link's destination) may come directly from
+            // the markdown text and we can locate the original link destination.
+            // NOTE: LinkReplacer also provides `Borrowed` but possibly from other sources,
+            // so `locate()` can fall back to use `span`.
+            CowStr::Borrowed(s) => locate(s, span),
+
+            // For anything else, we can only use the provided range.
+            CowStr::Boxed(_) | CowStr::Inlined(_) => span,
+        }
+    };
+
+    let mut push = |link: BrokenLink<'_>| {
+        let span = span_for_link(&CowStr::Borrowed(link.reference), link.span);
+        links.borrow_mut().push(MarkdownLink {
+            kind: LinkType::ShortcutUnknown,
+            link: link.reference.to_owned(),
+            range: span,
+        });
+        None
+    };
+    let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut push)).into_offset_iter();
+
+    // There's no need to thread an IdMap through to here because
+    // the IDs generated aren't going to be emitted anywhere.
+    let mut ids = IdMap::new();
+    let iter = Footnotes::new(HeadingLinks::new(p, None, &mut ids));
+
+    for ev in iter {
+        if let Event::Start(Tag::Link(kind, dest, _)) = ev.0 {
+            debug!("found link: {}", dest);
+            let span = span_for_link(&dest, ev.1);
+            links.borrow_mut().push(MarkdownLink { kind, link: dest.into_string(), range: span });
         }
     }
 
-    links.append(&mut shortcut_links);
-
-    links
+    links.into_inner()
 }
 
 #[derive(Debug)]
@@ -1185,6 +1203,7 @@ crate struct RustCodeBlock {
     crate code: Range<usize>,
     crate is_fenced: bool,
     crate syntax: Option<String>,
+    crate is_ignore: bool,
 }
 
 /// Returns a range of bytes for each code block in the markdown that is tagged as `rust` or
@@ -1200,7 +1219,7 @@ crate fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_, '_>) -> Vec<RustC
 
     while let Some((event, offset)) = p.next() {
         if let Event::Start(Tag::CodeBlock(syntax)) = event {
-            let (syntax, code_start, code_end, range, is_fenced) = match syntax {
+            let (syntax, code_start, code_end, range, is_fenced, is_ignore) = match syntax {
                 CodeBlockKind::Fenced(syntax) => {
                     let syntax = syntax.as_ref();
                     let lang_string = if syntax.is_empty() {
@@ -1211,6 +1230,7 @@ crate fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_, '_>) -> Vec<RustC
                     if !lang_string.rust {
                         continue;
                     }
+                    let is_ignore = lang_string.ignore != Ignore::None;
                     let syntax = if syntax.is_empty() { None } else { Some(syntax.to_owned()) };
                     let (code_start, mut code_end) = match p.next() {
                         Some((Event::Text(_), offset)) => (offset.start, offset.end),
@@ -1221,6 +1241,7 @@ crate fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_, '_>) -> Vec<RustC
                                 range: offset,
                                 code,
                                 syntax,
+                                is_ignore,
                             });
                             continue;
                         }
@@ -1231,6 +1252,7 @@ crate fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_, '_>) -> Vec<RustC
                                 range: offset,
                                 code,
                                 syntax,
+                                is_ignore,
                             });
                             continue;
                         }
@@ -1238,7 +1260,7 @@ crate fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_, '_>) -> Vec<RustC
                     while let Some((Event::Text(_), offset)) = p.next() {
                         code_end = offset.end;
                     }
-                    (syntax, code_start, code_end, offset, true)
+                    (syntax, code_start, code_end, offset, true, is_ignore)
                 }
                 CodeBlockKind::Indented => {
                     // The ending of the offset goes too far sometime so we reduce it by one in
@@ -1250,9 +1272,10 @@ crate fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_, '_>) -> Vec<RustC
                             offset.end,
                             Range { start: offset.start, end: offset.end - 1 },
                             false,
+                            false,
                         )
                     } else {
-                        (None, offset.start, offset.end, offset, false)
+                        (None, offset.start, offset.end, offset, false, false)
                     }
                 }
             };
@@ -1262,6 +1285,7 @@ crate fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_, '_>) -> Vec<RustC
                 range,
                 code: Range { start: code_start, end: code_end },
                 syntax,
+                is_ignore,
             });
         }
     }
@@ -1298,7 +1322,6 @@ fn init_id_map() -> FxHashMap<String, usize> {
     map.insert("trait-implementations".to_owned(), 1);
     map.insert("synthetic-implementations".to_owned(), 1);
     map.insert("blanket-implementations".to_owned(), 1);
-    map.insert("deref-methods".to_owned(), 1);
     map
 }
 
diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs
index c408e576639..497cbbb4250 100644
--- a/src/librustdoc/html/render/cache.rs
+++ b/src/librustdoc/html/render/cache.rs
@@ -78,7 +78,7 @@ crate fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
                 ty: item.type_(),
                 name: item.name.unwrap().to_string(),
                 path: fqp[..fqp.len() - 1].join("::"),
-                desc: item.doc_value().map_or_else(|| String::new(), short_markdown_summary),
+                desc: item.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s)),
                 parent: Some(did),
                 parent_idx: None,
                 search_type: get_index_search_type(&item),
@@ -127,7 +127,7 @@ crate fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
     let crate_doc = krate
         .module
         .as_ref()
-        .map(|module| module.doc_value().map_or_else(|| String::new(), short_markdown_summary))
+        .map(|module| module.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s)))
         .unwrap_or_default();
 
     #[derive(Serialize)]
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index c19262b72cf..6a32be60991 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -30,7 +30,6 @@ crate mod cache;
 #[cfg(test)]
 mod tests;
 
-use std::borrow::Cow;
 use std::cell::{Cell, RefCell};
 use std::cmp::Ordering;
 use std::collections::{BTreeMap, VecDeque};
@@ -116,6 +115,9 @@ crate struct Context<'tcx> {
     crate render_redirect_pages: bool,
     /// The map used to ensure all generated 'id=' attributes are unique.
     id_map: Rc<RefCell<IdMap>>,
+    /// Tracks section IDs for `Deref` targets so they match in both the main
+    /// body and the sidebar.
+    deref_id_map: Rc<RefCell<FxHashMap<DefId, String>>>,
     crate shared: Arc<SharedContext<'tcx>>,
     all: Rc<RefCell<AllTypes>>,
     /// Storage for the errors produced while generating documentation so they
@@ -198,12 +200,8 @@ impl SharedContext<'_> {
 
     /// Based on whether the `collapse-docs` pass was run, return either the `doc_value` or the
     /// `collapsed_doc_value` of the given item.
-    crate fn maybe_collapsed_doc_value<'a>(&self, item: &'a clean::Item) -> Option<Cow<'a, str>> {
-        if self.collapsed {
-            item.collapsed_doc_value().map(|s| s.into())
-        } else {
-            item.doc_value().map(|s| s.into())
-        }
+    crate fn maybe_collapsed_doc_value<'a>(&self, item: &'a clean::Item) -> Option<String> {
+        if self.collapsed { item.collapsed_doc_value() } else { item.doc_value() }
     }
 }
 
@@ -377,7 +375,6 @@ crate fn initial_ids() -> Vec<String> {
         "implementors-list",
         "synthetic-implementors-list",
         "methods",
-        "deref-methods",
         "implementations",
     ]
     .iter()
@@ -511,6 +508,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             dst,
             render_redirect_pages: false,
             id_map: Rc::new(RefCell::new(id_map)),
+            deref_id_map: Rc::new(RefCell::new(FxHashMap::default())),
             shared: Arc::new(scx),
             all: Rc::new(RefCell::new(AllTypes::new())),
             errors: Rc::new(receiver),
@@ -979,7 +977,7 @@ themePicker.onblur = handleThemeButtonsBlur;
                 .iter()
                 .map(|s| format!("\"{}\"", s.to_str().expect("invalid osstring conversion")))
                 .collect::<Vec<_>>();
-            files.sort_unstable_by(|a, b| a.cmp(b));
+            files.sort_unstable();
             let subs = subs.iter().map(|s| s.to_json_string()).collect::<Vec<_>>().join(",");
             let dirs =
                 if subs.is_empty() { String::new() } else { format!(",\"dirs\":[{}]", subs) };
@@ -1428,7 +1426,7 @@ impl Setting {
                     .map(|opt| format!(
                         "<option value=\"{}\" {}>{}</option>",
                         opt.0,
-                        if &opt.0 == default_value { "selected" } else { "" },
+                        if opt.0 == default_value { "selected" } else { "" },
                         opt.1,
                     ))
                     .collect::<String>(),
@@ -1595,7 +1593,7 @@ impl Context<'_> {
             if let Some(&(ref names, ty)) = cache.paths.get(&it.def_id) {
                 for name in &names[..names.len() - 1] {
                     url.push_str(name);
-                    url.push_str("/");
+                    url.push('/');
                 }
                 url.push_str(&item_path(ty, names.last().unwrap()));
                 layout::redirect(&url)
@@ -1622,7 +1620,7 @@ impl Context<'_> {
             let short = short.to_string();
             map.entry(short).or_default().push((
                 myname,
-                Some(item.doc_value().map_or_else(|| String::new(), plain_text_summary)),
+                Some(item.doc_value().map_or_else(String::new, |s| plain_text_summary(&s))),
             ));
         }
 
@@ -1880,7 +1878,7 @@ fn document_short(
         return;
     }
     if let Some(s) = item.doc_value() {
-        let mut summary_html = MarkdownSummaryLine(s, &item.links()).into_string();
+        let mut summary_html = MarkdownSummaryLine(&s, &item.links()).into_string();
 
         if s.contains('\n') {
             let link = format!(r#" <a href="{}">Read more</a>"#, naive_assoc_href(item, link));
@@ -2197,7 +2195,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
                 let stab = myitem.stability_class(cx.tcx());
                 let add = if stab.is_some() { " " } else { "" };
 
-                let doc_value = myitem.doc_value().unwrap_or("");
+                let doc_value = myitem.doc_value().unwrap_or_default();
                 write!(
                     w,
                     "<tr class=\"{stab}{add}module-item\">\
@@ -2207,7 +2205,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
                      </tr>",
                     name = *myitem.name.as_ref().unwrap(),
                     stab_tags = extra_info_tags(myitem, item, cx.tcx()),
-                    docs = MarkdownSummaryLine(doc_value, &myitem.links()).into_string(),
+                    docs = MarkdownSummaryLine(&doc_value, &myitem.links()).into_string(),
                     class = myitem.type_(),
                     add = add,
                     stab = stab.unwrap_or_else(String::new),
@@ -2308,7 +2306,7 @@ fn short_item_info(
             let since = &since.as_str();
             if !stability::deprecation_in_effect(is_since_rustc_version, Some(since)) {
                 if *since == "TBD" {
-                    format!("Deprecating in a future Rust version")
+                    String::from("Deprecating in a future Rust version")
                 } else {
                     format!("Deprecating in {}", Escape(since))
                 }
@@ -3522,14 +3520,18 @@ fn render_assoc_items(
                 RenderMode::Normal
             }
             AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
+                let id =
+                    cx.derive_id(small_url_encode(&format!("deref-methods-{:#}", type_.print())));
+                cx.deref_id_map.borrow_mut().insert(type_.def_id().unwrap(), id.clone());
                 write!(
                     w,
-                    "<h2 id=\"deref-methods\" class=\"small-section-header\">\
-                         Methods from {}&lt;Target = {}&gt;\
-                         <a href=\"#deref-methods\" class=\"anchor\"></a>\
+                    "<h2 id=\"{id}\" class=\"small-section-header\">\
+                         Methods from {trait_}&lt;Target = {type_}&gt;\
+                         <a href=\"#{id}\" class=\"anchor\"></a>\
                      </h2>",
-                    trait_.print(),
-                    type_.print()
+                    id = id,
+                    trait_ = trait_.print(),
+                    type_ = type_.print(),
                 );
                 RenderMode::ForDeref { mut_: deref_mut_ }
             }
@@ -3553,9 +3555,6 @@ fn render_assoc_items(
             );
         }
     }
-    if let AssocItemRender::DerefFor { .. } = what {
-        return;
-    }
     if !traits.is_empty() {
         let deref_impl =
             traits.iter().find(|t| t.inner_impl().trait_.def_id() == cache.deref_trait_did);
@@ -3565,6 +3564,12 @@ fn render_assoc_items(
             render_deref_methods(w, cx, impl_, containing_item, has_deref_mut, cache);
         }
 
+        // If we were already one level into rendering deref methods, we don't want to render
+        // anything after recursing into any further deref methods above.
+        if let AssocItemRender::DerefFor { .. } = what {
+            return;
+        }
+
         let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) =
             traits.iter().partition(|t| t.inner_impl().synthetic);
         let (blanket_impl, concrete): (Vec<&&Impl>, _) =
@@ -3636,6 +3641,13 @@ fn render_deref_methods(
     let what =
         AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut };
     if let Some(did) = target.def_id() {
+        if let Some(type_did) = impl_.inner_impl().for_.def_id() {
+            // `impl Deref<Target = S> for S`
+            if did == type_did {
+                // Avoid infinite cycles
+                return;
+            }
+        }
         render_assoc_items(w, cx, container_item, did, what, cache);
     } else {
         if let Some(prim) = target.primitive_type() {
@@ -4170,14 +4182,14 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer, cache:
         );
     }
     match *it.kind {
-        clean::StructItem(ref s) => sidebar_struct(buffer, it, s),
-        clean::TraitItem(ref t) => sidebar_trait(buffer, it, t),
-        clean::PrimitiveItem(_) => sidebar_primitive(buffer, it),
-        clean::UnionItem(ref u) => sidebar_union(buffer, it, u),
-        clean::EnumItem(ref e) => sidebar_enum(buffer, it, e),
-        clean::TypedefItem(_, _) => sidebar_typedef(buffer, it),
+        clean::StructItem(ref s) => sidebar_struct(cx, buffer, it, s),
+        clean::TraitItem(ref t) => sidebar_trait(cx, buffer, it, t),
+        clean::PrimitiveItem(_) => sidebar_primitive(cx, buffer, it),
+        clean::UnionItem(ref u) => sidebar_union(cx, buffer, it, u),
+        clean::EnumItem(ref e) => sidebar_enum(cx, buffer, it, e),
+        clean::TypedefItem(_, _) => sidebar_typedef(cx, buffer, it),
         clean::ModuleItem(ref m) => sidebar_module(buffer, &m.items),
-        clean::ForeignTypeItem => sidebar_foreign_type(buffer, it),
+        clean::ForeignTypeItem => sidebar_foreign_type(cx, buffer, it),
         _ => (),
     }
 
@@ -4278,7 +4290,7 @@ fn small_url_encode(s: &str) -> String {
         .replace("\"", "%22")
 }
 
-fn sidebar_assoc_items(it: &clean::Item) -> String {
+fn sidebar_assoc_items(cx: &Context<'_>, it: &clean::Item) -> String {
     let mut out = String::new();
     let c = cache();
     if let Some(v) = c.impls.get(&it.def_id) {
@@ -4308,69 +4320,22 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
                 .filter(|i| i.inner_impl().trait_.is_some())
                 .find(|i| i.inner_impl().trait_.def_id() == c.deref_trait_did)
             {
-                if let Some((target, real_target)) =
-                    impl_.inner_impl().items.iter().find_map(|item| match *item.kind {
-                        clean::TypedefItem(ref t, true) => Some(match *t {
-                            clean::Typedef { item_type: Some(ref type_), .. } => (type_, &t.type_),
-                            _ => (&t.type_, &t.type_),
-                        }),
-                        _ => None,
-                    })
-                {
-                    let deref_mut = v
-                        .iter()
-                        .filter(|i| i.inner_impl().trait_.is_some())
-                        .any(|i| i.inner_impl().trait_.def_id() == c.deref_mut_trait_did);
-                    let inner_impl = target
-                        .def_id()
-                        .or(target
-                            .primitive_type()
-                            .and_then(|prim| c.primitive_locations.get(&prim).cloned()))
-                        .and_then(|did| c.impls.get(&did));
-                    if let Some(impls) = inner_impl {
-                        out.push_str("<a class=\"sidebar-title\" href=\"#deref-methods\">");
-                        out.push_str(&format!(
-                            "Methods from {}&lt;Target={}&gt;",
-                            Escape(&format!(
-                                "{:#}",
-                                impl_.inner_impl().trait_.as_ref().unwrap().print()
-                            )),
-                            Escape(&format!("{:#}", real_target.print()))
-                        ));
-                        out.push_str("</a>");
-                        let mut ret = impls
-                            .iter()
-                            .filter(|i| i.inner_impl().trait_.is_none())
-                            .flat_map(|i| {
-                                get_methods(i.inner_impl(), true, &mut used_links, deref_mut)
-                            })
-                            .collect::<Vec<_>>();
-                        // We want links' order to be reproducible so we don't use unstable sort.
-                        ret.sort();
-                        if !ret.is_empty() {
-                            out.push_str(&format!(
-                                "<div class=\"sidebar-links\">{}</div>",
-                                ret.join("")
-                            ));
-                        }
-                    }
-                }
+                out.push_str(&sidebar_deref_methods(cx, impl_, v));
             }
             let format_impls = |impls: Vec<&Impl>| {
                 let mut links = FxHashSet::default();
 
                 let mut ret = impls
                     .iter()
-                    .filter_map(|i| {
-                        let is_negative_impl = is_negative_impl(i.inner_impl());
-                        if let Some(ref i) = i.inner_impl().trait_ {
+                    .filter_map(|it| {
+                        if let Some(ref i) = it.inner_impl().trait_ {
                             let i_display = format!("{:#}", i.print());
                             let out = Escape(&i_display);
                             let encoded = small_url_encode(&format!("{:#}", i.print()));
                             let generated = format!(
                                 "<a href=\"#impl-{}\">{}{}</a>",
                                 encoded,
-                                if is_negative_impl { "!" } else { "" },
+                                if it.inner_impl().negative_polarity { "!" } else { "" },
                                 out
                             );
                             if links.insert(generated.clone()) { Some(generated) } else { None }
@@ -4422,7 +4387,81 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
     out
 }
 
-fn sidebar_struct(buf: &mut Buffer, it: &clean::Item, s: &clean::Struct) {
+fn sidebar_deref_methods(cx: &Context<'_>, impl_: &Impl, v: &Vec<Impl>) -> String {
+    let mut out = String::new();
+    let c = cache();
+
+    debug!("found Deref: {:?}", impl_);
+    if let Some((target, real_target)) =
+        impl_.inner_impl().items.iter().find_map(|item| match *item.kind {
+            clean::TypedefItem(ref t, true) => Some(match *t {
+                clean::Typedef { item_type: Some(ref type_), .. } => (type_, &t.type_),
+                _ => (&t.type_, &t.type_),
+            }),
+            _ => None,
+        })
+    {
+        debug!("found target, real_target: {:?} {:?}", target, real_target);
+        let deref_mut = v
+            .iter()
+            .filter(|i| i.inner_impl().trait_.is_some())
+            .any(|i| i.inner_impl().trait_.def_id() == c.deref_mut_trait_did);
+        let inner_impl = target
+            .def_id()
+            .or_else(|| {
+                target.primitive_type().and_then(|prim| c.primitive_locations.get(&prim).cloned())
+            })
+            .and_then(|did| c.impls.get(&did));
+        if let Some(impls) = inner_impl {
+            debug!("found inner_impl: {:?}", impls);
+            let mut used_links = FxHashSet::default();
+            let mut ret = impls
+                .iter()
+                .filter(|i| i.inner_impl().trait_.is_none())
+                .flat_map(|i| get_methods(i.inner_impl(), true, &mut used_links, deref_mut))
+                .collect::<Vec<_>>();
+            if !ret.is_empty() {
+                let deref_id_map = cx.deref_id_map.borrow();
+                let id = deref_id_map
+                    .get(&real_target.def_id().unwrap())
+                    .expect("Deref section without derived id");
+                out.push_str(&format!(
+                    "<a class=\"sidebar-title\" href=\"#{}\">Methods from {}&lt;Target={}&gt;</a>",
+                    id,
+                    Escape(&format!("{:#}", impl_.inner_impl().trait_.as_ref().unwrap().print())),
+                    Escape(&format!("{:#}", real_target.print())),
+                ));
+                // We want links' order to be reproducible so we don't use unstable sort.
+                ret.sort();
+                out.push_str(&format!("<div class=\"sidebar-links\">{}</div>", ret.join("")));
+            }
+        }
+
+        // Recurse into any further impls that might exist for `target`
+        if let Some(target_did) = target.def_id() {
+            if let Some(target_impls) = c.impls.get(&target_did) {
+                if let Some(target_deref_impl) = target_impls
+                    .iter()
+                    .filter(|i| i.inner_impl().trait_.is_some())
+                    .find(|i| i.inner_impl().trait_.def_id() == c.deref_trait_did)
+                {
+                    if let Some(type_did) = impl_.inner_impl().for_.def_id() {
+                        // `impl Deref<Target = S> for S`
+                        if target_did == type_did {
+                            // Avoid infinite cycles
+                            return out;
+                        }
+                    }
+                    out.push_str(&sidebar_deref_methods(cx, target_deref_impl, target_impls));
+                }
+            }
+        }
+    }
+
+    out
+}
+
+fn sidebar_struct(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, s: &clean::Struct) {
     let mut sidebar = String::new();
     let fields = get_struct_fields_name(&s.fields);
 
@@ -4436,7 +4475,7 @@ fn sidebar_struct(buf: &mut Buffer, it: &clean::Item, s: &clean::Struct) {
         }
     }
 
-    sidebar.push_str(&sidebar_assoc_items(it));
+    sidebar.push_str(&sidebar_assoc_items(cx, it));
 
     if !sidebar.is_empty() {
         write!(buf, "<div class=\"block items\">{}</div>", sidebar);
@@ -4463,11 +4502,7 @@ fn extract_for_impl_name(item: &clean::Item) -> Option<(String, String)> {
     }
 }
 
-fn is_negative_impl(i: &clean::Impl) -> bool {
-    i.polarity == Some(clean::ImplPolarity::Negative)
-}
-
-fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
+fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
     let mut sidebar = String::new();
 
     let mut types = t
@@ -4567,7 +4602,7 @@ fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
         }
     }
 
-    sidebar.push_str(&sidebar_assoc_items(it));
+    sidebar.push_str(&sidebar_assoc_items(cx, it));
 
     sidebar.push_str("<a class=\"sidebar-title\" href=\"#implementors\">Implementors</a>");
     if t.is_auto {
@@ -4580,16 +4615,16 @@ fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
     write!(buf, "<div class=\"block items\">{}</div>", sidebar)
 }
 
-fn sidebar_primitive(buf: &mut Buffer, it: &clean::Item) {
-    let sidebar = sidebar_assoc_items(it);
+fn sidebar_primitive(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) {
+    let sidebar = sidebar_assoc_items(cx, it);
 
     if !sidebar.is_empty() {
         write!(buf, "<div class=\"block items\">{}</div>", sidebar);
     }
 }
 
-fn sidebar_typedef(buf: &mut Buffer, it: &clean::Item) {
-    let sidebar = sidebar_assoc_items(it);
+fn sidebar_typedef(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) {
+    let sidebar = sidebar_assoc_items(cx, it);
 
     if !sidebar.is_empty() {
         write!(buf, "<div class=\"block items\">{}</div>", sidebar);
@@ -4611,7 +4646,7 @@ fn get_struct_fields_name(fields: &[clean::Item]) -> String {
     fields.join("")
 }
 
-fn sidebar_union(buf: &mut Buffer, it: &clean::Item, u: &clean::Union) {
+fn sidebar_union(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, u: &clean::Union) {
     let mut sidebar = String::new();
     let fields = get_struct_fields_name(&u.fields);
 
@@ -4623,14 +4658,14 @@ fn sidebar_union(buf: &mut Buffer, it: &clean::Item, u: &clean::Union) {
         ));
     }
 
-    sidebar.push_str(&sidebar_assoc_items(it));
+    sidebar.push_str(&sidebar_assoc_items(cx, it));
 
     if !sidebar.is_empty() {
         write!(buf, "<div class=\"block items\">{}</div>", sidebar);
     }
 }
 
-fn sidebar_enum(buf: &mut Buffer, it: &clean::Item, e: &clean::Enum) {
+fn sidebar_enum(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, e: &clean::Enum) {
     let mut sidebar = String::new();
 
     let mut variants = e
@@ -4650,7 +4685,7 @@ fn sidebar_enum(buf: &mut Buffer, it: &clean::Item, e: &clean::Enum) {
         ));
     }
 
-    sidebar.push_str(&sidebar_assoc_items(it));
+    sidebar.push_str(&sidebar_assoc_items(cx, it));
 
     if !sidebar.is_empty() {
         write!(buf, "<div class=\"block items\">{}</div>", sidebar);
@@ -4739,8 +4774,8 @@ fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) {
     }
 }
 
-fn sidebar_foreign_type(buf: &mut Buffer, it: &clean::Item) {
-    let sidebar = sidebar_assoc_items(it);
+fn sidebar_foreign_type(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) {
+    let sidebar = sidebar_assoc_items(cx, it);
     if !sidebar.is_empty() {
         write!(buf, "<div class=\"block items\">{}</div>", sidebar);
     }
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 1de4b0016c5..ec8024ffca5 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -493,11 +493,7 @@ function defocusSearchBar() {
     document.addEventListener("keypress", handleShortcut);
     document.addEventListener("keydown", handleShortcut);
 
-    function resetMouseMoved(ev) {
-        mouseMovedAfterSearch = true;
-    }
-
-    document.addEventListener("mousemove", resetMouseMoved);
+    document.addEventListener("mousemove", function() { mouseMovedAfterSearch = true; });
 
     var handleSourceHighlight = (function() {
         var prev_line_id = 0;
@@ -667,13 +663,7 @@ function defocusSearchBar() {
                 results = {}, results_in_args = {}, results_returned = {},
                 split = valLower.split("::");
 
-            var length = split.length;
-            for (var z = 0; z < length; ++z) {
-                if (split[z] === "") {
-                    split.splice(z, 1);
-                    z -= 1;
-                }
-            }
+            split = split.filter(function(segment) { return segment !== ""; });
 
             function transformResults(results, isType) {
                 var out = [];
@@ -2157,14 +2147,14 @@ function defocusSearchBar() {
                 var code = document.createElement("code");
                 code.innerHTML = struct.text;
 
-                var x = code.getElementsByTagName("a");
-                var xlength = x.length;
-                for (var it = 0; it < xlength; it++) {
-                    var href = x[it].getAttribute("href");
+                onEachLazy(code.getElementsByTagName("a"), function(elem) {
+                    var href = elem.getAttribute("href");
+
                     if (href && href.indexOf("http") !== 0) {
-                        x[it].setAttribute("href", rootPath + href);
+                        elem.setAttribute("href", rootPath + href);
                     }
-                }
+                });
+
                 var display = document.createElement("h3");
                 addClass(display, "impl");
                 display.innerHTML = "<span class=\"in-band\"><table class=\"table-display\">" +
@@ -2553,14 +2543,12 @@ function defocusSearchBar() {
             var hiddenElems = e.getElementsByClassName("hidden");
             var needToggle = false;
 
-            var hlength = hiddenElems.length;
-            for (var i = 0; i < hlength; ++i) {
-                if (hasClass(hiddenElems[i], "content") === false &&
-                    hasClass(hiddenElems[i], "docblock") === false) {
-                    needToggle = true;
-                    break;
+            var needToggle = onEachLazy(e.getElementsByClassName("hidden"), function(hiddenElem) {
+                if (hasClass(hiddenElem, "content") === false &&
+                    hasClass(hiddenElem, "docblock") === false) {
+                    return true;
                 }
-            }
+            });
             if (needToggle === true) {
                 var inner_toggle = newToggle.cloneNode(true);
                 inner_toggle.onclick = toggleClicked;
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 62b08e519bf..8dad26dced9 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -1412,6 +1412,7 @@ h4 > .notable-traits {
 	.sidebar > .block.version {
 		border-bottom: none;
 		margin-top: 12px;
+		margin-bottom: 0;
 	}
 
 	nav.sub {
@@ -1582,7 +1583,10 @@ h4 > .notable-traits {
 		height: 73px;
 	}
 
-	#main {
+	/* This is to prevent the search bar from being underneath the <section>
+	 * element following it.
+	 */
+	#main, #search {
 		margin-top: 100px;
 	}
 
diff --git a/src/librustdoc/html/toc.rs b/src/librustdoc/html/toc.rs
index b39a4e179cd..c55f2459a9c 100644
--- a/src/librustdoc/html/toc.rs
+++ b/src/librustdoc/html/toc.rs
@@ -132,7 +132,7 @@ impl TocBuilder {
                 }
                 Some(entry) => {
                     sec_number = entry.sec_number.clone();
-                    sec_number.push_str(".");
+                    sec_number.push('.');
                     (entry.level, &entry.children)
                 }
             };
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index e347f7f8411..5dea64ef145 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -422,7 +422,7 @@ impl From<clean::Impl> for Impl {
             trait_,
             for_,
             items,
-            polarity,
+            negative_polarity,
             synthetic,
             blanket_impl,
         } = impl_;
@@ -436,7 +436,7 @@ impl From<clean::Impl> for Impl {
             trait_: trait_.map(Into::into),
             for_: for_.into(),
             items: ids(items),
-            negative: polarity == Some(clean::ImplPolarity::Negative),
+            negative: negative_polarity,
             synthetic,
             blanket_impl: blanket_impl.map(Into::into),
         }
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index 0a00323a317..05a3a15adac 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -235,12 +235,7 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> {
                 let mut tests = Tests { found_tests: 0 };
 
                 find_testable_code(
-                    &i.attrs
-                        .doc_strings
-                        .iter()
-                        .map(|d| d.doc.as_str())
-                        .collect::<Vec<_>>()
-                        .join("\n"),
+                    &i.attrs.collapsed_doc_value().unwrap_or_default(),
                     &mut tests,
                     ErrorCodes::No,
                     false,
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs
index 0c76dc571be..554392c213e 100644
--- a/src/librustdoc/passes/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/check_code_block_syntax.rs
@@ -51,10 +51,10 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
             let mut diag = if let Some(sp) =
                 super::source_span_for_markdown_range(self.cx, &dox, &code_block.range, &item.attrs)
             {
-                let warning_message = if buffer.has_errors {
-                    "could not parse code block as Rust code"
+                let (warning_message, suggest_using_text) = if buffer.has_errors {
+                    ("could not parse code block as Rust code", true)
                 } else {
-                    "Rust code block is empty"
+                    ("Rust code block is empty", false)
                 };
 
                 let mut diag = self.cx.sess().struct_span_warn(sp, warning_message);
@@ -67,6 +67,15 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
                         String::from("```text"),
                         Applicability::MachineApplicable,
                     );
+                } else if suggest_using_text && code_block.is_ignore {
+                    let sp = sp.from_inner(InnerSpan::new(0, 3));
+                    diag.span_suggestion(
+                        sp,
+                        "`ignore` code blocks require valid Rust code for syntax highlighting. \
+                         Mark blocks that do not contain Rust code as text",
+                        String::from("```text,"),
+                        Applicability::MachineApplicable,
+                    );
                 }
 
                 diag
diff --git a/src/librustdoc/passes/collapse_docs.rs b/src/librustdoc/passes/collapse_docs.rs
deleted file mode 100644
index e1ba75baa0f..00000000000
--- a/src/librustdoc/passes/collapse_docs.rs
+++ /dev/null
@@ -1,72 +0,0 @@
-use crate::clean::{self, DocFragment, DocFragmentKind, Item};
-use crate::core::DocContext;
-use crate::fold;
-use crate::fold::DocFolder;
-use crate::passes::Pass;
-
-use std::mem::take;
-
-crate const COLLAPSE_DOCS: Pass = Pass {
-    name: "collapse-docs",
-    run: collapse_docs,
-    description: "concatenates all document attributes into one document attribute",
-};
-
-crate fn collapse_docs(krate: clean::Crate, _: &DocContext<'_>) -> clean::Crate {
-    let mut krate = Collapser.fold_crate(krate);
-    krate.collapsed = true;
-    krate
-}
-
-struct Collapser;
-
-impl fold::DocFolder for Collapser {
-    fn fold_item(&mut self, mut i: Item) -> Option<Item> {
-        i.attrs.collapse_doc_comments();
-        Some(self.fold_item_recur(i))
-    }
-}
-
-fn collapse(doc_strings: &mut Vec<DocFragment>) {
-    let mut docs = vec![];
-    let mut last_frag: Option<DocFragment> = None;
-
-    for frag in take(doc_strings) {
-        if let Some(mut curr_frag) = last_frag.take() {
-            let curr_kind = &curr_frag.kind;
-            let new_kind = &frag.kind;
-
-            if matches!(*curr_kind, DocFragmentKind::Include { .. })
-                || curr_kind != new_kind
-                || curr_frag.parent_module != frag.parent_module
-            {
-                if *curr_kind == DocFragmentKind::SugaredDoc
-                    || *curr_kind == DocFragmentKind::RawDoc
-                {
-                    // add a newline for extra padding between segments
-                    curr_frag.doc.push('\n');
-                }
-                docs.push(curr_frag);
-                last_frag = Some(frag);
-            } else {
-                curr_frag.doc.push('\n');
-                curr_frag.doc.push_str(&frag.doc);
-                curr_frag.span = curr_frag.span.to(frag.span);
-                last_frag = Some(curr_frag);
-            }
-        } else {
-            last_frag = Some(frag);
-        }
-    }
-
-    if let Some(frag) = last_frag.take() {
-        docs.push(frag);
-    }
-    *doc_strings = docs;
-}
-
-impl clean::Attributes {
-    crate fn collapse_doc_comments(&mut self) {
-        collapse(&mut self.doc_strings);
-    }
-}
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 9f15038a353..708d7710058 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -25,6 +25,8 @@ use rustc_span::symbol::Symbol;
 use rustc_span::DUMMY_SP;
 use smallvec::{smallvec, SmallVec};
 
+use pulldown_cmark::LinkType;
+
 use std::borrow::Cow;
 use std::cell::Cell;
 use std::convert::{TryFrom, TryInto};
@@ -34,7 +36,7 @@ use std::ops::Range;
 use crate::clean::{self, utils::find_nearest_parent_module, Crate, Item, ItemLink, PrimitiveType};
 use crate::core::DocContext;
 use crate::fold::DocFolder;
-use crate::html::markdown::markdown_links;
+use crate::html::markdown::{markdown_links, MarkdownLink};
 use crate::passes::Pass;
 
 use super::span_of_attrs;
@@ -245,7 +247,7 @@ struct DiagnosticInfo<'a> {
     item: &'a Item,
     dox: &'a str,
     ori_link: &'a str,
-    link_range: Option<Range<usize>>,
+    link_range: Range<usize>,
 }
 
 #[derive(Clone, Debug, Hash)]
@@ -265,8 +267,9 @@ struct LinkCollector<'a, 'tcx> {
     /// because `clean` and the disambiguator code expect them to be different.
     /// See the code for associated items on inherent impls for details.
     kind_side_channel: Cell<Option<(DefKind, DefId)>>,
-    /// Cache the resolved links so we can avoid resolving (and emitting errors for) the same link
-    visited_links: FxHashMap<ResolutionInfo, CachedLink>,
+    /// Cache the resolved links so we can avoid resolving (and emitting errors for) the same link.
+    /// The link will be `None` if it could not be resolved (i.e. the error was cached).
+    visited_links: FxHashMap<ResolutionInfo, Option<CachedLink>>,
 }
 
 impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
@@ -391,10 +394,14 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                         ns,
                         impl_,
                     )
-                    .map(|item| match item.kind {
-                        ty::AssocKind::Fn => "method",
-                        ty::AssocKind::Const => "associatedconstant",
-                        ty::AssocKind::Type => "associatedtype",
+                    .map(|item| {
+                        let kind = item.kind;
+                        self.kind_side_channel.set(Some((kind.as_def_kind(), item.def_id)));
+                        match kind {
+                            ty::AssocKind::Fn => "method",
+                            ty::AssocKind::Const => "associatedconstant",
+                            ty::AssocKind::Type => "associatedtype",
+                        }
                     })
                     .map(|out| {
                         (
@@ -497,15 +504,9 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
             match res {
                 // FIXME(#76467): make this fallthrough to lookup the associated
                 // item a separate function.
-                Res::Def(DefKind::AssocFn | DefKind::AssocConst, _) => {
-                    assert_eq!(ns, ValueNS);
-                }
-                Res::Def(DefKind::AssocTy, _) => {
-                    assert_eq!(ns, TypeNS);
-                }
-                Res::Def(DefKind::Variant, _) => {
-                    return handle_variant(cx, res, extra_fragment);
-                }
+                Res::Def(DefKind::AssocFn | DefKind::AssocConst, _) => assert_eq!(ns, ValueNS),
+                Res::Def(DefKind::AssocTy, _) => assert_eq!(ns, TypeNS),
+                Res::Def(DefKind::Variant, _) => return handle_variant(cx, res, extra_fragment),
                 // Not a trait item; just return what we found.
                 Res::Primitive(ty) => {
                     if extra_fragment.is_some() {
@@ -515,12 +516,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                     }
                     return Ok((res, Some(ty.as_str().to_owned())));
                 }
-                Res::Def(DefKind::Mod, _) => {
-                    return Ok((res, extra_fragment.clone()));
-                }
-                _ => {
-                    return Ok((res, extra_fragment.clone()));
-                }
+                _ => return Ok((res, extra_fragment.clone())),
             }
         }
 
@@ -891,43 +887,18 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
         // In the presence of re-exports, this is not the same as the module of the item.
         // Rather than merging all documentation into one, resolve it one attribute at a time
         // so we know which module it came from.
-        let mut attrs = item.attrs.doc_strings.iter().peekable();
-        while let Some(attr) = attrs.next() {
-            // `collapse_docs` does not have the behavior we want:
-            // we want `///` and `#[doc]` to count as the same attribute,
-            // but currently it will treat them as separate.
-            // As a workaround, combine all attributes with the same parent module into the same attribute.
-            let mut combined_docs = attr.doc.clone();
-            loop {
-                match attrs.peek() {
-                    Some(next) if next.parent_module == attr.parent_module => {
-                        combined_docs.push('\n');
-                        combined_docs.push_str(&attrs.next().unwrap().doc);
-                    }
-                    _ => break,
-                }
-            }
-            debug!("combined_docs={}", combined_docs);
+        for (parent_module, doc) in item.attrs.collapsed_doc_value_by_module_level() {
+            debug!("combined_docs={}", doc);
 
-            let (krate, parent_node) = if let Some(id) = attr.parent_module {
-                trace!("docs {:?} came from {:?}", attr.doc, id);
+            let (krate, parent_node) = if let Some(id) = parent_module {
                 (id.krate, Some(id))
             } else {
-                trace!("no parent found for {:?}", attr.doc);
                 (item.def_id.krate, parent_node)
             };
             // NOTE: if there are links that start in one crate and end in another, this will not resolve them.
             // This is a degenerate case and it's not supported by rustdoc.
-            for (ori_link, link_range) in markdown_links(&combined_docs) {
-                let link = self.resolve_link(
-                    &item,
-                    &combined_docs,
-                    &self_name,
-                    parent_node,
-                    krate,
-                    ori_link,
-                    link_range,
-                );
+            for md_link in markdown_links(&doc) {
+                let link = self.resolve_link(&item, &doc, &self_name, parent_node, krate, md_link);
                 if let Some(link) = link {
                     item.attrs.links.push(link);
                 }
@@ -959,27 +930,26 @@ impl LinkCollector<'_, '_> {
         self_name: &Option<String>,
         parent_node: Option<DefId>,
         krate: CrateNum,
-        ori_link: String,
-        link_range: Option<Range<usize>>,
+        ori_link: MarkdownLink,
     ) -> Option<ItemLink> {
-        trace!("considering link '{}'", ori_link);
+        trace!("considering link '{}'", ori_link.link);
 
         // Bail early for real links.
-        if ori_link.contains('/') {
+        if ori_link.link.contains('/') {
             return None;
         }
 
         // [] is mostly likely not supposed to be a link
-        if ori_link.is_empty() {
+        if ori_link.link.is_empty() {
             return None;
         }
 
         let cx = self.cx;
-        let link = ori_link.replace("`", "");
+        let link = ori_link.link.replace("`", "");
         let parts = link.split('#').collect::<Vec<_>>();
         let (link, extra_fragment) = if parts.len() > 2 {
             // A valid link can't have multiple #'s
-            anchor_failure(cx, &item, &link, dox, link_range, AnchorFailure::MultipleAnchors);
+            anchor_failure(cx, &item, &link, dox, ori_link.range, AnchorFailure::MultipleAnchors);
             return None;
         } else if parts.len() == 2 {
             if parts[0].trim().is_empty() {
@@ -1035,7 +1005,7 @@ impl LinkCollector<'_, '_> {
                 path_str,
                 disambiguator,
                 dox,
-                link_range,
+                ori_link.range,
                 smallvec![ResolutionFailure::NoParentItem],
             );
             return None;
@@ -1043,12 +1013,18 @@ impl LinkCollector<'_, '_> {
 
         let resolved_self;
         // replace `Self` with suitable item's parent name
-        if path_str.starts_with("Self::") {
+        let is_lone_self = path_str == "Self";
+        let is_lone_crate = path_str == "crate";
+        if path_str.starts_with("Self::") || is_lone_self {
             if let Some(ref name) = self_name {
-                resolved_self = format!("{}::{}", name, &path_str[6..]);
-                path_str = &resolved_self;
+                if is_lone_self {
+                    path_str = name;
+                } else {
+                    resolved_self = format!("{}::{}", name, &path_str[6..]);
+                    path_str = &resolved_self;
+                }
             }
-        } else if path_str.starts_with("crate::") {
+        } else if path_str.starts_with("crate::") || is_lone_crate {
             use rustc_span::def_id::CRATE_DEF_INDEX;
 
             // HACK(jynelson): rustc_resolve thinks that `crate` is the crate currently being documented.
@@ -1057,8 +1033,12 @@ impl LinkCollector<'_, '_> {
             // HACK(jynelson)(2): If we just strip `crate::` then suddenly primitives become ambiguous
             // (consider `crate::char`). Instead, change it to `self::`. This works because 'self' is now the crate root.
             // FIXME(#78696): This doesn't always work.
-            resolved_self = format!("self::{}", &path_str["crate::".len()..]);
-            path_str = &resolved_self;
+            if is_lone_crate {
+                path_str = "self";
+            } else {
+                resolved_self = format!("self::{}", &path_str["crate::".len()..]);
+                path_str = &resolved_self;
+            }
             module_id = DefId { krate, index: CRATE_DEF_INDEX };
         }
 
@@ -1075,7 +1055,7 @@ impl LinkCollector<'_, '_> {
                         path_str,
                         disambiguator,
                         dox,
-                        link_range,
+                        ori_link.range,
                         smallvec![err_kind],
                     );
                     return None;
@@ -1091,15 +1071,22 @@ impl LinkCollector<'_, '_> {
             return None;
         }
 
-        let key = ResolutionInfo {
-            module_id,
-            dis: disambiguator,
-            path_str: path_str.to_owned(),
-            extra_fragment,
+        let diag_info = DiagnosticInfo {
+            item,
+            dox,
+            ori_link: &ori_link.link,
+            link_range: ori_link.range.clone(),
         };
-        let diag =
-            DiagnosticInfo { item, dox, ori_link: &ori_link, link_range: link_range.clone() };
-        let (mut res, mut fragment) = self.resolve_with_disambiguator_cached(key, diag)?;
+        let (mut res, mut fragment) = self.resolve_with_disambiguator_cached(
+            ResolutionInfo {
+                module_id,
+                dis: disambiguator,
+                path_str: path_str.to_owned(),
+                extra_fragment,
+            },
+            diag_info,
+            matches!(ori_link.kind, LinkType::Reference | LinkType::Shortcut),
+        )?;
 
         // Check for a primitive which might conflict with a module
         // Report the ambiguity and require that the user specify which one they meant.
@@ -1118,7 +1105,7 @@ impl LinkCollector<'_, '_> {
                             &item,
                             path_str,
                             dox,
-                            link_range,
+                            ori_link.range,
                             AnchorFailure::RustdocAnchorConflict(prim),
                         );
                         return None;
@@ -1128,7 +1115,7 @@ impl LinkCollector<'_, '_> {
                 } else {
                     // `[char]` when a `char` module is in scope
                     let candidates = vec![res, prim];
-                    ambiguity_error(cx, &item, path_str, dox, link_range, candidates);
+                    ambiguity_error(cx, &item, path_str, dox, ori_link.range, candidates);
                     return None;
                 }
             }
@@ -1146,61 +1133,89 @@ impl LinkCollector<'_, '_> {
                     specified.descr()
                 );
                 diag.note(&note);
-                suggest_disambiguator(resolved, diag, path_str, dox, sp, &link_range);
+                suggest_disambiguator(resolved, diag, path_str, dox, sp, &ori_link.range);
             };
-            report_diagnostic(cx, BROKEN_INTRA_DOC_LINKS, &msg, &item, dox, &link_range, callback);
+            report_diagnostic(
+                cx,
+                BROKEN_INTRA_DOC_LINKS,
+                &msg,
+                &item,
+                dox,
+                &ori_link.range,
+                callback,
+            );
         };
-        match res {
-            Res::Primitive(_) => match disambiguator {
-                Some(Disambiguator::Primitive | Disambiguator::Namespace(_)) | None => {
-                    Some(ItemLink { link: ori_link, link_text, did: None, fragment })
-                }
-                Some(other) => {
-                    report_mismatch(other, Disambiguator::Primitive);
-                    None
-                }
-            },
-            Res::Def(kind, id) => {
-                debug!("intra-doc link to {} resolved to {:?}", path_str, res);
-
-                // Disallow e.g. linking to enums with `struct@`
-                debug!("saw kind {:?} with disambiguator {:?}", kind, disambiguator);
-                match (self.kind_side_channel.take().map(|(kind, _)| kind).unwrap_or(kind), disambiguator) {
-                    | (DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst, Some(Disambiguator::Kind(DefKind::Const)))
-                    // NOTE: this allows 'method' to mean both normal functions and associated functions
-                    // This can't cause ambiguity because both are in the same namespace.
-                    | (DefKind::Fn | DefKind::AssocFn, Some(Disambiguator::Kind(DefKind::Fn)))
-                    // These are namespaces; allow anything in the namespace to match
-                    | (_, Some(Disambiguator::Namespace(_)))
-                    // If no disambiguator given, allow anything
-                    | (_, None)
-                    // All of these are valid, so do nothing
-                    => {}
-                    (actual, Some(Disambiguator::Kind(expected))) if actual == expected => {}
-                    (_, Some(specified @ Disambiguator::Kind(_) | specified @ Disambiguator::Primitive)) => {
-                        report_mismatch(specified, Disambiguator::Kind(kind));
-                        return None;
-                    }
+
+        let verify = |kind: DefKind, id: DefId| {
+            debug!("intra-doc link to {} resolved to {:?}", path_str, res);
+
+            // Disallow e.g. linking to enums with `struct@`
+            debug!("saw kind {:?} with disambiguator {:?}", kind, disambiguator);
+            match (self.kind_side_channel.take().map(|(kind, _)| kind).unwrap_or(kind), disambiguator) {
+                | (DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst, Some(Disambiguator::Kind(DefKind::Const)))
+                // NOTE: this allows 'method' to mean both normal functions and associated functions
+                // This can't cause ambiguity because both are in the same namespace.
+                | (DefKind::Fn | DefKind::AssocFn, Some(Disambiguator::Kind(DefKind::Fn)))
+                // These are namespaces; allow anything in the namespace to match
+                | (_, Some(Disambiguator::Namespace(_)))
+                // If no disambiguator given, allow anything
+                | (_, None)
+                // All of these are valid, so do nothing
+                => {}
+                (actual, Some(Disambiguator::Kind(expected))) if actual == expected => {}
+                (_, Some(specified @ Disambiguator::Kind(_) | specified @ Disambiguator::Primitive)) => {
+                    report_mismatch(specified, Disambiguator::Kind(kind));
+                    return None;
                 }
+            }
+
+            // item can be non-local e.g. when using #[doc(primitive = "pointer")]
+            if let Some((src_id, dst_id)) = id
+                .as_local()
+                .and_then(|dst_id| item.def_id.as_local().map(|src_id| (src_id, dst_id)))
+            {
+                use rustc_hir::def_id::LOCAL_CRATE;
 
-                // item can be non-local e.g. when using #[doc(primitive = "pointer")]
-                if let Some((src_id, dst_id)) = id
-                    .as_local()
-                    .and_then(|dst_id| item.def_id.as_local().map(|src_id| (src_id, dst_id)))
+                let hir_src = self.cx.tcx.hir().local_def_id_to_hir_id(src_id);
+                let hir_dst = self.cx.tcx.hir().local_def_id_to_hir_id(dst_id);
+
+                if self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_src)
+                    && !self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_dst)
                 {
-                    use rustc_hir::def_id::LOCAL_CRATE;
+                    privacy_error(cx, &item, &path_str, dox, &ori_link);
+                }
+            }
 
-                    let hir_src = self.cx.tcx.hir().local_def_id_to_hir_id(src_id);
-                    let hir_dst = self.cx.tcx.hir().local_def_id_to_hir_id(dst_id);
+            Some((kind, id))
+        };
 
-                    if self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_src)
-                        && !self.cx.tcx.privacy_access_levels(LOCAL_CRATE).is_exported(hir_dst)
-                    {
-                        privacy_error(cx, &item, &path_str, dox, link_range);
+        match res {
+            Res::Primitive(_) => {
+                if let Some((kind, id)) = self.kind_side_channel.take() {
+                    // We're actually resolving an associated item of a primitive, so we need to
+                    // verify the disambiguator (if any) matches the type of the associated item.
+                    // This case should really follow the same flow as the `Res::Def` branch below,
+                    // but attempting to add a call to `clean::register_res` causes an ICE. @jyn514
+                    // thinks `register_res` is only needed for cross-crate re-exports, but Rust
+                    // doesn't allow statements like `use str::trim;`, making this a (hopefully)
+                    // valid omission. See https://github.com/rust-lang/rust/pull/80660#discussion_r551585677
+                    // for discussion on the matter.
+                    verify(kind, id)?;
+                } else {
+                    match disambiguator {
+                        Some(Disambiguator::Primitive | Disambiguator::Namespace(_)) | None => {}
+                        Some(other) => {
+                            report_mismatch(other, Disambiguator::Primitive);
+                            return None;
+                        }
                     }
                 }
+                Some(ItemLink { link: ori_link.link, link_text, did: None, fragment })
+            }
+            Res::Def(kind, id) => {
+                let (kind, id) = verify(kind, id)?;
                 let id = clean::register_res(cx, rustc_hir::def::Res::Def(kind, id));
-                Some(ItemLink { link: ori_link, link_text, did: Some(id), fragment })
+                Some(ItemLink { link: ori_link.link, link_text, did: Some(id), fragment })
             }
         }
     }
@@ -1209,28 +1224,47 @@ impl LinkCollector<'_, '_> {
         &mut self,
         key: ResolutionInfo,
         diag: DiagnosticInfo<'_>,
+        cache_resolution_failure: bool,
     ) -> Option<(Res, Option<String>)> {
         // Try to look up both the result and the corresponding side channel value
         if let Some(ref cached) = self.visited_links.get(&key) {
-            self.kind_side_channel.set(cached.side_channel);
-            return Some(cached.res.clone());
+            match cached {
+                Some(cached) => {
+                    self.kind_side_channel.set(cached.side_channel.clone());
+                    return Some(cached.res.clone());
+                }
+                None if cache_resolution_failure => return None,
+                None => {
+                    // Although we hit the cache and found a resolution error, this link isn't
+                    // supposed to cache those. Run link resolution again to emit the expected
+                    // resolution error.
+                }
+            }
         }
 
         let res = self.resolve_with_disambiguator(&key, diag);
 
         // Cache only if resolved successfully - don't silence duplicate errors
-        if let Some(res) = &res {
+        if let Some(res) = res {
             // Store result for the actual namespace
             self.visited_links.insert(
                 key,
-                CachedLink {
+                Some(CachedLink {
                     res: res.clone(),
                     side_channel: self.kind_side_channel.clone().into_inner(),
-                },
+                }),
             );
-        }
 
-        res
+            Some(res)
+        } else {
+            if cache_resolution_failure {
+                // For reference-style links we only want to report one resolution error
+                // so let's cache them as well.
+                self.visited_links.insert(key, None);
+            }
+
+            None
+        }
     }
 
     /// After parsing the disambiguator, resolve the main part of the link.
@@ -1276,7 +1310,7 @@ impl LinkCollector<'_, '_> {
                         // This could just be a normal link or a broken link
                         // we could potentially check if something is
                         // "intra-doc-link-like" and warn in that case.
-                        return None;
+                        None
                     }
                     Err(ErrorKind::AnchorFailure(msg)) => {
                         anchor_failure(
@@ -1287,7 +1321,7 @@ impl LinkCollector<'_, '_> {
                             diag.link_range,
                             msg,
                         );
-                        return None;
+                        None
                     }
                 }
             }
@@ -1383,7 +1417,7 @@ impl LinkCollector<'_, '_> {
                         diag.link_range,
                         candidates.present_items().collect(),
                     );
-                    return None;
+                    None
                 }
             }
             Some(MacroNS) => {
@@ -1408,7 +1442,7 @@ impl LinkCollector<'_, '_> {
                             diag.link_range,
                             smallvec![kind],
                         );
-                        return None;
+                        None
                     }
                 }
             }
@@ -1606,7 +1640,7 @@ fn report_diagnostic(
     msg: &str,
     item: &Item,
     dox: &str,
-    link_range: &Option<Range<usize>>,
+    link_range: &Range<usize>,
     decorate: impl FnOnce(&mut DiagnosticBuilder<'_>, Option<rustc_span::Span>),
 ) {
     let hir_id = match cx.as_local_hir_id(item.def_id) {
@@ -1624,31 +1658,27 @@ fn report_diagnostic(
     cx.tcx.struct_span_lint_hir(lint, hir_id, sp, |lint| {
         let mut diag = lint.build(msg);
 
-        let span = link_range
-            .as_ref()
-            .and_then(|range| super::source_span_for_markdown_range(cx, dox, range, attrs));
+        let span = super::source_span_for_markdown_range(cx, dox, link_range, attrs);
 
-        if let Some(link_range) = link_range {
-            if let Some(sp) = span {
-                diag.set_span(sp);
-            } else {
-                // blah blah blah\nblah\nblah [blah] blah blah\nblah blah
-                //                       ^     ~~~~
-                //                       |     link_range
-                //                       last_new_line_offset
-                let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
-                let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
-
-                // Print the line containing the `link_range` and manually mark it with '^'s.
-                diag.note(&format!(
-                    "the link appears in this line:\n\n{line}\n\
+        if let Some(sp) = span {
+            diag.set_span(sp);
+        } else {
+            // blah blah blah\nblah\nblah [blah] blah blah\nblah blah
+            //                       ^     ~~~~
+            //                       |     link_range
+            //                       last_new_line_offset
+            let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
+            let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
+
+            // Print the line containing the `link_range` and manually mark it with '^'s.
+            diag.note(&format!(
+                "the link appears in this line:\n\n{line}\n\
                      {indicator: <before$}{indicator:^<found$}",
-                    line = line,
-                    indicator = "",
-                    before = link_range.start - last_new_line_offset,
-                    found = link_range.len(),
-                ));
-            }
+                line = line,
+                indicator = "",
+                before = link_range.start - last_new_line_offset,
+                found = link_range.len(),
+            ));
         }
 
         decorate(&mut diag, span);
@@ -1668,7 +1698,7 @@ fn resolution_failure(
     path_str: &str,
     disambiguator: Option<Disambiguator>,
     dox: &str,
-    link_range: Option<Range<usize>>,
+    link_range: Range<usize>,
     kinds: SmallVec<[ResolutionFailure<'_>; 3]>,
 ) {
     let tcx = collector.cx.tcx;
@@ -1892,7 +1922,7 @@ fn anchor_failure(
     item: &Item,
     path_str: &str,
     dox: &str,
-    link_range: Option<Range<usize>>,
+    link_range: Range<usize>,
     failure: AnchorFailure,
 ) {
     let msg = match failure {
@@ -1917,7 +1947,7 @@ fn ambiguity_error(
     item: &Item,
     path_str: &str,
     dox: &str,
-    link_range: Option<Range<usize>>,
+    link_range: Range<usize>,
     candidates: Vec<Res>,
 ) {
     let mut msg = format!("`{}` is ", path_str);
@@ -1966,13 +1996,12 @@ fn suggest_disambiguator(
     path_str: &str,
     dox: &str,
     sp: Option<rustc_span::Span>,
-    link_range: &Option<Range<usize>>,
+    link_range: &Range<usize>,
 ) {
     let suggestion = disambiguator.suggestion();
     let help = format!("to link to the {}, {}", disambiguator.descr(), suggestion.descr());
 
     if let Some(sp) = sp {
-        let link_range = link_range.as_ref().expect("must have a link range if we have a span");
         let msg = if dox.bytes().nth(link_range.start) == Some(b'`') {
             format!("`{}`", suggestion.as_help(path_str))
         } else {
@@ -1986,13 +2015,7 @@ fn suggest_disambiguator(
 }
 
 /// Report a link from a public item to a private one.
-fn privacy_error(
-    cx: &DocContext<'_>,
-    item: &Item,
-    path_str: &str,
-    dox: &str,
-    link_range: Option<Range<usize>>,
-) {
+fn privacy_error(cx: &DocContext<'_>, item: &Item, path_str: &str, dox: &str, link: &MarkdownLink) {
     let sym;
     let item_name = match item.name {
         Some(name) => {
@@ -2004,7 +2027,7 @@ fn privacy_error(
     let msg =
         format!("public documentation for `{}` links to private item `{}`", item_name, path_str);
 
-    report_diagnostic(cx, PRIVATE_INTRA_DOC_LINKS, &msg, item, dox, &link_range, |diag, sp| {
+    report_diagnostic(cx, PRIVATE_INTRA_DOC_LINKS, &msg, item, dox, &link.range, |diag, sp| {
         if let Some(sp) = sp {
             diag.span_label(sp, "this item is private");
         }
@@ -2062,13 +2085,13 @@ fn resolve_primitive(path_str: &str, ns: Namespace) -> Option<Res> {
         "f64" => F64,
         "char" => Char,
         "bool" | "true" | "false" => Bool,
-        "str" => Str,
+        "str" | "&str" => Str,
         // See #80181 for why these don't have symbols associated.
         "slice" => Slice,
         "array" => Array,
         "tuple" => Tuple,
         "unit" => Unit,
-        "pointer" | "*" | "*const" | "*mut" => RawPointer,
+        "pointer" | "*const" | "*mut" => RawPointer,
         "reference" | "&" | "&mut" => Reference,
         "fn" => Fn,
         "never" | "!" => Never,
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index 9b0ae09cb3f..7b5e9e5905f 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -3,7 +3,7 @@ use crate::clean::*;
 use crate::core::DocContext;
 use crate::fold::DocFolder;
 
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_middle::ty::DefIdTree;
 use rustc_span::symbol::sym;
@@ -54,39 +54,6 @@ crate fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate {
         }
     }
 
-    let mut cleaner = BadImplStripper { prims, items: crate_items };
-
-    // scan through included items ahead of time to splice in Deref targets to the "valid" sets
-    for it in &new_items {
-        if let ImplItem(Impl { ref for_, ref trait_, ref items, .. }) = *it.kind {
-            if cleaner.keep_item(for_) && trait_.def_id() == cx.tcx.lang_items().deref_trait() {
-                let target = items
-                    .iter()
-                    .find_map(|item| match *item.kind {
-                        TypedefItem(ref t, true) => Some(&t.type_),
-                        _ => None,
-                    })
-                    .expect("Deref impl without Target type");
-
-                if let Some(prim) = target.primitive_type() {
-                    cleaner.prims.insert(prim);
-                } else if let Some(did) = target.def_id() {
-                    cleaner.items.insert(did);
-                }
-            }
-        }
-    }
-
-    new_items.retain(|it| {
-        if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = *it.kind {
-            cleaner.keep_item(for_)
-                || trait_.as_ref().map_or(false, |t| cleaner.keep_item(t))
-                || blanket_impl.is_some()
-        } else {
-            true
-        }
-    });
-
     // `tcx.crates()` doesn't include the local crate, and `tcx.all_trait_implementations`
     // doesn't work with it anyway, so pull them from the HIR map instead
     for &trait_did in cx.tcx.all_traits(LOCAL_CRATE).iter() {
@@ -123,6 +90,63 @@ crate fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate {
         }
     }
 
+    let mut cleaner = BadImplStripper { prims, items: crate_items };
+
+    let mut type_did_to_deref_target: FxHashMap<DefId, &Type> = FxHashMap::default();
+    // Gather all type to `Deref` target edges.
+    for it in &new_items {
+        if let ImplItem(Impl { ref for_, ref trait_, ref items, .. }) = *it.kind {
+            if trait_.def_id() == cx.tcx.lang_items().deref_trait() {
+                let target = items.iter().find_map(|item| match *item.kind {
+                    TypedefItem(ref t, true) => Some(&t.type_),
+                    _ => None,
+                });
+                if let (Some(for_did), Some(target)) = (for_.def_id(), target) {
+                    type_did_to_deref_target.insert(for_did, target);
+                }
+            }
+        }
+    }
+    // Follow all `Deref` targets of included items and recursively add them as valid
+    fn add_deref_target(
+        map: &FxHashMap<DefId, &Type>,
+        cleaner: &mut BadImplStripper,
+        type_did: &DefId,
+    ) {
+        if let Some(target) = map.get(type_did) {
+            debug!("add_deref_target: type {:?}, target {:?}", type_did, target);
+            if let Some(target_prim) = target.primitive_type() {
+                cleaner.prims.insert(target_prim);
+            } else if let Some(target_did) = target.def_id() {
+                // `impl Deref<Target = S> for S`
+                if target_did == *type_did {
+                    // Avoid infinite cycles
+                    return;
+                }
+                cleaner.items.insert(target_did);
+                add_deref_target(map, cleaner, &target_did);
+            }
+        }
+    }
+    for type_did in type_did_to_deref_target.keys() {
+        // Since only the `DefId` portion of the `Type` instances is known to be same for both the
+        // `Deref` target type and the impl for type positions, this map of types is keyed by
+        // `DefId` and for convenience uses a special cleaner that accepts `DefId`s directly.
+        if cleaner.keep_impl_with_def_id(type_did) {
+            add_deref_target(&type_did_to_deref_target, &mut cleaner, type_did);
+        }
+    }
+
+    new_items.retain(|it| {
+        if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = *it.kind {
+            cleaner.keep_impl(for_)
+                || trait_.as_ref().map_or(false, |t| cleaner.keep_impl(t))
+                || blanket_impl.is_some()
+        } else {
+            true
+        }
+    });
+
     if let Some(ref mut it) = krate.module {
         if let ModuleItem(Module { ref mut items, .. }) = *it.kind {
             items.extend(synth.impls);
@@ -192,16 +216,20 @@ struct BadImplStripper {
 }
 
 impl BadImplStripper {
-    fn keep_item(&self, ty: &Type) -> bool {
+    fn keep_impl(&self, ty: &Type) -> bool {
         if let Generic(_) = ty {
             // keep impls made on generics
             true
         } else if let Some(prim) = ty.primitive_type() {
             self.prims.contains(&prim)
         } else if let Some(did) = ty.def_id() {
-            self.items.contains(&did)
+            self.keep_impl_with_def_id(&did)
         } else {
             false
         }
     }
+
+    fn keep_impl_with_def_id(&self, did: &DefId) -> bool {
+        self.items.contains(did)
+    }
 }
diff --git a/src/librustdoc/passes/html_tags.rs b/src/librustdoc/passes/html_tags.rs
index a7a1ba1118d..38ec2bef0ad 100644
--- a/src/librustdoc/passes/html_tags.rs
+++ b/src/librustdoc/passes/html_tags.rs
@@ -59,7 +59,7 @@ fn drop_tag(
                 continue;
             }
             let last_tag_name_low = last_tag_name.to_lowercase();
-            if ALLOWED_UNCLOSED.iter().any(|&at| at == &last_tag_name_low) {
+            if ALLOWED_UNCLOSED.iter().any(|&at| at == last_tag_name_low) {
                 continue;
             }
             // `tags` is used as a queue, meaning that everything after `pos` is included inside it.
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index 51818d7faf0..7ac42c75992 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -14,9 +14,6 @@ crate use stripper::*;
 mod non_autolinks;
 crate use self::non_autolinks::CHECK_NON_AUTOLINKS;
 
-mod collapse_docs;
-crate use self::collapse_docs::COLLAPSE_DOCS;
-
 mod strip_hidden;
 crate use self::strip_hidden::STRIP_HIDDEN;
 
@@ -84,7 +81,6 @@ crate const PASSES: &[Pass] = &[
     CHECK_PRIVATE_ITEMS_DOC_TESTS,
     STRIP_HIDDEN,
     UNINDENT_COMMENTS,
-    COLLAPSE_DOCS,
     STRIP_PRIVATE,
     STRIP_PRIV_IMPORTS,
     PROPAGATE_DOC_CFG,
@@ -99,7 +95,6 @@ crate const PASSES: &[Pass] = &[
 /// The list of passes run by default.
 crate const DEFAULT_PASSES: &[ConditionalPass] = &[
     ConditionalPass::always(COLLECT_TRAIT_IMPLS),
-    ConditionalPass::always(COLLAPSE_DOCS),
     ConditionalPass::always(UNINDENT_COMMENTS),
     ConditionalPass::always(CHECK_PRIVATE_ITEMS_DOC_TESTS),
     ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden),
diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs
index 01e3d0acaa8..a276b7a6337 100644
--- a/src/librustdoc/passes/strip_hidden.rs
+++ b/src/librustdoc/passes/strip_hidden.rs
@@ -26,9 +26,7 @@ crate fn strip_hidden(krate: clean::Crate, _: &DocContext<'_>) -> clean::Crate {
 
     // strip all impls referencing stripped items
     let mut stripper = ImplStripper { retained: &retained };
-    let krate = stripper.fold_crate(krate);
-
-    krate
+    stripper.fold_crate(krate)
 }
 
 struct Stripper<'a> {
diff --git a/src/librustdoc/passes/unindent_comments.rs b/src/librustdoc/passes/unindent_comments.rs
index d0345d1e48c..1cad480d4e8 100644
--- a/src/librustdoc/passes/unindent_comments.rs
+++ b/src/librustdoc/passes/unindent_comments.rs
@@ -68,7 +68,7 @@ fn unindent_fragments(docs: &mut Vec<DocFragment>) {
     let min_indent = match docs
         .iter()
         .map(|fragment| {
-            fragment.doc.lines().fold(usize::MAX, |min_indent, line| {
+            fragment.doc.as_str().lines().fold(usize::MAX, |min_indent, line| {
                 if line.chars().all(|c| c.is_whitespace()) {
                     min_indent
                 } else {
@@ -87,7 +87,7 @@ fn unindent_fragments(docs: &mut Vec<DocFragment>) {
     };
 
     for fragment in docs {
-        if fragment.doc.lines().count() == 0 {
+        if fragment.doc.as_str().lines().count() == 0 {
             continue;
         }
 
@@ -97,18 +97,6 @@ fn unindent_fragments(docs: &mut Vec<DocFragment>) {
             min_indent
         };
 
-        fragment.doc = fragment
-            .doc
-            .lines()
-            .map(|line| {
-                if line.chars().all(|c| c.is_whitespace()) {
-                    line.to_string()
-                } else {
-                    assert!(line.len() >= min_indent);
-                    line[min_indent..].to_string()
-                }
-            })
-            .collect::<Vec<_>>()
-            .join("\n");
+        fragment.indent = min_indent;
     }
 }
diff --git a/src/librustdoc/passes/unindent_comments/tests.rs b/src/librustdoc/passes/unindent_comments/tests.rs
index 9dec71f7683..9c9924841b9 100644
--- a/src/librustdoc/passes/unindent_comments/tests.rs
+++ b/src/librustdoc/passes/unindent_comments/tests.rs
@@ -1,21 +1,27 @@
 use super::*;
 use rustc_span::source_map::DUMMY_SP;
+use rustc_span::symbol::Symbol;
+use rustc_span::with_default_session_globals;
 
 fn create_doc_fragment(s: &str) -> Vec<DocFragment> {
     vec![DocFragment {
         line: 0,
         span: DUMMY_SP,
         parent_module: None,
-        doc: s.to_string(),
+        doc: Symbol::intern(s),
         kind: DocFragmentKind::SugaredDoc,
+        need_backline: false,
+        indent: 0,
     }]
 }
 
 #[track_caller]
 fn run_test(input: &str, expected: &str) {
-    let mut s = create_doc_fragment(input);
-    unindent_fragments(&mut s);
-    assert_eq!(s[0].doc, expected);
+    with_default_session_globals(|| {
+        let mut s = create_doc_fragment(input);
+        unindent_fragments(&mut s);
+        assert_eq!(&s.iter().collect::<String>(), expected);
+    });
 }
 
 #[test]
diff --git a/src/librustdoc/theme.rs b/src/librustdoc/theme.rs
index 3bcf64f91c9..24d57705412 100644
--- a/src/librustdoc/theme.rs
+++ b/src/librustdoc/theme.rs
@@ -70,15 +70,15 @@ impl Events {
     }
 
     fn is_comment(&self) -> bool {
-        match *self {
-            Events::StartLineComment(_) | Events::StartComment(_) | Events::EndComment(_) => true,
-            _ => false,
-        }
+        matches!(
+            self,
+            Events::StartLineComment(_) | Events::StartComment(_) | Events::EndComment(_)
+        )
     }
 }
 
 fn previous_is_line_comment(events: &[Events]) -> bool {
-    if let Some(&Events::StartLineComment(_)) = events.last() { true } else { false }
+    matches!(events.last(), Some(&Events::StartLineComment(_)))
 }
 
 fn is_line_comment(pos: usize, v: &[u8], events: &[Events]) -> bool {
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 3c0aeaad43e..1fedd26a1ef 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -61,20 +61,60 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
     }
 
     crate fn visit(mut self, krate: &'tcx hir::Crate<'_>) -> Module<'tcx> {
-        let mut module = self.visit_mod_contents(
+        let mut top_level_module = self.visit_mod_contents(
             krate.item.span,
             &Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public },
             hir::CRATE_HIR_ID,
             &krate.item.module,
             None,
         );
-        // Attach the crate's exported macros to the top-level module:
-        module.macros.extend(krate.exported_macros.iter().map(|def| (def, None)));
-        module.is_crate = true;
-
+        top_level_module.is_crate = true;
+        // Attach the crate's exported macros to the top-level module.
+        // In the case of macros 2.0 (`pub macro`), and for built-in `derive`s or attributes as
+        // well (_e.g._, `Copy`), these are wrongly bundled in there too, so we need to fix that by
+        // moving them back to their correct locations.
+        'exported_macros: for def in krate.exported_macros {
+            // The `def` of a macro in `exported_macros` should correspond to either:
+            //  - a `#[macro_export] macro_rules!` macro,
+            //  - a built-in `derive` (or attribute) macro such as the ones in `::core`,
+            //  - a `pub macro`.
+            // Only the last two need to be fixed, thus:
+            if def.ast.macro_rules {
+                top_level_module.macros.push((def, None));
+                continue 'exported_macros;
+            }
+            let tcx = self.cx.tcx;
+            // Note: this is not the same as `.parent_module()`. Indeed, the latter looks
+            // for the closest module _ancestor_, which is not necessarily a direct parent
+            // (since a direct parent isn't necessarily a module, c.f. #77828).
+            let macro_parent_def_id = {
+                use rustc_middle::ty::DefIdTree;
+                tcx.parent(tcx.hir().local_def_id(def.hir_id).to_def_id()).unwrap()
+            };
+            let macro_parent_path = tcx.def_path(macro_parent_def_id);
+            // HACK: rustdoc has no way to lookup `doctree::Module`s by their HirId. Instead,
+            // lookup the module by its name, by looking at each path segment one at a time.
+            let mut cur_mod = &mut top_level_module;
+            for path_segment in macro_parent_path.data {
+                // Path segments may refer to a module (in which case they belong to the type
+                // namespace), which is _necessary_ for the macro to be accessible outside it
+                // (no "associated macros" as of yet). Else we bail with an outer `continue`.
+                let path_segment_ty_ns = match path_segment.data {
+                    rustc_hir::definitions::DefPathData::TypeNs(symbol) => symbol,
+                    _ => continue 'exported_macros,
+                };
+                // Descend into the child module that matches this path segment (if any).
+                match cur_mod.mods.iter_mut().find(|child| child.name == Some(path_segment_ty_ns)) {
+                    Some(child_mod) => cur_mod = &mut *child_mod,
+                    None => continue 'exported_macros,
+                }
+            }
+            let cur_mod_def_id = tcx.hir().local_def_id(cur_mod.id).to_def_id();
+            assert_eq!(cur_mod_def_id, macro_parent_def_id);
+            cur_mod.macros.push((def, None));
+        }
         self.cx.renderinfo.get_mut().exact_paths = self.exact_paths;
-
-        module
+        top_level_module
     }
 
     fn visit_mod_contents(
diff --git a/src/test/codegen/sanitizer-no-sanitize.rs b/src/test/codegen/sanitizer-no-sanitize.rs
index 1b2b18822e6..fb9d249da03 100644
--- a/src/test/codegen/sanitizer-no-sanitize.rs
+++ b/src/test/codegen/sanitizer-no-sanitize.rs
@@ -1,4 +1,4 @@
-// Verifies that no_sanitze attribute can be used to
+// Verifies that no_sanitize attribute can be used to
 // selectively disable sanitizer instrumentation.
 //
 // needs-sanitizer-address
diff --git a/src/test/incremental/hygiene/load_cached_hygiene.rs b/src/test/incremental/hygiene/load_cached_hygiene.rs
index 8124141418b..d6a5cb993a4 100644
--- a/src/test/incremental/hygiene/load_cached_hygiene.rs
+++ b/src/test/incremental/hygiene/load_cached_hygiene.rs
@@ -1,5 +1,5 @@
 // revisions:rpass1 rpass2
-// compile-flags: -Z query-dep-graph
+// compile-flags: -Z query-dep-graph -O
 // aux-build:cached_hygiene.rs
 
 // This tests the folllowing scenario
@@ -19,7 +19,12 @@
 // the metadata. Specifically, we were not resetting `orig_id`
 // for an `EpxnData` generate in the current crate, which would cause
 // us to serialize the `ExpnId` pointing to a garbage location in
-// the metadata.
+// the metadata.o
+
+// NOTE: We're explicitly passing the `-O` optimization flag because if optimizations are not
+// enabled, then rustc will ignore the `#[inline(always)]` attribute which means we do not load
+// the optimized mir for the unmodified function to be loaded and so the CGU containing that
+// function will be reused.
 
 #![feature(rustc_attrs)]
 
diff --git a/src/test/incremental/remapped_paths_cc/main.rs b/src/test/incremental/remapped_paths_cc/main.rs
index b01f02444ea..735635029da 100644
--- a/src/test/incremental/remapped_paths_cc/main.rs
+++ b/src/test/incremental/remapped_paths_cc/main.rs
@@ -1,11 +1,18 @@
 // revisions:rpass1 rpass2 rpass3
-// compile-flags: -Z query-dep-graph -g
+// compile-flags: -Z query-dep-graph -g -O
 // aux-build:extern_crate.rs
 
 // ignore-asmjs wasm2js does not support source maps yet
+
 // This test case makes sure that we detect if paths emitted into debuginfo
 // are changed, even when the change happens in an external crate.
 
+// NOTE: We're explicitly passing the `-O` optimization flag because if no optimizations are
+// requested, rustc will ignore the `#[inline]` attribute. This is a performance optimization for
+// non-optimized builds which causes us to generate fewer copies of inlined functions when
+// runtime performance doesn't matter. Without this flag, the function will go into a different
+// CGU which can be reused by this crate.
+
 #![feature(rustc_attrs)]
 
 #![rustc_partition_reused(module="main", cfg="rpass2")]
diff --git a/src/test/run-make-fulldeps/coverage-reports/Makefile b/src/test/run-make-fulldeps/coverage-reports/Makefile
index c4700b317ef..f98245b4a99 100644
--- a/src/test/run-make-fulldeps/coverage-reports/Makefile
+++ b/src/test/run-make-fulldeps/coverage-reports/Makefile
@@ -172,7 +172,7 @@ else
 	# files are redundant, so there is no need to generate `expected_*.json` files or
 	# compare actual JSON results.)
 
-	$(DIFF) --ignore-matching-lines='::<.*>.*:$$' \
+	$(DIFF) --ignore-matching-lines='^  | .*::<.*>.*:$$' --ignore-matching-lines='^  | <.*>::.*:$$' \
 		expected_show_coverage.$@.txt "$(TMPDIR)"/actual_show_coverage.$@.txt || \
 		( grep -q '^\/\/ ignore-llvm-cov-show-diffs' $(SOURCEDIR)/$@.rs && \
 			>&2 echo 'diff failed, but suppressed with `// ignore-llvm-cov-show-diffs` in $(SOURCEDIR)/$@.rs' \
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt
index e1731c7223c..8f67170561a 100644
--- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt
@@ -21,50 +21,86 @@
    20|       |//!
    21|       |//! doctest returning a result:
    22|      1|//! ```
-   23|      1|//! #[derive(Debug)]
-   24|      1|//! struct SomeError;
-   25|      1|//! let mut res = Err(SomeError);
-   26|      1|//! if res.is_ok() {
-   27|      0|//!   res?;
-   28|      1|//! } else {
-   29|      1|//!   res = Ok(0);
-   30|      1|//! }
-   31|       |//! // need to be explicit because rustdoc cant infer the return type
-   32|      1|//! Ok::<(), SomeError>(())
-   33|      1|//! ```
-   34|       |//!
-   35|       |//! doctest with custom main:
-   36|       |//! ```
-   37|       |//! #[derive(Debug)]
-   38|       |//! struct SomeError;
-   39|       |//!
-   40|       |//! extern crate doctest_crate;
-   41|       |//!
-   42|      1|//! fn doctest_main() -> Result<(), SomeError> {
-   43|      1|//!     doctest_crate::fn_run_in_doctests(2);
-   44|      1|//!     Ok(())
-   45|      1|//! }
-   46|       |//!
-   47|       |//! // this `main` is not shown as covered, as it clashes with all the other
-   48|       |//! // `main` functions that were automatically generated for doctests
-   49|       |//! fn main() -> Result<(), SomeError> {
-   50|       |//!     doctest_main()
-   51|       |//! }
-   52|       |//! ```
-   53|       |
-   54|       |/// doctest attached to fn testing external code:
-   55|       |/// ```
-   56|      1|/// extern crate doctest_crate;
-   57|      1|/// doctest_crate::fn_run_in_doctests(3);
-   58|      1|/// ```
-   59|       |///
-   60|      1|fn main() {
-   61|      1|    if true {
-   62|      1|        assert_eq!(1, 1);
-   63|       |    } else {
-   64|       |        assert_eq!(1, 2);
-   65|       |    }
-   66|      1|}
+   23|      2|//! #[derive(Debug, PartialEq)]
+                       ^1
+   24|      1|//! struct SomeError {
+   25|      1|//!     msg: String,
+   26|      1|//! }
+   27|      1|//! let mut res = Err(SomeError { msg: String::from("a message") });
+   28|      1|//! if res.is_ok() {
+   29|      0|//!     res?;
+   30|       |//! } else {
+   31|      1|//!     if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+   32|      1|//!         println!("{:?}", res);
+   33|      1|//!     }
+                   ^0
+   34|      1|//!     if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+   35|      1|//!         res = Ok(1);
+   36|      1|//!     }
+                   ^0
+   37|      1|//!     res = Ok(0);
+   38|       |//! }
+   39|       |//! // need to be explicit because rustdoc cant infer the return type
+   40|      1|//! Ok::<(), SomeError>(())
+   41|      1|//! ```
+   42|       |//!
+   43|       |//! doctest with custom main:
+   44|       |//! ```
+   45|      1|//! fn some_func() {
+   46|      1|//!     println!("called some_func()");
+   47|      1|//! }
+   48|       |//!
+   49|       |//! #[derive(Debug)]
+   50|       |//! struct SomeError;
+   51|       |//!
+   52|       |//! extern crate doctest_crate;
+   53|       |//!
+   54|      1|//! fn doctest_main() -> Result<(), SomeError> {
+   55|      1|//!     some_func();
+   56|      1|//!     doctest_crate::fn_run_in_doctests(2);
+   57|      1|//!     Ok(())
+   58|      1|//! }
+   59|       |//!
+   60|       |//! // this `main` is not shown as covered, as it clashes with all the other
+   61|       |//! // `main` functions that were automatically generated for doctests
+   62|       |//! fn main() -> Result<(), SomeError> {
+   63|       |//!     doctest_main()
+   64|       |//! }
+   65|       |//! ```
+   66|       |
+   67|       |/// doctest attached to fn testing external code:
+   68|       |/// ```
+   69|      1|/// extern crate doctest_crate;
+   70|      1|/// doctest_crate::fn_run_in_doctests(3);
+   71|      1|/// ```
+   72|       |///
+   73|      1|fn main() {
+   74|      1|    if true {
+   75|      1|        assert_eq!(1, 1);
+   76|       |    } else {
+   77|       |        assert_eq!(1, 2);
+   78|       |    }
+   79|      1|}
+   80|       |
+   81|       |// FIXME(Swatinem): Fix known issue that coverage code region columns need to be offset by the
+   82|       |// doc comment line prefix (`///` or `//!`) and any additional indent (before or after the doc
+   83|       |// comment characters). This test produces `llvm-cov show` results demonstrating the problem.
+   84|       |//
+   85|       |// One of the above tests now includes: `derive(Debug, PartialEq)`, producing an `llvm-cov show`
+   86|       |// result with a distinct count for `Debug`, denoted by `^1`, but the caret points to the wrong
+   87|       |// column. Similarly, the `if` blocks without `else` blocks show `^0`, which should point at, or
+   88|       |// one character past, the `if` block's closing brace. In both cases, these are most likely off
+   89|       |// by the number of characters stripped from the beginning of each doc comment line: indent
+   90|       |// whitespace, if any, doc comment prefix (`//!` in this case) and (I assume) one space character
+   91|       |// (?). Note, when viewing `llvm-cov show` results in `--color` mode, the column offset errors are
+   92|       |// more pronounced, and show up in more places, with background color used to show some distinct
+   93|       |// code regions with different coverage counts.
+   94|       |//
+   95|       |// NOTE: Since the doc comment line prefix may vary, one possible solution is to replace each
+   96|       |// character stripped from the beginning of doc comment lines with a space. This will give coverage
+   97|       |// results the correct column offsets, and I think it should compile correctly, but I don't know
+   98|       |// what affect it might have on diagnostic messages from the compiler, and whether anyone would care
+   99|       |// if the indentation changed. I don't know if there is a more viable solution.
 
 ../coverage/lib/doctest_crate.rs:
     1|       |/// A function run only from within doctests
diff --git a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest/doctest.main.-------.InstrumentCoverage.0.html b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest/doctest.main.-------.InstrumentCoverage.0.html
index 8d074558aae..333476a2df5 100644
--- a/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest/doctest.main.-------.InstrumentCoverage.0.html
+++ b/src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest/doctest.main.-------.InstrumentCoverage.0.html
@@ -69,59 +69,59 @@ For revisions in Pull Requests (PR):
 </style>
 </head>
 <body>
-<div class="code" style="counter-reset: line 59"><span class="line"><span><span class="code even" style="--layer: 1"><span class="annotation">@0⦊</span>fn main() <span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0">{</span></span>
-<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code even" style="--layer: 1" title="61:8-61:12: @0[1]: _1 = const true
-61:8-61:12: @0[2]: FakeRead(ForMatchedPlace, _1)"><span class="annotation">@0⦊</span>true<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="62:9-62:26: @5[0]: _2 = const ()"><span class="annotation">@5⦊</span></span></span><span class="code even" style="--layer: 2" title="62:9-62:26: @6[5]: _75 = const main::promoted[3]
-62:9-62:26: @6[6]: _18 = &amp;(*_75)
-62:9-62:26: @6[7]: _17 = &amp;(*_18)
-62:9-62:26: @6[8]: _16 = move _17 as &amp;[&amp;str] (Pointer(Unsize))
-62:9-62:26: @6[17]: _26 = &amp;(*_8)
-62:9-62:26: @6[18]: _25 = &amp;_26
-62:9-62:26: @6[21]: _28 = &amp;(*_9)
-62:9-62:26: @6[22]: _27 = &amp;_28
-62:9-62:26: @6[23]: _24 = (move _25, move _27)
-62:9-62:26: @6[26]: FakeRead(ForMatchedPlace, _24)
-62:9-62:26: @6[28]: _29 = (_24.0: &amp;&amp;i32)
-62:9-62:26: @6[30]: _30 = (_24.1: &amp;&amp;i32)
-62:9-62:26: @6[33]: _32 = &amp;(*_29)
-62:9-62:26: @6[35]: _33 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-62:9-62:26: @6.Call: _31 = ArgumentV1::new::&lt;&amp;i32&gt;(move _32, move _33) -&gt; [return: bb7, unwind: bb17]
-62:9-62:26: @7[4]: _35 = &amp;(*_30)
-62:9-62:26: @7[6]: _36 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-62:9-62:26: @7.Call: _34 = ArgumentV1::new::&lt;&amp;i32&gt;(move _35, move _36) -&gt; [return: bb8, unwind: bb17]
-62:9-62:26: @8[2]: _23 = [move _31, move _34]
-62:9-62:26: @8[7]: _22 = &amp;_23
-62:9-62:26: @8[8]: _21 = &amp;(*_22)
-62:9-62:26: @8[9]: _20 = move _21 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-62:9-62:26: @8.Call: _15 = Arguments::new_v1(move _16, move _20) -&gt; [return: bb9, unwind: bb17]
-62:9-62:26: @9.Call: core::panicking::panic_fmt(move _15) -&gt; bb17"><span class="annotation">@4,6,7,8,9⦊</span>assert_eq!(1, 1);<span class="annotation">⦉@4,6,7,8,9</span></span><span><span class="code odd" style="--layer: 1" title="62:9-62:26: @5[0]: _2 = const ()"><span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
+<div class="code" style="counter-reset: line 72"><span class="line"><span><span class="code even" style="--layer: 1"><span class="annotation">@0⦊</span>fn main() <span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0">{</span></span>
+<span class="line"><span class="code" style="--layer: 0">    if </span><span><span class="code even" style="--layer: 1" title="74:8-74:12: @0[1]: _1 = const true
+74:8-74:12: @0[2]: FakeRead(ForMatchedPlace, _1)"><span class="annotation">@0⦊</span>true<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code odd" style="--layer: 1" title="75:9-75:26: @5[0]: _2 = const ()"><span class="annotation">@5⦊</span></span></span><span class="code even" style="--layer: 2" title="75:9-75:26: @6[5]: _75 = const main::promoted[3]
+75:9-75:26: @6[6]: _18 = &amp;(*_75)
+75:9-75:26: @6[7]: _17 = &amp;(*_18)
+75:9-75:26: @6[8]: _16 = move _17 as &amp;[&amp;str] (Pointer(Unsize))
+75:9-75:26: @6[17]: _26 = &amp;(*_8)
+75:9-75:26: @6[18]: _25 = &amp;_26
+75:9-75:26: @6[21]: _28 = &amp;(*_9)
+75:9-75:26: @6[22]: _27 = &amp;_28
+75:9-75:26: @6[23]: _24 = (move _25, move _27)
+75:9-75:26: @6[26]: FakeRead(ForMatchedPlace, _24)
+75:9-75:26: @6[28]: _29 = (_24.0: &amp;&amp;i32)
+75:9-75:26: @6[30]: _30 = (_24.1: &amp;&amp;i32)
+75:9-75:26: @6[33]: _32 = &amp;(*_29)
+75:9-75:26: @6[35]: _33 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+75:9-75:26: @6.Call: _31 = ArgumentV1::new::&lt;&amp;i32&gt;(move _32, move _33) -&gt; [return: bb7, unwind: bb17]
+75:9-75:26: @7[4]: _35 = &amp;(*_30)
+75:9-75:26: @7[6]: _36 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+75:9-75:26: @7.Call: _34 = ArgumentV1::new::&lt;&amp;i32&gt;(move _35, move _36) -&gt; [return: bb8, unwind: bb17]
+75:9-75:26: @8[2]: _23 = [move _31, move _34]
+75:9-75:26: @8[7]: _22 = &amp;_23
+75:9-75:26: @8[8]: _21 = &amp;(*_22)
+75:9-75:26: @8[9]: _20 = move _21 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+75:9-75:26: @8.Call: _15 = Arguments::new_v1(move _16, move _20) -&gt; [return: bb9, unwind: bb17]
+75:9-75:26: @9.Call: core::panicking::panic_fmt(move _15) -&gt; bb17"><span class="annotation">@4,6,7,8,9⦊</span>assert_eq!(1, 1);<span class="annotation">⦉@4,6,7,8,9</span></span><span><span class="code odd" style="--layer: 1" title="75:9-75:26: @5[0]: _2 = const ()"><span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    } else {</span></span>
-<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="64:9-64:26: @11[0]: _37 = const ()"><span class="annotation">@11⦊</span></span></span><span class="code even" style="--layer: 2" title="64:9-64:26: @12[5]: _72 = const main::promoted[0]
-64:9-64:26: @12[6]: _53 = &amp;(*_72)
-64:9-64:26: @12[7]: _52 = &amp;(*_53)
-64:9-64:26: @12[8]: _51 = move _52 as &amp;[&amp;str] (Pointer(Unsize))
-64:9-64:26: @12[17]: _61 = &amp;(*_43)
-64:9-64:26: @12[18]: _60 = &amp;_61
-64:9-64:26: @12[21]: _63 = &amp;(*_44)
-64:9-64:26: @12[22]: _62 = &amp;_63
-64:9-64:26: @12[23]: _59 = (move _60, move _62)
-64:9-64:26: @12[26]: FakeRead(ForMatchedPlace, _59)
-64:9-64:26: @12[28]: _64 = (_59.0: &amp;&amp;i32)
-64:9-64:26: @12[30]: _65 = (_59.1: &amp;&amp;i32)
-64:9-64:26: @12[33]: _67 = &amp;(*_64)
-64:9-64:26: @12[35]: _68 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-64:9-64:26: @12.Call: _66 = ArgumentV1::new::&lt;&amp;i32&gt;(move _67, move _68) -&gt; [return: bb13, unwind: bb17]
-64:9-64:26: @13[4]: _70 = &amp;(*_65)
-64:9-64:26: @13[6]: _71 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
-64:9-64:26: @13.Call: _69 = ArgumentV1::new::&lt;&amp;i32&gt;(move _70, move _71) -&gt; [return: bb14, unwind: bb17]
-64:9-64:26: @14[2]: _58 = [move _66, move _69]
-64:9-64:26: @14[7]: _57 = &amp;_58
-64:9-64:26: @14[8]: _56 = &amp;(*_57)
-64:9-64:26: @14[9]: _55 = move _56 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
-64:9-64:26: @14.Call: _50 = Arguments::new_v1(move _51, move _55) -&gt; [return: bb15, unwind: bb17]
-64:9-64:26: @15.Call: core::panicking::panic_fmt(move _50) -&gt; bb17"><span class="annotation">@10,12,13,14,15⦊</span>assert_eq!(1, 2);<span class="annotation">⦉@10,12,13,14,15</span></span><span><span class="code even" style="--layer: 1" title="64:9-64:26: @11[0]: _37 = const ()"><span class="annotation">⦉@11</span></span></span><span class="code" style="--layer: 0"></span></span>
+<span class="line"><span class="code" style="--layer: 0">        </span><span><span class="code even" style="--layer: 1" title="77:9-77:26: @11[0]: _37 = const ()"><span class="annotation">@11⦊</span></span></span><span class="code even" style="--layer: 2" title="77:9-77:26: @12[5]: _72 = const main::promoted[0]
+77:9-77:26: @12[6]: _53 = &amp;(*_72)
+77:9-77:26: @12[7]: _52 = &amp;(*_53)
+77:9-77:26: @12[8]: _51 = move _52 as &amp;[&amp;str] (Pointer(Unsize))
+77:9-77:26: @12[17]: _61 = &amp;(*_43)
+77:9-77:26: @12[18]: _60 = &amp;_61
+77:9-77:26: @12[21]: _63 = &amp;(*_44)
+77:9-77:26: @12[22]: _62 = &amp;_63
+77:9-77:26: @12[23]: _59 = (move _60, move _62)
+77:9-77:26: @12[26]: FakeRead(ForMatchedPlace, _59)
+77:9-77:26: @12[28]: _64 = (_59.0: &amp;&amp;i32)
+77:9-77:26: @12[30]: _65 = (_59.1: &amp;&amp;i32)
+77:9-77:26: @12[33]: _67 = &amp;(*_64)
+77:9-77:26: @12[35]: _68 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+77:9-77:26: @12.Call: _66 = ArgumentV1::new::&lt;&amp;i32&gt;(move _67, move _68) -&gt; [return: bb13, unwind: bb17]
+77:9-77:26: @13[4]: _70 = &amp;(*_65)
+77:9-77:26: @13[6]: _71 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
+77:9-77:26: @13.Call: _69 = ArgumentV1::new::&lt;&amp;i32&gt;(move _70, move _71) -&gt; [return: bb14, unwind: bb17]
+77:9-77:26: @14[2]: _58 = [move _66, move _69]
+77:9-77:26: @14[7]: _57 = &amp;_58
+77:9-77:26: @14[8]: _56 = &amp;(*_57)
+77:9-77:26: @14[9]: _55 = move _56 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
+77:9-77:26: @14.Call: _50 = Arguments::new_v1(move _51, move _55) -&gt; [return: bb15, unwind: bb17]
+77:9-77:26: @15.Call: core::panicking::panic_fmt(move _50) -&gt; bb17"><span class="annotation">@10,12,13,14,15⦊</span>assert_eq!(1, 2);<span class="annotation">⦉@10,12,13,14,15</span></span><span><span class="code even" style="--layer: 1" title="77:9-77:26: @11[0]: _37 = const ()"><span class="annotation">⦉@11</span></span></span><span class="code" style="--layer: 0"></span></span>
 <span class="line"><span class="code" style="--layer: 0">    }</span></span>
-<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="66:2-66:2: @16.Return: return"><span class="annotation">@16⦊</span>‸<span class="annotation">⦉@16</span></span></span></span></div>
+<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="79:2-79:2: @16.Return: return"><span class="annotation">@16⦊</span>‸<span class="annotation">⦉@16</span></span></span></span></div>
 </body>
 </html>
diff --git a/src/test/run-make-fulldeps/coverage/doctest.rs b/src/test/run-make-fulldeps/coverage/doctest.rs
index e41d669bf0c..ec04ea57063 100644
--- a/src/test/run-make-fulldeps/coverage/doctest.rs
+++ b/src/test/run-make-fulldeps/coverage/doctest.rs
@@ -20,13 +20,21 @@
 //!
 //! doctest returning a result:
 //! ```
-//! #[derive(Debug)]
-//! struct SomeError;
-//! let mut res = Err(SomeError);
+//! #[derive(Debug, PartialEq)]
+//! struct SomeError {
+//!     msg: String,
+//! }
+//! let mut res = Err(SomeError { msg: String::from("a message") });
 //! if res.is_ok() {
-//!   res?;
+//!     res?;
 //! } else {
-//!   res = Ok(0);
+//!     if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+//!         println!("{:?}", res);
+//!     }
+//!     if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+//!         res = Ok(1);
+//!     }
+//!     res = Ok(0);
 //! }
 //! // need to be explicit because rustdoc cant infer the return type
 //! Ok::<(), SomeError>(())
@@ -34,12 +42,17 @@
 //!
 //! doctest with custom main:
 //! ```
+//! fn some_func() {
+//!     println!("called some_func()");
+//! }
+//!
 //! #[derive(Debug)]
 //! struct SomeError;
 //!
 //! extern crate doctest_crate;
 //!
 //! fn doctest_main() -> Result<(), SomeError> {
+//!     some_func();
 //!     doctest_crate::fn_run_in_doctests(2);
 //!     Ok(())
 //! }
@@ -64,3 +77,23 @@ fn main() {
         assert_eq!(1, 2);
     }
 }
+
+// FIXME(Swatinem): Fix known issue that coverage code region columns need to be offset by the
+// doc comment line prefix (`///` or `//!`) and any additional indent (before or after the doc
+// comment characters). This test produces `llvm-cov show` results demonstrating the problem.
+//
+// One of the above tests now includes: `derive(Debug, PartialEq)`, producing an `llvm-cov show`
+// result with a distinct count for `Debug`, denoted by `^1`, but the caret points to the wrong
+// column. Similarly, the `if` blocks without `else` blocks show `^0`, which should point at, or
+// one character past, the `if` block's closing brace. In both cases, these are most likely off
+// by the number of characters stripped from the beginning of each doc comment line: indent
+// whitespace, if any, doc comment prefix (`//!` in this case) and (I assume) one space character
+// (?). Note, when viewing `llvm-cov show` results in `--color` mode, the column offset errors are
+// more pronounced, and show up in more places, with background color used to show some distinct
+// code regions with different coverage counts.
+//
+// NOTE: Since the doc comment line prefix may vary, one possible solution is to replace each
+// character stripped from the beginning of doc comment lines with a space. This will give coverage
+// results the correct column offsets, and I think it should compile correctly, but I don't know
+// what affect it might have on diagnostic messages from the compiler, and whether anyone would care
+// if the indentation changed. I don't know if there is a more viable solution.
diff --git a/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile b/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile
index 0cab955f644..d12a23fbbf0 100644
--- a/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile
+++ b/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile
@@ -1,7 +1,12 @@
 -include ../tools.mk
 
 all:
-	$(RUSTC) foo.rs --emit llvm-ir -C codegen-units=2
+	$(RUSTC) foo.rs --emit llvm-ir -C codegen-units=2 -C opt-level=0
+	if ![cat $(TMPDIR)/*.ll | $(CGREP) -e '\bcall\b']; then \
+		echo "not found call instruction when one was expected"; \
+		exit 1; \
+	fi
+	$(RUSTC) foo.rs --emit llvm-ir -C codegen-units=2 -C opt-level=1
 	if cat $(TMPDIR)/*.ll | $(CGREP) -e '\bcall\b'; then \
 		echo "found call instruction when one wasn't expected"; \
 		exit 1; \
diff --git a/src/test/rustdoc-ui/deref-recursive-cycle.rs b/src/test/rustdoc-ui/deref-recursive-cycle.rs
new file mode 100644
index 00000000000..4cb518cbbbd
--- /dev/null
+++ b/src/test/rustdoc-ui/deref-recursive-cycle.rs
@@ -0,0 +1,17 @@
+// check-pass
+// #26207: Ensure `Deref` cycles are properly handled without errors.
+
+#[derive(Copy, Clone)]
+struct S;
+
+impl std::ops::Deref for S {
+    type Target = S;
+
+    fn deref(&self) -> &S {
+        self
+    }
+}
+
+fn main() {
+    let s: S = *******S;
+}
diff --git a/src/test/rustdoc-ui/doc-alias-crate-level.rs b/src/test/rustdoc-ui/doc-alias-crate-level.rs
index 309d0bc4d43..70618ac01df 100644
--- a/src/test/rustdoc-ui/doc-alias-crate-level.rs
+++ b/src/test/rustdoc-ui/doc-alias-crate-level.rs
@@ -1,5 +1,3 @@
-#![feature(doc_alias)]
-
 #![doc(alias = "crate-level-not-working")] //~ ERROR
 
 #[doc(alias = "shouldn't work!")] //~ ERROR
diff --git a/src/test/rustdoc-ui/doc-alias-crate-level.stderr b/src/test/rustdoc-ui/doc-alias-crate-level.stderr
index a58e91c5aa7..9e746cba05f 100644
--- a/src/test/rustdoc-ui/doc-alias-crate-level.stderr
+++ b/src/test/rustdoc-ui/doc-alias-crate-level.stderr
@@ -1,11 +1,11 @@
 error: '\'' character isn't allowed in `#[doc(alias = "...")]`
-  --> $DIR/doc-alias-crate-level.rs:5:15
+  --> $DIR/doc-alias-crate-level.rs:3:15
    |
 LL | #[doc(alias = "shouldn't work!")]
    |               ^^^^^^^^^^^^^^^^^
 
 error: `#![doc(alias = "...")]` isn't allowed as a crate level attribute
-  --> $DIR/doc-alias-crate-level.rs:3:8
+  --> $DIR/doc-alias-crate-level.rs:1:8
    |
 LL | #![doc(alias = "crate-level-not-working")]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/rustdoc-ui/doc-alias-same-name.rs b/src/test/rustdoc-ui/doc-alias-same-name.rs
new file mode 100644
index 00000000000..da97c267618
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-alias-same-name.rs
@@ -0,0 +1,4 @@
+#![crate_type = "lib"]
+
+#[doc(alias = "Foo")] //~ ERROR
+pub struct Foo;
diff --git a/src/test/rustdoc-ui/doc-alias-same-name.stderr b/src/test/rustdoc-ui/doc-alias-same-name.stderr
new file mode 100644
index 00000000000..5ba09a2eae1
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-alias-same-name.stderr
@@ -0,0 +1,8 @@
+error: `#[doc(alias = "...")]` is the same as the item's name
+  --> $DIR/doc-alias-same-name.rs:3:7
+   |
+LL | #[doc(alias = "Foo")]
+   |       ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/ignore-block-help.rs b/src/test/rustdoc-ui/ignore-block-help.rs
new file mode 100644
index 00000000000..c22dddd11df
--- /dev/null
+++ b/src/test/rustdoc-ui/ignore-block-help.rs
@@ -0,0 +1,7 @@
+// check-pass
+
+/// ```ignore (to-prevent-tidy-error)
+/// let heart = '❤️';
+/// ```
+//~^^^ WARN
+pub struct X;
diff --git a/src/test/rustdoc-ui/ignore-block-help.stderr b/src/test/rustdoc-ui/ignore-block-help.stderr
new file mode 100644
index 00000000000..d45cd92d2d1
--- /dev/null
+++ b/src/test/rustdoc-ui/ignore-block-help.stderr
@@ -0,0 +1,17 @@
+warning: could not parse code block as Rust code
+  --> $DIR/ignore-block-help.rs:3:5
+   |
+LL |   /// ```ignore (to-prevent-tidy-error)
+   |  _____^
+LL | | /// let heart = '❤️';
+LL | | /// ```
+   | |_______^
+   |
+   = note: error from rustc: character literal may only contain one codepoint
+help: `ignore` code blocks require valid Rust code for syntax highlighting. Mark blocks that do not contain Rust code as text
+   |
+LL | /// ```text,ignore (to-prevent-tidy-error)
+   |     ^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.rs b/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.rs
new file mode 100644
index 00000000000..0d1d5d1134b
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.rs
@@ -0,0 +1,3 @@
+#![deny(broken_intra_doc_links)]
+//! [static@u8::MIN]
+//~^ ERROR incompatible link kind
diff --git a/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.stderr b/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.stderr
new file mode 100644
index 00000000000..ed1c10f9e0c
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/incompatible-primitive-disambiguator.stderr
@@ -0,0 +1,15 @@
+error: incompatible link kind for `u8::MIN`
+  --> $DIR/incompatible-primitive-disambiguator.rs:2:6
+   |
+LL | //! [static@u8::MIN]
+   |      ^^^^^^^^^^^^^^ help: to link to the associated constant, prefix with `const@`: `const@u8::MIN`
+   |
+note: the lint level is defined here
+  --> $DIR/incompatible-primitive-disambiguator.rs:1:9
+   |
+LL | #![deny(broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   = note: this link resolved to an associated constant, which is not a static
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/intra-doc/unused-extern-crate.rs b/src/test/rustdoc-ui/intra-doc/unused-extern-crate.rs
new file mode 100644
index 00000000000..186503cf69d
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/unused-extern-crate.rs
@@ -0,0 +1,5 @@
+// compile-flags: --extern zip=whatever.rlib
+#![deny(broken_intra_doc_links)]
+/// See [zip] crate.
+//~^ ERROR unresolved
+pub struct ArrayZip;
diff --git a/src/test/rustdoc-ui/intra-doc/unused-extern-crate.stderr b/src/test/rustdoc-ui/intra-doc/unused-extern-crate.stderr
new file mode 100644
index 00000000000..b3b57fd1318
--- /dev/null
+++ b/src/test/rustdoc-ui/intra-doc/unused-extern-crate.stderr
@@ -0,0 +1,15 @@
+error: unresolved link to `zip`
+  --> $DIR/unused-extern-crate.rs:3:10
+   |
+LL | /// See [zip] crate.
+   |          ^^^ no item named `zip` in scope
+   |
+note: the lint level is defined here
+  --> $DIR/unused-extern-crate.rs:2:9
+   |
+LL | #![deny(broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: aborting due to previous error
+
diff --git a/src/test/rustdoc-ui/invalid-syntax.stderr b/src/test/rustdoc-ui/invalid-syntax.stderr
index 9a7a4d21013..75acdc5ab5f 100644
--- a/src/test/rustdoc-ui/invalid-syntax.stderr
+++ b/src/test/rustdoc-ui/invalid-syntax.stderr
@@ -127,8 +127,10 @@ LL | /// ```text
 warning: could not parse code block as Rust code
   --> $DIR/invalid-syntax.rs:92:9
    |
-LL | ///     \____/
-   |         ^^^^^^
+LL |   ///     \____/
+   |  _________^
+LL | | ///
+   | |_
    |
    = note: error from rustc: unknown start of token: \
 
diff --git a/src/test/rustdoc-ui/range-pattern.rs b/src/test/rustdoc-ui/range-pattern.rs
new file mode 100644
index 00000000000..fd255d02fcb
--- /dev/null
+++ b/src/test/rustdoc-ui/range-pattern.rs
@@ -0,0 +1,3 @@
+// check-pass
+
+fn func(0u8..=255: u8) {}
diff --git a/src/test/rustdoc-ui/reference-link-reports-error-once.rs b/src/test/rustdoc-ui/reference-link-reports-error-once.rs
new file mode 100644
index 00000000000..7957ee373c4
--- /dev/null
+++ b/src/test/rustdoc-ui/reference-link-reports-error-once.rs
@@ -0,0 +1,20 @@
+#![deny(broken_intra_doc_links)]
+
+/// Links to [a] [link][a]
+/// And also a [third link][a]
+/// And also a [reference link][b]
+///
+/// Other links to the same target should still emit error: [ref] //~ERROR unresolved link to `ref`
+/// Duplicate [ref] //~ERROR unresolved link to `ref`
+///
+/// Other links to other targets should still emit error: [ref2] //~ERROR unresolved link to `ref2`
+/// Duplicate [ref2] //~ERROR unresolved link to `ref2`
+///
+/// [a]: ref
+//~^ ERROR unresolved link to `ref`
+/// [b]: ref2
+//~^ ERROR unresolved link to
+
+/// [ref][]
+//~^ ERROR unresolved link
+pub fn f() {}
diff --git a/src/test/rustdoc-ui/reference-link-reports-error-once.stderr b/src/test/rustdoc-ui/reference-link-reports-error-once.stderr
new file mode 100644
index 00000000000..218eb334a6f
--- /dev/null
+++ b/src/test/rustdoc-ui/reference-link-reports-error-once.stderr
@@ -0,0 +1,63 @@
+error: unresolved link to `ref`
+  --> $DIR/reference-link-reports-error-once.rs:13:10
+   |
+LL | /// [a]: ref
+   |          ^^^ no item named `ref` in scope
+   |
+note: the lint level is defined here
+  --> $DIR/reference-link-reports-error-once.rs:1:9
+   |
+LL | #![deny(broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref2`
+  --> $DIR/reference-link-reports-error-once.rs:15:10
+   |
+LL | /// [b]: ref2
+   |          ^^^^ no item named `ref2` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref`
+  --> $DIR/reference-link-reports-error-once.rs:7:62
+   |
+LL | /// Other links to the same target should still emit error: [ref]
+   |                                                              ^^^ no item named `ref` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref`
+  --> $DIR/reference-link-reports-error-once.rs:8:16
+   |
+LL | /// Duplicate [ref]
+   |                ^^^ no item named `ref` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref2`
+  --> $DIR/reference-link-reports-error-once.rs:10:60
+   |
+LL | /// Other links to other targets should still emit error: [ref2]
+   |                                                            ^^^^ no item named `ref2` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref2`
+  --> $DIR/reference-link-reports-error-once.rs:11:16
+   |
+LL | /// Duplicate [ref2]
+   |                ^^^^ no item named `ref2` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: unresolved link to `ref`
+  --> $DIR/reference-link-reports-error-once.rs:18:6
+   |
+LL | /// [ref][]
+   |      ^^^ no item named `ref` in scope
+   |
+   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+
+error: aborting due to 7 previous errors
+
diff --git a/src/test/rustdoc-ui/reference-links.rs b/src/test/rustdoc-ui/reference-links.rs
index 7c1a79722c9..6e00b9f0fa1 100644
--- a/src/test/rustdoc-ui/reference-links.rs
+++ b/src/test/rustdoc-ui/reference-links.rs
@@ -4,4 +4,3 @@
 //!
 //! [a]: std::process::Comman
 //~^ ERROR unresolved
-//~| ERROR unresolved
diff --git a/src/test/rustdoc-ui/reference-links.stderr b/src/test/rustdoc-ui/reference-links.stderr
index 6ba73fbdb00..3df89df21b4 100644
--- a/src/test/rustdoc-ui/reference-links.stderr
+++ b/src/test/rustdoc-ui/reference-links.stderr
@@ -10,11 +10,5 @@ note: the lint level is defined here
 LL | #![deny(broken_intra_doc_links)]
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
-error: unresolved link to `std::process::Comman`
-  --> $DIR/reference-links.rs:5:10
-   |
-LL | //! [a]: std::process::Comman
-   |          ^^^^^^^^^^^^^^^^^^^^ no item named `Comman` in module `process`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/src/test/rustdoc/auxiliary/macro_pub_in_module.rs b/src/test/rustdoc/auxiliary/macro_pub_in_module.rs
new file mode 100644
index 00000000000..137b1238600
--- /dev/null
+++ b/src/test/rustdoc/auxiliary/macro_pub_in_module.rs
@@ -0,0 +1,13 @@
+// edition:2018
+
+#![feature(decl_macro)]
+#![crate_name = "external_crate"]
+
+pub mod some_module {
+    /* == Make sure the logic is not affected by a re-export == */
+    mod private {
+        pub macro external_macro() {}
+    }
+
+    pub use private::external_macro;
+}
diff --git a/src/test/rustdoc/deref-recursive-pathbuf.rs b/src/test/rustdoc/deref-recursive-pathbuf.rs
new file mode 100644
index 00000000000..759e881aab4
--- /dev/null
+++ b/src/test/rustdoc/deref-recursive-pathbuf.rs
@@ -0,0 +1,26 @@
+// ignore-tidy-linelength
+
+// #26207: Show all methods reachable via Deref impls, recursing through multiple dereferencing
+// levels and across multiple crates.
+
+// @has 'foo/struct.Foo.html'
+// @has '-' '//*[@id="deref-methods-PathBuf"]' 'Methods from Deref<Target = PathBuf>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.as_path"]' 'pub fn as_path(&self)'
+// @has '-' '//*[@id="deref-methods-Path"]' 'Methods from Deref<Target = Path>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.exists"]' 'pub fn exists(&self)'
+// @has '-' '//*[@class="sidebar-title"][@href="#deref-methods-PathBuf"]' 'Methods from Deref<Target=PathBuf>'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.as_path"]' 'as_path'
+// @has '-' '//*[@class="sidebar-title"][@href="#deref-methods-Path"]' 'Methods from Deref<Target=Path>'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.exists"]' 'exists'
+
+#![crate_name = "foo"]
+
+use std::ops::Deref;
+use std::path::PathBuf;
+
+pub struct Foo(PathBuf);
+
+impl Deref for Foo {
+    type Target = PathBuf;
+    fn deref(&self) -> &PathBuf { &self.0 }
+}
diff --git a/src/test/rustdoc/deref-recursive.rs b/src/test/rustdoc/deref-recursive.rs
new file mode 100644
index 00000000000..5aef87c38cd
--- /dev/null
+++ b/src/test/rustdoc/deref-recursive.rs
@@ -0,0 +1,42 @@
+// ignore-tidy-linelength
+
+// #26207: Show all methods reachable via Deref impls, recursing through multiple dereferencing
+// levels if needed.
+
+// @has 'foo/struct.Foo.html'
+// @has '-' '//*[@id="deref-methods-Bar"]' 'Methods from Deref<Target = Bar>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.bar"]' 'pub fn bar(&self)'
+// @has '-' '//*[@id="deref-methods-Baz"]' 'Methods from Deref<Target = Baz>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.baz"]' 'pub fn baz(&self)'
+// @has '-' '//*[@class="sidebar-title"][@href="#deref-methods-Bar"]' 'Methods from Deref<Target=Bar>'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.bar"]' 'bar'
+// @has '-' '//*[@class="sidebar-title"][@href="#deref-methods-Baz"]' 'Methods from Deref<Target=Baz>'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.baz"]' 'baz'
+
+#![crate_name = "foo"]
+
+use std::ops::Deref;
+
+pub struct Foo(Bar);
+pub struct Bar(Baz);
+pub struct Baz;
+
+impl Deref for Foo {
+    type Target = Bar;
+    fn deref(&self) -> &Bar { &self.0 }
+}
+
+impl Deref for Bar {
+    type Target = Baz;
+    fn deref(&self) -> &Baz { &self.0 }
+}
+
+impl Bar {
+    /// This appears under `Foo` methods
+    pub fn bar(&self) {}
+}
+
+impl Baz {
+    /// This should also appear in `Foo` methods when recursing
+    pub fn baz(&self) {}
+}
diff --git a/src/test/rustdoc/deref-typedef.rs b/src/test/rustdoc/deref-typedef.rs
index 770f8d7289c..589f133b975 100644
--- a/src/test/rustdoc/deref-typedef.rs
+++ b/src/test/rustdoc/deref-typedef.rs
@@ -1,18 +1,29 @@
+// ignore-tidy-linelength
+
 #![crate_name = "foo"]
 
 // @has 'foo/struct.Bar.html'
-// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref<Target = FooC>'
+// @has '-' '//*[@id="deref-methods-FooJ"]' 'Methods from Deref<Target = FooJ>'
 // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_a"]' 'pub fn foo_a(&self)'
 // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_b"]' 'pub fn foo_b(&self)'
 // @has '-' '//*[@class="impl-items"]//*[@id="method.foo_c"]' 'pub fn foo_c(&self)'
-// @has '-' '//*[@class="sidebar-title"]' 'Methods from Deref<Target=FooC>'
+// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_j"]' 'pub fn foo_j(&self)'
+// @has '-' '//*[@class="sidebar-title"][@href="#deref-methods-FooJ"]' 'Methods from Deref<Target=FooJ>'
 // @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_a"]' 'foo_a'
 // @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_b"]' 'foo_b'
 // @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_c"]' 'foo_c'
+// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_j"]' 'foo_j'
 
 pub struct FooA;
 pub type FooB = FooA;
 pub type FooC = FooB;
+pub type FooD = FooC;
+pub type FooE = FooD;
+pub type FooF = FooE;
+pub type FooG = FooF;
+pub type FooH = FooG;
+pub type FooI = FooH;
+pub type FooJ = FooI;
 
 impl FooA {
     pub fn foo_a(&self) {}
@@ -26,8 +37,12 @@ impl FooC {
     pub fn foo_c(&self) {}
 }
 
+impl FooJ {
+    pub fn foo_j(&self) {}
+}
+
 pub struct Bar;
 impl std::ops::Deref for Bar {
-    type Target = FooC;
+    type Target = FooJ;
     fn deref(&self) -> &Self::Target { unimplemented!() }
 }
diff --git a/src/test/rustdoc/intra-doc-crate/auxiliary/self.rs b/src/test/rustdoc/intra-doc-crate/auxiliary/self.rs
index cdfe842f3cc..54902f12eb1 100644
--- a/src/test/rustdoc/intra-doc-crate/auxiliary/self.rs
+++ b/src/test/rustdoc/intra-doc-crate/auxiliary/self.rs
@@ -1,4 +1,7 @@
 #![crate_name = "cross_crate_self"]
+
+/// Link to [Self]
+/// Link to [crate]
 pub struct S;
 
 impl S {
diff --git a/src/test/rustdoc/intra-doc-crate/self.rs b/src/test/rustdoc/intra-doc-crate/self.rs
index 62aef8e85af..4db63b12b6b 100644
--- a/src/test/rustdoc/intra-doc-crate/self.rs
+++ b/src/test/rustdoc/intra-doc-crate/self.rs
@@ -1,6 +1,9 @@
 // aux-build:self.rs
+// build-aux-docs
 
 extern crate cross_crate_self;
 
 // @has self/struct.S.html '//a[@href="../self/struct.S.html#method.f"]' "Self::f"
+// @has self/struct.S.html '//a[@href="../self/struct.S.html"]' "Self"
+// @has self/struct.S.html '//a[@href="../cross_crate_self/index.html"]' "crate"
 pub use cross_crate_self::S;
diff --git a/src/test/rustdoc/intra-doc/non-path-primitives.rs b/src/test/rustdoc/intra-doc/non-path-primitives.rs
index ad4f6ddd9de..2c7e7b5c48c 100644
--- a/src/test/rustdoc/intra-doc/non-path-primitives.rs
+++ b/src/test/rustdoc/intra-doc/non-path-primitives.rs
@@ -8,14 +8,21 @@
 // @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.array.html#method.map"]' 'array::map'
 //! [array::map]
 
+// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html"]' 'owned str'
+// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html"]' 'str ref'
+// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.is_empty"]' 'str::is_empty'
+// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.len"]' '&str::len'
+//! [owned str][str]
+//! [str ref][&str]
+//! [str::is_empty]
+//! [&str::len]
+
 // @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.is_null"]' 'pointer::is_null'
 // @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.is_null"]' '*const::is_null'
 // @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.is_null"]' '*mut::is_null'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.is_null"]' '*::is_null'
 //! [pointer::is_null]
 //! [*const::is_null]
 //! [*mut::is_null]
-//! [*::is_null]
 
 // @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.unit.html"]' 'unit'
 //! [unit]
diff --git a/src/test/rustdoc/intra-doc/primitive-disambiguators.rs b/src/test/rustdoc/intra-doc/primitive-disambiguators.rs
new file mode 100644
index 00000000000..acdd07566c9
--- /dev/null
+++ b/src/test/rustdoc/intra-doc/primitive-disambiguators.rs
@@ -0,0 +1,4 @@
+#![deny(broken_intra_doc_links)]
+// @has primitive_disambiguators/index.html
+// @has - '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim'
+//! [str::trim()]
diff --git a/src/test/rustdoc/macro_pub_in_module.rs b/src/test/rustdoc/macro_pub_in_module.rs
new file mode 100644
index 00000000000..4fd85d68994
--- /dev/null
+++ b/src/test/rustdoc/macro_pub_in_module.rs
@@ -0,0 +1,82 @@
+// aux-build:macro_pub_in_module.rs
+// edition:2018
+// build-aux-docs
+
+//! See issue #74355
+#![feature(decl_macro, no_core, rustc_attrs)]
+#![crate_name = "krate"]
+#![no_core]
+
+ // @has external_crate/some_module/macro.external_macro.html
+  // @!has external_crate/macro.external_macro.html
+extern crate external_crate;
+
+pub mod inner {
+    // @has krate/inner/macro.raw_const.html
+    // @!has krate/macro.raw_const.html
+    pub macro raw_const() {}
+
+    // @has krate/inner/macro.test.html
+    // @!has krate/macro.test.html
+    #[rustc_builtin_macro]
+    pub macro test($item:item) {}
+
+    // @has krate/inner/macro.Clone.html
+    // @!has krate/macro.Clone.html
+    #[rustc_builtin_macro]
+    pub macro Clone($item:item) {}
+
+    // Make sure the logic is not affected by re-exports.
+    mod unrenamed {
+        // @!has krate/macro.unrenamed.html
+        #[rustc_macro_transparency = "semitransparent"]
+        pub macro unrenamed() {}
+    }
+    // @has krate/inner/macro.unrenamed.html
+    pub use unrenamed::unrenamed;
+
+    mod private {
+        // @!has krate/macro.m.html
+        pub macro m() {}
+    }
+    // @has krate/inner/macro.renamed.html
+    // @!has krate/macro.renamed.html
+    pub use private::m as renamed;
+
+    mod private2 {
+        // @!has krate/macro.m2.html
+        pub macro m2() {}
+    }
+    use private2 as renamed_mod;
+    // @has krate/inner/macro.m2.html
+    pub use renamed_mod::m2;
+
+    // @has krate/inner/macro.external_macro.html
+    // @!has krate/macro.external_macro.html
+    pub use ::external_crate::some_module::external_macro;
+}
+
+// Namespaces: Make sure the logic does not mix up a function name with a module name…
+fn both_fn_and_mod() {
+    // @!has krate/macro.in_both_fn_and_mod.html
+    pub macro in_both_fn_and_mod() {}
+}
+pub mod both_fn_and_mod {
+    // @!has krate/both_fn_and_mod/macro.in_both_fn_and_mod.html
+}
+
+const __: () = {
+    // @!has krate/macro.in_both_const_and_mod.html
+    pub macro in_both_const_and_mod() {}
+};
+pub mod __ {
+    // @!has krate/__/macro.in_both_const_and_mod.html
+}
+
+enum Enum {
+    Crazy = {
+        // @!has krate/macro.this_is_getting_weird.html;
+        pub macro this_is_getting_weird() {}
+        42
+    },
+}
diff --git a/src/test/rustdoc/macros.rs b/src/test/rustdoc/macros.rs
index fb4f02ad160..ae0cf7a1478 100644
--- a/src/test/rustdoc/macros.rs
+++ b/src/test/rustdoc/macros.rs
@@ -8,3 +8,17 @@ macro_rules! my_macro {
     ($a:tt) => ();
     ($e:expr) => {};
 }
+
+// Check that exported macro defined in a module are shown at crate root.
+// @has macros/macro.my_sub_macro.html //pre 'macro_rules! my_sub_macro {'
+// @has - //pre '() => { ... };'
+// @has - //pre '($a:tt) => { ... };'
+// @has - //pre '($e:expr) => { ... };'
+mod sub {
+    #[macro_export]
+    macro_rules! my_sub_macro {
+        () => {};
+        ($a:tt) => {};
+        ($e:expr) => {};
+    }
+}
diff --git a/src/test/rustdoc/range-arg-pattern.rs b/src/test/rustdoc/range-arg-pattern.rs
new file mode 100644
index 00000000000..f4cc36b1055
--- /dev/null
+++ b/src/test/rustdoc/range-arg-pattern.rs
@@ -0,0 +1,5 @@
+#![crate_name = "foo"]
+
+// @has foo/fn.f.html
+// @has - '//*[@class="rust fn"]' 'pub fn f(0u8 ...255: u8)'
+pub fn f(0u8...255: u8) {}
diff --git a/src/test/ui/abi/issues/issue-22565-rust-call.rs b/src/test/ui/abi/issues/issue-22565-rust-call.rs
index 055d959b46e..a08e0bfb5e5 100644
--- a/src/test/ui/abi/issues/issue-22565-rust-call.rs
+++ b/src/test/ui/abi/issues/issue-22565-rust-call.rs
@@ -1,8 +1,32 @@
 #![feature(unboxed_closures)]
 
 extern "rust-call" fn b(_i: i32) {}
-//~^ ERROR A function with the "rust-call" ABI must take a single non-self argument that is a tuple
+//~^ ERROR functions with the "rust-call" ABI must take a single non-self argument that is a tuple
+
+trait Tr {
+    extern "rust-call" fn a();
+
+    extern "rust-call" fn b() {}
+    //~^ ERROR functions with the "rust-call" ABI must take a single non-self argument
+}
+
+struct Foo;
+
+impl Foo {
+    extern "rust-call" fn bar() {}
+    //~^ ERROR functions with the "rust-call" ABI must take a single non-self argument
+}
+
+impl Tr for Foo {
+    extern "rust-call" fn a() {}
+    //~^ ERROR functions with the "rust-call" ABI must take a single non-self argument
+}
 
 fn main () {
     b(10);
+
+    Foo::bar();
+
+    <Foo as Tr>::a();
+    <Foo as Tr>::b();
 }
diff --git a/src/test/ui/abi/issues/issue-22565-rust-call.stderr b/src/test/ui/abi/issues/issue-22565-rust-call.stderr
index 31fb035eb99..3eee10bc5e9 100644
--- a/src/test/ui/abi/issues/issue-22565-rust-call.stderr
+++ b/src/test/ui/abi/issues/issue-22565-rust-call.stderr
@@ -1,8 +1,26 @@
-error: A function with the "rust-call" ABI must take a single non-self argument that is a tuple
+error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
   --> $DIR/issue-22565-rust-call.rs:3:1
    |
 LL | extern "rust-call" fn b(_i: i32) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
+  --> $DIR/issue-22565-rust-call.rs:9:5
+   |
+LL |     extern "rust-call" fn b() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
+  --> $DIR/issue-22565-rust-call.rs:16:5
+   |
+LL |     extern "rust-call" fn bar() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
+  --> $DIR/issue-22565-rust-call.rs:21:5
+   |
+LL |     extern "rust-call" fn a() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/ast-json/ast-json-noexpand-output.stdout b/src/test/ui/ast-json/ast-json-noexpand-output.stdout
index deb2a1af204..9c29a5f2337 100644
--- a/src/test/ui/ast-json/ast-json-noexpand-output.stdout
+++ b/src/test/ui/ast-json/ast-json-noexpand-output.stdout
@@ -1 +1 @@
-{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":null}]}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
+{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":null}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout
index 71336f452fc..cccd51985dc 100644
--- a/src/test/ui/ast-json/ast-json-output.stdout
+++ b/src/test/ui/ast-json/ast-json-output.stdout
@@ -1 +1 @@
-{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":null}]}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
+{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":null}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
diff --git a/src/test/ui/async-await/feature-async-closure.stderr b/src/test/ui/async-await/feature-async-closure.stderr
index ba851ba7d29..485a838b67f 100644
--- a/src/test/ui/async-await/feature-async-closure.stderr
+++ b/src/test/ui/async-await/feature-async-closure.stderr
@@ -6,6 +6,7 @@ LL |     let _ = async || {};
    |
    = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
    = help: add `#![feature(async_closure)]` to the crate attributes to enable
+   = help: to use an async block, remove the `||`: `async {`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/attributes/key-value-expansion-on-mac.rs b/src/test/ui/attributes/key-value-expansion-on-mac.rs
new file mode 100644
index 00000000000..1247ff2b230
--- /dev/null
+++ b/src/test/ui/attributes/key-value-expansion-on-mac.rs
@@ -0,0 +1,15 @@
+#![feature(extended_key_value_attributes)]
+#![feature(rustc_attrs)]
+
+#[rustc_dummy = stringify!(a)] // OK
+macro_rules! bar {
+    () => {};
+}
+
+// FIXME?: `bar` here expands before `stringify` has a chance to expand.
+// `#[rustc_dummy = ...]` is validated and dropped during expansion of `bar`,
+// the "unexpected token" errors comes from the validation.
+#[rustc_dummy = stringify!(b)] //~ ERROR unexpected token: `stringify!(b)`
+bar!();
+
+fn main() {}
diff --git a/src/test/ui/attributes/key-value-expansion-on-mac.stderr b/src/test/ui/attributes/key-value-expansion-on-mac.stderr
new file mode 100644
index 00000000000..b74f3518a7e
--- /dev/null
+++ b/src/test/ui/attributes/key-value-expansion-on-mac.stderr
@@ -0,0 +1,8 @@
+error: unexpected token: `stringify!(b)`
+  --> $DIR/key-value-expansion-on-mac.rs:12:17
+   |
+LL | #[rustc_dummy = stringify!(b)]
+   |                 ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/check-doc-alias-attr-location.rs b/src/test/ui/check-doc-alias-attr-location.rs
index dac9b7372e0..3a0436e468d 100644
--- a/src/test/ui/check-doc-alias-attr-location.rs
+++ b/src/test/ui/check-doc-alias-attr-location.rs
@@ -1,5 +1,4 @@
 #![crate_type="lib"]
-#![feature(doc_alias)]
 
 pub struct Bar;
 pub trait Foo {
diff --git a/src/test/ui/check-doc-alias-attr-location.stderr b/src/test/ui/check-doc-alias-attr-location.stderr
index 29a99e4470e..a66e9939eaf 100644
--- a/src/test/ui/check-doc-alias-attr-location.stderr
+++ b/src/test/ui/check-doc-alias-attr-location.stderr
@@ -1,23 +1,23 @@
 error: `#[doc(alias = "...")]` isn't allowed on extern block
-  --> $DIR/check-doc-alias-attr-location.rs:10:7
+  --> $DIR/check-doc-alias-attr-location.rs:9:7
    |
 LL | #[doc(alias = "foo")]
    |       ^^^^^^^^^^^^^
 
 error: `#[doc(alias = "...")]` isn't allowed on implementation block
-  --> $DIR/check-doc-alias-attr-location.rs:13:7
+  --> $DIR/check-doc-alias-attr-location.rs:12:7
    |
 LL | #[doc(alias = "bar")]
    |       ^^^^^^^^^^^^^
 
 error: `#[doc(alias = "...")]` isn't allowed on implementation block
-  --> $DIR/check-doc-alias-attr-location.rs:19:7
+  --> $DIR/check-doc-alias-attr-location.rs:18:7
    |
 LL | #[doc(alias = "foobar")]
    |       ^^^^^^^^^^^^^^^^
 
 error: `#[doc(alias = "...")]` isn't allowed on type alias in implementation block
-  --> $DIR/check-doc-alias-attr-location.rs:21:11
+  --> $DIR/check-doc-alias-attr-location.rs:20:11
    |
 LL |     #[doc(alias = "assoc")]
    |           ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/check-doc-alias-attr.rs b/src/test/ui/check-doc-alias-attr.rs
index 0ca2349a43b..912e35f9165 100644
--- a/src/test/ui/check-doc-alias-attr.rs
+++ b/src/test/ui/check-doc-alias-attr.rs
@@ -1,5 +1,4 @@
 #![crate_type = "lib"]
-#![feature(doc_alias)]
 
 #[doc(alias = "foo")] // ok!
 pub struct Bar;
diff --git a/src/test/ui/check-doc-alias-attr.stderr b/src/test/ui/check-doc-alias-attr.stderr
index dce325f9d38..1c7fc83bb8d 100644
--- a/src/test/ui/check-doc-alias-attr.stderr
+++ b/src/test/ui/check-doc-alias-attr.stderr
@@ -1,35 +1,35 @@
 error: doc alias attribute expects a string: #[doc(alias = "a")]
-  --> $DIR/check-doc-alias-attr.rs:7:7
+  --> $DIR/check-doc-alias-attr.rs:6:7
    |
 LL | #[doc(alias)]
    |       ^^^^^
 
 error: doc alias attribute expects a string: #[doc(alias = "a")]
-  --> $DIR/check-doc-alias-attr.rs:8:7
+  --> $DIR/check-doc-alias-attr.rs:7:7
    |
 LL | #[doc(alias = 0)]
    |       ^^^^^^^^^
 
 error: doc alias attribute expects a string: #[doc(alias = "a")]
-  --> $DIR/check-doc-alias-attr.rs:9:7
+  --> $DIR/check-doc-alias-attr.rs:8:7
    |
 LL | #[doc(alias("bar"))]
    |       ^^^^^^^^^^^^
 
 error: '\"' character isn't allowed in `#[doc(alias = "...")]`
-  --> $DIR/check-doc-alias-attr.rs:10:15
+  --> $DIR/check-doc-alias-attr.rs:9:15
    |
 LL | #[doc(alias = "\"")]
    |               ^^^^
 
 error: '\n' character isn't allowed in `#[doc(alias = "...")]`
-  --> $DIR/check-doc-alias-attr.rs:11:15
+  --> $DIR/check-doc-alias-attr.rs:10:15
    |
 LL | #[doc(alias = "\n")]
    |               ^^^^
 
 error: '\n' character isn't allowed in `#[doc(alias = "...")]`
-  --> $DIR/check-doc-alias-attr.rs:12:15
+  --> $DIR/check-doc-alias-attr.rs:11:15
    |
 LL |   #[doc(alias = "
    |  _______________^
@@ -37,19 +37,19 @@ LL | | ")]
    | |_^
 
 error: '\t' character isn't allowed in `#[doc(alias = "...")]`
-  --> $DIR/check-doc-alias-attr.rs:14:15
+  --> $DIR/check-doc-alias-attr.rs:13:15
    |
 LL | #[doc(alias = "\t")]
    |               ^^^^
 
 error: `#[doc(alias = "...")]` cannot start or end with ' '
-  --> $DIR/check-doc-alias-attr.rs:15:15
+  --> $DIR/check-doc-alias-attr.rs:14:15
    |
 LL | #[doc(alias = " hello")]
    |               ^^^^^^^^
 
 error: `#[doc(alias = "...")]` cannot start or end with ' '
-  --> $DIR/check-doc-alias-attr.rs:16:15
+  --> $DIR/check-doc-alias-attr.rs:15:15
    |
 LL | #[doc(alias = "hello ")]
    |               ^^^^^^^^
diff --git a/src/test/ui/codemap_tests/tab_3.stderr b/src/test/ui/codemap_tests/tab_3.stderr
index 958d54bbb15..e067dbbf85b 100644
--- a/src/test/ui/codemap_tests/tab_3.stderr
+++ b/src/test/ui/codemap_tests/tab_3.stderr
@@ -9,7 +9,7 @@ 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`
+note: this function takes ownership of the receiver `self`, which moves `some_vec`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    |
 LL |     fn into_iter(self) -> Self::IntoIter;
diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr b/src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr
index 7af23103ce7..8f6e56826fa 100644
--- a/src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr
+++ b/src/test/ui/const-generics/array-size-in-generic-struct-param.min.stderr
@@ -23,7 +23,7 @@ LL | struct B<const CFG: Config> {
    |                     ^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/const-generics/const-param-before-other-params.min.stderr b/src/test/ui/const-generics/const-param-before-other-params.min.stderr
index 1e49588f1b4..a9349ce43c9 100644
--- a/src/test/ui/const-generics/const-param-before-other-params.min.stderr
+++ b/src/test/ui/const-generics/const-param-before-other-params.min.stderr
@@ -17,7 +17,7 @@ LL | fn bar<const X: (), 'a>(_: &'a ()) {
    |                 ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `()` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-before-other-params.rs:10:17
@@ -26,7 +26,7 @@ LL | fn foo<const X: (), T>(_: &T) {}
    |                 ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr b/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr
index 5d3c8f7b2e6..48d33a785ae 100644
--- a/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr
+++ b/src/test/ui/const-generics/const-param-elided-lifetime.min.stderr
@@ -35,7 +35,7 @@ LL | struct A<const N: &u8>;
    |                   ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-elided-lifetime.rs:15:15
@@ -44,7 +44,7 @@ LL | impl<const N: &u8> A<N> {
    |               ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-elided-lifetime.rs:23:15
@@ -53,7 +53,7 @@ LL | impl<const N: &u8> B for A<N> {}
    |               ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-elided-lifetime.rs:27:17
@@ -62,7 +62,7 @@ LL | fn bar<const N: &u8>() {}
    |                 ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-elided-lifetime.rs:18:21
@@ -71,7 +71,7 @@ LL |     fn foo<const M: &u8>(&self) {}
    |                     ^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 10 previous errors
 
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr b/src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr
index d63bc236320..9804363f39a 100644
--- a/src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr
+++ b/src/test/ui/const-generics/const-param-type-depends-on-const-param.min.stderr
@@ -17,7 +17,7 @@ LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
    |                                               ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `[u8; _]` is forbidden as the type of a const generic parameter
   --> $DIR/const-param-type-depends-on-const-param.rs:15:35
@@ -26,7 +26,7 @@ LL | pub struct SelfDependent<const N: [u8; N]>;
    |                                   ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/const-generics/different_byref.min.stderr b/src/test/ui/const-generics/different_byref.min.stderr
index 05720d15404..93874fb1f5f 100644
--- a/src/test/ui/const-generics/different_byref.min.stderr
+++ b/src/test/ui/const-generics/different_byref.min.stderr
@@ -5,7 +5,7 @@ LL | struct Const<const V: [usize; 1]> {}
    |                       ^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr b/src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr
index 3912cf57751..80eac994d55 100644
--- a/src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr
+++ b/src/test/ui/const-generics/forbid-non-structural_match-types.min.stderr
@@ -5,7 +5,7 @@ LL | struct B<const X: A>; // ok
    |                   ^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `C` is forbidden as the type of a const generic parameter
   --> $DIR/forbid-non-structural_match-types.rs:14:19
@@ -14,7 +14,7 @@ LL | struct D<const X: C>;
    |                   ^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error[E0741]: `C` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
   --> $DIR/forbid-non-structural_match-types.rs:14:19
diff --git a/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr b/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr
index 4c2aaef3493..8701d54f5c9 100644
--- a/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr
+++ b/src/test/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr
@@ -14,7 +14,7 @@ LL | trait Trait<const S: &'static str> {}
    |                      ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr b/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr
index b6c6e6fe374..e96b9e70352 100644
--- a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr
+++ b/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.min.stderr
@@ -5,7 +5,7 @@ LL | trait Trait<const NAME: &'static str> {
    |                         ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr b/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr
index a0aee4821c6..5c9387d4012 100644
--- a/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-62579-no-match.min.stderr
@@ -5,7 +5,7 @@ LL | fn foo<const T: NoMatch>() -> bool {
    |                 ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-62878.min.stderr b/src/test/ui/const-generics/issues/issue-62878.min.stderr
index 920d7e43b9b..e4a71fe0618 100644
--- a/src/test/ui/const-generics/issues/issue-62878.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-62878.min.stderr
@@ -11,7 +11,7 @@ LL | fn foo<const N: usize, const A: [u8; N]>() {}
    |                                 ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr
index 543e4b29a16..2fb38addb2d 100644
--- a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr
@@ -5,7 +5,7 @@ LL | fn test<const T: &'static dyn A>() {
    |                  ^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error[E0741]: `&'static (dyn A + 'static)` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
   --> $DIR/issue-63322-forbid-dyn.rs:9:18
diff --git a/src/test/ui/const-generics/issues/issue-68615-adt.min.stderr b/src/test/ui/const-generics/issues/issue-68615-adt.min.stderr
index 2de8ada2766..4782b1d98eb 100644
--- a/src/test/ui/const-generics/issues/issue-68615-adt.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-68615-adt.min.stderr
@@ -5,7 +5,7 @@ LL | struct Const<const V: [usize; 0]> {}
    |                       ^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-68615-array.min.stderr b/src/test/ui/const-generics/issues/issue-68615-array.min.stderr
index 0d17b04a5cd..d0c190b91b0 100644
--- a/src/test/ui/const-generics/issues/issue-68615-array.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-68615-array.min.stderr
@@ -5,7 +5,7 @@ LL | struct Foo<const V: [usize; 0] > {}
    |                     ^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-71169.min.stderr b/src/test/ui/const-generics/issues/issue-71169.min.stderr
index 68ac47460b3..1c6e08adffd 100644
--- a/src/test/ui/const-generics/issues/issue-71169.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-71169.min.stderr
@@ -11,7 +11,7 @@ LL | fn foo<const LEN: usize, const DATA: [u8; LEN]>() {}
    |                                      ^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/issues/issue-73491.min.stderr b/src/test/ui/const-generics/issues/issue-73491.min.stderr
index aeab9e26772..c8f2e0dadc1 100644
--- a/src/test/ui/const-generics/issues/issue-73491.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-73491.min.stderr
@@ -5,7 +5,7 @@ LL | fn hoge<const IN: [u32; LEN]>() {}
    |                   ^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-74101.min.stderr b/src/test/ui/const-generics/issues/issue-74101.min.stderr
index 6561183f7ca..a7f0ecf0a26 100644
--- a/src/test/ui/const-generics/issues/issue-74101.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-74101.min.stderr
@@ -5,7 +5,7 @@ LL | fn test<const N: [u8; 1 + 2]>() {}
    |                  ^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `[u8; _]` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74101.rs:9:21
@@ -14,7 +14,7 @@ LL | struct Foo<const N: [u8; 1 + 2]>;
    |                     ^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/issues/issue-74255.min.stderr b/src/test/ui/const-generics/issues/issue-74255.min.stderr
index 2b6aa7dad97..62ad43974f4 100644
--- a/src/test/ui/const-generics/issues/issue-74255.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-74255.min.stderr
@@ -5,7 +5,7 @@ LL |     fn ice_struct_fn<const I: IceEnum>() {}
    |                               ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-74950.min.stderr b/src/test/ui/const-generics/issues/issue-74950.min.stderr
index 27393d38c6b..4e640ff857e 100644
--- a/src/test/ui/const-generics/issues/issue-74950.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-74950.min.stderr
@@ -5,7 +5,7 @@ LL | struct Outer<const I: Inner>;
    |                       ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `Inner` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74950.rs:17:23
@@ -14,7 +14,7 @@ LL | struct Outer<const I: Inner>;
    |                       ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `Inner` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74950.rs:17:23
@@ -23,7 +23,7 @@ LL | struct Outer<const I: Inner>;
    |                       ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `Inner` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74950.rs:17:23
@@ -32,7 +32,7 @@ LL | struct Outer<const I: Inner>;
    |                       ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `Inner` is forbidden as the type of a const generic parameter
   --> $DIR/issue-74950.rs:17:23
@@ -41,7 +41,7 @@ LL | struct Outer<const I: Inner>;
    |                       ^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/const-generics/issues/issue-75047.min.stderr b/src/test/ui/const-generics/issues/issue-75047.min.stderr
index 4ab90dd1ec6..3c1c3ea97b5 100644
--- a/src/test/ui/const-generics/issues/issue-75047.min.stderr
+++ b/src/test/ui/const-generics/issues/issue-75047.min.stderr
@@ -5,7 +5,7 @@ LL | struct Foo<const N: [u8; Bar::<u32>::value()]>;
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/min_const_generics/complex-types.stderr b/src/test/ui/const-generics/min_const_generics/complex-types.stderr
index 20d498f9c93..a658a7b3956 100644
--- a/src/test/ui/const-generics/min_const_generics/complex-types.stderr
+++ b/src/test/ui/const-generics/min_const_generics/complex-types.stderr
@@ -5,7 +5,7 @@ LL | struct Foo<const N: [u8; 0]>;
    |                     ^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `()` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:6:21
@@ -14,7 +14,7 @@ LL | struct Bar<const N: ()>;
    |                     ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `No` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:11:21
@@ -23,7 +23,7 @@ LL | struct Fez<const N: No>;
    |                     ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `&'static u8` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:14:21
@@ -32,7 +32,7 @@ LL | struct Faz<const N: &'static u8>;
    |                     ^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `!` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:17:21
@@ -41,7 +41,7 @@ LL | struct Fiz<const N: !>;
    |                     ^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `()` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:20:19
@@ -50,7 +50,7 @@ LL | enum Goo<const N: ()> { A, B }
    |                   ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `()` is forbidden as the type of a const generic parameter
   --> $DIR/complex-types.rs:23:20
@@ -59,7 +59,7 @@ LL | union Boo<const N: ()> { a: () }
    |                    ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.stderr b/src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.stderr
index 05939b05bba..647ef5400cb 100644
--- a/src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.stderr
+++ b/src/test/ui/const-generics/min_const_generics/static-reference-array-const-param.stderr
@@ -5,7 +5,7 @@ LL | fn a<const X: &'static [u32]>() {}
    |               ^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr b/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr
index 8724c7e33b1..d612e0c35a1 100644
--- a/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr
+++ b/src/test/ui/const-generics/min_const_generics/transmute-const-param-static-reference.stderr
@@ -5,7 +5,7 @@ LL | struct Const<const P: &'static ()>;
    |                       ^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/nested-type.min.stderr b/src/test/ui/const-generics/nested-type.min.stderr
index dabb3f245f5..6defd393ba0 100644
--- a/src/test/ui/const-generics/nested-type.min.stderr
+++ b/src/test/ui/const-generics/nested-type.min.stderr
@@ -12,7 +12,7 @@ LL | | }]>;
    | |__^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
   --> $DIR/nested-type.rs:15:5
diff --git a/src/test/ui/const-generics/slice-const-param-mismatch.min.stderr b/src/test/ui/const-generics/slice-const-param-mismatch.min.stderr
index 13d0b217ed2..166a35ee455 100644
--- a/src/test/ui/const-generics/slice-const-param-mismatch.min.stderr
+++ b/src/test/ui/const-generics/slice-const-param-mismatch.min.stderr
@@ -5,7 +5,7 @@ LL | struct ConstString<const T: &'static str>;
    |                             ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `&'static [u8]` is forbidden as the type of a const generic parameter
   --> $DIR/slice-const-param-mismatch.rs:9:28
@@ -14,7 +14,7 @@ LL | struct ConstBytes<const T: &'static [u8]>;
    |                            ^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/slice-const-param.min.stderr b/src/test/ui/const-generics/slice-const-param.min.stderr
index 821c6e3995a..ed39a0c56b4 100644
--- a/src/test/ui/const-generics/slice-const-param.min.stderr
+++ b/src/test/ui/const-generics/slice-const-param.min.stderr
@@ -5,7 +5,7 @@ LL | pub fn function_with_str<const STRING: &'static str>() -> &'static str {
    |                                        ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `&'static [u8]` is forbidden as the type of a const generic parameter
   --> $DIR/slice-const-param.rs:12:41
@@ -14,7 +14,7 @@ LL | pub fn function_with_bytes<const BYTES: &'static [u8]>() -> &'static [u8] {
    |                                         ^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/std/const-generics-range.min.stderr b/src/test/ui/const-generics/std/const-generics-range.min.stderr
index d7d2a8447e9..86e6159fdb5 100644
--- a/src/test/ui/const-generics/std/const-generics-range.min.stderr
+++ b/src/test/ui/const-generics/std/const-generics-range.min.stderr
@@ -5,7 +5,7 @@ LL | struct _Range<const R: std::ops::Range<usize>>;
    |                        ^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `RangeFrom<usize>` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:12:28
@@ -14,7 +14,7 @@ LL | struct _RangeFrom<const R: std::ops::RangeFrom<usize>>;
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `RangeFull` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:17:28
@@ -23,7 +23,7 @@ LL | struct _RangeFull<const R: std::ops::RangeFull>;
    |                            ^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `RangeInclusive<usize>` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:23:33
@@ -32,7 +32,7 @@ LL | struct _RangeInclusive<const R: std::ops::RangeInclusive<usize>>;
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `RangeTo<usize>` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:28:26
@@ -41,7 +41,7 @@ LL | struct _RangeTo<const R: std::ops::RangeTo<usize>>;
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `RangeToInclusive<usize>` is forbidden as the type of a const generic parameter
   --> $DIR/const-generics-range.rs:33:35
@@ -50,7 +50,7 @@ LL | struct _RangeToInclusive<const R: std::ops::RangeToInclusive<usize>>;
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/const-generics/suggest_const_for_array.rs b/src/test/ui/const-generics/suggest_const_for_array.rs
new file mode 100644
index 00000000000..f3e5a3186cd
--- /dev/null
+++ b/src/test/ui/const-generics/suggest_const_for_array.rs
@@ -0,0 +1,10 @@
+#![crate_type = "lib"]
+
+fn example<const N: usize>() {}
+
+fn other() {
+  example::<[usize; 3]>();
+  //~^ ERROR type provided when a const
+  example::<[usize; 4+5]>();
+  //~^ ERROR type provided when a const
+}
diff --git a/src/test/ui/const-generics/suggest_const_for_array.stderr b/src/test/ui/const-generics/suggest_const_for_array.stderr
new file mode 100644
index 00000000000..a617bf2bb0d
--- /dev/null
+++ b/src/test/ui/const-generics/suggest_const_for_array.stderr
@@ -0,0 +1,15 @@
+error[E0747]: type provided when a constant was expected
+  --> $DIR/suggest_const_for_array.rs:6:13
+   |
+LL |   example::<[usize; 3]>();
+   |             ^^^^^^^^^^ help: array type provided where a `usize` was expected, try: `{ 3 }`
+
+error[E0747]: type provided when a constant was expected
+  --> $DIR/suggest_const_for_array.rs:8:13
+   |
+LL |   example::<[usize; 4+5]>();
+   |             ^^^^^^^^^^^^ help: array type provided where a `usize` was expected, try: `{ 4+5 }`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0747`.
diff --git a/src/test/ui/const-generics/type-dependent/issue-71348.min.stderr b/src/test/ui/const-generics/type-dependent/issue-71348.min.stderr
index 92f5d815a0f..f3516d1de96 100644
--- a/src/test/ui/const-generics/type-dependent/issue-71348.min.stderr
+++ b/src/test/ui/const-generics/type-dependent/issue-71348.min.stderr
@@ -5,7 +5,7 @@ LL | trait Get<'a, const N: &'static str> {
    |                        ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: `&'static str` is forbidden as the type of a const generic parameter
   --> $DIR/issue-71348.rs:18:25
@@ -14,7 +14,7 @@ LL |     fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Ta
    |                         ^^^^^^^^^^^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/consts/const-address-of-interior-mut.stderr b/src/test/ui/consts/const-address-of-interior-mut.stderr
index f15174c33b3..93120753b1a 100644
--- a/src/test/ui/consts/const-address-of-interior-mut.stderr
+++ b/src/test/ui/consts/const-address-of-interior-mut.stderr
@@ -1,27 +1,39 @@
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
   --> $DIR/const-address-of-interior-mut.rs:5:39
    |
 LL | const A: () = { let x = Cell::new(2); &raw const x; };
    |                                       ^^^^^^^^^^^^
+   |
+   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
 
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
   --> $DIR/const-address-of-interior-mut.rs:7:40
    |
 LL | static B: () = { let x = Cell::new(2); &raw const x; };
    |                                        ^^^^^^^^^^^^
+   |
+   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
 
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
   --> $DIR/const-address-of-interior-mut.rs:9:44
    |
 LL | static mut C: () = { let x = Cell::new(2); &raw const x; };
    |                                            ^^^^^^^^^^^^
+   |
+   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
 
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
   --> $DIR/const-address-of-interior-mut.rs:13:13
    |
 LL |     let y = &raw const x;
    |             ^^^^^^^^^^^^
+   |
+   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0492`.
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/const-multi-ref.rs b/src/test/ui/consts/const-multi-ref.rs
index 18645efc887..7e0f1a812fd 100644
--- a/src/test/ui/consts/const-multi-ref.rs
+++ b/src/test/ui/consts/const-multi-ref.rs
@@ -13,7 +13,7 @@ const _: i32 = {
 
 const _: std::cell::Cell<i32> = {
     let mut a = std::cell::Cell::new(5);
-    let p = &a; //~ ERROR cannot borrow a constant which may contain interior mutability
+    let p = &a; //~ ERROR borrowed element may contain interior mutability
 
     let reborrow = {p};
     let pp = &reborrow;
diff --git a/src/test/ui/consts/const-multi-ref.stderr b/src/test/ui/consts/const-multi-ref.stderr
index 9a7914b4588..c0a320d46cb 100644
--- a/src/test/ui/consts/const-multi-ref.stderr
+++ b/src/test/ui/consts/const-multi-ref.stderr
@@ -4,13 +4,16 @@ error[E0764]: mutable references are not allowed in constants
 LL |     let p = &mut a;
    |             ^^^^^^ `&mut` is only allowed in `const fn`
 
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
   --> $DIR/const-multi-ref.rs:16:13
    |
 LL |     let p = &a;
    |             ^^
+   |
+   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0492, E0764.
-For more information about an error, try `rustc --explain E0492`.
+Some errors have detailed explanations: E0658, E0764.
+For more information about an error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/partial_qualif.rs b/src/test/ui/consts/partial_qualif.rs
index 32c68e69f4b..7c28b8b8a62 100644
--- a/src/test/ui/consts/partial_qualif.rs
+++ b/src/test/ui/consts/partial_qualif.rs
@@ -3,7 +3,7 @@ use std::cell::Cell;
 const FOO: &(Cell<usize>, bool) = {
     let mut a = (Cell::new(0), false);
     a.1 = true; // sets `qualif(a)` to `qualif(a) | qualif(true)`
-    &{a} //~ ERROR cannot borrow a constant which may contain interior mutability
+    &{a} //~ ERROR cannot refer to interior mutable
 };
 
 fn main() {}
diff --git a/src/test/ui/consts/partial_qualif.stderr b/src/test/ui/consts/partial_qualif.stderr
index 221e449b6f9..32c25be2173 100644
--- a/src/test/ui/consts/partial_qualif.stderr
+++ b/src/test/ui/consts/partial_qualif.stderr
@@ -1,8 +1,8 @@
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0492]: constants cannot refer to interior mutable data
   --> $DIR/partial_qualif.rs:6:5
    |
 LL |     &{a}
-   |     ^^^^
+   |     ^^^^ this borrow of an interior mutable value may end up in the final value
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/promotion.rs b/src/test/ui/consts/promotion.rs
index e6f5c3d27ca..b6e7127a9b7 100644
--- a/src/test/ui/consts/promotion.rs
+++ b/src/test/ui/consts/promotion.rs
@@ -4,12 +4,23 @@
 
 fn foo(_: &'static [&'static str]) {}
 fn bar(_: &'static [&'static str; 3]) {}
-fn baz_i32(_: &'static i32) {}
-fn baz_u32(_: &'static u32) {}
+const fn baz_i32(_: &'static i32) {}
+const fn baz_u32(_: &'static u32) {}
+
+const fn fail() -> i32 { 1/0 }
+const C: i32 = {
+    // Promoted that fails to evaluate in dead code -- this must work
+    // (for backwards compatibility reasons).
+    if false {
+        baz_i32(&fail());
+    }
+    42
+};
 
 fn main() {
     foo(&["a", "b", "c"]);
     bar(&["d", "e", "f"]);
+    assert_eq!(C, 42);
 
     // make sure that these do not cause trouble despite overflowing
     baz_u32(&(0-1));
diff --git a/src/test/ui/consts/qualif_overwrite.rs b/src/test/ui/consts/qualif_overwrite.rs
index 430eea37de7..aae4e41ffd7 100644
--- a/src/test/ui/consts/qualif_overwrite.rs
+++ b/src/test/ui/consts/qualif_overwrite.rs
@@ -7,7 +7,7 @@ use std::cell::Cell;
 const FOO: &Option<Cell<usize>> = {
     let mut a = Some(Cell::new(0));
     a = None; // sets `qualif(a)` to `qualif(a) | qualif(None)`
-    &{a} //~ ERROR cannot borrow a constant which may contain interior mutability
+    &{a} //~ ERROR cannot refer to interior mutable
 };
 
 fn main() {}
diff --git a/src/test/ui/consts/qualif_overwrite.stderr b/src/test/ui/consts/qualif_overwrite.stderr
index fbaae711d7c..86a669c433d 100644
--- a/src/test/ui/consts/qualif_overwrite.stderr
+++ b/src/test/ui/consts/qualif_overwrite.stderr
@@ -1,8 +1,8 @@
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0492]: constants cannot refer to interior mutable data
   --> $DIR/qualif_overwrite.rs:10:5
    |
 LL |     &{a}
-   |     ^^^^
+   |     ^^^^ this borrow of an interior mutable value may end up in the final value
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/qualif_overwrite_2.rs b/src/test/ui/consts/qualif_overwrite_2.rs
index fa79b5c14a7..1819d9a6d20 100644
--- a/src/test/ui/consts/qualif_overwrite_2.rs
+++ b/src/test/ui/consts/qualif_overwrite_2.rs
@@ -5,7 +5,7 @@ use std::cell::Cell;
 const FOO: &Option<Cell<usize>> = {
     let mut a = (Some(Cell::new(0)),);
     a.0 = None; // sets `qualif(a)` to `qualif(a) | qualif(None)`
-    &{a.0} //~ ERROR cannot borrow a constant which may contain interior mutability
+    &{a.0} //~ ERROR cannot refer to interior mutable
 };
 
 fn main() {}
diff --git a/src/test/ui/consts/qualif_overwrite_2.stderr b/src/test/ui/consts/qualif_overwrite_2.stderr
index a393c4e336d..9eb123d0b01 100644
--- a/src/test/ui/consts/qualif_overwrite_2.stderr
+++ b/src/test/ui/consts/qualif_overwrite_2.stderr
@@ -1,8 +1,8 @@
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0492]: constants cannot refer to interior mutable data
   --> $DIR/qualif_overwrite_2.rs:8:5
    |
 LL |     &{a.0}
-   |     ^^^^^^
+   |     ^^^^^^ this borrow of an interior mutable value may end up in the final value
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/std/cell.rs b/src/test/ui/consts/std/cell.rs
index cf6c0f2379d..f1ef541319a 100644
--- a/src/test/ui/consts/std/cell.rs
+++ b/src/test/ui/consts/std/cell.rs
@@ -1,18 +1,31 @@
+#![feature(const_refs_to_cell)]
+
 use std::cell::*;
 
-// not ok, because this would create a silent constant with interior mutability.
-// the rules could be relaxed in the future
+// not ok, because this creates a dangling pointer, just like `let x = Cell::new(42).as_ptr()` would
 static FOO: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr());
-//~^ ERROR cannot borrow a constant which may contain interior mutability
+//~^ ERROR encountered dangling pointer
+const FOO_CONST: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr());
+//~^ ERROR encountered dangling pointer
 
+// Ok, these are just base values and it is the `Wrap` author's job to uphold `Send` and `Sync`
+// invariants, since they used `unsafe impl`.
 static FOO3: Wrap<Cell<u32>> = Wrap(Cell::new(42));
-// ok
+const FOO3_CONST: Wrap<Cell<u32>> = Wrap(Cell::new(42));
+
+// ok, we are referring to the memory of another static item.
 static FOO4: Wrap<*mut u32> = Wrap(FOO3.0.as_ptr());
 
-// not ok, because the `as_ptr` call takes a reference to a type with interior mutability
-// which is not allowed in constants
+// not ok, the use of a constant here is equivalent to an inline declaration of the value, so
+// its memory will get freed before the constant is finished evaluating, thus creating a dangling
+// pointer. This would happen exactly the same at runtime.
+const FOO4_CONST: Wrap<*mut u32> = Wrap(FOO3_CONST.0.as_ptr());
+//~^ ERROR encountered dangling pointer
+
+// not ok, because the `as_ptr` call takes a reference to a temporary that will get freed
+// before the constant is finished evaluating.
 const FOO2: *mut u32 = Cell::new(42).as_ptr();
-//~^ ERROR cannot borrow a constant which may contain interior mutability
+//~^ ERROR encountered dangling pointer
 
 struct IMSafeTrustMe(UnsafeCell<u32>);
 unsafe impl Send for IMSafeTrustMe {}
@@ -21,10 +34,13 @@ unsafe impl Sync for IMSafeTrustMe {}
 static BAR: IMSafeTrustMe = IMSafeTrustMe(UnsafeCell::new(5));
 
 
+
 struct Wrap<T>(T);
 unsafe impl<T> Send for Wrap<T> {}
 unsafe impl<T> Sync for Wrap<T> {}
 
 static BAR_PTR: Wrap<*mut u32> = Wrap(BAR.0.get());
 
+const fn fst_ref<T, U>(x: &(T, U)) -> &T { &x.0 }
+
 fn main() {}
diff --git a/src/test/ui/consts/std/cell.stderr b/src/test/ui/consts/std/cell.stderr
index f75aadff6d5..355c326f0b6 100644
--- a/src/test/ui/consts/std/cell.stderr
+++ b/src/test/ui/consts/std/cell.stderr
@@ -1,15 +1,26 @@
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
-  --> $DIR/cell.rs:5:35
+error: encountered dangling pointer in final constant
+  --> $DIR/cell.rs:6:1
    |
 LL | static FOO: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr());
-   |                                   ^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
-  --> $DIR/cell.rs:14:24
+error: encountered dangling pointer in final constant
+  --> $DIR/cell.rs:8:1
+   |
+LL | const FOO_CONST: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr());
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: encountered dangling pointer in final constant
+  --> $DIR/cell.rs:22:1
+   |
+LL | const FOO4_CONST: Wrap<*mut u32> = Wrap(FOO3_CONST.0.as_ptr());
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: encountered dangling pointer in final constant
+  --> $DIR/cell.rs:27:1
    |
 LL | const FOO2: *mut u32 = Cell::new(42).as_ptr();
-   |                        ^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0492`.
diff --git a/src/test/ui/doc-alias-crate-level.rs b/src/test/ui/doc-alias-crate-level.rs
index 9b596ece5b5..c7783aae5ea 100644
--- a/src/test/ui/doc-alias-crate-level.rs
+++ b/src/test/ui/doc-alias-crate-level.rs
@@ -1,7 +1,5 @@
 // compile-flags: -Zdeduplicate-diagnostics=no
 
-#![feature(doc_alias)]
-
 #![crate_type = "lib"]
 
 #![doc(alias = "not working!")] //~ ERROR
diff --git a/src/test/ui/doc-alias-crate-level.stderr b/src/test/ui/doc-alias-crate-level.stderr
index b6437fad5d0..c0467514ae1 100644
--- a/src/test/ui/doc-alias-crate-level.stderr
+++ b/src/test/ui/doc-alias-crate-level.stderr
@@ -1,11 +1,11 @@
 error: '\'' character isn't allowed in `#[doc(alias = "...")]`
-  --> $DIR/doc-alias-crate-level.rs:9:15
+  --> $DIR/doc-alias-crate-level.rs:7:15
    |
 LL | #[doc(alias = "shouldn't work!")]
    |               ^^^^^^^^^^^^^^^^^
 
 error: `#![doc(alias = "...")]` isn't allowed as a crate level attribute
-  --> $DIR/doc-alias-crate-level.rs:7:8
+  --> $DIR/doc-alias-crate-level.rs:5:8
    |
 LL | #![doc(alias = "not working!")]
    |        ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/doc-alias-same-name.rs b/src/test/ui/doc-alias-same-name.rs
new file mode 100644
index 00000000000..da97c267618
--- /dev/null
+++ b/src/test/ui/doc-alias-same-name.rs
@@ -0,0 +1,4 @@
+#![crate_type = "lib"]
+
+#[doc(alias = "Foo")] //~ ERROR
+pub struct Foo;
diff --git a/src/test/ui/doc-alias-same-name.stderr b/src/test/ui/doc-alias-same-name.stderr
new file mode 100644
index 00000000000..5ba09a2eae1
--- /dev/null
+++ b/src/test/ui/doc-alias-same-name.stderr
@@ -0,0 +1,8 @@
+error: `#[doc(alias = "...")]` is the same as the item's name
+  --> $DIR/doc-alias-same-name.rs:3:7
+   |
+LL | #[doc(alias = "Foo")]
+   |       ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/error-codes/E0435.fixed b/src/test/ui/error-codes/E0435.fixed
new file mode 100644
index 00000000000..fdf896d2dbb
--- /dev/null
+++ b/src/test/ui/error-codes/E0435.fixed
@@ -0,0 +1,6 @@
+// run-rustfix
+fn main () {
+    #[allow(non_upper_case_globals)]
+    const foo: usize = 42;
+    let _: [u8; foo]; //~ ERROR E0435
+}
diff --git a/src/test/ui/error-codes/E0435.rs b/src/test/ui/error-codes/E0435.rs
index 620dd30a23b..d9354efb8fd 100644
--- a/src/test/ui/error-codes/E0435.rs
+++ b/src/test/ui/error-codes/E0435.rs
@@ -1,4 +1,6 @@
+// run-rustfix
 fn main () {
-    let foo = 42u32;
+    #[allow(non_upper_case_globals)]
+    let foo: usize = 42;
     let _: [u8; foo]; //~ ERROR E0435
 }
diff --git a/src/test/ui/error-codes/E0435.stderr b/src/test/ui/error-codes/E0435.stderr
index 349aa0d07c5..fc08fade91c 100644
--- a/src/test/ui/error-codes/E0435.stderr
+++ b/src/test/ui/error-codes/E0435.stderr
@@ -1,6 +1,8 @@
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/E0435.rs:3:17
+  --> $DIR/E0435.rs:5:17
    |
+LL |     let foo: usize = 42;
+   |     ------- help: consider using `const` instead of `let`: `const foo`
 LL |     let _: [u8; foo];
    |                 ^^^ non-constant value
 
diff --git a/src/test/ui/error-codes/E0492.rs b/src/test/ui/error-codes/E0492.rs
index 2de4c12eb64..2c735fcc9f9 100644
--- a/src/test/ui/error-codes/E0492.rs
+++ b/src/test/ui/error-codes/E0492.rs
@@ -1,7 +1,10 @@
 use std::sync::atomic::AtomicUsize;
 
 const A: AtomicUsize = AtomicUsize::new(0);
-static B: &'static AtomicUsize = &A; //~ ERROR E0492
+const B: &'static AtomicUsize = &A; //~ ERROR E0492
+static C: &'static AtomicUsize = &A; //~ ERROR E0492
+
+const NONE: &'static Option<AtomicUsize> = &None;
 
 fn main() {
 }
diff --git a/src/test/ui/error-codes/E0492.stderr b/src/test/ui/error-codes/E0492.stderr
index 5f337dd7f42..557c977e87d 100644
--- a/src/test/ui/error-codes/E0492.stderr
+++ b/src/test/ui/error-codes/E0492.stderr
@@ -1,9 +1,17 @@
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
-  --> $DIR/E0492.rs:4:34
+error[E0492]: constants cannot refer to interior mutable data
+  --> $DIR/E0492.rs:4:33
    |
-LL | static B: &'static AtomicUsize = &A;
-   |                                  ^^
+LL | const B: &'static AtomicUsize = &A;
+   |                                 ^^ this borrow of an interior mutable value may end up in the final value
 
-error: aborting due to previous error
+error[E0492]: statics cannot refer to interior mutable data
+  --> $DIR/E0492.rs:5:34
+   |
+LL | static C: &'static AtomicUsize = &A;
+   |                                  ^^ this borrow of an interior mutable value may end up in the final value
+   |
+   = help: to fix this, the value can be extracted to a separate `static` item and then referenced
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0492`.
diff --git a/src/test/ui/feature-gate/feature-gate-const_refs_to_cell.rs b/src/test/ui/feature-gate/feature-gate-const_refs_to_cell.rs
new file mode 100644
index 00000000000..63159ed0553
--- /dev/null
+++ b/src/test/ui/feature-gate/feature-gate-const_refs_to_cell.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![feature(const_refs_to_cell)]
+
+const FOO: () = {
+    let x = std::cell::Cell::new(42);
+    let y = &x;
+};
+
+fn main() {
+    FOO;
+}
diff --git a/src/test/ui/feature-gates/feature-gate-const_generics.stderr b/src/test/ui/feature-gates/feature-gate-const_generics.stderr
index b2b7e4576bf..ed19109b38b 100644
--- a/src/test/ui/feature-gates/feature-gate-const_generics.stderr
+++ b/src/test/ui/feature-gates/feature-gate-const_generics.stderr
@@ -5,7 +5,7 @@ LL | fn foo<const X: ()>() {}
    |                 ^^
    |
    = note: the only supported types are integers, `bool` and `char`
-   = help: more complex types are supported with `#[feature(const_generics)]`
+   = help: more complex types are supported with `#![feature(const_generics)]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
index ef9c9ef48a8..128795f50f9 100644
--- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
@@ -173,12 +173,6 @@ LL |     #[deny(x5100)] impl S { }
    |            ^^^^^
 
 warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:438:1
-   |
-LL | #[macro_escape]
-   | ^^^^^^^^^^^^^^^
-
-warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:441:17
    |
 LL |     mod inner { #![macro_escape] }
@@ -186,6 +180,12 @@ LL |     mod inner { #![macro_escape] }
    |
    = help: try an outer attribute: `#[macro_use]`
 
+warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:438:1
+   |
+LL | #[macro_escape]
+   | ^^^^^^^^^^^^^^^
+
 warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:228:17
    |
diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-macro_use.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-macro_use.stderr
index 52a682e4bfa..7f6d608038f 100644
--- a/src/test/ui/feature-gates/issue-43106-gating-of-macro_use.stderr
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-macro_use.stderr
@@ -1,8 +1,8 @@
 error: arguments to `macro_use` are not allowed here
-  --> $DIR/issue-43106-gating-of-macro_use.rs:6:1
+  --> $DIR/issue-43106-gating-of-macro_use.rs:12:17
    |
-LL | #![macro_use(my_macro)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
+LL |     mod inner { #![macro_use(my_macro)] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: arguments to `macro_use` are not allowed here
   --> $DIR/issue-43106-gating-of-macro_use.rs:9:1
@@ -11,10 +11,10 @@ LL | #[macro_use(my_macro)]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 error: arguments to `macro_use` are not allowed here
-  --> $DIR/issue-43106-gating-of-macro_use.rs:12:17
+  --> $DIR/issue-43106-gating-of-macro_use.rs:6:1
    |
-LL |     mod inner { #![macro_use(my_macro)] }
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![macro_use(my_macro)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: malformed `macro_use` attribute input
   --> $DIR/issue-43106-gating-of-macro_use.rs:15:5
diff --git a/src/test/ui/impl-trait/bindings.stderr b/src/test/ui/impl-trait/bindings.stderr
index e983fdecdba..4da49f4dc7d 100644
--- a/src/test/ui/impl-trait/bindings.stderr
+++ b/src/test/ui/impl-trait/bindings.stderr
@@ -2,25 +2,33 @@ error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/bindings.rs:5:29
    |
 LL |     const foo: impl Clone = x;
-   |                             ^ non-constant value
+   |     ---------               ^ non-constant value
+   |     |
+   |     help: consider using `let` instead of `const`: `let foo`
 
 error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/bindings.rs:11:33
    |
 LL |         const foo: impl Clone = x;
-   |                                 ^ non-constant value
+   |         ---------               ^ non-constant value
+   |         |
+   |         help: consider using `let` instead of `const`: `let foo`
 
 error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/bindings.rs:18:33
    |
 LL |         const foo: impl Clone = x;
-   |                                 ^ non-constant value
+   |         ---------               ^ non-constant value
+   |         |
+   |         help: consider using `let` instead of `const`: `let foo`
 
 error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/bindings.rs:25:33
    |
 LL |         const foo: impl Clone = x;
-   |                                 ^ non-constant value
+   |         ---------               ^ non-constant value
+   |         |
+   |         help: consider using `let` instead of `const`: `let foo`
 
 warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/bindings.rs:1:12
diff --git a/src/test/ui/issues/issue-17718-const-borrow.rs b/src/test/ui/issues/issue-17718-const-borrow.rs
index 8a31bd0c66a..89316dbd5c4 100644
--- a/src/test/ui/issues/issue-17718-const-borrow.rs
+++ b/src/test/ui/issues/issue-17718-const-borrow.rs
@@ -2,13 +2,13 @@ use std::cell::UnsafeCell;
 
 const A: UnsafeCell<usize> = UnsafeCell::new(1);
 const B: &'static UnsafeCell<usize> = &A;
-//~^ ERROR: cannot borrow a constant which may contain interior mutability
+//~^ ERROR: cannot refer to interior mutable
 
 struct C { a: UnsafeCell<usize> }
 const D: C = C { a: UnsafeCell::new(1) };
 const E: &'static UnsafeCell<usize> = &D.a;
-//~^ ERROR: cannot borrow a constant which may contain interior mutability
+//~^ ERROR: cannot refer to interior mutable
 const F: &'static C = &D;
-//~^ ERROR: cannot borrow a constant which may contain interior mutability
+//~^ ERROR: cannot refer to interior mutable
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-17718-const-borrow.stderr b/src/test/ui/issues/issue-17718-const-borrow.stderr
index b4330049689..e3ff6c923ad 100644
--- a/src/test/ui/issues/issue-17718-const-borrow.stderr
+++ b/src/test/ui/issues/issue-17718-const-borrow.stderr
@@ -1,20 +1,20 @@
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0492]: constants cannot refer to interior mutable data
   --> $DIR/issue-17718-const-borrow.rs:4:39
    |
 LL | const B: &'static UnsafeCell<usize> = &A;
-   |                                       ^^
+   |                                       ^^ this borrow of an interior mutable value may end up in the final value
 
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0492]: constants cannot refer to interior mutable data
   --> $DIR/issue-17718-const-borrow.rs:9:39
    |
 LL | const E: &'static UnsafeCell<usize> = &D.a;
-   |                                       ^^^^
+   |                                       ^^^^ this borrow of an interior mutable value may end up in the final value
 
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0492]: constants cannot refer to interior mutable data
   --> $DIR/issue-17718-const-borrow.rs:11:23
    |
 LL | const F: &'static C = &D;
-   |                       ^^
+   |                       ^^ this borrow of an interior mutable value may end up in the final value
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issues/issue-27433.fixed b/src/test/ui/issues/issue-27433.fixed
new file mode 100644
index 00000000000..ce31f6bea4b
--- /dev/null
+++ b/src/test/ui/issues/issue-27433.fixed
@@ -0,0 +1,7 @@
+// run-rustfix
+fn main() {
+    let foo = 42u32;
+    #[allow(unused_variables, non_snake_case)]
+    let FOO : u32 = foo;
+                   //~^ ERROR attempt to use a non-constant value in a constant
+}
diff --git a/src/test/ui/issues/issue-27433.rs b/src/test/ui/issues/issue-27433.rs
index 156ae68efe2..01411a51c13 100644
--- a/src/test/ui/issues/issue-27433.rs
+++ b/src/test/ui/issues/issue-27433.rs
@@ -1,5 +1,7 @@
+// run-rustfix
 fn main() {
     let foo = 42u32;
+    #[allow(unused_variables, non_snake_case)]
     const FOO : u32 = foo;
                    //~^ ERROR attempt to use a non-constant value in a constant
 }
diff --git a/src/test/ui/issues/issue-27433.stderr b/src/test/ui/issues/issue-27433.stderr
index e232d17e6d7..da751a64957 100644
--- a/src/test/ui/issues/issue-27433.stderr
+++ b/src/test/ui/issues/issue-27433.stderr
@@ -1,8 +1,10 @@
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/issue-27433.rs:3:23
+  --> $DIR/issue-27433.rs:5:23
    |
 LL |     const FOO : u32 = foo;
-   |                       ^^^ non-constant value
+   |     ---------         ^^^ non-constant value
+   |     |
+   |     help: consider using `let` instead of `const`: `let FOO`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-34721.stderr b/src/test/ui/issues/issue-34721.stderr
index b4cc1a0aa7e..b14faff8f7b 100644
--- a/src/test/ui/issues/issue-34721.stderr
+++ b/src/test/ui/issues/issue-34721.stderr
@@ -13,7 +13,7 @@ LL |         };
 LL |         x.zero()
    |         ^ value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
+note: this function takes ownership of the receiver `self`, which moves `x`
   --> $DIR/issue-34721.rs:4:13
    |
 LL |     fn zero(self) -> Self;
diff --git a/src/test/ui/issues/issue-3521-2.fixed b/src/test/ui/issues/issue-3521-2.fixed
new file mode 100644
index 00000000000..140c24b9395
--- /dev/null
+++ b/src/test/ui/issues/issue-3521-2.fixed
@@ -0,0 +1,9 @@
+// run-rustfix
+fn main() {
+    let foo = 100;
+
+    let y: isize = foo + 1;
+    //~^ ERROR attempt to use a non-constant value in a constant
+
+    println!("{}", y);
+}
diff --git a/src/test/ui/issues/issue-3521-2.rs b/src/test/ui/issues/issue-3521-2.rs
index 871394f9eae..f66efec45e5 100644
--- a/src/test/ui/issues/issue-3521-2.rs
+++ b/src/test/ui/issues/issue-3521-2.rs
@@ -1,3 +1,4 @@
+// run-rustfix
 fn main() {
     let foo = 100;
 
diff --git a/src/test/ui/issues/issue-3521-2.stderr b/src/test/ui/issues/issue-3521-2.stderr
index d54bbbcdc33..84c7a9efa35 100644
--- a/src/test/ui/issues/issue-3521-2.stderr
+++ b/src/test/ui/issues/issue-3521-2.stderr
@@ -1,8 +1,10 @@
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/issue-3521-2.rs:4:23
+  --> $DIR/issue-3521-2.rs:5:23
    |
 LL |     static y: isize = foo + 1;
-   |                       ^^^ non-constant value
+   |     --------          ^^^ non-constant value
+   |     |
+   |     help: consider using `let` instead of `static`: `let y`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-3521.fixed b/src/test/ui/issues/issue-3521.fixed
new file mode 100644
index 00000000000..f76106dfff1
--- /dev/null
+++ b/src/test/ui/issues/issue-3521.fixed
@@ -0,0 +1,13 @@
+// run-rustfix
+fn main() {
+    #[allow(non_upper_case_globals)]
+    const foo: isize = 100;
+
+    #[derive(Debug)]
+    enum Stuff {
+        Bar = foo
+        //~^ ERROR attempt to use a non-constant value in a constant
+    }
+
+    println!("{:?}", Stuff::Bar);
+}
diff --git a/src/test/ui/issues/issue-3521.rs b/src/test/ui/issues/issue-3521.rs
index 9e72dd29a40..c425a22df91 100644
--- a/src/test/ui/issues/issue-3521.rs
+++ b/src/test/ui/issues/issue-3521.rs
@@ -1,5 +1,7 @@
+// run-rustfix
 fn main() {
-    let foo = 100;
+    #[allow(non_upper_case_globals)]
+    let foo: isize = 100;
 
     #[derive(Debug)]
     enum Stuff {
diff --git a/src/test/ui/issues/issue-3521.stderr b/src/test/ui/issues/issue-3521.stderr
index ae199875269..aa42772f12d 100644
--- a/src/test/ui/issues/issue-3521.stderr
+++ b/src/test/ui/issues/issue-3521.stderr
@@ -1,6 +1,9 @@
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/issue-3521.rs:6:15
+  --> $DIR/issue-3521.rs:8:15
    |
+LL |     let foo: isize = 100;
+   |     ------- help: consider using `const` instead of `let`: `const foo`
+...
 LL |         Bar = foo
    |               ^^^ non-constant value
 
diff --git a/src/test/ui/issues/issue-3668-2.fixed b/src/test/ui/issues/issue-3668-2.fixed
new file mode 100644
index 00000000000..a95781c6edc
--- /dev/null
+++ b/src/test/ui/issues/issue-3668-2.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+#![allow(unused_variables, dead_code)]
+fn f(x:isize) {
+    let child: isize = x + 1;
+    //~^ ERROR attempt to use a non-constant value in a constant
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-3668-2.rs b/src/test/ui/issues/issue-3668-2.rs
index 525f6f5684e..8aa0897ecb4 100644
--- a/src/test/ui/issues/issue-3668-2.rs
+++ b/src/test/ui/issues/issue-3668-2.rs
@@ -1,3 +1,5 @@
+// run-rustfix
+#![allow(unused_variables, dead_code)]
 fn f(x:isize) {
     static child: isize = x + 1;
     //~^ ERROR attempt to use a non-constant value in a constant
diff --git a/src/test/ui/issues/issue-3668-2.stderr b/src/test/ui/issues/issue-3668-2.stderr
index d6a6e837960..ba965104154 100644
--- a/src/test/ui/issues/issue-3668-2.stderr
+++ b/src/test/ui/issues/issue-3668-2.stderr
@@ -1,8 +1,10 @@
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/issue-3668-2.rs:2:27
+  --> $DIR/issue-3668-2.rs:4:27
    |
 LL |     static child: isize = x + 1;
-   |                           ^ non-constant value
+   |     ------------          ^ non-constant value
+   |     |
+   |     help: consider using `let` instead of `static`: `let child`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-3668.stderr b/src/test/ui/issues/issue-3668.stderr
index 98cd3631a53..edc49979c10 100644
--- a/src/test/ui/issues/issue-3668.stderr
+++ b/src/test/ui/issues/issue-3668.stderr
@@ -2,7 +2,9 @@ error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/issue-3668.rs:8:34
    |
 LL |        static childVal: Box<P> = self.child.get();
-   |                                  ^^^^ non-constant value
+   |        ---------------           ^^^^ non-constant value
+   |        |
+   |        help: consider using `let` instead of `static`: `let childVal`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-42060.stderr b/src/test/ui/issues/issue-42060.stderr
index 72408c79194..effcbe4d7f3 100644
--- a/src/test/ui/issues/issue-42060.stderr
+++ b/src/test/ui/issues/issue-42060.stderr
@@ -1,12 +1,16 @@
 error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/issue-42060.rs:3:23
    |
+LL |     let thing = ();
+   |     --------- help: consider using `const` instead of `let`: `const thing`
 LL |     let other: typeof(thing) = thing;
    |                       ^^^^^ non-constant value
 
 error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/issue-42060.rs:9:13
    |
+LL |     let q = 1;
+   |     ----- help: consider using `const` instead of `let`: `const q`
 LL |     <typeof(q)>::N
    |             ^ non-constant value
 
diff --git a/src/test/ui/issues/issue-44239.fixed b/src/test/ui/issues/issue-44239.fixed
new file mode 100644
index 00000000000..e6c29cee97d
--- /dev/null
+++ b/src/test/ui/issues/issue-44239.fixed
@@ -0,0 +1,11 @@
+// run-rustfix
+#![allow(dead_code, non_upper_case_globals)]
+fn main() {
+    const n: usize = 0;
+
+    struct Foo;
+    impl Foo {
+        const N: usize = n;
+        //~^ ERROR attempt to use a non-constant value
+    }
+}
diff --git a/src/test/ui/issues/issue-44239.rs b/src/test/ui/issues/issue-44239.rs
index 99a865f75a4..482ed194c7a 100644
--- a/src/test/ui/issues/issue-44239.rs
+++ b/src/test/ui/issues/issue-44239.rs
@@ -1,5 +1,7 @@
+// run-rustfix
+#![allow(dead_code, non_upper_case_globals)]
 fn main() {
-    let n = 0;
+    let n: usize = 0;
 
     struct Foo;
     impl Foo {
diff --git a/src/test/ui/issues/issue-44239.stderr b/src/test/ui/issues/issue-44239.stderr
index bc5a6a03f03..2a245c92c48 100644
--- a/src/test/ui/issues/issue-44239.stderr
+++ b/src/test/ui/issues/issue-44239.stderr
@@ -1,6 +1,9 @@
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/issue-44239.rs:6:26
+  --> $DIR/issue-44239.rs:8:26
    |
+LL |     let n: usize = 0;
+   |     ----- help: consider using `const` instead of `let`: `const n`
+...
 LL |         const N: usize = n;
    |                          ^ non-constant value
 
diff --git a/src/test/ui/issues/issue-61108.stderr b/src/test/ui/issues/issue-61108.stderr
index d6c289cbd66..fb242f738c8 100644
--- a/src/test/ui/issues/issue-61108.stderr
+++ b/src/test/ui/issues/issue-61108.stderr
@@ -12,7 +12,7 @@ LL |     for l in 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`
+note: this function takes ownership of the receiver `self`, which moves `bad_letters`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    |
 LL |     fn into_iter(self) -> Self::IntoIter;
diff --git a/src/test/ui/issues/issue-64559.stderr b/src/test/ui/issues/issue-64559.stderr
index 5b97e21b888..e0da3fd5195 100644
--- a/src/test/ui/issues/issue-64559.stderr
+++ b/src/test/ui/issues/issue-64559.stderr
@@ -13,7 +13,7 @@ LL |     let _closure = || orig;
    |                    |
    |                    value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `orig`
+note: this function takes ownership of the receiver `self`, which moves `orig`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    |
 LL |     fn into_iter(self) -> Self::IntoIter;
diff --git a/src/test/ui/issues/issue-80607.rs b/src/test/ui/issues/issue-80607.rs
new file mode 100644
index 00000000000..63f4df359b8
--- /dev/null
+++ b/src/test/ui/issues/issue-80607.rs
@@ -0,0 +1,10 @@
+// This tests makes sure the diagnostics print the offending enum variant, not just the type.
+pub enum Enum {
+    V1(i32),
+}
+
+pub fn foo(x: i32) -> Enum {
+    Enum::V1 { x } //~ ERROR `Enum::V1` has no field named `x`
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-80607.stderr b/src/test/ui/issues/issue-80607.stderr
new file mode 100644
index 00000000000..5375478942b
--- /dev/null
+++ b/src/test/ui/issues/issue-80607.stderr
@@ -0,0 +1,14 @@
+error[E0559]: variant `Enum::V1` has no field named `x`
+  --> $DIR/issue-80607.rs:7:16
+   |
+LL |     V1(i32),
+   |     -- `Enum::V1` defined here
+...
+LL |     Enum::V1 { x }
+   |     --------   ^ field does not exist
+   |     |
+   |     `Enum::V1` is a tuple variant, use the appropriate syntax: `Enum::V1(/* fields */)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0559`.
diff --git a/src/test/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.rs b/src/test/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.rs
new file mode 100644
index 00000000000..8cc4f976a4b
--- /dev/null
+++ b/src/test/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.rs
@@ -0,0 +1,19 @@
+#![warn(unused)]
+#![allow(dead_code)]
+#![deny(non_snake_case)]
+
+mod Impl {}
+//~^ ERROR module `Impl` should have a snake case name
+
+fn While() {}
+//~^ ERROR function `While` should have a snake case name
+
+fn main() {
+    let Mod: usize = 0;
+    //~^ ERROR variable `Mod` should have a snake case name
+    //~^^ WARN unused variable: `Mod`
+
+    let Super: usize = 0;
+    //~^ ERROR variable `Super` should have a snake case name
+    //~^^ WARN unused variable: `Super`
+}
diff --git a/src/test/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.stderr b/src/test/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.stderr
new file mode 100644
index 00000000000..c179f4a25bd
--- /dev/null
+++ b/src/test/ui/lint/lint-non-snake-case-identifiers-suggestion-reserved.stderr
@@ -0,0 +1,67 @@
+warning: unused variable: `Mod`
+  --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:12:9
+   |
+LL |     let Mod: usize = 0;
+   |         ^^^ help: if this is intentional, prefix it with an underscore: `_Mod`
+   |
+note: the lint level is defined here
+  --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:1:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
+
+warning: unused variable: `Super`
+  --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:16:9
+   |
+LL |     let Super: usize = 0;
+   |         ^^^^^ help: if this is intentional, prefix it with an underscore: `_Super`
+
+error: module `Impl` should have a snake case name
+  --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:5:5
+   |
+LL | mod Impl {}
+   |     ^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:3:9
+   |
+LL | #![deny(non_snake_case)]
+   |         ^^^^^^^^^^^^^^
+help: rename the identifier or convert it to a snake case raw identifier
+   |
+LL | mod r#impl {}
+   |     ^^^^^^
+
+error: function `While` should have a snake case name
+  --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:8:4
+   |
+LL | fn While() {}
+   |    ^^^^^
+   |
+help: rename the identifier or convert it to a snake case raw identifier
+   |
+LL | fn r#while() {}
+   |    ^^^^^^^
+
+error: variable `Mod` should have a snake case name
+  --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:12:9
+   |
+LL |     let Mod: usize = 0;
+   |         ^^^
+   |
+help: rename the identifier or convert it to a snake case raw identifier
+   |
+LL |     let r#mod: usize = 0;
+   |         ^^^^^
+
+error: variable `Super` should have a snake case name
+  --> $DIR/lint-non-snake-case-identifiers-suggestion-reserved.rs:16:9
+   |
+LL |     let Super: usize = 0;
+   |         ^^^^^ help: rename the identifier
+   |
+   = note: `super` cannot be used as a raw identifier
+
+error: aborting due to 4 previous errors; 2 warnings emitted
+
diff --git a/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.rs b/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.rs
new file mode 100644
index 00000000000..2437155d981
--- /dev/null
+++ b/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.rs
@@ -0,0 +1,21 @@
+// Ensures -Zmir-opt-level=2 (specifically, inlining) is not allowed with -Zinstrument-coverage.
+// Regression test for issue #80060.
+//
+// needs-profiler-support
+// build-pass
+// compile-flags: -Zmir-opt-level=2 -Zinstrument-coverage
+#[inline(never)]
+fn foo() {}
+
+pub fn baz() {
+    bar();
+}
+
+#[inline(always)]
+fn bar() {
+    foo();
+}
+
+fn main() {
+    bar();
+}
diff --git a/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.stderr b/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.stderr
new file mode 100644
index 00000000000..eb50e5075ca
--- /dev/null
+++ b/src/test/ui/mir/mir-inlining/inline-instrument-coverage-fail.stderr
@@ -0,0 +1,2 @@
+warning: `-Z mir-opt-level=2` (or any level > 1) enables function inlining, which is incompatible with `-Z instrument-coverage`. Inlining will be disabled.
+
diff --git a/src/test/ui/moves/move-fn-self-receiver.rs b/src/test/ui/moves/move-fn-self-receiver.rs
index 6107f53fa19..946642ef6f3 100644
--- a/src/test/ui/moves/move-fn-self-receiver.rs
+++ b/src/test/ui/moves/move-fn-self-receiver.rs
@@ -69,6 +69,11 @@ fn move_out(val: Container) {
     let container = Container(vec![]);
     for _val in container.custom_into_iter() {}
     container; //~ ERROR use of moved
+
+    let foo2 = Foo;
+    loop {
+        foo2.use_self(); //~ 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
index dd263c1e906..eca6bb9296d 100644
--- a/src/test/ui/moves/move-fn-self-receiver.stderr
+++ b/src/test/ui/moves/move-fn-self-receiver.stderr
@@ -6,7 +6,7 @@ LL |     val.0.into_iter().next();
 LL |     val.0;
    |     ^^^^^ value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `val.0`
+note: this function takes ownership of the receiver `self`, which moves `val.0`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    |
 LL |     fn into_iter(self) -> Self::IntoIter;
@@ -23,7 +23,7 @@ LL |     foo.use_self();
 LL |     foo;
    |     ^^^ value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `foo`
+note: this function takes ownership of the receiver `self`, which moves `foo`
   --> $DIR/move-fn-self-receiver.rs:13:17
    |
 LL |     fn use_self(self) {}
@@ -49,7 +49,7 @@ LL |     boxed_foo.use_box_self();
 LL |     boxed_foo;
    |     ^^^^^^^^^ value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `boxed_foo`
+note: this function takes ownership of the receiver `self`, which moves `boxed_foo`
   --> $DIR/move-fn-self-receiver.rs:14:21
    |
 LL |     fn use_box_self(self: Box<Self>) {}
@@ -65,7 +65,7 @@ LL |     pin_box_foo.use_pin_box_self();
 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`
+note: this function takes ownership of the receiver `self`, which moves `pin_box_foo`
   --> $DIR/move-fn-self-receiver.rs:15:25
    |
 LL |     fn use_pin_box_self(self: Pin<Box<Self>>) {}
@@ -91,7 +91,7 @@ LL |     rc_foo.use_rc_self();
 LL |     rc_foo;
    |     ^^^^^^ value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `rc_foo`
+note: this function takes ownership of the receiver `self`, which moves `rc_foo`
   --> $DIR/move-fn-self-receiver.rs:16:20
    |
 LL |     fn use_rc_self(self: Rc<Self>) {}
@@ -146,13 +146,22 @@ LL |     for _val in container.custom_into_iter() {}
 LL |     container;
    |     ^^^^^^^^^ value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `container`
+note: this function takes ownership of the receiver `self`, 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
+error[E0382]: use of moved value: `foo2`
+  --> $DIR/move-fn-self-receiver.rs:75:9
+   |
+LL |     let foo2 = Foo;
+   |         ---- move occurs because `foo2` has type `Foo`, which does not implement the `Copy` trait
+LL |     loop {
+LL |         foo2.use_self();
+   |         ^^^^ ---------- `foo2` moved due to this method call, in previous iteration of loop
+
+error: aborting due to 12 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 11e94569580..3cc8ca29144 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
@@ -8,7 +8,7 @@ LL |     consume(x.into_iter().next().unwrap());
 LL |     touch(&x[0]);
    |            ^ value borrowed here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
+note: this function takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    |
 LL |     fn into_iter(self) -> Self::IntoIter;
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 46940cf4936..9bcec36740d 100644
--- a/src/test/ui/moves/moves-based-on-type-exprs.stderr
+++ b/src/test/ui/moves/moves-based-on-type-exprs.stderr
@@ -108,7 +108,7 @@ LL |     let _y = x.into_iter().next().unwrap();
 LL |     touch(&x);
    |           ^^ value borrowed here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
+note: this function takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    |
 LL |     fn into_iter(self) -> Self::IntoIter;
@@ -124,7 +124,7 @@ LL |     let _y = [x.into_iter().next().unwrap(); 1];
 LL |     touch(&x);
    |           ^^ value borrowed here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `x`
+note: this function takes ownership of the receiver `self`, which moves `x`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
    |
 LL |     fn into_iter(self) -> Self::IntoIter;
diff --git a/src/test/ui/no-patterns-in-args-2.stderr b/src/test/ui/no-patterns-in-args-2.stderr
index 21f4439d890..98932349a79 100644
--- a/src/test/ui/no-patterns-in-args-2.stderr
+++ b/src/test/ui/no-patterns-in-args-2.stderr
@@ -8,7 +8,7 @@ error: patterns aren't allowed in functions without bodies
   --> $DIR/no-patterns-in-args-2.rs:4:11
    |
 LL |     fn f1(mut arg: u8);
-   |           ^^^^^^^
+   |           ^^^^^^^ help: remove `mut` from the parameter: `arg`
    |
 note: the lint level is defined here
   --> $DIR/no-patterns-in-args-2.rs:1:9
diff --git a/src/test/ui/non-constant-expr-for-arr-len.stderr b/src/test/ui/non-constant-expr-for-arr-len.stderr
index b947cb7e19c..d684b8eaabd 100644
--- a/src/test/ui/non-constant-expr-for-arr-len.stderr
+++ b/src/test/ui/non-constant-expr-for-arr-len.stderr
@@ -1,8 +1,10 @@
 error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/non-constant-expr-for-arr-len.rs:5:22
    |
+LL |     fn bar(n: usize) {
+   |            - this would need to be a `const`
 LL |         let _x = [0; n];
-   |                      ^ non-constant value
+   |                      ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/overloaded-calls-nontuple.rs b/src/test/ui/overloaded-calls-nontuple.rs
index 76b114c5592..07d44ff82b1 100644
--- a/src/test/ui/overloaded-calls-nontuple.rs
+++ b/src/test/ui/overloaded-calls-nontuple.rs
@@ -11,13 +11,13 @@ impl FnMut<isize> for S {
     extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
         self.x + self.y + z
     }
-    //~^^^ ERROR A function with the "rust-call" ABI must take a single non-self argument
+    //~^^^ ERROR functions with the "rust-call" ABI must take a single non-self argument
 }
 
 impl FnOnce<isize> for S {
     type Output = isize;
     extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) }
-    //~^ ERROR A function with the "rust-call" ABI must take a single non-self argument
+    //~^ ERROR functions with the "rust-call" ABI must take a single non-self argument
 }
 
 fn main() {
diff --git a/src/test/ui/overloaded-calls-nontuple.stderr b/src/test/ui/overloaded-calls-nontuple.stderr
index bdadb95db29..8f299bc9434 100644
--- a/src/test/ui/overloaded-calls-nontuple.stderr
+++ b/src/test/ui/overloaded-calls-nontuple.stderr
@@ -1,10 +1,10 @@
-error: A function with the "rust-call" ABI must take a single non-self argument that is a tuple
+error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
   --> $DIR/overloaded-calls-nontuple.rs:11:5
    |
 LL |     extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: A function with the "rust-call" ABI must take a single non-self argument that is a tuple
+error: functions with the "rust-call" ABI must take a single non-self argument that is a tuple
   --> $DIR/overloaded-calls-nontuple.rs:19:5
    |
 LL |     extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) }
diff --git a/src/test/ui/panic-handler/weak-lang-item.stderr b/src/test/ui/panic-handler/weak-lang-item.stderr
index b7c040c7a85..68e3e21df3e 100644
--- a/src/test/ui/panic-handler/weak-lang-item.stderr
+++ b/src/test/ui/panic-handler/weak-lang-item.stderr
@@ -10,10 +10,10 @@ help: you can use `as` to change the binding name of the import
 LL | extern crate core as other_core;
    |
 
-error: `#[panic_handler]` function required, but not found
-
 error: language item required, but not found: `eh_personality`
 
+error: `#[panic_handler]` function required, but not found
+
 error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0259`.
diff --git a/src/test/ui/parser/block-no-opening-brace.rs b/src/test/ui/parser/block-no-opening-brace.rs
index e4bb39f6836..8a6599488b1 100644
--- a/src/test/ui/parser/block-no-opening-brace.rs
+++ b/src/test/ui/parser/block-no-opening-brace.rs
@@ -26,6 +26,6 @@ fn f4() {
     }
 
 fn f5() {
-    async //~ ERROR async closures are unstable
+    async
         let x = 0; //~ ERROR expected one of `move`, `|`, or `||`, found keyword `let`
     }
diff --git a/src/test/ui/parser/block-no-opening-brace.stderr b/src/test/ui/parser/block-no-opening-brace.stderr
index a88e4ac44cf..e32c8bdc73a 100644
--- a/src/test/ui/parser/block-no-opening-brace.stderr
+++ b/src/test/ui/parser/block-no-opening-brace.stderr
@@ -39,15 +39,5 @@ LL |     async
 LL |         let x = 0;
    |         ^^^ unexpected token
 
-error[E0658]: async closures are unstable
-  --> $DIR/block-no-opening-brace.rs:29:5
-   |
-LL |     async
-   |     ^^^^^
-   |
-   = note: see issue #62290 <https://github.com/rust-lang/rust/issues/62290> for more information
-   = help: add `#![feature(async_closure)]` to the crate attributes to enable
-
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/parser/import-from-path.stderr b/src/test/ui/parser/import-from-path.stderr
index 5842037fb80..93bdf82d0f5 100644
--- a/src/test/ui/parser/import-from-path.stderr
+++ b/src/test/ui/parser/import-from-path.stderr
@@ -3,6 +3,8 @@ error: expected `;`, found `::`
    |
 LL | use foo::{bar}::baz
    |               ^^ expected `;`
+   |
+   = note: glob-like brace syntax must be last on the path
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/import-from-rename.stderr b/src/test/ui/parser/import-from-rename.stderr
index a966e993737..d78f6de9222 100644
--- a/src/test/ui/parser/import-from-rename.stderr
+++ b/src/test/ui/parser/import-from-rename.stderr
@@ -3,6 +3,8 @@ error: expected `;`, found keyword `as`
    |
 LL | use foo::{bar} as baz;
    |                ^^ expected `;`
+   |
+   = note: glob-like brace syntax must be last on the path
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/import-glob-path.stderr b/src/test/ui/parser/import-glob-path.stderr
index ebca2db8305..a93ef255c94 100644
--- a/src/test/ui/parser/import-glob-path.stderr
+++ b/src/test/ui/parser/import-glob-path.stderr
@@ -3,6 +3,8 @@ error: expected `;`, found `::`
    |
 LL | use foo::*::bar
    |           ^^ expected `;`
+   |
+   = note: the wildcard token must be last on the path
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/import-glob-rename.stderr b/src/test/ui/parser/import-glob-rename.stderr
index 28538732782..e1a026b639e 100644
--- a/src/test/ui/parser/import-glob-rename.stderr
+++ b/src/test/ui/parser/import-glob-rename.stderr
@@ -3,6 +3,8 @@ error: expected `;`, found keyword `as`
    |
 LL | use foo::* as baz;
    |            ^^ expected `;`
+   |
+   = note: the wildcard token must be last on the path
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr
index 0fa77fb73da..2ca774a48b6 100644
--- a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr
+++ b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr
@@ -6,6 +6,7 @@ LL |     match uninhab_ref() {
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&!`
+   = note: references are always considered inhabited
 
 error[E0004]: non-exhaustive patterns: type `Foo` is non-empty
   --> $DIR/always-inhabited-union-ref.rs:27:11
diff --git a/src/test/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs b/src/test/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs
new file mode 100644
index 00000000000..6c5a331b4b5
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.rs
@@ -0,0 +1,11 @@
+enum A {}
+    //~^ NOTE `A` defined here
+
+fn f(a: &A) {
+    match a {}
+    //~^ ERROR non-exhaustive patterns: type `&A` is non-empty
+    //~| NOTE the matched value is of type `&A`
+    //~| NOTE references are always considered inhabited
+}
+
+fn main() {}
diff --git a/src/test/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr b/src/test/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr
new file mode 100644
index 00000000000..e992632a91f
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/issue-78123-non-exhaustive-reference.stderr
@@ -0,0 +1,16 @@
+error[E0004]: non-exhaustive patterns: type `&A` is non-empty
+  --> $DIR/issue-78123-non-exhaustive-reference.rs:5:11
+   |
+LL | enum A {}
+   | --------- `A` defined here
+...
+LL |     match a {}
+   |           ^
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `&A`
+   = note: references are always considered inhabited
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout b/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout
index 4c0810217bf..5f513684cfa 100644
--- a/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout
+++ b/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout
@@ -1211,141 +1211,141 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
         spacing: Alone,
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Group {
         delimiter: Bracket,
         stream: TokenStream [
             Ident {
                 ident: "allow",
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Group {
                 delimiter: Parenthesis,
                 stream: TokenStream [
                     Ident {
                         ident: "dead_code",
-                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                     },
                 ],
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
         ],
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Punct {
         ch: '#',
         spacing: Alone,
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Group {
         delimiter: Bracket,
         stream: TokenStream [
             Ident {
                 ident: "print_helper",
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Group {
                 delimiter: Parenthesis,
                 stream: TokenStream [
                     Ident {
                         ident: "b",
-                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                     },
                 ],
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
         ],
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Punct {
         ch: '#',
         spacing: Alone,
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Group {
         delimiter: Bracket,
         stream: TokenStream [
             Ident {
                 ident: "print_helper",
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Group {
                 delimiter: Parenthesis,
                 stream: TokenStream [
                     Ident {
                         ident: "a",
-                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                     },
                 ],
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
         ],
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Ident {
         ident: "struct",
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Ident {
         ident: "Foo",
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Punct {
         ch: '<',
         spacing: Alone,
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Ident {
         ident: "B",
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Punct {
         ch: '>',
         spacing: Alone,
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
     Group {
         delimiter: Brace,
         stream: TokenStream [
             Ident {
                 ident: "second",
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Ident {
                 ident: "bool",
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Punct {
                 ch: ',',
                 spacing: Alone,
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Ident {
                 ident: "third",
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Group {
                 delimiter: Bracket,
                 stream: TokenStream [
                     Ident {
                         ident: "u8",
-                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                     },
                     Punct {
                         ch: ';',
                         spacing: Alone,
-                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                     },
                     Group {
                         delimiter: Brace,
@@ -1353,58 +1353,58 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
                             Punct {
                                 ch: '#',
                                 spacing: Alone,
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Group {
                                 delimiter: Bracket,
                                 stream: TokenStream [
                                     Ident {
                                         ident: "cfg",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Group {
                                         delimiter: Parenthesis,
                                         stream: TokenStream [
                                             Ident {
                                                 ident: "not",
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                             Group {
                                                 delimiter: Parenthesis,
                                                 stream: TokenStream [
                                                     Ident {
                                                         ident: "FALSE",
-                                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                     },
                                                 ],
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                         ],
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                 ],
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Ident {
                                 ident: "struct",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Ident {
                                 ident: "Inner",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Punct {
                                 ch: ';',
                                 spacing: Alone,
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Ident {
                                 ident: "match",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Ident {
                                 ident: "true",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Group {
                                 delimiter: Brace,
@@ -1412,146 +1412,146 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
                                     Punct {
                                         ch: '#',
                                         spacing: Alone,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Group {
                                         delimiter: Bracket,
                                         stream: TokenStream [
                                             Ident {
                                                 ident: "allow",
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                             Group {
                                                 delimiter: Parenthesis,
                                                 stream: TokenStream [
                                                     Ident {
                                                         ident: "warnings",
-                                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                     },
                                                 ],
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                         ],
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Ident {
                                         ident: "false",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Punct {
                                         ch: '=',
                                         spacing: Joint,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Punct {
                                         ch: '>',
                                         spacing: Alone,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Group {
                                         delimiter: Brace,
                                         stream: TokenStream [],
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Ident {
                                         ident: "_",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Punct {
                                         ch: '=',
                                         spacing: Joint,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Punct {
                                         ch: '>',
                                         spacing: Alone,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Group {
                                         delimiter: Brace,
                                         stream: TokenStream [],
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                 ],
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Punct {
                                 ch: ';',
                                 spacing: Alone,
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Punct {
                                 ch: '#',
                                 spacing: Alone,
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Group {
                                 delimiter: Bracket,
                                 stream: TokenStream [
                                     Ident {
                                         ident: "print_helper",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Group {
                                         delimiter: Parenthesis,
                                         stream: TokenStream [
                                             Ident {
                                                 ident: "c",
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                         ],
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                 ],
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Punct {
                                 ch: '#',
                                 spacing: Alone,
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Group {
                                 delimiter: Bracket,
                                 stream: TokenStream [
                                     Ident {
                                         ident: "cfg",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Group {
                                         delimiter: Parenthesis,
                                         stream: TokenStream [
                                             Ident {
                                                 ident: "not",
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                             Group {
                                                 delimiter: Parenthesis,
                                                 stream: TokenStream [
                                                     Ident {
                                                         ident: "FALSE",
-                                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                     },
                                                 ],
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                         ],
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                 ],
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Ident {
                                 ident: "fn",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Ident {
                                 ident: "kept_fn",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Group {
                                 delimiter: Parenthesis,
                                 stream: TokenStream [],
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Group {
                                 delimiter: Brace,
@@ -1559,82 +1559,82 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
                                     Punct {
                                         ch: '#',
                                         spacing: Joint,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Punct {
                                         ch: '!',
                                         spacing: Alone,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Group {
                                         delimiter: Bracket,
                                         stream: TokenStream [
                                             Ident {
                                                 ident: "cfg",
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                             Group {
                                                 delimiter: Parenthesis,
                                                 stream: TokenStream [
                                                     Ident {
                                                         ident: "not",
-                                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                     },
                                                     Group {
                                                         delimiter: Parenthesis,
                                                         stream: TokenStream [
                                                             Ident {
                                                                 ident: "FALSE",
-                                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                             },
                                                         ],
-                                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                     },
                                                 ],
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                         ],
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Ident {
                                         ident: "let",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Ident {
                                         ident: "my_val",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Punct {
                                         ch: '=',
                                         spacing: Alone,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Ident {
                                         ident: "true",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Punct {
                                         ch: ';',
                                         spacing: Alone,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                 ],
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Ident {
                                 ident: "enum",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Ident {
                                 ident: "TupleEnum",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Group {
                                 delimiter: Brace,
                                 stream: TokenStream [
                                     Ident {
                                         ident: "Foo",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Group {
                                         delimiter: Parenthesis,
@@ -1642,69 +1642,69 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
                                             Punct {
                                                 ch: '#',
                                                 spacing: Alone,
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                             Group {
                                                 delimiter: Bracket,
                                                 stream: TokenStream [
                                                     Ident {
                                                         ident: "cfg",
-                                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                     },
                                                     Group {
                                                         delimiter: Parenthesis,
                                                         stream: TokenStream [
                                                             Ident {
                                                                 ident: "not",
-                                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                             },
                                                             Group {
                                                                 delimiter: Parenthesis,
                                                                 stream: TokenStream [
                                                                     Ident {
                                                                         ident: "FALSE",
-                                                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                                     },
                                                                 ],
-                                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                             },
                                                         ],
-                                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                     },
                                                 ],
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                             Ident {
                                                 ident: "i32",
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                             Punct {
                                                 ch: ',',
                                                 spacing: Alone,
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                             Ident {
                                                 ident: "u8",
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                         ],
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Punct {
                                         ch: ',',
                                         spacing: Alone,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                 ],
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Ident {
                                 ident: "struct",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Ident {
                                 ident: "TupleStruct",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Group {
                                 delimiter: Parenthesis,
@@ -1712,120 +1712,120 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
                                     Punct {
                                         ch: '#',
                                         spacing: Alone,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Group {
                                         delimiter: Bracket,
                                         stream: TokenStream [
                                             Ident {
                                                 ident: "cfg",
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                             Group {
                                                 delimiter: Parenthesis,
                                                 stream: TokenStream [
                                                     Ident {
                                                         ident: "not",
-                                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                     },
                                                     Group {
                                                         delimiter: Parenthesis,
                                                         stream: TokenStream [
                                                             Ident {
                                                                 ident: "FALSE",
-                                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                             },
                                                         ],
-                                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                                     },
                                                 ],
-                                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                             },
                                         ],
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Ident {
                                         ident: "i32",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Punct {
                                         ch: ',',
                                         spacing: Alone,
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                     Ident {
                                         ident: "u8",
-                                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                                     },
                                 ],
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Punct {
                                 ch: ';',
                                 spacing: Alone,
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                             Literal {
                                 kind: Integer,
                                 symbol: "0",
                                 suffix: None,
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                         ],
-                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                     },
                 ],
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Punct {
                 ch: ',',
                 spacing: Alone,
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Punct {
                 ch: '#',
                 spacing: Alone,
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Group {
                 delimiter: Bracket,
                 stream: TokenStream [
                     Ident {
                         ident: "print_helper",
-                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                     },
                     Group {
                         delimiter: Parenthesis,
                         stream: TokenStream [
                             Ident {
                                 ident: "d",
-                                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                             },
                         ],
-                        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
                     },
                 ],
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Ident {
                 ident: "fourth",
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Ident {
                 ident: "B",
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
             Punct {
                 ch: ',',
                 spacing: Alone,
-                span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+                span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
             },
         ],
-        span: $DIR/issue-75930-derive-cfg.rs:1:1: 1:1 (#0),
+        span: $DIR/issue-75930-derive-cfg.rs:21:1: 64:2 (#0),
     },
 ]
diff --git a/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout b/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout
index c4ee44f6541..40da5aa93bf 100644
--- a/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout
+++ b/src/test/ui/proc-macro/issue-78675-captured-inner-attrs.stdout
@@ -34,11 +34,11 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
                 stream: TokenStream [
                     Ident {
                         ident: "mod",
-                        span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
+                        span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0),
                     },
                     Ident {
                         ident: "bar",
-                        span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
+                        span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0),
                     },
                     Group {
                         delimiter: Brace,
@@ -46,36 +46,36 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
                             Punct {
                                 ch: '#',
                                 spacing: Joint,
-                                span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
+                                span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0),
                             },
                             Punct {
                                 ch: '!',
                                 spacing: Alone,
-                                span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
+                                span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0),
                             },
                             Group {
                                 delimiter: Bracket,
                                 stream: TokenStream [
                                     Ident {
                                         ident: "doc",
-                                        span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
+                                        span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0),
                                     },
                                     Punct {
                                         ch: '=',
                                         spacing: Alone,
-                                        span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
+                                        span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0),
                                     },
                                     Literal {
                                         kind: StrRaw(0),
                                         symbol: " Foo",
                                         suffix: None,
-                                        span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
+                                        span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0),
                                     },
                                 ],
-                                span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
+                                span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0),
                             },
                         ],
-                        span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
+                        span: $DIR/issue-78675-captured-inner-attrs.rs:27:5: 29:6 (#0),
                     },
                 ],
                 span: $DIR/issue-78675-captured-inner-attrs.rs:22:13: 22:18 (#4),
diff --git a/src/test/ui/proc-macro/issue-80760-empty-stmt.rs b/src/test/ui/proc-macro/issue-80760-empty-stmt.rs
new file mode 100644
index 00000000000..86865af0b52
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-80760-empty-stmt.rs
@@ -0,0 +1,26 @@
+// check-pass
+// aux-build:test-macros.rs
+// compile-flags: -Z span-debug
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+macro_rules! empty_stmt {
+    ($s:stmt) => {
+        print_bang!($s);
+
+        // Currently, all attributes are ignored
+        // on an empty statement
+        #[print_attr]
+        #[rustc_dummy(first)]
+        #[rustc_dummy(second)]
+        $s
+    }
+}
+
+fn main() {
+    empty_stmt!(;);
+}
diff --git a/src/test/ui/proc-macro/issue-80760-empty-stmt.stdout b/src/test/ui/proc-macro/issue-80760-empty-stmt.stdout
new file mode 100644
index 00000000000..4b7ed874307
--- /dev/null
+++ b/src/test/ui/proc-macro/issue-80760-empty-stmt.stdout
@@ -0,0 +1,14 @@
+PRINT-BANG INPUT (DISPLAY): ;
+PRINT-BANG INPUT (DEBUG): TokenStream [
+    Group {
+        delimiter: None,
+        stream: TokenStream [
+            Punct {
+                ch: ';',
+                spacing: Alone,
+                span: $DIR/issue-80760-empty-stmt.rs:25:17: 25:18 (#0),
+            },
+        ],
+        span: $DIR/issue-80760-empty-stmt.rs:13:21: 13:23 (#4),
+    },
+]
diff --git a/src/test/ui/repeat_count.stderr b/src/test/ui/repeat_count.stderr
index 5fcda348ab3..e90754e9118 100644
--- a/src/test/ui/repeat_count.stderr
+++ b/src/test/ui/repeat_count.stderr
@@ -1,6 +1,8 @@
 error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/repeat_count.rs:5:17
    |
+LL |     let n = 1;
+   |     ----- help: consider using `const` instead of `let`: `const n`
 LL |     let a = [0; n];
    |                 ^ non-constant value
 
diff --git a/src/test/ui/sanitize/unsupported-target.stderr b/src/test/ui/sanitize/unsupported-target.stderr
index f5961a11b1f..093678707fb 100644
--- a/src/test/ui/sanitize/unsupported-target.stderr
+++ b/src/test/ui/sanitize/unsupported-target.stderr
@@ -1,4 +1,4 @@
-error: `-Zsanitizer=leak` only works with targets: aarch64-unknown-linux-gnu, x86_64-apple-darwin, x86_64-unknown-linux-gnu
+error: `-Zsanitizer=leak` only works with targets: aarch64-apple-darwin, aarch64-unknown-linux-gnu, x86_64-apple-darwin, x86_64-unknown-linux-gnu
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/borrow-for-loop-head.stderr b/src/test/ui/suggestions/borrow-for-loop-head.stderr
index de342a969f4..28c319b6597 100644
--- a/src/test/ui/suggestions/borrow-for-loop-head.stderr
+++ b/src/test/ui/suggestions/borrow-for-loop-head.stderr
@@ -15,8 +15,14 @@ LL |     for i in &a {
 LL |         for j in a {
    |                  ^
    |                  |
-   |                  value moved here, in previous iteration of loop
+   |                  `a` moved due to this implicit call to `.into_iter()`, in previous iteration of loop
    |                  help: consider borrowing to avoid moving into the for loop: `&a`
+   |
+note: this function takes ownership of the receiver `self`, which moves `a`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |                  ^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/terminal-width/tabs-trimming.rs b/src/test/ui/terminal-width/tabs-trimming.rs
new file mode 100644
index 00000000000..ade21753b45
--- /dev/null
+++ b/src/test/ui/terminal-width/tabs-trimming.rs
@@ -0,0 +1,13 @@
+// Test for #78438: ensure underline alignment with many tabs on the left, long line on the right
+
+// ignore-tidy-linelength
+// ignore-tidy-tab
+
+					fn main() {
+						let money = 42i32;
+						match money {
+							v @ 1 | 2 | 3 => panic!("You gave me too little money {}", v), // Long text here: TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
+							//~^ ERROR variable `v` is not bound in all patterns
+							v => println!("Enough money {}", v),
+						}
+					}
diff --git a/src/test/ui/terminal-width/tabs-trimming.stderr b/src/test/ui/terminal-width/tabs-trimming.stderr
new file mode 100644
index 00000000000..6c8d9afc73b
--- /dev/null
+++ b/src/test/ui/terminal-width/tabs-trimming.stderr
@@ -0,0 +1,12 @@
+error[E0408]: variable `v` is not bound in all patterns
+  --> $DIR/tabs-trimming.rs:9:16
+   |
+LL | ...   v @ 1 | 2 | 3 => panic!("You gave me too little money {}", v), // Long text here: TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT...
+   |       -       ^   ^ pattern doesn't bind `v`
+   |       |       |
+   |       |       pattern doesn't bind `v`
+   |       variable not in all patterns
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0408`.
diff --git a/src/test/ui/type/type-dependent-def-issue-49241.stderr b/src/test/ui/type/type-dependent-def-issue-49241.stderr
index c5dcfa7a431..64c7687f7a8 100644
--- a/src/test/ui/type/type-dependent-def-issue-49241.stderr
+++ b/src/test/ui/type/type-dependent-def-issue-49241.stderr
@@ -2,7 +2,9 @@ error[E0435]: attempt to use a non-constant value in a constant
   --> $DIR/type-dependent-def-issue-49241.rs:3:22
    |
 LL |     const l: usize = v.count();
-   |                      ^ non-constant value
+   |     -------          ^ non-constant value
+   |     |
+   |     help: consider using `let` instead of `const`: `let l`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
index 960c4792e65..7b999f50773 100644
--- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
+++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
@@ -23,6 +23,7 @@ LL |     let _ = match x {};
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&Void`
+   = note: references are always considered inhabited
 
 error[E0004]: non-exhaustive patterns: type `(Void,)` is non-empty
   --> $DIR/uninhabited-matches-feature-gated.rs:18:19
diff --git a/src/test/ui/unsafe/ranged_ints3_const.rs b/src/test/ui/unsafe/ranged_ints3_const.rs
index 7b03d8eda93..c069ae7da02 100644
--- a/src/test/ui/unsafe/ranged_ints3_const.rs
+++ b/src/test/ui/unsafe/ranged_ints3_const.rs
@@ -9,13 +9,13 @@ fn main() {}
 
 const fn foo() -> NonZero<Cell<u32>> {
     let mut x = unsafe { NonZero(Cell::new(1)) };
-    let y = &x.0; //~ ERROR cannot borrow a constant which may contain interior mutability
+    let y = &x.0; //~ ERROR the borrowed element may contain interior mutability
     //~^ ERROR borrow of layout constrained field with interior mutability
     unsafe { NonZero(Cell::new(1)) }
 }
 
 const fn bar() -> NonZero<Cell<u32>> {
     let mut x = unsafe { NonZero(Cell::new(1)) };
-    let y = unsafe { &x.0 }; //~ ERROR cannot borrow a constant which may contain interior mut
+    let y = unsafe { &x.0 }; //~ ERROR the borrowed element may contain interior mutability
     unsafe { NonZero(Cell::new(1)) }
 }
diff --git a/src/test/ui/unsafe/ranged_ints3_const.stderr b/src/test/ui/unsafe/ranged_ints3_const.stderr
index d2eb3bc5360..215005571f6 100644
--- a/src/test/ui/unsafe/ranged_ints3_const.stderr
+++ b/src/test/ui/unsafe/ranged_ints3_const.stderr
@@ -1,14 +1,20 @@
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
   --> $DIR/ranged_ints3_const.rs:12:13
    |
 LL |     let y = &x.0;
    |             ^^^^
+   |
+   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
 
-error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+error[E0658]: cannot borrow here, since the borrowed element may contain interior mutability
   --> $DIR/ranged_ints3_const.rs:19:22
    |
 LL |     let y = unsafe { &x.0 };
    |                      ^^^^
+   |
+   = note: see issue #80384 <https://github.com/rust-lang/rust/issues/80384> for more information
+   = help: add `#![feature(const_refs_to_cell)]` to the crate attributes to enable
 
 error[E0133]: borrow of layout constrained field with interior mutability is unsafe and requires unsafe function or block
   --> $DIR/ranged_ints3_const.rs:12:13
@@ -20,5 +26,5 @@ LL |     let y = &x.0;
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0133, E0492.
+Some errors have detailed explanations: E0133, E0658.
 For more information about an error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsized-locals/borrow-after-move.stderr b/src/test/ui/unsized-locals/borrow-after-move.stderr
index 5934276cc1d..4f2bc06d4ab 100644
--- a/src/test/ui/unsized-locals/borrow-after-move.stderr
+++ b/src/test/ui/unsized-locals/borrow-after-move.stderr
@@ -51,7 +51,7 @@ LL |         y.foo();
 LL |         println!("{}", &y);
    |                        ^^ value borrowed here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `y`
+note: this function takes ownership of the receiver `self`, which moves `y`
   --> $DIR/borrow-after-move.rs:5:12
    |
 LL |     fn foo(self) -> String;
diff --git a/src/test/ui/unsized-locals/double-move.stderr b/src/test/ui/unsized-locals/double-move.stderr
index b897dbbc9a3..4bb2ad88faf 100644
--- a/src/test/ui/unsized-locals/double-move.stderr
+++ b/src/test/ui/unsized-locals/double-move.stderr
@@ -47,7 +47,7 @@ LL |         y.foo();
 LL |         y.foo();
    |         ^ value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `y`
+note: this function takes ownership of the receiver `self`, which moves `y`
   --> $DIR/double-move.rs:5:12
    |
 LL |     fn foo(self) -> String;
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 b9440f4de07..7fdc4ab251f 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
@@ -8,7 +8,7 @@ LL |         self.bar();
 LL |         return self.x;
    |                ^^^^^^ value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `self`
+note: this function takes ownership of the receiver `self`, which moves `self`
   --> $DIR/use-after-move-self-based-on-type.rs:15:16
    |
 LL |     pub fn bar(self) {}
diff --git a/src/test/ui/use/use-after-move-self.stderr b/src/test/ui/use/use-after-move-self.stderr
index 3da53b024db..073deee63b9 100644
--- a/src/test/ui/use/use-after-move-self.stderr
+++ b/src/test/ui/use/use-after-move-self.stderr
@@ -8,7 +8,7 @@ LL |         self.bar();
 LL |         return *self.x;
    |                ^^^^^^^ value used here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `self`
+note: this function takes ownership of the receiver `self`, which moves `self`
   --> $DIR/use-after-move-self.rs:13:16
    |
 LL |     pub fn bar(self) {}
diff --git a/src/test/ui/walk-struct-literal-with.stderr b/src/test/ui/walk-struct-literal-with.stderr
index ece63a2b819..cda08b0f4e0 100644
--- a/src/test/ui/walk-struct-literal-with.stderr
+++ b/src/test/ui/walk-struct-literal-with.stderr
@@ -8,7 +8,7 @@ LL |     let end = Mine{other_val:1, ..start.make_string_bar()};
 LL |     println!("{}", start.test);
    |                    ^^^^^^^^^^ value borrowed here after move
    |
-note: this function consumes the receiver `self` by taking ownership of it, which moves `start`
+note: this function takes ownership of the receiver `self`, which moves `start`
   --> $DIR/walk-struct-literal-with.rs:7:28
    |
 LL |     fn make_string_bar(mut self) -> Mine{
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 75d5d8cffe3464631f82dcd3c470b78dc1dda8b
+Subproject 329895f5b52a358e5d9ecb26215708b5cb31d90
diff --git a/src/tools/clippy/.github/ISSUE_TEMPLATE/false_negative.md b/src/tools/clippy/.github/ISSUE_TEMPLATE/false_negative.md
new file mode 100644
index 00000000000..f46828fec91
--- /dev/null
+++ b/src/tools/clippy/.github/ISSUE_TEMPLATE/false_negative.md
@@ -0,0 +1,35 @@
+---
+name: Bug Report (False Negative)
+about: Create a bug report about missing warnings from a lint
+labels: L-bug, L-false-negative
+---
+<!--
+Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
+along with any information you feel relevant to replicating the bug.
+-->
+Lint name:
+
+
+I tried this code:
+
+```rust
+<code>
+```
+
+I expected to see this happen: *explanation*
+
+Instead, this happened: *explanation*
+
+### Meta
+
+- `cargo clippy -V`: e.g. clippy 0.0.212 (f455e46 2020-06-20)
+- `rustc -Vv`:
+  ```
+  rustc 1.46.0-nightly (f455e46ea 2020-06-20)
+  binary: rustc
+  commit-hash: f455e46eae1a227d735091091144601b467e1565
+  commit-date: 2020-06-20
+  host: x86_64-unknown-linux-gnu
+  release: 1.46.0-nightly
+  LLVM version: 10.0
+  ```
diff --git a/src/tools/clippy/.github/ISSUE_TEMPLATE/false_positive.md b/src/tools/clippy/.github/ISSUE_TEMPLATE/false_positive.md
new file mode 100644
index 00000000000..92a7373fc27
--- /dev/null
+++ b/src/tools/clippy/.github/ISSUE_TEMPLATE/false_positive.md
@@ -0,0 +1,35 @@
+---
+name: Bug Report (False Positive)
+about: Create a bug report about a wrongly emitted lint warning
+labels: L-bug, L-false-positive
+---
+<!--
+Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
+along with any information you feel relevant to replicating the bug.
+-->
+Lint name:
+
+
+I tried this code:
+
+```rust
+<code>
+```
+
+I expected to see this happen: *explanation*
+
+Instead, this happened: *explanation*
+
+### Meta
+
+- `cargo clippy -V`: e.g. clippy 0.0.212 (f455e46 2020-06-20)
+- `rustc -Vv`:
+  ```
+  rustc 1.46.0-nightly (f455e46ea 2020-06-20)
+  binary: rustc
+  commit-hash: f455e46eae1a227d735091091144601b467e1565
+  commit-date: 2020-06-20
+  host: x86_64-unknown-linux-gnu
+  release: 1.46.0-nightly
+  LLVM version: 10.0
+  ```
diff --git a/src/tools/clippy/.github/workflows/clippy.yml b/src/tools/clippy/.github/workflows/clippy.yml
index 530e60001f7..9d5e12aac5f 100644
--- a/src/tools/clippy/.github/workflows/clippy.yml
+++ b/src/tools/clippy/.github/workflows/clippy.yml
@@ -50,6 +50,9 @@ jobs:
     - name: Build
       run: cargo build --features deny-warnings,internal-lints
 
+    - name: Test "--fix -Zunstable-options"
+      run: cargo run --features deny-warnings,internal-lints --bin cargo-clippy -- clippy --fix -Zunstable-options
+
     - name: Test
       run: cargo test --features deny-warnings,internal-lints
 
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index af3b1c1db2a..de8da99cdee 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -1841,6 +1841,7 @@ Released 2018-09-13
 [`forget_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_copy
 [`forget_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_ref
 [`from_iter_instead_of_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_iter_instead_of_collect
+[`from_over_into`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into
 [`future_not_send`]: https://rust-lang.github.io/rust-clippy/master/index.html#future_not_send
 [`get_last_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_last_with_len
 [`get_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_unwrap
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index a765390c603..e60aa472846 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy"
-version = "0.0.212"
+version = "0.1.51"
 authors = [
 	"Manish Goregaokar <manishsmail@gmail.com>",
 	"Andre Bogus <bogusandre@gmail.com>",
@@ -29,7 +29,7 @@ path = "src/driver.rs"
 
 [dependencies]
 # begin automatic update
-clippy_lints = { version = "0.0.212", path = "clippy_lints" }
+clippy_lints = { version = "0.1.50", path = "clippy_lints" }
 # end automatic update
 semver = "0.11"
 rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util" }
diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md
index aaa55e11c7d..a4928e17e6a 100644
--- a/src/tools/clippy/README.md
+++ b/src/tools/clippy/README.md
@@ -10,16 +10,16 @@ A collection of lints to catch common mistakes and improve your [Rust](https://g
 Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html).
 You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the lint level by category.
 
-Category | Description | Default level
--- | -- | --
-`clippy::all` | all lints that are on by default (correctness, style, complexity, perf) | **warn/deny**
-`clippy::correctness` | code that is outright wrong or very useless | **deny**
-`clippy::style` | code that should be written in a more idiomatic way | **warn**
-`clippy::complexity` | code that does something simple but in a complex way | **warn**
-`clippy::perf` | code that can be written to run faster | **warn**
-`clippy::pedantic` | lints which are rather strict or might have false positives | allow
-`clippy::nursery` | new lints that are still under development | allow
-`clippy::cargo` | lints for the cargo manifest | allow
+| Category              | Description                                                             | Default level |
+| --------------------- | ----------------------------------------------------------------------- | ------------- |
+| `clippy::all`         | all lints that are on by default (correctness, style, complexity, perf) | **warn/deny** |
+| `clippy::correctness` | code that is outright wrong or very useless                             | **deny**      |
+| `clippy::style`       | code that should be written in a more idiomatic way                     | **warn**      |
+| `clippy::complexity`  | code that does something simple but in a complex way                    | **warn**      |
+| `clippy::perf`        | code that can be written to run faster                                  | **warn**      |
+| `clippy::pedantic`    | lints which are rather strict or might have false positives             | allow         |
+| `clippy::nursery`     | new lints that are still under development                              | allow         |
+| `clippy::cargo`       | lints for the cargo manifest                                            | allow         |
 
 More to come, please [file an issue](https://github.com/rust-lang/rust-clippy/issues) if you have ideas!
 
@@ -98,17 +98,6 @@ If you want to run Clippy **only** on the given crate, use the `--no-deps` optio
 cargo clippy -p example -- --no-deps 
 ```
 
-### Running Clippy from the command line without installing it
-
-To have cargo compile your crate with Clippy without Clippy installation
-in your code, you can use:
-
-```terminal
-cargo run --bin cargo-clippy --manifest-path=path_to_clippys_Cargo.toml
-```
-
-*Note:* Be sure that Clippy was compiled with the same version of rustc that cargo invokes here!
-
 ### Travis CI
 
 You can add Clippy to Travis CI in the same way you use it locally:
@@ -130,18 +119,6 @@ script:
   # etc.
 ```
 
-If you are on nightly, It might happen that Clippy is not available for a certain nightly release.
-In this case you can try to conditionally install Clippy from the Git repo.
-
-```yaml
-language: rust
-rust:
-  - nightly
-before_script:
-   - rustup component add clippy --toolchain=nightly || cargo install --git https://github.com/rust-lang/rust-clippy/ --force clippy
-   # etc.
-```
-
 Note that adding `-D warnings` will cause your build to fail if **any** warnings are found in your code.
 That includes warnings found by rustc (e.g. `dead_code`, etc.). If you want to avoid this and only cause
 an error for Clippy warnings, use `#![deny(clippy::all)]` in your code or `-D clippy::all` on the command
diff --git a/src/tools/clippy/clippy_dev/src/ra_setup.rs b/src/tools/clippy/clippy_dev/src/ra_setup.rs
index 40bf4a9505a..5f5048e79e7 100644
--- a/src/tools/clippy/clippy_dev/src/ra_setup.rs
+++ b/src/tools/clippy/clippy_dev/src/ra_setup.rs
@@ -3,7 +3,7 @@
 use std::fs;
 use std::fs::File;
 use std::io::prelude::*;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 
 // This module takes an absolute path to a rustc repo and alters the dependencies to point towards
 // the respective rustc subcrates instead of using extern crate xyz.
@@ -44,7 +44,7 @@ pub fn run(rustc_path: Option<&str>) {
 }
 
 fn inject_deps_into_manifest(
-    rustc_source_dir: &PathBuf,
+    rustc_source_dir: &Path,
     manifest_path: &str,
     cargo_toml: &str,
     lib_rs: &str,
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index 7697eba650a..a9516560a61 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "clippy_lints"
 # begin automatic update
-version = "0.0.212"
+version = "0.1.51"
 # end automatic update
 authors = [
 	"Manish Goregaokar <manishsmail@gmail.com>",
diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs
index f69f6f1412a..b0d7c7b3baa 100644
--- a/src/tools/clippy/clippy_lints/src/default.rs
+++ b/src/tools/clippy/clippy_lints/src/default.rs
@@ -6,7 +6,7 @@ use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{self, Adt, Ty};
+use rustc_middle::ty;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::Span;
@@ -103,18 +103,41 @@ impl LateLintPass<'_> for Default {
     }
 
     fn check_block<'tcx>(&mut self, cx: &LateContext<'tcx>, block: &Block<'tcx>) {
-        // find all binding statements like `let mut _ = T::default()` where `T::default()` is the
-        // `default` method of the `Default` trait, and store statement index in current block being
-        // checked and the name of the bound variable
-        let binding_statements_using_default = enumerate_bindings_using_default(cx, block);
-
         // start from the `let mut _ = _::default();` and look at all the following
         // statements, see if they re-assign the fields of the binding
-        for (stmt_idx, binding_name, binding_type, span) in binding_statements_using_default {
-            // the last statement of a block cannot trigger the lint
-            if stmt_idx == block.stmts.len() - 1 {
-                break;
-            }
+        let stmts_head = match block.stmts {
+            // Skip the last statement since there cannot possibly be any following statements that re-assign fields.
+            [head @ .., _] if !head.is_empty() => head,
+            _ => return,
+        };
+        for (stmt_idx, stmt) in stmts_head.iter().enumerate() {
+            // find all binding statements like `let mut _ = T::default()` where `T::default()` is the
+            // `default` method of the `Default` trait, and store statement index in current block being
+            // checked and the name of the bound variable
+            let (local, variant, binding_name, binding_type, span) = if_chain! {
+                // only take `let ...` statements
+                if let StmtKind::Local(local) = stmt.kind;
+                if let Some(expr) = local.init;
+                // only take bindings to identifiers
+                if let PatKind::Binding(_, binding_id, ident, _) = local.pat.kind;
+                // only when assigning `... = Default::default()`
+                if is_expr_default(expr, cx);
+                let binding_type = cx.typeck_results().node_type(binding_id);
+                if let Some(adt) = binding_type.ty_adt_def();
+                if adt.is_struct();
+                let variant = adt.non_enum_variant();
+                if adt.did.is_local() || !variant.is_field_list_non_exhaustive();
+                let module_did = cx.tcx.parent_module(stmt.hir_id).to_def_id();
+                if variant
+                    .fields
+                    .iter()
+                    .all(|field| field.vis.is_accessible_from(module_did, cx.tcx));
+                then {
+                    (local, variant, ident.name, binding_type, expr.span)
+                } else {
+                    continue;
+                }
+            };
 
             // find all "later statement"'s where the fields of the binding set as
             // Default::default() get reassigned, unless the reassignment refers to the original binding
@@ -122,15 +145,8 @@ impl LateLintPass<'_> for Default {
             let mut assigned_fields = Vec::new();
             let mut cancel_lint = false;
             for consecutive_statement in &block.stmts[stmt_idx + 1..] {
-                // interrupt if the statement is a let binding (`Local`) that shadows the original
-                // binding
-                if stmt_shadows_binding(consecutive_statement, binding_name) {
-                    break;
-                }
                 // find out if and which field was set by this `consecutive_statement`
-                else if let Some((field_ident, assign_rhs)) =
-                    field_reassigned_by_stmt(consecutive_statement, binding_name)
-                {
+                if let Some((field_ident, assign_rhs)) = field_reassigned_by_stmt(consecutive_statement, binding_name) {
                     // interrupt and cancel lint if assign_rhs references the original binding
                     if contains_name(binding_name, assign_rhs) {
                         cancel_lint = true;
@@ -152,7 +168,7 @@ impl LateLintPass<'_> for Default {
                         first_assign = Some(consecutive_statement);
                     }
                 }
-                // interrupt also if no field was assigned, since we only want to look at consecutive statements
+                // interrupt if no field was assigned, since we only want to look at consecutive statements
                 else {
                     break;
                 }
@@ -161,55 +177,45 @@ impl LateLintPass<'_> for Default {
             // if there are incorrectly assigned fields, do a span_lint_and_note to suggest
             // construction using `Ty { fields, ..Default::default() }`
             if !assigned_fields.is_empty() && !cancel_lint {
-                // take the original assignment as span
-                let stmt = &block.stmts[stmt_idx];
-
-                if let StmtKind::Local(preceding_local) = &stmt.kind {
-                    // filter out fields like `= Default::default()`, because the FRU already covers them
-                    let assigned_fields = assigned_fields
-                        .into_iter()
-                        .filter(|(_, rhs)| !is_expr_default(rhs, cx))
-                        .collect::<Vec<(Symbol, &Expr<'_>)>>();
+                // if all fields of the struct are not assigned, add `.. Default::default()` to the suggestion.
+                let ext_with_default = !variant
+                    .fields
+                    .iter()
+                    .all(|field| assigned_fields.iter().any(|(a, _)| a == &field.ident.name));
 
-                    // if all fields of the struct are not assigned, add `.. Default::default()` to the suggestion.
-                    let ext_with_default = !fields_of_type(binding_type)
-                        .iter()
-                        .all(|field| assigned_fields.iter().any(|(a, _)| a == &field.name));
+                let field_list = assigned_fields
+                    .into_iter()
+                    .map(|(field, rhs)| {
+                        // extract and store the assigned value for help message
+                        let value_snippet = snippet(cx, rhs.span, "..");
+                        format!("{}: {}", field, value_snippet)
+                    })
+                    .collect::<Vec<String>>()
+                    .join(", ");
 
-                    let field_list = assigned_fields
-                        .into_iter()
-                        .map(|(field, rhs)| {
-                            // extract and store the assigned value for help message
-                            let value_snippet = snippet(cx, rhs.span, "..");
-                            format!("{}: {}", field, value_snippet)
-                        })
-                        .collect::<Vec<String>>()
-                        .join(", ");
-
-                    let sugg = if ext_with_default {
-                        if field_list.is_empty() {
-                            format!("{}::default()", binding_type)
-                        } else {
-                            format!("{} {{ {}, ..Default::default() }}", binding_type, field_list)
-                        }
+                let sugg = if ext_with_default {
+                    if field_list.is_empty() {
+                        format!("{}::default()", binding_type)
                     } else {
-                        format!("{} {{ {} }}", binding_type, field_list)
-                    };
+                        format!("{} {{ {}, ..Default::default() }}", binding_type, field_list)
+                    }
+                } else {
+                    format!("{} {{ {} }}", binding_type, field_list)
+                };
 
-                    // span lint once per statement that binds default
-                    span_lint_and_note(
-                        cx,
-                        FIELD_REASSIGN_WITH_DEFAULT,
-                        first_assign.unwrap().span,
-                        "field assignment outside of initializer for an instance created with Default::default()",
-                        Some(preceding_local.span),
-                        &format!(
-                            "consider initializing the variable with `{}` and removing relevant reassignments",
-                            sugg
-                        ),
-                    );
-                    self.reassigned_linted.insert(span);
-                }
+                // span lint once per statement that binds default
+                span_lint_and_note(
+                    cx,
+                    FIELD_REASSIGN_WITH_DEFAULT,
+                    first_assign.unwrap().span,
+                    "field assignment outside of initializer for an instance created with Default::default()",
+                    Some(local.span),
+                    &format!(
+                        "consider initializing the variable with `{}` and removing relevant reassignments",
+                        sugg
+                    ),
+                );
+                self.reassigned_linted.insert(span);
             }
         }
     }
@@ -230,47 +236,6 @@ fn is_expr_default<'tcx>(expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> bool
     }
 }
 
-/// Returns the block indices, identifiers and types of bindings set as `Default::default()`, except
-/// for when the pattern type is a tuple.
-fn enumerate_bindings_using_default<'tcx>(
-    cx: &LateContext<'tcx>,
-    block: &Block<'tcx>,
-) -> Vec<(usize, Symbol, Ty<'tcx>, Span)> {
-    block
-        .stmts
-        .iter()
-        .enumerate()
-        .filter_map(|(idx, stmt)| {
-            if_chain! {
-                // only take `let ...` statements
-                if let StmtKind::Local(ref local) = stmt.kind;
-                // only take bindings to identifiers
-                if let PatKind::Binding(_, _, ident, _) = local.pat.kind;
-                // that are not tuples
-                let ty = cx.typeck_results().pat_ty(local.pat);
-                if !matches!(ty.kind(), ty::Tuple(_));
-                // only when assigning `... = Default::default()`
-                if let Some(ref expr) = local.init;
-                if is_expr_default(expr, cx);
-                then {
-                    Some((idx, ident.name, ty, expr.span))
-                } else {
-                    None
-                }
-            }
-        })
-        .collect()
-}
-
-fn stmt_shadows_binding(this: &Stmt<'_>, shadowed: Symbol) -> bool {
-    if let StmtKind::Local(local) = &this.kind {
-        if let PatKind::Binding(_, _, ident, _) = local.pat.kind {
-            return ident.name == shadowed;
-        }
-    }
-    false
-}
-
 /// Returns the reassigned field and the assigning expression (right-hand side of assign).
 fn field_reassigned_by_stmt<'tcx>(this: &Stmt<'tcx>, binding_name: Symbol) -> Option<(Ident, &'tcx Expr<'tcx>)> {
     if_chain! {
@@ -290,14 +255,3 @@ fn field_reassigned_by_stmt<'tcx>(this: &Stmt<'tcx>, binding_name: Symbol) -> Op
         }
     }
 }
-
-/// Returns the vec of fields for a struct and an empty vec for non-struct ADTs.
-fn fields_of_type(ty: Ty<'_>) -> Vec<Ident> {
-    if let Adt(adt, _) = ty.kind() {
-        if adt.is_struct() {
-            let variant = &adt.non_enum_variant();
-            return variant.fields.iter().map(|f| f.ident).collect();
-        }
-    }
-    vec![]
-}
diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs
new file mode 100644
index 00000000000..1e7e5f53cc2
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs
@@ -0,0 +1,83 @@
+use crate::utils::paths::INTO;
+use crate::utils::{match_def_path, meets_msrv, span_lint_and_help};
+use if_chain::if_chain;
+use rustc_hir as hir;
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_semver::RustcVersion;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+
+const FROM_OVER_INTO_MSRV: RustcVersion = RustcVersion::new(1, 41, 0);
+
+declare_clippy_lint! {
+    /// **What it does:** Searches for implementations of the `Into<..>` trait and suggests to implement `From<..>` instead.
+    ///
+    /// **Why is this bad?** According the std docs implementing `From<..>` is preferred since it gives you `Into<..>` for free where the reverse isn't true.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust
+    /// struct StringWrapper(String);
+    ///
+    /// impl Into<StringWrapper> for String {
+    ///     fn into(self) -> StringWrapper {
+    ///         StringWrapper(self)
+    ///     }
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// struct StringWrapper(String);
+    ///
+    /// impl From<String> for StringWrapper {
+    ///     fn from(s: String) -> StringWrapper {
+    ///         StringWrapper(s)
+    ///     }
+    /// }
+    /// ```
+    pub FROM_OVER_INTO,
+    style,
+    "Warns on implementations of `Into<..>` to use `From<..>`"
+}
+
+pub struct FromOverInto {
+    msrv: Option<RustcVersion>,
+}
+
+impl FromOverInto {
+    #[must_use]
+    pub fn new(msrv: Option<RustcVersion>) -> Self {
+        FromOverInto { msrv }
+    }
+}
+
+impl_lint_pass!(FromOverInto => [FROM_OVER_INTO]);
+
+impl LateLintPass<'_> for FromOverInto {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
+        if !meets_msrv(self.msrv.as_ref(), &FROM_OVER_INTO_MSRV) {
+            return;
+        }
+
+        let impl_def_id = cx.tcx.hir().local_def_id(item.hir_id);
+        if_chain! {
+            if let hir::ItemKind::Impl{ .. } = &item.kind;
+            if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(impl_def_id);
+            if match_def_path(cx, impl_trait_ref.def_id, &INTO);
+
+            then {
+                span_lint_and_help(
+                    cx,
+                    FROM_OVER_INTO,
+                    item.span,
+                    "an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true",
+                    None,
+                    "consider to implement `From` instead",
+                );
+            }
+        }
+    }
+
+    extract_msrv_attr!(LateContext);
+}
diff --git a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
index 3c7880d74ee..ad9b4f357a7 100644
--- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
+++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
@@ -4,6 +4,7 @@ use crate::utils::{snippet_opt, span_lint_and_then};
 use rustc_errors::Applicability;
 use rustc_hir::{Item, ItemKind, VariantData};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_target::abi::LayoutOf;
 
@@ -58,6 +59,9 @@ impl_lint_pass!(LargeEnumVariant => [LARGE_ENUM_VARIANT]);
 
 impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
+        if in_external_macro(cx.tcx.sess, item.span) {
+            return;
+        }
         let did = cx.tcx.hir().local_def_id(item.hir_id);
         if let ItemKind::Enum(ref def, _) = item.kind {
             let ty = cx.tcx.type_of(did);
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 02ba422a2f5..35b057d7b6a 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -207,6 +207,7 @@ mod float_literal;
 mod floating_point_arithmetic;
 mod format;
 mod formatting;
+mod from_over_into;
 mod functions;
 mod future_not_send;
 mod get_last_with_len;
@@ -614,6 +615,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         &formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING,
         &formatting::SUSPICIOUS_ELSE_FORMATTING,
         &formatting::SUSPICIOUS_UNARY_OP_FORMATTING,
+        &from_over_into::FROM_OVER_INTO,
         &functions::DOUBLE_MUST_USE,
         &functions::MUST_USE_CANDIDATE,
         &functions::MUST_USE_UNIT,
@@ -1014,6 +1016,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(move || box checked_conversions::CheckedConversions::new(msrv));
     store.register_late_pass(move || box mem_replace::MemReplace::new(msrv));
     store.register_late_pass(move || box ranges::Ranges::new(msrv));
+    store.register_late_pass(move || box from_over_into::FromOverInto::new(msrv));
     store.register_late_pass(move || box use_self::UseSelf::new(msrv));
     store.register_late_pass(move || box missing_const_for_fn::MissingConstForFn::new(msrv));
 
@@ -1417,6 +1420,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING),
         LintId::of(&formatting::SUSPICIOUS_ELSE_FORMATTING),
         LintId::of(&formatting::SUSPICIOUS_UNARY_OP_FORMATTING),
+        LintId::of(&from_over_into::FROM_OVER_INTO),
         LintId::of(&functions::DOUBLE_MUST_USE),
         LintId::of(&functions::MUST_USE_UNIT),
         LintId::of(&functions::NOT_UNSAFE_PTR_ARG_DEREF),
@@ -1663,6 +1667,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING),
         LintId::of(&formatting::SUSPICIOUS_ELSE_FORMATTING),
         LintId::of(&formatting::SUSPICIOUS_UNARY_OP_FORMATTING),
+        LintId::of(&from_over_into::FROM_OVER_INTO),
         LintId::of(&functions::DOUBLE_MUST_USE),
         LintId::of(&functions::MUST_USE_UNIT),
         LintId::of(&functions::RESULT_UNIT_ERR),
diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs
index b4b4b3dc18d..bb52888883a 100644
--- a/src/tools/clippy/clippy_lints/src/macro_use.rs
+++ b/src/tools/clippy/clippy_lints/src/macro_use.rs
@@ -105,7 +105,7 @@ impl MacroUseImports {
 impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
         if_chain! {
-            if cx.sess().opts.edition == Edition::Edition2018;
+            if cx.sess().opts.edition >= Edition::Edition2018;
             if let hir::ItemKind::Use(path, _kind) = &item.kind;
             if let Some(mac_attr) = item
                 .attrs
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 7b3b450ef93..29439e52c48 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -69,7 +69,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
                     |diag| {
                         if_chain! {
                             if let Some(header_snip) = snippet_opt(cx, header_span);
-                            if let Some(ret_pos) = position_before_rarrow(header_snip.clone());
+                            if let Some(ret_pos) = position_before_rarrow(&header_snip);
                             if let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output);
                             then {
                                 let help = format!("make the function `async` and {}", ret_sugg);
diff --git a/src/tools/clippy/clippy_lints/src/map_err_ignore.rs b/src/tools/clippy/clippy_lints/src/map_err_ignore.rs
index f3c0515b9bc..76fe8e776ea 100644
--- a/src/tools/clippy/clippy_lints/src/map_err_ignore.rs
+++ b/src/tools/clippy/clippy_lints/src/map_err_ignore.rs
@@ -7,7 +7,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
 declare_clippy_lint! {
     /// **What it does:** Checks for instances of `map_err(|_| Some::Enum)`
     ///
-    /// **Why is this bad?** This map_err throws away the original error rather than allowing the enum to contain and report the cause of the error
+    /// **Why is this bad?** This `map_err` throws away the original error rather than allowing the enum to contain and report the cause of the error
     ///
     /// **Known problems:** None.
     ///
@@ -135,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for MapErrIgnore {
                                     body_span,
                                     "`map_err(|_|...` wildcard pattern discards the original error",
                                     None,
-                                    "Consider storing the original error as a source in the new error, or silence this warning using an ignored identifier (`.map_err(|_foo| ...`)",
+                                    "consider storing the original error as a source in the new error, or silence this warning using an ignored identifier (`.map_err(|_foo| ...`)",
                                 );
                             }
                         }
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index dcb643a28ae..c494a713631 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -182,20 +182,6 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
 
         if let ty::Ref(_, ty, Mutability::Not) = ty.kind() {
             if is_type_diagnostic_item(cx, ty, sym::vec_type) {
-                let mut ty_snippet = None;
-                if_chain! {
-                    if let TyKind::Path(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).kind;
-                    if let Some(&PathSegment{args: Some(ref parameters), ..}) = path.segments.last();
-                    then {
-                        let types: Vec<_> = parameters.args.iter().filter_map(|arg| match arg {
-                            GenericArg::Type(ty) => Some(ty),
-                            _ => None,
-                        }).collect();
-                        if types.len() == 1 {
-                            ty_snippet = snippet_opt(cx, types[0].span);
-                        }
-                    }
-                };
                 if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_owned()")]) {
                     span_lint_and_then(
                         cx,
@@ -204,7 +190,7 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
                         "writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used \
                          with non-Vec-based slices.",
                         |diag| {
-                            if let Some(ref snippet) = ty_snippet {
+                            if let Some(ref snippet) = get_only_generic_arg_snippet(cx, arg) {
                                 diag.span_suggestion(
                                     arg.span,
                                     "change this to",
@@ -247,6 +233,33 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
                         },
                     );
                 }
+            } else if match_type(cx, ty, &paths::PATH_BUF) {
+                if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_path_buf()"), ("as_path", "")]) {
+                    span_lint_and_then(
+                        cx,
+                        PTR_ARG,
+                        arg.span,
+                        "writing `&PathBuf` instead of `&Path` involves a new object where a slice will do.",
+                        |diag| {
+                            diag.span_suggestion(
+                                arg.span,
+                                "change this to",
+                                "&Path".into(),
+                                Applicability::Unspecified,
+                            );
+                            for (clonespan, suggestion) in spans {
+                                diag.span_suggestion_short(
+                                    clonespan,
+                                    &snippet_opt(cx, clonespan).map_or("change the call to".into(), |x| {
+                                        Cow::Owned(format!("change `{}` to", x))
+                                    }),
+                                    suggestion.into(),
+                                    Applicability::Unspecified,
+                                );
+                            }
+                        },
+                    );
+                }
             } else if match_type(cx, ty, &paths::COW) {
                 if_chain! {
                     if let TyKind::Rptr(_, MutTy { ref ty, ..} ) = arg.kind;
@@ -309,6 +322,23 @@ fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id:
     }
 }
 
+fn get_only_generic_arg_snippet(cx: &LateContext<'_>, arg: &Ty<'_>) -> Option<String> {
+    if_chain! {
+        if let TyKind::Path(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).kind;
+        if let Some(&PathSegment{args: Some(ref parameters), ..}) = path.segments.last();
+        let types: Vec<_> = parameters.args.iter().filter_map(|arg| match arg {
+            GenericArg::Type(ty) => Some(ty),
+            _ => None,
+        }).collect();
+        if types.len() == 1;
+        then {
+            snippet_opt(cx, types[0].span)
+        } else {
+            None
+        }
+    }
+}
+
 fn get_rptr_lm<'tcx>(ty: &'tcx Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability, Span)> {
     if let TyKind::Rptr(ref lt, ref m) = ty.kind {
         Some((lt, m.mutbl, ty.span))
diff --git a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
index 35b38eca14d..1fc4ff5c2e6 100644
--- a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
@@ -40,7 +40,7 @@ impl EarlyLintPass for SingleComponentPathImports {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
         if_chain! {
             if !in_macro(item.span);
-            if cx.sess.opts.edition == Edition::Edition2018;
+            if cx.sess.opts.edition >= Edition::Edition2018;
             if !item.vis.kind.is_pub();
             if let ItemKind::Use(use_tree) = &item.kind;
             if let segments = &use_tree.prefix.segments;
diff --git a/src/tools/clippy/clippy_lints/src/unused_unit.rs b/src/tools/clippy/clippy_lints/src/unused_unit.rs
index f61fd2ecd73..a31cd5fda84 100644
--- a/src/tools/clippy/clippy_lints/src/unused_unit.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_unit.rs
@@ -120,7 +120,7 @@ fn is_unit_expr(expr: &ast::Expr) -> bool {
 
 fn lint_unneeded_unit_return(cx: &EarlyContext<'_>, ty: &ast::Ty, span: Span) {
     let (ret_span, appl) = if let Ok(fn_source) = cx.sess().source_map().span_to_snippet(span.with_hi(ty.span.hi())) {
-        position_before_rarrow(fn_source).map_or((ty.span, Applicability::MaybeIncorrect), |rpos| {
+        position_before_rarrow(&fn_source).map_or((ty.span, Applicability::MaybeIncorrect), |rpos| {
             (
                 #[allow(clippy::cast_possible_truncation)]
                 ty.span.with_lo(BytePos(span.lo().0 + rpos as u32)),
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 940573e4caa..eac5d0aa3ee 100644
--- a/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs
@@ -501,8 +501,18 @@ pub fn eq_generic_param(l: &GenericParam, r: &GenericParam) -> bool {
         && match (&l.kind, &r.kind) {
             (Lifetime, Lifetime) => true,
             (Type { default: l }, Type { default: r }) => both(l, r, |l, r| eq_ty(l, r)),
-            (Const { ty: lt, kw_span: _ , default: ld}, Const { ty: rt, kw_span: _, default: rd }) =>
-                eq_ty(lt, rt) && both(ld, rd, |ld, rd| eq_anon_const(ld, rd)),
+            (
+                Const {
+                    ty: lt,
+                    kw_span: _,
+                    default: ld,
+                },
+                Const {
+                    ty: rt,
+                    kw_span: _,
+                    default: rd,
+                },
+            ) => eq_ty(lt, rt) && both(ld, rd, |ld, rd| eq_anon_const(ld, rd)),
             _ => false,
         }
         && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r))
@@ -546,7 +556,7 @@ pub fn eq_mac_args(l: &MacArgs, r: &MacArgs) -> bool {
     match (l, r) {
         (Empty, Empty) => true,
         (Delimited(_, ld, lts), Delimited(_, rd, rts)) => ld == rd && lts.eq_unspanned(rts),
-        (Eq(_, lts), Eq(_, rts)) => lts.eq_unspanned(rts),
+        (Eq(_, lt), Eq(_, rt)) => lt.kind == rt.kind,
         _ => false,
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs
index 424856090f2..1c68e837c4a 100644
--- a/src/tools/clippy/clippy_lints/src/utils/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs
@@ -788,8 +788,7 @@ pub fn indent_of<T: LintContext>(cx: &T, span: Span) -> Option<usize> {
 /// fn into3(self)   -> () {}
 ///               ^
 /// ```
-#[allow(clippy::needless_pass_by_value)]
-pub fn position_before_rarrow(s: String) -> Option<usize> {
+pub fn position_before_rarrow(s: &str) -> Option<usize> {
     s.rfind("->").map(|rpos| {
         let mut rpos = rpos;
         let chars: Vec<char> = s.chars().collect();
diff --git a/src/tools/clippy/clippy_lints/src/utils/ptr.rs b/src/tools/clippy/clippy_lints/src/utils/ptr.rs
index bd2c619f000..b330f3d890e 100644
--- a/src/tools/clippy/clippy_lints/src/utils/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/ptr.rs
@@ -72,7 +72,6 @@ impl<'a, 'tcx> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> {
                     }
                 }
             }
-            return;
         }
         walk_expr(self, expr);
     }
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index d2e84132f4e..c579beeae89 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2020-12-20"
+channel = "nightly-2021-01-02"
 components = ["llvm-tools-preview", "rustc-dev", "rust-src", "rustfmt"]
diff --git a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
index f985a15eda2..18324823468 100644
--- a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
@@ -84,3 +84,13 @@ macro_rules! as_conv {
         0u32 as u64
     };
 }
+
+#[macro_export]
+macro_rules! large_enum_variant {
+    () => {
+        enum LargeEnumInMacro {
+            A(i32),
+            B([i32; 8000]),
+        }
+    };
+}
diff --git a/src/tools/clippy/tests/ui/field_reassign_with_default.rs b/src/tools/clippy/tests/ui/field_reassign_with_default.rs
index 79a30c22f95..3e0921022b4 100644
--- a/src/tools/clippy/tests/ui/field_reassign_with_default.rs
+++ b/src/tools/clippy/tests/ui/field_reassign_with_default.rs
@@ -107,4 +107,16 @@ fn main() {
     x.i = side_effect.next();
     x.j = 2;
     x.i = side_effect.next();
+
+    // don't lint - some private fields
+    let mut x = m::F::default();
+    x.a = 1;
+}
+
+mod m {
+    #[derive(Default)]
+    pub struct F {
+        pub a: u64,
+        b: u64,
+    }
 }
diff --git a/src/tools/clippy/tests/ui/field_reassign_with_default.stderr b/src/tools/clippy/tests/ui/field_reassign_with_default.stderr
index c788ebae552..9a2bc778c3f 100644
--- a/src/tools/clippy/tests/ui/field_reassign_with_default.stderr
+++ b/src/tools/clippy/tests/ui/field_reassign_with_default.stderr
@@ -53,7 +53,7 @@ error: field assignment outside of initializer for an instance created with Defa
 LL |     a.i = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: consider initializing the variable with `A::default()` and removing relevant reassignments
+note: consider initializing the variable with `A { i: Default::default(), ..Default::default() }` and removing relevant reassignments
   --> $DIR/field_reassign_with_default.rs:90:5
    |
 LL |     let mut a: A = Default::default();
@@ -65,7 +65,7 @@ error: field assignment outside of initializer for an instance created with Defa
 LL |     a.i = Default::default();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: consider initializing the variable with `A { j: 45, ..Default::default() }` and removing relevant reassignments
+note: consider initializing the variable with `A { i: Default::default(), j: 45 }` and removing relevant reassignments
   --> $DIR/field_reassign_with_default.rs:94:5
    |
 LL |     let mut a: A = Default::default();
diff --git a/src/tools/clippy/tests/ui/from_over_into.rs b/src/tools/clippy/tests/ui/from_over_into.rs
new file mode 100644
index 00000000000..292d0924fb1
--- /dev/null
+++ b/src/tools/clippy/tests/ui/from_over_into.rs
@@ -0,0 +1,21 @@
+#![warn(clippy::from_over_into)]
+
+// this should throw an error
+struct StringWrapper(String);
+
+impl Into<StringWrapper> for String {
+    fn into(self) -> StringWrapper {
+        StringWrapper(self)
+    }
+}
+
+// this is fine
+struct A(String);
+
+impl From<String> for A {
+    fn from(s: String) -> A {
+        A(s)
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/from_over_into.stderr b/src/tools/clippy/tests/ui/from_over_into.stderr
new file mode 100644
index 00000000000..18f56f85432
--- /dev/null
+++ b/src/tools/clippy/tests/ui/from_over_into.stderr
@@ -0,0 +1,15 @@
+error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
+  --> $DIR/from_over_into.rs:6:1
+   |
+LL | / impl Into<StringWrapper> for String {
+LL | |     fn into(self) -> StringWrapper {
+LL | |         StringWrapper(self)
+LL | |     }
+LL | | }
+   | |_^
+   |
+   = note: `-D clippy::from-over-into` implied by `-D warnings`
+   = help: consider to implement `From` instead
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/large_enum_variant.rs b/src/tools/clippy/tests/ui/large_enum_variant.rs
index 852ef5fec0e..d22fee3f27b 100644
--- a/src/tools/clippy/tests/ui/large_enum_variant.rs
+++ b/src/tools/clippy/tests/ui/large_enum_variant.rs
@@ -1,7 +1,12 @@
+// aux-build:macro_rules.rs
+
 #![allow(dead_code)]
 #![allow(unused_variables)]
 #![warn(clippy::large_enum_variant)]
 
+#[macro_use]
+extern crate macro_rules;
+
 enum LargeEnum {
     A(i32),
     B([i32; 8000]),
@@ -51,4 +56,6 @@ enum LargeEnumOk {
     LargeB([i32; 8001]),
 }
 
-fn main() {}
+fn main() {
+    large_enum_variant!();
+}
diff --git a/src/tools/clippy/tests/ui/large_enum_variant.stderr b/src/tools/clippy/tests/ui/large_enum_variant.stderr
index 8ce641a81f2..d39a4d462aa 100644
--- a/src/tools/clippy/tests/ui/large_enum_variant.stderr
+++ b/src/tools/clippy/tests/ui/large_enum_variant.stderr
@@ -1,12 +1,12 @@
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:7:5
+  --> $DIR/large_enum_variant.rs:12:5
    |
 LL |     B([i32; 8000]),
    |     ^^^^^^^^^^^^^^ this variant is 32000 bytes
    |
    = note: `-D clippy::large-enum-variant` implied by `-D warnings`
 note: and the second-largest variant is 4 bytes:
-  --> $DIR/large_enum_variant.rs:6:5
+  --> $DIR/large_enum_variant.rs:11:5
    |
 LL |     A(i32),
    |     ^^^^^^
@@ -16,13 +16,13 @@ LL |     B(Box<[i32; 8000]>),
    |       ^^^^^^^^^^^^^^^^
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:31:5
+  --> $DIR/large_enum_variant.rs:36:5
    |
 LL |     ContainingLargeEnum(LargeEnum),
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this variant is 32004 bytes
    |
 note: and the second-largest variant is 8 bytes:
-  --> $DIR/large_enum_variant.rs:30:5
+  --> $DIR/large_enum_variant.rs:35:5
    |
 LL |     VariantOk(i32, u32),
    |     ^^^^^^^^^^^^^^^^^^^
@@ -32,30 +32,30 @@ LL |     ContainingLargeEnum(Box<LargeEnum>),
    |                         ^^^^^^^^^^^^^^
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:41:5
+  --> $DIR/large_enum_variant.rs:46:5
    |
 LL |     StructLikeLarge { x: [i32; 8000], y: i32 },
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this variant is 32004 bytes
    |
 note: and the second-largest variant is 8 bytes:
-  --> $DIR/large_enum_variant.rs:40:5
+  --> $DIR/large_enum_variant.rs:45:5
    |
 LL |     VariantOk(i32, u32),
    |     ^^^^^^^^^^^^^^^^^^^
 help: consider boxing the large fields to reduce the total size of the enum
-  --> $DIR/large_enum_variant.rs:41:5
+  --> $DIR/large_enum_variant.rs:46:5
    |
 LL |     StructLikeLarge { x: [i32; 8000], y: i32 },
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: large size difference between variants
-  --> $DIR/large_enum_variant.rs:46:5
+  --> $DIR/large_enum_variant.rs:51:5
    |
 LL |     StructLikeLarge2 { x: [i32; 8000] },
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this variant is 32000 bytes
    |
 note: and the second-largest variant is 8 bytes:
-  --> $DIR/large_enum_variant.rs:45:5
+  --> $DIR/large_enum_variant.rs:50:5
    |
 LL |     VariantOk(i32, u32),
    |     ^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/map_err.stderr b/src/tools/clippy/tests/ui/map_err.stderr
index 8ee2941790d..37e87e64de2 100644
--- a/src/tools/clippy/tests/ui/map_err.stderr
+++ b/src/tools/clippy/tests/ui/map_err.stderr
@@ -5,7 +5,7 @@ LL |     println!("{:?}", x.map_err(|_| Errors::Ignored));
    |                                ^^^
    |
    = note: `-D clippy::map-err-ignore` implied by `-D warnings`
-   = help: Consider storing the original error as a source in the new error, or silence this warning using an ignored identifier (`.map_err(|_foo| ...`)
+   = help: consider storing the original error as a source in the new error, or silence this warning using an ignored identifier (`.map_err(|_foo| ...`)
 
 error: aborting due to previous error
 
diff --git a/src/tools/clippy/tests/ui/min_rust_version_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_attr.rs
index 3848bca3207..0f47f1cbc40 100644
--- a/src/tools/clippy/tests/ui/min_rust_version_attr.rs
+++ b/src/tools/clippy/tests/ui/min_rust_version_attr.rs
@@ -57,6 +57,14 @@ pub fn checked_conversion() {
     let _ = value <= (u32::MAX as i64) && value >= 0;
 }
 
+pub struct FromOverInto(String);
+
+impl Into<FromOverInto> for String {
+    fn into(self) -> FromOverInto {
+        FromOverInto(self)
+    }
+}
+
 pub fn filter_map_next() {
     let a = ["1", "lol", "3", "NaN", "5"];
 
diff --git a/src/tools/clippy/tests/ui/min_rust_version_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_attr.stderr
index 34805263104..e3e3b335cbe 100644
--- a/src/tools/clippy/tests/ui/min_rust_version_attr.stderr
+++ b/src/tools/clippy/tests/ui/min_rust_version_attr.stderr
@@ -1,12 +1,12 @@
 error: stripping a prefix manually
-  --> $DIR/min_rust_version_attr.rs:142:24
+  --> $DIR/min_rust_version_attr.rs:150:24
    |
 LL |             assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
    |                        ^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::manual-strip` implied by `-D warnings`
 note: the prefix was tested here
-  --> $DIR/min_rust_version_attr.rs:141:9
+  --> $DIR/min_rust_version_attr.rs:149:9
    |
 LL |         if s.starts_with("hello, ") {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -17,13 +17,13 @@ LL |             assert_eq!(<stripped>.to_uppercase(), "WORLD!");
    |
 
 error: stripping a prefix manually
-  --> $DIR/min_rust_version_attr.rs:154:24
+  --> $DIR/min_rust_version_attr.rs:162:24
    |
 LL |             assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
    |                        ^^^^^^^^^^^^^^^^^^^^
    |
 note: the prefix was tested here
-  --> $DIR/min_rust_version_attr.rs:153:9
+  --> $DIR/min_rust_version_attr.rs:161:9
    |
 LL |         if s.starts_with("hello, ") {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/ptr_arg.rs b/src/tools/clippy/tests/ui/ptr_arg.rs
index 541225e6351..06370dfce65 100644
--- a/src/tools/clippy/tests/ui/ptr_arg.rs
+++ b/src/tools/clippy/tests/ui/ptr_arg.rs
@@ -2,6 +2,7 @@
 #![warn(clippy::ptr_arg)]
 
 use std::borrow::Cow;
+use std::path::PathBuf;
 
 fn do_vec(x: &Vec<i64>) {
     //Nothing here
@@ -21,6 +22,15 @@ fn do_str_mut(x: &mut String) {
     //Nothing here either
 }
 
+fn do_path(x: &PathBuf) {
+    //Nothing here either
+}
+
+fn do_path_mut(x: &mut PathBuf) {
+    // no error here
+    //Nothing here either
+}
+
 fn main() {}
 
 trait Foo {
@@ -55,6 +65,14 @@ fn str_cloned(x: &String) -> String {
     x.clone()
 }
 
+fn path_cloned(x: &PathBuf) -> PathBuf {
+    let a = x.clone();
+    let b = x.clone();
+    let c = b.clone();
+    let d = a.clone().clone().clone();
+    x.clone()
+}
+
 fn false_positive_capacity(x: &Vec<u8>, y: &String) {
     let a = x.capacity();
     let b = y.clone();
@@ -87,10 +105,12 @@ impl Foo2 for String {
 // Check that the allow attribute on parameters is honored
 mod issue_5644 {
     use std::borrow::Cow;
+    use std::path::PathBuf;
 
     fn allowed(
         #[allow(clippy::ptr_arg)] _v: &Vec<u32>,
         #[allow(clippy::ptr_arg)] _s: &String,
+        #[allow(clippy::ptr_arg)] _p: &PathBuf,
         #[allow(clippy::ptr_arg)] _c: &Cow<[i32]>,
     ) {
     }
@@ -100,6 +120,7 @@ mod issue_5644 {
         fn allowed(
             #[allow(clippy::ptr_arg)] _v: &Vec<u32>,
             #[allow(clippy::ptr_arg)] _s: &String,
+            #[allow(clippy::ptr_arg)] _p: &PathBuf,
             #[allow(clippy::ptr_arg)] _c: &Cow<[i32]>,
         ) {
         }
@@ -109,8 +130,28 @@ mod issue_5644 {
         fn allowed(
             #[allow(clippy::ptr_arg)] _v: &Vec<u32>,
             #[allow(clippy::ptr_arg)] _s: &String,
+            #[allow(clippy::ptr_arg)] _p: &PathBuf,
             #[allow(clippy::ptr_arg)] _c: &Cow<[i32]>,
         ) {
         }
     }
 }
+
+mod issue6509 {
+    use std::path::PathBuf;
+
+    fn foo_vec(vec: &Vec<u8>) {
+        let _ = vec.clone().pop();
+        let _ = vec.clone().clone();
+    }
+
+    fn foo_path(path: &PathBuf) {
+        let _ = path.clone().pop();
+        let _ = path.clone().clone();
+    }
+
+    fn foo_str(str: &PathBuf) {
+        let _ = str.clone().pop();
+        let _ = str.clone().clone();
+    }
+}
diff --git a/src/tools/clippy/tests/ui/ptr_arg.stderr b/src/tools/clippy/tests/ui/ptr_arg.stderr
index 314f23497f9..708318bbe29 100644
--- a/src/tools/clippy/tests/ui/ptr_arg.stderr
+++ b/src/tools/clippy/tests/ui/ptr_arg.stderr
@@ -1,5 +1,5 @@
 error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices.
-  --> $DIR/ptr_arg.rs:6:14
+  --> $DIR/ptr_arg.rs:7:14
    |
 LL | fn do_vec(x: &Vec<i64>) {
    |              ^^^^^^^^^ help: change this to: `&[i64]`
@@ -7,19 +7,25 @@ LL | fn do_vec(x: &Vec<i64>) {
    = note: `-D clippy::ptr-arg` implied by `-D warnings`
 
 error: writing `&String` instead of `&str` involves a new object where a slice will do.
-  --> $DIR/ptr_arg.rs:15:14
+  --> $DIR/ptr_arg.rs:16:14
    |
 LL | fn do_str(x: &String) {
    |              ^^^^^^^ help: change this to: `&str`
 
+error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do.
+  --> $DIR/ptr_arg.rs:25:15
+   |
+LL | fn do_path(x: &PathBuf) {
+   |               ^^^^^^^^ help: change this to: `&Path`
+
 error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices.
-  --> $DIR/ptr_arg.rs:28:18
+  --> $DIR/ptr_arg.rs:38:18
    |
 LL |     fn do_vec(x: &Vec<i64>);
    |                  ^^^^^^^^^ help: change this to: `&[i64]`
 
 error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices.
-  --> $DIR/ptr_arg.rs:41:14
+  --> $DIR/ptr_arg.rs:51:14
    |
 LL | fn cloned(x: &Vec<u8>) -> Vec<u8> {
    |              ^^^^^^^^
@@ -38,7 +44,7 @@ LL |     x.to_owned()
    |
 
 error: writing `&String` instead of `&str` involves a new object where a slice will do.
-  --> $DIR/ptr_arg.rs:50:18
+  --> $DIR/ptr_arg.rs:60:18
    |
 LL | fn str_cloned(x: &String) -> String {
    |                  ^^^^^^^
@@ -60,8 +66,31 @@ help: change `x.clone()` to
 LL |     x.to_string()
    |
 
+error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do.
+  --> $DIR/ptr_arg.rs:68:19
+   |
+LL | fn path_cloned(x: &PathBuf) -> PathBuf {
+   |                   ^^^^^^^^
+   |
+help: change this to
+   |
+LL | fn path_cloned(x: &Path) -> PathBuf {
+   |                   ^^^^^
+help: change `x.clone()` to
+   |
+LL |     let a = x.to_path_buf();
+   |             ^^^^^^^^^^^^^^^
+help: change `x.clone()` to
+   |
+LL |     let b = x.to_path_buf();
+   |             ^^^^^^^^^^^^^^^
+help: change `x.clone()` to
+   |
+LL |     x.to_path_buf()
+   |
+
 error: writing `&String` instead of `&str` involves a new object where a slice will do.
-  --> $DIR/ptr_arg.rs:58:44
+  --> $DIR/ptr_arg.rs:76:44
    |
 LL | fn false_positive_capacity(x: &Vec<u8>, y: &String) {
    |                                            ^^^^^^^
@@ -80,10 +109,67 @@ LL |     let c = y;
    |             ^
 
 error: using a reference to `Cow` is not recommended.
-  --> $DIR/ptr_arg.rs:72:25
+  --> $DIR/ptr_arg.rs:90:25
    |
 LL | fn test_cow_with_ref(c: &Cow<[i32]>) {}
    |                         ^^^^^^^^^^^ help: change this to: `&[i32]`
 
-error: aborting due to 7 previous errors
+error: writing `&Vec<_>` instead of `&[_]` involves one more reference and cannot be used with non-Vec-based slices.
+  --> $DIR/ptr_arg.rs:143:21
+   |
+LL |     fn foo_vec(vec: &Vec<u8>) {
+   |                     ^^^^^^^^
+   |
+help: change this to
+   |
+LL |     fn foo_vec(vec: &[u8]) {
+   |                     ^^^^^
+help: change `vec.clone()` to
+   |
+LL |         let _ = vec.to_owned().pop();
+   |                 ^^^^^^^^^^^^^^
+help: change `vec.clone()` to
+   |
+LL |         let _ = vec.to_owned().clone();
+   |                 ^^^^^^^^^^^^^^
+
+error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do.
+  --> $DIR/ptr_arg.rs:148:23
+   |
+LL |     fn foo_path(path: &PathBuf) {
+   |                       ^^^^^^^^
+   |
+help: change this to
+   |
+LL |     fn foo_path(path: &Path) {
+   |                       ^^^^^
+help: change `path.clone()` to
+   |
+LL |         let _ = path.to_path_buf().pop();
+   |                 ^^^^^^^^^^^^^^^^^^
+help: change `path.clone()` to
+   |
+LL |         let _ = path.to_path_buf().clone();
+   |                 ^^^^^^^^^^^^^^^^^^
+
+error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do.
+  --> $DIR/ptr_arg.rs:153:21
+   |
+LL |     fn foo_str(str: &PathBuf) {
+   |                     ^^^^^^^^
+   |
+help: change this to
+   |
+LL |     fn foo_str(str: &Path) {
+   |                     ^^^^^
+help: change `str.clone()` to
+   |
+LL |         let _ = str.to_path_buf().pop();
+   |                 ^^^^^^^^^^^^^^^^^
+help: change `str.clone()` to
+   |
+LL |         let _ = str.to_path_buf().clone();
+   |                 ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unused_unit.fixed b/src/tools/clippy/tests/ui/unused_unit.fixed
index 7afc5361356..a192ebde3eb 100644
--- a/src/tools/clippy/tests/ui/unused_unit.fixed
+++ b/src/tools/clippy/tests/ui/unused_unit.fixed
@@ -11,6 +11,7 @@
 
 #![deny(clippy::unused_unit)]
 #![allow(dead_code)]
+#![allow(clippy::from_over_into)]
 
 struct Unitter;
 impl Unitter {
diff --git a/src/tools/clippy/tests/ui/unused_unit.rs b/src/tools/clippy/tests/ui/unused_unit.rs
index 96cef1ed5a5..96041a7dd85 100644
--- a/src/tools/clippy/tests/ui/unused_unit.rs
+++ b/src/tools/clippy/tests/ui/unused_unit.rs
@@ -11,6 +11,7 @@
 
 #![deny(clippy::unused_unit)]
 #![allow(dead_code)]
+#![allow(clippy::from_over_into)]
 
 struct Unitter;
 impl Unitter {
diff --git a/src/tools/clippy/tests/ui/unused_unit.stderr b/src/tools/clippy/tests/ui/unused_unit.stderr
index c45634c2b6d..02038b5fb6b 100644
--- a/src/tools/clippy/tests/ui/unused_unit.stderr
+++ b/src/tools/clippy/tests/ui/unused_unit.stderr
@@ -1,5 +1,5 @@
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:18:28
+  --> $DIR/unused_unit.rs:19:28
    |
 LL |     pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
    |                            ^^^^^^ help: remove the `-> ()`
@@ -11,109 +11,109 @@ LL | #![deny(clippy::unused_unit)]
    |         ^^^^^^^^^^^^^^^^^^^
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:19:18
+  --> $DIR/unused_unit.rs:20:18
    |
 LL |     where G: Fn() -> () {
    |                  ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:18:58
+  --> $DIR/unused_unit.rs:19:58
    |
 LL |     pub fn get_unit<F: Fn() -> (), G>(&self, f: F, _g: G) -> ()
    |                                                          ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:20:26
+  --> $DIR/unused_unit.rs:21:26
    |
 LL |         let _y: &dyn Fn() -> () = &f;
    |                          ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:27:18
+  --> $DIR/unused_unit.rs:28:18
    |
 LL |     fn into(self) -> () {
    |                  ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit expression
-  --> $DIR/unused_unit.rs:28:9
+  --> $DIR/unused_unit.rs:29:9
    |
 LL |         ()
    |         ^^ help: remove the final `()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:33:29
+  --> $DIR/unused_unit.rs:34:29
    |
 LL |     fn redundant<F: FnOnce() -> (), G, H>(&self, _f: F, _g: G, _h: H)
    |                             ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:35:19
+  --> $DIR/unused_unit.rs:36:19
    |
 LL |         G: FnMut() -> (),
    |                   ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:36:16
+  --> $DIR/unused_unit.rs:37:16
    |
 LL |         H: Fn() -> ();
    |                ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:40:29
+  --> $DIR/unused_unit.rs:41:29
    |
 LL |     fn redundant<F: FnOnce() -> (), G, H>(&self, _f: F, _g: G, _h: H)
    |                             ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:42:19
+  --> $DIR/unused_unit.rs:43:19
    |
 LL |         G: FnMut() -> (),
    |                   ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:43:16
+  --> $DIR/unused_unit.rs:44:16
    |
 LL |         H: Fn() -> () {}
    |                ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:46:17
+  --> $DIR/unused_unit.rs:47:17
    |
 LL | fn return_unit() -> () { () }
    |                 ^^^^^^ help: remove the `-> ()`
 
 error: unneeded unit expression
-  --> $DIR/unused_unit.rs:46:26
+  --> $DIR/unused_unit.rs:47:26
    |
 LL | fn return_unit() -> () { () }
    |                          ^^ help: remove the final `()`
 
 error: unneeded `()`
-  --> $DIR/unused_unit.rs:56:14
+  --> $DIR/unused_unit.rs:57:14
    |
 LL |         break();
    |              ^^ help: remove the `()`
 
 error: unneeded `()`
-  --> $DIR/unused_unit.rs:58:11
+  --> $DIR/unused_unit.rs:59:11
    |
 LL |     return();
    |           ^^ help: remove the `()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:75:10
+  --> $DIR/unused_unit.rs:76:10
    |
 LL | fn test()->(){}
    |          ^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:78:11
+  --> $DIR/unused_unit.rs:79:11
    |
 LL | fn test2() ->(){}
    |           ^^^^^ help: remove the `-> ()`
 
 error: unneeded unit return type
-  --> $DIR/unused_unit.rs:81:11
+  --> $DIR/unused_unit.rs:82:11
    |
 LL | fn test3()-> (){}
    |           ^^^^^ help: remove the `-> ()`
diff --git a/src/tools/clippy/tests/versioncheck.rs b/src/tools/clippy/tests/versioncheck.rs
index f5d03c645df..76b6126c76c 100644
--- a/src/tools/clippy/tests/versioncheck.rs
+++ b/src/tools/clippy/tests/versioncheck.rs
@@ -1,3 +1,6 @@
+#![allow(clippy::single_match_else)]
+use rustc_tools_util::VersionInfo;
+
 #[test]
 fn check_that_clippy_lints_has_the_same_version_as_clippy() {
     let clippy_meta = cargo_metadata::MetadataCommand::new()
@@ -17,3 +20,54 @@ fn check_that_clippy_lints_has_the_same_version_as_clippy() {
         }
     }
 }
+
+#[test]
+fn check_that_clippy_has_the_same_major_version_as_rustc() {
+    let clippy_version = rustc_tools_util::get_version_info!();
+    let clippy_major = clippy_version.major;
+    let clippy_minor = clippy_version.minor;
+    let clippy_patch = clippy_version.patch;
+
+    // get the rustc version either from the rustc installed with the toolchain file or from
+    // `RUSTC_REAL` if Clippy is build in the Rust repo with `./x.py`.
+    let rustc = std::env::var("RUSTC_REAL").unwrap_or_else(|_| "rustc".to_string());
+    let rustc_version = String::from_utf8(
+        std::process::Command::new(&rustc)
+            .arg("--version")
+            .output()
+            .expect("failed to run `rustc --version`")
+            .stdout,
+    )
+    .unwrap();
+    // extract "1 XX 0" from "rustc 1.XX.0-nightly (<commit> <date>)"
+    let vsplit: Vec<&str> = rustc_version
+        .split(' ')
+        .nth(1)
+        .unwrap()
+        .split('-')
+        .next()
+        .unwrap()
+        .split('.')
+        .collect();
+    match vsplit.as_slice() {
+        [rustc_major, rustc_minor, _rustc_patch] => {
+            // clippy 0.1.XX should correspond to rustc 1.XX.0
+            assert_eq!(clippy_major, 0); // this will probably stay the same for a long time
+            assert_eq!(
+                clippy_minor.to_string(),
+                *rustc_major,
+                "clippy minor version does not equal rustc major version"
+            );
+            assert_eq!(
+                clippy_patch.to_string(),
+                *rustc_minor,
+                "clippy patch version does not equal rustc minor version"
+            );
+            // do not check rustc_patch because when a stable-patch-release is made (like 1.50.2),
+            // we don't want our tests failing suddenly
+        },
+        _ => {
+            panic!("Failed to parse rustc version: {:?}", vsplit);
+        },
+    };
+}
diff --git a/src/tools/clippy/util/gh-pages/index.html b/src/tools/clippy/util/gh-pages/index.html
index 428708136cb..1852fb6640e 100644
--- a/src/tools/clippy/util/gh-pages/index.html
+++ b/src/tools/clippy/util/gh-pages/index.html
@@ -77,7 +77,7 @@
                     <div class="col-md-12 form-horizontal">
                         <div class="input-group">
                             <label class="input-group-addon" id="filter-label" for="filter-input">Filter:</label>
-                            <input type="text" class="form-control" placeholder="Keywords or search string" id="filter-input" ng-model="search" />
+                            <input type="text" class="form-control" placeholder="Keywords or search string" id="filter-input" ng-model="search" ng-model-options="{debounce: 50}"/>
                             <span class="input-group-btn">
                                 <button class="btn btn-default" type="button" ng-click="search = ''">
                                     Clear
@@ -119,6 +119,7 @@
                             {{title}}
                         </h4>
                         <div class="list-group-item-text" ng-bind-html="text | markdown"></div>
+                        <a ng-if="title == 'Known problems'" href="https://github.com/rust-lang/rust-clippy/issues?q=is%3Aissue+is%3Aopen+{{lint.id}}">Search on GitHub</a>
                     </li>
                 </ul>
             </article>
@@ -180,6 +181,22 @@
             }
         }
 
+        function searchLint(lint, term) {
+            for (const field in lint.docs) {
+                // Continue if it's not a property
+                if (!lint.docs.hasOwnProperty(field)) {
+                    continue;
+                }
+
+                // Return if not found
+                if (lint.docs[field].toLowerCase().indexOf(term) !== -1) {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
         angular.module("clippy", [])
         .filter('markdown', function ($sce) {
             return function (text) {
@@ -216,40 +233,31 @@
             };
 
             $scope.bySearch = function (lint, index, array) {
-                let search_str = $scope.search;
+                let searchStr = $scope.search;
                 // It can be `null` I haven't missed this value 
-                if (search_str == null || search_str.length == 0) {
+                if (searchStr == null || searchStr.length < 3) {
                     return true;
                 }
-                search_str = search_str.toLowerCase();
+                searchStr = searchStr.toLowerCase();
 
                 // Search by id
-                let id_search = search_str.trim().replace(/(\-| )/g, "_");
-                if (lint.id.includes(id_search)) {
+                if (lint.id.indexOf(searchStr.replace("-", "_")) !== -1) {
                     return true;
                 }
 
                 // Search the description
                 // The use of `for`-loops instead of `foreach` enables us to return early 
-                let search_lint = (lint, therm) => {
-                    for (const field in lint.docs) {
-                        // Continue if it's not a property
-                        if (!lint.docs.hasOwnProperty(field)) {
-                            continue;
-                        }
-
-                        // Return if not found
-                        if (lint.docs[field].toLowerCase().includes(therm)) {
-                            return true;
-                        }
+                let terms = searchStr.split(" ");
+                for (index = 0; index < terms.length; index++) {
+                    if (lint.id.indexOf(terms[index]) !== -1) {
+                        continue;
                     }
-                    return false;
-                };
-                let therms = search_str.split(" ");
-                for (index = 0; index < therms.length; index++) {
-                    if (!search_lint(lint, therms[index])) {
-                        return false;
+
+                    if (searchLint(lint, terms[index])) {
+                        continue;
                     }
+
+                    return false;
                 }
 
                 return true;
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index 4f77e719fba..1647df8044c 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -82,6 +82,7 @@ const ARCH_TABLE: &[(&str, &str)] = &[
 ];
 
 pub const ASAN_SUPPORTED_TARGETS: &[&str] = &[
+    "aarch64-apple-darwin",
     "aarch64-fuchsia",
     "aarch64-unknown-linux-gnu",
     "x86_64-apple-darwin",
@@ -90,13 +91,18 @@ pub const ASAN_SUPPORTED_TARGETS: &[&str] = &[
     "x86_64-unknown-linux-gnu",
 ];
 
-pub const LSAN_SUPPORTED_TARGETS: &[&str] =
-    &["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
+pub const LSAN_SUPPORTED_TARGETS: &[&str] = &[
+    "aarch64-apple-darwin",
+    "aarch64-unknown-linux-gnu",
+    "x86_64-apple-darwin",
+    "x86_64-unknown-linux-gnu",
+];
 
 pub const MSAN_SUPPORTED_TARGETS: &[&str] =
     &["aarch64-unknown-linux-gnu", "x86_64-unknown-freebsd", "x86_64-unknown-linux-gnu"];
 
 pub const TSAN_SUPPORTED_TARGETS: &[&str] = &[
+    "aarch64-apple-darwin",
     "aarch64-unknown-linux-gnu",
     "x86_64-apple-darwin",
     "x86_64-unknown-freebsd",
diff --git a/src/tools/miri b/src/tools/miri
-Subproject 2065b52dfef3cd5a5216e65c21a056a69574bdd
+Subproject a09f8b0c06c6bb051bd1e104c6be56fbe51f3d8
diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml
index 99310157a64..8e17f291908 100644
--- a/src/tools/rustbook/Cargo.toml
+++ b/src/tools/rustbook/Cargo.toml
@@ -10,6 +10,6 @@ clap = "2.25.0"
 env_logger = "0.7.1"
 
 [dependencies.mdbook]
-version = "0.4.3"
+version = "0.4.5"
 default-features = false
 features = ["search"]