about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes8
-rw-r--r--Cargo.lock141
-rw-r--r--compiler/rustc_ast/src/ast_like.rs3
-rw-r--r--compiler/rustc_ast/src/lib.rs2
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs5
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs19
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs1
-rw-r--r--compiler/rustc_ast_passes/src/lib.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/test.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/archive.rs9
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs17
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs16
-rw-r--r--compiler/rustc_codegen_cranelift/src/toolchain.rs89
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/back/archive.rs83
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs251
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs13
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs76
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/mod.rs44
-rw-r--r--compiler/rustc_codegen_ssa/Cargo.toml4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/archive.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs588
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs144
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs40
-rw-r--r--compiler/rustc_codegen_ssa/src/back/rpath.rs27
-rw-r--r--compiler/rustc_codegen_ssa/src/back/rpath/tests.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs20
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs17
-rw-r--r--compiler/rustc_codegen_ssa/src/coverageinfo/map.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs59
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs17
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/analyze.rs79
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/backend.rs13
-rw-r--r--compiler/rustc_data_structures/src/lib.rs4
-rw-r--r--compiler/rustc_data_structures/src/obligation_forest/mod.rs24
-rw-r--r--compiler/rustc_data_structures/src/stable_hasher.rs32
-rw-r--r--compiler/rustc_data_structures/src/sync.rs62
-rw-r--r--compiler/rustc_data_structures/src/tagged_ptr.rs10
-rw-r--r--compiler/rustc_data_structures/src/vec_map.rs155
-rw-r--r--compiler/rustc_data_structures/src/vec_map/tests.rs48
-rw-r--r--compiler/rustc_driver/src/lib.rs32
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs32
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0316.md32
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0759.md6
-rw-r--r--compiler/rustc_errors/src/json.rs4
-rw-r--r--compiler/rustc_errors/src/lib.rs2
-rw-r--r--compiler/rustc_expand/src/base.rs6
-rw-r--r--compiler/rustc_expand/src/expand.rs144
-rw-r--r--compiler/rustc_expand/src/lib.rs2
-rw-r--r--compiler/rustc_expand/src/mbe/macro_parser.rs9
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs6
-rw-r--r--compiler/rustc_feature/src/active.rs4
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs4
-rw-r--r--compiler/rustc_feature/src/removed.rs4
-rw-r--r--compiler/rustc_hir/src/definitions.rs22
-rw-r--r--compiler/rustc_hir/src/hir.rs8
-rw-r--r--compiler/rustc_hir/src/lib.rs2
-rw-r--r--compiler/rustc_hir/src/tests.rs13
-rw-r--r--compiler/rustc_incremental/src/persist/dirty_clean.rs128
-rw-r--r--compiler/rustc_incremental/src/persist/fs.rs19
-rw-r--r--compiler/rustc_incremental/src/persist/load.rs8
-rw-r--r--compiler/rustc_incremental/src/persist/save.rs1
-rw-r--r--compiler/rustc_index/src/lib.rs2
-rw-r--r--compiler/rustc_index/src/vec.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs7
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs25
-rw-r--r--compiler/rustc_infer/src/infer/equate.rs1
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/glb.rs3
-rw-r--r--compiler/rustc_infer/src/infer/lub.rs3
-rw-r--r--compiler/rustc_infer/src/infer/nll_relate/mod.rs34
-rw-r--r--compiler/rustc_infer/src/infer/sub.rs1
-rw-r--r--compiler/rustc_infer/src/lib.rs2
-rw-r--r--compiler/rustc_interface/src/lib.rs1
-rw-r--r--compiler/rustc_interface/src/passes.rs20
-rw-r--r--compiler/rustc_interface/src/queries.rs27
-rw-r--r--compiler/rustc_interface/src/util.rs91
-rw-r--r--compiler/rustc_lint/src/builtin.rs2
-rw-r--r--compiler/rustc_lint/src/context.rs39
-rw-r--r--compiler/rustc_lint/src/levels.rs16
-rw-r--r--compiler/rustc_lint/src/lib.rs2
-rw-r--r--compiler/rustc_lint/src/types.rs65
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs1
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs6
-rw-r--r--compiler/rustc_llvm/build.rs1
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp87
-rw-r--r--compiler/rustc_llvm/src/lib.rs8
-rw-r--r--compiler/rustc_macros/src/serialize.rs18
-rw-r--r--compiler/rustc_metadata/src/creader.rs19
-rw-r--r--compiler/rustc_metadata/src/lib.rs2
-rw-r--r--compiler/rustc_metadata/src/locator.rs8
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs72
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs14
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs26
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs5
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs2
-rw-r--r--compiler/rustc_middle/src/dep_graph/dep_node.rs2
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs12
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs4
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs1
-rw-r--r--compiler/rustc_middle/src/lib.rs2
-rw-r--r--compiler/rustc_middle/src/lint.rs30
-rw-r--r--compiler/rustc_middle/src/middle/cstore.rs12
-rw-r--r--compiler/rustc_middle/src/middle/exported_symbols.rs6
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs1
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs6
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs15
-rw-r--r--compiler/rustc_middle/src/mir/query.rs5
-rw-r--r--compiler/rustc_middle/src/query/mod.rs19
-rw-r--r--compiler/rustc_middle/src/ty/_match.rs1
-rw-r--r--compiler/rustc_middle/src/ty/context.rs60
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs1
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs9
-rw-r--r--compiler/rustc_middle/src/ty/list.rs2
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs34
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/query/on_disk_cache.rs50
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs85
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs67
-rw-r--r--compiler/rustc_mir/src/borrow_check/constraints/graph.rs68
-rw-r--r--compiler/rustc_mir/src/borrow_check/constraints/mod.rs31
-rw-r--r--compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs14
-rw-r--r--compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs20
-rw-r--r--compiler/rustc_mir/src/borrow_check/mod.rs12
-rw-r--r--compiler/rustc_mir/src/borrow_check/nll.rs9
-rw-r--r--compiler/rustc_mir/src/borrow_check/places_conflict.rs19
-rw-r--r--compiler/rustc_mir/src/borrow_check/region_infer/dump_mir.rs2
-rw-r--r--compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs12
-rw-r--r--compiler/rustc_mir/src/borrow_check/region_infer/mod.rs107
-rw-r--r--compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs22
-rw-r--r--compiler/rustc_mir/src/borrow_check/type_check/constraint_conversion.rs1
-rw-r--r--compiler/rustc_mir/src/borrow_check/type_check/liveness/mod.rs2
-rw-r--r--compiler/rustc_mir/src/borrow_check/type_check/mod.rs56
-rw-r--r--compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs8
-rw-r--r--compiler/rustc_mir/src/dataflow/move_paths/builder.rs6
-rw-r--r--compiler/rustc_mir/src/interpret/intrinsics/type_name.rs9
-rw-r--r--compiler/rustc_mir/src/lib.rs5
-rw-r--r--compiler/rustc_mir/src/transform/check_consts/validation.rs27
-rw-r--r--compiler/rustc_mir/src/transform/check_unsafety.rs8
-rw-r--r--compiler/rustc_mir/src/transform/const_goto.rs2
-rw-r--r--compiler/rustc_mir/src/transform/coverage/debug.rs1
-rw-r--r--compiler/rustc_mir/src/transform/deduplicate_blocks.rs2
-rw-r--r--compiler/rustc_mir/src/transform/dest_prop.rs15
-rw-r--r--compiler/rustc_mir/src/transform/early_otherwise_branch.rs2
-rw-r--r--compiler/rustc_mir/src/transform/generator.rs4
-rw-r--r--compiler/rustc_mir/src/transform/inline.rs2
-rw-r--r--compiler/rustc_mir/src/transform/instcombine.rs21
-rw-r--r--compiler/rustc_mir/src/transform/match_branches.rs2
-rw-r--r--compiler/rustc_mir/src/transform/multiple_return_terminators.rs2
-rw-r--r--compiler/rustc_mir/src/transform/promote_consts.rs6
-rw-r--r--compiler/rustc_mir/src/transform/remove_unneeded_drops.rs2
-rw-r--r--compiler/rustc_mir/src/transform/remove_zsts.rs58
-rw-r--r--compiler/rustc_mir/src/transform/simplify.rs85
-rw-r--r--compiler/rustc_mir/src/transform/simplify_try.rs2
-rw-r--r--compiler/rustc_mir/src/transform/unreachable_prop.rs2
-rw-r--r--compiler/rustc_mir/src/transform/validate.rs22
-rw-r--r--compiler/rustc_mir/src/util/generic_graph.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs34
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs17
-rw-r--r--compiler/rustc_mir_build/src/lib.rs3
-rw-r--r--compiler/rustc_parse/src/lib.rs1
-rw-r--r--compiler/rustc_parse/src/parser/attr_wrapper.rs10
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs12
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs1
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs17
-rw-r--r--compiler/rustc_parse/src/parser/path.rs84
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs23
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs1
-rw-r--r--compiler/rustc_passes/src/check_attr.rs29
-rw-r--r--compiler/rustc_passes/src/lib.rs2
-rw-r--r--compiler/rustc_query_impl/src/lib.rs4
-rw-r--r--compiler/rustc_query_impl/src/profiling_support.rs2
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs80
-rw-r--r--compiler/rustc_query_system/src/dep_graph/serialized.rs12
-rw-r--r--compiler/rustc_query_system/src/lib.rs4
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs2
-rw-r--r--compiler/rustc_resolve/src/late.rs6
-rw-r--r--compiler/rustc_resolve/src/late/lifetimes.rs10
-rw-r--r--compiler/rustc_resolve/src/lib.rs14
-rw-r--r--compiler/rustc_save_analysis/src/dump_visitor.rs7
-rw-r--r--compiler/rustc_save_analysis/src/lib.rs19
-rw-r--r--compiler/rustc_serialize/src/collection_impls.rs48
-rw-r--r--compiler/rustc_serialize/src/json.rs171
-rw-r--r--compiler/rustc_serialize/src/lib.rs3
-rw-r--r--compiler/rustc_serialize/src/serialize.rs133
-rw-r--r--compiler/rustc_session/src/config.rs72
-rw-r--r--compiler/rustc_session/src/options.rs1
-rw-r--r--compiler/rustc_session/src/session.rs28
-rw-r--r--compiler/rustc_span/src/crate_disambiguator.rs35
-rw-r--r--compiler/rustc_span/src/def_id.rs118
-rw-r--r--compiler/rustc_span/src/lib.rs72
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs7
-rw-r--r--compiler/rustc_symbol_mangling/src/lib.rs8
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs6
-rw-r--r--compiler/rustc_target/src/abi/call/bpf.rs31
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs2
-rw-r--r--compiler/rustc_target/src/abi/mod.rs16
-rw-r--r--compiler/rustc_target/src/asm/bpf.rs129
-rw-r--r--compiler/rustc_target/src/asm/mod.rs25
-rw-r--r--compiler/rustc_target/src/lib.rs2
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_ios.rs1
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs1
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs1
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_tvos.rs1
-rw-r--r--compiler/rustc_target/src/spec/apple_base.rs1
-rw-r--r--compiler/rustc_target/src/spec/apple_sdk_base.rs1
-rw-r--r--compiler/rustc_target/src/spec/bpf_base.rs42
-rw-r--r--compiler/rustc_target/src/spec/bpfeb_unknown_none.rs12
-rw-r--r--compiler/rustc_target/src/spec/bpfel_unknown_none.rs12
-rw-r--r--compiler/rustc_target/src/spec/mod.rs7
-rw-r--r--compiler/rustc_target/src/spec/msp430_none_elf.rs1
-rw-r--r--compiler/rustc_target/src/spec/wasm_base.rs7
-rw-r--r--compiler/rustc_trait_selection/src/autoderef.rs4
-rw-r--r--compiler/rustc_trait_selection/src/opaque_types.rs85
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs4
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs8
-rw-r--r--compiler/rustc_type_ir/src/lib.rs1
-rw-r--r--compiler/rustc_typeck/src/check/check.rs21
-rw-r--r--compiler/rustc_typeck/src/check/demand.rs52
-rw-r--r--compiler/rustc_typeck/src/check/dropck.rs1
-rw-r--r--compiler/rustc_typeck/src/check/inherited.rs5
-rw-r--r--compiler/rustc_typeck/src/check/place_op.rs2
-rw-r--r--compiler/rustc_typeck/src/check/upvar.rs5
-rw-r--r--compiler/rustc_typeck/src/check/writeback.rs34
-rw-r--r--compiler/rustc_typeck/src/collect.rs21
-rw-r--r--compiler/rustc_typeck/src/collect/type_of.rs28
-rw-r--r--config.toml.example2
-rw-r--r--library/alloc/benches/vec.rs10
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs13
-rw-r--r--library/alloc/src/collections/vec_deque/pair_slices.rs3
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/string.rs111
-rw-r--r--library/alloc/src/vec/cow.rs18
-rw-r--r--library/alloc/src/vec/mod.rs8
-rw-r--r--library/alloc/src/vec/spec_from_iter.rs35
-rw-r--r--library/alloc/src/vec/splice.rs2
-rw-r--r--library/alloc/tests/lib.rs1
-rw-r--r--library/alloc/tests/vec.rs10
-rw-r--r--library/core/src/array/mod.rs4
-rw-r--r--library/core/src/char/methods.rs4
-rw-r--r--library/core/src/intrinsics.rs337
-rw-r--r--library/core/src/iter/adapters/take.rs23
-rw-r--r--library/core/src/iter/adapters/zip.rs2
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/core/src/mem/mod.rs6
-rw-r--r--library/core/src/num/f32.rs4
-rw-r--r--library/core/src/num/f64.rs4
-rw-r--r--library/core/src/ops/range.rs38
-rw-r--r--library/core/src/prelude/mod.rs20
-rw-r--r--library/core/src/ptr/mod.rs16
-rw-r--r--library/core/src/ptr/mut_ptr.rs3
-rw-r--r--library/core/src/slice/mod.rs24
-rw-r--r--library/core/tests/any.rs13
-rw-r--r--library/core/tests/array.rs46
-rw-r--r--library/core/tests/const_ptr.rs50
-rw-r--r--library/core/tests/iter/adapters/zip.rs4
-rw-r--r--library/panic_abort/src/lib.rs5
-rw-r--r--library/panic_unwind/src/lib.rs5
-rw-r--r--library/proc_macro/src/lib.rs15
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/src/io/impls.rs10
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/net/ip.rs82
-rw-r--r--library/std/src/panicking.rs2
-rw-r--r--library/std/src/path.rs42
-rw-r--r--library/std/src/prelude/mod.rs14
-rw-r--r--library/std/src/sys/unix/mod.rs1
-rw-r--r--library/std/src/time.rs4
-rw-r--r--library/term/src/lib.rs6
-rw-r--r--library/test/src/formatters/pretty.rs6
-rw-r--r--library/test/src/formatters/terse.rs6
-rw-r--r--library/test/src/lib.rs2
-rw-r--r--library/test/src/tests.rs76
-rw-r--r--library/test/src/types.rs34
-rw-r--r--library/unwind/build.rs14
-rw-r--r--src/bootstrap/bin/rustc.rs7
-rw-r--r--src/bootstrap/bootstrap.py8
-rw-r--r--src/bootstrap/builder.rs22
-rw-r--r--src/bootstrap/compile.rs12
-rw-r--r--src/bootstrap/lib.rs11
-rw-r--r--src/bootstrap/native.rs2
-rw-r--r--src/bootstrap/test.rs5
-rw-r--r--src/bootstrap/tool.rs1
-rw-r--r--src/bootstrap/util.rs4
m---------src/doc/reference0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/doc/rustc/src/codegen-options/index.md5
-rw-r--r--src/doc/rustc/src/platform-support.md2
-rw-r--r--src/doc/rustdoc/src/documentation-tests.md4
-rw-r--r--src/doc/rustdoc/src/unstable-features.md16
-rw-r--r--src/doc/unstable-book/src/compiler-flags/force-warns.md21
-rw-r--r--src/doc/unstable-book/src/language-features/external-doc.md40
-rw-r--r--src/doc/unstable-book/src/library-features/asm.md6
-rw-r--r--src/etc/htmldocck.py4
-rw-r--r--src/etc/natvis/intrinsic.natvis53
-rw-r--r--src/etc/natvis/libcore.natvis17
-rw-r--r--src/librustdoc/clean/auto_trait.rs5
-rw-r--r--src/librustdoc/clean/inline.rs2
-rw-r--r--src/librustdoc/clean/mod.rs13
-rw-r--r--src/librustdoc/clean/types.rs132
-rw-r--r--src/librustdoc/clean/utils.rs59
-rw-r--r--src/librustdoc/config.rs3
-rw-r--r--src/librustdoc/core.rs12
-rw-r--r--src/librustdoc/doctest.rs6
-rw-r--r--src/librustdoc/html/format.rs22
-rw-r--r--src/librustdoc/html/layout.rs11
-rw-r--r--src/librustdoc/html/render/context.rs9
-rw-r--r--src/librustdoc/html/render/mod.rs277
-rw-r--r--src/librustdoc/html/render/print_item.rs10
-rw-r--r--src/librustdoc/html/render/write_shared.rs1
-rw-r--r--src/librustdoc/html/static/main.js103
-rw-r--r--src/librustdoc/html/static/rustdoc.css83
-rw-r--r--src/librustdoc/html/static/search.js2
-rw-r--r--src/librustdoc/html/static/sidebar-items.js2
-rw-r--r--src/librustdoc/html/static/themes/ayu.css11
-rw-r--r--src/librustdoc/html/static/themes/dark.css10
-rw-r--r--src/librustdoc/html/static/themes/light.css10
-rw-r--r--src/librustdoc/html/static_files.rs3
-rw-r--r--src/librustdoc/json/conversions.rs6
-rw-r--r--src/librustdoc/json/mod.rs2
-rw-r--r--src/librustdoc/lib.rs15
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs19
-rw-r--r--src/librustdoc/visit_ast.rs3
m---------src/llvm-project0
-rw-r--r--src/rustdoc-json-types/lib.rs2
-rw-r--r--src/test/assembly/asm/bpf-types.rs154
-rw-r--r--src/test/codegen/async-fn-debug-msvc.rs16
-rw-r--r--src/test/codegen/bpf-alu32.rs11
-rw-r--r--src/test/codegen/generator-debug-msvc.rs16
-rw-r--r--src/test/debuginfo/msvc-pretty-enums.rs97
-rw-r--r--src/test/debuginfo/pretty-std.rs7
-rw-r--r--src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs10
-rw-r--r--src/test/incremental/callee_caller_cross_crate/b.rs4
-rw-r--r--src/test/incremental/change_add_field/struct_point.rs14
-rw-r--r--src/test/incremental/change_private_fn/struct_point.rs10
-rw-r--r--src/test/incremental/change_private_fn_cc/struct_point.rs10
-rw-r--r--src/test/incremental/change_private_impl_method/struct_point.rs10
-rw-r--r--src/test/incremental/change_private_impl_method_cc/struct_point.rs10
-rw-r--r--src/test/incremental/change_pub_inherent_method_body/struct_point.rs10
-rw-r--r--src/test/incremental/change_pub_inherent_method_sig/struct_point.rs10
-rw-r--r--src/test/incremental/crate_hash_reorder.rs4
-rw-r--r--src/test/incremental/dirty_clean.rs15
-rw-r--r--src/test/incremental/hashes/call_expressions.rs8
-rw-r--r--src/test/incremental/hashes/enum_defs.rs20
-rw-r--r--src/test/incremental/hashes/extern_mods.rs26
-rw-r--r--src/test/incremental/hashes/indexing_expressions.rs42
-rw-r--r--src/test/incremental/hashes/inherent_impls.rs5
-rw-r--r--src/test/incremental/hashes/struct_defs.rs252
-rw-r--r--src/test/incremental/hashes/trait_defs.rs426
-rw-r--r--src/test/incremental/hashes/trait_impls.rs161
-rw-r--r--src/test/incremental/hello_world.rs4
-rw-r--r--src/test/incremental/hygiene/auxiliary/cached_hygiene.rs2
-rw-r--r--src/test/incremental/ich_method_call_trait_scope.rs8
-rw-r--r--src/test/incremental/ich_nested_items.rs6
-rw-r--r--src/test/incremental/ich_resolve_results.rs12
-rw-r--r--src/test/incremental/rlib_cross_crate/b.rs8
-rw-r--r--src/test/incremental/source_loc_macros.rs15
-rw-r--r--src/test/incremental/span_hash_stable/auxiliary/sub1.rs2
-rw-r--r--src/test/incremental/span_hash_stable/auxiliary/sub2.rs2
-rw-r--r--src/test/incremental/spans_significant_w_debuginfo.rs3
-rw-r--r--src/test/incremental/spans_significant_w_panic.rs2
-rw-r--r--src/test/incremental/string_constant.rs9
-rw-r--r--src/test/incremental/struct_add_field.rs6
-rw-r--r--src/test/incremental/struct_change_field_name.rs6
-rw-r--r--src/test/incremental/struct_change_field_type.rs6
-rw-r--r--src/test/incremental/struct_change_field_type_cross_crate/b.rs6
-rw-r--r--src/test/incremental/struct_change_nothing.rs6
-rw-r--r--src/test/incremental/struct_remove_field.rs6
-rw-r--r--src/test/incremental/type_alias_cross_crate/b.rs8
-rw-r--r--src/test/incremental/unchecked_dirty_clean.rs18
-rw-r--r--src/test/mir-opt/bool_compare.opt1.InstCombine.diff35
-rw-r--r--src/test/mir-opt/bool_compare.opt2.InstCombine.diff35
-rw-r--r--src/test/mir-opt/bool_compare.opt3.InstCombine.diff35
-rw-r--r--src/test/mir-opt/bool_compare.opt4.InstCombine.diff35
-rw-r--r--src/test/mir-opt/bool_compare.rs26
-rw-r--r--src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff2
-rw-r--r--src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff2
-rw-r--r--src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff2
-rw-r--r--src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff2
-rw-r--r--src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff2
-rw-r--r--src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff2
-rw-r--r--src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff2
-rw-r--r--src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff2
-rw-r--r--src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir4
-rw-r--r--src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff2
-rw-r--r--src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff2
-rw-r--r--src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff2
-rw-r--r--src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff2
-rw-r--r--src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff6
-rw-r--r--src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir2
-rw-r--r--src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir2
-rw-r--r--src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir4
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async2.txt1
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.conditions.txt8
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt4
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.drop_trait.txt10
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generator.txt32
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generics.txt28
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.loops_branches.txt38
-rw-r--r--src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.tight_inf_loop.txt2
-rw-r--r--src/test/run-make-fulldeps/coverage/conditions.rs4
-rw-r--r--src/test/run-make-fulldeps/coverage/generator.rs30
-rw-r--r--src/test/run-make-fulldeps/coverage/generics.rs10
-rw-r--r--src/test/run-make-fulldeps/coverage/loops_branches.rs8
-rw-r--r--src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs21
-rw-r--r--src/test/run-make-fulldeps/include_bytes_deps/main.rs4
-rw-r--r--src/test/run-make-fulldeps/save-analysis/foo.rs7
-rw-r--r--src/test/run-make/raw-dylib/Makefile21
-rw-r--r--src/test/run-make/raw-dylib/driver.rs5
-rw-r--r--src/test/run-make/raw-dylib/extern_1.c16
-rw-r--r--src/test/run-make/raw-dylib/extern_2.c6
-rw-r--r--src/test/run-make/raw-dylib/lib.rs22
-rw-r--r--src/test/run-make/raw-dylib/output.txt3
-rw-r--r--src/test/run-make/unstable-flag-required/Makefile1
-rw-r--r--src/test/run-make/unstable-flag-required/force-warns.stderr2
-rw-r--r--src/test/rustdoc-gui/search-result-description.goml5
-rw-r--r--src/test/rustdoc-gui/sidebar.goml57
-rw-r--r--src/test/rustdoc-gui/src/lib.rs3
-rw-r--r--src/test/rustdoc-gui/src/lib2.rs11
-rw-r--r--src/test/rustdoc-gui/type-weight.rs2
-rw-r--r--src/test/rustdoc-ui/check.rs1
-rw-r--r--src/test/rustdoc-ui/check.stderr16
-rw-r--r--src/test/rustdoc-ui/doc-include-suggestion.rs10
-rw-r--r--src/test/rustdoc-ui/doc-include-suggestion.stderr12
-rw-r--r--src/test/rustdoc-ui/doc-spotlight.fixed5
-rw-r--r--src/test/rustdoc-ui/doc-spotlight.rs5
-rw-r--r--src/test/rustdoc-ui/doc-spotlight.stderr13
-rw-r--r--src/test/rustdoc-ui/failed-doctest-compile-fail.stdout2
-rw-r--r--src/test/rustdoc-ui/failed-doctest-missing-codes.stdout2
-rw-r--r--src/test/rustdoc-ui/intra-doc/email-address-localhost.rs1
-rw-r--r--src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr6
-rw-r--r--src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs1
-rw-r--r--src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr26
-rw-r--r--src/test/rustdoc-ui/issue-80992.stdout2
-rw-r--r--src/test/rustdoc-ui/no-crate-level-doc-lint.rs1
-rw-r--r--src/test/rustdoc-ui/no-crate-level-doc-lint.stderr4
-rw-r--r--src/test/rustdoc-ui/no-run-flag.stdout12
-rw-r--r--src/test/rustdoc-ui/test-type.rs26
-rw-r--r--src/test/rustdoc-ui/test-type.stdout10
-rw-r--r--src/test/rustdoc-ui/wasm-safe.rs7
-rw-r--r--src/test/rustdoc/async-fn.rs6
-rw-r--r--src/test/rustdoc/auto_aliases.rs2
-rw-r--r--src/test/rustdoc/auxiliary/external-cross-doc.md2
-rw-r--r--src/test/rustdoc/auxiliary/external-cross.rs6
-rw-r--r--src/test/rustdoc/auxiliary/external-doc.md2
-rw-r--r--src/test/rustdoc/blanket-reexport-item.rs2
-rw-r--r--src/test/rustdoc/const-display.rs4
-rw-r--r--src/test/rustdoc/const-fn.rs2
-rw-r--r--src/test/rustdoc/const-generics/add-impl.rs2
-rw-r--r--src/test/rustdoc/const-generics/const-generic-defaults.rs6
-rw-r--r--src/test/rustdoc/const-generics/const-generic-slice.rs2
-rw-r--r--src/test/rustdoc/const-generics/const-generics-docs.rs4
-rw-r--r--src/test/rustdoc/const-generics/const-impl.rs10
-rw-r--r--src/test/rustdoc/doc-assoc-item.rs2
-rw-r--r--src/test/rustdoc/duplicate_impls/issue-33054.rs4
-rw-r--r--src/test/rustdoc/empty-impls.rs6
-rw-r--r--src/test/rustdoc/ensure-src-link.rs2
-rw-r--r--src/test/rustdoc/external-doc.rs9
-rw-r--r--src/test/rustdoc/generic-impl.rs4
-rw-r--r--src/test/rustdoc/impl-parts.rs2
-rw-r--r--src/test/rustdoc/inline_cross/issue-31948-1.rs4
-rw-r--r--src/test/rustdoc/inline_cross/issue-31948-2.rs6
-rw-r--r--src/test/rustdoc/inline_cross/issue-31948.rs6
-rw-r--r--src/test/rustdoc/intra-doc/associated-items.rs6
-rw-r--r--src/test/rustdoc/intra-doc/builtin-macros.rs2
-rw-r--r--src/test/rustdoc/intra-doc/field.rs4
-rw-r--r--src/test/rustdoc/intra-doc/generic-params.rs28
-rw-r--r--src/test/rustdoc/intra-doc/non-path-primitives.rs34
-rw-r--r--src/test/rustdoc/intra-doc/prim-assoc.rs2
-rw-r--r--src/test/rustdoc/intra-doc/prim-methods-external-core.rs4
-rw-r--r--src/test/rustdoc/intra-doc/prim-methods-local.rs4
-rw-r--r--src/test/rustdoc/intra-doc/prim-methods.rs4
-rw-r--r--src/test/rustdoc/intra-doc/prim-precedence.rs4
-rw-r--r--src/test/rustdoc/intra-doc/primitive-disambiguators.rs2
-rw-r--r--src/test/rustdoc/intra-doc/primitive-non-default-impl.rs20
-rw-r--r--src/test/rustdoc/intra-doc/pub-use.rs4
-rw-r--r--src/test/rustdoc/intra-doc/trait-item.rs2
-rw-r--r--src/test/rustdoc/intra-doc/true-false.rs4
-rw-r--r--src/test/rustdoc/intra-link-prim-self.rs7
-rw-r--r--src/test/rustdoc/issue-21474.rs2
-rw-r--r--src/test/rustdoc/issue-29503.rs2
-rw-r--r--src/test/rustdoc/issue-33302.rs6
-rw-r--r--src/test/rustdoc/issue-45584.rs8
-rw-r--r--src/test/rustdoc/issue-50159.rs2
-rw-r--r--src/test/rustdoc/issue-51236.rs4
-rw-r--r--src/test/rustdoc/issue-53812.rs11
-rw-r--r--src/test/rustdoc/issue-54705.rs8
-rw-r--r--src/test/rustdoc/issue-55321.rs14
-rw-r--r--src/test/rustdoc/issue-56822.rs4
-rw-r--r--src/test/rustdoc/issue-60726.rs8
-rw-r--r--src/test/rustdoc/issue-76501.rs3
-rw-r--r--src/test/rustdoc/issue-78673.rs8
-rw-r--r--src/test/rustdoc/keyword.rs3
-rw-r--r--src/test/rustdoc/mut-params.rs2
-rw-r--r--src/test/rustdoc/negative-impl.rs6
-rw-r--r--src/test/rustdoc/primitive-generic-impl.rs2
-rw-r--r--src/test/rustdoc/primitive-link.rs10
-rw-r--r--src/test/rustdoc/primitive-reexport.rs12
-rw-r--r--src/test/rustdoc/pub-method.rs4
-rw-r--r--src/test/rustdoc/sidebar-links-to-foreign-impl.rs4
-rw-r--r--src/test/rustdoc/sized_trait.rs6
-rw-r--r--src/test/rustdoc/spotlight-from-dependency.rs2
-rw-r--r--src/test/rustdoc/src-links-auto-impls.rs12
-rw-r--r--src/test/rustdoc/synthetic_auto/basic.rs4
-rw-r--r--src/test/rustdoc/synthetic_auto/complex.rs4
-rw-r--r--src/test/rustdoc/synthetic_auto/lifetimes.rs8
-rw-r--r--src/test/rustdoc/synthetic_auto/manual.rs10
-rw-r--r--src/test/rustdoc/synthetic_auto/negative.rs8
-rw-r--r--src/test/rustdoc/synthetic_auto/nested.rs6
-rw-r--r--src/test/rustdoc/synthetic_auto/no-redundancy.rs4
-rw-r--r--src/test/rustdoc/synthetic_auto/project.rs9
-rw-r--r--src/test/rustdoc/synthetic_auto/self-referential.rs4
-rw-r--r--src/test/rustdoc/synthetic_auto/static-region.rs4
-rw-r--r--src/test/rustdoc/trait-attributes.rs6
-rw-r--r--src/test/rustdoc/trait-impl-items-links-and-anchors.rs68
-rw-r--r--src/test/rustdoc/typedef.rs4
-rw-r--r--src/test/rustdoc/unindent.rs6
-rw-r--r--src/test/rustdoc/where.rs6
-rw-r--r--src/test/ui/c-variadic/variadic-ffi-4.stderr8
-rw-r--r--src/test/ui/const-generics/array-impls/into-iter-impls-length-32.rs14
-rw-r--r--src/test/ui/const-generics/array-impls/into-iter-impls-length-33.rs14
-rw-r--r--src/test/ui/const-generics/defaults/forward-declared.rs15
-rw-r--r--src/test/ui/const-generics/defaults/forward-declared.stderr27
-rw-r--r--src/test/ui/const-ptr/out_of_bounds_read.rs16
-rw-r--r--src/test/ui/const-ptr/out_of_bounds_read.stderr59
-rw-r--r--src/test/ui/consts/copy-intrinsic.rs45
-rw-r--r--src/test/ui/consts/copy-intrinsic.stderr69
-rw-r--r--src/test/ui/consts/miri_unleashed/tls.stderr4
-rw-r--r--src/test/ui/dep-graph/dep-graph-check-attr.rs2
-rw-r--r--src/test/ui/dep-graph/dep-graph-check-attr.stderr2
-rw-r--r--src/test/ui/deprecation/deprecation-lint.rs18
-rw-r--r--src/test/ui/error-codes/E0121.stderr2
-rw-r--r--src/test/ui/extern/external-doc-error.rs31
-rw-r--r--src/test/ui/extern/external-doc-error.stderr38
-rw-r--r--src/test/ui/feature-gates/feature-gate-external_doc.rs3
-rw-r--r--src/test/ui/feature-gates/feature-gate-external_doc.stderr21
-rw-r--r--src/test/ui/feature-gates/feature-gate-raw-dylib-2.rs (renamed from src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.rs)0
-rw-r--r--src/test/ui/feature-gates/feature-gate-raw-dylib-2.stderr (renamed from src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.stderr)0
-rw-r--r--src/test/ui/feature-gates/feature-gate-raw-dylib-windows-gnu.rs8
-rw-r--r--src/test/ui/feature-gates/feature-gate-raw-dylib-windows-gnu.stderr18
-rw-r--r--src/test/ui/feature-gates/feature-gate-raw-dylib-windows-msvc.rs (renamed from src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.rs)2
-rw-r--r--src/test/ui/feature-gates/feature-gate-raw-dylib-windows-msvc.stderr (renamed from src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.stderr)2
-rw-r--r--src/test/ui/generator/print/generator-print-verbose-1.stderr10
-rw-r--r--src/test/ui/intrinsics/issue-84297-reifying-copy.rs9
-rw-r--r--src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr2
-rw-r--r--src/test/ui/layout/issue-84108.rs14
-rw-r--r--src/test/ui/layout/issue-84108.stderr44
-rw-r--r--src/test/ui/lint/force-warn/force-allowed-by-default-lint.rs11
-rw-r--r--src/test/ui/lint/force-warn/force-allowed-by-default-lint.stderr10
-rw-r--r--src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.rs9
-rw-r--r--src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.stderr14
-rw-r--r--src/test/ui/lint/force-warn/force-allowed-warning.rs9
-rw-r--r--src/test/ui/lint/force-warn/force-allowed-warning.stderr10
-rw-r--r--src/test/ui/lint/force-warn/force-deny-by-default-lint.rs8
-rw-r--r--src/test/ui/lint/force-warn/force-deny-by-default-lint.stderr14
-rw-r--r--src/test/ui/lint/force-warn/force-lint-allow-all-warnings.rs9
-rw-r--r--src/test/ui/lint/force-warn/force-lint-allow-all-warnings.stderr10
-rw-r--r--src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.rs9
-rw-r--r--src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.stderr10
-rw-r--r--src/test/ui/lint/force-warn/force-lint-in-allowed-group.rs12
-rw-r--r--src/test/ui/lint/force-warn/force-lint-in-allowed-group.stderr12
-rw-r--r--src/test/ui/lint/force-warn/force-warn-group-allow-warning.rs12
-rw-r--r--src/test/ui/lint/force-warn/force-warn-group-allow-warning.stderr12
-rw-r--r--src/test/ui/lint/force-warn/force-warn-group.rs12
-rw-r--r--src/test/ui/lint/force-warn/force-warn-group.stderr12
-rw-r--r--src/test/ui/lint/lint-ctypes-fn.rs11
-rw-r--r--src/test/ui/lint/lint-ctypes-fn.stderr64
-rw-r--r--src/test/ui/lto-duplicate-symbols.stderr2
-rw-r--r--src/test/ui/macros/local-ambiguity-multiple-parsing-options.stderr4
-rw-r--r--src/test/ui/manual/manual-link-unsupported-kind.rs5
-rw-r--r--src/test/ui/manual/manual-link-unsupported-kind.stderr2
-rw-r--r--src/test/ui/match/match-ref-mut-invariance.nll.stderr3
-rw-r--r--src/test/ui/match/match-ref-mut-let-invariance.nll.stderr3
-rw-r--r--src/test/ui/nll/type-check-pointer-coercions.stderr6
-rw-r--r--src/test/ui/nll/type-check-pointer-comparisons.stderr18
-rw-r--r--src/test/ui/panics/panic-macro-any-wrapped.rs2
-rw-r--r--src/test/ui/panics/panic-macro-any.rs2
-rw-r--r--src/test/ui/parser/issue-84104.rs3
-rw-r--r--src/test/ui/parser/issue-84104.stderr16
-rw-r--r--src/test/ui/parser/issue-84148-1.rs4
-rw-r--r--src/test/ui/parser/issue-84148-1.stderr23
-rw-r--r--src/test/ui/parser/issue-84148-2.rs4
-rw-r--r--src/test/ui/parser/issue-84148-2.stderr31
-rw-r--r--src/test/ui/parser/unmatched-langle-1.rs9
-rw-r--r--src/test/ui/parser/unmatched-langle-1.stderr22
-rw-r--r--src/test/ui/parser/unmatched-langle-2.rs15
-rw-r--r--src/test/ui/parser/unmatched-langle-2.stderr8
-rw-r--r--src/test/ui/prelude2021.rs7
-rw-r--r--src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.rs37
-rw-r--r--src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout540
-rw-r--r--src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr3
-rw-r--r--src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr3
-rw-r--r--src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr3
-rw-r--r--src/test/ui/regions/regions-trait-object-subtyping.nll.stderr6
-rw-r--r--src/test/ui/reify-intrinsic.rs6
-rw-r--r--src/test/ui/reify-intrinsic.stderr8
-rw-r--r--src/test/ui/rfc-2627-raw-dylib/raw-dylib-msvc-only.rs8
-rw-r--r--src/test/ui/rfc-2627-raw-dylib/raw-dylib-msvc-only.stderr17
-rw-r--r--src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.rs7
-rw-r--r--src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr17
-rw-r--r--src/test/ui/rustdoc/deny-invalid-doc-attrs.rs7
-rw-r--r--src/test/ui/rustdoc/deny-invalid-doc-attrs.stderr16
-rw-r--r--src/test/ui/rustdoc/doc-inline-extern-crate.rs9
-rw-r--r--src/test/ui/rustdoc/doc-inline-extern-crate.stderr13
-rw-r--r--src/test/ui/simd/issue-85915-simd-ptrs.rs67
-rw-r--r--src/test/ui/simd/simd-type-generic-monomorphisation-extern-nonnull-ptr.rs23
-rw-r--r--src/test/ui/simd/simd-type-generic-monomorphisation-wide-ptr.rs12
-rw-r--r--src/test/ui/simd/simd-type-generic-monomorphisation-wide-ptr.stderr4
-rw-r--r--src/test/ui/simd/simd-type-wide-ptr.rs12
-rw-r--r--src/test/ui/simd/simd-type-wide-ptr.stderr4
-rw-r--r--src/test/ui/simd/wasm-simd-indirect.rs33
-rw-r--r--src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr24
-rw-r--r--src/test/ui/specialization/min_specialization/repeated_projection_type.stderr2
-rw-r--r--src/test/ui/suggestions/auxiliary/proc-macro-type-error.rs18
-rw-r--r--src/test/ui/suggestions/format-borrow.rs4
-rw-r--r--src/test/ui/suggestions/format-borrow.stderr22
-rw-r--r--src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs9
-rw-r--r--src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr20
-rw-r--r--src/test/ui/suggestions/suggest-ref-macro.rs29
-rw-r--r--src/test/ui/suggestions/suggest-ref-macro.stderr34
-rw-r--r--src/test/ui/symbol-names/basic.legacy.stderr4
-rw-r--r--src/test/ui/symbol-names/basic.rs4
-rw-r--r--src/test/ui/symbol-names/basic.v0.stderr4
-rw-r--r--src/test/ui/symbol-names/const-generics-demangling.rs16
-rw-r--r--src/test/ui/symbol-names/const-generics-demangling.stderr16
-rw-r--r--src/test/ui/symbol-names/impl1.rs12
-rw-r--r--src/test/ui/symbol-names/impl1.v0.stderr12
-rw-r--r--src/test/ui/symbol-names/issue-60925.legacy.stderr4
-rw-r--r--src/test/ui/symbol-names/issue-60925.rs4
-rw-r--r--src/test/ui/symbol-names/issue-60925.v0.stderr4
-rw-r--r--src/test/ui/symbol-names/issue-75326.rs4
-rw-r--r--src/test/ui/symbol-names/issue-75326.v0.stderr4
-rw-r--r--src/test/ui/symbol-names/trait-objects.v0.stderr6
-rw-r--r--src/test/ui/target-feature/gate.rs1
-rw-r--r--src/test/ui/target-feature/gate.stderr2
-rw-r--r--src/test/ui/target-feature/wasm-safe.rs44
-rw-r--r--src/test/ui/test-attrs/test-type.rs28
-rw-r--r--src/test/ui/test-attrs/test-type.run.stdout8
-rw-r--r--src/test/ui/test-panic-abort-nocapture.run.stdout2
-rw-r--r--src/test/ui/test-panic-abort.run.stdout2
-rw-r--r--src/test/ui/thread-local-static.rs17
-rw-r--r--src/test/ui/thread-local-static.stderr50
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs12
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs16
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr15
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs16
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr8
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs18
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr18
-rw-r--r--src/test/ui/typeck/typeck_type_placeholder_item.full_tait.stderr16
-rw-r--r--src/test/ui/typeck/typeck_type_placeholder_item.min_tait.stderr16
-rw-r--r--src/test/ui/typeck/typeck_type_placeholder_item_help.stderr8
-rw-r--r--src/test/ui/where-clauses/where-for-self.stderr1
-rw-r--r--src/tools/build-manifest/src/main.rs2
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/CHANGELOG.md3
-rw-r--r--src/tools/clippy/COPYRIGHT2
-rw-r--r--src/tools/clippy/Cargo.toml3
-rw-r--r--src/tools/clippy/LICENSE-APACHE2
-rw-r--r--src/tools/clippy/LICENSE-MIT2
-rw-r--r--src/tools/clippy/README.md3
-rw-r--r--src/tools/clippy/build.rs2
-rw-r--r--src/tools/clippy/clippy.toml1
-rw-r--r--src/tools/clippy/clippy_lints/src/absurd_extreme_comparisons.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/arithmetic.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/assertions_on_constants.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/bit_mask.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/booleans.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/collapsible_if.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/comparison_chain.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/consts.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/copies.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/deprecated_lints.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/double_comparison.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/duration_subsec.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/entry.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/enum_clike.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/enum_variants.rs80
-rw-r--r--src/tools/clippy/clippy_lints/src/eq_op.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/erasing_op.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs31
-rw-r--r--src/tools/clippy/clippy_lints/src/eval_order_dependence.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/must_use.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/future_not_send.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/identity_op.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_return.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/indexing_slicing.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/infinite_iter.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/len_zero.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/let_underscore.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs635
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/literal_representation.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/needless_collect.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/same_item_push.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/utils.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/macro_use.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_strip.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/map_clone.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/matches.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/mem_discriminant.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs47
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs99
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs115
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs56
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/minmax.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/misc.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/mod.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_doc.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_reference.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_bool.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_borrow.rs219
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_for_each.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/neg_multiply.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/no_effect.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/non_expressive_names.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/open_options.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/ranges.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_closure_call.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/regex.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/repeat_once.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/returns.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/shadow.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/single_component_path_imports.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/trait_bounds.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/transmuting_null.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/types/mod.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unicode.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs21
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_io_amount.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs34
-rw-r--r--src/tools/clippy/clippy_lints/src/use_self.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/conf.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/vec.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/verbose_file_reads.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/write.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/zero_div_zero.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/attrs.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs22
-rw-r--r--src/tools/clippy/clippy_utils/src/diagnostics.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/higher.rs36
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs267
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs84
-rw-r--r--src/tools/clippy/clippy_utils/src/msrvs.rs1
-rw-r--r--src/tools/clippy/clippy_utils/src/numeric_literal.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/paths.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/ptr.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs29
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs17
-rw-r--r--src/tools/clippy/clippy_utils/src/usage.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/visitors.rs43
-rw-r--r--src/tools/clippy/doc/release.md2
-rw-r--r--src/tools/clippy/mini-macro/Cargo.toml14
-rw-r--r--src/tools/clippy/mini-macro/src/lib.rs29
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/rustc_tools_util/src/lib.rs12
-rw-r--r--src/tools/clippy/tests/clippy.toml1
-rw-r--r--src/tools/clippy/tests/compile-test.rs42
-rw-r--r--src/tools/clippy/tests/dogfood.rs31
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr2
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs19
-rw-r--r--src/tools/clippy/tests/ui/crashes/auxiliary/ice-7272-aux.rs14
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-7272.rs12
-rw-r--r--src/tools/clippy/tests/ui/crashes/procedural_macro.rs11
-rw-r--r--src/tools/clippy/tests/ui/def_id_nocore.rs2
-rw-r--r--src/tools/clippy/tests/ui/deprecated.rs2
-rw-r--r--src/tools/clippy/tests/ui/deprecated.stderr14
-rw-r--r--src/tools/clippy/tests/ui/enum_variants.rs7
-rw-r--r--src/tools/clippy/tests/ui/enum_variants.stderr37
-rw-r--r--src/tools/clippy/tests/ui/eta.fixed3
-rw-r--r--src/tools/clippy/tests/ui/eta.rs3
-rw-r--r--src/tools/clippy/tests/ui/eta.stderr16
-rw-r--r--src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed14
-rw-r--r--src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs14
-rw-r--r--src/tools/clippy/tests/ui/from_iter_instead_of_collect.stderr40
-rw-r--r--src/tools/clippy/tests/ui/functions.stderr18
-rw-r--r--src/tools/clippy/tests/ui/macro_use_imports.fixed3
-rw-r--r--src/tools/clippy/tests/ui/macro_use_imports.rs3
-rw-r--r--src/tools/clippy/tests/ui/macro_use_imports.stderr14
-rw-r--r--src/tools/clippy/tests/ui/manual_str_repeat.fixed66
-rw-r--r--src/tools/clippy/tests/ui/manual_str_repeat.rs66
-rw-r--r--src/tools/clippy/tests/ui/manual_str_repeat.stderr64
-rw-r--r--src/tools/clippy/tests/ui/missing-doc-crate.rs3
-rw-r--r--src/tools/clippy/tests/ui/missing-doc-impl.rs5
-rw-r--r--src/tools/clippy/tests/ui/missing-doc-impl.stderr8
-rw-r--r--src/tools/clippy/tests/ui/module_name_repetitions.rs8
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow.fixed17
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow.rs17
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow.stderr16
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow_pat.rs151
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow_pat.stderr112
-rw-r--r--src/tools/clippy/tests/ui/needless_collect_indirect.rs8
-rw-r--r--src/tools/clippy/tests/ui/no_effect.rs3
-rw-r--r--src/tools/clippy/tests/ui/ref_binding_to_reference.rs76
-rw-r--r--src/tools/clippy/tests/ui/ref_binding_to_reference.stderr88
-rw-r--r--src/tools/clippy/tests/ui/similar_names.rs4
-rw-r--r--src/tools/clippy/tests/ui/similar_names.stderr4
-rw-r--r--src/tools/clippy/tests/ui/single_char_pattern.fixed4
-rw-r--r--src/tools/clippy/tests/ui/single_char_pattern.rs4
-rw-r--r--src/tools/clippy/tests/ui/single_char_pattern.stderr4
-rw-r--r--src/tools/clippy/tests/ui/suspicious_splitn.rs20
-rw-r--r--src/tools/clippy/tests/ui/suspicious_splitn.stderr75
-rw-r--r--src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr8
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_wraps.rs2
-rw-r--r--src/tools/clippy/tests/ui/unseparated_prefix_literals.fixed3
-rw-r--r--src/tools/clippy/tests/ui/unseparated_prefix_literals.rs3
-rw-r--r--src/tools/clippy/tests/ui/unseparated_prefix_literals.stderr18
-rw-r--r--src/tools/clippy/tests/ui/wrong_self_convention.rs1
-rw-r--r--src/tools/clippy/tests/ui/wrong_self_convention.stderr48
-rw-r--r--src/tools/clippy/tests/ui/wrong_self_convention2.rs1
-rw-r--r--src/tools/clippy/tests/ui/wrong_self_convention2.stderr4
-rwxr-xr-xsrc/tools/clippy/util/cov.sh37
-rw-r--r--src/tools/compiletest/src/main.rs4
-rw-r--r--src/tools/compiletest/src/runtest.rs8
-rw-r--r--src/tools/compiletest/src/util.rs2
-rw-r--r--src/tools/jsondocck/Cargo.toml5
-rw-r--r--src/tools/jsondocck/src/main.rs12
-rwxr-xr-xsrc/tools/linkchecker/linkcheck.sh10
-rw-r--r--src/tools/linkchecker/main.rs2
m---------src/tools/miri17
m---------src/tools/rls0
m---------src/tools/rust-analyzer34
-rw-r--r--src/tools/rustdoc-gui/tester.js7
-rw-r--r--triagebot.toml2
868 files changed, 10626 insertions, 6520 deletions
diff --git a/.gitattributes b/.gitattributes
index 82599b14503..51a670b5fbe 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -16,11 +16,3 @@ config.toml.example linguist-language=TOML
 *.ico binary
 *.woff binary
 *.woff2 binary
-
-# Needed as part of converting rustfmt to a subtree, can hopefully be removed later.
-src/tools/rustfmt/tests/source/issue-3494/crlf.rs -text
-src/tools/rustfmt/tests/source/comment_crlf_newline.rs -text
-src/tools/rustfmt/tests/source/configs/enum_discrim_align_threshold/40.rs -text
-src/tools/rustfmt/tests/target/issue-3494/crlf.rs -text
-src/tools/rustfmt/tests/target/comment_crlf_newline.rs -text
-src/tools/rustfmt/tests/target/configs/enum_discrim_align_threshold/40.rs -text
diff --git a/Cargo.lock b/Cargo.lock
index 1d3b539c682..de110c55a4b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -278,6 +278,7 @@ dependencies = [
  "humantime 2.0.1",
  "ignore",
  "im-rc",
+ "itertools 0.10.0",
  "jobserver",
  "lazy_static",
  "lazycell",
@@ -293,7 +294,7 @@ dependencies = [
  "rand 0.8.3",
  "rustc-workspace-hack",
  "rustfix",
- "semver 0.10.0",
+ "semver 1.0.3",
  "serde",
  "serde_ignored",
  "serde_json",
@@ -551,10 +552,10 @@ name = "clippy"
 version = "0.1.54"
 dependencies = [
  "cargo_metadata 0.12.0",
- "clippy-mini-macro-test",
  "clippy_lints",
  "compiletest_rs",
  "derive-new",
+ "filetime",
  "quote",
  "regex",
  "rustc-workspace-hack",
@@ -567,10 +568,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "clippy-mini-macro-test"
-version = "0.2.0"
-
-[[package]]
 name = "clippy_dev"
 version = "0.0.1"
 dependencies = [
@@ -655,9 +652,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.43"
+version = "0.1.45"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65af2dcae4779003dfa91aedc6ade7bdc7ba685944e50a8b4f9380df376a4466"
+checksum = "787187ae221adfcda34b03006f1617099e4ae26b50e5a4db282496014ab75837"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
@@ -1716,6 +1713,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "itertools"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319"
+dependencies = [
+ "either",
+]
+
+[[package]]
 name = "itoa"
 version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1743,11 +1749,10 @@ dependencies = [
  "fs-err",
  "getopts",
  "jsonpath_lib",
- "lazy_static",
+ "once_cell",
  "regex",
- "serde",
  "serde_json",
- "shlex 0.1.1",
+ "shlex",
 ]
 
 [[package]]
@@ -2128,7 +2133,7 @@ dependencies = [
  "serde",
  "serde_derive",
  "serde_json",
- "shlex 1.0.0",
+ "shlex",
  "tempfile",
  "toml",
 ]
@@ -2149,9 +2154,9 @@ dependencies = [
 
 [[package]]
 name = "memchr"
-version = "2.3.3"
+version = "2.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
+checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
 
 [[package]]
 name = "memmap2"
@@ -2355,6 +2360,17 @@ dependencies = [
 ]
 
 [[package]]
+name = "object"
+version = "0.25.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8bc1d42047cf336f0f939c99e97183cf31551bf0f2865a2ec9c8d91fd4ffb5e"
+dependencies = [
+ "crc32fast",
+ "indexmap",
+ "memchr",
+]
+
+[[package]]
 name = "once_cell"
 version = "1.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2846,9 +2862,9 @@ dependencies = [
 
 [[package]]
 name = "racer"
-version = "2.1.47"
+version = "2.1.48"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "513c70e67444a0d62fdc581dffa521c6820942a5f08300d0864863f8d0e750e3"
+checksum = "7fec2e85e7a30f8fd31b7cf288ad363b5e51fd2cb6f53b416b0cfaabd84e1ccb"
 dependencies = [
  "bitflags",
  "clap",
@@ -3072,7 +3088,7 @@ dependencies = [
  "anyhow",
  "cargo",
  "cargo-util",
- "cargo_metadata 0.8.2",
+ "cargo_metadata 0.12.0",
  "clippy_lints",
  "crossbeam-channel",
  "difference",
@@ -3205,9 +3221,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_arena"
-version = "718.0.0"
+version = "722.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "526610f47139efa440178239553b59ea805ff57a532b4e295c71d2a9b18fd676"
+checksum = "550ca1a0925d31a0af089b18c89f5adf3b286e319e3e1f1a5204c21bd2f17371"
 dependencies = [
  "rustc-ap-rustc_data_structures",
  "smallvec",
@@ -3215,9 +3231,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_ast"
-version = "718.0.0"
+version = "722.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf6a9dda0804a7243b0282e3b75a8cf4654c7a61f033e587751941e1fe39391b"
+checksum = "4aa53b68080df17994a54747f7c37b0686288a670efb9ba3b382ce62e744aed2"
 dependencies = [
  "bitflags",
  "rustc-ap-rustc_data_structures",
@@ -3232,9 +3248,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_ast_pretty"
-version = "718.0.0"
+version = "722.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82f5019be8b41a58664169fd2f4b1a37fe82705681db394b76419e4e87d40ab1"
+checksum = "0ae71e68fada466a4b2c39c79ca6aee3226587abe6787170d2f6c92237569565"
 dependencies = [
  "rustc-ap-rustc_ast",
  "rustc-ap-rustc_span",
@@ -3243,9 +3259,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_data_structures"
-version = "718.0.0"
+version = "722.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a701717fb14549331085756b9741ae3b4bf35808489f1887d72c1d0e0fe52b77"
+checksum = "faa484d6e0ca32d1d82303647275c696f745599b3d97e686f396ceef5b99d7ae"
 dependencies = [
  "arrayvec",
  "bitflags",
@@ -3275,9 +3291,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_errors"
-version = "718.0.0"
+version = "722.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3182ce85e8bfc96443475547f2f5aa2b5e67655d9b88721795f36f0ba9e265a"
+checksum = "5f85ba19cca320ad797e3a29c35cab9bddfff0e7adbde336a436249e54cee7b1"
 dependencies = [
  "annotate-snippets",
  "atty",
@@ -3295,9 +3311,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_feature"
-version = "718.0.0"
+version = "722.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eed033b93270126ef60963c3ebbd0e026bf53b985172b6366c7b0e7881c9d507"
+checksum = "97d538adab96b8b2b1ca9fcd4c8c47d4e23e862a23d1a38b6c15cd8fd52b34b1"
 dependencies = [
  "rustc-ap-rustc_data_structures",
  "rustc-ap-rustc_span",
@@ -3305,21 +3321,21 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_fs_util"
-version = "718.0.0"
+version = "722.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28ee6531986a205101e09fd143d7bf31897388f33b1814d4bcc45fd62211dca6"
+checksum = "8ad6f13d240944fa8f360d2f3b849a7cadaec75e477829e7dde61e838deda83d"
 
 [[package]]
 name = "rustc-ap-rustc_graphviz"
-version = "718.0.0"
+version = "722.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3398fddc0e23d2db89c036f8952ddf78cadc597f7059752116e69483e164a5b6"
+checksum = "08b3451153cc5828c02cc4f1a0df146d25ac4b3382a112e25fd9d3f5bff15cdc"
 
 [[package]]
 name = "rustc-ap-rustc_index"
-version = "718.0.0"
+version = "722.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dca4e27eb5b701f6bbd47d8fc9d242378fca3e4107a519a28415c2989c4a3bd3"
+checksum = "cd39a9f01b442c629bdff5778cb3dd29b7c2ea4afe62d5ab61d216bd1b556692"
 dependencies = [
  "arrayvec",
  "rustc-ap-rustc_macros",
@@ -3328,18 +3344,18 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_lexer"
-version = "718.0.0"
+version = "722.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "786bbfe9d4d5264294c1819dbf1497a2480b583d5eda1ca9ae22e12d6661f5df"
+checksum = "a5de290c44a90e671d2cd730062b9ef73d11155da7e44e7741d633e1e51e616e"
 dependencies = [
  "unicode-xid",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_lint_defs"
-version = "718.0.0"
+version = "722.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be2f045e2b999c154ec505d5fea69c994b742f3ebd2f552d11a6c81723921e47"
+checksum = "69570b4beb61088926b131579865bbe70d124d30778c46307a62ec8b310ae462"
 dependencies = [
  "rustc-ap-rustc_ast",
  "rustc-ap-rustc_data_structures",
@@ -3352,9 +3368,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_macros"
-version = "718.0.0"
+version = "722.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "27789cd26d6b9e2fdfa68a262a20664d79ca67d31a3886d40fb88ebf6935869c"
+checksum = "86bd877df37f15c5a44d9679d1b5207ebc95f3943fbc336eeac670195ac58610"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3364,9 +3380,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_parse"
-version = "718.0.0"
+version = "722.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1dc331f4958350679679e619d63a891e8d5d34ef99087068c89aa9e657d52caa"
+checksum = "02502d8522ba31d0bcad28a78822b68c1b6ba947a2b4aa6a2341b30594379b80"
 dependencies = [
  "bitflags",
  "rustc-ap-rustc_ast",
@@ -3384,9 +3400,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_serialize"
-version = "718.0.0"
+version = "722.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e9a6824a462c4c1a379e911b0faf86d303a54bcf8673d4cc445195085966a4a4"
+checksum = "5f741f8e9aee6323fbe127329490608a5a250cc0072ac91e684ef62518cdb1ff"
 dependencies = [
  "indexmap",
  "smallvec",
@@ -3394,9 +3410,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_session"
-version = "718.0.0"
+version = "722.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a782a5f6ada0dbe089c6416ad0104f0b8a8bdb4bd26ea95e5fefaec67aed5e8a"
+checksum = "dba61eca749f4fced4427ad1cc7f23342cfc6527c3bcc624e3aa56abc1f81298"
 dependencies = [
  "bitflags",
  "getopts",
@@ -3416,9 +3432,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_span"
-version = "718.0.0"
+version = "722.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a257546cb264b250c7abdb81239bb02f18a274a966211755a3ea89411b122214"
+checksum = "a642e8d6fc883f34e0778e079f8242ac40c6614a6b7a0ef61681333e847f5e62"
 dependencies = [
  "cfg-if 0.1.10",
  "md-5",
@@ -3436,9 +3452,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_target"
-version = "718.0.0"
+version = "722.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5a72dd689421bcb5750f3ed0dedf367076e714ef0ba56c02ed391b9a8582862"
+checksum = "80feebd8c323b80dd73a395fa7fabba9e2098b6277670ff89c473f618ffa07de"
 dependencies = [
  "bitflags",
  "rustc-ap-rustc_data_structures",
@@ -3697,7 +3713,7 @@ dependencies = [
  "itertools 0.9.0",
  "jobserver",
  "libc",
- "object",
+ "object 0.25.2",
  "pathdiff",
  "rustc_apfloat",
  "rustc_ast",
@@ -4676,6 +4692,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "semver"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f3aac57ee7f3272d8395c6e4f502f434f0e289fcd62876f70daa008c20dcabe"
+dependencies = [
+ "serde",
+]
+
+[[package]]
 name = "semver-parser"
 version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4797,12 +4822,6 @@ checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f"
 
 [[package]]
 name = "shlex"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
-
-[[package]]
-name = "shlex"
 version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "42a568c8f2cd051a4d283bd6eb0343ac214c1b0f1ac19f93e1175b2dee38c73d"
@@ -4905,7 +4924,7 @@ dependencies = [
  "hermit-abi",
  "libc",
  "miniz_oxide",
- "object",
+ "object 0.22.0",
  "panic_abort",
  "panic_unwind",
  "profiler_builtins",
@@ -5034,9 +5053,9 @@ dependencies = [
 
 [[package]]
 name = "tar"
-version = "0.4.33"
+version = "0.4.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0bcfbd6a598361fda270d82469fff3d65089dc33e175c9a131f7b4cd395f228"
+checksum = "7d779dc6aeff029314570f666ec83f19df7280bb36ef338442cfa8c604021b80"
 dependencies = [
  "filetime",
  "libc",
diff --git a/compiler/rustc_ast/src/ast_like.rs b/compiler/rustc_ast/src/ast_like.rs
index 945a44ab663..d586426d70e 100644
--- a/compiler/rustc_ast/src/ast_like.rs
+++ b/compiler/rustc_ast/src/ast_like.rs
@@ -82,7 +82,8 @@ impl AstLike for crate::token::Nonterminal {
             Nonterminal::NtMeta(attr_item) => attr_item.tokens_mut(),
             Nonterminal::NtPath(path) => path.tokens_mut(),
             Nonterminal::NtVis(vis) => vis.tokens_mut(),
-            _ => panic!("Called tokens_mut on {:?}", self),
+            Nonterminal::NtBlock(block) => block.tokens_mut(),
+            Nonterminal::NtIdent(..) | Nonterminal::NtLifetime(..) | Nonterminal::NtTT(..) => None,
         }
     }
 }
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index 14ecf27813d..7c79b4aab3c 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -12,13 +12,11 @@
 #![feature(box_patterns)]
 #![cfg_attr(bootstrap, feature(const_fn_unsize))]
 #![feature(const_fn_transmute)]
-#![feature(const_panic)]
 #![feature(crate_visibility_modifier)]
 #![feature(iter_zip)]
 #![feature(label_break_value)]
 #![feature(nll)]
 #![feature(min_specialization)]
-#![feature(trusted_step)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index 2d463a4588c..5d994dbad4d 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -218,8 +218,7 @@ impl AttrAnnotatedTokenStream {
                 AttrAnnotatedTokenTree::Attributes(data) => {
                     let mut outer_attrs = Vec::new();
                     let mut inner_attrs = Vec::new();
-                    let attrs: Vec<_> = data.attrs.clone().into();
-                    for attr in attrs {
+                    for attr in &data.attrs {
                         match attr.style {
                             crate::AttrStyle::Outer => {
                                 assert!(
@@ -264,7 +263,7 @@ impl AttrAnnotatedTokenStream {
                                 // so we never reach this code.
 
                                 let mut builder = TokenStreamBuilder::new();
-                                for inner_attr in &inner_attrs {
+                                for inner_attr in inner_attrs {
                                     builder.push(inner_attr.tokens().to_tokenstream());
                                 }
                                 builder.push(delim_tokens.clone());
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 6f1772ff818..0ff1efd8165 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -43,7 +43,7 @@ use rustc_ast::walk_list;
 use rustc_ast::{self as ast, *};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::captures::Captures;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{struct_span_err, Applicability};
 use rustc_hir as hir;
@@ -198,7 +198,7 @@ pub trait ResolverAstLowering {
 
     fn next_node_id(&mut self) -> NodeId;
 
-    fn trait_map(&self) -> &NodeMap<Vec<hir::TraitCandidate>>;
+    fn take_trait_map(&mut self) -> NodeMap<Vec<hir::TraitCandidate>>;
 
     fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId>;
 
@@ -501,14 +501,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let proc_macros =
             c.proc_macros.iter().map(|id| self.node_id_to_hir_id[*id].unwrap()).collect();
 
-        let trait_map = self
-            .resolver
-            .trait_map()
-            .iter()
-            .filter_map(|(&k, v)| {
-                self.node_id_to_hir_id.get(k).and_then(|id| id.as_ref()).map(|id| (*id, v.clone()))
-            })
-            .collect();
+        let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default();
+        for (k, v) in self.resolver.take_trait_map().into_iter() {
+            if let Some(Some(hir_id)) = self.node_id_to_hir_id.get(k) {
+                let map = trait_map.entry(hir_id.owner).or_default();
+                map.insert(hir_id.local_id, v.into_boxed_slice());
+            }
+        }
 
         let mut def_id_to_hir_id = IndexVec::default();
 
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 4996c2195ef..664e138b39d 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -318,7 +318,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                 }}
 
                 gate_doc!(
-                    include => external_doc
                     cfg => doc_cfg
                     masked => doc_masked
                     notable_trait => doc_notable_trait
diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs
index c9e2d202da9..26da18b571c 100644
--- a/compiler/rustc_ast_passes/src/lib.rs
+++ b/compiler/rustc_ast_passes/src/lib.rs
@@ -6,7 +6,6 @@
 
 #![feature(bindings_after_at)]
 #![feature(iter_is_partitioned)]
-#![feature(box_syntax)]
 #![feature(box_patterns)]
 #![recursion_limit = "256"]
 
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index e845f9ec55a..99544ddb66e 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -254,6 +254,10 @@ pub fn expand_test_or_bench(
                                         "allow_fail",
                                         cx.expr_bool(sp, should_fail(&cx.sess, &item)),
                                     ),
+                                    // compile_fail: true | false
+                                    field("compile_fail", cx.expr_bool(sp, false)),
+                                    // no_run: true | false
+                                    field("no_run", cx.expr_bool(sp, false)),
                                     // should_panic: ...
                                     field(
                                         "should_panic",
diff --git a/compiler/rustc_codegen_cranelift/src/archive.rs b/compiler/rustc_codegen_cranelift/src/archive.rs
index bd54adc53ee..22897c43e7e 100644
--- a/compiler/rustc_codegen_cranelift/src/archive.rs
+++ b/compiler/rustc_codegen_cranelift/src/archive.rs
@@ -254,6 +254,15 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
             }
         }
     }
+
+    fn inject_dll_import_lib(
+        &mut self,
+        _lib_name: &str,
+        _dll_imports: &[rustc_middle::middle::cstore::DllImport],
+        _tmpdir: &rustc_data_structures::temp_dir::MaybeTempDir,
+    ) {
+        bug!("injecting dll imports is not supported");
+    }
 }
 
 impl<'a> ArArchiveBuilder<'a> {
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index 9cf51d15c8c..6676d88602c 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -177,21 +177,6 @@ pub(crate) fn run_aot(
     metadata: EncodedMetadata,
     need_metadata_module: bool,
 ) -> Box<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)> {
-    use rustc_span::symbol::sym;
-
-    let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
-    let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem);
-    let windows_subsystem = subsystem.map(|subsystem| {
-        if subsystem != sym::windows && subsystem != sym::console {
-            tcx.sess.fatal(&format!(
-                "invalid windows subsystem `{}`, only \
-                                    `windows` and `console` are allowed",
-                subsystem
-            ));
-        }
-        subsystem.to_string()
-    });
-
     let mut work_products = FxHashMap::default();
 
     let cgus = if tcx.sess.opts.output_types.should_codegen() {
@@ -307,12 +292,10 @@ pub(crate) fn run_aot(
 
     Box::new((
         CodegenResults {
-            crate_name: tcx.crate_name(LOCAL_CRATE),
             modules,
             allocator_module,
             metadata_module,
             metadata,
-            windows_subsystem,
             linker_info: LinkerInfo::new(tcx, crate::target_triple(tcx.sess).to_string()),
             crate_info: CrateInfo::new(tcx),
         },
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index 637e91f5117..6aadaf8a7ca 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -29,8 +29,7 @@ use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_codegen_ssa::CodegenResults;
 use rustc_errors::ErrorReported;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
-use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::middle::cstore::EncodedMetadata;
 use rustc_session::config::OutputFilenames;
 use rustc_session::Session;
 
@@ -165,17 +164,14 @@ impl CodegenBackend for CraneliftCodegenBackend {
         }
     }
 
-    fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
-        Box::new(rustc_codegen_ssa::back::metadata::DefaultMetadataLoader)
-    }
-
-    fn provide(&self, _providers: &mut Providers) {}
-    fn provide_extern(&self, _providers: &mut Providers) {}
-
     fn target_features(&self, _sess: &Session) -> Vec<rustc_span::Symbol> {
         vec![]
     }
 
+    fn print_version(&self) {
+        println!("Cranelift version: {}", cranelift_codegen::VERSION);
+    }
+
     fn codegen_crate(
         &self,
         tcx: TyCtxt<'_>,
@@ -223,7 +219,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
             sess,
             &codegen_results,
             outputs,
-            &codegen_results.crate_name.as_str(),
+            &codegen_results.crate_info.local_crate_name.as_str(),
         );
 
         Ok(())
diff --git a/compiler/rustc_codegen_cranelift/src/toolchain.rs b/compiler/rustc_codegen_cranelift/src/toolchain.rs
index 484a9b699a0..f86236ef3ea 100644
--- a/compiler/rustc_codegen_cranelift/src/toolchain.rs
+++ b/compiler/rustc_codegen_cranelift/src/toolchain.rs
@@ -2,9 +2,8 @@
 
 use std::path::PathBuf;
 
-use rustc_middle::bug;
+use rustc_codegen_ssa::back::link::linker_and_flavor;
 use rustc_session::Session;
-use rustc_target::spec::LinkerFlavor;
 
 /// Tries to infer the path of a binary for the target toolchain from the linker name.
 pub(crate) fn get_toolchain_binary(sess: &Session, tool: &str) -> PathBuf {
@@ -30,89 +29,3 @@ pub(crate) fn get_toolchain_binary(sess: &Session, tool: &str) -> PathBuf {
 
     linker
 }
-
-// Adapted from https://github.com/rust-lang/rust/blob/5db778affee7c6600c8e7a177c48282dab3f6292/src/librustc_codegen_ssa/back/link.rs#L848-L931
-fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
-    fn infer_from(
-        sess: &Session,
-        linker: Option<PathBuf>,
-        flavor: Option<LinkerFlavor>,
-    ) -> Option<(PathBuf, LinkerFlavor)> {
-        match (linker, flavor) {
-            (Some(linker), Some(flavor)) => Some((linker, flavor)),
-            // only the linker flavor is known; use the default linker for the selected flavor
-            (None, Some(flavor)) => Some((
-                PathBuf::from(match flavor {
-                    LinkerFlavor::Em => {
-                        if cfg!(windows) {
-                            "emcc.bat"
-                        } else {
-                            "emcc"
-                        }
-                    }
-                    LinkerFlavor::Gcc => {
-                        if cfg!(any(target_os = "solaris", target_os = "illumos")) {
-                            // On historical Solaris systems, "cc" may have
-                            // been Sun Studio, which is not flag-compatible
-                            // with "gcc".  This history casts a long shadow,
-                            // and many modern illumos distributions today
-                            // ship GCC as "gcc" without also making it
-                            // available as "cc".
-                            "gcc"
-                        } else {
-                            "cc"
-                        }
-                    }
-                    LinkerFlavor::Ld => "ld",
-                    LinkerFlavor::Msvc => "link.exe",
-                    LinkerFlavor::Lld(_) => "lld",
-                    LinkerFlavor::PtxLinker => "rust-ptx-linker",
-                }),
-                flavor,
-            )),
-            (Some(linker), None) => {
-                let stem = linker.file_stem().and_then(|stem| stem.to_str()).unwrap_or_else(|| {
-                    sess.fatal("couldn't extract file stem from specified linker")
-                });
-
-                let flavor = if stem == "emcc" {
-                    LinkerFlavor::Em
-                } else if stem == "gcc"
-                    || stem.ends_with("-gcc")
-                    || stem == "clang"
-                    || stem.ends_with("-clang")
-                {
-                    LinkerFlavor::Gcc
-                } else if stem == "ld" || stem == "ld.lld" || stem.ends_with("-ld") {
-                    LinkerFlavor::Ld
-                } else if stem == "link" || stem == "lld-link" {
-                    LinkerFlavor::Msvc
-                } else if stem == "lld" || stem == "rust-lld" {
-                    LinkerFlavor::Lld(sess.target.lld_flavor)
-                } else {
-                    // fall back to the value in the target spec
-                    sess.target.linker_flavor
-                };
-
-                Some((linker, flavor))
-            }
-            (None, None) => None,
-        }
-    }
-
-    // linker and linker flavor specified via command line have precedence over what the target
-    // specification specifies
-    if let Some(ret) = infer_from(sess, sess.opts.cg.linker.clone(), sess.opts.cg.linker_flavor) {
-        return ret;
-    }
-
-    if let Some(ret) = infer_from(
-        sess,
-        sess.target.linker.clone().map(PathBuf::from),
-        Some(sess.target.linker_flavor),
-    ) {
-        return ret;
-    }
-
-    bug!("Not enough information provided to determine how to invoke the linker");
-}
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index 0aef77129d8..ecf62ed213d 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -288,6 +288,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
                 InlineAsmArch::Mips | InlineAsmArch::Mips64 => {}
                 InlineAsmArch::SpirV => {}
                 InlineAsmArch::Wasm32 => {}
+                InlineAsmArch::Bpf => {}
             }
         }
         if !options.contains(InlineAsmOptions::NOMEM) {
@@ -593,6 +594,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
             InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
             InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "^Yk",
             InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
+            InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
+            InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
             InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
                 bug!("LLVM backend does not support SPIR-V")
             }
@@ -661,6 +664,7 @@ fn modifier_to_llvm(
         },
         InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None,
         InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None,
+        InlineAsmRegClass::Bpf(_) => None,
         InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
             bug!("LLVM backend does not support SPIR-V")
         }
@@ -708,6 +712,8 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
         | InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(),
         InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(),
         InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
+        InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => cx.type_i64(),
+        InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => cx.type_i32(),
         InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
             bug!("LLVM backend does not support SPIR-V")
         }
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs
index 261affe2c42..64416bced31 100644
--- a/compiler/rustc_codegen_llvm/src/back/archive.rs
+++ b/compiler/rustc_codegen_llvm/src/back/archive.rs
@@ -8,9 +8,11 @@ use std::ptr;
 use std::str;
 
 use crate::llvm::archive_ro::{ArchiveRO, Child};
-use crate::llvm::{self, ArchiveKind};
+use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
 use rustc_codegen_ssa::back::archive::{find_library, ArchiveBuilder};
 use rustc_codegen_ssa::{looks_like_rust_object_file, METADATA_FILENAME};
+use rustc_data_structures::temp_dir::MaybeTempDir;
+use rustc_middle::middle::cstore::DllImport;
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 
@@ -61,6 +63,17 @@ fn archive_config<'a>(sess: &'a Session, output: &Path, input: Option<&Path>) ->
     }
 }
 
+/// Map machine type strings to values of LLVM's MachineTypes enum.
+fn llvm_machine_type(cpu: &str) -> LLVMMachineType {
+    match cpu {
+        "x86_64" => LLVMMachineType::AMD64,
+        "x86" => LLVMMachineType::I386,
+        "aarch64" => LLVMMachineType::ARM64,
+        "arm" => LLVMMachineType::ARM,
+        _ => panic!("unsupported cpu type {}", cpu),
+    }
+}
+
 impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
     /// Creates a new static archive, ready for modifying the archive specified
     /// by `config`.
@@ -175,6 +188,74 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
             self.config.sess.fatal(&format!("failed to build archive: {}", e));
         }
     }
+
+    fn inject_dll_import_lib(
+        &mut self,
+        lib_name: &str,
+        dll_imports: &[DllImport],
+        tmpdir: &MaybeTempDir,
+    ) {
+        let output_path = {
+            let mut output_path: PathBuf = tmpdir.as_ref().to_path_buf();
+            output_path.push(format!("{}_imports", lib_name));
+            output_path.with_extension("lib")
+        };
+
+        // we've checked for \0 characters in the library name already
+        let dll_name_z = CString::new(lib_name).unwrap();
+        // All import names are Rust identifiers and therefore cannot contain \0 characters.
+        // FIXME: when support for #[link_name] implemented, ensure that import.name values don't
+        // have any \0 characters
+        let import_name_vector: Vec<CString> = dll_imports
+            .iter()
+            .map(if self.config.sess.target.arch == "x86" {
+                |import: &DllImport| CString::new(format!("_{}", import.name.to_string())).unwrap()
+            } else {
+                |import: &DllImport| CString::new(import.name.to_string()).unwrap()
+            })
+            .collect();
+
+        let output_path_z = rustc_fs_util::path_to_c_string(&output_path);
+
+        tracing::trace!("invoking LLVMRustWriteImportLibrary");
+        tracing::trace!("  dll_name {:#?}", dll_name_z);
+        tracing::trace!("  output_path {}", output_path.display());
+        tracing::trace!(
+            "  import names: {}",
+            dll_imports.iter().map(|import| import.name.to_string()).collect::<Vec<_>>().join(", "),
+        );
+
+        let ffi_exports: Vec<LLVMRustCOFFShortExport> = import_name_vector
+            .iter()
+            .map(|name_z| LLVMRustCOFFShortExport::from_name(name_z.as_ptr()))
+            .collect();
+        let result = unsafe {
+            crate::llvm::LLVMRustWriteImportLibrary(
+                dll_name_z.as_ptr(),
+                output_path_z.as_ptr(),
+                ffi_exports.as_ptr(),
+                ffi_exports.len(),
+                llvm_machine_type(&self.config.sess.target.arch) as u16,
+                !self.config.sess.target.is_like_msvc,
+            )
+        };
+
+        if result == crate::llvm::LLVMRustResult::Failure {
+            self.config.sess.fatal(&format!(
+                "Error creating import library for {}: {}",
+                lib_name,
+                llvm::last_error().unwrap_or("unknown LLVM error".to_string())
+            ));
+        }
+
+        self.add_archive(&output_path, |_| false).unwrap_or_else(|e| {
+            self.config.sess.fatal(&format!(
+                "failed to add native library {}: {}",
+                output_path.display(),
+                e
+            ));
+        });
+    }
 }
 
 impl<'a> LlvmArchiveBuilder<'a> {
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index bc9d99ed4a1..c8cf0116c64 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -69,6 +69,7 @@ impl abi::HasDataLayout for Builder<'_, '_, '_> {
 }
 
 impl ty::layout::HasTyCtxt<'tcx> for Builder<'_, '_, 'tcx> {
+    #[inline]
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.cx.tcx
     }
@@ -81,6 +82,7 @@ impl ty::layout::HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> {
 }
 
 impl HasTargetSpec for Builder<'_, '_, 'tcx> {
+    #[inline]
     fn target_spec(&self) -> &Target {
         &self.cx.target_spec()
     }
@@ -98,6 +100,7 @@ impl abi::LayoutOf for Builder<'_, '_, 'tcx> {
 impl Deref for Builder<'_, 'll, 'tcx> {
     type Target = CodegenCx<'ll, 'tcx>;
 
+    #[inline]
     fn deref(&self) -> &Self::Target {
         self.cx
     }
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index f5c54b11c08..6aa952462fa 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -765,18 +765,21 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> {
 }
 
 impl HasDataLayout for CodegenCx<'ll, 'tcx> {
+    #[inline]
     fn data_layout(&self) -> &TargetDataLayout {
         &self.tcx.data_layout
     }
 }
 
 impl HasTargetSpec for CodegenCx<'ll, 'tcx> {
+    #[inline]
     fn target_spec(&self) -> &Target {
         &self.tcx.sess.target
     }
 }
 
 impl ty::layout::HasTyCtxt<'tcx> for CodegenCx<'ll, 'tcx> {
+    #[inline]
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 0db6659f8e2..1e70664e64d 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -1457,7 +1457,6 @@ struct EnumMemberDescriptionFactory<'ll, 'tcx> {
     enum_type: Ty<'tcx>,
     layout: TyAndLayout<'tcx>,
     tag_type_metadata: Option<&'ll DIType>,
-    containing_scope: &'ll DIScope,
     common_members: Vec<Option<&'ll DIType>>,
     span: Span,
 }
@@ -1486,13 +1485,9 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
             _ => bug!(),
         };
 
-        // This will always find the metadata in the type map.
         let fallback = use_enum_fallback(cx);
-        let self_metadata = if fallback {
-            self.containing_scope
-        } else {
-            type_metadata(cx, self.enum_type, self.span)
-        };
+        // This will always find the metadata in the type map.
+        let self_metadata = type_metadata(cx, self.enum_type, self.span);
 
         match self.layout.variants {
             Variants::Single { index } => {
@@ -1507,7 +1502,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                     cx,
                     self.layout,
                     variant_info,
-                    NoTag,
+                    None,
                     self_metadata,
                     self.span,
                 );
@@ -1539,13 +1534,26 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                 ..
             } => {
                 let tag_info = if fallback {
-                    RegularTag {
+                    // For MSVC, we generate a union of structs for each variant with an explicit
+                    // discriminant field roughly equivalent to the following C:
+                    // ```c
+                    // union enum$<{name}> {
+                    //   struct {variant 0 name} {
+                    //     tag$ variant$;
+                    //     <variant 0 fields>
+                    //   } variant0;
+                    //   <other variant structs>
+                    // }
+                    // ```
+                    // The natvis in `intrinsic.nativs` then matches on `this.variant0.variant$` to
+                    // determine which variant is active and then displays it.
+                    Some(DirectTag {
                         tag_field: Field::from(tag_field),
                         tag_type_metadata: self.tag_type_metadata.unwrap(),
-                    }
+                    })
                 } else {
                     // This doesn't matter in this case.
-                    NoTag
+                    None
                 };
                 variants
                     .iter_enumerated()
@@ -1574,7 +1582,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
 
                         MemberDescription {
                             name: if fallback {
-                                String::new()
+                                format!("variant{}", i.as_u32())
                             } else {
                                 variant_info.variant_name()
                             },
@@ -1599,77 +1607,135 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                 ref variants,
                 tag_field,
             } => {
+                let calculate_niche_value = |i: VariantIdx| {
+                    if i == dataful_variant {
+                        None
+                    } else {
+                        let value = (i.as_u32() as u128)
+                            .wrapping_sub(niche_variants.start().as_u32() as u128)
+                            .wrapping_add(niche_start);
+                        let value = tag.value.size(cx).truncate(value);
+                        // NOTE(eddyb) do *NOT* remove this assert, until
+                        // we pass the full 128-bit value to LLVM, otherwise
+                        // truncation will be silent and remain undetected.
+                        assert_eq!(value as u64 as u128, value);
+                        Some(value as u64)
+                    }
+                };
+
+                // For MSVC, we will generate a union of two fields, one for the dataful variant
+                // and one that just points to the discriminant. We also create an enum that
+                // contains tag values for the non-dataful variants and make the discriminant field
+                // that type. We then use natvis to render the enum type correctly in Windbg/VS.
+                // This will generate debuginfo roughly equivalent to the following C:
+                // ```c
+                // union enum$<{name}, {min niche}, {max niche}, {dataful variant name}> {
+                //   struct <dataful variant name> {
+                //     <fields in dataful variant>
+                //   } dataful_variant;
+                //   enum Discriminant$ {
+                //     <non-dataful variants>
+                //   } discriminant;
+                // }
+                // ```
+                // The natvis in `intrinsic.natvis` matches on the type name `enum$<*, *, *, *>`
+                // and evaluates `this.discriminant`. If the value is between the min niche and max
+                // niche, then the enum is in the dataful variant and `this.dataful_variant` is
+                // rendered. Otherwise, the enum is in one of the non-dataful variants. In that
+                // case, we just need to render the name of the `this.discriminant` enum.
                 if fallback {
-                    let variant = self.layout.for_variant(cx, dataful_variant);
-                    // Create a description of the non-null variant.
-                    let (variant_type_metadata, member_description_factory) = describe_enum_variant(
+                    let dataful_variant_layout = self.layout.for_variant(cx, dataful_variant);
+
+                    let mut discr_enum_ty = tag.value.to_ty(cx.tcx);
+                    // If the niche is the NULL value of a reference, then `discr_enum_ty` will be a RawPtr.
+                    // CodeView doesn't know what to do with enums whose base type is a pointer so we fix this up
+                    // to just be `usize`.
+                    if let ty::RawPtr(_) = discr_enum_ty.kind() {
+                        discr_enum_ty = cx.tcx.types.usize;
+                    }
+
+                    let tags: Vec<_> = variants
+                        .iter_enumerated()
+                        .filter_map(|(variant_idx, _)| {
+                            calculate_niche_value(variant_idx).map(|tag| {
+                                let variant = variant_info_for(variant_idx);
+                                let name = variant.variant_name();
+
+                                Some(unsafe {
+                                    llvm::LLVMRustDIBuilderCreateEnumerator(
+                                        DIB(cx),
+                                        name.as_ptr().cast(),
+                                        name.len(),
+                                        tag as i64,
+                                        !discr_enum_ty.is_signed(),
+                                    )
+                                })
+                            })
+                        })
+                        .collect();
+
+                    let discr_enum = unsafe {
+                        llvm::LLVMRustDIBuilderCreateEnumerationType(
+                            DIB(cx),
+                            self_metadata,
+                            "Discriminant$".as_ptr().cast(),
+                            "Discriminant$".len(),
+                            unknown_file_metadata(cx),
+                            UNKNOWN_LINE_NUMBER,
+                            tag.value.size(cx).bits(),
+                            tag.value.align(cx).abi.bits() as u32,
+                            create_DIArray(DIB(cx), &tags),
+                            type_metadata(cx, discr_enum_ty, self.span),
+                            true,
+                        )
+                    };
+
+                    let variant_info = variant_info_for(dataful_variant);
+                    let (variant_type_metadata, member_desc_factory) = describe_enum_variant(
                         cx,
-                        variant,
-                        variant_info_for(dataful_variant),
-                        OptimizedTag,
-                        self.containing_scope,
+                        dataful_variant_layout,
+                        variant_info,
+                        Some(NicheTag),
+                        self_metadata,
                         self.span,
                     );
 
-                    let variant_member_descriptions =
-                        member_description_factory.create_member_descriptions(cx);
+                    let member_descriptions = member_desc_factory.create_member_descriptions(cx);
 
                     set_members_of_composite_type(
                         cx,
                         self.enum_type,
                         variant_type_metadata,
-                        variant_member_descriptions,
+                        member_descriptions,
                         Some(&self.common_members),
                     );
 
-                    // Encode the information about the null variant in the union
-                    // member's name.
-                    let mut name = String::from("RUST$ENCODED$ENUM$");
-                    // Right now it's not even going to work for `niche_start > 0`,
-                    // and for multiple niche variants it only supports the first.
-                    fn compute_field_path<'a, 'tcx>(
-                        cx: &CodegenCx<'a, 'tcx>,
-                        name: &mut String,
-                        layout: TyAndLayout<'tcx>,
-                        offset: Size,
-                        size: Size,
-                    ) {
-                        for i in 0..layout.fields.count() {
-                            let field_offset = layout.fields.offset(i);
-                            if field_offset > offset {
-                                continue;
-                            }
-                            let inner_offset = offset - field_offset;
-                            let field = layout.field(cx, i);
-                            if inner_offset + size <= field.size {
-                                write!(name, "{}$", i).unwrap();
-                                compute_field_path(cx, name, field, inner_offset, size);
-                            }
-                        }
-                    }
-                    compute_field_path(
-                        cx,
-                        &mut name,
-                        self.layout,
-                        self.layout.fields.offset(tag_field),
-                        self.layout.field(cx, tag_field).size,
-                    );
-                    let variant_info = variant_info_for(*niche_variants.start());
-                    variant_info.map_struct_name(|variant_name| {
-                        name.push_str(variant_name);
-                    });
-
-                    // Create the (singleton) list of descriptions of union members.
-                    vec![MemberDescription {
-                        name,
-                        type_metadata: variant_type_metadata,
-                        offset: Size::ZERO,
-                        size: variant.size,
-                        align: variant.align.abi,
-                        flags: DIFlags::FlagZero,
-                        discriminant: None,
-                        source_info: variant_info.source_info(cx),
-                    }]
+                    let (size, align) =
+                        cx.size_and_align_of(dataful_variant_layout.field(cx, tag_field).ty);
+
+                    vec![
+                        MemberDescription {
+                            // Name the dataful variant so that we can identify it for natvis
+                            name: "dataful_variant".to_string(),
+                            type_metadata: variant_type_metadata,
+                            offset: Size::ZERO,
+                            size: self.layout.size,
+                            align: self.layout.align.abi,
+                            flags: DIFlags::FlagZero,
+                            discriminant: None,
+                            source_info: variant_info.source_info(cx),
+                        },
+                        MemberDescription {
+                            name: "discriminant".into(),
+                            type_metadata: discr_enum,
+                            offset: dataful_variant_layout.fields.offset(tag_field),
+                            size,
+                            align,
+                            flags: DIFlags::FlagZero,
+                            discriminant: None,
+                            source_info: None,
+                        },
+                    ]
                 } else {
                     variants
                         .iter_enumerated()
@@ -1681,7 +1747,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                                     cx,
                                     variant,
                                     variant_info,
-                                    OptimizedTag,
+                                    Some(NicheTag),
                                     self_metadata,
                                     self.span,
                                 );
@@ -1697,19 +1763,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
                                 Some(&self.common_members),
                             );
 
-                            let niche_value = if i == dataful_variant {
-                                None
-                            } else {
-                                let value = (i.as_u32() as u128)
-                                    .wrapping_sub(niche_variants.start().as_u32() as u128)
-                                    .wrapping_add(niche_start);
-                                let value = tag.value.size(cx).truncate(value);
-                                // NOTE(eddyb) do *NOT* remove this assert, until
-                                // we pass the full 128-bit value to LLVM, otherwise
-                                // truncation will be silent and remain undetected.
-                                assert_eq!(value as u64 as u128, value);
-                                Some(value as u64)
-                            };
+                            let niche_value = calculate_niche_value(i);
 
                             MemberDescription {
                                 name: variant_info.variant_name(),
@@ -1771,14 +1825,10 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> {
     }
 }
 
-// FIXME: terminology here should be aligned with `abi::TagEncoding`.
-// `OptimizedTag` is `TagEncoding::Niche`, `RegularTag` is `TagEncoding::Direct`.
-// `NoTag` should be removed; users should use `Option<EnumTagInfo>` instead.
 #[derive(Copy, Clone)]
 enum EnumTagInfo<'ll> {
-    RegularTag { tag_field: Field, tag_type_metadata: &'ll DIType },
-    OptimizedTag,
-    NoTag,
+    DirectTag { tag_field: Field, tag_type_metadata: &'ll DIType },
+    NicheTag,
 }
 
 #[derive(Copy, Clone)]
@@ -1859,7 +1909,7 @@ fn describe_enum_variant(
     cx: &CodegenCx<'ll, 'tcx>,
     layout: layout::TyAndLayout<'tcx>,
     variant: VariantInfo<'_, 'tcx>,
-    discriminant_info: EnumTagInfo<'ll>,
+    discriminant_info: Option<EnumTagInfo<'ll>>,
     containing_scope: &'ll DIScope,
     span: Span,
 ) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) {
@@ -1882,12 +1932,11 @@ fn describe_enum_variant(
     let (offsets, args) = if use_enum_fallback(cx) {
         // If this is not a univariant enum, there is also the discriminant field.
         let (discr_offset, discr_arg) = match discriminant_info {
-            RegularTag { tag_field, .. } => {
+            Some(DirectTag { tag_field, .. }) => {
                 // We have the layout of an enum variant, we need the layout of the outer enum
                 let enum_layout = cx.layout_of(layout.ty);
                 let offset = enum_layout.fields.offset(tag_field.as_usize());
-                let args =
-                    ("RUST$ENUM$DISR".to_owned(), enum_layout.field(cx, tag_field.as_usize()).ty);
+                let args = ("variant$".to_owned(), enum_layout.field(cx, tag_field.as_usize()).ty);
                 (Some(offset), Some(args))
             }
             _ => (None, None),
@@ -1918,7 +1967,7 @@ fn describe_enum_variant(
         offsets,
         args,
         tag_type_metadata: match discriminant_info {
-            RegularTag { tag_type_metadata, .. } => Some(tag_type_metadata),
+            Some(DirectTag { tag_type_metadata, .. }) => Some(tag_type_metadata),
             _ => None,
         },
         span,
@@ -2048,9 +2097,9 @@ fn prepare_enum_metadata(
 
     if use_enum_fallback(cx) {
         let discriminant_type_metadata = match layout.variants {
-            Variants::Single { .. }
-            | Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => None,
-            Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. } => {
+            Variants::Single { .. } => None,
+            Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, ref tag, .. }
+            | Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. } => {
                 Some(discriminant_type_metadata(tag.value))
             }
         };
@@ -2062,7 +2111,7 @@ fn prepare_enum_metadata(
             unsafe {
                 llvm::LLVMRustDIBuilderCreateUnionType(
                     DIB(cx),
-                    containing_scope,
+                    None,
                     enum_name.as_ptr().cast(),
                     enum_name.len(),
                     file_metadata,
@@ -2088,7 +2137,6 @@ fn prepare_enum_metadata(
                 enum_type,
                 layout,
                 tag_type_metadata: discriminant_type_metadata,
-                containing_scope,
                 common_members: vec![],
                 span,
             }),
@@ -2241,7 +2289,6 @@ fn prepare_enum_metadata(
             enum_type,
             layout,
             tag_type_metadata: None,
-            containing_scope,
             common_members: outer_fields,
             span,
         }),
@@ -2437,7 +2484,7 @@ fn create_union_stub(
 
         llvm::LLVMRustDIBuilderCreateUnionType(
             DIB(cx),
-            containing_scope,
+            Some(containing_scope),
             union_type_name.as_ptr().cast(),
             union_type_name.len(),
             unknown_file_metadata(cx),
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 728f1224dd8..776cb2ee99b 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -29,8 +29,8 @@ use rustc_codegen_ssa::{CodegenResults, CompiledModule};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{ErrorReported, FatalError, Handler};
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
-use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::middle::cstore::EncodedMetadata;
+use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{OptLevel, OutputFilenames, PrintRequest};
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
@@ -248,13 +248,6 @@ impl CodegenBackend for LlvmCodegenBackend {
         target_features(sess)
     }
 
-    fn metadata_loader(&self) -> Box<MetadataLoaderDyn> {
-        Box::new(rustc_codegen_ssa::back::metadata::DefaultMetadataLoader)
-    }
-
-    fn provide(&self, _providers: &mut ty::query::Providers) {}
-    fn provide_extern(&self, _providers: &mut ty::query::Providers) {}
-
     fn codegen_crate<'tcx>(
         &self,
         tcx: TyCtxt<'tcx>,
@@ -304,7 +297,7 @@ impl CodegenBackend for LlvmCodegenBackend {
             sess,
             &codegen_results,
             outputs,
-            &codegen_results.crate_name.as_str(),
+            &codegen_results.crate_info.local_crate_name.as_str(),
         );
 
         Ok(())
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 8b1dcea3fa2..91923251018 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -29,6 +29,31 @@ pub enum LLVMRustResult {
     Success,
     Failure,
 }
+
+// Rust version of the C struct with the same name in rustc_llvm/llvm-wrapper/RustWrapper.cpp.
+#[repr(C)]
+pub struct LLVMRustCOFFShortExport {
+    pub name: *const c_char,
+}
+
+impl LLVMRustCOFFShortExport {
+    pub fn from_name(name: *const c_char) -> LLVMRustCOFFShortExport {
+        LLVMRustCOFFShortExport { name }
+    }
+}
+
+/// Translation of LLVM's MachineTypes enum, defined in llvm\include\llvm\BinaryFormat\COFF.h.
+///
+/// We include only architectures supported on Windows.
+#[derive(Copy, Clone, PartialEq)]
+#[repr(C)]
+pub enum LLVMMachineType {
+    AMD64 = 0x8664,
+    I386 = 0x14c,
+    ARM64 = 0xaa64,
+    ARM = 0x01c0,
+}
+
 // Consts for the LLVM CallConv type, pre-cast to usize.
 
 /// LLVM CallingConv::ID. Should we wrap this?
@@ -583,11 +608,6 @@ extern "C" {
     pub type PassManagerBuilder;
 }
 extern "C" {
-    pub type ObjectFile;
-}
-#[repr(C)]
-pub struct SectionIterator<'a>(InvariantOpaque<'a>);
-extern "C" {
     pub type Pass;
 }
 extern "C" {
@@ -1703,35 +1723,6 @@ extern "C" {
 
     pub fn LLVMDisposeMessage(message: *mut c_char);
 
-    // Stuff that's in llvm-wrapper/ because it's not upstream yet.
-
-    /// Opens an object file.
-    pub fn LLVMCreateObjectFile(
-        MemBuf: &'static mut MemoryBuffer,
-    ) -> Option<&'static mut ObjectFile>;
-    /// Closes an object file.
-    pub fn LLVMDisposeObjectFile(ObjFile: &'static mut ObjectFile);
-
-    /// Enumerates the sections in an object file.
-    pub fn LLVMGetSections(ObjFile: &'a ObjectFile) -> &'a mut SectionIterator<'a>;
-    /// Destroys a section iterator.
-    pub fn LLVMDisposeSectionIterator(SI: &'a mut SectionIterator<'a>);
-    /// Returns `true` if the section iterator is at the end of the section
-    /// list:
-    pub fn LLVMIsSectionIteratorAtEnd(ObjFile: &'a ObjectFile, SI: &SectionIterator<'a>) -> Bool;
-    /// Moves the section iterator to point to the next section.
-    pub fn LLVMMoveToNextSection(SI: &SectionIterator<'_>);
-    /// Returns the current section size.
-    pub fn LLVMGetSectionSize(SI: &SectionIterator<'_>) -> c_ulonglong;
-    /// Returns the current section contents as a string buffer.
-    pub fn LLVMGetSectionContents(SI: &SectionIterator<'_>) -> *const c_char;
-
-    /// Reads the given file and returns it as a memory buffer. Use
-    /// LLVMDisposeMemoryBuffer() to get rid of it.
-    pub fn LLVMRustCreateMemoryBufferWithContentsOfFile(
-        Path: *const c_char,
-    ) -> Option<&'static mut MemoryBuffer>;
-
     pub fn LLVMStartMultithreaded() -> Bool;
 
     /// Returns a string describing the last error caused by an LLVMRust* call.
@@ -2038,7 +2029,7 @@ extern "C" {
 
     pub fn LLVMRustDIBuilderCreateUnionType(
         Builder: &DIBuilder<'a>,
-        Scope: &'a DIScope,
+        Scope: Option<&'a DIScope>,
         Name: *const c_char,
         NameLen: size_t,
         File: &'a DIFile,
@@ -2237,12 +2228,6 @@ extern "C" {
     pub fn LLVMRustDestroyArchive(AR: &'static mut Archive);
 
     #[allow(improper_ctypes)]
-    pub fn LLVMRustGetSectionName(
-        SI: &SectionIterator<'_>,
-        data: &mut Option<std::ptr::NonNull<c_char>>,
-    ) -> size_t;
-
-    #[allow(improper_ctypes)]
     pub fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString);
 
     pub fn LLVMContextSetDiagnosticHandler(
@@ -2305,6 +2290,15 @@ extern "C" {
     ) -> &'a mut RustArchiveMember<'a>;
     pub fn LLVMRustArchiveMemberFree(Member: &'a mut RustArchiveMember<'a>);
 
+    pub fn LLVMRustWriteImportLibrary(
+        ImportName: *const c_char,
+        Path: *const c_char,
+        Exports: *const LLVMRustCOFFShortExport,
+        NumExports: usize,
+        Machine: u16,
+        MinGW: bool,
+    ) -> LLVMRustResult;
+
     pub fn LLVMRustSetDataLayoutFromTargetMachine(M: &'a Module, TM: &'a TargetMachine);
 
     pub fn LLVMRustBuildOperandBundleDef(
diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
index bb9c6d47373..38d56f87211 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
@@ -150,50 +150,6 @@ impl Attribute {
     }
 }
 
-// Memory-managed interface to object files.
-
-pub struct ObjectFile {
-    pub llof: &'static mut ffi::ObjectFile,
-}
-
-unsafe impl Send for ObjectFile {}
-
-impl ObjectFile {
-    // This will take ownership of llmb
-    pub fn new(llmb: &'static mut MemoryBuffer) -> Option<ObjectFile> {
-        unsafe {
-            let llof = LLVMCreateObjectFile(llmb)?;
-            Some(ObjectFile { llof })
-        }
-    }
-}
-
-impl Drop for ObjectFile {
-    fn drop(&mut self) {
-        unsafe {
-            LLVMDisposeObjectFile(&mut *(self.llof as *mut _));
-        }
-    }
-}
-
-// Memory-managed interface to section iterators.
-
-pub struct SectionIter<'a> {
-    pub llsi: &'a mut SectionIterator<'a>,
-}
-
-impl Drop for SectionIter<'a> {
-    fn drop(&mut self) {
-        unsafe {
-            LLVMDisposeSectionIterator(&mut *(self.llsi as *mut _));
-        }
-    }
-}
-
-pub fn mk_section_iter(llof: &ffi::ObjectFile) -> SectionIter<'_> {
-    unsafe { SectionIter { llsi: LLVMGetSections(llof) } }
-}
-
 pub fn set_section(llglobal: &Value, section_name: &str) {
     let section_name_cstr = CString::new(section_name).expect("unexpected CString error");
     unsafe {
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index 3a677a2437c..9bd5764f073 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -35,6 +35,6 @@ rustc_target = { path = "../rustc_target" }
 rustc_session = { path = "../rustc_session" }
 
 [dependencies.object]
-version = "0.22.0"
+version = "0.25.2"
 default-features = false
-features = ["read_core", "elf", "macho", "pe", "unaligned", "archive"]
+features = ["read_core", "elf", "macho", "pe", "unaligned", "archive", "write"]
diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs
index c197d48d4ea..63f457bb979 100644
--- a/compiler/rustc_codegen_ssa/src/back/archive.rs
+++ b/compiler/rustc_codegen_ssa/src/back/archive.rs
@@ -1,3 +1,5 @@
+use rustc_data_structures::temp_dir::MaybeTempDir;
+use rustc_middle::middle::cstore::DllImport;
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 
@@ -57,4 +59,11 @@ pub trait ArchiveBuilder<'a> {
     fn update_symbols(&mut self);
 
     fn build(self);
+
+    fn inject_dll_import_lib(
+        &mut self,
+        lib_name: &str,
+        dll_imports: &[DllImport],
+        tmpdir: &MaybeTempDir,
+    );
 }
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 32275e9b073..6a2005b4d23 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -1,9 +1,9 @@
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::temp_dir::MaybeTempDir;
 use rustc_errors::Handler;
 use rustc_fs_util::fix_windows_verbatim_for_gcc;
 use rustc_hir::def_id::CrateNum;
-use rustc_middle::middle::cstore::{EncodedMetadata, LibSource};
+use rustc_middle::middle::cstore::{DllImport, LibSource};
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_session::config::{self, CFGuard, CrateType, DebugInfo};
 use rustc_session::config::{OutputFilenames, OutputType, PrintRequest};
@@ -14,6 +14,7 @@ use rustc_session::utils::NativeLibKind;
 /// need out of the shared crate context before we get rid of it.
 use rustc_session::{filesearch, Session};
 use rustc_span::symbol::Symbol;
+use rustc_target::abi::Endian;
 use rustc_target::spec::crt_objects::{CrtObjects, CrtObjectsFallback};
 use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo};
 use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target};
@@ -28,8 +29,12 @@ use crate::{
 };
 
 use cc::windows_registry;
+use object::elf;
+use object::write::Object;
+use object::{Architecture, BinaryFormat, Endianness, FileFlags, SectionFlags, SectionKind};
 use tempfile::Builder as TempFileBuilder;
 
+use std::cmp::Ordering;
 use std::ffi::OsString;
 use std::path::{Path, PathBuf};
 use std::process::{ExitStatus, Output, Stdio};
@@ -278,9 +283,9 @@ pub fn each_linked_rlib(
 /// building an `.rlib` (stomping over one another), or writing an `.rmeta` into a
 /// directory being searched for `extern crate` (observing an incomplete file).
 /// The returned path is the temporary file containing the complete metadata.
-pub fn emit_metadata(sess: &Session, metadata: &EncodedMetadata, tmpdir: &MaybeTempDir) -> PathBuf {
+pub fn emit_metadata(sess: &Session, metadata: &[u8], tmpdir: &MaybeTempDir) -> PathBuf {
     let out_filename = tmpdir.as_ref().join(METADATA_FILENAME);
-    let result = fs::write(&out_filename, &metadata.raw_data);
+    let result = fs::write(&out_filename, metadata);
 
     if let Err(e) = result {
         sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
@@ -339,6 +344,12 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
         }
     }
 
+    for (raw_dylib_name, raw_dylib_imports) in
+        collate_raw_dylibs(&codegen_results.crate_info.used_libraries)
+    {
+        ab.inject_dll_import_lib(&raw_dylib_name, &raw_dylib_imports, tmpdir);
+    }
+
     // After adding all files to the archive, we need to update the
     // symbol table of the archive.
     ab.update_symbols();
@@ -366,9 +377,11 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
     // code above.
     match flavor {
         RlibFlavor::Normal => {
-            // Instead of putting the metadata in an object file section, rlibs
-            // contain the metadata in a separate file.
-            ab.add_file(&emit_metadata(sess, &codegen_results.metadata, tmpdir));
+            // metadata in rlib files is wrapped in a "dummy" object file for
+            // the target platform so the rlib can be processed entirely by
+            // normal linkers for the platform.
+            let metadata = create_metadata_file(sess, &codegen_results.metadata.raw_data);
+            ab.add_file(&emit_metadata(sess, &metadata, tmpdir));
 
             // After adding all files to the archive, we need to update the
             // symbol table of the archive. This currently dies on macOS (see
@@ -385,8 +398,188 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
             }
         }
     }
+    return ab;
+
+    // For rlibs we "pack" rustc metadata into a dummy object file. When rustc
+    // creates a dylib crate type it will pass `--whole-archive` (or the
+    // platform equivalent) to include all object files from an rlib into the
+    // final dylib itself. This causes linkers to iterate and try to include all
+    // files located in an archive, so if metadata is stored in an archive then
+    // it needs to be of a form that the linker will be able to process.
+    //
+    // Note, though, that we don't actually want this metadata to show up in any
+    // final output of the compiler. Instead this is purely for rustc's own
+    // metadata tracking purposes.
+    //
+    // With the above in mind, each "flavor" of object format gets special
+    // handling here depending on the target:
+    //
+    // * MachO - macos-like targets will insert the metadata into a section that
+    //   is sort of fake dwarf debug info. Inspecting the source of the macos
+    //   linker this causes these sections to be skipped automatically because
+    //   it's not in an allowlist of otherwise well known dwarf section names to
+    //   go into the final artifact.
+    //
+    // * WebAssembly - we actually don't have any container format for this
+    //   target. WebAssembly doesn't support the `dylib` crate type anyway so
+    //   there's no need for us to support this at this time. Consequently the
+    //   metadata bytes are simply stored as-is into an rlib.
+    //
+    // * COFF - Windows-like targets create an object with a section that has
+    //   the `IMAGE_SCN_LNK_REMOVE` flag set which ensures that if the linker
+    //   ever sees the section it doesn't process it and it's removed.
+    //
+    // * ELF - All other targets are similar to Windows in that there's a
+    //   `SHF_EXCLUDE` flag we can set on sections in an object file to get
+    //   automatically removed from the final output.
+    //
+    // Note that this metdata format is kept in sync with
+    // `rustc_codegen_ssa/src/back/metadata.rs`.
+    fn create_metadata_file(sess: &Session, metadata: &[u8]) -> Vec<u8> {
+        let endianness = match sess.target.options.endian {
+            Endian::Little => Endianness::Little,
+            Endian::Big => Endianness::Big,
+        };
+        let architecture = match &sess.target.arch[..] {
+            "arm" => Architecture::Arm,
+            "aarch64" => Architecture::Aarch64,
+            "x86" => Architecture::I386,
+            "s390x" => Architecture::S390x,
+            "mips" => Architecture::Mips,
+            "mips64" => Architecture::Mips64,
+            "x86_64" => {
+                if sess.target.pointer_width == 32 {
+                    Architecture::X86_64_X32
+                } else {
+                    Architecture::X86_64
+                }
+            }
+            "powerpc" => Architecture::PowerPc,
+            "powerpc64" => Architecture::PowerPc64,
+            "riscv32" => Architecture::Riscv32,
+            "riscv64" => Architecture::Riscv64,
+            "sparc64" => Architecture::Sparc64,
+
+            // This is used to handle all "other" targets. This includes targets
+            // in two categories:
+            //
+            // * Some targets don't have support in the `object` crate just yet
+            //   to write an object file. These targets are likely to get filled
+            //   out over time.
+            //
+            // * Targets like WebAssembly don't support dylibs, so the purpose
+            //   of putting metadata in object files, to support linking rlibs
+            //   into dylibs, is moot.
+            //
+            // In both of these cases it means that linking into dylibs will
+            // not be supported by rustc. This doesn't matter for targets like
+            // WebAssembly and for targets not supported by the `object` crate
+            // yet it means that work will need to be done in the `object` crate
+            // to add a case above.
+            _ => return metadata.to_vec(),
+        };
+
+        if sess.target.is_like_osx {
+            let mut file = Object::new(BinaryFormat::MachO, architecture, endianness);
+
+            let section =
+                file.add_section(b"__DWARF".to_vec(), b".rmeta".to_vec(), SectionKind::Debug);
+            file.append_section_data(section, metadata, 1);
+            file.write().unwrap()
+        } else if sess.target.is_like_windows {
+            const IMAGE_SCN_LNK_REMOVE: u32 = 0;
+            let mut file = Object::new(BinaryFormat::Coff, architecture, endianness);
+
+            let section = file.add_section(Vec::new(), b".rmeta".to_vec(), SectionKind::Debug);
+            file.section_mut(section).flags =
+                SectionFlags::Coff { characteristics: IMAGE_SCN_LNK_REMOVE };
+            file.append_section_data(section, metadata, 1);
+            file.write().unwrap()
+        } else {
+            const SHF_EXCLUDE: u64 = 0x80000000;
+            let mut file = Object::new(BinaryFormat::Elf, architecture, endianness);
+
+            match &sess.target.arch[..] {
+                // copied from `mipsel-linux-gnu-gcc foo.c -c` and
+                // inspecting the resulting `e_flags` field.
+                "mips" => {
+                    let e_flags = elf::EF_MIPS_ARCH_32R2 | elf::EF_MIPS_CPIC | elf::EF_MIPS_PIC;
+                    file.flags = FileFlags::Elf { e_flags };
+                }
+                // copied from `mips64el-linux-gnuabi64-gcc foo.c -c`
+                "mips64" => {
+                    let e_flags = elf::EF_MIPS_ARCH_64R2 | elf::EF_MIPS_CPIC | elf::EF_MIPS_PIC;
+                    file.flags = FileFlags::Elf { e_flags };
+                }
+
+                // copied from `riscv64-linux-gnu-gcc foo.c -c`, note though
+                // that the `+d` target feature represents whether the double
+                // float abi is enabled.
+                "riscv64" if sess.target.options.features.contains("+d") => {
+                    let e_flags = elf::EF_RISCV_RVC | elf::EF_RISCV_FLOAT_ABI_DOUBLE;
+                    file.flags = FileFlags::Elf { e_flags };
+                }
+
+                _ => {}
+            }
+
+            let section = file.add_section(Vec::new(), b".rmeta".to_vec(), SectionKind::Debug);
+            file.section_mut(section).flags = SectionFlags::Elf { sh_flags: SHF_EXCLUDE };
+            file.append_section_data(section, metadata, 1);
+            file.write().unwrap()
+        }
+    }
+}
+
+/// Extract all symbols defined in raw-dylib libraries, collated by library name.
+///
+/// If we have multiple extern blocks that specify symbols defined in the same raw-dylib library,
+/// then the CodegenResults value contains one NativeLib instance for each block.  However, the
+/// linker appears to expect only a single import library for each library used, so we need to
+/// collate the symbols together by library name before generating the import libraries.
+fn collate_raw_dylibs(used_libraries: &[NativeLib]) -> Vec<(String, Vec<DllImport>)> {
+    let mut dylib_table: FxHashMap<String, FxHashSet<Symbol>> = FxHashMap::default();
+
+    for lib in used_libraries {
+        if lib.kind == NativeLibKind::RawDylib {
+            let name = lib.name.unwrap_or_else(||
+                bug!("`link` attribute with kind = \"raw-dylib\" and no name should have caused error earlier")
+            );
+            let name = if matches!(lib.verbatim, Some(true)) {
+                name.to_string()
+            } else {
+                format!("{}.dll", name)
+            };
+            dylib_table
+                .entry(name)
+                .or_default()
+                .extend(lib.dll_imports.iter().map(|import| import.name));
+        }
+    }
 
-    ab
+    // FIXME: when we add support for ordinals, fix this to propagate ordinals.  Also figure out
+    // what we should do if we have two DllImport values with the same name but different
+    // ordinals.
+    let mut result = dylib_table
+        .into_iter()
+        .map(|(lib_name, imported_names)| {
+            let mut names = imported_names
+                .iter()
+                .map(|name| DllImport { name: *name, ordinal: None })
+                .collect::<Vec<_>>();
+            names.sort_unstable_by(|a: &DllImport, b: &DllImport| {
+                match a.name.as_str().cmp(&b.name.as_str()) {
+                    Ordering::Equal => a.ordinal.cmp(&b.ordinal),
+                    x => x,
+                }
+            });
+            (lib_name, names)
+        })
+        .collect::<Vec<_>>();
+    result.sort_unstable_by(|a: &(String, Vec<DllImport>), b: &(String, Vec<DllImport>)| {
+        a.0.cmp(&b.0)
+    });
+    result
 }
 
 /// Create a static archive.
@@ -865,7 +1058,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
     }
 }
 
-fn link_sanitizers(sess: &Session, crate_type: CrateType, linker: &mut dyn Linker) {
+fn add_sanitizer_libraries(sess: &Session, crate_type: CrateType, linker: &mut dyn Linker) {
     // On macOS the runtimes are distributed as dylibs which should be linked to
     // both executables and dynamic shared objects. Everywhere else the runtimes
     // are currently distributed as static liraries which should be linked to
@@ -954,7 +1147,8 @@ pub fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool
         && (info.compiler_builtins == Some(cnum) || info.is_no_builtins.contains(&cnum))
 }
 
-fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
+// This functions tries to determine the appropriate linker (and corresponding LinkerFlavor) to use
+pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
     fn infer_from(
         sess: &Session,
         linker: Option<PathBuf>,
@@ -989,6 +1183,7 @@ fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
                     LinkerFlavor::Msvc => "link.exe",
                     LinkerFlavor::Lld(_) => "lld",
                     LinkerFlavor::PtxLinker => "rust-ptx-linker",
+                    LinkerFlavor::BpfLinker => "bpf-linker",
                 }),
                 flavor,
             )),
@@ -1005,6 +1200,8 @@ fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
                     || stem.ends_with("-clang")
                 {
                     LinkerFlavor::Gcc
+                } else if stem == "wasm-ld" || stem.ends_with("-wasm-ld") {
+                    LinkerFlavor::Lld(LldFlavor::Wasm)
                 } else if stem == "ld" || stem == "ld.lld" || stem.ends_with("-ld") {
                     LinkerFlavor::Ld
                 } else if stem == "link" || stem == "lld-link" {
@@ -1484,55 +1681,6 @@ fn add_local_crate_metadata_objects(
     }
 }
 
-/// Link native libraries corresponding to the current crate and all libraries corresponding to
-/// all its dependency crates.
-/// FIXME: Consider combining this with the functions above adding object files for the local crate.
-fn link_local_crate_native_libs_and_dependent_crate_libs<'a, B: ArchiveBuilder<'a>>(
-    cmd: &mut dyn Linker,
-    sess: &'a Session,
-    crate_type: CrateType,
-    codegen_results: &CodegenResults,
-    tmpdir: &Path,
-) {
-    // Take careful note of the ordering of the arguments we pass to the linker
-    // here. Linkers will assume that things on the left depend on things to the
-    // right. Things on the right cannot depend on things on the left. This is
-    // all formally implemented in terms of resolving symbols (libs on the right
-    // resolve unknown symbols of libs on the left, but not vice versa).
-    //
-    // For this reason, we have organized the arguments we pass to the linker as
-    // such:
-    //
-    // 1. The local object that LLVM just generated
-    // 2. Local native libraries
-    // 3. Upstream rust libraries
-    // 4. Upstream native libraries
-    //
-    // The rationale behind this ordering is that those items lower down in the
-    // list can't depend on items higher up in the list. For example nothing can
-    // depend on what we just generated (e.g., that'd be a circular dependency).
-    // Upstream rust libraries are not allowed to depend on our local native
-    // libraries as that would violate the structure of the DAG, in that
-    // scenario they are required to link to them as well in a shared fashion.
-    //
-    // Note that upstream rust libraries may contain native dependencies as
-    // well, but they also can't depend on what we just started to add to the
-    // link line. And finally upstream native libraries can't depend on anything
-    // in this DAG so far because they're only dylibs and dylibs can only depend
-    // on other dylibs (e.g., other native deps).
-    //
-    // If -Zlink-native-libraries=false is set, then the assumption is that an
-    // external build system already has the native dependencies defined, and it
-    // will provide them to the linker itself.
-    if sess.opts.debugging_opts.link_native_libraries {
-        add_local_native_libraries(cmd, sess, codegen_results);
-    }
-    add_upstream_rust_crates::<B>(cmd, sess, codegen_results, crate_type, tmpdir);
-    if sess.opts.debugging_opts.link_native_libraries {
-        add_upstream_native_libraries(cmd, sess, codegen_results, crate_type);
-    }
-}
-
 /// Add sysroot and other globally set directories to the directory search list.
 fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session, self_contained: bool) {
     // The default library location, we need this to find the runtime.
@@ -1567,36 +1715,27 @@ fn add_rpath_args(
 ) {
     // FIXME (#2397): At some point we want to rpath our guesses as to
     // where extern libraries might live, based on the
-    // addl_lib_search_paths
+    // add_lib_search_paths
     if sess.opts.cg.rpath {
-        let target_triple = sess.opts.target_triple.triple();
-        let mut get_install_prefix_lib_path = || {
-            let install_prefix = option_env!("CFG_PREFIX").expect("CFG_PREFIX");
-            let tlib = rustc_target::target_rustlib_path(&sess.sysroot, target_triple).join("lib");
-            let mut path = PathBuf::from(install_prefix);
-            path.push(&tlib);
-
-            path
-        };
         let mut rpath_config = RPathConfig {
             used_crates: &codegen_results.crate_info.used_crates_dynamic,
             out_filename: out_filename.to_path_buf(),
             has_rpath: sess.target.has_rpath,
             is_like_osx: sess.target.is_like_osx,
             linker_is_gnu: sess.target.linker_is_gnu,
-            get_install_prefix_lib_path: &mut get_install_prefix_lib_path,
         };
         cmd.args(&rpath::get_rpath_flags(&mut rpath_config));
     }
 }
 
 /// Produce the linker command line containing linker path and arguments.
-/// `NO-OPT-OUT` marks the arguments that cannot be removed from the command line
-/// by the user without creating a custom target specification.
-/// `OBJECT-FILES` specify whether the arguments can add object files.
-/// `CUSTOMIZATION-POINT` means that arbitrary arguments defined by the user
-/// or by the target spec can be inserted here.
-/// `AUDIT-ORDER` - need to figure out whether the option is order-dependent or not.
+///
+/// When comments in the function say "order-(in)dependent" they mean order-dependence between
+/// options and libraries/object files. For example `--whole-archive` (order-dependent) applies
+/// to specific libraries passed after it, and `-o` (output file, order-independent) applies
+/// to the linking process as a whole.
+/// Order-independent options may still override each other in order-dependent fashion,
+/// e.g `--foo=yes --foo=no` may be equivalent to `--foo=no`.
 fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
     path: &Path,
     flavor: LinkerFlavor,
@@ -1614,16 +1753,151 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
     let cmd = &mut *codegen_results.linker_info.to_linker(base_cmd, &sess, flavor);
     let link_output_kind = link_output_kind(sess, crate_type);
 
-    // NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
+    // ------------ Early order-dependent options ------------
+
+    // If we're building something like a dynamic library then some platforms
+    // need to make sure that all symbols are exported correctly from the
+    // dynamic library.
+    // Must be passed before any libraries to prevent the symbols to export from being thrown away,
+    // at least on some platforms (e.g. windows-gnu).
+    cmd.export_symbols(tmpdir, crate_type);
+
+    // Can be used for adding custom CRT objects or overriding order-dependent options above.
+    // FIXME: In practice built-in target specs use this for arbitrary order-independent options,
+    // introduce a target spec option for order-independent linker options and migrate built-in
+    // specs to it.
     add_pre_link_args(cmd, sess, flavor);
 
-    // NO-OPT-OUT, OBJECT-FILES-NO
+    // ------------ Object code and libraries, order-dependent ------------
+
+    // Pre-link CRT objects.
+    add_pre_link_objects(cmd, sess, link_output_kind, crt_objects_fallback);
+
+    // Sanitizer libraries.
+    add_sanitizer_libraries(sess, crate_type, cmd);
+
+    // Object code from the current crate.
+    // Take careful note of the ordering of the arguments we pass to the linker
+    // here. Linkers will assume that things on the left depend on things to the
+    // right. Things on the right cannot depend on things on the left. This is
+    // all formally implemented in terms of resolving symbols (libs on the right
+    // resolve unknown symbols of libs on the left, but not vice versa).
+    //
+    // For this reason, we have organized the arguments we pass to the linker as
+    // such:
+    //
+    // 1. The local object that LLVM just generated
+    // 2. Local native libraries
+    // 3. Upstream rust libraries
+    // 4. Upstream native libraries
+    //
+    // The rationale behind this ordering is that those items lower down in the
+    // list can't depend on items higher up in the list. For example nothing can
+    // depend on what we just generated (e.g., that'd be a circular dependency).
+    // Upstream rust libraries are not supposed to depend on our local native
+    // libraries as that would violate the structure of the DAG, in that
+    // scenario they are required to link to them as well in a shared fashion.
+    // (The current implementation still doesn't prevent it though, see the FIXME below.)
+    //
+    // Note that upstream rust libraries may contain native dependencies as
+    // well, but they also can't depend on what we just started to add to the
+    // link line. And finally upstream native libraries can't depend on anything
+    // in this DAG so far because they can only depend on other native libraries
+    // and such dependencies are also required to be specified.
+    add_local_crate_regular_objects(cmd, codegen_results);
+    add_local_crate_metadata_objects(cmd, crate_type, codegen_results);
+    add_local_crate_allocator_objects(cmd, codegen_results);
+
+    // Avoid linking to dynamic libraries unless they satisfy some undefined symbols
+    // at the point at which they are specified on the command line.
+    // Must be passed before any (dynamic) libraries to have effect on them.
+    // On Solaris-like systems, `-z ignore` acts as both `--as-needed` and `--gc-sections`
+    // so it will ignore unreferenced ELF sections from relocatable objects.
+    // For that reason, we put this flag after metadata objects as they would otherwise be removed.
+    // FIXME: Support more fine-grained dead code removal on Solaris/illumos
+    // and move this option back to the top.
+    cmd.add_as_needed();
+
+    // FIXME: Move this below to other native libraries
+    // (or alternatively link all native libraries after their respective crates).
+    // This change is somewhat breaking in practice due to local static libraries being linked
+    // as whole-archive (#85144), so removing whole-archive may be a pre-requisite.
+    if sess.opts.debugging_opts.link_native_libraries {
+        add_local_native_libraries(cmd, sess, codegen_results);
+    }
+
+    // Rust libraries.
+    add_upstream_rust_crates::<B>(cmd, sess, codegen_results, crate_type, tmpdir);
+
+    // Native libraries linked with `#[link]` attributes at and `-l` command line options.
+    // If -Zlink-native-libraries=false is set, then the assumption is that an
+    // external build system already has the native dependencies defined, and it
+    // will provide them to the linker itself.
+    if sess.opts.debugging_opts.link_native_libraries {
+        add_upstream_native_libraries(cmd, sess, codegen_results, crate_type);
+    }
+
+    // Library linking above uses some global state for things like `-Bstatic`/`-Bdynamic` to make
+    // command line shorter, reset it to default here before adding more libraries.
+    cmd.reset_per_library_state();
+
+    // FIXME: Built-in target specs occasionally use this for linking system libraries,
+    // eliminate all such uses by migrating them to `#[link]` attributes in `lib(std,c,unwind)`
+    // and remove the option.
+    add_late_link_args(cmd, sess, flavor, crate_type, codegen_results);
+
+    // ------------ Arbitrary order-independent options ------------
+
+    // Add order-independent options determined by rustc from its compiler options,
+    // target properties and source code.
+    add_order_independent_options(
+        cmd,
+        sess,
+        link_output_kind,
+        crt_objects_fallback,
+        flavor,
+        crate_type,
+        codegen_results,
+        out_filename,
+        tmpdir,
+    );
+
+    // Can be used for arbitrary order-independent options.
+    // In practice may also be occasionally used for linking native libraries.
+    // Passed after compiler-generated options to support manual overriding when necessary.
+    add_user_defined_link_args(cmd, sess);
+
+    // ------------ Object code and libraries, order-dependent ------------
+
+    // Post-link CRT objects.
+    add_post_link_objects(cmd, sess, link_output_kind, crt_objects_fallback);
+
+    // ------------ Late order-dependent options ------------
+
+    // Doesn't really make sense.
+    // FIXME: In practice built-in target specs use this for arbitrary order-independent options,
+    // introduce a target spec option for order-independent linker options, migrate built-in specs
+    // to it and remove the option.
+    add_post_link_args(cmd, sess, flavor);
+
+    cmd.take_cmd()
+}
+
+fn add_order_independent_options(
+    cmd: &mut dyn Linker,
+    sess: &Session,
+    link_output_kind: LinkOutputKind,
+    crt_objects_fallback: bool,
+    flavor: LinkerFlavor,
+    crate_type: CrateType,
+    codegen_results: &CodegenResults,
+    out_filename: &Path,
+    tmpdir: &Path,
+) {
     add_apple_sdk(cmd, sess, flavor);
 
-    // NO-OPT-OUT
     add_link_script(cmd, sess, tmpdir, crate_type);
 
-    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
     if sess.target.is_like_fuchsia && crate_type == CrateType::Executable {
         let prefix = if sess.opts.debugging_opts.sanitizer.contains(SanitizerSet::ADDRESS) {
             "asan/"
@@ -1633,30 +1907,17 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
         cmd.arg(format!("--dynamic-linker={}ld.so.1", prefix));
     }
 
-    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
     if sess.target.eh_frame_header {
         cmd.add_eh_frame_header();
     }
 
-    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
     // Make the binary compatible with data execution prevention schemes.
     cmd.add_no_exec();
 
-    // NO-OPT-OUT, OBJECT-FILES-NO
-    // Avoid linking to dynamic libraries unless they satisfy some undefined symbols
-    // at the point at which they are specified on the command line.
-    // Must be passed before any dynamic libraries.
-    cmd.add_as_needed();
-
-    // NO-OPT-OUT, OBJECT-FILES-NO
     if crt_objects_fallback {
         cmd.no_crt_objects();
     }
 
-    // NO-OPT-OUT, OBJECT-FILES-YES
-    add_pre_link_objects(cmd, sess, link_output_kind, crt_objects_fallback);
-
-    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
     if sess.target.is_like_emscripten {
         cmd.arg("-s");
         cmd.arg(if sess.panic_strategy() == PanicStrategy::Abort {
@@ -1666,45 +1927,32 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
         });
     }
 
-    // OBJECT-FILES-YES, AUDIT-ORDER
-    link_sanitizers(sess, crate_type, cmd);
+    if flavor == LinkerFlavor::PtxLinker {
+        // Provide the linker with fallback to internal `target-cpu`.
+        cmd.arg("--fallback-arch");
+        cmd.arg(&codegen_results.linker_info.target_cpu);
+    } else if flavor == LinkerFlavor::BpfLinker {
+        cmd.arg("--cpu");
+        cmd.arg(&codegen_results.linker_info.target_cpu);
+        cmd.arg("--cpu-features");
+        cmd.arg(match &sess.opts.cg.target_feature {
+            feat if !feat.is_empty() => feat,
+            _ => &sess.target.options.features,
+        });
+    }
 
-    // OBJECT-FILES-NO, AUDIT-ORDER
-    // Linker plugins should be specified early in the list of arguments
-    // FIXME: How "early" exactly?
     cmd.linker_plugin_lto();
 
-    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
-    // FIXME: Order-dependent, at least relatively to other args adding searh directories.
     add_library_search_dirs(cmd, sess, crt_objects_fallback);
 
-    // OBJECT-FILES-YES
-    add_local_crate_regular_objects(cmd, codegen_results);
-
-    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
     cmd.output_filename(out_filename);
 
-    // OBJECT-FILES-NO, AUDIT-ORDER
     if crate_type == CrateType::Executable && sess.target.is_like_windows {
-        if let Some(ref s) = codegen_results.windows_subsystem {
+        if let Some(ref s) = codegen_results.crate_info.windows_subsystem {
             cmd.subsystem(s);
         }
     }
 
-    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
-    // If we're building something like a dynamic library then some platforms
-    // need to make sure that all symbols are exported correctly from the
-    // dynamic library.
-    cmd.export_symbols(tmpdir, crate_type);
-
-    // OBJECT-FILES-YES
-    add_local_crate_metadata_objects(cmd, crate_type, codegen_results);
-
-    // OBJECT-FILES-YES
-    add_local_crate_allocator_objects(cmd, codegen_results);
-
-    // OBJECT-FILES-NO, AUDIT-ORDER
-    // FIXME: Order dependent, applies to the following objects. Where should it be placed?
     // Try to strip as much out of the generated object by removing unused
     // sections if possible. See more comments in linker.rs
     if !sess.link_dead_code() {
@@ -1712,65 +1960,31 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
         cmd.gc_sections(keep_metadata);
     }
 
-    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
     cmd.set_output_kind(link_output_kind, out_filename);
 
-    // OBJECT-FILES-NO, AUDIT-ORDER
     add_relro_args(cmd, sess);
 
-    // OBJECT-FILES-NO, AUDIT-ORDER
     // Pass optimization flags down to the linker.
     cmd.optimize();
 
-    // OBJECT-FILES-NO, AUDIT-ORDER
     // Pass debuginfo and strip flags down to the linker.
     cmd.debuginfo(sess.opts.debugging_opts.strip);
 
-    // OBJECT-FILES-NO, AUDIT-ORDER
     // We want to prevent the compiler from accidentally leaking in any system libraries,
     // so by default we tell linkers not to link to any default libraries.
     if !sess.opts.cg.default_linker_libraries && sess.target.no_default_libraries {
         cmd.no_default_libraries();
     }
 
-    // OBJECT-FILES-YES
-    link_local_crate_native_libs_and_dependent_crate_libs::<B>(
-        cmd,
-        sess,
-        crate_type,
-        codegen_results,
-        tmpdir,
-    );
-
-    // OBJECT-FILES-NO, AUDIT-ORDER
     if sess.opts.cg.profile_generate.enabled() || sess.instrument_coverage() {
         cmd.pgo_gen();
     }
 
-    // OBJECT-FILES-NO, AUDIT-ORDER
     if sess.opts.cg.control_flow_guard != CFGuard::Disabled {
         cmd.control_flow_guard();
     }
 
-    // OBJECT-FILES-NO, AUDIT-ORDER
     add_rpath_args(cmd, sess, codegen_results, out_filename);
-
-    // OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
-    add_user_defined_link_args(cmd, sess);
-
-    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
-    cmd.finalize();
-
-    // NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
-    add_late_link_args(cmd, sess, flavor, crate_type, codegen_results);
-
-    // NO-OPT-OUT, OBJECT-FILES-YES
-    add_post_link_objects(cmd, sess, link_output_kind, crt_objects_fallback);
-
-    // NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
-    add_post_link_args(cmd, sess, flavor);
-
-    cmd.take_cmd()
 }
 
 /// # Native library linking
@@ -1964,11 +2178,8 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
     }
 
     // Adds the static "rlib" versions of all crates to the command line.
-    // There's a bit of magic which happens here specifically related to LTO and
-    // dynamic libraries. Specifically:
-    //
-    // * For LTO, we remove upstream object files.
-    // * For dylibs we remove metadata and bytecode from upstream rlibs
+    // There's a bit of magic which happens here specifically related to LTO,
+    // namely that we remove upstream object files.
     //
     // When performing LTO, almost(*) all of the bytecode from the upstream
     // libraries has already been included in our object file output. As a
@@ -1981,20 +2192,9 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
     // their bytecode wasn't included. The object files in those libraries must
     // still be passed to the linker.
     //
-    // When making a dynamic library, linkers by default don't include any
-    // object files in an archive if they're not necessary to resolve the link.
-    // We basically want to convert the archive (rlib) to a dylib, though, so we
-    // *do* want everything included in the output, regardless of whether the
-    // linker thinks it's needed or not. As a result we must use the
-    // --whole-archive option (or the platform equivalent). When using this
-    // option the linker will fail if there are non-objects in the archive (such
-    // as our own metadata and/or bytecode). All in all, for rlibs to be
-    // entirely included in dylibs, we need to remove all non-object files.
-    //
-    // Note, however, that if we're not doing LTO or we're not producing a dylib
-    // (aka we're making an executable), we can just pass the rlib blindly to
-    // the linker (fast) because it's fine if it's not actually included as
-    // we're at the end of the dependency chain.
+    // Note, however, that if we're not doing LTO we can just pass the rlib
+    // blindly to the linker (fast) because it's fine if it's not actually
+    // included as we're at the end of the dependency chain.
     fn add_static_crate<'a, B: ArchiveBuilder<'a>>(
         cmd: &mut dyn Linker,
         sess: &'a Session,
@@ -2006,6 +2206,24 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
         let src = &codegen_results.crate_info.used_crate_source[&cnum];
         let cratepath = &src.rlib.as_ref().unwrap().0;
 
+        let mut link_upstream = |path: &Path| {
+            // If we're creating a dylib, then we need to include the
+            // whole of each object in our archive into that artifact. This is
+            // because a `dylib` can be reused as an intermediate artifact.
+            //
+            // Note, though, that we don't want to include the whole of a
+            // compiler-builtins crate (e.g., compiler-rt) because it'll get
+            // repeatedly linked anyway.
+            let path = fix_windows_verbatim_for_gcc(path);
+            if crate_type == CrateType::Dylib
+                && codegen_results.crate_info.compiler_builtins != Some(cnum)
+            {
+                cmd.link_whole_rlib(&path);
+            } else {
+                cmd.link_rlib(&path);
+            }
+        };
+
         // See the comment above in `link_staticlib` and `link_rlib` for why if
         // there's a static library that's not relevant we skip all object
         // files.
@@ -2017,10 +2235,9 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
 
         if (!are_upstream_rust_objects_already_included(sess)
             || ignored_for_lto(sess, &codegen_results.crate_info, cnum))
-            && crate_type != CrateType::Dylib
             && !skip_native
         {
-            cmd.link_rlib(&fix_windows_verbatim_for_gcc(cratepath));
+            link_upstream(cratepath);
             return;
         }
 
@@ -2070,21 +2287,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
                 return;
             }
             archive.build();
-
-            // If we're creating a dylib, then we need to include the
-            // whole of each object in our archive into that artifact. This is
-            // because a `dylib` can be reused as an intermediate artifact.
-            //
-            // Note, though, that we don't want to include the whole of a
-            // compiler-builtins crate (e.g., compiler-rt) because it'll get
-            // repeatedly linked anyway.
-            if crate_type == CrateType::Dylib
-                && codegen_results.crate_info.compiler_builtins != Some(cnum)
-            {
-                cmd.link_whole_rlib(&fix_windows_verbatim_for_gcc(&dst));
-            } else {
-                cmd.link_rlib(&fix_windows_verbatim_for_gcc(&dst));
-            }
+            link_upstream(&dst);
         });
     }
 
@@ -2178,10 +2381,7 @@ fn add_upstream_native_libraries(
                 // already included them when we included the rust library
                 // previously
                 NativeLibKind::Static { bundle: None | Some(true), .. } => {}
-                NativeLibKind::RawDylib => {
-                    // FIXME(#58713): Proper handling for raw dylibs.
-                    bug!("raw_dylib feature not yet implemented");
-                }
+                NativeLibKind::RawDylib => {}
             }
         }
     }
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 4dc9a3f5e41..1d53e9ad8b3 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -37,7 +37,7 @@ pub fn disable_localization(linker: &mut Command) {
 /// need out of the shared crate context before we get rid of it.
 #[derive(Encodable, Decodable)]
 pub struct LinkerInfo {
-    target_cpu: String,
+    pub(super) target_cpu: String,
     exports: FxHashMap<CrateType, Vec<String>>,
 }
 
@@ -81,8 +81,10 @@ impl LinkerInfo {
                 Box::new(WasmLd::new(cmd, sess, self)) as Box<dyn Linker>
             }
 
-            LinkerFlavor::PtxLinker => {
-                Box::new(PtxLinker { cmd, sess, info: self }) as Box<dyn Linker>
+            LinkerFlavor::PtxLinker => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
+
+            LinkerFlavor::BpfLinker => {
+                Box::new(BpfLinker { cmd, sess, info: self }) as Box<dyn Linker>
             }
         }
     }
@@ -128,7 +130,7 @@ pub trait Linker {
     fn add_eh_frame_header(&mut self) {}
     fn add_no_exec(&mut self) {}
     fn add_as_needed(&mut self) {}
-    fn finalize(&mut self);
+    fn reset_per_library_state(&mut self) {}
 }
 
 impl dyn Linker + '_ {
@@ -472,7 +474,9 @@ impl<'a> Linker for GccLinker<'a> {
         // eliminate the metadata. If we're building an executable, however,
         // --gc-sections drops the size of hello world from 1.8MB to 597K, a 67%
         // reduction.
-        } else if self.sess.target.linker_is_gnu && !keep_metadata {
+        } else if (self.sess.target.linker_is_gnu || self.sess.target.is_like_wasm)
+            && !keep_metadata
+        {
             self.linker_arg("--gc-sections");
         }
     }
@@ -480,13 +484,13 @@ impl<'a> Linker for GccLinker<'a> {
     fn no_gc_sections(&mut self) {
         if self.sess.target.is_like_osx {
             self.linker_arg("-no_dead_strip");
-        } else if self.sess.target.linker_is_gnu {
+        } else if self.sess.target.linker_is_gnu || self.sess.target.is_like_wasm {
             self.linker_arg("--no-gc-sections");
         }
     }
 
     fn optimize(&mut self) {
-        if !self.sess.target.linker_is_gnu {
+        if !self.sess.target.linker_is_gnu && !self.sess.target.is_like_wasm {
             return;
         }
 
@@ -647,7 +651,7 @@ impl<'a> Linker for GccLinker<'a> {
         self.linker_arg(&subsystem);
     }
 
-    fn finalize(&mut self) {
+    fn reset_per_library_state(&mut self) {
         self.hint_dynamic(); // Reset to default before returning the composed command line.
     }
 
@@ -931,8 +935,6 @@ impl<'a> Linker for MsvcLinker<'a> {
         }
     }
 
-    fn finalize(&mut self) {}
-
     // MSVC doesn't need group indicators
     fn group_start(&mut self) {}
     fn group_end(&mut self) {}
@@ -1093,8 +1095,6 @@ impl<'a> Linker for EmLinker<'a> {
         // noop
     }
 
-    fn finalize(&mut self) {}
-
     // Appears not necessary on Emscripten
     fn group_start(&mut self) {}
     fn group_end(&mut self) {}
@@ -1275,8 +1275,6 @@ impl<'a> Linker for WasmLd<'a> {
 
     fn subsystem(&mut self, _subsystem: &str) {}
 
-    fn finalize(&mut self) {}
-
     // Not needed for now with LLD
     fn group_start(&mut self) {}
     fn group_end(&mut self) {}
@@ -1330,7 +1328,6 @@ fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
 pub struct PtxLinker<'a> {
     cmd: Command,
     sess: &'a Session,
-    info: &'a LinkerInfo,
 }
 
 impl<'a> Linker for PtxLinker<'a> {
@@ -1374,9 +1371,105 @@ impl<'a> Linker for PtxLinker<'a> {
         self.cmd.arg("-o").arg(path);
     }
 
-    fn finalize(&mut self) {
-        // Provide the linker with fallback to internal `target-cpu`.
-        self.cmd.arg("--fallback-arch").arg(&self.info.target_cpu);
+    fn link_dylib(&mut self, _lib: Symbol, _verbatim: bool, _as_needed: bool) {
+        panic!("external dylibs not supported")
+    }
+
+    fn link_rust_dylib(&mut self, _lib: Symbol, _path: &Path) {
+        panic!("external dylibs not supported")
+    }
+
+    fn link_staticlib(&mut self, _lib: Symbol, _verbatim: bool) {
+        panic!("staticlibs not supported")
+    }
+
+    fn link_whole_staticlib(&mut self, _lib: Symbol, _verbatim: bool, _search_path: &[PathBuf]) {
+        panic!("staticlibs not supported")
+    }
+
+    fn framework_path(&mut self, _path: &Path) {
+        panic!("frameworks not supported")
+    }
+
+    fn link_framework(&mut self, _framework: Symbol, _as_needed: bool) {
+        panic!("frameworks not supported")
+    }
+
+    fn full_relro(&mut self) {}
+
+    fn partial_relro(&mut self) {}
+
+    fn no_relro(&mut self) {}
+
+    fn gc_sections(&mut self, _keep_metadata: bool) {}
+
+    fn no_gc_sections(&mut self) {}
+
+    fn pgo_gen(&mut self) {}
+
+    fn no_crt_objects(&mut self) {}
+
+    fn no_default_libraries(&mut self) {}
+
+    fn control_flow_guard(&mut self) {}
+
+    fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType) {}
+
+    fn subsystem(&mut self, _subsystem: &str) {}
+
+    fn group_start(&mut self) {}
+
+    fn group_end(&mut self) {}
+
+    fn linker_plugin_lto(&mut self) {}
+}
+
+pub struct BpfLinker<'a> {
+    cmd: Command,
+    sess: &'a Session,
+    info: &'a LinkerInfo,
+}
+
+impl<'a> Linker for BpfLinker<'a> {
+    fn cmd(&mut self) -> &mut Command {
+        &mut self.cmd
+    }
+
+    fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {}
+
+    fn link_rlib(&mut self, path: &Path) {
+        self.cmd.arg(path);
+    }
+
+    fn link_whole_rlib(&mut self, path: &Path) {
+        self.cmd.arg(path);
+    }
+
+    fn include_path(&mut self, path: &Path) {
+        self.cmd.arg("-L").arg(path);
+    }
+
+    fn debuginfo(&mut self, _strip: Strip) {
+        self.cmd.arg("--debug");
+    }
+
+    fn add_object(&mut self, path: &Path) {
+        self.cmd.arg(path);
+    }
+
+    fn optimize(&mut self) {
+        self.cmd.arg(match self.sess.opts.optimize {
+            OptLevel::No => "-O0",
+            OptLevel::Less => "-O1",
+            OptLevel::Default => "-O2",
+            OptLevel::Aggressive => "-O3",
+            OptLevel::Size => "-Os",
+            OptLevel::SizeMin => "-Oz",
+        });
+    }
+
+    fn output_filename(&mut self, path: &Path) {
+        self.cmd.arg("-o").arg(path);
     }
 
     fn link_dylib(&mut self, _lib: Symbol, _verbatim: bool, _as_needed: bool) {
@@ -1421,7 +1514,20 @@ impl<'a> Linker for PtxLinker<'a> {
 
     fn control_flow_guard(&mut self) {}
 
-    fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType) {}
+    fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
+        let path = tmpdir.join("symbols");
+        let res: io::Result<()> = try {
+            let mut f = BufWriter::new(File::create(&path)?);
+            for sym in self.info.exports[&crate_type].iter() {
+                writeln!(f, "{}", sym)?;
+            }
+        };
+        if let Err(e) = res {
+            self.sess.fatal(&format!("failed to write symbols file: {}", e));
+        } else {
+            self.cmd.arg("--export-symbols").arg(&path);
+        }
+    }
 
     fn subsystem(&mut self, _subsystem: &str) {}
 
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 37d1f8ecc83..0fff3195808 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -3,6 +3,7 @@
 use std::fs::File;
 use std::path::Path;
 
+use object::{Object, ObjectSection};
 use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::owning_ref::OwningRef;
 use rustc_data_structures::rustc_erase_owner;
@@ -46,7 +47,10 @@ impl MetadataLoader for DefaultMetadataLoader {
                 let entry = entry_result
                     .map_err(|e| format!("failed to parse rlib '{}': {}", path.display(), e))?;
                 if entry.name() == METADATA_FILENAME.as_bytes() {
-                    return Ok(entry.data());
+                    let data = entry
+                        .data(data)
+                        .map_err(|e| format!("failed to parse rlib '{}': {}", path.display(), e))?;
+                    return search_for_metadata(path, data, ".rmeta");
                 }
             }
 
@@ -55,17 +59,27 @@ impl MetadataLoader for DefaultMetadataLoader {
     }
 
     fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> {
-        use object::{Object, ObjectSection};
-
-        load_metadata_with(path, |data| {
-            let file = object::File::parse(&data)
-                .map_err(|e| format!("failed to parse dylib '{}': {}", path.display(), e))?;
-            file.section_by_name(".rustc")
-                .ok_or_else(|| format!("no .rustc section in '{}'", path.display()))?
-                .data()
-                .map_err(|e| {
-                    format!("failed to read .rustc section in '{}': {}", path.display(), e)
-                })
-        })
+        load_metadata_with(path, |data| search_for_metadata(path, data, ".rustc"))
     }
 }
+
+fn search_for_metadata<'a>(
+    path: &Path,
+    bytes: &'a [u8],
+    section: &str,
+) -> Result<&'a [u8], String> {
+    let file = match object::File::parse(bytes) {
+        Ok(f) => f,
+        // The parse above could fail for odd reasons like corruption, but for
+        // now we just interpret it as this target doesn't support metadata
+        // emission in object files so the entire byte slice itself is probably
+        // a metadata file. Ideally though if necessary we could at least check
+        // the prefix of bytes to see if it's an actual metadata object and if
+        // not forward the error along here.
+        Err(_) => return Ok(bytes),
+    };
+    file.section_by_name(section)
+        .ok_or_else(|| format!("no `{}` section in '{}'", section, path.display()))?
+        .data()
+        .map_err(|e| format!("failed to read {} section in '{}': {}", section, path.display(), e))
+}
diff --git a/compiler/rustc_codegen_ssa/src/back/rpath.rs b/compiler/rustc_codegen_ssa/src/back/rpath.rs
index 5f21046b05e..39b0ccd120d 100644
--- a/compiler/rustc_codegen_ssa/src/back/rpath.rs
+++ b/compiler/rustc_codegen_ssa/src/back/rpath.rs
@@ -13,7 +13,6 @@ pub struct RPathConfig<'a> {
     pub is_like_osx: bool,
     pub has_rpath: bool,
     pub linker_is_gnu: bool,
-    pub get_install_prefix_lib_path: &'a mut dyn FnMut() -> PathBuf,
 }
 
 pub fn get_rpath_flags(config: &mut RPathConfig<'_>) -> Vec<String> {
@@ -63,24 +62,13 @@ fn get_rpaths(config: &mut RPathConfig<'_>, libs: &[PathBuf]) -> Vec<String> {
     // Use relative paths to the libraries. Binaries can be moved
     // as long as they maintain the relative relationship to the
     // crates they depend on.
-    let rel_rpaths = get_rpaths_relative_to_output(config, libs);
+    let rpaths = get_rpaths_relative_to_output(config, libs);
 
-    // And a final backup rpath to the global library location.
-    let fallback_rpaths = vec![get_install_prefix_rpath(config)];
-
-    fn log_rpaths(desc: &str, rpaths: &[String]) {
-        debug!("{} rpaths:", desc);
-        for rpath in rpaths {
-            debug!("    {}", *rpath);
-        }
+    debug!("rpaths:");
+    for rpath in &rpaths {
+        debug!("    {}", rpath);
     }
 
-    log_rpaths("relative", &rel_rpaths);
-    log_rpaths("fallback", &fallback_rpaths);
-
-    let mut rpaths = rel_rpaths;
-    rpaths.extend_from_slice(&fallback_rpaths);
-
     // Remove duplicates
     minimize_rpaths(&rpaths)
 }
@@ -113,13 +101,6 @@ fn path_relative_from(path: &Path, base: &Path) -> Option<PathBuf> {
     diff_paths(path, base)
 }
 
-fn get_install_prefix_rpath(config: &mut RPathConfig<'_>) -> String {
-    let path = (config.get_install_prefix_lib_path)();
-    let path = env::current_dir().unwrap().join(&path);
-    // FIXME (#9639): This needs to handle non-utf8 paths
-    path.to_str().expect("non-utf8 component in rpath").to_owned()
-}
-
 fn minimize_rpaths(rpaths: &[String]) -> Vec<String> {
     let mut set = FxHashSet::default();
     let mut minimized = Vec::new();
diff --git a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs
index 35836ae719b..24c362db122 100644
--- a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs
+++ b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs
@@ -40,7 +40,6 @@ fn test_rpath_relative() {
             is_like_osx: true,
             linker_is_gnu: false,
             out_filename: PathBuf::from("bin/rustc"),
-            get_install_prefix_lib_path: &mut || panic!(),
         };
         let res = get_rpath_relative_to_output(config, Path::new("lib/libstd.so"));
         assert_eq!(res, "@loader_path/../lib");
@@ -48,7 +47,6 @@ fn test_rpath_relative() {
         let config = &mut RPathConfig {
             used_crates: &[],
             out_filename: PathBuf::from("bin/rustc"),
-            get_install_prefix_lib_path: &mut || panic!(),
             has_rpath: true,
             is_like_osx: false,
             linker_is_gnu: true,
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 14d6f0ba147..b2ecc3b0f32 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -370,7 +370,6 @@ pub fn provide(providers: &mut Providers) {
 pub fn provide_extern(providers: &mut Providers) {
     providers.is_reachable_non_generic = is_reachable_non_generic_provider_extern;
     providers.upstream_monomorphizations_for = upstream_monomorphizations_for_provider;
-    providers.wasm_import_module_map = wasm_import_module_map;
 }
 
 fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel {
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 49774dc6d5c..ff4e6409571 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -31,7 +31,7 @@ use rustc_session::config::{self, CrateType, Lto, OutputFilenames, OutputType};
 use rustc_session::config::{Passes, SwitchWithOptPath};
 use rustc_session::Session;
 use rustc_span::source_map::SourceMap;
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::sym;
 use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span};
 use rustc_target::spec::{MergeFunctions, PanicStrategy, SanitizerSet};
 
@@ -426,21 +426,9 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
     let (coordinator_send, coordinator_receive) = channel();
     let sess = tcx.sess;
 
-    let crate_name = tcx.crate_name(LOCAL_CRATE);
     let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
     let no_builtins = tcx.sess.contains_name(crate_attrs, sym::no_builtins);
     let is_compiler_builtins = tcx.sess.contains_name(crate_attrs, sym::compiler_builtins);
-    let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem);
-    let windows_subsystem = subsystem.map(|subsystem| {
-        if subsystem != sym::windows && subsystem != sym::console {
-            tcx.sess.fatal(&format!(
-                "invalid windows subsystem `{}`, only \
-                                     `windows` and `console` are allowed",
-                subsystem
-            ));
-        }
-        subsystem.to_string()
-    });
 
     let linker_info = LinkerInfo::new(tcx, target_cpu);
     let crate_info = CrateInfo::new(tcx);
@@ -472,9 +460,7 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
 
     OngoingCodegen {
         backend,
-        crate_name,
         metadata,
-        windows_subsystem,
         linker_info,
         crate_info,
 
@@ -1812,9 +1798,7 @@ impl SharedEmitterMain {
 
 pub struct OngoingCodegen<B: ExtraBackendMethods> {
     pub backend: B,
-    pub crate_name: Symbol,
     pub metadata: EncodedMetadata,
-    pub windows_subsystem: Option<String>,
     pub linker_info: LinkerInfo,
     pub crate_info: CrateInfo,
     pub coordinator_send: Sender<Box<dyn Any + Send>>,
@@ -1857,9 +1841,7 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
 
         (
             CodegenResults {
-                crate_name: self.crate_name,
                 metadata: self.metadata,
-                windows_subsystem: self.windows_subsystem,
                 linker_info: self.linker_info,
                 crate_info: self.crate_info,
 
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index b44e74d5ae8..38ab39febe0 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -30,6 +30,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_session::cgu_reuse_tracker::CguReuse;
 use rustc_session::config::{self, EntryFnType};
 use rustc_session::Session;
+use rustc_span::symbol::sym;
 use rustc_target::abi::{Align, LayoutOf, VariantIdx};
 
 use std::ops::{Deref, DerefMut};
@@ -755,7 +756,22 @@ impl<B: ExtraBackendMethods> Drop for AbortCodegenOnDrop<B> {
 
 impl CrateInfo {
     pub fn new(tcx: TyCtxt<'_>) -> CrateInfo {
+        let local_crate_name = tcx.crate_name(LOCAL_CRATE);
+        let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
+        let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem);
+        let windows_subsystem = subsystem.map(|subsystem| {
+            if subsystem != sym::windows && subsystem != sym::console {
+                tcx.sess.fatal(&format!(
+                    "invalid windows subsystem `{}`, only \
+                                     `windows` and `console` are allowed",
+                    subsystem
+                ));
+            }
+            subsystem.to_string()
+        });
+
         let mut info = CrateInfo {
+            local_crate_name,
             panic_runtime: None,
             compiler_builtins: None,
             profiler_runtime: None,
@@ -769,6 +785,7 @@ impl CrateInfo {
             lang_item_to_crate: Default::default(),
             missing_lang_items: Default::default(),
             dependency_formats: tcx.dependency_formats(()),
+            windows_subsystem,
         };
         let lang_items = tcx.lang_items();
 
diff --git a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs
index 08442c588f8..c1dfe1ef856 100644
--- a/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs
+++ b/compiler/rustc_codegen_ssa/src/coverageinfo/map.rs
@@ -28,6 +28,7 @@ pub struct Expression {
 /// only whitespace or comments). According to LLVM Code Coverage Mapping documentation, "A count
 /// for a gap area is only used as the line execution count if there are no other regions on a
 /// line."
+#[derive(Debug)]
 pub struct FunctionCoverage<'tcx> {
     instance: Instance<'tcx>,
     source_hash: u64,
@@ -113,6 +114,14 @@ impl<'tcx> FunctionCoverage<'tcx> {
             expression_id, lhs, op, rhs, region
         );
         let expression_index = self.expression_index(u32::from(expression_id));
+        debug_assert!(
+            expression_index.as_usize() < self.expressions.len(),
+            "expression_index {} is out of range for expressions.len() = {}
+            for {:?}",
+            expression_index.as_usize(),
+            self.expressions.len(),
+            self,
+        );
         if let Some(previous_expression) = self.expressions[expression_index].replace(Expression {
             lhs,
             op,
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index d1bbf74307c..7b4b0821c4b 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -3,7 +3,8 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_middle::ty::{self, subst::SubstsRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty, TyCtxt};
+use rustc_target::abi::{TagEncoding, Variants};
 
 use std::fmt::Write;
 
@@ -45,8 +46,12 @@ pub fn push_debuginfo_type_name<'tcx>(
         ty::Float(float_ty) => output.push_str(float_ty.name_str()),
         ty::Foreign(def_id) => push_item_name(tcx, def_id, qualified, output),
         ty::Adt(def, substs) => {
-            push_item_name(tcx, def.did, qualified, output);
-            push_type_params(tcx, substs, output, visited);
+            if def.is_enum() && cpp_like_names {
+                msvc_enum_fallback(tcx, t, def, substs, output, visited);
+            } else {
+                push_item_name(tcx, def.did, qualified, output);
+                push_type_params(tcx, substs, output, visited);
+            }
         }
         ty::Tuple(component_types) => {
             if cpp_like_names {
@@ -233,6 +238,54 @@ pub fn push_debuginfo_type_name<'tcx>(
         }
     }
 
+    /// MSVC names enums differently than other platforms so that the debugging visualization
+    // format (natvis) is able to understand enums and render the active variant correctly in the
+    // debugger. For more information, look in `src/etc/natvis/intrinsic.natvis` and
+    // `EnumMemberDescriptionFactor::create_member_descriptions`.
+    fn msvc_enum_fallback(
+        tcx: TyCtxt<'tcx>,
+        ty: Ty<'tcx>,
+        def: &AdtDef,
+        substs: SubstsRef<'tcx>,
+        output: &mut String,
+        visited: &mut FxHashSet<Ty<'tcx>>,
+    ) {
+        let layout = tcx.layout_of(tcx.param_env(def.did).and(ty)).expect("layout error");
+
+        if let Variants::Multiple {
+            tag_encoding: TagEncoding::Niche { dataful_variant, .. },
+            tag,
+            variants,
+            ..
+        } = &layout.variants
+        {
+            let dataful_variant_layout = &variants[*dataful_variant];
+
+            // calculate the range of values for the dataful variant
+            let dataful_discriminant_range =
+                &dataful_variant_layout.largest_niche.as_ref().unwrap().scalar.valid_range;
+
+            let min = dataful_discriminant_range.start();
+            let min = tag.value.size(&tcx).truncate(*min);
+
+            let max = dataful_discriminant_range.end();
+            let max = tag.value.size(&tcx).truncate(*max);
+
+            output.push_str("enum$<");
+            push_item_name(tcx, def.did, true, output);
+            push_type_params(tcx, substs, output, visited);
+
+            let dataful_variant_name = def.variants[*dataful_variant].ident.as_str();
+
+            output.push_str(&format!(", {}, {}, {}>", min, max, dataful_variant_name));
+        } else {
+            output.push_str("enum$<");
+            push_item_name(tcx, def.did, true, output);
+            push_type_params(tcx, substs, output, visited);
+            output.push('>');
+        }
+    }
+
     fn push_item_name(tcx: TyCtxt<'tcx>, def_id: DefId, qualified: bool, output: &mut String) {
         if qualified {
             output.push_str(&tcx.crate_name(def_id.krate).as_str());
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 6c4bb021cb3..b6de12fa35e 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -1,15 +1,11 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![feature(assert_matches)]
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
-#![feature(drain_filter)]
 #![feature(try_blocks)]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
 #![feature(associated_type_bounds)]
-#![feature(iter_zip)]
 #![recursion_limit = "256"]
-#![feature(box_syntax)]
 
 //! This crate contains codegen code that is used by all codegen backends (LLVM and others).
 //! The backend-agnostic functions of this crate use functions defined in various traits that
@@ -114,11 +110,18 @@ pub struct NativeLib {
     pub name: Option<Symbol>,
     pub cfg: Option<ast::MetaItem>,
     pub verbatim: Option<bool>,
+    pub dll_imports: Vec<cstore::DllImport>,
 }
 
 impl From<&cstore::NativeLib> for NativeLib {
     fn from(lib: &cstore::NativeLib) -> Self {
-        NativeLib { kind: lib.kind, name: lib.name, cfg: lib.cfg.clone(), verbatim: lib.verbatim }
+        NativeLib {
+            kind: lib.kind,
+            name: lib.name,
+            cfg: lib.cfg.clone(),
+            verbatim: lib.verbatim,
+            dll_imports: lib.dll_imports.clone(),
+        }
     }
 }
 
@@ -132,6 +135,7 @@ impl From<&cstore::NativeLib> for NativeLib {
 /// and the corresponding properties without referencing information outside of a `CrateInfo`.
 #[derive(Debug, Encodable, Decodable)]
 pub struct CrateInfo {
+    pub local_crate_name: Symbol,
     pub panic_runtime: Option<CrateNum>,
     pub compiler_builtins: Option<CrateNum>,
     pub profiler_runtime: Option<CrateNum>,
@@ -145,16 +149,15 @@ pub struct CrateInfo {
     pub lang_item_to_crate: FxHashMap<LangItem, CrateNum>,
     pub missing_lang_items: FxHashMap<CrateNum, Vec<LangItem>>,
     pub dependency_formats: Lrc<Dependencies>,
+    pub windows_subsystem: Option<String>,
 }
 
 #[derive(Encodable, Decodable)]
 pub struct CodegenResults {
-    pub crate_name: Symbol,
     pub modules: Vec<CompiledModule>,
     pub allocator_module: Option<CompiledModule>,
     pub metadata_module: Option<CompiledModule>,
     pub metadata: rustc_middle::middle::cstore::EncodedMetadata,
-    pub windows_subsystem: Option<String>,
     pub linker_info: back::linker::LinkerInfo,
     pub crate_info: CrateInfo,
 }
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index 38e928145a8..8a22a74f97c 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -7,11 +7,8 @@ use rustc_data_structures::graph::dominators::Dominators;
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::mir::traversal;
-use rustc_middle::mir::visit::{
-    MutatingUseContext, NonMutatingUseContext, NonUseContext, PlaceContext, Visitor,
-};
+use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::{self, Location, TerminatorKind};
-use rustc_middle::ty;
 use rustc_middle::ty::layout::HasTyCtxt;
 use rustc_target::abi::LayoutOf;
 
@@ -21,7 +18,9 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     let mir = fx.mir;
     let mut analyzer = LocalAnalyzer::new(fx);
 
-    analyzer.visit_body(&mir);
+    for (bb, data) in mir.basic_blocks().iter_enumerated() {
+        analyzer.visit_basic_block_data(bb, data);
+    }
 
     for (local, decl) in mir.local_decls.iter_enumerated() {
         let ty = fx.monomorphize(decl.ty);
@@ -142,36 +141,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
 
             if let mir::ProjectionElem::Deref = elem {
                 // Deref projections typically only read the pointer.
-                // (the exception being `VarDebugInfo` contexts, handled below)
                 base_context = PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy);
-
-                // Indirect debuginfo requires going through memory, that only
-                // the debugger accesses, following our emitted DWARF pointer ops.
-                //
-                // FIXME(eddyb) Investigate the possibility of relaxing this, but
-                // note that `llvm.dbg.declare` *must* be used for indirect places,
-                // even if we start using `llvm.dbg.value` for all other cases,
-                // as we don't necessarily know when the value changes, but only
-                // where it lives in memory.
-                //
-                // It's possible `llvm.dbg.declare` could support starting from
-                // a pointer that doesn't point to an `alloca`, but this would
-                // only be useful if we know the pointer being `Deref`'d comes
-                // from an immutable place, and if `llvm.dbg.declare` calls
-                // must be at the very start of the function, then only function
-                // arguments could contain such pointers.
-                if context == PlaceContext::NonUse(NonUseContext::VarDebugInfo) {
-                    // We use `NonUseContext::VarDebugInfo` for the base,
-                    // which might not force the base local to memory,
-                    // so we have to do it manually.
-                    self.visit_local(&place_ref.local, context, location);
-                }
-            }
-
-            // `NonUseContext::VarDebugInfo` needs to flow all the
-            // way down to the base local (see `visit_local`).
-            if context == PlaceContext::NonUse(NonUseContext::VarDebugInfo) {
-                base_context = context;
             }
 
             self.process_place(&place_base, base_context, location);
@@ -186,20 +156,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
                 );
             }
         } else {
-            // FIXME this is super_place code, is repeated here to avoid cloning place or changing
-            // visit_place API
-            let mut context = context;
-
-            if !place_ref.projection.is_empty() {
-                context = if context.is_mutating_use() {
-                    PlaceContext::MutatingUse(MutatingUseContext::Projection)
-                } else {
-                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
-                };
-            }
-
             self.visit_local(&place_ref.local, context, location);
-            self.visit_projection(*place_ref, context, location);
         }
     }
 }
@@ -228,34 +185,6 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
         self.visit_rvalue(rvalue, location);
     }
 
-    fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) {
-        let check = match terminator.kind {
-            mir::TerminatorKind::Call { func: mir::Operand::Constant(ref c), ref args, .. } => {
-                match *c.ty().kind() {
-                    ty::FnDef(did, _) => Some((did, args)),
-                    _ => None,
-                }
-            }
-            _ => None,
-        };
-        if let Some((def_id, args)) = check {
-            if Some(def_id) == self.fx.cx.tcx().lang_items().box_free_fn() {
-                // box_free(x) shares with `drop x` the property that it
-                // is not guaranteed to be statically dominated by the
-                // definition of x, so x must always be in an alloca.
-                if let mir::Operand::Move(ref place) = args[0] {
-                    self.visit_place(
-                        place,
-                        PlaceContext::MutatingUse(MutatingUseContext::Drop),
-                        location,
-                    );
-                }
-            }
-        }
-
-        self.super_terminator(terminator, location);
-    }
-
     fn visit_place(&mut self, place: &mir::Place<'tcx>, context: PlaceContext, location: Location) {
         debug!("visit_place(place={:?}, context={:?})", place, context);
         self.process_place(&place.as_ref(), context, location);
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 98d550d732f..b10de567744 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -210,6 +210,8 @@ const WASM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     ("nontrapping-fptoint", Some(sym::wasm_target_feature)),
 ];
 
+const BPF_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[("alu32", Some(sym::bpf_target_feature))];
+
 /// When rustdoc is running, provide a list of all known features so that all their respective
 /// primitives may be documented.
 ///
@@ -224,6 +226,7 @@ pub fn all_known_features() -> impl Iterator<Item = (&'static str, Option<Symbol
         .chain(MIPS_ALLOWED_FEATURES.iter())
         .chain(RISCV_ALLOWED_FEATURES.iter())
         .chain(WASM_ALLOWED_FEATURES.iter())
+        .chain(BPF_ALLOWED_FEATURES.iter())
         .cloned()
 }
 
@@ -237,6 +240,7 @@ pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Opt
         "powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES,
         "riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES,
         "wasm32" | "wasm64" => WASM_ALLOWED_FEATURES,
+        "bpf" => BPF_ALLOWED_FEATURES,
         _ => &[],
     }
 }
diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs
index f28db2fe84b..dc4146ec7b5 100644
--- a/compiler/rustc_codegen_ssa/src/traits/backend.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs
@@ -63,9 +63,16 @@ pub trait CodegenBackend {
         None
     }
 
-    fn metadata_loader(&self) -> Box<MetadataLoaderDyn>;
-    fn provide(&self, _providers: &mut Providers);
-    fn provide_extern(&self, _providers: &mut Providers);
+    /// The metadata loader used to load rlib and dylib metadata.
+    ///
+    /// Alternative codegen backends may want to use different rlib or dylib formats than the
+    /// default native static archives and dynamic libraries.
+    fn metadata_loader(&self) -> Box<MetadataLoaderDyn> {
+        Box::new(crate::back::metadata::DefaultMetadataLoader)
+    }
+
+    fn provide(&self, _providers: &mut Providers) {}
+    fn provide_extern(&self, _providers: &mut Providers) {}
     fn codegen_crate<'tcx>(
         &self,
         tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index adbb98fa750..bbfe225e23e 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -10,15 +10,12 @@
 #![feature(array_windows)]
 #![feature(control_flow_enum)]
 #![feature(in_band_lifetimes)]
-#![feature(unboxed_closures)]
 #![feature(generator_trait)]
-#![feature(fn_traits)]
 #![feature(min_specialization)]
 #![feature(auto_traits)]
 #![feature(nll)]
 #![feature(allow_internal_unstable)]
 #![feature(hash_raw_entry)]
-#![feature(stmt_expr_attributes)]
 #![feature(core_intrinsics)]
 #![feature(test)]
 #![feature(associated_type_bounds)]
@@ -99,6 +96,7 @@ pub mod thin_vec;
 pub mod tiny_list;
 pub mod transitive_relation;
 pub mod vec_linked_list;
+pub mod vec_map;
 pub mod work_queue;
 pub use atomic_ref::AtomicRef;
 pub mod frozen;
diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
index 29d685ab530..05b1a85381f 100644
--- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs
+++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
@@ -342,7 +342,7 @@ impl<O: ForestObligation> ObligationForest<O> {
             return Ok(());
         }
 
-        match self.active_cache.entry(cache_key.clone()) {
+        match self.active_cache.entry(cache_key) {
             Entry::Occupied(o) => {
                 let node = &mut self.nodes[*o.get()];
                 if let Some(parent_index) = parent {
@@ -366,8 +366,7 @@ impl<O: ForestObligation> ObligationForest<O> {
                     && self
                         .error_cache
                         .get(&obligation_tree_id)
-                        .map(|errors| errors.contains(&cache_key))
-                        .unwrap_or(false);
+                        .map_or(false, |errors| errors.contains(v.key()));
 
                 if already_failed {
                     Err(())
@@ -597,7 +596,7 @@ impl<O: ForestObligation> ObligationForest<O> {
                 Some(rpos) => {
                     // Cycle detected.
                     processor.process_backedge(
-                        stack[rpos..].iter().map(GetObligation(&self.nodes)),
+                        stack[rpos..].iter().map(|&i| &self.nodes[i].obligation),
                         PhantomData,
                     );
                 }
@@ -705,20 +704,3 @@ impl<O: ForestObligation> ObligationForest<O> {
         });
     }
 }
-
-// I need a Clone closure.
-#[derive(Clone)]
-struct GetObligation<'a, O>(&'a [Node<O>]);
-
-impl<'a, 'b, O> FnOnce<(&'b usize,)> for GetObligation<'a, O> {
-    type Output = &'a O;
-    extern "rust-call" fn call_once(self, args: (&'b usize,)) -> &'a O {
-        &self.0[*args.0].obligation
-    }
-}
-
-impl<'a, 'b, O> FnMut<(&'b usize,)> for GetObligation<'a, O> {
-    extern "rust-call" fn call_mut(&mut self, args: (&'b usize,)) -> &'a O {
-        &self.0[*args.0].obligation
-    }
-}
diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs
index ff28784a1dc..18b352cf3b0 100644
--- a/compiler/rustc_data_structures/src/stable_hasher.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher.rs
@@ -550,35 +550,3 @@ pub fn hash_stable_hashmap<HCX, K, V, R, SK, F>(
     entries.sort_unstable_by(|&(ref sk1, _), &(ref sk2, _)| sk1.cmp(sk2));
     entries.hash_stable(hcx, hasher);
 }
-
-/// A vector container that makes sure that its items are hashed in a stable
-/// order.
-#[derive(Debug)]
-pub struct StableVec<T>(Vec<T>);
-
-impl<T> StableVec<T> {
-    pub fn new(v: Vec<T>) -> Self {
-        StableVec(v)
-    }
-}
-
-impl<T> ::std::ops::Deref for StableVec<T> {
-    type Target = Vec<T>;
-
-    fn deref(&self) -> &Vec<T> {
-        &self.0
-    }
-}
-
-impl<T, HCX> HashStable<HCX> for StableVec<T>
-where
-    T: HashStable<HCX> + ToStableHashKey<HCX>,
-{
-    fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
-        let StableVec(ref v) = *self;
-
-        let mut sorted: Vec<_> = v.iter().map(|x| x.to_stable_hash_key(hcx)).collect();
-        sorted.sort_unstable();
-        sorted.hash_stable(hcx, hasher);
-    }
-}
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index 26706cd2b1b..722ce6b6367 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -43,49 +43,9 @@ cfg_if! {
         use std::ops::Add;
         use std::panic::{resume_unwind, catch_unwind, AssertUnwindSafe};
 
-        /// This is a single threaded variant of AtomicCell provided by crossbeam.
-        /// Unlike `Atomic` this is intended for all `Copy` types,
-        /// but it lacks the explicit ordering arguments.
-        #[derive(Debug)]
-        pub struct AtomicCell<T: Copy>(Cell<T>);
-
-        impl<T: Copy> AtomicCell<T> {
-            #[inline]
-            pub fn new(v: T) -> Self {
-                AtomicCell(Cell::new(v))
-            }
-
-            #[inline]
-            pub fn get_mut(&mut self) -> &mut T {
-                self.0.get_mut()
-            }
-        }
-
-        impl<T: Copy> AtomicCell<T> {
-            #[inline]
-            pub fn into_inner(self) -> T {
-                self.0.into_inner()
-            }
-
-            #[inline]
-            pub fn load(&self) -> T {
-                self.0.get()
-            }
-
-            #[inline]
-            pub fn store(&self, val: T) {
-                self.0.set(val)
-            }
-
-            #[inline]
-            pub fn swap(&self, val: T) -> T {
-                self.0.replace(val)
-            }
-        }
-
         /// This is a single threaded variant of `AtomicU64`, `AtomicUsize`, etc.
-        /// It differs from `AtomicCell` in that it has explicit ordering arguments
-        /// and is only intended for use with the native atomic types.
+        /// It has explicit ordering arguments and is only intended for use with
+        /// the native atomic types.
         /// You should use this type through the `AtomicU64`, `AtomicUsize`, etc, type aliases
         /// as it's not intended to be used separately.
         #[derive(Debug)]
@@ -159,22 +119,6 @@ cfg_if! {
             (oper_a(), oper_b())
         }
 
-        pub struct SerialScope;
-
-        impl SerialScope {
-            pub fn spawn<F>(&self, f: F)
-                where F: FnOnce(&SerialScope)
-            {
-                f(self)
-            }
-        }
-
-        pub fn scope<F, R>(f: F) -> R
-            where F: FnOnce(&SerialScope) -> R
-        {
-            f(&SerialScope)
-        }
-
         #[macro_export]
         macro_rules! parallel {
             ($($blocks:tt),*) => {
@@ -318,8 +262,6 @@ cfg_if! {
 
         pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64};
 
-        pub use crossbeam_utils::atomic::AtomicCell;
-
         pub use std::sync::Arc as Lrc;
         pub use std::sync::Weak as Weak;
 
diff --git a/compiler/rustc_data_structures/src/tagged_ptr.rs b/compiler/rustc_data_structures/src/tagged_ptr.rs
index cd1e12ca450..324a8624dd0 100644
--- a/compiler/rustc_data_structures/src/tagged_ptr.rs
+++ b/compiler/rustc_data_structures/src/tagged_ptr.rs
@@ -90,9 +90,11 @@ pub unsafe trait Tag: Copy {
 
 unsafe impl<T> Pointer for Box<T> {
     const BITS: usize = std::mem::align_of::<T>().trailing_zeros() as usize;
+    #[inline]
     fn into_usize(self) -> usize {
         Box::into_raw(self) as usize
     }
+    #[inline]
     unsafe fn from_usize(ptr: usize) -> Self {
         Box::from_raw(ptr as *mut T)
     }
@@ -104,9 +106,11 @@ unsafe impl<T> Pointer for Box<T> {
 
 unsafe impl<T> Pointer for Rc<T> {
     const BITS: usize = std::mem::align_of::<T>().trailing_zeros() as usize;
+    #[inline]
     fn into_usize(self) -> usize {
         Rc::into_raw(self) as usize
     }
+    #[inline]
     unsafe fn from_usize(ptr: usize) -> Self {
         Rc::from_raw(ptr as *const T)
     }
@@ -118,9 +122,11 @@ unsafe impl<T> Pointer for Rc<T> {
 
 unsafe impl<T> Pointer for Arc<T> {
     const BITS: usize = std::mem::align_of::<T>().trailing_zeros() as usize;
+    #[inline]
     fn into_usize(self) -> usize {
         Arc::into_raw(self) as usize
     }
+    #[inline]
     unsafe fn from_usize(ptr: usize) -> Self {
         Arc::from_raw(ptr as *const T)
     }
@@ -132,9 +138,11 @@ unsafe impl<T> Pointer for Arc<T> {
 
 unsafe impl<'a, T: 'a> Pointer for &'a T {
     const BITS: usize = std::mem::align_of::<T>().trailing_zeros() as usize;
+    #[inline]
     fn into_usize(self) -> usize {
         self as *const T as usize
     }
+    #[inline]
     unsafe fn from_usize(ptr: usize) -> Self {
         &*(ptr as *const T)
     }
@@ -145,9 +153,11 @@ unsafe impl<'a, T: 'a> Pointer for &'a T {
 
 unsafe impl<'a, T: 'a> Pointer for &'a mut T {
     const BITS: usize = std::mem::align_of::<T>().trailing_zeros() as usize;
+    #[inline]
     fn into_usize(self) -> usize {
         self as *mut T as usize
     }
+    #[inline]
     unsafe fn from_usize(ptr: usize) -> Self {
         &mut *(ptr as *mut T)
     }
diff --git a/compiler/rustc_data_structures/src/vec_map.rs b/compiler/rustc_data_structures/src/vec_map.rs
new file mode 100644
index 00000000000..73b04d3329c
--- /dev/null
+++ b/compiler/rustc_data_structures/src/vec_map.rs
@@ -0,0 +1,155 @@
+use std::borrow::Borrow;
+use std::iter::FromIterator;
+use std::slice::{Iter, IterMut};
+use std::vec::IntoIter;
+
+use crate::stable_hasher::{HashStable, StableHasher};
+
+/// A map type implemented as a vector of pairs `K` (key) and `V` (value).
+/// It currently provides a subset of all the map operations, the rest could be added as needed.
+#[derive(Clone, Encodable, Decodable, Debug)]
+pub struct VecMap<K, V>(Vec<(K, V)>);
+
+impl<K, V> VecMap<K, V>
+where
+    K: PartialEq,
+{
+    pub fn new() -> Self {
+        VecMap(Default::default())
+    }
+
+    /// Sets the value of the entry, and returns the entry's old value.
+    pub fn insert(&mut self, k: K, v: V) -> Option<V> {
+        if let Some(elem) = self.0.iter_mut().find(|(key, _)| *key == k) {
+            Some(std::mem::replace(&mut elem.1, v))
+        } else {
+            self.0.push((k, v));
+            None
+        }
+    }
+
+    /// Gets a reference to the value in the entry.
+    pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
+    where
+        K: Borrow<Q>,
+        Q: Eq,
+    {
+        self.0.iter().find(|(key, _)| k == key.borrow()).map(|elem| &elem.1)
+    }
+
+    /// Returns the value corresponding to the supplied predicate filter.
+    ///
+    /// The supplied predicate will be applied to each (key, value) pair and it will return a
+    /// reference to the values where the predicate returns `true`.
+    pub fn get_by(&self, mut predicate: impl FnMut(&(K, V)) -> bool) -> Option<&V> {
+        self.0.iter().find(|kv| predicate(kv)).map(|elem| &elem.1)
+    }
+
+    /// Returns `true` if the map contains a value for the specified key.
+    ///
+    /// The key may be any borrowed form of the map's key type,
+    /// [`Eq`] on the borrowed form *must* match those for
+    /// the key type.
+    pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
+    where
+        K: Borrow<Q>,
+        Q: Eq,
+    {
+        self.get(k).is_some()
+    }
+
+    /// Returns `true` if the map contains no elements.
+    pub fn is_empty(&self) -> bool {
+        self.0.is_empty()
+    }
+
+    pub fn iter(&self) -> Iter<'_, (K, V)> {
+        self.into_iter()
+    }
+
+    pub fn iter_mut(&mut self) -> IterMut<'_, (K, V)> {
+        self.into_iter()
+    }
+}
+
+impl<K, V> Default for VecMap<K, V> {
+    #[inline]
+    fn default() -> Self {
+        Self(Default::default())
+    }
+}
+
+impl<K, V> From<Vec<(K, V)>> for VecMap<K, V> {
+    fn from(vec: Vec<(K, V)>) -> Self {
+        Self(vec)
+    }
+}
+
+impl<K, V> Into<Vec<(K, V)>> for VecMap<K, V> {
+    fn into(self) -> Vec<(K, V)> {
+        self.0
+    }
+}
+
+impl<K, V> FromIterator<(K, V)> for VecMap<K, V> {
+    fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self {
+        Self(iter.into_iter().collect())
+    }
+}
+
+impl<'a, K, V> IntoIterator for &'a VecMap<K, V> {
+    type Item = &'a (K, V);
+    type IntoIter = Iter<'a, (K, V)>;
+
+    #[inline]
+    fn into_iter(self) -> Self::IntoIter {
+        self.0.iter()
+    }
+}
+
+impl<'a, K, V> IntoIterator for &'a mut VecMap<K, V> {
+    type Item = &'a mut (K, V);
+    type IntoIter = IterMut<'a, (K, V)>;
+
+    #[inline]
+    fn into_iter(self) -> Self::IntoIter {
+        self.0.iter_mut()
+    }
+}
+
+impl<K, V> IntoIterator for VecMap<K, V> {
+    type Item = (K, V);
+    type IntoIter = IntoIter<(K, V)>;
+
+    #[inline]
+    fn into_iter(self) -> Self::IntoIter {
+        self.0.into_iter()
+    }
+}
+
+impl<K, V> Extend<(K, V)> for VecMap<K, V> {
+    fn extend<I: IntoIterator<Item = (K, V)>>(&mut self, iter: I) {
+        self.0.extend(iter);
+    }
+
+    fn extend_one(&mut self, item: (K, V)) {
+        self.0.extend_one(item);
+    }
+
+    fn extend_reserve(&mut self, additional: usize) {
+        self.0.extend_reserve(additional);
+    }
+}
+
+impl<K, V, CTX> HashStable<CTX> for VecMap<K, V>
+where
+    K: HashStable<CTX> + Eq,
+    V: HashStable<CTX>,
+{
+    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
+        self.0.hash_stable(hcx, hasher)
+    }
+}
+
+#[cfg(test)]
+mod tests;
diff --git a/compiler/rustc_data_structures/src/vec_map/tests.rs b/compiler/rustc_data_structures/src/vec_map/tests.rs
new file mode 100644
index 00000000000..9083de85982
--- /dev/null
+++ b/compiler/rustc_data_structures/src/vec_map/tests.rs
@@ -0,0 +1,48 @@
+use super::*;
+
+impl<K, V> VecMap<K, V> {
+    fn into_vec(self) -> Vec<(K, V)> {
+        self.0.into()
+    }
+}
+
+#[test]
+fn test_from_iterator() {
+    assert_eq!(
+        std::iter::empty().collect::<VecMap<i32, bool>>().into_vec(),
+        Vec::<(i32, bool)>::new()
+    );
+    assert_eq!(std::iter::once((42, true)).collect::<VecMap<_, _>>().into_vec(), vec![(42, true)]);
+    assert_eq!(
+        vec![(1, true), (2, false)].into_iter().collect::<VecMap<_, _>>().into_vec(),
+        vec![(1, true), (2, false)]
+    );
+}
+
+#[test]
+fn test_into_iterator_owned() {
+    assert_eq!(VecMap::new().into_iter().collect::<Vec<(i32, bool)>>(), Vec::<(i32, bool)>::new());
+    assert_eq!(VecMap::from(vec![(1, true)]).into_iter().collect::<Vec<_>>(), vec![(1, true)]);
+    assert_eq!(
+        VecMap::from(vec![(1, true), (2, false)]).into_iter().collect::<Vec<_>>(),
+        vec![(1, true), (2, false)]
+    );
+}
+
+#[test]
+fn test_insert() {
+    let mut v = VecMap::new();
+    assert_eq!(v.insert(1, true), None);
+    assert_eq!(v.insert(2, false), None);
+    assert_eq!(v.clone().into_vec(), vec![(1, true), (2, false)]);
+    assert_eq!(v.insert(1, false), Some(true));
+    assert_eq!(v.into_vec(), vec![(1, false), (2, false)]);
+}
+
+#[test]
+fn test_get() {
+    let v = vec![(1, true), (2, false)].into_iter().collect::<VecMap<_, _>>();
+    assert_eq!(v.get(&1), Some(&true));
+    assert_eq!(v.get(&2), Some(&false));
+    assert_eq!(v.get(&3), None);
+}
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index c9b36dd0c24..b943977e4c2 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -21,7 +21,7 @@ use rustc_data_structures::sync::SeqCst;
 use rustc_errors::registry::{InvalidErrorCode, Registry};
 use rustc_errors::{ErrorReported, PResult};
 use rustc_feature::find_gated_cfg;
-use rustc_interface::util::{self, collect_crate_types, get_builtin_codegen_backend};
+use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
 use rustc_interface::{interface, Queries};
 use rustc_lint::LintStore;
 use rustc_metadata::locator;
@@ -499,7 +499,7 @@ fn make_input(
     }
 }
 
-// Whether to stop or continue compilation.
+/// Whether to stop or continue compilation.
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub enum Compilation {
     Stop,
@@ -765,9 +765,16 @@ pub fn version(binary: &str, matches: &getopts::Matches) {
         println!("commit-date: {}", unw(util::commit_date_str()));
         println!("host: {}", config::host_triple());
         println!("release: {}", unw(util::release_str()));
-        if cfg!(feature = "llvm") {
-            get_builtin_codegen_backend(&None, "llvm")().print_version();
-        }
+
+        let debug_flags = matches.opt_strs("Z");
+        let backend_name = debug_flags.iter().find_map(|x| {
+            if x.starts_with("codegen-backend=") {
+                Some(&x["codegen-backends=".len()..])
+            } else {
+                None
+            }
+        });
+        get_codegen_backend(&None, backend_name).print_version();
     }
 }
 
@@ -1039,8 +1046,8 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
     }
 
     // Don't handle -W help here, because we might first load plugins.
-    let r = matches.opt_strs("Z");
-    if r.iter().any(|x| *x == "help") {
+    let debug_flags = matches.opt_strs("Z");
+    if debug_flags.iter().any(|x| *x == "help") {
         describe_debug_flags();
         return None;
     }
@@ -1060,9 +1067,14 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
     }
 
     if cg_flags.iter().any(|x| *x == "passes=list") {
-        if cfg!(feature = "llvm") {
-            get_builtin_codegen_backend(&None, "llvm")().print_passes();
-        }
+        let backend_name = debug_flags.iter().find_map(|x| {
+            if x.starts_with("codegen-backend=") {
+                Some(&x["codegen-backends=".len()..])
+            } else {
+                None
+            }
+        });
+        get_codegen_backend(&None, backend_name).print_passes();
         return None;
     }
 
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index c343809179b..f10efd83236 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -157,6 +157,7 @@ E0308: include_str!("./error_codes/E0308.md"),
 E0309: include_str!("./error_codes/E0309.md"),
 E0310: include_str!("./error_codes/E0310.md"),
 E0312: include_str!("./error_codes/E0312.md"),
+E0316: include_str!("./error_codes/E0316.md"),
 E0317: include_str!("./error_codes/E0317.md"),
 E0321: include_str!("./error_codes/E0321.md"),
 E0322: include_str!("./error_codes/E0322.md"),
@@ -553,9 +554,8 @@ E0783: include_str!("./error_codes/E0783.md"),
     E0311, // thing may not live long enough
     E0313, // lifetime of borrowed pointer outlives lifetime of captured
            // variable
-    E0314, // closure outlives stack frame
-    E0315, // cannot invoke closure outside of its lifetime
-    E0316, // nested quantification of lifetimes
+//  E0314, // closure outlives stack frame
+//  E0315, // cannot invoke closure outside of its lifetime
 //  E0319, // trait impls for defaulted traits allowed just for structs/enums
     E0320, // recursive overflow during dropck
 //  E0372, // coherence not object safe
@@ -584,21 +584,21 @@ E0783: include_str!("./error_codes/E0783.md"),
 //  E0470, removed
 //  E0471, // constant evaluation error (in pattern)
     E0472, // llvm_asm! is unsupported on this target
-    E0473, // dereference of reference outside its lifetime
-    E0474, // captured variable `..` does not outlive the enclosing closure
-    E0475, // index of slice outside its lifetime
+//  E0473, // dereference of reference outside its lifetime
+//  E0474, // captured variable `..` does not outlive the enclosing closure
+//  E0475, // index of slice outside its lifetime
     E0476, // lifetime of the source pointer does not outlive lifetime bound...
-    E0479, // the type `..` (provided as the value of a type parameter) is...
-    E0480, // lifetime of method receiver does not outlive the method call
-    E0481, // lifetime of function argument does not outlive the function call
+//  E0479, // the type `..` (provided as the value of a type parameter) is...
+//  E0480, // lifetime of method receiver does not outlive the method call
+//  E0481, // lifetime of function argument does not outlive the function call
     E0482, // lifetime of return value does not outlive the function call
-    E0483, // lifetime of operand does not outlive the operation
-    E0484, // reference is not valid at the time of borrow
-    E0485, // automatically reference is not valid at the time of borrow
-    E0486, // type of expression contains references that are not valid during..
-    E0487, // unsafe use of destructor: destructor might be called while...
-    E0488, // lifetime of variable does not enclose its declaration
-    E0489, // type/lifetime parameter not in scope here
+//  E0483, // lifetime of operand does not outlive the operation
+//  E0484, // reference is not valid at the time of borrow
+//  E0485, // automatically reference is not valid at the time of borrow
+//  E0486, // type of expression contains references that are not valid during..
+//  E0487, // unsafe use of destructor: destructor might be called while...
+//  E0488, // lifetime of variable does not enclose its declaration
+//  E0489, // type/lifetime parameter not in scope here
     E0490, // a value of type `..` is borrowed for too long
     E0498,  // malformed plugin attribute
     E0514, // metadata version mismatch
diff --git a/compiler/rustc_error_codes/src/error_codes/E0316.md b/compiler/rustc_error_codes/src/error_codes/E0316.md
new file mode 100644
index 00000000000..4368c321737
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0316.md
@@ -0,0 +1,32 @@
+A `where` clause contains a nested quantification over lifetimes.
+
+Erroneous code example:
+
+```compile_fail,E0316
+trait Tr<'a, 'b> {}
+
+fn foo<T>(t: T)
+where
+    for<'a> &'a T: for<'b> Tr<'a, 'b>, // error: nested quantification
+{
+}
+```
+
+Rust syntax allows lifetime quantifications in two places within
+`where` clauses: Quantifying over the trait bound only (as in
+`Ty: for<'l> Trait<'l>`) and quantifying over the whole clause
+(as in `for<'l> &'l Ty: Trait<'l>`). Using both in the same clause
+leads to a nested lifetime quantification, which is not supported.
+
+The following example compiles, because the clause with the nested
+quantification has been rewritten to use only one `for<>`:
+
+```
+trait Tr<'a, 'b> {}
+
+fn foo<T>(t: T)
+where
+    for<'a, 'b> &'a T: Tr<'a, 'b>, // ok
+{
+}
+```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0759.md b/compiler/rustc_error_codes/src/error_codes/E0759.md
index 2fe5ada257f..6b16a7d415a 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0759.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0759.md
@@ -16,13 +16,13 @@ fn bar(x: &i32) -> Box<dyn Debug> { // error!
 
 Add `'static` requirement to fix them:
 
-```compile_fail,E0759
+```
 # use std::fmt::Debug;
-fn foo(x: &i32) -> impl Debug + 'static { // ok!
+fn foo(x: &'static i32) -> impl Debug + 'static { // ok!
     x
 }
 
-fn bar(x: &i32) -> Box<dyn Debug + 'static> { // ok!
+fn bar(x: &'static i32) -> Box<dyn Debug + 'static> { // ok!
     Box::new(x)
 }
 ```
diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs
index 5d175a3ade9..72395bd31ec 100644
--- a/compiler/rustc_errors/src/json.rs
+++ b/compiler/rustc_errors/src/json.rs
@@ -216,7 +216,7 @@ macro_rules! encode_fields {
             $(
                 $enc.emit_struct_field(
                     stringify!($name),
-                    idx,
+                    idx == 0,
                     |enc| $name.encode(enc),
                 )?;
                 idx += 1;
@@ -229,7 +229,7 @@ macro_rules! encode_fields {
 // Special-case encoder to skip tool_metadata if not set
 impl<E: Encoder> Encodable<E> for Diagnostic {
     fn encode(&self, s: &mut E) -> Result<(), E::Error> {
-        s.emit_struct("diagnostic", 7, |s| {
+        s.emit_struct(false, |s| {
             let mut idx = 0;
 
             idx = encode_fields!(
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 65352f0bc6e..979f2d3b300 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -715,6 +715,7 @@ impl Handler {
         self.inner.borrow_mut().bug(msg)
     }
 
+    #[inline]
     pub fn err_count(&self) -> usize {
         self.inner.borrow().err_count()
     }
@@ -924,6 +925,7 @@ impl HandlerInner {
         }
     }
 
+    #[inline]
     fn err_count(&self) -> usize {
         self.err_count + self.stashed_diagnostics.len()
     }
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index e1c218c6408..aab2741c852 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -1068,11 +1068,11 @@ impl<'a> ExtCtxt<'a> {
         self.resolver.check_unused_macros();
     }
 
-    /// Resolves a path mentioned inside Rust code.
+    /// Resolves a `path` mentioned inside Rust code, returning an absolute path.
     ///
-    /// This unifies the logic used for resolving `include_X!`, and `#[doc(include)]` file paths.
+    /// This unifies the logic used for resolving `include_X!`.
     ///
-    /// Returns an absolute path to the file that `path` refers to.
+    /// FIXME: move this to `rustc_builtin_macros` and make it private.
     pub fn resolve_path(
         &self,
         path: impl Into<PathBuf>,
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index f5c6bb3db65..39c0447bd09 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -12,11 +12,11 @@ use rustc_ast::ptr::P;
 use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
-use rustc_ast::{AstLike, AttrItem, Block, Inline, ItemKind, LitKind, MacArgs};
+use rustc_ast::{AstLike, Block, Inline, ItemKind, MacArgs};
 use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem};
 use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe};
 use rustc_ast_pretty::pprust;
-use rustc_attr::{self as attr, is_builtin_attr};
+use rustc_attr::is_builtin_attr;
 use rustc_data_structures::map_in_place::MapInPlace;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_data_structures::sync::Lrc;
@@ -28,15 +28,14 @@ use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS;
 use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_session::parse::{feature_err, ParseSess};
 use rustc_session::Limit;
-use rustc_span::symbol::{sym, Ident, Symbol};
-use rustc_span::{ExpnId, FileName, Span, DUMMY_SP};
+use rustc_span::symbol::{sym, Ident};
+use rustc_span::{ExpnId, FileName, Span};
 
 use smallvec::{smallvec, SmallVec};
-use std::io::ErrorKind;
 use std::ops::DerefMut;
 use std::path::PathBuf;
 use std::rc::Rc;
-use std::{iter, mem, slice};
+use std::{iter, mem};
 
 macro_rules! ast_fragments {
     (
@@ -1524,139 +1523,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
         noop_flat_map_generic_param(param, self)
     }
 
-    fn visit_attribute(&mut self, at: &mut ast::Attribute) {
-        // turn `#[doc(include="filename")]` attributes into `#[doc(include(file="filename",
-        // contents="file contents")]` attributes
-        if !self.cx.sess.check_name(at, sym::doc) {
-            return noop_visit_attribute(at, self);
-        }
-
-        if let Some(list) = at.meta_item_list() {
-            if !list.iter().any(|it| it.has_name(sym::include)) {
-                return noop_visit_attribute(at, self);
-            }
-
-            let mut items = vec![];
-
-            for mut it in list {
-                if !it.has_name(sym::include) {
-                    items.push({
-                        noop_visit_meta_list_item(&mut it, self);
-                        it
-                    });
-                    continue;
-                }
-
-                if let Some(file) = it.value_str() {
-                    let err_count = self.cx.sess.parse_sess.span_diagnostic.err_count();
-                    self.check_attributes(slice::from_ref(at));
-                    if self.cx.sess.parse_sess.span_diagnostic.err_count() > err_count {
-                        // avoid loading the file if they haven't enabled the feature
-                        return noop_visit_attribute(at, self);
-                    }
-
-                    let filename = match self.cx.resolve_path(&*file.as_str(), it.span()) {
-                        Ok(filename) => filename,
-                        Err(mut err) => {
-                            err.emit();
-                            continue;
-                        }
-                    };
-
-                    match self.cx.source_map().load_file(&filename) {
-                        Ok(source_file) => {
-                            let src = source_file
-                                .src
-                                .as_ref()
-                                .expect("freshly loaded file should have a source");
-                            let src_interned = Symbol::intern(src.as_str());
-
-                            let include_info = vec![
-                                ast::NestedMetaItem::MetaItem(attr::mk_name_value_item_str(
-                                    Ident::with_dummy_span(sym::file),
-                                    file,
-                                    DUMMY_SP,
-                                )),
-                                ast::NestedMetaItem::MetaItem(attr::mk_name_value_item_str(
-                                    Ident::with_dummy_span(sym::contents),
-                                    src_interned,
-                                    DUMMY_SP,
-                                )),
-                            ];
-
-                            let include_ident = Ident::with_dummy_span(sym::include);
-                            let item = attr::mk_list_item(include_ident, include_info);
-                            items.push(ast::NestedMetaItem::MetaItem(item));
-                        }
-                        Err(e) => {
-                            let lit_span = it.name_value_literal_span().unwrap();
-
-                            if e.kind() == ErrorKind::InvalidData {
-                                self.cx
-                                    .struct_span_err(
-                                        lit_span,
-                                        &format!("{} wasn't a utf-8 file", filename.display()),
-                                    )
-                                    .span_label(lit_span, "contains invalid utf-8")
-                                    .emit();
-                            } else {
-                                let mut err = self.cx.struct_span_err(
-                                    lit_span,
-                                    &format!("couldn't read {}: {}", filename.display(), e),
-                                );
-                                err.span_label(lit_span, "couldn't read file");
-
-                                err.emit();
-                            }
-                        }
-                    }
-                } else {
-                    let mut err = self
-                        .cx
-                        .struct_span_err(it.span(), "expected path to external documentation");
-
-                    // Check if the user erroneously used `doc(include(...))` syntax.
-                    let literal = it.meta_item_list().and_then(|list| {
-                        if list.len() == 1 {
-                            list[0].literal().map(|literal| &literal.kind)
-                        } else {
-                            None
-                        }
-                    });
-
-                    let (path, applicability) = match &literal {
-                        Some(LitKind::Str(path, ..)) => {
-                            (path.to_string(), Applicability::MachineApplicable)
-                        }
-                        _ => (String::from("<path>"), Applicability::HasPlaceholders),
-                    };
-
-                    err.span_suggestion(
-                        it.span(),
-                        "provide a file path with `=`",
-                        format!("include = \"{}\"", path),
-                        applicability,
-                    );
-
-                    err.emit();
-                }
-            }
-
-            let meta = attr::mk_list_item(Ident::with_dummy_span(sym::doc), items);
-            *at = ast::Attribute {
-                kind: ast::AttrKind::Normal(
-                    AttrItem { path: meta.path, args: meta.kind.mac_args(meta.span), tokens: None },
-                    None,
-                ),
-                span: at.span,
-                id: at.id,
-                style: at.style,
-            };
-        } else {
-            noop_visit_attribute(at, self)
-        }
-    }
-
     fn visit_id(&mut self, id: &mut ast::NodeId) {
         if self.monotonic {
             debug_assert_eq!(*id, ast::DUMMY_NODE_ID);
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs
index 16510b3eb07..efed41de23a 100644
--- a/compiler/rustc_expand/src/lib.rs
+++ b/compiler/rustc_expand/src/lib.rs
@@ -1,7 +1,7 @@
-#![feature(bool_to_option)]
 #![feature(crate_visibility_modifier)]
 #![feature(decl_macro)]
 #![feature(destructuring_assignment)]
+#![feature(format_args_capture)]
 #![feature(iter_zip)]
 #![feature(proc_macro_diagnostic)]
 #![feature(proc_macro_internals)]
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index 1aed42a24e2..a7434d73abe 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -85,6 +85,7 @@ use smallvec::{smallvec, SmallVec};
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
+use rustc_span::symbol::Ident;
 use std::borrow::Cow;
 use std::collections::hash_map::Entry::{Occupied, Vacant};
 use std::mem;
@@ -615,7 +616,11 @@ fn inner_parse_loop<'root, 'tt>(
 
 /// Use the given sequence of token trees (`ms`) as a matcher. Match the token
 /// stream from the given `parser` against it and return the match.
-pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> NamedParseResult {
+pub(super) fn parse_tt(
+    parser: &mut Cow<'_, Parser<'_>>,
+    ms: &[TokenTree],
+    macro_name: Ident,
+) -> NamedParseResult {
     // A queue of possible matcher positions. We initialize it with the matcher position in which
     // the "dot" is before the first token of the first token tree in `ms`. `inner_parse_loop` then
     // processes all of these possible matcher positions and produces possible next positions into
@@ -711,7 +716,7 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na
             return Error(
                 parser.token.span,
                 format!(
-                    "local ambiguity: multiple parsing options: {}",
+                    "local ambiguity when calling macro `{macro_name}`: multiple parsing options: {}",
                     match next_items.len() {
                         0 => format!("built-in NTs {}.", nts),
                         1 => format!("built-in NTs {} or 1 other option.", nts),
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 6608573d720..abad190b072 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -245,7 +245,7 @@ fn generic_extension<'cx>(
         // are not recorded. On the first `Success(..)`ful matcher, the spans are merged.
         let mut gated_spans_snapshot = mem::take(&mut *sess.gated_spans.spans.borrow_mut());
 
-        match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) {
+        match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt, name) {
             Success(named_matches) => {
                 // The matcher was `Success(..)`ful.
                 // Merge the gated spans from parsing the matcher with the pre-existing ones.
@@ -338,7 +338,7 @@ fn generic_extension<'cx>(
                 _ => continue,
             };
             if let Success(_) =
-                parse_tt(&mut Cow::Borrowed(&parser_from_cx(sess, arg.clone())), lhs_tt)
+                parse_tt(&mut Cow::Borrowed(&parser_from_cx(sess, arg.clone())), lhs_tt, name)
             {
                 if comma_span.is_dummy() {
                     err.note("you might be missing a comma");
@@ -432,7 +432,7 @@ pub fn compile_declarative_macro(
     ];
 
     let parser = Parser::new(&sess.parse_sess, body, true, rustc_parse::MACRO_ARGUMENTS);
-    let argument_map = match parse_tt(&mut Cow::Borrowed(&parser), &argument_gram) {
+    let argument_map = match parse_tt(&mut Cow::Borrowed(&parser), &argument_gram, def.ident) {
         Success(m) => m,
         Failure(token, msg) => {
             let s = parse_failure_msg(&token);
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index a84737e80a0..0359f503ef9 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -250,6 +250,7 @@ declare_features! (
     (active, f16c_target_feature, "1.36.0", Some(44839), None),
     (active, riscv_target_feature, "1.45.0", Some(44839), None),
     (active, ermsb_target_feature, "1.49.0", Some(44839), None),
+    (active, bpf_target_feature, "1.54.0", Some(44839), None),
 
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates (target features)
@@ -370,9 +371,6 @@ declare_features! (
     /// Allows `#[doc(masked)]`.
     (active, doc_masked, "1.21.0", Some(44027), None),
 
-    /// Allows `#[doc(include = "some-file")]`.
-    (active, external_doc, "1.22.0", Some(44732), None),
-
     /// Allows using `crate` as visibility modifier, synonymous with `pub(crate)`.
     (active, crate_visibility_modifier, "1.23.0", Some(53120), None),
 
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index e7e128f8a9b..259a6328a22 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -569,10 +569,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     rustc_attr!(TEST, rustc_if_this_changed, AssumedUsed, template!(Word, List: "DepNode")),
     rustc_attr!(TEST, rustc_then_this_would_need, AssumedUsed, template!(List: "DepNode")),
     rustc_attr!(
-        TEST, rustc_dirty, AssumedUsed,
-        template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#),
-    ),
-    rustc_attr!(
         TEST, rustc_clean, AssumedUsed,
         template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#),
     ),
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 138398825af..71c10eb6507 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -140,6 +140,10 @@ declare_features! (
     (removed, const_fn, "1.54.0", Some(57563), None,
      Some("split into finer-grained feature gates")),
 
+    /// Allows `#[doc(include = "some-file")]`.
+    (removed, external_doc, "1.54.0", Some(44732), None,
+     Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")),
+
     // -------------------------------------------------------------------------
     // feature-group-end: removed features
     // -------------------------------------------------------------------------
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index 77aad0baef5..753b8c85670 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -14,6 +14,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_index::vec::IndexVec;
+use rustc_span::crate_disambiguator::CrateDisambiguator;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::{kw, sym, Symbol};
 
@@ -93,15 +94,6 @@ impl DefPathTable {
             .iter_enumerated()
             .map(move |(index, key)| (index, key, &self.def_path_hashes[index]))
     }
-
-    pub fn all_def_path_hashes_and_def_ids(
-        &self,
-        krate: CrateNum,
-    ) -> impl Iterator<Item = (DefPathHash, DefId)> + '_ {
-        self.def_path_hashes
-            .iter_enumerated()
-            .map(move |(index, hash)| (*hash, DefId { krate, index }))
-    }
 }
 
 /// The definition table containing node definitions.
@@ -305,6 +297,7 @@ impl Definitions {
         self.table.index_to_key.len()
     }
 
+    #[inline]
     pub fn def_key(&self, id: LocalDefId) -> DefKey {
         self.table.def_key(id.local_def_index)
     }
@@ -337,7 +330,7 @@ impl Definitions {
     }
 
     /// Adds a root definition (no parent) and a few other reserved definitions.
-    pub fn new(stable_crate_id: StableCrateId) -> Definitions {
+    pub fn new(crate_name: &str, crate_disambiguator: CrateDisambiguator) -> Definitions {
         let key = DefKey {
             parent: None,
             disambiguated_data: DisambiguatedDefPathData {
@@ -346,6 +339,7 @@ impl Definitions {
             },
         };
 
+        let stable_crate_id = StableCrateId::new(crate_name, crate_disambiguator);
         let parent_hash = DefPathHash::new(stable_crate_id, 0);
         let def_path_hash = key.compute_stable_hash(parent_hash);
 
@@ -437,6 +431,14 @@ impl Definitions {
     pub fn iter_local_def_id(&self) -> impl Iterator<Item = LocalDefId> + '_ {
         self.def_id_to_hir_id.iter_enumerated().map(|(k, _)| k)
     }
+
+    #[inline(always)]
+    pub fn local_def_path_hash_to_def_id(&self, hash: DefPathHash) -> Option<LocalDefId> {
+        self.table
+            .def_path_hash_to_index
+            .get(&hash)
+            .map(|&local_def_index| LocalDefId { local_def_index })
+    }
 }
 
 #[derive(Copy, Clone, PartialEq, Debug)]
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 91fd97a0d40..577d43b1c8e 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1,7 +1,7 @@
 // ignore-tidy-filelength
 use crate::def::{CtorKind, DefKind, Res};
 use crate::def_id::DefId;
-crate use crate::hir_id::HirId;
+crate use crate::hir_id::{HirId, ItemLocalId};
 use crate::{itemlikevisit, LangItem};
 
 use rustc_ast::util::parser::ExprPrecedence;
@@ -10,6 +10,7 @@ use rustc_ast::{Attribute, FloatTy, IntTy, Label, LitKind, StrStyle, TraitObject
 pub use rustc_ast::{BorrowKind, ImplPolarity, IsAuto};
 pub use rustc_ast::{CaptureBy, Movability, Mutability};
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
 use rustc_macros::HashStable_Generic;
 use rustc_span::source_map::Spanned;
@@ -658,7 +659,9 @@ pub struct Crate<'hir> {
     /// they are declared in the static array generated by proc_macro_harness.
     pub proc_macros: Vec<HirId>,
 
-    pub trait_map: BTreeMap<HirId, Vec<TraitCandidate>>,
+    /// Map indicating what traits are in scope for places where this
+    /// is relevant; generated by resolve.
+    pub trait_map: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Box<[TraitCandidate]>>>,
 
     /// Collected attributes from HIR nodes.
     pub attrs: BTreeMap<HirId, &'hir [Attribute]>,
@@ -2485,6 +2488,7 @@ pub enum FnRetTy<'hir> {
 }
 
 impl FnRetTy<'_> {
+    #[inline]
     pub fn span(&self) -> Span {
         match *self {
             Self::DefaultReturn(span) => span,
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index 7f3c410b1ec..ad2ecae9233 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -3,12 +3,10 @@
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
 
 #![feature(crate_visibility_modifier)]
-#![feature(const_panic)]
 #![cfg_attr(bootstrap, feature(extended_key_value_attributes))]
 #![feature(in_band_lifetimes)]
 #![feature(once_cell)]
 #![feature(min_specialization)]
-#![feature(trusted_step)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs
index 4636d515249..2aafc6afa23 100644
--- a/compiler/rustc_hir/src/tests.rs
+++ b/compiler/rustc_hir/src/tests.rs
@@ -1,4 +1,6 @@
 use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData};
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_span::crate_disambiguator::CrateDisambiguator;
 use rustc_span::def_id::{DefPathHash, StableCrateId};
 
 #[test]
@@ -11,16 +13,17 @@ fn def_path_hash_depends_on_crate_id() {
     // the crate by changing the crate disambiguator (e.g. via bumping the
     // crate's version number).
 
-    let id0 = StableCrateId::new("foo", false, vec!["1".to_string()]);
-    let id1 = StableCrateId::new("foo", false, vec!["2".to_string()]);
+    let d0 = CrateDisambiguator::from(Fingerprint::new(12, 34));
+    let d1 = CrateDisambiguator::from(Fingerprint::new(56, 78));
 
-    let h0 = mk_test_hash(id0);
-    let h1 = mk_test_hash(id1);
+    let h0 = mk_test_hash("foo", d0);
+    let h1 = mk_test_hash("foo", d1);
 
     assert_ne!(h0.stable_crate_id(), h1.stable_crate_id());
     assert_ne!(h0.local_hash(), h1.local_hash());
 
-    fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash {
+    fn mk_test_hash(crate_name: &str, crate_disambiguator: CrateDisambiguator) -> DefPathHash {
+        let stable_crate_id = StableCrateId::new(crate_name, crate_disambiguator);
         let parent_hash = DefPathHash::new(stable_crate_id, 0);
 
         let key = DefKey {
diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs
index e7bd488af8e..9abd4eae914 100644
--- a/compiler/rustc_incremental/src/persist/dirty_clean.rs
+++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs
@@ -1,6 +1,5 @@
-//! Debugging code to test fingerprints computed for query results.
-//! For each node marked with `#[rustc_clean]` or `#[rustc_dirty]`,
-//! we will compare the fingerprint from the current and from the previous
+//! Debugging code to test fingerprints computed for query results.  For each node marked with
+//! `#[rustc_clean]` we will compare the fingerprint from the current and from the previous
 //! compilation session as appropriate:
 //!
 //! - `#[rustc_clean(cfg="rev2", except="typeck")]` if we are
@@ -30,7 +29,6 @@ use std::iter::FromIterator;
 use std::vec::Vec;
 
 const EXCEPT: Symbol = sym::except;
-const LABEL: Symbol = sym::label;
 const CFG: Symbol = sym::cfg;
 
 // Base and Extra labels to build up the labels
@@ -102,6 +100,12 @@ const LABELS_FN_IN_TRAIT: &[&[&str]] =
 const LABELS_HIR_ONLY: &[&[&str]] = &[BASE_HIR];
 
 /// Impl `DepNode`s.
+const LABELS_TRAIT: &[&[&str]] = &[
+    BASE_HIR,
+    &[label_strs::associated_item_def_ids, label_strs::predicates_of, label_strs::generics_of],
+];
+
+/// Impl `DepNode`s.
 const LABELS_IMPL: &[&[&str]] = &[BASE_HIR, BASE_IMPL];
 
 /// Abstract data type (struct, enum, union) `DepNode`s.
@@ -122,22 +126,12 @@ struct Assertion {
     dirty: Labels,
 }
 
-impl Assertion {
-    fn from_clean_labels(labels: Labels) -> Assertion {
-        Assertion { clean: labels, dirty: Labels::default() }
-    }
-
-    fn from_dirty_labels(labels: Labels) -> Assertion {
-        Assertion { clean: Labels::default(), dirty: labels }
-    }
-}
-
 pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) {
     if !tcx.sess.opts.debugging_opts.query_dep_graph {
         return;
     }
 
-    // can't add `#[rustc_dirty]` etc without opting in to this feature
+    // can't add `#[rustc_clean]` etc without opting in to this feature
     if !tcx.features().rustc_attrs {
         return;
     }
@@ -147,11 +141,7 @@ pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) {
         let mut dirty_clean_visitor = DirtyCleanVisitor { tcx, checked_attrs: Default::default() };
         krate.visit_all_item_likes(&mut dirty_clean_visitor);
 
-        let mut all_attrs = FindAllAttrs {
-            tcx,
-            attr_names: &[sym::rustc_dirty, sym::rustc_clean],
-            found_attrs: vec![],
-        };
+        let mut all_attrs = FindAllAttrs { tcx, found_attrs: vec![] };
         intravisit::walk_crate(&mut all_attrs, krate);
 
         // Note that we cannot use the existing "unused attribute"-infrastructure
@@ -169,37 +159,20 @@ pub struct DirtyCleanVisitor<'tcx> {
 impl DirtyCleanVisitor<'tcx> {
     /// Possibly "deserialize" the attribute into a clean/dirty assertion
     fn assertion_maybe(&mut self, item_id: LocalDefId, attr: &Attribute) -> Option<Assertion> {
-        let is_clean = if self.tcx.sess.check_name(attr, sym::rustc_dirty) {
-            false
-        } else if self.tcx.sess.check_name(attr, sym::rustc_clean) {
-            true
-        } else {
+        if !self.tcx.sess.check_name(attr, sym::rustc_clean) {
             // skip: not rustc_clean/dirty
             return None;
-        };
+        }
         if !check_config(self.tcx, attr) {
             // skip: not the correct `cfg=`
             return None;
         }
-        let assertion = if let Some(labels) = self.labels(attr) {
-            if is_clean {
-                Assertion::from_clean_labels(labels)
-            } else {
-                Assertion::from_dirty_labels(labels)
-            }
-        } else {
-            self.assertion_auto(item_id, attr, is_clean)
-        };
+        let assertion = self.assertion_auto(item_id, attr);
         Some(assertion)
     }
 
     /// Gets the "auto" assertion on pre-validated attr, along with the `except` labels.
-    fn assertion_auto(
-        &mut self,
-        item_id: LocalDefId,
-        attr: &Attribute,
-        is_clean: bool,
-    ) -> Assertion {
+    fn assertion_auto(&mut self, item_id: LocalDefId, attr: &Attribute) -> Assertion {
         let (name, mut auto) = self.auto_labels(item_id, attr);
         let except = self.except(attr);
         for e in except.iter() {
@@ -211,21 +184,7 @@ impl DirtyCleanVisitor<'tcx> {
                 self.tcx.sess.span_fatal(attr.span, &msg);
             }
         }
-        if is_clean {
-            Assertion { clean: auto, dirty: except }
-        } else {
-            Assertion { clean: except, dirty: auto }
-        }
-    }
-
-    fn labels(&self, attr: &Attribute) -> Option<Labels> {
-        for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
-            if item.has_name(LABEL) {
-                let value = expect_associated_value(self.tcx, &item);
-                return Some(self.resolve_labels(&item, value));
-            }
-        }
-        None
+        Assertion { clean: auto, dirty: except }
     }
 
     /// `except=` attribute value
@@ -288,20 +247,7 @@ impl DirtyCleanVisitor<'tcx> {
                     HirItem::Union(..) => ("ItemUnion", LABELS_ADT),
 
                     // Represents a Trait Declaration
-                    // FIXME(michaelwoerister): trait declaration is buggy because sometimes some of
-                    // the depnodes don't exist (because they legitimately didn't need to be
-                    // calculated)
-                    //
-                    // michaelwoerister and vitiral came up with a possible solution,
-                    // to just do this before every query
-                    // ```
-                    // ::rustc_middle::ty::query::plumbing::force_from_dep_node(tcx, dep_node)
-                    // ```
-                    //
-                    // However, this did not seem to work effectively and more bugs were hit.
-                    // Nebie @vitiral gave up :)
-                    //
-                    //HirItem::Trait(..) => ("ItemTrait", LABELS_TRAIT),
+                    HirItem::Trait(..) => ("ItemTrait", LABELS_TRAIT),
 
                     // An implementation, eg `impl<A> Trait for Foo { .. }`
                     HirItem::Impl { .. } => ("ItemKind::Impl", LABELS_IMPL),
@@ -434,35 +380,23 @@ impl ItemLikeVisitor<'tcx> for DirtyCleanVisitor<'tcx> {
     }
 }
 
-/// Given a `#[rustc_dirty]` or `#[rustc_clean]` attribute, scan
-/// for a `cfg="foo"` attribute and check whether we have a cfg
-/// flag called `foo`.
-///
-/// Also make sure that the `label` and `except` fields do not
-/// both exist.
+/// Given a `#[rustc_clean]` attribute, scan for a `cfg="foo"` attribute and check whether we have
+/// a cfg flag called `foo`.
 fn check_config(tcx: TyCtxt<'_>, attr: &Attribute) -> bool {
     debug!("check_config(attr={:?})", attr);
     let config = &tcx.sess.parse_sess.config;
     debug!("check_config: config={:?}", config);
-    let (mut cfg, mut except, mut label) = (None, false, false);
+    let mut cfg = None;
     for item in attr.meta_item_list().unwrap_or_else(Vec::new) {
         if item.has_name(CFG) {
             let value = expect_associated_value(tcx, &item);
             debug!("check_config: searching for cfg {:?}", value);
             cfg = Some(config.contains(&(value, None)));
-        }
-        if item.has_name(LABEL) {
-            label = true;
-        }
-        if item.has_name(EXCEPT) {
-            except = true;
+        } else if !item.has_name(EXCEPT) {
+            tcx.sess.span_err(attr.span, &format!("unknown item `{}`", item.name_or_empty()));
         }
     }
 
-    if label && except {
-        tcx.sess.span_fatal(attr.span, "must specify only one of: `label`, `except`");
-    }
-
     match cfg {
         None => tcx.sess.span_fatal(attr.span, "no cfg attribute"),
         Some(c) => c,
@@ -483,21 +417,18 @@ fn expect_associated_value(tcx: TyCtxt<'_>, item: &NestedMetaItem) -> Symbol {
     }
 }
 
-// A visitor that collects all #[rustc_dirty]/#[rustc_clean] attributes from
+// A visitor that collects all #[rustc_clean] attributes from
 // the HIR. It is used to verify that we really ran checks for all annotated
 // nodes.
-pub struct FindAllAttrs<'a, 'tcx> {
+pub struct FindAllAttrs<'tcx> {
     tcx: TyCtxt<'tcx>,
-    attr_names: &'a [Symbol],
     found_attrs: Vec<&'tcx Attribute>,
 }
 
-impl FindAllAttrs<'_, 'tcx> {
+impl FindAllAttrs<'tcx> {
     fn is_active_attr(&mut self, attr: &Attribute) -> bool {
-        for attr_name in self.attr_names {
-            if self.tcx.sess.check_name(attr, *attr_name) && check_config(self.tcx, attr) {
-                return true;
-            }
+        if self.tcx.sess.check_name(attr, sym::rustc_clean) && check_config(self.tcx, attr) {
+            return true;
         }
 
         false
@@ -506,17 +437,14 @@ impl FindAllAttrs<'_, 'tcx> {
     fn report_unchecked_attrs(&self, mut checked_attrs: FxHashSet<ast::AttrId>) {
         for attr in &self.found_attrs {
             if !checked_attrs.contains(&attr.id) {
-                self.tcx.sess.span_err(
-                    attr.span,
-                    "found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute",
-                );
+                self.tcx.sess.span_err(attr.span, "found unchecked `#[rustc_clean]` attribute");
                 checked_attrs.insert(attr.id);
             }
         }
     }
 }
 
-impl intravisit::Visitor<'tcx> for FindAllAttrs<'_, 'tcx> {
+impl intravisit::Visitor<'tcx> for FindAllAttrs<'tcx> {
     type Map = Map<'tcx>;
 
     fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index 2ed0539841a..83e80b55dae 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -108,7 +108,7 @@ use rustc_data_structures::svh::Svh;
 use rustc_data_structures::{base_n, flock};
 use rustc_errors::ErrorReported;
 use rustc_fs_util::{link_or_copy, LinkOrCopy};
-use rustc_session::{Session, StableCrateId};
+use rustc_session::{CrateDisambiguator, Session};
 
 use std::fs as std_fs;
 use std::io;
@@ -189,7 +189,7 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu
 pub fn prepare_session_directory(
     sess: &Session,
     crate_name: &str,
-    stable_crate_id: StableCrateId,
+    crate_disambiguator: CrateDisambiguator,
 ) -> Result<(), ErrorReported> {
     if sess.opts.incremental.is_none() {
         return Ok(());
@@ -200,7 +200,7 @@ pub fn prepare_session_directory(
     debug!("prepare_session_directory");
 
     // {incr-comp-dir}/{crate-name-and-disambiguator}
-    let crate_dir = crate_path(sess, crate_name, stable_crate_id);
+    let crate_dir = crate_path(sess, crate_name, crate_disambiguator);
     debug!("crate-dir: {}", crate_dir.display());
     create_dir(sess, &crate_dir, "crate")?;
 
@@ -648,12 +648,19 @@ fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> {
     Ok(UNIX_EPOCH + duration)
 }
 
-fn crate_path(sess: &Session, crate_name: &str, stable_crate_id: StableCrateId) -> PathBuf {
+fn crate_path(
+    sess: &Session,
+    crate_name: &str,
+    crate_disambiguator: CrateDisambiguator,
+) -> PathBuf {
     let incr_dir = sess.opts.incremental.as_ref().unwrap().clone();
 
-    let stable_crate_id = base_n::encode(stable_crate_id.to_u64() as u128, INT_ENCODE_BASE);
+    // The full crate disambiguator is really long. 64 bits of it should be
+    // sufficient.
+    let crate_disambiguator = crate_disambiguator.to_fingerprint().to_smaller_hash();
+    let crate_disambiguator = base_n::encode(crate_disambiguator as u128, INT_ENCODE_BASE);
 
-    let crate_name = format!("{}-{}", crate_name, stable_crate_id);
+    let crate_name = format!("{}-{}", crate_name, crate_disambiguator);
     incr_dir.join(crate_name)
 }
 
diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs
index 303c39a39a9..8539cc69371 100644
--- a/compiler/rustc_incremental/src/persist/load.rs
+++ b/compiler/rustc_incremental/src/persist/load.rs
@@ -1,7 +1,6 @@
 //! Code to save/load the dep-graph from files.
 
 use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::definitions::DefPathTable;
 use rustc_middle::dep_graph::{SerializedDepGraph, WorkProduct, WorkProductId};
 use rustc_middle::ty::query::OnDiskCache;
 use rustc_serialize::opaque::Decoder;
@@ -196,10 +195,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
 /// If we are not in incremental compilation mode, returns `None`.
 /// Otherwise, tries to load the query result cache from disk,
 /// creating an empty cache if it could not be loaded.
-pub fn load_query_result_cache<'a>(
-    sess: &'a Session,
-    def_path_table: &DefPathTable,
-) -> Option<OnDiskCache<'a>> {
+pub fn load_query_result_cache<'a>(sess: &'a Session) -> Option<OnDiskCache<'a>> {
     if sess.opts.incremental.is_none() {
         return None;
     }
@@ -212,7 +208,7 @@ pub fn load_query_result_cache<'a>(
         sess.is_nightly_build(),
     ) {
         LoadResult::Ok { data: (bytes, start_pos) } => {
-            Some(OnDiskCache::new(sess, bytes, start_pos, def_path_table))
+            Some(OnDiskCache::new(sess, bytes, start_pos))
         }
         _ => Some(OnDiskCache::new_empty(sess.source_map())),
     }
diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs
index 9603b102cbc..a8455854ebb 100644
--- a/compiler/rustc_incremental/src/persist/save.rs
+++ b/compiler/rustc_incremental/src/persist/save.rs
@@ -229,6 +229,7 @@ pub fn build_dep_graph(
     }
 
     Some(DepGraph::new(
+        &sess.prof,
         prev_graph,
         prev_work_products,
         encoder,
diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs
index 04d62391c02..0093fa5e562 100644
--- a/compiler/rustc_index/src/lib.rs
+++ b/compiler/rustc_index/src/lib.rs
@@ -1,12 +1,10 @@
 #![feature(allow_internal_unstable)]
 #![feature(bench_black_box)]
-#![feature(const_panic)]
 #![feature(extend_one)]
 #![feature(iter_zip)]
 #![feature(unboxed_closures)]
 #![feature(test)]
 #![feature(fn_traits)]
-#![feature(trusted_step)]
 
 pub mod bit_set;
 pub mod vec;
diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs
index 3f759f4023b..246fa28d986 100644
--- a/compiler/rustc_index/src/vec.rs
+++ b/compiler/rustc_index/src/vec.rs
@@ -65,7 +65,7 @@ impl Idx for u32 {
 /// `u32::MAX`. You can also customize things like the `Debug` impl,
 /// what traits are derived, and so forth via the macro.
 #[macro_export]
-#[allow_internal_unstable(step_trait, rustc_attrs)]
+#[allow_internal_unstable(step_trait, rustc_attrs, trusted_step)]
 macro_rules! newtype_index {
     // ---- public rules ----
 
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index b8ecc949588..c3c28d70081 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -660,7 +660,12 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
         )
     }
 
-    fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>) {
+    fn push_outlives(
+        &mut self,
+        sup: ty::Region<'tcx>,
+        sub: ty::Region<'tcx>,
+        _info: ty::VarianceDiagInfo<'tcx>,
+    ) {
         self.obligations.push(Obligation {
             cause: self.cause.clone(),
             param_env: self.param_env,
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index 30214e94203..3a11b5a2144 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -371,9 +371,12 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
         match dir {
             EqTo => self.equate(a_is_expected).relate(a_ty, b_ty),
             SubtypeOf => self.sub(a_is_expected).relate(a_ty, b_ty),
-            SupertypeOf => {
-                self.sub(a_is_expected).relate_with_variance(ty::Contravariant, a_ty, b_ty)
-            }
+            SupertypeOf => self.sub(a_is_expected).relate_with_variance(
+                ty::Contravariant,
+                ty::VarianceDiagInfo::default(),
+                a_ty,
+                b_ty,
+            ),
         }?;
 
         Ok(())
@@ -574,6 +577,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
+        _info: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
@@ -737,7 +741,12 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
                 if self.tcx().lazy_normalization() =>
             {
                 assert_eq!(promoted, None);
-                let substs = self.relate_with_variance(ty::Variance::Invariant, substs, substs)?;
+                let substs = self.relate_with_variance(
+                    ty::Variance::Invariant,
+                    ty::VarianceDiagInfo::default(),
+                    substs,
+                    substs,
+                )?;
                 Ok(self.tcx().mk_const(ty::Const {
                     ty: c.ty,
                     val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
@@ -831,6 +840,7 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         _variance: ty::Variance,
+        _info: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
@@ -965,7 +975,12 @@ impl TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
                 if self.tcx().lazy_normalization() =>
             {
                 assert_eq!(promoted, None);
-                let substs = self.relate_with_variance(ty::Variance::Invariant, substs, substs)?;
+                let substs = self.relate_with_variance(
+                    ty::Variance::Invariant,
+                    ty::VarianceDiagInfo::default(),
+                    substs,
+                    substs,
+                )?;
                 Ok(self.tcx().mk_const(ty::Const {
                     ty: c.ty,
                     val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs
index 45ba50bb634..0c93271a1ae 100644
--- a/compiler/rustc_infer/src/infer/equate.rs
+++ b/compiler/rustc_infer/src/infer/equate.rs
@@ -59,6 +59,7 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         _: ty::Variance,
+        _info: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 680f6af63f2..fb762d2deba 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -524,7 +524,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             }
 
             fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
-                Ok(vec![self.tcx.original_crate_name(cnum).to_string()])
+                Ok(vec![self.tcx.crate_name(cnum).to_string()])
             }
             fn path_qualified(
                 self,
diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs
index 02662043dba..60f02b84aa3 100644
--- a/compiler/rustc_infer/src/infer/glb.rs
+++ b/compiler/rustc_infer/src/infer/glb.rs
@@ -43,6 +43,7 @@ impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
+        _info: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
@@ -96,7 +97,7 @@ impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> {
         // When higher-ranked types are involved, computing the LUB is
         // very challenging, switch to invariance. This is obviously
         // overly conservative but works ok in practice.
-        self.relate_with_variance(ty::Variance::Invariant, a, b)?;
+        self.relate_with_variance(ty::Variance::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
         Ok(a)
     }
 }
diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs
index 4fa8f2f1a6a..a08323535c5 100644
--- a/compiler/rustc_infer/src/infer/lub.rs
+++ b/compiler/rustc_infer/src/infer/lub.rs
@@ -43,6 +43,7 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
+        _info: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
@@ -96,7 +97,7 @@ impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> {
         // When higher-ranked types are involved, computing the LUB is
         // very challenging, switch to invariance. This is obviously
         // overly conservative but works ok in practice.
-        self.relate_with_variance(ty::Variance::Invariant, a, b)?;
+        self.relate_with_variance(ty::Variance::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
         Ok(a)
     }
 }
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index 077d2cc20a2..20be06adfd0 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -55,6 +55,8 @@ where
     /// - Bivariant means that it doesn't matter.
     ambient_variance: ty::Variance,
 
+    ambient_variance_info: ty::VarianceDiagInfo<'tcx>,
+
     /// When we pass through a set of binders (e.g., when looking into
     /// a `fn` type), we push a new bound region scope onto here. This
     /// will contain the instantiated region for each region in those
@@ -78,7 +80,12 @@ pub trait TypeRelatingDelegate<'tcx> {
     /// satisfied for the two types to be related. `sub` and `sup` may
     /// be regions from the type or new variables created through the
     /// delegate.
-    fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>);
+    fn push_outlives(
+        &mut self,
+        sup: ty::Region<'tcx>,
+        sub: ty::Region<'tcx>,
+        info: ty::VarianceDiagInfo<'tcx>,
+    );
 
     fn const_equate(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>);
 
@@ -138,7 +145,14 @@ where
         delegate: D,
         ambient_variance: ty::Variance,
     ) -> Self {
-        Self { infcx, delegate, ambient_variance, a_scopes: vec![], b_scopes: vec![] }
+        Self {
+            infcx,
+            delegate,
+            ambient_variance,
+            ambient_variance_info: ty::VarianceDiagInfo::default(),
+            a_scopes: vec![],
+            b_scopes: vec![],
+        }
     }
 
     fn ambient_covariance(&self) -> bool {
@@ -239,10 +253,15 @@ where
 
     /// Push a new outlives requirement into our output set of
     /// constraints.
-    fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>) {
+    fn push_outlives(
+        &mut self,
+        sup: ty::Region<'tcx>,
+        sub: ty::Region<'tcx>,
+        info: ty::VarianceDiagInfo<'tcx>,
+    ) {
         debug!("push_outlives({:?}: {:?})", sup, sub);
 
-        self.delegate.push_outlives(sup, sub);
+        self.delegate.push_outlives(sup, sub, info);
     }
 
     /// Relate a projection type and some value type lazily. This will always
@@ -490,6 +509,7 @@ where
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
+        info: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
@@ -497,6 +517,7 @@ where
 
         let old_ambient_variance = self.ambient_variance;
         self.ambient_variance = self.ambient_variance.xform(variance);
+        self.ambient_variance_info = self.ambient_variance_info.clone().xform(info);
 
         debug!("relate_with_variance: ambient_variance = {:?}", self.ambient_variance);
 
@@ -574,12 +595,12 @@ where
 
         if self.ambient_covariance() {
             // Covariance: a <= b. Hence, `b: a`.
-            self.push_outlives(v_b, v_a);
+            self.push_outlives(v_b, v_a, self.ambient_variance_info.clone());
         }
 
         if self.ambient_contravariance() {
             // Contravariant: b <= a. Hence, `a: b`.
-            self.push_outlives(v_a, v_b);
+            self.push_outlives(v_a, v_b, self.ambient_variance_info.clone());
         }
 
         Ok(a)
@@ -835,6 +856,7 @@ where
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
+        _info: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs
index bf5f328233d..b3131936ae0 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/sub.rs
@@ -62,6 +62,7 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
+        _info: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs
index 6b452bca8e7..ee358c52c2f 100644
--- a/compiler/rustc_infer/src/lib.rs
+++ b/compiler/rustc_infer/src/lib.rs
@@ -16,14 +16,12 @@
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(const_panic)]
 #![feature(extend_one)]
 #![feature(iter_zip)]
 #![feature(never_type)]
 #![feature(in_band_lifetimes)]
 #![feature(control_flow_enum)]
 #![feature(min_specialization)]
-#![feature(trusted_step)]
 #![recursion_limit = "512"] // For rustdoc
 
 #[macro_use]
diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs
index f2b69da3f86..b5af2bfca35 100644
--- a/compiler/rustc_interface/src/lib.rs
+++ b/compiler/rustc_interface/src/lib.rs
@@ -1,6 +1,5 @@
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
-#![feature(box_syntax)]
 #![feature(internal_output_capture)]
 #![feature(nll)]
 #![feature(generator_trait)]
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index dd4caab28dc..cfe65c5372d 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -12,7 +12,7 @@ use rustc_data_structures::temp_dir::MaybeTempDir;
 use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel};
 use rustc_errors::{ErrorReported, PResult};
 use rustc_expand::base::ExtCtxt;
-use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE};
+use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_hir::Crate;
 use rustc_lint::LintStore;
 use rustc_metadata::creader::CStore;
@@ -170,13 +170,9 @@ pub fn register_plugins<'a>(
     let crate_types = util::collect_crate_types(sess, &krate.attrs);
     sess.init_crate_types(crate_types);
 
-    let stable_crate_id = StableCrateId::new(
-        crate_name,
-        sess.crate_types().contains(&CrateType::Executable),
-        sess.opts.cg.metadata.clone(),
-    );
-    sess.stable_crate_id.set(stable_crate_id).expect("not yet initialized");
-    rustc_incremental::prepare_session_directory(sess, &crate_name, stable_crate_id)?;
+    let disambiguator = util::compute_crate_disambiguator(sess);
+    sess.crate_disambiguator.set(disambiguator).expect("not yet initialized");
+    rustc_incremental::prepare_session_directory(sess, &crate_name, disambiguator)?;
 
     if sess.opts.incremental.is_some() {
         sess.time("incr_comp_garbage_collect_session_directories", || {
@@ -769,9 +765,7 @@ pub fn create_global_ctxt<'tcx>(
 ) -> QueryContext<'tcx> {
     let sess = &compiler.session();
 
-    let def_path_table = resolver_outputs.definitions.def_path_table();
-    let query_result_on_disk_cache =
-        rustc_incremental::load_query_result_cache(sess, def_path_table);
+    let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess);
 
     let codegen_backend = compiler.codegen_backend();
     let mut local_providers = *DEFAULT_QUERY_PROVIDERS;
@@ -799,7 +793,7 @@ pub fn create_global_ctxt<'tcx>(
                 query_result_on_disk_cache,
                 queries.as_dyn(),
                 &crate_name,
-                &outputs,
+                outputs,
             )
         })
     });
@@ -985,7 +979,7 @@ fn encode_and_write_metadata(
             .tempdir_in(out_filename.parent().unwrap())
             .unwrap_or_else(|err| tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err)));
         let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps);
-        let metadata_filename = emit_metadata(tcx.sess, &metadata, &metadata_tmpdir);
+        let metadata_filename = emit_metadata(tcx.sess, &metadata.raw_data, &metadata_tmpdir);
         if let Err(e) = util::non_durable_rename(&metadata_filename, &out_filename) {
             tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
         }
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 969b526235b..2320f0b47d2 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -245,8 +245,7 @@ impl<'tcx> Queries<'tcx> {
         self.prepare_outputs.compute(|| {
             let expansion_result = self.expansion()?;
             let (krate, boxed_resolver, _) = &*expansion_result.peek();
-            let crate_name = self.crate_name()?;
-            let crate_name = crate_name.peek();
+            let crate_name = self.crate_name()?.peek();
             passes::prepare_outputs(
                 self.session(),
                 self.compiler,
@@ -343,32 +342,36 @@ impl<'tcx> Queries<'tcx> {
     }
 
     pub fn linker(&'tcx self) -> Result<Linker> {
-        let dep_graph = self.dep_graph()?;
-        let prepare_outputs = self.prepare_outputs()?;
-        let crate_hash = self.global_ctxt()?.peek_mut().enter(|tcx| tcx.crate_hash(LOCAL_CRATE));
-        let ongoing_codegen = self.ongoing_codegen()?;
-
         let sess = self.session().clone();
         let codegen_backend = self.codegen_backend().clone();
 
+        let dep_graph = self.dep_graph()?.peek().clone();
+        let prepare_outputs = self.prepare_outputs()?.take();
+        let crate_hash = self.global_ctxt()?.peek_mut().enter(|tcx| tcx.crate_hash(LOCAL_CRATE));
+        let ongoing_codegen = self.ongoing_codegen()?.take();
+
         Ok(Linker {
             sess,
-            dep_graph: dep_graph.peek().clone(),
-            prepare_outputs: prepare_outputs.take(),
-            crate_hash,
-            ongoing_codegen: ongoing_codegen.take(),
             codegen_backend,
+
+            dep_graph,
+            prepare_outputs,
+            crate_hash,
+            ongoing_codegen,
         })
     }
 }
 
 pub struct Linker {
+    // compilation inputs
     sess: Lrc<Session>,
+    codegen_backend: Lrc<Box<dyn CodegenBackend>>,
+
+    // compilation outputs
     dep_graph: DepGraph,
     prepare_outputs: OutputFilenames,
     crate_hash: Svh,
     ongoing_codegen: Box<dyn Any>,
-    codegen_backend: Lrc<Box<dyn CodegenBackend>>,
 }
 
 impl Linker {
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 15cda299208..6485fbebd66 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -2,9 +2,11 @@ use rustc_ast::mut_visit::{visit_clobber, MutVisitor, *};
 use rustc_ast::ptr::P;
 use rustc_ast::{self as ast, AttrVec, BlockCheckMode};
 use rustc_codegen_ssa::traits::CodegenBackend;
+use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 #[cfg(parallel_compiler)]
 use rustc_data_structures::jobserver;
+use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::registry::Registry;
 use rustc_metadata::dynamic_lib::DynamicLibrary;
@@ -16,6 +18,7 @@ use rustc_session::config::{self, CrateType};
 use rustc_session::config::{ErrorOutputType, Input, OutputFilenames};
 use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::parse::CrateConfig;
+use rustc_session::CrateDisambiguator;
 use rustc_session::{early_error, filesearch, output, DiagnosticOutput, Session};
 use rustc_span::edition::Edition;
 use rustc_span::lev_distance::find_best_match_for_name;
@@ -32,7 +35,7 @@ use std::ops::DerefMut;
 use std::panic;
 use std::path::{Path, PathBuf};
 use std::sync::atomic::{AtomicBool, Ordering};
-use std::sync::{Arc, Mutex, Once};
+use std::sync::{Arc, Mutex};
 use std::thread;
 use tracing::info;
 
@@ -73,7 +76,10 @@ pub fn create_session(
     let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend {
         make_codegen_backend(&sopts)
     } else {
-        get_codegen_backend(&sopts)
+        get_codegen_backend(
+            &sopts.maybe_sysroot,
+            sopts.debugging_opts.codegen_backend.as_ref().map(|name| &name[..]),
+        )
     };
 
     // target_override is documented to be called before init(), so this is okay
@@ -241,35 +247,34 @@ fn load_backend_from_dylib(path: &Path) -> fn() -> Box<dyn CodegenBackend> {
     }
 }
 
-pub fn get_codegen_backend(sopts: &config::Options) -> Box<dyn CodegenBackend> {
-    static INIT: Once = Once::new();
-
-    static mut LOAD: fn() -> Box<dyn CodegenBackend> = || unreachable!();
+/// Get the codegen backend based on the name and specified sysroot.
+///
+/// A name of `None` indicates that the default backend should be used.
+pub fn get_codegen_backend(
+    maybe_sysroot: &Option<PathBuf>,
+    backend_name: Option<&str>,
+) -> Box<dyn CodegenBackend> {
+    static LOAD: SyncOnceCell<unsafe fn() -> Box<dyn CodegenBackend>> = SyncOnceCell::new();
 
-    INIT.call_once(|| {
+    let load = LOAD.get_or_init(|| {
         #[cfg(feature = "llvm")]
         const DEFAULT_CODEGEN_BACKEND: &str = "llvm";
 
         #[cfg(not(feature = "llvm"))]
         const DEFAULT_CODEGEN_BACKEND: &str = "cranelift";
 
-        let codegen_name = sopts
-            .debugging_opts
-            .codegen_backend
-            .as_ref()
-            .map(|name| &name[..])
-            .unwrap_or(DEFAULT_CODEGEN_BACKEND);
-
-        let backend = match codegen_name {
+        match backend_name.unwrap_or(DEFAULT_CODEGEN_BACKEND) {
             filename if filename.contains('.') => load_backend_from_dylib(filename.as_ref()),
-            codegen_name => get_builtin_codegen_backend(&sopts.maybe_sysroot, codegen_name),
-        };
-
-        unsafe {
-            LOAD = backend;
+            #[cfg(feature = "llvm")]
+            "llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new,
+            backend_name => get_codegen_sysroot(maybe_sysroot, backend_name),
         }
     });
-    unsafe { LOAD() }
+
+    // SAFETY: In case of a builtin codegen backend this is safe. In case of an external codegen
+    // backend we hope that the backend links against the same rustc_driver version. If this is not
+    // the case, we get UB.
+    unsafe { load() }
 }
 
 // This is used for rustdoc, but it uses similar machinery to codegen backend
@@ -387,17 +392,6 @@ fn sysroot_candidates() -> Vec<PathBuf> {
     }
 }
 
-pub fn get_builtin_codegen_backend(
-    maybe_sysroot: &Option<PathBuf>,
-    backend_name: &str,
-) -> fn() -> Box<dyn CodegenBackend> {
-    match backend_name {
-        #[cfg(feature = "llvm")]
-        "llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new,
-        _ => get_codegen_sysroot(maybe_sysroot, backend_name),
-    }
-}
-
 pub fn get_codegen_sysroot(
     maybe_sysroot: &Option<PathBuf>,
     backend_name: &str,
@@ -493,6 +487,39 @@ pub fn get_codegen_sysroot(
     }
 }
 
+pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguator {
+    use std::hash::Hasher;
+
+    // The crate_disambiguator is a 128 bit hash. The disambiguator is fed
+    // into various other hashes quite a bit (symbol hashes, incr. comp. hashes,
+    // debuginfo type IDs, etc), so we don't want it to be too wide. 128 bits
+    // should still be safe enough to avoid collisions in practice.
+    let mut hasher = StableHasher::new();
+
+    let mut metadata = session.opts.cg.metadata.clone();
+    // We don't want the crate_disambiguator to dependent on the order
+    // -C metadata arguments, so sort them:
+    metadata.sort();
+    // Every distinct -C metadata value is only incorporated once:
+    metadata.dedup();
+
+    hasher.write(b"metadata");
+    for s in &metadata {
+        // Also incorporate the length of a metadata string, so that we generate
+        // different values for `-Cmetadata=ab -Cmetadata=c` and
+        // `-Cmetadata=a -Cmetadata=bc`
+        hasher.write_usize(s.len());
+        hasher.write(s.as_bytes());
+    }
+
+    // Also incorporate crate type, so that we don't get symbol conflicts when
+    // linking against a library of the same name, if this is an executable.
+    let is_exe = session.crate_types().contains(&CrateType::Executable);
+    hasher.write(if is_exe { b"exe" } else { b"lib" });
+
+    CrateDisambiguator::from(hasher.finish::<Fingerprint>())
+}
+
 pub(crate) fn check_attr_crate_type(
     sess: &Session,
     attrs: &[ast::Attribute],
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index e7275374b89..f6a84966f7a 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -489,7 +489,7 @@ fn has_doc(sess: &Session, attr: &ast::Attribute) -> bool {
 
     if let Some(list) = attr.meta_item_list() {
         for meta in list {
-            if meta.has_name(sym::include) || meta.has_name(sym::hidden) {
+            if meta.has_name(sym::hidden) {
                 return true;
             }
         }
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index c1d6a4f1de1..a8df1b0952c 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -334,8 +334,14 @@ impl LintStore {
         }
     }
 
-    /// Checks the validity of lint names derived from the command line
-    pub fn check_lint_name_cmdline(&self, sess: &Session, lint_name: &str, level: Level) {
+    /// Checks the validity of lint names derived from the command line. Returns
+    /// true if the lint is valid, false otherwise.
+    pub fn check_lint_name_cmdline(
+        &self,
+        sess: &Session,
+        lint_name: &str,
+        level: Option<Level>,
+    ) -> bool {
         let db = match self.check_lint_name(lint_name, None) {
             CheckLintNameResult::Ok(_) => None,
             CheckLintNameResult::Warning(ref msg, _) => Some(sess.struct_warn(msg)),
@@ -361,18 +367,23 @@ impl LintStore {
         };
 
         if let Some(mut db) = db {
-            let msg = format!(
-                "requested on the command line with `{} {}`",
-                match level {
-                    Level::Allow => "-A",
-                    Level::Warn => "-W",
-                    Level::Deny => "-D",
-                    Level::Forbid => "-F",
-                },
-                lint_name
-            );
-            db.note(&msg);
+            if let Some(level) = level {
+                let msg = format!(
+                    "requested on the command line with `{} {}`",
+                    match level {
+                        Level::Allow => "-A",
+                        Level::Warn => "-W",
+                        Level::Deny => "-D",
+                        Level::Forbid => "-F",
+                    },
+                    lint_name
+                );
+                db.note(&msg);
+            }
             db.emit();
+            false
+        } else {
+            true
         }
     }
 
@@ -922,7 +933,7 @@ impl<'tcx> LateContext<'tcx> {
             }
 
             fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
-                Ok(vec![self.tcx.original_crate_name(cnum)])
+                Ok(vec![self.tcx.crate_name(cnum)])
             }
 
             fn path_qualified(
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 91cdef9b089..0ee434f5fb5 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -88,7 +88,7 @@ impl<'s> LintLevelsBuilder<'s> {
         self.sets.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid);
 
         for &(ref lint_name, level) in &sess.opts.lint_opts {
-            store.check_lint_name_cmdline(sess, &lint_name, level);
+            store.check_lint_name_cmdline(sess, &lint_name, Some(level));
             let orig_level = level;
 
             // If the cap is less than this specified level, e.g., if we've got
@@ -109,6 +109,16 @@ impl<'s> LintLevelsBuilder<'s> {
             }
         }
 
+        for lint_name in &sess.opts.force_warns {
+            let valid = store.check_lint_name_cmdline(sess, lint_name, None);
+            if valid {
+                let lints = store
+                    .find_lints(lint_name)
+                    .unwrap_or_else(|_| bug!("A valid lint failed to produce a lint ids"));
+                self.sets.force_warns.extend(&lints);
+            }
+        }
+
         self.sets.list.push(LintSet::CommandLine { specs });
     }
 
@@ -142,6 +152,9 @@ impl<'s> LintLevelsBuilder<'s> {
                     LintLevelSource::Default => false,
                     LintLevelSource::Node(symbol, _, _) => self.store.is_lint_group(symbol),
                     LintLevelSource::CommandLine(symbol, _) => self.store.is_lint_group(symbol),
+                    LintLevelSource::ForceWarn(_symbol) => {
+                        bug!("forced warn lint returned a forbid lint level")
+                    }
                 };
                 debug!(
                     "fcw_warning={:?}, specs.get(&id) = {:?}, old_src={:?}, id_name={:?}",
@@ -166,6 +179,7 @@ impl<'s> LintLevelsBuilder<'s> {
                         LintLevelSource::CommandLine(_, _) => {
                             diag_builder.note("`forbid` lint level was set on command line");
                         }
+                        _ => bug!("forced warn lint returned a forbid lint level"),
                     }
                     diag_builder.emit();
                 };
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 45ed6872f18..4f59460aa82 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -36,8 +36,6 @@
 #![feature(iter_zip)]
 #![feature(never_type)]
 #![feature(nll)]
-#![feature(half_open_range_patterns)]
-#![feature(exclusive_range_pattern)]
 #![feature(control_flow_enum)]
 #![recursion_limit = "256"]
 
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 9c94bab04e9..a3a87a48768 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -5,7 +5,6 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::{is_range_literal, ExprKind, Node};
-use rustc_index::vec::Idx;
 use rustc_middle::ty::layout::{IntegerExt, SizeSkeleton};
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable};
@@ -13,7 +12,7 @@ use rustc_span::source_map;
 use rustc_span::symbol::sym;
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::Abi;
-use rustc_target::abi::{Integer, LayoutOf, TagEncoding, VariantIdx, Variants};
+use rustc_target::abi::{Integer, LayoutOf, TagEncoding, Variants};
 use rustc_target::spec::abi::Abi as SpecAbi;
 
 use std::cmp;
@@ -680,16 +679,11 @@ pub fn transparent_newtype_field<'a, 'tcx>(
     variant: &'a ty::VariantDef,
 ) -> Option<&'a ty::FieldDef> {
     let param_env = tcx.param_env(variant.def_id);
-    for field in &variant.fields {
+    variant.fields.iter().find(|field| {
         let field_ty = tcx.type_of(field.did);
         let is_zst = tcx.layout_of(param_env.and(field_ty)).map_or(false, |layout| layout.is_zst());
-
-        if !is_zst {
-            return Some(field);
-        }
-    }
-
-    None
+        !is_zst
+    })
 }
 
 /// Is type known to be non-null?
@@ -712,15 +706,10 @@ fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKi
                 return false;
             }
 
-            for variant in &def.variants {
-                if let Some(field) = transparent_newtype_field(cx.tcx, variant) {
-                    if ty_is_known_nonnull(cx, field.ty(tcx, substs), mode) {
-                        return true;
-                    }
-                }
-            }
-
-            false
+            def.variants
+                .iter()
+                .filter_map(|variant| transparent_newtype_field(cx.tcx, variant))
+                .any(|field| ty_is_known_nonnull(cx, field.ty(tcx, substs), mode))
         }
         _ => false,
     }
@@ -783,25 +772,14 @@ crate fn repr_nullable_ptr<'tcx>(
 ) -> Option<Ty<'tcx>> {
     debug!("is_repr_nullable_ptr(cx, ty = {:?})", ty);
     if let ty::Adt(ty_def, substs) = ty.kind() {
-        if ty_def.variants.len() != 2 {
-            return None;
-        }
-
-        let get_variant_fields = |index| &ty_def.variants[VariantIdx::new(index)].fields;
-        let variant_fields = [get_variant_fields(0), get_variant_fields(1)];
-        let fields = if variant_fields[0].is_empty() {
-            &variant_fields[1]
-        } else if variant_fields[1].is_empty() {
-            &variant_fields[0]
-        } else {
-            return None;
+        let field_ty = match &ty_def.variants.raw[..] {
+            [var_one, var_two] => match (&var_one.fields[..], &var_two.fields[..]) {
+                ([], [field]) | ([field], []) => field.ty(cx.tcx, substs),
+                _ => return None,
+            },
+            _ => return None,
         };
 
-        if fields.len() != 1 {
-            return None;
-        }
-
-        let field_ty = fields[0].ty(cx.tcx, substs);
         if !ty_is_known_nonnull(cx, field_ty, ckind) {
             return None;
         }
@@ -921,11 +899,18 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         }
 
         match *ty.kind() {
-            ty::Adt(def, _) if def.is_box() && matches!(self.mode, CItemKind::Definition) => {
-                FfiSafe
-            }
-
             ty::Adt(def, substs) => {
+                if def.is_box() && matches!(self.mode, CItemKind::Definition) {
+                    if ty.boxed_ty().is_sized(tcx.at(DUMMY_SP), self.cx.param_env) {
+                        return FfiSafe;
+                    } else {
+                        return FfiUnsafe {
+                            ty,
+                            reason: format!("box cannot be represented as a single pointer"),
+                            help: None,
+                        };
+                    }
+                }
                 if def.is_phantom_data() {
                     return FfiPhantom(ty);
                 }
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 15246971bae..352146d6463 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -2994,6 +2994,7 @@ declare_lint_pass! {
         USELESS_DEPRECATED,
         UNSUPPORTED_NAKED_FUNCTIONS,
         MISSING_ABI,
+        INVALID_DOC_ATTRIBUTES,
         SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
         DISJOINT_CAPTURE_MIGRATION,
         LEGACY_DERIVE_HELPERS,
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 70475563a4a..f1c4e5fb4a3 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -25,7 +25,11 @@ macro_rules! pluralize {
 /// before applying the suggestion.
 #[derive(Copy, Clone, Debug, PartialEq, Hash, Encodable, Decodable)]
 pub enum Applicability {
-    /// The suggestion is definitely what the user intended. This suggestion should be
+    /// The suggestion is definitely what the user intended, or maintains the exact meaning of the code.
+    /// This suggestion should be automatically applied.
+    ///
+    /// In case of multiple `MachineApplicable` suggestions (whether as part of
+    /// the same `multipart_suggestion` or not), all of them should be
     /// automatically applied.
     MachineApplicable,
 
diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs
index 301ed639f3b..452d1b19a18 100644
--- a/compiler/rustc_llvm/build.rs
+++ b/compiler/rustc_llvm/build.rs
@@ -86,6 +86,7 @@ fn main() {
         "nvptx",
         "hexagon",
         "riscv",
+        "bpf",
     ];
 
     let required_components = &[
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 2e135fbe2bd..9b757eb40c1 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -6,6 +6,7 @@
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/Object/Archive.h"
+#include "llvm/Object/COFFImportFile.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Bitcode/BitcodeWriterPass.h"
 #include "llvm/Support/Signals.h"
@@ -70,17 +71,6 @@ extern "C" void LLVMRustInstallFatalErrorHandler() {
   install_fatal_error_handler(FatalErrorHandler);
 }
 
-extern "C" LLVMMemoryBufferRef
-LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) {
-  ErrorOr<std::unique_ptr<MemoryBuffer>> BufOr =
-      MemoryBuffer::getFile(Path, -1, false);
-  if (!BufOr) {
-    LLVMRustSetLastError(BufOr.getError().message().c_str());
-    return nullptr;
-  }
-  return wrap(BufOr.get().release());
-}
-
 extern "C" char *LLVMRustGetLastError(void) {
   char *Ret = LastError;
   LastError = nullptr;
@@ -1077,30 +1067,6 @@ extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
   }
 }
 
-// Note that the two following functions look quite similar to the
-// LLVMGetSectionName function. Sadly, it appears that this function only
-// returns a char* pointer, which isn't guaranteed to be null-terminated. The
-// function provided by LLVM doesn't return the length, so we've created our own
-// function which returns the length as well as the data pointer.
-//
-// For an example of this not returning a null terminated string, see
-// lib/Object/COFFObjectFile.cpp in the getSectionName function. One of the
-// branches explicitly creates a StringRef without a null terminator, and then
-// that's returned.
-
-inline section_iterator *unwrap(LLVMSectionIteratorRef SI) {
-  return reinterpret_cast<section_iterator *>(SI);
-}
-
-extern "C" size_t LLVMRustGetSectionName(LLVMSectionIteratorRef SI,
-                                         const char **Ptr) {
-  auto NameOrErr = (*unwrap(SI))->getName();
-  if (!NameOrErr)
-    report_fatal_error(NameOrErr.takeError());
-  *Ptr = NameOrErr->data();
-  return NameOrErr->size();
-}
-
 // LLVMArrayType function does not support 64-bit ElementCount
 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
                                          uint64_t ElementCount) {
@@ -1757,3 +1723,54 @@ extern "C" LLVMValueRef
 LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
     return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
 }
+
+// This struct contains all necessary info about a symbol exported from a DLL.
+// At the moment, it's just the symbol's name, but we use a separate struct to
+// make it easier to add other information like ordinal later.
+struct LLVMRustCOFFShortExport {
+  const char* name;
+};
+
+// Machine must be a COFF machine type, as defined in PE specs.
+extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
+  const char* ImportName,
+  const char* Path,
+  const LLVMRustCOFFShortExport* Exports,
+  size_t NumExports,
+  uint16_t Machine,
+  bool MinGW)
+{
+  std::vector<llvm::object::COFFShortExport> ConvertedExports;
+  ConvertedExports.reserve(NumExports);
+
+  for (size_t i = 0; i < NumExports; ++i) {
+    ConvertedExports.push_back(llvm::object::COFFShortExport{
+      Exports[i].name,  // Name
+      std::string{},    // ExtName
+      std::string{},    // SymbolName
+      std::string{},    // AliasTarget
+      0,                // Ordinal
+      false,            // Noname
+      false,            // Data
+      false,            // Private
+      false             // Constant
+    });
+  }
+
+  auto Error = llvm::object::writeImportLibrary(
+    ImportName,
+    Path,
+    ConvertedExports,
+    static_cast<llvm::COFF::MachineTypes>(Machine),
+    MinGW);
+  if (Error) {
+    std::string errorString;
+    llvm::raw_string_ostream stream(errorString);
+    stream << Error;
+    stream.flush();
+    LLVMRustSetLastError(errorString.c_str());
+    return LLVMRustResult::Failure;
+  } else {
+    return LLVMRustResult::Success;
+  }
+}
diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs
index 555aefb1929..122627eb500 100644
--- a/compiler/rustc_llvm/src/lib.rs
+++ b/compiler/rustc_llvm/src/lib.rs
@@ -167,4 +167,12 @@ pub fn initialize_available_targets() {
         LLVMInitializeWebAssemblyAsmPrinter,
         LLVMInitializeWebAssemblyAsmParser
     );
+    init_target!(
+        llvm_component = "bpf",
+        LLVMInitializeBPFTargetInfo,
+        LLVMInitializeBPFTarget,
+        LLVMInitializeBPFTargetMC,
+        LLVMInitializeBPFAsmPrinter,
+        LLVMInitializeBPFAsmParser
+    );
 }
diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs
index 72bd4804e98..7bc669f2b00 100644
--- a/compiler/rustc_macros/src/serialize.rs
+++ b/compiler/rustc_macros/src/serialize.rs
@@ -43,12 +43,9 @@ fn decodable_body(
     let decode_body = match s.variants() {
         [vi] => {
             let construct = vi.construct(|field, index| decode_field(field, index, true));
-            let n_fields = vi.ast().fields.len();
             quote! {
                 ::rustc_serialize::Decoder::read_struct(
                     __decoder,
-                    #ty_name,
-                    #n_fields,
                     |__decoder| { ::std::result::Result::Ok(#construct) },
                 )
             }
@@ -77,7 +74,6 @@ fn decodable_body(
             quote! {
                 ::rustc_serialize::Decoder::read_enum(
                     __decoder,
-                    #ty_name,
                     |__decoder| {
                         ::rustc_serialize::Decoder::read_enum_variant(
                             __decoder,
@@ -128,7 +124,7 @@ fn decode_field(field: &syn::Field, index: usize, is_struct: bool) -> proc_macro
 
     quote! {
         match ::rustc_serialize::Decoder::#decode_method(
-            __decoder, #opt_field_name #index, #decode_inner_method) {
+            __decoder, #opt_field_name #decode_inner_method) {
             ::std::result::Result::Ok(__res) => __res,
             ::std::result::Result::Err(__err) => return ::std::result::Result::Err(__err),
         }
@@ -183,7 +179,6 @@ fn encodable_body(
         }
     });
 
-    let ty_name = s.ast().ident.to_string();
     let encode_body = match s.variants() {
         [_] => {
             let mut field_idx = 0usize;
@@ -197,11 +192,12 @@ fn encodable_body(
                             .ident
                             .as_ref()
                             .map_or_else(|| field_idx.to_string(), |i| i.to_string());
+                        let first = field_idx == 0;
                         let result = quote! {
                             match ::rustc_serialize::Encoder::emit_struct_field(
                                 __encoder,
                                 #field_name,
-                                #field_idx,
+                                #first,
                                 |__encoder|
                                 ::rustc_serialize::Encodable::<#encoder_ty>::encode(#bind_ident, __encoder),
                             ) {
@@ -215,8 +211,9 @@ fn encodable_body(
                     })
                     .collect::<TokenStream>()
             });
+            let no_fields = field_idx == 0;
             quote! {
-                ::rustc_serialize::Encoder::emit_struct(__encoder, #ty_name, #field_idx, |__encoder| {
+                ::rustc_serialize::Encoder::emit_struct(__encoder, #no_fields, |__encoder| {
                     ::std::result::Result::Ok(match *self { #encode_inner })
                 })
             }
@@ -232,10 +229,11 @@ fn encodable_body(
                     .iter()
                     .map(|binding| {
                         let bind_ident = &binding.binding;
+                        let first = field_idx == 0;
                         let result = quote! {
                             match ::rustc_serialize::Encoder::emit_enum_variant_arg(
                                 __encoder,
-                                #field_idx,
+                                #first,
                                 |__encoder|
                                 ::rustc_serialize::Encodable::<#encoder_ty>::encode(#bind_ident, __encoder),
                             ) {
@@ -260,7 +258,7 @@ fn encodable_body(
                 result
             });
             quote! {
-                ::rustc_serialize::Encoder::emit_enum(__encoder, #ty_name, |__encoder| {
+                ::rustc_serialize::Encoder::emit_enum(__encoder, |__encoder| {
                     match *self {
                         #encode_inner
                     }
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 42c32219aba..e9ae22f8ced 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -21,7 +21,7 @@ use rustc_session::config::{self, CrateType, ExternLocation};
 use rustc_session::lint::{self, BuiltinLintDiagnostics, ExternDepSpec};
 use rustc_session::output::validate_crate_name;
 use rustc_session::search_paths::PathKind;
-use rustc_session::Session;
+use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::edition::Edition;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -222,8 +222,10 @@ impl<'a> CrateLoader<'a> {
         metadata_loader: &'a MetadataLoaderDyn,
         local_crate_name: &str,
     ) -> Self {
+        let local_crate_stable_id =
+            StableCrateId::new(local_crate_name, sess.local_crate_disambiguator());
         let mut stable_crate_ids = FxHashMap::default();
-        stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE);
+        stable_crate_ids.insert(local_crate_stable_id, LOCAL_CRATE);
 
         CrateLoader {
             sess,
@@ -325,14 +327,17 @@ impl<'a> CrateLoader<'a> {
 
     fn verify_no_symbol_conflicts(&self, root: &CrateRoot<'_>) -> Result<(), CrateError> {
         // Check for (potential) conflicts with the local crate
-        if self.sess.local_stable_crate_id() == root.stable_crate_id() {
+        if self.local_crate_name == root.name()
+            && self.sess.local_crate_disambiguator() == root.disambiguator()
+        {
             return Err(CrateError::SymbolConflictsCurrent(root.name()));
         }
 
         // Check for conflicts with any crate loaded so far
         let mut res = Ok(());
         self.cstore.iter_crate_data(|_, other| {
-            if other.stable_crate_id() == root.stable_crate_id() && // same stable crate id
+            if other.name() == root.name() && // same crate-name
+               other.disambiguator() == root.disambiguator() && // same crate-disambiguator
                other.hash() != root.hash()
             {
                 // but different SVH
@@ -406,7 +411,7 @@ impl<'a> CrateLoader<'a> {
                 None => (&source, &crate_root),
             };
             let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate");
-            Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.stable_crate_id())?)
+            Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.disambiguator())?)
         } else {
             None
         };
@@ -659,7 +664,7 @@ impl<'a> CrateLoader<'a> {
     fn dlsym_proc_macros(
         &self,
         path: &Path,
-        stable_crate_id: StableCrateId,
+        disambiguator: CrateDisambiguator,
     ) -> Result<&'static [ProcMacro], CrateError> {
         // Make sure the path contains a / or the linker will search for it.
         let path = env::current_dir().unwrap().join(path);
@@ -668,7 +673,7 @@ impl<'a> CrateLoader<'a> {
             Err(s) => return Err(CrateError::DlOpen(s)),
         };
 
-        let sym = self.sess.generate_proc_macro_decls_symbol(stable_crate_id);
+        let sym = self.sess.generate_proc_macro_decls_symbol(disambiguator);
         let decls = unsafe {
             let sym = match lib.symbol(&sym) {
                 Ok(f) => f,
diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs
index c5bbb96f777..2c9bad7e5ce 100644
--- a/compiler/rustc_metadata/src/lib.rs
+++ b/compiler/rustc_metadata/src/lib.rs
@@ -1,5 +1,4 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![feature(core_intrinsics)]
 #![feature(crate_visibility_modifier)]
 #![feature(drain_filter)]
 #![feature(in_band_lifetimes)]
@@ -7,7 +6,6 @@
 #![feature(once_cell)]
 #![feature(proc_macro_internals)]
 #![feature(min_specialization)]
-#![feature(stmt_expr_attributes)]
 #![feature(try_blocks)]
 #![feature(never_type)]
 #![recursion_limit = "256"]
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index b830c6b2481..6e736095090 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -226,7 +226,7 @@ use rustc_session::config::{self, CrateType};
 use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch};
 use rustc_session::search_paths::PathKind;
 use rustc_session::utils::CanonicalizedPath;
-use rustc_session::{Session, StableCrateId};
+use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use rustc_target::spec::{Target, TargetTriple};
@@ -787,7 +787,7 @@ pub fn find_plugin_registrar(
     metadata_loader: &dyn MetadataLoader,
     span: Span,
     name: Symbol,
-) -> (PathBuf, StableCrateId) {
+) -> (PathBuf, CrateDisambiguator) {
     match find_plugin_registrar_impl(sess, metadata_loader, name) {
         Ok(res) => res,
         // `core` is always available if we got as far as loading plugins.
@@ -799,7 +799,7 @@ fn find_plugin_registrar_impl<'a>(
     sess: &'a Session,
     metadata_loader: &dyn MetadataLoader,
     name: Symbol,
-) -> Result<(PathBuf, StableCrateId), CrateError> {
+) -> Result<(PathBuf, CrateDisambiguator), CrateError> {
     info!("find plugin registrar `{}`", name);
     let mut locator = CrateLocator::new(
         sess,
@@ -816,7 +816,7 @@ fn find_plugin_registrar_impl<'a>(
 
     match locator.maybe_load_library_crate()? {
         Some(library) => match library.source.dylib {
-            Some(dylib) => Ok((dylib.0, library.metadata.get_root().stable_crate_id())),
+            Some(dylib) => Ok((dylib.0, library.metadata.get_root().disambiguator())),
             None => Err(CrateError::NonDylibPlugin(name)),
         },
         None => Err(locator.into_error()),
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index bc342119efb..cd4c394ae14 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -3,7 +3,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_middle::middle::cstore::NativeLib;
+use rustc_middle::middle::cstore::{DllImport, NativeLib};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::parse::feature_err;
 use rustc_session::utils::NativeLibKind;
@@ -33,8 +33,8 @@ struct Collector<'tcx> {
 
 impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
     fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
-        let abi = match it.kind {
-            hir::ItemKind::ForeignMod { abi, .. } => abi,
+        let (abi, foreign_mod_items) = match it.kind {
+            hir::ItemKind::ForeignMod { abi, items } => (abi, items),
             _ => return,
         };
 
@@ -57,6 +57,7 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
                 foreign_module: Some(it.def_id.to_def_id()),
                 wasm_import_module: None,
                 verbatim: None,
+                dll_imports: Vec::new(),
             };
             let mut kind_specified = false;
 
@@ -196,6 +197,27 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> {
                 .span_label(m.span, "missing `name` argument")
                 .emit();
             }
+
+            if lib.kind == NativeLibKind::RawDylib {
+                match abi {
+                    Abi::C { .. } => (),
+                    Abi::Cdecl => (),
+                    _ => {
+                        if sess.target.arch == "x86" {
+                            sess.span_fatal(
+                                it.span,
+                                r#"`#[link(kind = "raw-dylib")]` only supports C and Cdecl ABIs"#,
+                            );
+                        }
+                    }
+                };
+                lib.dll_imports.extend(
+                    foreign_mod_items
+                        .iter()
+                        .map(|child_item| DllImport { name: child_item.ident.name, ordinal: None }),
+                );
+            }
+
             self.register_native_lib(Some(m.span), lib);
         }
     }
@@ -253,15 +275,42 @@ impl Collector<'tcx> {
             )
             .emit();
         }
-        if lib.kind == NativeLibKind::RawDylib && !self.tcx.features().raw_dylib {
-            feature_err(
-                &self.tcx.sess.parse_sess,
-                sym::raw_dylib,
-                span.unwrap_or(rustc_span::DUMMY_SP),
-                "kind=\"raw-dylib\" is unstable",
-            )
-            .emit();
+        // this just unwraps lib.name; we already established that it isn't empty above.
+        if let (NativeLibKind::RawDylib, Some(lib_name)) = (lib.kind, lib.name) {
+            let span = match span {
+                Some(s) => s,
+                None => {
+                    bug!("raw-dylib libraries are not supported on the command line");
+                }
+            };
+
+            if !self.tcx.sess.target.options.is_like_windows {
+                self.tcx.sess.span_fatal(
+                    span,
+                    "`#[link(...)]` with `kind = \"raw-dylib\"` only supported on Windows",
+                );
+            } else if !self.tcx.sess.target.options.is_like_msvc {
+                self.tcx.sess.span_warn(
+                    span,
+                    "`#[link(...)]` with `kind = \"raw-dylib\"` not supported on windows-gnu",
+                );
+            }
+
+            if lib_name.as_str().contains('\0') {
+                self.tcx.sess.span_err(span, "library name may not contain NUL characters");
+            }
+
+            if !self.tcx.features().raw_dylib {
+                feature_err(
+                    &self.tcx.sess.parse_sess,
+                    sym::raw_dylib,
+                    span,
+                    "kind=\"raw-dylib\" is unstable",
+                )
+                .emit();
+            }
         }
+
         self.libs.push(lib);
     }
 
@@ -337,6 +386,7 @@ impl Collector<'tcx> {
                     foreign_module: None,
                     wasm_import_module: None,
                     verbatim: passed_lib.verbatim,
+                    dll_imports: Vec::new(),
                 };
                 self.register_native_lib(None, lib);
             } else {
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index cc269fad46f..52cb1e1996e 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -300,7 +300,7 @@ impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> {
     {
         let tcx = self.tcx();
 
-        let key = ty::CReaderCacheKey { cnum: self.cdata().cnum, pos: shorthand };
+        let key = ty::CReaderCacheKey { cnum: Some(self.cdata().cnum), pos: shorthand };
 
         if let Some(&ty) = tcx.ty_rcache.borrow().get(&key) {
             return Ok(ty);
@@ -620,6 +620,10 @@ impl CrateRoot<'_> {
         self.name
     }
 
+    crate fn disambiguator(&self) -> CrateDisambiguator {
+        self.disambiguator
+    }
+
     crate fn hash(&self) -> Svh {
         self.hash
     }
@@ -1923,14 +1927,18 @@ impl CrateMetadata {
         self.root.name
     }
 
-    crate fn stable_crate_id(&self) -> StableCrateId {
-        self.root.stable_crate_id
+    crate fn disambiguator(&self) -> CrateDisambiguator {
+        self.root.disambiguator
     }
 
     crate fn hash(&self) -> Svh {
         self.root.hash
     }
 
+    fn num_def_ids(&self) -> usize {
+        self.root.tables.def_keys.size()
+    }
+
     fn local_def_id(&self, index: DefIndex) -> DefId {
         DefId { krate: self.cnum, index }
     }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 818376b20de..9a97835d9c0 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -19,7 +19,7 @@ use rustc_middle::middle::stability::DeprecationEntry;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, Visibility};
 use rustc_session::utils::NativeLibKind;
-use rustc_session::{Session, StableCrateId};
+use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::source_map::{Span, Spanned};
 use rustc_span::symbol::Symbol;
 
@@ -155,6 +155,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) }
 
     dylib_dependency_formats => { cdata.get_dylib_dependency_formats(tcx) }
+    is_private_dep => { cdata.private_dep }
     is_panic_runtime => { cdata.root.panic_runtime }
     is_compiler_builtins => { cdata.root.compiler_builtins }
     has_global_allocator => { cdata.root.has_global_allocator }
@@ -185,9 +186,10 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     }
     native_libraries => { Lrc::new(cdata.get_native_libraries(tcx.sess)) }
     foreign_modules => { cdata.get_foreign_modules(tcx) }
+    crate_disambiguator => { cdata.root.disambiguator }
     crate_hash => { cdata.root.hash }
     crate_host_hash => { cdata.host_hash }
-    original_crate_name => { cdata.root.name }
+    crate_name => { cdata.root.name }
 
     extra_filename => { cdata.root.extra_filename.clone() }
 
@@ -204,7 +206,6 @@ provide! { <'tcx> tcx, def_id, other, cdata,
         let r = *cdata.dep_kind.lock();
         r
     }
-    crate_name => { cdata.root.name }
     item_children => {
         let mut result = SmallVec::<[_; 8]>::new();
         cdata.each_child_of_item(def_id.index, |child| result.push(child), tcx.sess);
@@ -250,6 +251,10 @@ pub fn provide(providers: &mut Providers) {
         is_statically_included_foreign_item: |tcx, id| {
             matches!(tcx.native_library_kind(id), Some(NativeLibKind::Static { .. }))
         },
+        is_private_dep: |_tcx, cnum| {
+            assert_eq!(cnum, LOCAL_CRATE);
+            false
+        },
         native_library_kind: |tcx, id| {
             tcx.native_libraries(id.krate)
                 .iter()
@@ -454,6 +459,13 @@ impl CStore {
         self.get_crate_data(def_id.krate).module_expansion(def_id.index, sess)
     }
 
+    /// Only public-facing way to traverse all the definitions in a non-local crate.
+    /// Critically useful for this third-party project: <https://github.com/hacspec/hacspec>.
+    /// See <https://github.com/rust-lang/rust/pull/85889> for context.
+    pub fn num_def_ids_untracked(&self, cnum: CrateNum) -> usize {
+        self.get_crate_data(cnum).num_def_ids()
+    }
+
     pub fn item_attrs(&self, def_id: DefId, sess: &Session) -> Vec<ast::Attribute> {
         self.get_crate_data(def_id.krate).get_item_attrs(def_id.index, sess).collect()
     }
@@ -477,12 +489,8 @@ impl CrateStore for CStore {
         self.get_crate_data(cnum).root.name
     }
 
-    fn crate_is_private_dep_untracked(&self, cnum: CrateNum) -> bool {
-        self.get_crate_data(cnum).private_dep
-    }
-
-    fn stable_crate_id_untracked(&self, cnum: CrateNum) -> StableCrateId {
-        self.get_crate_data(cnum).root.stable_crate_id
+    fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator {
+        self.get_crate_data(cnum).root.disambiguator
     }
 
     fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 5c45e4130d2..76007398000 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -671,6 +671,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
             triple: tcx.sess.opts.target_triple.clone(),
             hash: tcx.crate_hash(LOCAL_CRATE),
+            disambiguator: tcx.sess.local_crate_disambiguator(),
             stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
             panic_strategy: tcx.sess.panic_strategy(),
             edition: tcx.sess.edition(),
@@ -942,7 +943,7 @@ impl EncodeContext<'a, 'tcx> {
             });
             record!(self.tables.span[def_id] <- tcx.def_span(def_id));
             record!(self.tables.attributes[def_id] <- tcx.get_attrs(def_id));
-            record!(self.tables.expn_that_defined[def_id] <- self.tcx.expansion_that_defined(def_id));
+            record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id));
             if should_encode_visibility(def_kind) {
                 record!(self.tables.visibility[def_id] <- self.tcx.visibility(def_id));
             }
@@ -1673,7 +1674,7 @@ impl EncodeContext<'a, 'tcx> {
             .iter()
             .map(|&cnum| {
                 let dep = CrateDep {
-                    name: self.tcx.original_crate_name(cnum),
+                    name: self.tcx.crate_name(cnum),
                     hash: self.tcx.crate_hash(cnum),
                     host_hash: self.tcx.crate_host_hash(cnum),
                     kind: self.tcx.dep_kind(cnum),
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 37930580623..99ea0cc8f2f 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -18,6 +18,7 @@ use rustc_middle::mir;
 use rustc_middle::ty::{self, ReprOptions, Ty};
 use rustc_serialize::opaque::Encoder;
 use rustc_session::config::SymbolManglingVersion;
+use rustc_session::CrateDisambiguator;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{Ident, Symbol};
@@ -201,6 +202,7 @@ crate struct CrateRoot<'tcx> {
     triple: TargetTriple,
     extra_filename: String,
     hash: Svh,
+    disambiguator: CrateDisambiguator,
     stable_crate_id: StableCrateId,
     panic_strategy: PanicStrategy,
     edition: Edition,
diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs
index aa54d1ae7b9..8476929eaec 100644
--- a/compiler/rustc_middle/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs
@@ -285,7 +285,7 @@ pub type DepNode = rustc_query_system::dep_graph::DepNode<DepKind>;
 // 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);
+static_assert_size!(DepNode, 18);
 
 #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
 static_assert_size!(DepNode, 24);
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 07b39c97c49..20bbf9097f4 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -15,7 +15,6 @@ use rustc_hir::intravisit::Visitor;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
 use rustc_hir::*;
 use rustc_index::vec::Idx;
-use rustc_span::def_id::StableCrateId;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, Ident, Symbol};
@@ -991,24 +990,25 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
     upstream_crates.hash_stable(&mut hcx, &mut stable_hasher);
     source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
     tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher);
-    tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher);
+    tcx.sess.local_crate_disambiguator().to_fingerprint().hash_stable(&mut hcx, &mut stable_hasher);
     tcx.untracked_crate.non_exported_macro_attrs.hash_stable(&mut hcx, &mut stable_hasher);
 
     let crate_hash: Fingerprint = stable_hasher.finish();
     Svh::new(crate_hash.to_smaller_hash())
 }
 
-fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(StableCrateId, Svh)> {
+fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> {
     let mut upstream_crates: Vec<_> = cstore
         .crates_untracked()
         .iter()
         .map(|&cnum| {
-            let stable_crate_id = cstore.stable_crate_id_untracked(cnum);
+            let name = cstore.crate_name_untracked(cnum);
+            let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint();
             let hash = cstore.crate_hash_untracked(cnum);
-            (stable_crate_id, hash)
+            (name, disambiguator, hash)
         })
         .collect();
-    upstream_crates.sort_unstable_by_key(|&(stable_crate_id, _)| stable_crate_id);
+    upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name.as_str(), dis));
     upstream_crates
 }
 
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index b8407833c90..087f772c812 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -167,4 +167,8 @@ pub fn provide(providers: &mut Providers) {
     };
     providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id.expect_local());
     providers.all_local_trait_impls = |tcx, ()| &tcx.hir_crate(()).trait_impls;
+    providers.expn_that_defined = |tcx, id| {
+        let id = id.expect_local();
+        tcx.definitions.expansion_that_defined(id)
+    };
 }
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 5df2f91f09f..d764d45ba7e 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -294,6 +294,7 @@ TrivialTypeFoldableImpls! {
 }
 
 impl<'tcx> CanonicalVarValues<'tcx> {
+    #[inline]
     pub fn len(&self) -> usize {
         self.var_values.len()
     }
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 6f97716e2e0..e1d7bc4be53 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -29,7 +29,6 @@
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(const_panic)]
 #![feature(core_intrinsics)]
 #![feature(discriminant_kind)]
 #![feature(never_type)]
@@ -50,7 +49,6 @@
 #![feature(associated_type_defaults)]
 #![feature(iter_zip)]
 #![feature(thread_local_const_init)]
-#![feature(trusted_step)]
 #![recursion_limit = "512"]
 
 #[macro_use]
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 38d0793a682..4c7ea937ceb 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -1,7 +1,7 @@
 use std::cmp;
 
 use crate::ich::StableHashingContext;
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_errors::{DiagnosticBuilder, DiagnosticId};
 use rustc_hir::HirId;
@@ -28,6 +28,9 @@ pub enum LintLevelSource {
     /// The provided `Level` is the level specified on the command line.
     /// (The actual level may be lower due to `--cap-lints`.)
     CommandLine(Symbol, Level),
+
+    /// Lint is being forced to warn no matter what.
+    ForceWarn(Symbol),
 }
 
 impl LintLevelSource {
@@ -36,6 +39,7 @@ impl LintLevelSource {
             LintLevelSource::Default => symbol::kw::Default,
             LintLevelSource::Node(name, _, _) => name,
             LintLevelSource::CommandLine(name, _) => name,
+            LintLevelSource::ForceWarn(name) => name,
         }
     }
 
@@ -44,6 +48,7 @@ impl LintLevelSource {
             LintLevelSource::Default => DUMMY_SP,
             LintLevelSource::Node(_, span, _) => span,
             LintLevelSource::CommandLine(_, _) => DUMMY_SP,
+            LintLevelSource::ForceWarn(_) => DUMMY_SP,
         }
     }
 }
@@ -55,6 +60,7 @@ pub type LevelAndSource = (Level, LintLevelSource);
 pub struct LintLevelSets {
     pub list: Vec<LintSet>,
     pub lint_cap: Level,
+    pub force_warns: FxHashSet<LintId>,
 }
 
 #[derive(Debug)]
@@ -73,7 +79,11 @@ pub enum LintSet {
 
 impl LintLevelSets {
     pub fn new() -> Self {
-        LintLevelSets { list: Vec::new(), lint_cap: Level::Forbid }
+        LintLevelSets {
+            list: Vec::new(),
+            lint_cap: Level::Forbid,
+            force_warns: FxHashSet::default(),
+        }
     }
 
     pub fn get_lint_level(
@@ -83,6 +93,11 @@ impl LintLevelSets {
         aux: Option<&FxHashMap<LintId, LevelAndSource>>,
         sess: &Session,
     ) -> LevelAndSource {
+        // Check whether we should always warn
+        if self.force_warns.contains(&LintId::of(lint)) {
+            return (Level::Warn, LintLevelSource::ForceWarn(Symbol::intern(lint.name)));
+        }
+
         let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux);
 
         // If `level` is none then we actually assume the default level for this
@@ -176,11 +191,11 @@ impl LintLevelMap {
 impl<'a> HashStable<StableHashingContext<'a>> for LintLevelMap {
     #[inline]
     fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
-        let LintLevelMap { ref sets, ref id_to_set } = *self;
+        let LintLevelMap { ref sets, ref id_to_set, .. } = *self;
 
         id_to_set.hash_stable(hcx, hasher);
 
-        let LintLevelSets { ref list, lint_cap } = *sets;
+        let LintLevelSets { ref list, lint_cap, .. } = *sets;
 
         lint_cap.hash_stable(hcx, hasher);
 
@@ -346,6 +361,13 @@ pub fn struct_lint_level<'s, 'd>(
                     );
                 }
             }
+            LintLevelSource::ForceWarn(_) => {
+                sess.diag_note_once(
+                    &mut err,
+                    DiagnosticMessageId::from(lint),
+                    "warning forced by `force-warns` commandline option",
+                );
+            }
         }
 
         err.code(DiagnosticId::Lint { name, has_future_breakage });
diff --git a/compiler/rustc_middle/src/middle/cstore.rs b/compiler/rustc_middle/src/middle/cstore.rs
index 965de117e75..a7ab43d106c 100644
--- a/compiler/rustc_middle/src/middle/cstore.rs
+++ b/compiler/rustc_middle/src/middle/cstore.rs
@@ -14,7 +14,7 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
 use rustc_macros::HashStable;
 use rustc_session::search_paths::PathKind;
 use rustc_session::utils::NativeLibKind;
-use rustc_session::StableCrateId;
+use rustc_session::CrateDisambiguator;
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 use rustc_target::spec::Target;
@@ -95,6 +95,13 @@ pub struct NativeLib {
     pub foreign_module: Option<DefId>,
     pub wasm_import_module: Option<Symbol>,
     pub verbatim: Option<bool>,
+    pub dll_imports: Vec<DllImport>,
+}
+
+#[derive(Clone, Debug, Encodable, Decodable, HashStable)]
+pub struct DllImport {
+    pub name: Symbol,
+    pub ordinal: Option<u16>,
 }
 
 #[derive(Clone, TyEncodable, TyDecodable, HashStable, Debug)]
@@ -199,8 +206,7 @@ pub trait CrateStore {
 
     // "queries" used in resolve that aren't tracked for incremental compilation
     fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol;
-    fn crate_is_private_dep_untracked(&self, cnum: CrateNum) -> bool;
-    fn stable_crate_id_untracked(&self, cnum: CrateNum) -> StableCrateId;
+    fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator;
     fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh;
 
     // This is basically a 1-based range of ints, which is a little
diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs
index 26694afb513..288dd039446 100644
--- a/compiler/rustc_middle/src/middle/exported_symbols.rs
+++ b/compiler/rustc_middle/src/middle/exported_symbols.rs
@@ -48,8 +48,8 @@ impl<'tcx> ExportedSymbol<'tcx> {
 
 pub fn metadata_symbol_name(tcx: TyCtxt<'_>) -> String {
     format!(
-        "rust_metadata_{}_{:08x}",
-        tcx.original_crate_name(LOCAL_CRATE),
-        tcx.sess.local_stable_crate_id().to_u64(),
+        "rust_metadata_{}_{}",
+        tcx.crate_name(LOCAL_CRATE),
+        tcx.crate_disambiguator(LOCAL_CRATE).to_fingerprint().to_hex()
     )
 }
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index d03a7421ca7..14bdb0a5a2d 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -246,6 +246,7 @@ pub struct AllocDecodingState {
 }
 
 impl AllocDecodingState {
+    #[inline]
     pub fn new_decoding_session(&self) -> AllocDecodingSession<'_> {
         static DECODER_SESSION_ID: AtomicU32 = AtomicU32::new(0);
         let counter = DECODER_SESSION_ID.fetch_add(1, Ordering::SeqCst);
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 1cc7f235d7d..7ae7eab6e5a 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1249,10 +1249,12 @@ impl<'tcx> BasicBlockData<'tcx> {
     ///
     /// Terminator may not be None after construction of the basic block is complete. This accessor
     /// provides a convenience way to reach the terminator.
+    #[inline]
     pub fn terminator(&self) -> &Terminator<'tcx> {
         self.terminator.as_ref().expect("invalid terminator state")
     }
 
+    #[inline]
     pub fn terminator_mut(&mut self) -> &mut Terminator<'tcx> {
         self.terminator.as_mut().expect("invalid terminator state")
     }
@@ -1870,6 +1872,7 @@ impl<'tcx> PlaceRef<'tcx> {
 
     /// If this place represents a local variable like `_X` with no
     /// projections, return `Some(_X)`.
+    #[inline]
     pub fn as_local(&self) -> Option<Local> {
         match *self {
             PlaceRef { local, projection: [] } => Some(local),
@@ -1877,6 +1880,7 @@ impl<'tcx> PlaceRef<'tcx> {
         }
     }
 
+    #[inline]
     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))
@@ -2464,12 +2468,14 @@ impl Constant<'tcx> {
             _ => None,
         }
     }
+    #[inline]
     pub fn ty(&self) -> Ty<'tcx> {
         self.literal.ty()
     }
 }
 
 impl From<&'tcx ty::Const<'tcx>> for ConstantKind<'tcx> {
+    #[inline]
     fn from(ct: &'tcx ty::Const<'tcx>) -> Self {
         Self::Ty(ct)
     }
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index a160bcf6c1d..74650f50a1c 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -267,6 +267,7 @@ pub enum Visibility {
 }
 
 impl<'tcx> CodegenUnit<'tcx> {
+    #[inline]
     pub fn new(name: Symbol) -> CodegenUnit<'tcx> {
         CodegenUnit { name, items: Default::default(), size_estimate: None, primary: false }
     }
@@ -311,6 +312,7 @@ impl<'tcx> CodegenUnit<'tcx> {
         self.size_estimate = Some(self.items.keys().map(|mi| mi.size_estimate(tcx)).sum());
     }
 
+    #[inline]
     pub fn size_estimate(&self) -> usize {
         // Should only be called if `estimate_size` has previously been called.
         self.size_estimate.expect("estimate_size must be called before getting a size_estimate")
@@ -488,18 +490,15 @@ impl CodegenUnitNameBuilder<'tcx> {
             // local crate's ID. Otherwise there can be collisions between CGUs
             // instantiating stuff for upstream crates.
             let local_crate_id = if cnum != LOCAL_CRATE {
-                let local_stable_crate_id = tcx.sess.local_stable_crate_id();
-                format!(
-                    "-in-{}.{:08x}",
-                    tcx.crate_name(LOCAL_CRATE),
-                    local_stable_crate_id.to_u64()
-                )
+                let local_crate_disambiguator = format!("{}", tcx.crate_disambiguator(LOCAL_CRATE));
+                format!("-in-{}.{}", tcx.crate_name(LOCAL_CRATE), &local_crate_disambiguator[0..8])
             } else {
                 String::new()
             };
 
-            let stable_crate_id = tcx.sess.local_stable_crate_id();
-            format!("{}.{:08x}{}", tcx.crate_name(cnum), stable_crate_id.to_u64(), local_crate_id)
+            let crate_disambiguator = tcx.crate_disambiguator(cnum).to_string();
+            // Using a shortened disambiguator of about 40 bits
+            format!("{}.{}{}", tcx.crate_name(cnum), &crate_disambiguator[0..8], local_crate_id)
         });
 
         write!(cgu_name, "{}", crate_prefix).unwrap();
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 0edb79fdbc8..4fb737f463a 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -2,13 +2,14 @@
 
 use crate::mir::{abstract_const, Body, Promoted};
 use crate::ty::{self, Ty, TyCtxt};
-use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::vec_map::VecMap;
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_index::bit_set::BitMatrix;
 use rustc_index::vec::IndexVec;
+use rustc_middle::ty::OpaqueTypeKey;
 use rustc_span::Span;
 use rustc_target::abi::VariantIdx;
 use smallvec::SmallVec;
@@ -210,7 +211,7 @@ pub struct BorrowCheckResult<'tcx> {
     /// All the opaque types that are restricted to concrete types
     /// by this function. Unlike the value in `TypeckResults`, this has
     /// unerased regions.
-    pub concrete_opaque_types: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
+    pub concrete_opaque_types: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
     pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
     pub used_mut_upvars: SmallVec<[Field; 8]>,
 }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 9974f2bb8ca..0860520ef9d 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -210,8 +210,8 @@ rustc_queries! {
         desc { |tcx| "parent module of `{}`", tcx.def_path_str(key.to_def_id()) }
     }
 
-    /// Internal helper query. Use `tcx.expansion_that_defined` instead
     query expn_that_defined(key: DefId) -> rustc_span::ExpnId {
+        eval_always
         desc { |tcx| "expansion that defined `{}`", tcx.def_path_str(key) }
     }
 
@@ -1127,8 +1127,7 @@ rustc_queries! {
         desc { "computing whether impls specialize one another" }
     }
     query in_scope_traits_map(_: LocalDefId)
-        -> Option<&'tcx FxHashMap<ItemLocalId, StableVec<TraitCandidate>>> {
-        eval_always
+        -> Option<&'tcx FxHashMap<ItemLocalId, Box<[TraitCandidate]>>> {
         desc { "traits in scope at a block" }
     }
 
@@ -1238,6 +1237,10 @@ rustc_queries! {
     query proc_macro_decls_static(_: ()) -> Option<LocalDefId> {
         desc { "looking up the derive registrar for a crate" }
     }
+    query crate_disambiguator(_: CrateNum) -> CrateDisambiguator {
+        eval_always
+        desc { "looking up the disambiguator a crate" }
+    }
     // The macro which defines `rustc_metadata::provide_extern` depends on this query's name.
     // Changing the name should cause a compiler error, but in case that changes, be aware.
     query crate_hash(_: CrateNum) -> Svh {
@@ -1248,10 +1251,6 @@ rustc_queries! {
         eval_always
         desc { "looking up the hash of a host version of a crate" }
     }
-    query original_crate_name(_: CrateNum) -> Symbol {
-        eval_always
-        desc { "looking up the original name a crate" }
-    }
     query extra_filename(_: CrateNum) -> String {
         eval_always
         desc { "looking up the extra filename for a crate" }
@@ -1415,6 +1414,12 @@ rustc_queries! {
         eval_always
         desc { "generating a postorder list of CrateNums" }
     }
+    /// Returns whether or not the crate with CrateNum 'cnum'
+    /// is marked as a private dependency
+    query is_private_dep(c: CrateNum) -> bool {
+        eval_always
+        desc { "check whether crate {} is a private dependency", c }
+    }
 
     query upvars_mentioned(def_id: DefId) -> Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>> {
         desc { |tcx| "collecting upvars mentioned in `{}`", tcx.def_path_str(def_id) }
diff --git a/compiler/rustc_middle/src/ty/_match.rs b/compiler/rustc_middle/src/ty/_match.rs
index 8e2c79701af..02ff1b9f4d6 100644
--- a/compiler/rustc_middle/src/ty/_match.rs
+++ b/compiler/rustc_middle/src/ty/_match.rs
@@ -46,6 +46,7 @@ impl TypeRelation<'tcx> for Match<'tcx> {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         _: ty::Variance,
+        _: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 17590814322..d13cbdd1228 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -31,9 +31,10 @@ use rustc_attr as attr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableVec};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::steal::Steal;
 use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal};
+use rustc_data_structures::vec_map::VecMap;
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
@@ -47,6 +48,7 @@ use rustc_hir::{
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable;
 use rustc_middle::mir::FakeReadCause;
+use rustc_middle::ty::OpaqueTypeKey;
 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
 use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
 use rustc_session::lint::{Level, Lint};
@@ -286,17 +288,6 @@ impl<'a, V> LocalTableInContextMut<'a, V> {
     }
 }
 
-/// All information necessary to validate and reveal an `impl Trait`.
-#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
-pub struct ResolvedOpaqueTy<'tcx> {
-    /// The revealed type as seen by this function.
-    pub concrete_type: Ty<'tcx>,
-    /// Generic parameters on the opaque type as passed by this function.
-    /// For `type Foo<A, B> = impl Bar<A, B>; fn foo<T, U>() -> Foo<T, U> { .. }`
-    /// this is `[T, U]`, not `[A, B]`.
-    pub substs: SubstsRef<'tcx>,
-}
-
 /// Whenever a value may be live across a generator yield, the type of that value winds up in the
 /// `GeneratorInteriorTypeCause` struct. This struct adds additional information about such
 /// captured types that can be useful for diagnostics. In particular, it stores the span that
@@ -424,7 +415,7 @@ pub struct TypeckResults<'tcx> {
 
     /// All the opaque types that are restricted to concrete types
     /// by this function.
-    pub concrete_opaque_types: FxHashMap<DefId, ResolvedOpaqueTy<'tcx>>,
+    pub concrete_opaque_types: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
 
     /// Tracks the minimum captures required for a closure;
     /// see `MinCaptureInformationMap` for more details.
@@ -966,10 +957,6 @@ pub struct GlobalCtxt<'tcx> {
     /// Resolutions of `extern crate` items produced by resolver.
     extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
 
-    /// Map indicating what traits are in scope for places where this
-    /// is relevant; generated by resolve.
-    trait_map: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, StableVec<TraitCandidate>>>,
-
     /// Export map produced by name resolution.
     export_map: ExportMap<LocalDefId>,
 
@@ -1009,7 +996,7 @@ pub struct GlobalCtxt<'tcx> {
 
     /// The definite name of the current crate after taking into account
     /// attributes, commandline parameters, etc.
-    pub crate_name: Symbol,
+    crate_name: Symbol,
 
     /// Data layout specification for the current target.
     pub data_layout: TargetDataLayout,
@@ -1139,7 +1126,7 @@ impl<'tcx> TyCtxt<'tcx> {
         on_disk_cache: Option<query::OnDiskCache<'tcx>>,
         queries: &'tcx dyn query::QueryEngine<'tcx>,
         crate_name: &str,
-        output_filenames: &OutputFilenames,
+        output_filenames: OutputFilenames,
     ) -> GlobalCtxt<'tcx> {
         let data_layout = TargetDataLayout::parse(&s.target).unwrap_or_else(|err| {
             s.fatal(&err);
@@ -1150,12 +1137,6 @@ impl<'tcx> TyCtxt<'tcx> {
         let common_consts = CommonConsts::new(&interners, &common_types);
         let cstore = resolutions.cstore;
 
-        let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default();
-        for (hir_id, v) in krate.trait_map.iter() {
-            let map = trait_map.entry(hir_id.owner).or_default();
-            map.insert(hir_id.local_id, StableVec::new(v.to_vec()));
-        }
-
         GlobalCtxt {
             sess: s,
             lint_store,
@@ -1169,7 +1150,6 @@ impl<'tcx> TyCtxt<'tcx> {
             consts: common_consts,
             visibilities: resolutions.visibilities,
             extern_crate_map: resolutions.extern_crate_map,
-            trait_map,
             export_map: resolutions.export_map,
             maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports,
             maybe_unused_extern_crates: resolutions.maybe_unused_extern_crates,
@@ -1190,7 +1170,7 @@ impl<'tcx> TyCtxt<'tcx> {
             stability_interner: Default::default(),
             const_stability_interner: Default::default(),
             alloc_map: Lock::new(interpret::AllocMap::new()),
-            output_filenames: Arc::new(output_filenames.clone()),
+            output_filenames: Arc::new(output_filenames),
             main_def: resolutions.main_def,
         }
     }
@@ -1275,12 +1255,6 @@ impl<'tcx> TyCtxt<'tcx> {
         }
     }
 
-    /// Returns whether or not the crate with CrateNum 'cnum'
-    /// is marked as a private dependency
-    pub fn is_private_dep(self, cnum: CrateNum) -> bool {
-        if cnum == LOCAL_CRATE { false } else { self.cstore.crate_is_private_dep_untracked(cnum) }
-    }
-
     #[inline]
     pub fn def_path_hash(self, def_id: DefId) -> rustc_hir::definitions::DefPathHash {
         if let Some(def_id) = def_id.as_local() {
@@ -1292,24 +1266,24 @@ impl<'tcx> TyCtxt<'tcx> {
 
     pub fn def_path_debug_str(self, def_id: DefId) -> String {
         // We are explicitly not going through queries here in order to get
-        // crate name and stable crate id since this code is called from debug!()
+        // crate name and disambiguator since this code is called from debug!()
         // statements within the query system and we'd run into endless
         // recursion otherwise.
-        let (crate_name, stable_crate_id) = if def_id.is_local() {
-            (self.crate_name, self.sess.local_stable_crate_id())
+        let (crate_name, crate_disambiguator) = if def_id.is_local() {
+            (self.crate_name, self.sess.local_crate_disambiguator())
         } else {
             (
                 self.cstore.crate_name_untracked(def_id.krate),
-                self.def_path_hash(def_id.krate.as_def_id()).stable_crate_id(),
+                self.cstore.crate_disambiguator_untracked(def_id.krate),
             )
         };
 
         format!(
             "{}[{}]{}",
             crate_name,
-            // Don't print the whole stable crate id. That's just
+            // Don't print the whole crate disambiguator. That's just
             // annoying in debug output.
-            &(format!("{:08x}", stable_crate_id.to_u64()))[..4],
+            &(crate_disambiguator.to_fingerprint().to_hex())[..4],
             self.def_path(def_id).to_string_no_crate_verbose()
         )
     }
@@ -2658,8 +2632,10 @@ impl<'tcx> TyCtxt<'tcx> {
         struct_lint_level(self.sess, lint, level, src, None, decorate);
     }
 
-    pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx StableVec<TraitCandidate>> {
-        self.in_scope_traits_map(id.owner).and_then(|map| map.get(&id.local_id))
+    pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate]> {
+        let map = self.in_scope_traits_map(id.owner)?;
+        let candidates = map.get(&id.local_id)?;
+        Some(&*candidates)
     }
 
     pub fn named_region(self, id: HirId) -> Option<resolve_lifetime::Region> {
@@ -2789,7 +2765,7 @@ fn ptr_eq<T, U>(t: *const T, u: *const U) -> bool {
 }
 
 pub fn provide(providers: &mut ty::query::Providers) {
-    providers.in_scope_traits_map = |tcx, id| tcx.gcx.trait_map.get(&id);
+    providers.in_scope_traits_map = |tcx, id| tcx.hir_crate(()).trait_map.get(&id);
     providers.module_exports = |tcx, id| tcx.gcx.export_map.get(&id).map(|v| &v[..]);
     providers.crate_name = |tcx, id| {
         assert_eq!(id, LOCAL_CRATE);
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index c8fdbc30d15..4e3f475a915 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -93,6 +93,7 @@ pub struct Generics {
 }
 
 impl<'tcx> Generics {
+    #[inline]
     pub fn count(&self) -> usize {
         self.parent_count + self.params.len()
     }
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 03a026500d7..28a44b09de2 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -367,7 +367,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
         for &i in &inverse_memory_index {
             let field = fields[i as usize];
             if !sized {
-                bug!("univariant: field #{} of `{}` comes after unsized field", offsets.len(), ty);
+                self.tcx.sess.delay_span_bug(
+                    DUMMY_SP,
+                    &format!(
+                        "univariant: field #{} of `{}` comes after unsized field",
+                        offsets.len(),
+                        ty
+                    ),
+                );
             }
 
             if field.is_unsized() {
diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs
index e657088a5e4..44dfcbf1866 100644
--- a/compiler/rustc_middle/src/ty/list.rs
+++ b/compiler/rustc_middle/src/ty/list.rs
@@ -37,9 +37,11 @@ pub struct List<T> {
 
 unsafe impl<'a, T: 'a> rustc_data_structures::tagged_ptr::Pointer for &'a List<T> {
     const BITS: usize = std::mem::align_of::<usize>().trailing_zeros() as usize;
+    #[inline]
     fn into_usize(self) -> usize {
         self as *const List<T> as usize
     }
+    #[inline]
     unsafe fn from_usize(ptr: usize) -> Self {
         &*(ptr as *const List<T>)
     }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 94e325e9e87..227aa8dc284 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -39,7 +39,6 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, CRATE_DEF_INDEX};
 use rustc_hir::{Constness, Node};
 use rustc_macros::HashStable;
-use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::Span;
 use rustc_target::abi::Align;
@@ -59,7 +58,7 @@ pub use self::consts::{Const, ConstInt, ConstKind, InferConst, ScalarInt, Uneval
 pub use self::context::{
     tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
     CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorInteriorTypeCause, GlobalCtxt,
-    Lift, ResolvedOpaqueTy, TyCtxt, TypeckResults, UserType, UserTypeAnnotationIndex,
+    Lift, TyCtxt, TypeckResults, UserType, UserTypeAnnotationIndex,
 };
 pub use self::instance::{Instance, InstanceDef};
 pub use self::list::List;
@@ -72,7 +71,7 @@ pub use self::sty::{
     ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig,
     GeneratorSubsts, GeneratorSubstsParts, ParamConst, ParamTy, PolyExistentialProjection,
     PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind,
-    RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts,
+    RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo, VarianceDiagMutKind,
 };
 pub use self::trait_def::TraitDef;
 
@@ -269,7 +268,7 @@ pub struct CrateVariancesMap<'tcx> {
 // the types of AST nodes.
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub struct CReaderCacheKey {
-    pub cnum: CrateNum,
+    pub cnum: Option<CrateNum>,
     pub pos: usize,
 }
 
@@ -836,6 +835,12 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
     }
 }
 
+#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+pub struct OpaqueTypeKey<'tcx> {
+    pub def_id: DefId,
+    pub substs: SubstsRef<'tcx>,
+}
+
 rustc_index::newtype_index! {
     /// "Universes" are used during type- and trait-checking in the
     /// presence of `for<..>` binders to control what sets of names are
@@ -1097,12 +1102,14 @@ pub struct ParamEnv<'tcx> {
 
 unsafe impl rustc_data_structures::tagged_ptr::Tag for traits::Reveal {
     const BITS: usize = 1;
+    #[inline]
     fn into_usize(self) -> usize {
         match self {
             traits::Reveal::UserFacing => 0,
             traits::Reveal::All => 1,
         }
     }
+    #[inline]
     unsafe fn from_usize(ptr: usize) -> Self {
         match ptr {
             0 => traits::Reveal::UserFacing,
@@ -1200,6 +1207,7 @@ impl<'tcx> ParamEnv<'tcx> {
     }
 
     /// Returns this same environment but with no caller bounds.
+    #[inline]
     pub fn without_caller_bounds(self) -> Self {
         Self::new(List::empty(), self.reveal())
     }
@@ -1618,7 +1626,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
     fn item_name_from_def_id(self, def_id: DefId) -> Option<Symbol> {
         if def_id.index == CRATE_DEF_INDEX {
-            Some(self.original_crate_name(def_id.krate))
+            Some(self.crate_name(def_id.krate))
         } else {
             let def_key = self.def_key(def_id);
             match def_key.disambiguated_data.data {
@@ -1859,20 +1867,11 @@ impl<'tcx> TyCtxt<'tcx> {
             && use_name
                 .span
                 .ctxt()
-                .hygienic_eq(def_name.span.ctxt(), self.expansion_that_defined(def_parent_def_id))
-    }
-
-    pub fn expansion_that_defined(self, scope: DefId) -> ExpnId {
-        match scope.as_local() {
-            // Parsing and expansion aren't incremental, so we don't
-            // need to go through a query for the same-crate case.
-            Some(scope) => self.hir().definitions().expansion_that_defined(scope),
-            None => self.expn_that_defined(scope),
-        }
+                .hygienic_eq(def_name.span.ctxt(), self.expn_that_defined(def_parent_def_id))
     }
 
     pub fn adjust_ident(self, mut ident: Ident, scope: DefId) -> Ident {
-        ident.span.normalize_to_macros_2_0_and_adjust(self.expansion_that_defined(scope));
+        ident.span.normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope));
         ident
     }
 
@@ -1883,8 +1882,7 @@ impl<'tcx> TyCtxt<'tcx> {
         block: hir::HirId,
     ) -> (Ident, DefId) {
         let scope =
-            match ident.span.normalize_to_macros_2_0_and_adjust(self.expansion_that_defined(scope))
-            {
+            match ident.span.normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope)) {
                 Some(actual_expansion) => {
                     self.hir().definitions().parent_module_of_macro_def(actual_expansion)
                 }
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index f514278a11c..25557bdd100 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -452,7 +452,7 @@ pub trait PrettyPrinter<'tcx>:
             }
             // Re-exported `extern crate` (#43189).
             DefPathData::CrateRoot => {
-                data = DefPathData::TypeNs(self.tcx().original_crate_name(def_id.krate));
+                data = DefPathData::TypeNs(self.tcx().crate_name(def_id.krate));
             }
             _ => {}
         }
diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query/mod.rs
index bec13da017e..297110ee3ec 100644
--- a/compiler/rustc_middle/src/ty/query/mod.rs
+++ b/compiler/rustc_middle/src/ty/query/mod.rs
@@ -34,7 +34,6 @@ use crate::ty::subst::{GenericArg, SubstsRef};
 use crate::ty::util::AlwaysRequiresDrop;
 use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
-use rustc_data_structures::stable_hasher::StableVec;
 use rustc_data_structures::steal::Steal;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::Lrc;
@@ -48,6 +47,7 @@ use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
 use rustc_serialize::opaque;
 use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
 use rustc_session::utils::NativeLibKind;
+use rustc_session::CrateDisambiguator;
 use rustc_target::spec::PanicStrategy;
 
 use rustc_ast as ast;
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 ce10744bfb6..5c42625306b 100644
--- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
@@ -10,7 +10,7 @@ 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, DefPathTable};
+use rustc_hir::definitions::DefPathHash;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_query_system::dep_graph::DepContext;
 use rustc_query_system::query::QueryContext;
@@ -18,7 +18,7 @@ use rustc_serialize::{
     opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize},
     Decodable, Decoder, Encodable, Encoder,
 };
-use rustc_session::{Session, StableCrateId};
+use rustc_session::{CrateDisambiguator, Session};
 use rustc_span::hygiene::{
     ExpnDataDecodeMode, ExpnDataEncodeMode, ExpnId, HygieneDecodeContext, HygieneEncodeContext,
     SyntaxContext, SyntaxContextData,
@@ -27,7 +27,6 @@ use rustc_span::source_map::{SourceMap, StableSourceFileId};
 use rustc_span::CachingSourceMapView;
 use rustc_span::{BytePos, ExpnData, SourceFile, Span, DUMMY_SP};
 use std::collections::hash_map::Entry;
-use std::iter::FromIterator;
 use std::mem;
 
 const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
@@ -52,7 +51,7 @@ pub struct OnDiskCache<'sess> {
     // session.
     current_diagnostics: Lock<FxHashMap<DepNodeIndex, Vec<Diagnostic>>>,
 
-    prev_cnums: Vec<(u32, StableCrateId)>,
+    prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
     cnum_map: OnceCell<IndexVec<CrateNum, Option<CrateNum>>>,
 
     source_map: &'sess SourceMap,
@@ -103,12 +102,6 @@ pub struct OnDiskCache<'sess> {
     // during the next compilation session.
     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: 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
@@ -120,7 +113,7 @@ pub struct OnDiskCache<'sess> {
 #[derive(Encodable, Decodable)]
 struct Footer {
     file_index_to_stable_id: FxHashMap<SourceFileIndex, StableSourceFileId>,
-    prev_cnums: Vec<(u32, StableCrateId)>,
+    prev_cnums: Vec<(u32, String, CrateDisambiguator)>,
     query_result_index: EncodedQueryResultIndex,
     diagnostics_index: EncodedQueryResultIndex,
     // The location of all allocations.
@@ -168,12 +161,7 @@ crate struct RawDefId {
 
 impl<'sess> OnDiskCache<'sess> {
     /// Creates a new `OnDiskCache` instance from the serialized data in `data`.
-    pub fn new(
-        sess: &'sess Session,
-        data: Vec<u8>,
-        start_pos: usize,
-        def_path_table: &DefPathTable,
-    ) -> Self {
+    pub fn new(sess: &'sess Session, data: Vec<u8>, start_pos: usize) -> Self {
         debug_assert!(sess.opts.incremental.is_some());
 
         // Wrap in a scope so we can borrow `data`.
@@ -210,11 +198,6 @@ impl<'sess> OnDiskCache<'sess> {
             hygiene_context: Default::default(),
             foreign_def_path_hashes: footer.foreign_def_path_hashes,
             latest_foreign_def_path_hashes: Default::default(),
-            local_def_path_hash_to_def_id: UnhashMap::from_iter(
-                def_path_table
-                    .all_def_path_hashes_and_def_ids(LOCAL_CRATE)
-                    .map(|(hash, def_id)| (hash, def_id.as_local().unwrap())),
-            ),
             def_path_hash_to_def_id_cache: Default::default(),
         }
     }
@@ -236,7 +219,6 @@ impl<'sess> OnDiskCache<'sess> {
             hygiene_context: Default::default(),
             foreign_def_path_hashes: Default::default(),
             latest_foreign_def_path_hashes: Default::default(),
-            local_def_path_hash_to_def_id: Default::default(),
             def_path_hash_to_def_id_cache: Default::default(),
         }
     }
@@ -349,8 +331,9 @@ impl<'sess> OnDiskCache<'sess> {
             let prev_cnums: Vec<_> = sorted_cnums
                 .iter()
                 .map(|&cnum| {
-                    let stable_crate_id = tcx.def_path_hash(cnum.as_def_id()).stable_crate_id();
-                    (cnum.as_u32(), stable_crate_id)
+                    let crate_name = tcx.crate_name(cnum).to_string();
+                    let crate_disambiguator = tcx.crate_disambiguator(cnum);
+                    (cnum.as_u32(), crate_name, crate_disambiguator)
                 })
                 .collect();
 
@@ -574,23 +557,25 @@ impl<'sess> OnDiskCache<'sess> {
     // maps to None.
     fn compute_cnum_map(
         tcx: TyCtxt<'_>,
-        prev_cnums: &[(u32, StableCrateId)],
+        prev_cnums: &[(u32, String, CrateDisambiguator)],
     ) -> IndexVec<CrateNum, Option<CrateNum>> {
         tcx.dep_graph.with_ignore(|| {
             let current_cnums = tcx
                 .all_crate_nums(())
                 .iter()
                 .map(|&cnum| {
-                    let stable_crate_id = tcx.def_path_hash(cnum.as_def_id()).stable_crate_id();
-                    (stable_crate_id, cnum)
+                    let crate_name = tcx.crate_name(cnum).to_string();
+                    let crate_disambiguator = tcx.crate_disambiguator(cnum);
+                    ((crate_name, crate_disambiguator), cnum)
                 })
                 .collect::<FxHashMap<_, _>>();
 
             let map_size = prev_cnums.iter().map(|&(cnum, ..)| cnum).max().unwrap_or(0) + 1;
             let mut map = IndexVec::from_elem_n(None, map_size as usize);
 
-            for &(prev_cnum, stable_crate_id) in prev_cnums {
-                map[CrateNum::from_u32(prev_cnum)] = current_cnums.get(&stable_crate_id).cloned();
+            for &(prev_cnum, ref crate_name, crate_disambiguator) in prev_cnums {
+                let key = (crate_name.clone(), crate_disambiguator);
+                map[CrateNum::from_u32(prev_cnum)] = current_cnums.get(&key).cloned();
             }
 
             map[LOCAL_CRATE] = Some(LOCAL_CRATE);
@@ -613,7 +598,7 @@ impl<'sess> OnDiskCache<'sess> {
                 debug!("def_path_hash_to_def_id({:?})", hash);
                 // Check if the `DefPathHash` corresponds to a definition in the current
                 // crate
-                if let Some(def_id) = self.local_def_path_hash_to_def_id.get(&hash).cloned() {
+                if let Some(def_id) = tcx.definitions.local_def_path_hash_to_def_id(hash) {
                     let def_id = def_id.to_def_id();
                     e.insert(Some(def_id));
                     return Some(def_id);
@@ -755,8 +740,7 @@ impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> {
     {
         let tcx = self.tcx();
 
-        let cache_key =
-            ty::CReaderCacheKey { cnum: CrateNum::ReservedForIncrCompCache, pos: shorthand };
+        let cache_key = ty::CReaderCacheKey { cnum: None, pos: shorthand };
 
         if let Some(&ty) = tcx.ty_rcache.borrow().get(&cache_key) {
             return Ok(ty);
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index b6f93c9bd59..872d12cac93 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -67,6 +67,7 @@ pub trait TypeRelation<'tcx>: Sized {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         variance: ty::Variance,
+        info: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T>;
@@ -111,24 +112,23 @@ pub trait Relate<'tcx>: TypeFoldable<'tcx> + Copy {
 ///////////////////////////////////////////////////////////////////////////
 // Relate impls
 
-impl<'tcx> Relate<'tcx> for ty::TypeAndMut<'tcx> {
-    fn relate<R: TypeRelation<'tcx>>(
-        relation: &mut R,
-        a: ty::TypeAndMut<'tcx>,
-        b: ty::TypeAndMut<'tcx>,
-    ) -> RelateResult<'tcx, ty::TypeAndMut<'tcx>> {
-        debug!("{}.mts({:?}, {:?})", relation.tag(), a, b);
-        if a.mutbl != b.mutbl {
-            Err(TypeError::Mutability)
-        } else {
-            let mutbl = a.mutbl;
-            let variance = match mutbl {
-                ast::Mutability::Not => ty::Covariant,
-                ast::Mutability::Mut => ty::Invariant,
-            };
-            let ty = relation.relate_with_variance(variance, a.ty, b.ty)?;
-            Ok(ty::TypeAndMut { ty, mutbl })
-        }
+fn relate_type_and_mut<'tcx, R: TypeRelation<'tcx>>(
+    relation: &mut R,
+    a: ty::TypeAndMut<'tcx>,
+    b: ty::TypeAndMut<'tcx>,
+    kind: ty::VarianceDiagMutKind,
+) -> RelateResult<'tcx, ty::TypeAndMut<'tcx>> {
+    debug!("{}.mts({:?}, {:?})", relation.tag(), a, b);
+    if a.mutbl != b.mutbl {
+        Err(TypeError::Mutability)
+    } else {
+        let mutbl = a.mutbl;
+        let (variance, info) = match mutbl {
+            ast::Mutability::Not => (ty::Covariant, ty::VarianceDiagInfo::None),
+            ast::Mutability::Mut => (ty::Invariant, ty::VarianceDiagInfo::Mut { kind, ty: a.ty }),
+        };
+        let ty = relation.relate_with_variance(variance, info, a.ty, b.ty)?;
+        Ok(ty::TypeAndMut { ty, mutbl })
     }
 }
 
@@ -142,7 +142,7 @@ pub fn relate_substs<R: TypeRelation<'tcx>>(
 
     let params = iter::zip(a_subst, b_subst).enumerate().map(|(i, (a, b))| {
         let variance = variances.map_or(ty::Invariant, |v| v[i]);
-        relation.relate_with_variance(variance, a, b)
+        relation.relate_with_variance(variance, ty::VarianceDiagInfo::default(), a, b)
     });
 
     tcx.mk_substs(params)
@@ -177,7 +177,12 @@ impl<'tcx> Relate<'tcx> for ty::FnSig<'tcx> {
                 if is_output {
                     relation.relate(a, b)
                 } else {
-                    relation.relate_with_variance(ty::Contravariant, a, b)
+                    relation.relate_with_variance(
+                        ty::Contravariant,
+                        ty::VarianceDiagInfo::default(),
+                        a,
+                        b,
+                    )
                 }
             })
             .enumerate()
@@ -251,8 +256,18 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
                 b.item_def_id,
             )))
         } else {
-            let ty = relation.relate_with_variance(ty::Invariant, a.ty, b.ty)?;
-            let substs = relation.relate_with_variance(ty::Invariant, a.substs, b.substs)?;
+            let ty = relation.relate_with_variance(
+                ty::Invariant,
+                ty::VarianceDiagInfo::default(),
+                a.ty,
+                b.ty,
+            )?;
+            let substs = relation.relate_with_variance(
+                ty::Invariant,
+                ty::VarianceDiagInfo::default(),
+                a.substs,
+                b.substs,
+            )?;
             Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, ty })
         }
     }
@@ -364,7 +379,12 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
 
         (&ty::Dynamic(a_obj, a_region), &ty::Dynamic(b_obj, b_region)) => {
             let region_bound = relation.with_cause(Cause::ExistentialRegionBound, |relation| {
-                relation.relate_with_variance(ty::Contravariant, a_region, b_region)
+                relation.relate_with_variance(
+                    ty::Contravariant,
+                    ty::VarianceDiagInfo::default(),
+                    a_region,
+                    b_region,
+                )
             })?;
             Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound))
         }
@@ -398,15 +418,20 @@ pub fn super_relate_tys<R: TypeRelation<'tcx>>(
         }
 
         (&ty::RawPtr(a_mt), &ty::RawPtr(b_mt)) => {
-            let mt = relation.relate(a_mt, b_mt)?;
+            let mt = relate_type_and_mut(relation, a_mt, b_mt, ty::VarianceDiagMutKind::RawPtr)?;
             Ok(tcx.mk_ptr(mt))
         }
 
         (&ty::Ref(a_r, a_ty, a_mutbl), &ty::Ref(b_r, b_ty, b_mutbl)) => {
-            let r = relation.relate_with_variance(ty::Contravariant, a_r, b_r)?;
+            let r = relation.relate_with_variance(
+                ty::Contravariant,
+                ty::VarianceDiagInfo::default(),
+                a_r,
+                b_r,
+            )?;
             let a_mt = ty::TypeAndMut { ty: a_ty, mutbl: a_mutbl };
             let b_mt = ty::TypeAndMut { ty: b_ty, mutbl: b_mutbl };
-            let mt = relation.relate(a_mt, b_mt)?;
+            let mt = relate_type_and_mut(relation, a_mt, b_mt, ty::VarianceDiagMutKind::Ref)?;
             Ok(tcx.mk_ref(r, mt))
         }
 
@@ -536,8 +561,12 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
         (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
             if au.def == bu.def && au.promoted == bu.promoted =>
         {
-            let substs =
-                relation.relate_with_variance(ty::Variance::Invariant, au.substs, bu.substs)?;
+            let substs = relation.relate_with_variance(
+                ty::Variance::Invariant,
+                ty::VarianceDiagInfo::default(),
+                au.substs,
+                bu.substs,
+            )?;
             return Ok(tcx.mk_const(ty::Const {
                 val: ty::ConstKind::Unevaluated(ty::Unevaluated {
                     def: au.def,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index f35ecb4d3cd..1d9ff512288 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1837,10 +1837,12 @@ impl<'tcx> TyS<'tcx> {
 
     #[inline]
     pub fn is_enum(&self) -> bool {
-        match self.kind() {
-            Adt(adt_def, _) => adt_def.is_enum(),
-            _ => false,
-        }
+        matches!(self.kind(), Adt(adt_def, _) if adt_def.is_enum())
+    }
+
+    #[inline]
+    pub fn is_union(&self) -> bool {
+        matches!(self.kind(), Adt(adt_def, _) if adt_def.is_union())
     }
 
     #[inline]
@@ -1889,11 +1891,6 @@ impl<'tcx> TyS<'tcx> {
     }
 
     #[inline]
-    pub fn is_machine(&self) -> bool {
-        matches!(self.kind(), Int(..) | Uint(..) | Float(..))
-    }
-
-    #[inline]
     pub fn has_concrete_skeleton(&self) -> bool {
         !matches!(self.kind(), Param(_) | Infer(_) | Error(_))
     }
@@ -2184,3 +2181,55 @@ impl<'tcx> TyS<'tcx> {
         }
     }
 }
+
+/// Extra information about why we ended up with a particular variance.
+/// This is only used to add more information to error messages, and
+/// has no effect on soundness. While choosing the 'wrong' `VarianceDiagInfo`
+/// may lead to confusing notes in error messages, it will never cause
+/// a miscompilation or unsoundness.
+///
+/// When in doubt, use `VarianceDiagInfo::default()`
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub enum VarianceDiagInfo<'tcx> {
+    /// No additional information - this is the default.
+    /// We will not add any additional information to error messages.
+    None,
+    /// We switched our variance because a type occurs inside
+    /// the generic argument of a mutable reference or pointer
+    /// (`*mut T` or `&mut T`). In either case, our variance
+    /// will always be `Invariant`.
+    Mut {
+        /// Tracks whether we had a mutable pointer or reference,
+        /// for better error messages
+        kind: VarianceDiagMutKind,
+        /// The type parameter of the mutable pointer/reference
+        /// (the `T` in `&mut T` or `*mut T`).
+        ty: Ty<'tcx>,
+    },
+}
+
+#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub enum VarianceDiagMutKind {
+    /// A mutable raw pointer (`*mut T`)
+    RawPtr,
+    /// A mutable reference (`&mut T`)
+    Ref,
+}
+
+impl<'tcx> VarianceDiagInfo<'tcx> {
+    /// Mirrors `Variance::xform` - used to 'combine' the existing
+    /// and new `VarianceDiagInfo`s when our variance changes.
+    pub fn xform(self, other: VarianceDiagInfo<'tcx>) -> VarianceDiagInfo<'tcx> {
+        // For now, just use the first `VarianceDiagInfo::Mut` that we see
+        match self {
+            VarianceDiagInfo::None => other,
+            VarianceDiagInfo::Mut { .. } => self,
+        }
+    }
+}
+
+impl<'tcx> Default for VarianceDiagInfo<'tcx> {
+    fn default() -> Self {
+        Self::None
+    }
+}
diff --git a/compiler/rustc_mir/src/borrow_check/constraints/graph.rs b/compiler/rustc_mir/src/borrow_check/constraints/graph.rs
index f3f6b8c10da..9e4cfb2cc00 100644
--- a/compiler/rustc_mir/src/borrow_check/constraints/graph.rs
+++ b/compiler/rustc_mir/src/borrow_check/constraints/graph.rs
@@ -1,7 +1,7 @@
 use rustc_data_structures::graph;
 use rustc_index::vec::IndexVec;
 use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::ty::RegionVid;
+use rustc_middle::ty::{RegionVid, VarianceDiagInfo};
 use rustc_span::DUMMY_SP;
 
 use crate::borrow_check::{
@@ -26,8 +26,8 @@ crate type ReverseConstraintGraph = ConstraintGraph<Reverse>;
 /// Marker trait that controls whether a `R1: R2` constraint
 /// represents an edge `R1 -> R2` or `R2 -> R1`.
 crate trait ConstraintGraphDirecton: Copy + 'static {
-    fn start_region(c: &OutlivesConstraint) -> RegionVid;
-    fn end_region(c: &OutlivesConstraint) -> RegionVid;
+    fn start_region(c: &OutlivesConstraint<'_>) -> RegionVid;
+    fn end_region(c: &OutlivesConstraint<'_>) -> RegionVid;
     fn is_normal() -> bool;
 }
 
@@ -39,11 +39,11 @@ crate trait ConstraintGraphDirecton: Copy + 'static {
 crate struct Normal;
 
 impl ConstraintGraphDirecton for Normal {
-    fn start_region(c: &OutlivesConstraint) -> RegionVid {
+    fn start_region(c: &OutlivesConstraint<'_>) -> RegionVid {
         c.sup
     }
 
-    fn end_region(c: &OutlivesConstraint) -> RegionVid {
+    fn end_region(c: &OutlivesConstraint<'_>) -> RegionVid {
         c.sub
     }
 
@@ -60,11 +60,11 @@ impl ConstraintGraphDirecton for Normal {
 crate struct Reverse;
 
 impl ConstraintGraphDirecton for Reverse {
-    fn start_region(c: &OutlivesConstraint) -> RegionVid {
+    fn start_region(c: &OutlivesConstraint<'_>) -> RegionVid {
         c.sub
     }
 
-    fn end_region(c: &OutlivesConstraint) -> RegionVid {
+    fn end_region(c: &OutlivesConstraint<'_>) -> RegionVid {
         c.sup
     }
 
@@ -78,7 +78,7 @@ impl<D: ConstraintGraphDirecton> ConstraintGraph<D> {
     /// R2` is treated as an edge `R1 -> R2`. We use this graph to
     /// construct SCCs for region inference but also for error
     /// reporting.
-    crate fn new(direction: D, set: &OutlivesConstraintSet, num_region_vars: usize) -> Self {
+    crate fn new(direction: D, set: &OutlivesConstraintSet<'_>, num_region_vars: usize) -> Self {
         let mut first_constraints = IndexVec::from_elem_n(None, num_region_vars);
         let mut next_constraints = IndexVec::from_elem(None, &set.outlives);
 
@@ -96,21 +96,21 @@ impl<D: ConstraintGraphDirecton> ConstraintGraph<D> {
     /// Given the constraint set from which this graph was built
     /// creates a region graph so that you can iterate over *regions*
     /// and not constraints.
-    crate fn region_graph<'rg>(
+    crate fn region_graph<'rg, 'tcx>(
         &'rg self,
-        set: &'rg OutlivesConstraintSet,
+        set: &'rg OutlivesConstraintSet<'tcx>,
         static_region: RegionVid,
-    ) -> RegionGraph<'rg, D> {
+    ) -> RegionGraph<'rg, 'tcx, D> {
         RegionGraph::new(set, self, static_region)
     }
 
     /// Given a region `R`, iterate over all constraints `R: R1`.
-    crate fn outgoing_edges<'a>(
+    crate fn outgoing_edges<'a, 'tcx>(
         &'a self,
         region_sup: RegionVid,
-        constraints: &'a OutlivesConstraintSet,
+        constraints: &'a OutlivesConstraintSet<'tcx>,
         static_region: RegionVid,
-    ) -> Edges<'a, D> {
+    ) -> Edges<'a, 'tcx, D> {
         //if this is the `'static` region and the graph's direction is normal,
         //then setup the Edges iterator to return all regions #53178
         if region_sup == static_region && D::is_normal() {
@@ -129,22 +129,22 @@ impl<D: ConstraintGraphDirecton> ConstraintGraph<D> {
     }
 }
 
-crate struct Edges<'s, D: ConstraintGraphDirecton> {
+crate struct Edges<'s, 'tcx, D: ConstraintGraphDirecton> {
     graph: &'s ConstraintGraph<D>,
-    constraints: &'s OutlivesConstraintSet,
+    constraints: &'s OutlivesConstraintSet<'tcx>,
     pointer: Option<OutlivesConstraintIndex>,
     next_static_idx: Option<usize>,
     static_region: RegionVid,
 }
 
-impl<'s, D: ConstraintGraphDirecton> Iterator for Edges<'s, D> {
-    type Item = OutlivesConstraint;
+impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Edges<'s, 'tcx, D> {
+    type Item = OutlivesConstraint<'tcx>;
 
     fn next(&mut self) -> Option<Self::Item> {
         if let Some(p) = self.pointer {
             self.pointer = self.graph.next_constraints[p];
 
-            Some(self.constraints[p])
+            Some(self.constraints[p].clone())
         } else if let Some(next_static_idx) = self.next_static_idx {
             self.next_static_idx = if next_static_idx == (self.graph.first_constraints.len() - 1) {
                 None
@@ -157,6 +157,7 @@ impl<'s, D: ConstraintGraphDirecton> Iterator for Edges<'s, D> {
                 sub: next_static_idx.into(),
                 locations: Locations::All(DUMMY_SP),
                 category: ConstraintCategory::Internal,
+                variance_info: VarianceDiagInfo::default(),
             })
         } else {
             None
@@ -167,19 +168,19 @@ impl<'s, D: ConstraintGraphDirecton> Iterator for Edges<'s, D> {
 /// This struct brings together a constraint set and a (normal, not
 /// reverse) constraint graph. It implements the graph traits and is
 /// usd for doing the SCC computation.
-crate struct RegionGraph<'s, D: ConstraintGraphDirecton> {
-    set: &'s OutlivesConstraintSet,
+crate struct RegionGraph<'s, 'tcx, D: ConstraintGraphDirecton> {
+    set: &'s OutlivesConstraintSet<'tcx>,
     constraint_graph: &'s ConstraintGraph<D>,
     static_region: RegionVid,
 }
 
-impl<'s, D: ConstraintGraphDirecton> RegionGraph<'s, D> {
+impl<'s, 'tcx, D: ConstraintGraphDirecton> RegionGraph<'s, 'tcx, D> {
     /// Creates a "dependency graph" where each region constraint `R1:
     /// R2` is treated as an edge `R1 -> R2`. We use this graph to
     /// construct SCCs for region inference but also for error
     /// reporting.
     crate fn new(
-        set: &'s OutlivesConstraintSet,
+        set: &'s OutlivesConstraintSet<'tcx>,
         constraint_graph: &'s ConstraintGraph<D>,
         static_region: RegionVid,
     ) -> Self {
@@ -188,18 +189,18 @@ impl<'s, D: ConstraintGraphDirecton> RegionGraph<'s, D> {
 
     /// Given a region `R`, iterate over all regions `R1` such that
     /// there exists a constraint `R: R1`.
-    crate fn outgoing_regions(&self, region_sup: RegionVid) -> Successors<'_, D> {
+    crate fn outgoing_regions(&self, region_sup: RegionVid) -> Successors<'_, 'tcx, D> {
         Successors {
             edges: self.constraint_graph.outgoing_edges(region_sup, self.set, self.static_region),
         }
     }
 }
 
-crate struct Successors<'s, D: ConstraintGraphDirecton> {
-    edges: Edges<'s, D>,
+crate struct Successors<'s, 'tcx, D: ConstraintGraphDirecton> {
+    edges: Edges<'s, 'tcx, D>,
 }
 
-impl<'s, D: ConstraintGraphDirecton> Iterator for Successors<'s, D> {
+impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Successors<'s, 'tcx, D> {
     type Item = RegionVid;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -207,23 +208,26 @@ impl<'s, D: ConstraintGraphDirecton> Iterator for Successors<'s, D> {
     }
 }
 
-impl<'s, D: ConstraintGraphDirecton> graph::DirectedGraph for RegionGraph<'s, D> {
+impl<'s, 'tcx, D: ConstraintGraphDirecton> graph::DirectedGraph for RegionGraph<'s, 'tcx, D> {
     type Node = RegionVid;
 }
 
-impl<'s, D: ConstraintGraphDirecton> graph::WithNumNodes for RegionGraph<'s, D> {
+impl<'s, 'tcx, D: ConstraintGraphDirecton> graph::WithNumNodes for RegionGraph<'s, 'tcx, D> {
     fn num_nodes(&self) -> usize {
         self.constraint_graph.first_constraints.len()
     }
 }
 
-impl<'s, D: ConstraintGraphDirecton> graph::WithSuccessors for RegionGraph<'s, D> {
+impl<'s, 'tcx, D: ConstraintGraphDirecton> graph::WithSuccessors for RegionGraph<'s, 'tcx, D> {
     fn successors(&self, node: Self::Node) -> <Self as graph::GraphSuccessors<'_>>::Iter {
         self.outgoing_regions(node)
     }
 }
 
-impl<'s, 'graph, D: ConstraintGraphDirecton> graph::GraphSuccessors<'graph> for RegionGraph<'s, D> {
+impl<'s, 'graph, 'tcx, D: ConstraintGraphDirecton> graph::GraphSuccessors<'graph>
+    for RegionGraph<'s, 'tcx, D>
+{
     type Item = RegionVid;
-    type Iter = Successors<'graph, D>;
+    // FIXME - why can't this be `'graph, 'tcx`
+    type Iter = Successors<'graph, 'graph, D>;
 }
diff --git a/compiler/rustc_mir/src/borrow_check/constraints/mod.rs b/compiler/rustc_mir/src/borrow_check/constraints/mod.rs
index 3772b7d8f98..b944479ca45 100644
--- a/compiler/rustc_mir/src/borrow_check/constraints/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/constraints/mod.rs
@@ -1,7 +1,7 @@
 use rustc_data_structures::graph::scc::Sccs;
 use rustc_index::vec::IndexVec;
 use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::ty::RegionVid;
+use rustc_middle::ty::{RegionVid, VarianceDiagInfo};
 use std::fmt;
 use std::ops::Index;
 
@@ -14,12 +14,12 @@ crate mod graph;
 /// a unique `OutlivesConstraintIndex` and you can index into the set
 /// (`constraint_set[i]`) to access the constraint details.
 #[derive(Clone, Default)]
-crate struct OutlivesConstraintSet {
-    outlives: IndexVec<OutlivesConstraintIndex, OutlivesConstraint>,
+crate struct OutlivesConstraintSet<'tcx> {
+    outlives: IndexVec<OutlivesConstraintIndex, OutlivesConstraint<'tcx>>,
 }
 
-impl OutlivesConstraintSet {
-    crate fn push(&mut self, constraint: OutlivesConstraint) {
+impl<'tcx> OutlivesConstraintSet<'tcx> {
+    crate fn push(&mut self, constraint: OutlivesConstraint<'tcx>) {
         debug!(
             "OutlivesConstraintSet::push({:?}: {:?} @ {:?}",
             constraint.sup, constraint.sub, constraint.locations
@@ -59,21 +59,21 @@ impl OutlivesConstraintSet {
         Sccs::new(region_graph)
     }
 
-    crate fn outlives(&self) -> &IndexVec<OutlivesConstraintIndex, OutlivesConstraint> {
+    crate fn outlives(&self) -> &IndexVec<OutlivesConstraintIndex, OutlivesConstraint<'tcx>> {
         &self.outlives
     }
 }
 
-impl Index<OutlivesConstraintIndex> for OutlivesConstraintSet {
-    type Output = OutlivesConstraint;
+impl<'tcx> Index<OutlivesConstraintIndex> for OutlivesConstraintSet<'tcx> {
+    type Output = OutlivesConstraint<'tcx>;
 
     fn index(&self, i: OutlivesConstraintIndex) -> &Self::Output {
         &self.outlives[i]
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
-pub struct OutlivesConstraint {
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub struct OutlivesConstraint<'tcx> {
     // NB. The ordering here is not significant for correctness, but
     // it is for convenience. Before we dump the constraints in the
     // debugging logs, we sort them, and we'd like the "super region"
@@ -89,11 +89,18 @@ pub struct OutlivesConstraint {
 
     /// What caused this constraint?
     pub category: ConstraintCategory,
+
+    /// Variance diagnostic information
+    pub variance_info: VarianceDiagInfo<'tcx>,
 }
 
-impl fmt::Debug for OutlivesConstraint {
+impl<'tcx> fmt::Debug for OutlivesConstraint<'tcx> {
     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(formatter, "({:?}: {:?}) due to {:?}", self.sup, self.sub, self.locations)
+        write!(
+            formatter,
+            "({:?}: {:?}) due to {:?} ({:?})",
+            self.sup, self.sub, self.locations, self.variance_info
+        )
     }
 }
 
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
index 1b0cae51d58..e9f1ecb9bbc 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
@@ -15,6 +15,7 @@ use rustc_middle::ty::{self, RegionVid, TyCtxt};
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
 
+use crate::borrow_check::region_infer::BlameConstraint;
 use crate::borrow_check::{
     borrow_set::BorrowData, nll::ConstraintDescription, region_infer::Cause, MirBorrowckCtxt,
     WriteKind,
@@ -289,12 +290,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         borrow_region: RegionVid,
         outlived_region: RegionVid,
     ) -> (ConstraintCategory, bool, Span, Option<RegionName>) {
-        let (category, from_closure, span) = self.regioncx.best_blame_constraint(
-            &self.body,
-            borrow_region,
-            NllRegionVariableOrigin::FreeRegion,
-            |r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region),
-        );
+        let BlameConstraint { category, from_closure, span, variance_info: _ } =
+            self.regioncx.best_blame_constraint(
+                &self.body,
+                borrow_region,
+                NllRegionVariableOrigin::FreeRegion,
+                |r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region),
+            );
 
         let outlived_fr_name = self.give_region_a_name(outlived_region);
 
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
index 8665ef06126..feb7672f650 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
@@ -13,6 +13,7 @@ use rustc_span::Span;
 
 use crate::util::borrowck_errors;
 
+use crate::borrow_check::region_infer::BlameConstraint;
 use crate::borrow_check::{
     nll::ConstraintDescription,
     region_infer::{values::RegionElement, TypeTest},
@@ -275,12 +276,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     ) {
         debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
 
-        let (category, _, span) =
+        let BlameConstraint { category, span, variance_info, from_closure: _ } =
             self.regioncx.best_blame_constraint(&self.body, fr, fr_origin, |r| {
                 self.regioncx.provides_universal_region(r, fr, outlived_fr)
             });
 
-        debug!("report_region_error: category={:?} {:?}", category, span);
+        debug!("report_region_error: category={:?} {:?} {:?}", category, span, variance_info);
         // Check if we can use one of the "nice region errors".
         if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
             let nice = NiceRegionError::new_from_span(self.infcx, span, o, f);
@@ -309,7 +310,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             span,
         };
 
-        let diag = match (category, fr_is_local, outlived_fr_is_local) {
+        let mut diag = match (category, fr_is_local, outlived_fr_is_local) {
             (ConstraintCategory::Return(kind), true, false) if self.is_closure_fn_mut(fr) => {
                 self.report_fnmut_error(&errci, kind)
             }
@@ -332,6 +333,19 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             }
         };
 
+        match variance_info {
+            ty::VarianceDiagInfo::None => {}
+            ty::VarianceDiagInfo::Mut { kind, ty } => {
+                let kind_name = match kind {
+                    ty::VarianceDiagMutKind::Ref => "reference",
+                    ty::VarianceDiagMutKind::RawPtr => "pointer",
+                };
+                diag.note(&format!("requirement occurs because of a mutable {kind_name} to {ty}",));
+                diag.note(&format!("mutable {kind_name}s are invariant over their type parameter"));
+                diag.help("see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance");
+            }
+        }
+
         diag.buffer(&mut self.errors_buffer);
     }
 
diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs
index 4c35be39a3d..36eb8a4baa8 100644
--- a/compiler/rustc_mir/src/borrow_check/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/mod.rs
@@ -1965,13 +1965,11 @@ 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, _) = base.ty(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)
-                        }) {
-                            return;
-                        }
+                if base.ty(this.body(), tcx).ty.is_union() {
+                    if this.move_data.path_map[mpi].iter().any(|moi| {
+                        this.move_data.moves[*moi].source.is_predecessor_of(location, this.body)
+                    }) {
+                        return;
                     }
                 }
 
diff --git a/compiler/rustc_mir/src/borrow_check/nll.rs b/compiler/rustc_mir/src/borrow_check/nll.rs
index a0265b20d12..bfeafa33a91 100644
--- a/compiler/rustc_mir/src/borrow_check/nll.rs
+++ b/compiler/rustc_mir/src/borrow_check/nll.rs
@@ -1,15 +1,14 @@
 //! The entry point of the NLL borrow checker.
 
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::vec_map::VecMap;
 use rustc_errors::Diagnostic;
-use rustc_hir::def_id::DefId;
 use rustc_index::vec::IndexVec;
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::mir::{
     BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location,
     Promoted,
 };
-use rustc_middle::ty::{self, RegionKind, RegionVid};
+use rustc_middle::ty::{self, OpaqueTypeKey, RegionKind, RegionVid, Ty};
 use rustc_span::symbol::sym;
 use std::env;
 use std::fmt::Debug;
@@ -47,7 +46,7 @@ crate type PoloniusOutput = Output<RustcFacts>;
 /// closure requirements to propagate, and any generated errors.
 crate struct NllOutput<'tcx> {
     pub regioncx: RegionInferenceContext<'tcx>,
-    pub opaque_type_values: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
+    pub opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
     pub polonius_output: Option<Rc<PoloniusOutput>>,
     pub opt_closure_req: Option<ClosureRegionRequirements<'tcx>>,
     pub nll_errors: RegionErrors<'tcx>,
@@ -367,7 +366,7 @@ pub(super) fn dump_annotation<'a, 'tcx>(
     body: &Body<'tcx>,
     regioncx: &RegionInferenceContext<'tcx>,
     closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
-    opaque_type_values: &FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
+    opaque_type_values: &VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
     errors_buffer: &mut Vec<Diagnostic>,
 ) {
     let tcx = infcx.tcx;
diff --git a/compiler/rustc_mir/src/borrow_check/places_conflict.rs b/compiler/rustc_mir/src/borrow_check/places_conflict.rs
index 3654b51949e..d21550a8e1a 100644
--- a/compiler/rustc_mir/src/borrow_check/places_conflict.rs
+++ b/compiler/rustc_mir/src/borrow_check/places_conflict.rs
@@ -331,17 +331,14 @@ fn place_projection_conflict<'tcx>(
                 Overlap::EqualOrDisjoint
             } else {
                 let ty = Place::ty_from(pi1_local, pi1_proj_base, body, tcx).ty;
-                match ty.kind() {
-                    ty::Adt(def, _) if def.is_union() => {
-                        // Different fields of a union, we are basically stuck.
-                        debug!("place_element_conflict: STUCK-UNION");
-                        Overlap::Arbitrary
-                    }
-                    _ => {
-                        // Different fields of a struct (`a.x` vs. `a.y`). Disjoint!
-                        debug!("place_element_conflict: DISJOINT-FIELD");
-                        Overlap::Disjoint
-                    }
+                if ty.is_union() {
+                    // Different fields of a union, we are basically stuck.
+                    debug!("place_element_conflict: STUCK-UNION");
+                    Overlap::Arbitrary
+                } else {
+                    // Different fields of a struct (`a.x` vs. `a.y`). Disjoint!
+                    debug!("place_element_conflict: DISJOINT-FIELD");
+                    Overlap::Disjoint
                 }
             }
         }
diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/dump_mir.rs b/compiler/rustc_mir/src/borrow_check/region_infer/dump_mir.rs
index 5892ef37eba..213ebff12ab 100644
--- a/compiler/rustc_mir/src/borrow_check/region_infer/dump_mir.rs
+++ b/compiler/rustc_mir/src/borrow_check/region_infer/dump_mir.rs
@@ -74,7 +74,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
         constraints.sort();
         for constraint in &constraints {
-            let OutlivesConstraint { sup, sub, locations, category } = constraint;
+            let OutlivesConstraint { sup, sub, locations, category, variance_info: _ } = constraint;
             let (name, arg) = match locations {
                 Locations::All(span) => {
                     ("All", tcx.sess.source_map().span_to_embeddable_string(*span))
diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs b/compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs
index 7156612f473..b944d74e6f2 100644
--- a/compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs
+++ b/compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs
@@ -35,7 +35,7 @@ struct RawConstraints<'a, 'tcx> {
 
 impl<'a, 'this, 'tcx> dot::Labeller<'this> for RawConstraints<'a, 'tcx> {
     type Node = RegionVid;
-    type Edge = OutlivesConstraint;
+    type Edge = OutlivesConstraint<'tcx>;
 
     fn graph_id(&'this self) -> dot::Id<'this> {
         dot::Id::new("RegionInferenceContext").unwrap()
@@ -49,31 +49,31 @@ impl<'a, 'this, 'tcx> dot::Labeller<'this> for RawConstraints<'a, 'tcx> {
     fn node_label(&'this self, n: &RegionVid) -> dot::LabelText<'this> {
         dot::LabelText::LabelStr(format!("{:?}", n).into())
     }
-    fn edge_label(&'this self, e: &OutlivesConstraint) -> dot::LabelText<'this> {
+    fn edge_label(&'this self, e: &OutlivesConstraint<'tcx>) -> dot::LabelText<'this> {
         dot::LabelText::LabelStr(format!("{:?}", e.locations).into())
     }
 }
 
 impl<'a, 'this, 'tcx> dot::GraphWalk<'this> for RawConstraints<'a, 'tcx> {
     type Node = RegionVid;
-    type Edge = OutlivesConstraint;
+    type Edge = OutlivesConstraint<'tcx>;
 
     fn nodes(&'this self) -> dot::Nodes<'this, RegionVid> {
         let vids: Vec<RegionVid> = self.regioncx.definitions.indices().collect();
         vids.into()
     }
-    fn edges(&'this self) -> dot::Edges<'this, OutlivesConstraint> {
+    fn edges(&'this self) -> dot::Edges<'this, OutlivesConstraint<'tcx>> {
         (&self.regioncx.constraints.outlives().raw[..]).into()
     }
 
     // Render `a: b` as `a -> b`, indicating the flow
     // of data during inference.
 
-    fn source(&'this self, edge: &OutlivesConstraint) -> RegionVid {
+    fn source(&'this self, edge: &OutlivesConstraint<'tcx>) -> RegionVid {
         edge.sup
     }
 
-    fn target(&'this self, edge: &OutlivesConstraint) -> RegionVid {
+    fn target(&'this self, edge: &OutlivesConstraint<'tcx>) -> RegionVid {
         edge.sub
     }
 }
diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs b/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs
index f4d78ac04cb..dded7a7e3cf 100644
--- a/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs
@@ -54,7 +54,7 @@ pub struct RegionInferenceContext<'tcx> {
     liveness_constraints: LivenessValues<RegionVid>,
 
     /// The outlives constraints computed by the type-check.
-    constraints: Frozen<OutlivesConstraintSet>,
+    constraints: Frozen<OutlivesConstraintSet<'tcx>>,
 
     /// The constraint-set, but in graph form, making it easy to traverse
     /// the constraints adjacent to a particular region. Used to construct
@@ -227,10 +227,10 @@ enum RegionRelationCheckResult {
     Error,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-enum Trace {
+#[derive(Clone, PartialEq, Eq, Debug)]
+enum Trace<'tcx> {
     StartRegion,
-    FromOutlivesConstraint(OutlivesConstraint),
+    FromOutlivesConstraint(OutlivesConstraint<'tcx>),
     NotVisited,
 }
 
@@ -247,7 +247,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         universal_regions: Rc<UniversalRegions<'tcx>>,
         placeholder_indices: Rc<PlaceholderIndices>,
         universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
-        outlives_constraints: OutlivesConstraintSet,
+        outlives_constraints: OutlivesConstraintSet<'tcx>,
         member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
         closure_bounds_mapping: FxHashMap<
             Location,
@@ -1750,20 +1750,35 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     crate fn retrieve_closure_constraint_info(
         &self,
         body: &Body<'tcx>,
-        constraint: &OutlivesConstraint,
-    ) -> (ConstraintCategory, bool, Span) {
+        constraint: &OutlivesConstraint<'tcx>,
+    ) -> BlameConstraint<'tcx> {
         let loc = match constraint.locations {
-            Locations::All(span) => return (constraint.category, false, span),
+            Locations::All(span) => {
+                return BlameConstraint {
+                    category: constraint.category,
+                    from_closure: false,
+                    span,
+                    variance_info: constraint.variance_info.clone(),
+                };
+            }
             Locations::Single(loc) => loc,
         };
 
         let opt_span_category =
             self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub));
-        opt_span_category.map(|&(category, span)| (category, true, span)).unwrap_or((
-            constraint.category,
-            false,
-            body.source_info(loc).span,
-        ))
+        opt_span_category
+            .map(|&(category, span)| BlameConstraint {
+                category,
+                from_closure: true,
+                span: span,
+                variance_info: constraint.variance_info.clone(),
+            })
+            .unwrap_or(BlameConstraint {
+                category: constraint.category,
+                from_closure: false,
+                span: body.source_info(loc).span,
+                variance_info: constraint.variance_info.clone(),
+            })
     }
 
     /// Finds a good span to blame for the fact that `fr1` outlives `fr2`.
@@ -1774,9 +1789,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         fr1_origin: NllRegionVariableOrigin,
         fr2: RegionVid,
     ) -> (ConstraintCategory, Span) {
-        let (category, _, span) = self.best_blame_constraint(body, fr1, fr1_origin, |r| {
-            self.provides_universal_region(r, fr1, fr2)
-        });
+        let BlameConstraint { category, span, .. } =
+            self.best_blame_constraint(body, fr1, fr1_origin, |r| {
+                self.provides_universal_region(r, fr1, fr2)
+            });
         (category, span)
     }
 
@@ -1792,7 +1808,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         &self,
         from_region: RegionVid,
         target_test: impl Fn(RegionVid) -> bool,
-    ) -> Option<(Vec<OutlivesConstraint>, RegionVid)> {
+    ) -> Option<(Vec<OutlivesConstraint<'tcx>>, RegionVid)> {
         let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions);
         context[from_region] = Trace::StartRegion;
 
@@ -1816,14 +1832,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 let mut result = vec![];
                 let mut p = r;
                 loop {
-                    match context[p] {
+                    match context[p].clone() {
                         Trace::NotVisited => {
                             bug!("found unvisited region {:?} on path to {:?}", p, r)
                         }
 
                         Trace::FromOutlivesConstraint(c) => {
-                            result.push(c);
                             p = c.sup;
+                            result.push(c);
                         }
 
                         Trace::StartRegion => {
@@ -1846,7 +1862,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
             // Always inline this closure because it can be hot.
             let mut handle_constraint = #[inline(always)]
-            |constraint: OutlivesConstraint| {
+            |constraint: OutlivesConstraint<'tcx>| {
                 debug_assert_eq!(constraint.sup, r);
                 let sub_region = constraint.sub;
                 if let Trace::NotVisited = context[sub_region] {
@@ -1870,6 +1886,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     sub: constraint.min_choice,
                     locations: Locations::All(p_c.definition_span),
                     category: ConstraintCategory::OpaqueType,
+                    variance_info: ty::VarianceDiagInfo::default(),
                 };
                 handle_constraint(constraint);
             }
@@ -1967,7 +1984,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         from_region: RegionVid,
         from_region_origin: NllRegionVariableOrigin,
         target_test: impl Fn(RegionVid) -> bool,
-    ) -> (ConstraintCategory, bool, Span) {
+    ) -> BlameConstraint<'tcx> {
         debug!(
             "best_blame_constraint(from_region={:?}, from_region_origin={:?})",
             from_region, from_region_origin
@@ -1979,7 +1996,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         debug!(
             "best_blame_constraint: path={:#?}",
             path.iter()
-                .map(|&c| format!(
+                .map(|c| format!(
                     "{:?} ({:?}: {:?})",
                     c,
                     self.constraint_sccs.scc(c.sup),
@@ -1989,13 +2006,18 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         );
 
         // Classify each of the constraints along the path.
-        let mut categorized_path: Vec<(ConstraintCategory, bool, Span)> = path
+        let mut categorized_path: Vec<BlameConstraint<'tcx>> = path
             .iter()
             .map(|constraint| {
                 if constraint.category == ConstraintCategory::ClosureBounds {
                     self.retrieve_closure_constraint_info(body, &constraint)
                 } else {
-                    (constraint.category, false, constraint.locations.span(body))
+                    BlameConstraint {
+                        category: constraint.category,
+                        from_closure: false,
+                        span: constraint.locations.span(body),
+                        variance_info: constraint.variance_info.clone(),
+                    }
                 }
             })
             .collect();
@@ -2067,12 +2089,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         };
 
         let find_region = |i: &usize| {
-            let constraint = path[*i];
+            let constraint = &path[*i];
 
             let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup);
 
             if blame_source {
-                match categorized_path[*i].0 {
+                match categorized_path[*i].category {
                     ConstraintCategory::OpaqueType
                     | ConstraintCategory::Boring
                     | ConstraintCategory::BoringNoLocation
@@ -2083,7 +2105,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     _ => constraint_sup_scc != target_scc,
                 }
             } else {
-                match categorized_path[*i].0 {
+                match categorized_path[*i].category {
                     ConstraintCategory::OpaqueType
                     | ConstraintCategory::Boring
                     | ConstraintCategory::BoringNoLocation
@@ -2103,37 +2125,42 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         if let Some(i) = best_choice {
             if let Some(next) = categorized_path.get(i + 1) {
-                if matches!(categorized_path[i].0, ConstraintCategory::Return(_))
-                    && next.0 == ConstraintCategory::OpaqueType
+                if matches!(categorized_path[i].category, ConstraintCategory::Return(_))
+                    && next.category == ConstraintCategory::OpaqueType
                 {
                     // The return expression is being influenced by the return type being
                     // impl Trait, point at the return type and not the return expr.
-                    return *next;
+                    return next.clone();
                 }
             }
 
-            if categorized_path[i].0 == ConstraintCategory::Return(ReturnConstraint::Normal) {
+            if categorized_path[i].category == ConstraintCategory::Return(ReturnConstraint::Normal)
+            {
                 let field = categorized_path.iter().find_map(|p| {
-                    if let ConstraintCategory::ClosureUpvar(f) = p.0 { Some(f) } else { None }
+                    if let ConstraintCategory::ClosureUpvar(f) = p.category {
+                        Some(f)
+                    } else {
+                        None
+                    }
                 });
 
                 if let Some(field) = field {
-                    categorized_path[i].0 =
+                    categorized_path[i].category =
                         ConstraintCategory::Return(ReturnConstraint::ClosureUpvar(field));
                 }
             }
 
-            return categorized_path[i];
+            return categorized_path[i].clone();
         }
 
         // If that search fails, that is.. unusual. Maybe everything
         // is in the same SCC or something. In that case, find what
         // appears to be the most interesting point to report to the
         // user via an even more ad-hoc guess.
-        categorized_path.sort_by(|p0, p1| p0.0.cmp(&p1.0));
+        categorized_path.sort_by(|p0, p1| p0.category.cmp(&p1.category));
         debug!("`: sorted_path={:#?}", categorized_path);
 
-        *categorized_path.first().unwrap()
+        categorized_path.remove(0)
     }
 }
 
@@ -2228,3 +2255,11 @@ impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx
             .collect()
     }
 }
+
+#[derive(Clone, Debug)]
+pub struct BlameConstraint<'tcx> {
+    pub category: ConstraintCategory,
+    pub from_closure: bool,
+    pub span: Span,
+    pub variance_info: ty::VarianceDiagInfo<'tcx>,
+}
diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs b/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs
index 0d1d2551042..3ec24156f22 100644
--- a/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs
+++ b/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs
@@ -1,7 +1,6 @@
-use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def_id::DefId;
+use rustc_data_structures::vec_map::VecMap;
 use rustc_infer::infer::InferCtxt;
-use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
 use rustc_span::Span;
 use rustc_trait_selection::opaque_types::InferCtxtExt;
 
@@ -51,12 +50,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     pub(in crate::borrow_check) fn infer_opaque_types(
         &self,
         infcx: &InferCtxt<'_, 'tcx>,
-        opaque_ty_decls: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
+        opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
         span: Span,
-    ) -> FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>> {
+    ) -> VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>> {
         opaque_ty_decls
             .into_iter()
-            .map(|(opaque_def_id, ty::ResolvedOpaqueTy { concrete_type, substs })| {
+            .map(|(opaque_type_key, concrete_type)| {
+                let substs = opaque_type_key.substs;
                 debug!(?concrete_type, ?substs);
 
                 let mut subst_regions = vec![self.universal_regions.fr_static];
@@ -110,16 +110,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
                 debug!(?universal_concrete_type, ?universal_substs);
 
+                let opaque_type_key =
+                    OpaqueTypeKey { def_id: opaque_type_key.def_id, substs: universal_substs };
                 let remapped_type = infcx.infer_opaque_definition_from_instantiation(
-                    opaque_def_id,
-                    universal_substs,
+                    opaque_type_key,
                     universal_concrete_type,
                     span,
                 );
-                (
-                    opaque_def_id,
-                    ty::ResolvedOpaqueTy { concrete_type: remapped_type, substs: universal_substs },
-                )
+                (opaque_type_key, remapped_type)
             })
             .collect()
     }
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/constraint_conversion.rs b/compiler/rustc_mir/src/borrow_check/type_check/constraint_conversion.rs
index 8513e5e531b..eb11b937143 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/constraint_conversion.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/constraint_conversion.rs
@@ -143,6 +143,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
             category: self.category,
             sub,
             sup,
+            variance_info: ty::VarianceDiagInfo::default(),
         });
     }
 
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/liveness/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/liveness/mod.rs
index bddcd34ed3e..a34ae281b70 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/liveness/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/liveness/mod.rs
@@ -107,7 +107,7 @@ fn compute_live_locals(
 fn regions_that_outlive_free_regions(
     num_region_vars: usize,
     universal_regions: &UniversalRegions<'tcx>,
-    constraint_set: &OutlivesConstraintSet,
+    constraint_set: &OutlivesConstraintSet<'tcx>,
 ) -> FxHashSet<RegionVid> {
     // Build a graph of the outlives constraints thus far. This is
     // a reverse graph, so for each constraint `R1: R2` we have an
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 d27fcb2f26f..09cafddeeff 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
@@ -7,9 +7,10 @@ use either::Either;
 
 use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::vec_map::VecMap;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::LocalDefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::canonical::QueryRegionConstraints;
@@ -27,8 +28,8 @@ use rustc_middle::ty::cast::CastTy;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::subst::{GenericArgKind, Subst, SubstsRef, UserSubsts};
 use rustc_middle::ty::{
-    self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, RegionVid, ToPredicate, Ty,
-    TyCtxt, UserType, UserTypeAnnotationIndex, WithConstness,
+    self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueTypeKey, RegionVid,
+    ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, WithConstness,
 };
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::VariantIdx;
@@ -226,7 +227,7 @@ fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) {
         let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
         let location_table = cx.location_table;
         facts.outlives.extend(cx.constraints.outlives_constraints.outlives().iter().flat_map(
-            |constraint: &OutlivesConstraint| {
+            |constraint: &OutlivesConstraint<'_>| {
                 if let Some(from_location) = constraint.locations.from_location() {
                     Either::Left(iter::once((
                         constraint.sup,
@@ -572,7 +573,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
 
         let locations = location.to_locations();
         for constraint in constraints.outlives().iter() {
-            let mut constraint = *constraint;
+            let mut constraint = constraint.clone();
             constraint.locations = locations;
             if let ConstraintCategory::Return(_)
             | ConstraintCategory::UseAsConst
@@ -818,7 +819,7 @@ struct TypeChecker<'a, 'tcx> {
     reported_errors: FxHashSet<(Ty<'tcx>, Span)>,
     borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
     universal_region_relations: &'a UniversalRegionRelations<'tcx>,
-    opaque_type_values: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
+    opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
 }
 
 struct BorrowCheckContext<'a, 'tcx> {
@@ -833,7 +834,7 @@ struct BorrowCheckContext<'a, 'tcx> {
 crate struct MirTypeckResults<'tcx> {
     crate constraints: MirTypeckRegionConstraints<'tcx>,
     pub(in crate::borrow_check) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
-    crate opaque_type_values: FxHashMap<DefId, ty::ResolvedOpaqueTy<'tcx>>,
+    crate opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
 }
 
 /// A collection of region constraints that must be satisfied for the
@@ -862,7 +863,7 @@ crate struct MirTypeckRegionConstraints<'tcx> {
     /// hence it must report on their liveness constraints.
     crate liveness_constraints: LivenessValues<RegionVid>,
 
-    crate outlives_constraints: OutlivesConstraintSet,
+    crate outlives_constraints: OutlivesConstraintSet<'tcx>,
 
     crate member_constraints: MemberConstraintSet<'tcx, RegionVid>,
 
@@ -978,7 +979,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             borrowck_context,
             reported_errors: Default::default(),
             universal_region_relations,
-            opaque_type_values: FxHashMap::default(),
+            opaque_type_values: VecMap::default(),
         };
         checker.check_user_type_annotations();
         checker
@@ -1240,7 +1241,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         let param_env = self.param_env;
         let body = self.body;
         let concrete_opaque_types = &tcx.typeck(anon_owner_def_id).concrete_opaque_types;
-        let mut opaque_type_values = Vec::new();
+        let mut opaque_type_values = VecMap::new();
 
         debug!("eq_opaque_type_and_type: mir_def_id={:?}", body.source.def_id());
         let opaque_type_map = self.fully_perform_op(
@@ -1281,37 +1282,39 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                             .eq(output_ty, revealed_ty)?,
                     );
 
-                    for (&opaque_def_id, opaque_decl) in &opaque_type_map {
+                    for &(opaque_type_key, opaque_decl) in &opaque_type_map {
                         let resolved_ty = infcx.resolve_vars_if_possible(opaque_decl.concrete_ty);
                         let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind() {
-                            *def_id == opaque_def_id
+                            *def_id == opaque_type_key.def_id
                         } else {
                             false
                         };
-                        let opaque_defn_ty = match concrete_opaque_types.get(&opaque_def_id) {
+
+                        let concrete_ty = match concrete_opaque_types
+                            .get_by(|(key, _)| key.def_id == opaque_type_key.def_id)
+                        {
                             None => {
                                 if !concrete_is_opaque {
                                     tcx.sess.delay_span_bug(
                                         body.span,
                                         &format!(
                                             "Non-defining use of {:?} with revealed type",
-                                            opaque_def_id,
+                                            opaque_type_key.def_id,
                                         ),
                                     );
                                 }
                                 continue;
                             }
-                            Some(opaque_defn_ty) => opaque_defn_ty,
+                            Some(concrete_ty) => concrete_ty,
                         };
-                        debug!("opaque_defn_ty = {:?}", opaque_defn_ty);
-                        let subst_opaque_defn_ty =
-                            opaque_defn_ty.concrete_type.subst(tcx, opaque_decl.substs);
+                        debug!("concrete_ty = {:?}", concrete_ty);
+                        let subst_opaque_defn_ty = concrete_ty.subst(tcx, opaque_type_key.substs);
                         let renumbered_opaque_defn_ty =
                             renumber::renumber_regions(infcx, subst_opaque_defn_ty);
 
                         debug!(
                             "eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?}",
-                            opaque_decl.concrete_ty, resolved_ty, renumbered_opaque_defn_ty,
+                            concrete_ty, resolved_ty, renumbered_opaque_defn_ty,
                         );
 
                         if !concrete_is_opaque {
@@ -1322,13 +1325,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                                     .at(&ObligationCause::dummy(), param_env)
                                     .eq(opaque_decl.concrete_ty, renumbered_opaque_defn_ty)?,
                             );
-                            opaque_type_values.push((
-                                opaque_def_id,
-                                ty::ResolvedOpaqueTy {
-                                    concrete_type: renumbered_opaque_defn_ty,
-                                    substs: opaque_decl.substs,
-                                },
-                            ));
+                            opaque_type_values.insert(opaque_type_key, renumbered_opaque_defn_ty);
                         } else {
                             // We're using an opaque `impl Trait` type without
                             // 'revealing' it. For example, code like this:
@@ -1351,7 +1348,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                             // gets 'revealed' into
                             debug!(
                                 "eq_opaque_type_and_type: non-defining use of {:?}",
-                                opaque_def_id,
+                                opaque_type_key.def_id,
                             );
                         }
                     }
@@ -1376,14 +1373,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         // prove that `T: Iterator` where `T` is the type we
         // instantiated it with).
         if let Some(opaque_type_map) = opaque_type_map {
-            for (opaque_def_id, opaque_decl) in opaque_type_map {
+            for (opaque_type_key, opaque_decl) in opaque_type_map {
                 self.fully_perform_op(
                     locations,
                     ConstraintCategory::OpaqueType,
                     CustomTypeOp::new(
                         |_cx| {
                             infcx.constrain_opaque_type(
-                                opaque_def_id,
+                                opaque_type_key,
                                 &opaque_decl,
                                 GenerateMemberConstraints::IfNoStaticBound,
                                 universal_region_relations,
@@ -2535,6 +2532,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                                 sub: borrow_region.to_region_vid(),
                                 locations: location.to_locations(),
                                 category,
+                                variance_info: ty::VarianceDiagInfo::default(),
                             });
 
                             match mutbl {
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs b/compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs
index 249945f04b7..f97252a117a 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs
+++ b/compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs
@@ -94,7 +94,12 @@ impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> {
         )
     }
 
-    fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>) {
+    fn push_outlives(
+        &mut self,
+        sup: ty::Region<'tcx>,
+        sub: ty::Region<'tcx>,
+        info: ty::VarianceDiagInfo<'tcx>,
+    ) {
         if let Some(borrowck_context) = &mut self.borrowck_context {
             let sub = borrowck_context.universal_regions.to_region_vid(sub);
             let sup = borrowck_context.universal_regions.to_region_vid(sup);
@@ -103,6 +108,7 @@ impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> {
                 sub,
                 locations: self.locations,
                 category: self.category,
+                variance_info: info,
             });
         }
     }
diff --git a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
index 1bfbb843114..cea465ea1ed 100644
--- a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
+++ b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
@@ -519,10 +519,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
         // Check if we are assigning into a field of a union, if so, lookup the place
         // of the union so it is marked as initialized again.
         if let Some((place_base, ProjectionElem::Field(_, _))) = place.last_projection() {
-            if let ty::Adt(def, _) = place_base.ty(self.builder.body, self.builder.tcx).ty.kind() {
-                if def.is_union() {
-                    place = place_base;
-                }
+            if place_base.ty(self.builder.body, self.builder.tcx).ty.is_union() {
+                place = place_base;
             }
         }
 
diff --git a/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs b/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs
index 4978cc3606d..a7012cd63f3 100644
--- a/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs
+++ b/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs
@@ -1,5 +1,5 @@
 use rustc_hir::def_id::CrateNum;
-use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
+use rustc_hir::definitions::DisambiguatedDefPathData;
 use rustc_middle::mir::interpret::Allocation;
 use rustc_middle::ty::{
     self,
@@ -88,7 +88,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
     }
 
     fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
-        self.path.push_str(&self.tcx.original_crate_name(cnum).as_str());
+        self.path.push_str(&self.tcx.crate_name(cnum).as_str());
         Ok(self)
     }
 
@@ -127,11 +127,6 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
     ) -> Result<Self::Path, Self::Error> {
         self = print_prefix(self)?;
 
-        // Skip `::{{constructor}}` on tuple/unit structs.
-        if disambiguated_data.data == DefPathData::Ctor {
-            return Ok(self);
-        }
-
         write!(self.path, "::{}", disambiguated_data.data).unwrap();
 
         Ok(self)
diff --git a/compiler/rustc_mir/src/lib.rs b/compiler/rustc_mir/src/lib.rs
index 647c368d2bb..1da17bddcb7 100644
--- a/compiler/rustc_mir/src/lib.rs
+++ b/compiler/rustc_mir/src/lib.rs
@@ -12,16 +12,14 @@ Rust MIR: a lowered representation of Rust.
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(const_panic)]
 #![feature(crate_visibility_modifier)]
 #![feature(decl_macro)]
 #![feature(exact_size_is_empty)]
-#![feature(exhaustive_patterns)]
+#![feature(format_args_capture)]
 #![feature(iter_zip)]
 #![feature(never_type)]
 #![feature(map_try_insert)]
 #![feature(min_specialization)]
-#![feature(slice_ptr_len)]
 #![feature(slice_ptr_get)]
 #![feature(trusted_len)]
 #![feature(try_blocks)]
@@ -31,7 +29,6 @@ Rust MIR: a lowered representation of Rust.
 #![feature(option_get_or_insert_default)]
 #![feature(once_cell)]
 #![feature(control_flow_enum)]
-#![feature(trusted_step)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs
index 41d9d0d04b5..4fbd27c89d9 100644
--- a/compiler/rustc_mir/src/transform/check_consts/validation.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs
@@ -356,10 +356,9 @@ impl Validator<'mir, 'tcx> {
     }
 
     fn check_static(&mut self, def_id: DefId, span: Span) {
-        assert!(
-            !self.tcx.is_thread_local_static(def_id),
-            "tls access is checked in `Rvalue::ThreadLocalRef"
-        );
+        if self.tcx.is_thread_local_static(def_id) {
+            self.tcx.sess.delay_span_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef");
+        }
         self.check_op_spanned(ops::StaticAccess, span)
     }
 
@@ -730,13 +729,11 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
                 let base_ty = Place::ty_from(place_local, proj_base, self.body, self.tcx).ty;
                 if let ty::RawPtr(_) = base_ty.kind() {
                     if proj_base.is_empty() {
-                        if let (local, []) = (place_local, proj_base) {
-                            let decl = &self.body.local_decls[local];
-                            if let Some(box LocalInfo::StaticRef { def_id, .. }) = decl.local_info {
-                                let span = decl.source_info.span;
-                                self.check_static(def_id, span);
-                                return;
-                            }
+                        let decl = &self.body.local_decls[place_local];
+                        if let Some(box LocalInfo::StaticRef { def_id, .. }) = decl.local_info {
+                            let span = decl.source_info.span;
+                            self.check_static(def_id, span);
+                            return;
                         }
                     }
                     self.check_op(ops::RawPtrDeref);
@@ -753,12 +750,8 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
             | ProjectionElem::Field(..)
             | ProjectionElem::Index(_) => {
                 let base_ty = Place::ty_from(place_local, proj_base, self.body, self.tcx).ty;
-                match base_ty.ty_adt_def() {
-                    Some(def) if def.is_union() => {
-                        self.check_op(ops::UnionAccess);
-                    }
-
-                    _ => {}
+                if base_ty.is_union() {
+                    self.check_op(ops::UnionAccess);
                 }
             }
         }
diff --git a/compiler/rustc_mir/src/transform/check_unsafety.rs b/compiler/rustc_mir/src/transform/check_unsafety.rs
index 955be8cc81e..103ddda1a1d 100644
--- a/compiler/rustc_mir/src/transform/check_unsafety.rs
+++ b/compiler/rustc_mir/src/transform/check_unsafety.rs
@@ -221,7 +221,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
             }
 
             let base_ty = base.ty(self.body, self.tcx).ty;
-            if base_ty.ty_adt_def().map_or(false, |adt| adt.is_union()) {
+            if base_ty.is_union() {
                 // If we did not hit a `Deref` yet and the overall place use is an assignment, the
                 // rules are different.
                 let assign_to_field = !saw_deref
@@ -376,6 +376,12 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
     /// Checks whether calling `func_did` needs an `unsafe` context or not, i.e. whether
     /// the called function has target features the calling function hasn't.
     fn check_target_features(&mut self, func_did: DefId) {
+        // Unsafety isn't required on wasm targets. For more information see
+        // the corresponding check in typeck/src/collect.rs
+        if self.tcx.sess.target.options.is_like_wasm {
+            return;
+        }
+
         let callee_features = &self.tcx.codegen_fn_attrs(func_did).target_features;
         let self_features = &self.tcx.codegen_fn_attrs(self.body_did).target_features;
 
diff --git a/compiler/rustc_mir/src/transform/const_goto.rs b/compiler/rustc_mir/src/transform/const_goto.rs
index b5c8b4bebc3..ba10b54c5ae 100644
--- a/compiler/rustc_mir/src/transform/const_goto.rs
+++ b/compiler/rustc_mir/src/transform/const_goto.rs
@@ -47,7 +47,7 @@ impl<'tcx> MirPass<'tcx> for ConstGoto {
         // if we applied optimizations, we potentially have some cfg to cleanup to
         // make it easier for further passes
         if should_simplify {
-            simplify_cfg(body);
+            simplify_cfg(tcx, body);
             simplify_locals(body, tcx);
         }
     }
diff --git a/compiler/rustc_mir/src/transform/coverage/debug.rs b/compiler/rustc_mir/src/transform/coverage/debug.rs
index 2397d627880..f6672335cb1 100644
--- a/compiler/rustc_mir/src/transform/coverage/debug.rs
+++ b/compiler/rustc_mir/src/transform/coverage/debug.rs
@@ -116,7 +116,6 @@ use crate::util::pretty;
 use crate::util::spanview::{self, SpanViewable};
 
 use rustc_data_structures::fx::FxHashMap;
-use rustc_index::vec::Idx;
 use rustc_middle::mir::coverage::*;
 use rustc_middle::mir::{self, BasicBlock, TerminatorKind};
 use rustc_middle::ty::TyCtxt;
diff --git a/compiler/rustc_mir/src/transform/deduplicate_blocks.rs b/compiler/rustc_mir/src/transform/deduplicate_blocks.rs
index c41e71e09a4..912505c6598 100644
--- a/compiler/rustc_mir/src/transform/deduplicate_blocks.rs
+++ b/compiler/rustc_mir/src/transform/deduplicate_blocks.rs
@@ -26,7 +26,7 @@ impl<'tcx> MirPass<'tcx> for DeduplicateBlocks {
         if has_opts_to_apply {
             let mut opt_applier = OptApplier { tcx, duplicates };
             opt_applier.visit_body(body);
-            simplify_cfg(body);
+            simplify_cfg(tcx, body);
         }
     }
 }
diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs
index 29df86ca6cd..4f5a467a6ee 100644
--- a/compiler/rustc_mir/src/transform/dest_prop.rs
+++ b/compiler/rustc_mir/src/transform/dest_prop.rs
@@ -114,7 +114,7 @@ use rustc_middle::mir::{
     traversal, Body, InlineAsmOperand, Local, LocalKind, Location, Operand, Place, PlaceElem,
     Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
 };
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::TyCtxt;
 
 // Empirical measurements have resulted in some observations:
 // - Running on a body with a single block and 500 locals takes barely any time
@@ -910,17 +910,8 @@ impl<'a, 'tcx> Visitor<'tcx> for FindAssignments<'a, 'tcx> {
 
             // Handle the "subtle case" described above by rejecting any `dest` that is or
             // projects through a union.
-            let is_union = |ty: Ty<'_>| {
-                if let ty::Adt(def, _) = ty.kind() {
-                    if def.is_union() {
-                        return true;
-                    }
-                }
-
-                false
-            };
             let mut place_ty = PlaceTy::from_ty(self.body.local_decls[dest.local].ty);
-            if is_union(place_ty.ty) {
+            if place_ty.ty.is_union() {
                 return;
             }
             for elem in dest.projection {
@@ -930,7 +921,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindAssignments<'a, 'tcx> {
                 }
 
                 place_ty = place_ty.projection_ty(self.tcx, elem);
-                if is_union(place_ty.ty) {
+                if place_ty.ty.is_union() {
                     return;
                 }
             }
diff --git a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs
index 7934d4ba849..07127042fa4 100644
--- a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs
+++ b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs
@@ -164,7 +164,7 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
         // Since this optimization adds new basic blocks and invalidates others,
         // clean up the cfg to make it nicer for other passes
         if should_cleanup {
-            simplify_cfg(body);
+            simplify_cfg(tcx, body);
         }
     }
 }
diff --git a/compiler/rustc_mir/src/transform/generator.rs b/compiler/rustc_mir/src/transform/generator.rs
index 003003a8abb..3560b4b1e86 100644
--- a/compiler/rustc_mir/src/transform/generator.rs
+++ b/compiler/rustc_mir/src/transform/generator.rs
@@ -964,7 +964,7 @@ fn create_generator_drop_shim<'tcx>(
 
     // Make sure we remove dead blocks to remove
     // unrelated code from the resume part of the function
-    simplify::remove_dead_blocks(&mut body);
+    simplify::remove_dead_blocks(tcx, &mut body);
 
     dump_mir(tcx, None, "generator_drop", &0, &body, |_, _| Ok(()));
 
@@ -1137,7 +1137,7 @@ fn create_generator_resume_function<'tcx>(
 
     // Make sure we remove dead blocks to remove
     // unrelated code from the drop part of the function
-    simplify::remove_dead_blocks(body);
+    simplify::remove_dead_blocks(tcx, body);
 
     dump_mir(tcx, None, "generator_resume", &0, body, |_, _| Ok(()));
 }
diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs
index b6f80763bc8..f1c95a84ade 100644
--- a/compiler/rustc_mir/src/transform/inline.rs
+++ b/compiler/rustc_mir/src/transform/inline.rs
@@ -57,7 +57,7 @@ impl<'tcx> MirPass<'tcx> for Inline {
         if inline(tcx, body) {
             debug!("running simplify cfg on {:?}", body.source);
             CfgSimplifier::new(body).simplify();
-            remove_dead_blocks(body);
+            remove_dead_blocks(tcx, body);
         }
     }
 }
diff --git a/compiler/rustc_mir/src/transform/instcombine.rs b/compiler/rustc_mir/src/transform/instcombine.rs
index 7aaf0224164..b64189a7f3c 100644
--- a/compiler/rustc_mir/src/transform/instcombine.rs
+++ b/compiler/rustc_mir/src/transform/instcombine.rs
@@ -4,7 +4,7 @@ use crate::transform::MirPass;
 use rustc_hir::Mutability;
 use rustc_middle::mir::{
     BinOp, Body, Constant, LocalDecls, Operand, Place, ProjectionElem, Rvalue, SourceInfo,
-    StatementKind,
+    StatementKind, UnOp,
 };
 use rustc_middle::ty::{self, TyCtxt};
 
@@ -47,28 +47,35 @@ impl<'tcx, 'a> InstCombineContext<'tcx, 'a> {
             Rvalue::BinaryOp(op @ (BinOp::Eq | BinOp::Ne), box (a, b)) => {
                 let new = match (op, self.try_eval_bool(a), self.try_eval_bool(b)) {
                     // Transform "Eq(a, true)" ==> "a"
-                    (BinOp::Eq, _, Some(true)) => Some(a.clone()),
+                    (BinOp::Eq, _, Some(true)) => Some(Rvalue::Use(a.clone())),
 
                     // Transform "Ne(a, false)" ==> "a"
-                    (BinOp::Ne, _, Some(false)) => Some(a.clone()),
+                    (BinOp::Ne, _, Some(false)) => Some(Rvalue::Use(a.clone())),
 
                     // Transform "Eq(true, b)" ==> "b"
-                    (BinOp::Eq, Some(true), _) => Some(b.clone()),
+                    (BinOp::Eq, Some(true), _) => Some(Rvalue::Use(b.clone())),
 
                     // Transform "Ne(false, b)" ==> "b"
-                    (BinOp::Ne, Some(false), _) => Some(b.clone()),
+                    (BinOp::Ne, Some(false), _) => Some(Rvalue::Use(b.clone())),
 
-                    // FIXME: Consider combining remaining comparisons into logical operations:
                     // Transform "Eq(false, b)" ==> "Not(b)"
+                    (BinOp::Eq, Some(false), _) => Some(Rvalue::UnaryOp(UnOp::Not, b.clone())),
+
                     // Transform "Ne(true, b)" ==> "Not(b)"
+                    (BinOp::Ne, Some(true), _) => Some(Rvalue::UnaryOp(UnOp::Not, b.clone())),
+
                     // Transform "Eq(a, false)" ==> "Not(a)"
+                    (BinOp::Eq, _, Some(false)) => Some(Rvalue::UnaryOp(UnOp::Not, a.clone())),
+
                     // Transform "Ne(a, true)" ==> "Not(a)"
+                    (BinOp::Ne, _, Some(true)) => Some(Rvalue::UnaryOp(UnOp::Not, a.clone())),
+
                     _ => None,
                 };
 
                 if let Some(new) = new {
                     if self.should_combine(source_info, rvalue) {
-                        *rvalue = Rvalue::Use(new);
+                        *rvalue = new;
                     }
                 }
             }
diff --git a/compiler/rustc_mir/src/transform/match_branches.rs b/compiler/rustc_mir/src/transform/match_branches.rs
index f7a9835353e..21b208a08c2 100644
--- a/compiler/rustc_mir/src/transform/match_branches.rs
+++ b/compiler/rustc_mir/src/transform/match_branches.rs
@@ -167,7 +167,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
         }
 
         if should_cleanup {
-            simplify_cfg(body);
+            simplify_cfg(tcx, body);
         }
     }
 }
diff --git a/compiler/rustc_mir/src/transform/multiple_return_terminators.rs b/compiler/rustc_mir/src/transform/multiple_return_terminators.rs
index 4aaa0baa9f4..cd2db180552 100644
--- a/compiler/rustc_mir/src/transform/multiple_return_terminators.rs
+++ b/compiler/rustc_mir/src/transform/multiple_return_terminators.rs
@@ -38,6 +38,6 @@ impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators {
             }
         }
 
-        simplify::remove_dead_blocks(body)
+        simplify::remove_dead_blocks(tcx, body)
     }
 }
diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs
index f6b1323e107..78e84419c62 100644
--- a/compiler/rustc_mir/src/transform/promote_consts.rs
+++ b/compiler/rustc_mir/src/transform/promote_consts.rs
@@ -415,11 +415,9 @@ impl<'tcx> Validator<'_, 'tcx> {
 
                     ProjectionElem::Field(..) => {
                         let base_ty = place_base.ty(self.body, self.tcx).ty;
-                        if let Some(def) = base_ty.ty_adt_def() {
+                        if base_ty.is_union() {
                             // No promotion of union field accesses.
-                            if def.is_union() {
-                                return Err(Unpromotable);
-                            }
+                            return Err(Unpromotable);
                         }
                     }
                 }
diff --git a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs b/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs
index 5144d48750d..02e45021a0a 100644
--- a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs
+++ b/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs
@@ -36,7 +36,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops {
         // if we applied optimizations, we potentially have some cfg to cleanup to
         // make it easier for further passes
         if should_simplify {
-            simplify_cfg(body);
+            simplify_cfg(tcx, body);
         }
     }
 }
diff --git a/compiler/rustc_mir/src/transform/remove_zsts.rs b/compiler/rustc_mir/src/transform/remove_zsts.rs
index 70f7538dd57..40b1a8a2da9 100644
--- a/compiler/rustc_mir/src/transform/remove_zsts.rs
+++ b/compiler/rustc_mir/src/transform/remove_zsts.rs
@@ -16,32 +16,29 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts {
         let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
         for block in basic_blocks.iter_mut() {
             for statement in block.statements.iter_mut() {
-                match statement.kind {
-                    StatementKind::Assign(box (place, _)) => {
-                        let place_ty = place.ty(local_decls, tcx).ty;
-                        if !maybe_zst(place_ty) {
-                            continue;
-                        }
-                        let layout = match tcx.layout_of(param_env.and(place_ty)) {
-                            Ok(layout) => layout,
-                            Err(_) => continue,
-                        };
-                        if !layout.is_zst() {
-                            continue;
-                        }
-                        if involves_a_union(place, local_decls, tcx) {
-                            continue;
-                        }
-                        if tcx.consider_optimizing(|| {
-                            format!(
-                                "RemoveZsts - Place: {:?} SourceInfo: {:?}",
-                                place, statement.source_info
-                            )
-                        }) {
-                            statement.make_nop();
-                        }
+                if let StatementKind::Assign(box (place, _)) = statement.kind {
+                    let place_ty = place.ty(local_decls, tcx).ty;
+                    if !maybe_zst(place_ty) {
+                        continue;
+                    }
+                    let layout = match tcx.layout_of(param_env.and(place_ty)) {
+                        Ok(layout) => layout,
+                        Err(_) => continue,
+                    };
+                    if !layout.is_zst() {
+                        continue;
+                    }
+                    if involves_a_union(place, local_decls, tcx) {
+                        continue;
+                    }
+                    if tcx.consider_optimizing(|| {
+                        format!(
+                            "RemoveZsts - Place: {:?} SourceInfo: {:?}",
+                            place, statement.source_info
+                        )
+                    }) {
+                        statement.make_nop();
                     }
-                    _ => {}
                 }
             }
         }
@@ -69,21 +66,14 @@ fn involves_a_union<'tcx>(
     tcx: TyCtxt<'tcx>,
 ) -> bool {
     let mut place_ty = PlaceTy::from_ty(local_decls[place.local].ty);
-    if is_union(place_ty.ty) {
+    if place_ty.ty.is_union() {
         return true;
     }
     for elem in place.projection {
         place_ty = place_ty.projection_ty(tcx, elem);
-        if is_union(place_ty.ty) {
+        if place_ty.ty.is_union() {
             return true;
         }
     }
     return false;
 }
-
-fn is_union(ty: Ty<'_>) -> bool {
-    match ty.kind() {
-        ty::Adt(def, _) if def.is_union() => true,
-        _ => false,
-    }
-}
diff --git a/compiler/rustc_mir/src/transform/simplify.rs b/compiler/rustc_mir/src/transform/simplify.rs
index 65e2d096b20..7aebca77e6f 100644
--- a/compiler/rustc_mir/src/transform/simplify.rs
+++ b/compiler/rustc_mir/src/transform/simplify.rs
@@ -29,6 +29,7 @@
 
 use crate::transform::MirPass;
 use rustc_index::vec::{Idx, IndexVec};
+use rustc_middle::mir::coverage::*;
 use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
@@ -46,9 +47,9 @@ impl SimplifyCfg {
     }
 }
 
-pub fn simplify_cfg(body: &mut Body<'_>) {
+pub fn simplify_cfg(tcx: TyCtxt<'tcx>, body: &mut Body<'_>) {
     CfgSimplifier::new(body).simplify();
-    remove_dead_blocks(body);
+    remove_dead_blocks(tcx, body);
 
     // FIXME: Should probably be moved into some kind of pass manager
     body.basic_blocks_mut().raw.shrink_to_fit();
@@ -59,9 +60,9 @@ impl<'tcx> MirPass<'tcx> for SimplifyCfg {
         Cow::Borrowed(&self.label)
     }
 
-    fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body.source);
-        simplify_cfg(body);
+        simplify_cfg(tcx, body);
     }
 }
 
@@ -286,7 +287,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
     }
 }
 
-pub fn remove_dead_blocks(body: &mut Body<'_>) {
+pub fn remove_dead_blocks(tcx: TyCtxt<'tcx>, body: &mut Body<'_>) {
     let reachable = traversal::reachable_as_bitset(body);
     let num_blocks = body.basic_blocks().len();
     if num_blocks == reachable.count() {
@@ -306,6 +307,11 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) {
         }
         used_blocks += 1;
     }
+
+    if tcx.sess.instrument_coverage() {
+        save_unreachable_coverage(basic_blocks, used_blocks);
+    }
+
     basic_blocks.raw.truncate(used_blocks);
 
     for block in basic_blocks {
@@ -315,6 +321,75 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) {
     }
 }
 
+/// Some MIR transforms can determine at compile time that a sequences of
+/// statements will never be executed, so they can be dropped from the MIR.
+/// For example, an `if` or `else` block that is guaranteed to never be executed
+/// because its condition can be evaluated at compile time, such as by const
+/// evaluation: `if false { ... }`.
+///
+/// Those statements are bypassed by redirecting paths in the CFG around the
+/// `dead blocks`; but with `-Z instrument-coverage`, the dead blocks usually
+/// include `Coverage` statements representing the Rust source code regions to
+/// be counted at runtime. Without these `Coverage` statements, the regions are
+/// lost, and the Rust source code will show no coverage information.
+///
+/// What we want to show in a coverage report is the dead code with coverage
+/// counts of `0`. To do this, we need to save the code regions, by injecting
+/// `Unreachable` coverage statements. These are non-executable statements whose
+/// code regions are still recorded in the coverage map, representing regions
+/// with `0` executions.
+fn save_unreachable_coverage(
+    basic_blocks: &mut IndexVec<BasicBlock, BasicBlockData<'_>>,
+    first_dead_block: usize,
+) {
+    let has_live_counters = basic_blocks.raw[0..first_dead_block].iter().any(|live_block| {
+        live_block.statements.iter().any(|statement| {
+            if let StatementKind::Coverage(coverage) = &statement.kind {
+                matches!(coverage.kind, CoverageKind::Counter { .. })
+            } else {
+                false
+            }
+        })
+    });
+    if !has_live_counters {
+        // If there are no live `Counter` `Coverage` statements anymore, don't
+        // move dead coverage to the `START_BLOCK`. Just allow the dead
+        // `Coverage` statements to be dropped with the dead blocks.
+        //
+        // The `generator::StateTransform` MIR pass can create atypical
+        // conditions, where all live `Counter`s are dropped from the MIR.
+        //
+        // At least one Counter per function is required by LLVM (and necessary,
+        // to add the `function_hash` to the counter's call to the LLVM
+        // intrinsic `instrprof.increment()`).
+        return;
+    }
+
+    // Retain coverage info for dead blocks, so coverage reports will still
+    // report `0` executions for the uncovered code regions.
+    let mut dropped_coverage = Vec::new();
+    for dead_block in basic_blocks.raw[first_dead_block..].iter() {
+        for statement in dead_block.statements.iter() {
+            if let StatementKind::Coverage(coverage) = &statement.kind {
+                if let Some(code_region) = &coverage.code_region {
+                    dropped_coverage.push((statement.source_info, code_region.clone()));
+                }
+            }
+        }
+    }
+
+    let start_block = &mut basic_blocks[START_BLOCK];
+    for (source_info, code_region) in dropped_coverage {
+        start_block.statements.push(Statement {
+            source_info,
+            kind: StatementKind::Coverage(box Coverage {
+                kind: CoverageKind::Unreachable,
+                code_region: Some(code_region),
+            }),
+        })
+    }
+}
+
 pub struct SimplifyLocals;
 
 impl<'tcx> MirPass<'tcx> for SimplifyLocals {
diff --git a/compiler/rustc_mir/src/transform/simplify_try.rs b/compiler/rustc_mir/src/transform/simplify_try.rs
index 89fddc95c98..dd2ec39c066 100644
--- a/compiler/rustc_mir/src/transform/simplify_try.rs
+++ b/compiler/rustc_mir/src/transform/simplify_try.rs
@@ -558,7 +558,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyBranchSame {
 
         if did_remove_blocks {
             // We have dead blocks now, so remove those.
-            simplify::remove_dead_blocks(body);
+            simplify::remove_dead_blocks(tcx, body);
         }
     }
 }
diff --git a/compiler/rustc_mir/src/transform/unreachable_prop.rs b/compiler/rustc_mir/src/transform/unreachable_prop.rs
index 658c6b6e9db..e7fb6b4f6b4 100644
--- a/compiler/rustc_mir/src/transform/unreachable_prop.rs
+++ b/compiler/rustc_mir/src/transform/unreachable_prop.rs
@@ -60,7 +60,7 @@ impl MirPass<'_> for UnreachablePropagation {
         }
 
         if replaced {
-            simplify::remove_dead_blocks(body);
+            simplify::remove_dead_blocks(tcx, body);
         }
     }
 }
diff --git a/compiler/rustc_mir/src/transform/validate.rs b/compiler/rustc_mir/src/transform/validate.rs
index d009b0b1b23..835789069bb 100644
--- a/compiler/rustc_mir/src/transform/validate.rs
+++ b/compiler/rustc_mir/src/transform/validate.rs
@@ -11,8 +11,9 @@ use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::traversal;
 use rustc_middle::mir::visit::{PlaceContext, Visitor};
 use rustc_middle::mir::{
-    AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceRef,
-    Rvalue, SourceScope, Statement, StatementKind, Terminator, TerminatorKind,
+    AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, PlaceElem,
+    PlaceRef, ProjectionElem, Rvalue, SourceScope, Statement, StatementKind, Terminator,
+    TerminatorKind,
 };
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeFoldable};
@@ -217,6 +218,23 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
         self.super_operand(operand, location);
     }
 
+    fn visit_projection_elem(
+        &mut self,
+        local: Local,
+        proj_base: &[PlaceElem<'tcx>],
+        elem: PlaceElem<'tcx>,
+        context: PlaceContext,
+        location: Location,
+    ) {
+        if let ProjectionElem::Index(index) = elem {
+            let index_ty = self.body.local_decls[index].ty;
+            if index_ty != self.tcx.types.usize {
+                self.fail(location, format!("bad index ({:?} != usize)", index_ty))
+            }
+        }
+        self.super_projection_elem(local, proj_base, elem, context, location);
+    }
+
     fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
         match &statement.kind {
             StatementKind::Assign(box (dest, rvalue)) => {
diff --git a/compiler/rustc_mir/src/util/generic_graph.rs b/compiler/rustc_mir/src/util/generic_graph.rs
index 6ce305a4821..770b52a4d4b 100644
--- a/compiler/rustc_mir/src/util/generic_graph.rs
+++ b/compiler/rustc_mir/src/util/generic_graph.rs
@@ -1,6 +1,5 @@
 use gsgdt::{Edge, Graph, Node, NodeStyle};
 use rustc_hir::def_id::DefId;
-use rustc_index::vec::Idx;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index 2185bd3a5c6..69786c14ee8 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -186,25 +186,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // };
                 // ```
                 //
-                // FIXME(RFC2229, rust#85435): Remove feature gate once diagnostics are
-                // improved and unsafe checking works properly in closure bodies again.
-                if this.tcx.features().capture_disjoint_fields {
-                    for (thir_place, cause, hir_id) in fake_reads.into_iter() {
-                        let place_builder =
-                            unpack!(block = this.as_place_builder(block, &this.thir[*thir_place]));
-
-                        if let Ok(place_builder_resolved) =
-                            place_builder.try_upvars_resolved(this.tcx, this.typeck_results)
-                        {
-                            let mir_place =
-                                place_builder_resolved.into_place(this.tcx, this.typeck_results);
-                            this.cfg.push_fake_read(
-                                block,
-                                this.source_info(this.tcx.hir().span(*hir_id)),
-                                *cause,
-                                mir_place,
-                            );
-                        }
+                for (thir_place, cause, hir_id) in fake_reads.into_iter() {
+                    let place_builder =
+                        unpack!(block = this.as_place_builder(block, &this.thir[*thir_place]));
+
+                    if let Ok(place_builder_resolved) =
+                        place_builder.try_upvars_resolved(this.tcx, this.typeck_results)
+                    {
+                        let mir_place =
+                            place_builder_resolved.into_place(this.tcx, this.typeck_results);
+                        this.cfg.push_fake_read(
+                            block,
+                            this.source_info(this.tcx.hir().span(*hir_id)),
+                            *cause,
+                            mir_place,
+                        );
                     }
                 }
 
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index d1aaabe92ed..2d52577829c 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -166,13 +166,16 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
                     self.requires_unsafe(expr.span, CallToUnsafeFunction);
                 } else if let &ty::FnDef(func_did, _) = self.thir[fun].ty.kind() {
                     // If the called function has target features the calling function hasn't,
-                    // the call requires `unsafe`.
-                    if !self
-                        .tcx
-                        .codegen_fn_attrs(func_did)
-                        .target_features
-                        .iter()
-                        .all(|feature| self.body_target_features.contains(feature))
+                    // the call requires `unsafe`. Don't check this on wasm
+                    // targets, though. For more information on wasm see the
+                    // is_like_wasm check in typeck/src/collect.rs
+                    if !self.tcx.sess.target.options.is_like_wasm
+                        && !self
+                            .tcx
+                            .codegen_fn_attrs(func_did)
+                            .target_features
+                            .iter()
+                            .all(|feature| self.body_target_features.contains(feature))
                     {
                         self.requires_unsafe(expr.span, CallToFunctionWith);
                     }
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index 99b854ff066..d2992f0bf18 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -1,17 +1,14 @@
 //! Construction of MIR from HIR.
 //!
 //! This crate also contains the match exhaustiveness and usefulness checking.
-#![feature(array_windows)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(const_panic)]
 #![feature(control_flow_enum)]
 #![feature(crate_visibility_modifier)]
 #![feature(bool_to_option)]
 #![feature(iter_zip)]
 #![feature(once_cell)]
 #![feature(min_specialization)]
-#![feature(trusted_step)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index da642bb2d28..51df06bd989 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -3,7 +3,6 @@
 #![feature(array_windows)]
 #![feature(crate_visibility_modifier)]
 #![feature(bindings_after_at)]
-#![feature(iter_order_by)]
 #![feature(box_syntax)]
 #![feature(box_patterns)]
 #![recursion_limit = "256"]
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index 35759a396e8..e1d0b84f419 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -342,16 +342,10 @@ impl<'a> Parser<'a> {
 
         // If we support tokens at all
         if let Some(target_tokens) = ret.tokens_mut() {
-            if let Some(target_tokens) = target_tokens {
-                assert!(
-                    !self.capture_cfg,
-                    "Encountered existing tokens with capture_cfg set: {:?}",
-                    target_tokens
-                );
-            } else {
+            if target_tokens.is_none() {
                 // Store se our newly captured tokens into the AST node
                 *target_tokens = Some(tokens.clone());
-            };
+            }
         }
 
         let final_attrs = ret.attrs();
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 56c97b59476..a764cf6bdb0 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -94,17 +94,7 @@ impl<'a> Parser<'a> {
 
     /// Parses an expression, forcing tokens to be collected
     pub fn parse_expr_force_collect(&mut self) -> PResult<'a, P<Expr>> {
-        // If we have outer attributes, then the call to `collect_tokens_trailing_token`
-        // will be made for us.
-        if matches!(self.token.kind, TokenKind::Pound | TokenKind::DocComment(..)) {
-            self.parse_expr()
-        } else {
-            // If we don't have outer attributes, then we need to ensure
-            // that collection happens by using `collect_tokens_no_attrs`.
-            // Expression don't support custom inner attributes, so `parse_expr`
-            // will never try to collect tokens if we don't have outer attributes.
-            self.collect_tokens_no_attrs(|this| this.parse_expr())
-        }
+        self.collect_tokens_no_attrs(|this| this.parse_expr())
     }
 
     pub fn parse_anon_const_expr(&mut self) -> PResult<'a, AnonConst> {
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 4c2bc6ebf31..cd9f84db5e5 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -63,6 +63,7 @@ enum BlockMode {
 
 /// Whether or not we should force collection of tokens for an AST node,
 /// regardless of whether or not it has attributes
+#[derive(Clone, Copy, PartialEq)]
 pub enum ForceCollect {
     Yes,
     No,
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index 0c43e304f1e..30a6b61407f 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -1,5 +1,6 @@
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Nonterminal, NonterminalKind, Token};
+use rustc_ast::AstLike;
 use rustc_ast_pretty::pprust;
 use rustc_errors::PResult;
 use rustc_span::symbol::{kw, Ident};
@@ -102,7 +103,7 @@ impl<'a> Parser<'a> {
         // which requires having captured tokens available. Since we cannot determine
         // in advance whether or not a proc-macro will be (transitively) invoked,
         // we always capture tokens for any `Nonterminal` which needs them.
-        Ok(match kind {
+        let mut nt = match kind {
             NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? {
                 Some(item) => token::NtItem(item),
                 None => {
@@ -169,7 +170,19 @@ impl<'a> Parser<'a> {
                     return Err(self.struct_span_err(self.token.span, msg));
                 }
             }
-        })
+        };
+
+        // If tokens are supported at all, they should be collected.
+        if matches!(nt.tokens_mut(), Some(None)) {
+            panic!(
+                "Missing tokens for nt {:?} at {:?}: {:?}",
+                nt,
+                nt.span(),
+                pprust::nonterminal_to_string(&nt)
+            );
+        }
+
+        Ok(nt)
     }
 }
 
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 9cc600d9ede..953c6915068 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -352,49 +352,59 @@ impl<'a> Parser<'a> {
         debug!("parse_generic_args_with_leading_angle_bracket_recovery: (snapshotting)");
         match self.parse_angle_args() {
             Ok(args) => Ok(args),
-            Err(ref mut e) if is_first_invocation && self.unmatched_angle_bracket_count > 0 => {
-                // Cancel error from being unable to find `>`. We know the error
-                // must have been this due to a non-zero unmatched angle bracket
-                // count.
-                e.cancel();
-
+            Err(mut e) if is_first_invocation && self.unmatched_angle_bracket_count > 0 => {
                 // Swap `self` with our backup of the parser state before attempting to parse
                 // generic arguments.
                 let snapshot = mem::replace(self, snapshot.unwrap());
 
-                debug!(
-                    "parse_generic_args_with_leading_angle_bracket_recovery: (snapshot failure) \
-                     snapshot.count={:?}",
-                    snapshot.unmatched_angle_bracket_count,
-                );
-
                 // Eat the unmatched angle brackets.
-                for _ in 0..snapshot.unmatched_angle_bracket_count {
-                    self.eat_lt();
-                }
-
-                // Make a span over ${unmatched angle bracket count} characters.
-                let span = lo.with_hi(lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count));
-                self.struct_span_err(
-                    span,
-                    &format!(
-                        "unmatched angle bracket{}",
-                        pluralize!(snapshot.unmatched_angle_bracket_count)
-                    ),
-                )
-                .span_suggestion(
-                    span,
-                    &format!(
-                        "remove extra angle bracket{}",
-                        pluralize!(snapshot.unmatched_angle_bracket_count)
-                    ),
-                    String::new(),
-                    Applicability::MachineApplicable,
-                )
-                .emit();
+                let all_angle_brackets = (0..snapshot.unmatched_angle_bracket_count)
+                    .fold(true, |a, _| a && self.eat_lt());
+
+                if !all_angle_brackets {
+                    // If there are other tokens in between the extraneous `<`s, we cannot simply
+                    // suggest to remove them. This check also prevents us from accidentally ending
+                    // up in the middle of a multibyte character (issue #84104).
+                    let _ = mem::replace(self, snapshot);
+                    Err(e)
+                } else {
+                    // Cancel error from being unable to find `>`. We know the error
+                    // must have been this due to a non-zero unmatched angle bracket
+                    // count.
+                    e.cancel();
+
+                    debug!(
+                        "parse_generic_args_with_leading_angle_bracket_recovery: (snapshot failure) \
+                         snapshot.count={:?}",
+                        snapshot.unmatched_angle_bracket_count,
+                    );
+
+                    // Make a span over ${unmatched angle bracket count} characters.
+                    // This is safe because `all_angle_brackets` ensures that there are only `<`s,
+                    // i.e. no multibyte characters, in this range.
+                    let span =
+                        lo.with_hi(lo.lo() + BytePos(snapshot.unmatched_angle_bracket_count));
+                    self.struct_span_err(
+                        span,
+                        &format!(
+                            "unmatched angle bracket{}",
+                            pluralize!(snapshot.unmatched_angle_bracket_count)
+                        ),
+                    )
+                    .span_suggestion(
+                        span,
+                        &format!(
+                            "remove extra angle bracket{}",
+                            pluralize!(snapshot.unmatched_angle_bracket_count)
+                        ),
+                        String::new(),
+                        Applicability::MachineApplicable,
+                    )
+                    .emit();
 
-                // Try again without unmatched angle bracket characters.
-                self.parse_angle_args()
+                    // Try again without unmatched angle bracket characters.
+                    self.parse_angle_args()
+                }
             }
             Err(e) => Err(e),
         }
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index b40eed8c5d1..4f0dcfeb5da 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -73,7 +73,11 @@ impl<'a> Parser<'a> {
             // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something
             // that starts like a path (1 token), but it fact not a path.
             // Also, we avoid stealing syntax from `parse_item_`.
-            self.parse_stmt_path_start(lo, attrs, force_collect)?
+            if force_collect == ForceCollect::Yes {
+                self.collect_tokens_no_attrs(|this| this.parse_stmt_path_start(lo, attrs))
+            } else {
+                self.parse_stmt_path_start(lo, attrs)
+            }?
         } else if let Some(item) =
             self.parse_item_common(attrs.clone(), false, true, |_| true, force_collect)?
         {
@@ -85,7 +89,13 @@ impl<'a> Parser<'a> {
             self.mk_stmt(lo, StmtKind::Empty)
         } else if self.token != token::CloseDelim(token::Brace) {
             // Remainder are line-expr stmts.
-            let e = self.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs))?;
+            let e = if force_collect == ForceCollect::Yes {
+                self.collect_tokens_no_attrs(|this| {
+                    this.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs))
+                })
+            } else {
+                self.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs))
+            }?;
             self.mk_stmt(lo.to(e.span), StmtKind::Expr(e))
         } else {
             self.error_outer_attrs(&attrs.take_for_recovery());
@@ -93,13 +103,8 @@ impl<'a> Parser<'a> {
         }))
     }
 
-    fn parse_stmt_path_start(
-        &mut self,
-        lo: Span,
-        attrs: AttrWrapper,
-        force_collect: ForceCollect,
-    ) -> PResult<'a, Stmt> {
-        let stmt = self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| {
+    fn parse_stmt_path_start(&mut self, lo: Span, attrs: AttrWrapper) -> PResult<'a, Stmt> {
+        let stmt = self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
             let path = this.parse_path(PathStyle::Expr)?;
 
             if this.eat(&token::Not) {
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 89cf2d7876e..de5a5632600 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -334,7 +334,6 @@ impl<'a> Parser<'a> {
         mut bounds: GenericBounds,
         plus: bool,
     ) -> PResult<'a, TyKind> {
-        assert_ne!(self.token, token::Question);
         if plus {
             self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded
             bounds.append(&mut self.parse_generic_bounds(Some(self.prev_token.span))?);
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index bf574bbfbb5..b18ef302962 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -577,7 +577,7 @@ impl CheckAttrVisitor<'tcx> {
         target: Target,
         specified_inline: &mut Option<(bool, Span)>,
     ) -> bool {
-        if target == Target::Use {
+        if target == Target::Use || target == Target::ExternCrate {
             let do_inline = meta.name_or_empty() == sym::inline;
             if let Some((prev_inline, prev_span)) = *specified_inline {
                 if do_inline != prev_inline {
@@ -705,7 +705,7 @@ impl CheckAttrVisitor<'tcx> {
         let mut is_valid = true;
 
         if let Some(list) = attr.meta().and_then(|mi| mi.meta_item_list().map(|l| l.to_vec())) {
-            for meta in list {
+            for meta in &list {
                 if let Some(i_meta) = meta.meta_item() {
                     match i_meta.name_or_empty() {
                         sym::alias
@@ -757,7 +757,6 @@ impl CheckAttrVisitor<'tcx> {
                         | sym::html_no_source
                         | sym::html_playground_url
                         | sym::html_root_url
-                        | sym::include
                         | sym::inline
                         | sym::issue_tracker_base_url
                         | sym::keyword
@@ -792,6 +791,30 @@ impl CheckAttrVisitor<'tcx> {
                                         );
                                         diag.note("`doc(spotlight)` is now a no-op");
                                     }
+                                    if i_meta.has_name(sym::include) {
+                                        if let Some(value) = i_meta.value_str() {
+                                            // if there are multiple attributes, the suggestion would suggest deleting all of them, which is incorrect
+                                            let applicability = if list.len() == 1 {
+                                                Applicability::MachineApplicable
+                                            } else {
+                                                Applicability::MaybeIncorrect
+                                            };
+                                            let inner = if attr.style == AttrStyle::Inner {
+                                                "!"
+                                            } else {
+                                                ""
+                                            };
+                                            diag.span_suggestion(
+                                                attr.meta().unwrap().span,
+                                                "use `doc = include_str!` instead",
+                                                format!(
+                                                    "#{}[doc = include_str!(\"{}\")]",
+                                                    inner, value
+                                                ),
+                                                applicability,
+                                            );
+                                        }
+                                    }
                                     diag.emit();
                                 },
                             );
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 4803148eba9..28633faa205 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -5,13 +5,11 @@
 //! This API is completely unstable and subject to change.
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![feature(const_panic)]
 #![feature(crate_visibility_modifier)]
 #![feature(in_band_lifetimes)]
 #![feature(iter_zip)]
 #![feature(nll)]
 #![feature(min_specialization)]
-#![feature(trusted_step)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index ac81c0261e2..4175fb6925a 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -2,13 +2,9 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(in_band_lifetimes)]
-#![feature(exhaustive_patterns)]
 #![feature(nll)]
 #![feature(min_specialization)]
-#![feature(crate_visibility_modifier)]
-#![feature(once_cell)]
 #![feature(rustc_attrs)]
-#![feature(never_type)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs
index 2517793ecea..95edc1e93a5 100644
--- a/compiler/rustc_query_impl/src/profiling_support.rs
+++ b/compiler/rustc_query_impl/src/profiling_support.rs
@@ -61,7 +61,7 @@ impl<'p, 'c, 'tcx> QueryKeyStringBuilder<'p, 'c, 'tcx> {
 
         match def_key.disambiguated_data.data {
             DefPathData::CrateRoot => {
-                crate_name = self.tcx.original_crate_name(def_id.krate).as_str();
+                crate_name = self.tcx.crate_name(def_id.krate).as_str();
                 name = &*crate_name;
                 dis = "";
                 end_index = 3;
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index cfae65abe83..71e67dfee53 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -44,6 +44,7 @@ rustc_index::newtype_index! {
 
 impl DepNodeIndex {
     pub const INVALID: DepNodeIndex = DepNodeIndex::MAX;
+    pub const SINGLETON_DEPENDENCYLESS_ANON_NODE: DepNodeIndex = DepNodeIndex::from_u32(0);
 }
 
 impl std::convert::From<DepNodeIndex> for QueryInvocationId {
@@ -108,6 +109,7 @@ where
 
 impl<K: DepKind> DepGraph<K> {
     pub fn new(
+        profiler: &SelfProfilerRef,
         prev_graph: SerializedDepGraph<K>,
         prev_work_products: FxHashMap<WorkProductId, WorkProduct>,
         encoder: FileEncoder,
@@ -116,16 +118,23 @@ impl<K: DepKind> DepGraph<K> {
     ) -> DepGraph<K> {
         let prev_graph_node_count = prev_graph.node_count();
 
+        let current =
+            CurrentDepGraph::new(prev_graph_node_count, encoder, record_graph, record_stats);
+
+        // Instantiate a dependy-less node only once for anonymous queries.
+        let _green_node_index = current.intern_new_node(
+            profiler,
+            DepNode { kind: DepKind::NULL, hash: current.anon_id_seed.into() },
+            smallvec![],
+            Fingerprint::ZERO,
+        );
+        debug_assert_eq!(_green_node_index, DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE);
+
         DepGraph {
             data: Some(Lrc::new(DepGraphData {
                 previous_work_products: prev_work_products,
                 dep_node_debug: Default::default(),
-                current: CurrentDepGraph::new(
-                    prev_graph_node_count,
-                    encoder,
-                    record_graph,
-                    record_stats,
-                ),
+                current,
                 emitting_diagnostics: Default::default(),
                 emitting_diagnostics_cond_var: Condvar::new(),
                 previous: prev_graph,
@@ -287,30 +296,47 @@ impl<K: DepKind> DepGraph<K> {
             let task_deps = Lock::new(TaskDeps::default());
             let result = K::with_deps(Some(&task_deps), op);
             let task_deps = task_deps.into_inner();
+            let task_deps = task_deps.reads;
+
+            let dep_node_index = match task_deps.len() {
+                0 => {
+                    // Because the dep-node id of anon nodes is computed from the sets of its
+                    // dependencies we already know what the ID of this dependency-less node is
+                    // going to be (i.e. equal to the precomputed
+                    // `SINGLETON_DEPENDENCYLESS_ANON_NODE`). As a consequence we can skip creating
+                    // a `StableHasher` and sending the node through interning.
+                    DepNodeIndex::SINGLETON_DEPENDENCYLESS_ANON_NODE
+                }
+                1 => {
+                    // When there is only one dependency, don't bother creating a node.
+                    task_deps[0]
+                }
+                _ => {
+                    // The dep node indices are hashed here instead of hashing the dep nodes of the
+                    // dependencies. These indices may refer to different nodes per session, but this isn't
+                    // a problem here because we that ensure the final dep node hash is per session only by
+                    // combining it with the per session random number `anon_id_seed`. This hash only need
+                    // to map the dependencies to a single value on a per session basis.
+                    let mut hasher = StableHasher::new();
+                    task_deps.hash(&mut hasher);
+
+                    let target_dep_node = DepNode {
+                        kind: dep_kind,
+                        // Fingerprint::combine() is faster than sending Fingerprint
+                        // through the StableHasher (at least as long as StableHasher
+                        // is so slow).
+                        hash: data.current.anon_id_seed.combine(hasher.finish()).into(),
+                    };
 
-            // The dep node indices are hashed here instead of hashing the dep nodes of the
-            // dependencies. These indices may refer to different nodes per session, but this isn't
-            // a problem here because we that ensure the final dep node hash is per session only by
-            // combining it with the per session random number `anon_id_seed`. This hash only need
-            // to map the dependencies to a single value on a per session basis.
-            let mut hasher = StableHasher::new();
-            task_deps.reads.hash(&mut hasher);
-
-            let target_dep_node = DepNode {
-                kind: dep_kind,
-                // Fingerprint::combine() is faster than sending Fingerprint
-                // through the StableHasher (at least as long as StableHasher
-                // is so slow).
-                hash: data.current.anon_id_seed.combine(hasher.finish()).into(),
+                    data.current.intern_new_node(
+                        cx.profiler(),
+                        target_dep_node,
+                        task_deps,
+                        Fingerprint::ZERO,
+                    )
+                }
             };
 
-            let dep_node_index = data.current.intern_new_node(
-                cx.profiler(),
-                target_dep_node,
-                task_deps.reads,
-                Fingerprint::ZERO,
-            );
-
             (result, dep_node_index)
         } else {
             (op(), self.next_virtual_depnode_index())
diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs
index 6a84a28be66..73c00fc49ba 100644
--- a/compiler/rustc_query_system/src/dep_graph/serialized.rs
+++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs
@@ -122,21 +122,21 @@ impl<'a, K: DepKind + Decodable<opaque::Decoder<'a>>> Decodable<opaque::Decoder<
         let mut edge_list_data = Vec::with_capacity(edge_count);
 
         for _index in 0..node_count {
-            d.read_struct("NodeInfo", 3, |d| {
-                let dep_node: DepNode<K> = d.read_struct_field("node", 0, Decodable::decode)?;
+            d.read_struct(|d| {
+                let dep_node: DepNode<K> = d.read_struct_field("node", Decodable::decode)?;
                 let _i: SerializedDepNodeIndex = nodes.push(dep_node);
                 debug_assert_eq!(_i.index(), _index);
 
                 let fingerprint: Fingerprint =
-                    d.read_struct_field("fingerprint", 1, Decodable::decode)?;
+                    d.read_struct_field("fingerprint", Decodable::decode)?;
                 let _i: SerializedDepNodeIndex = fingerprints.push(fingerprint);
                 debug_assert_eq!(_i.index(), _index);
 
-                d.read_struct_field("edges", 2, |d| {
+                d.read_struct_field("edges", |d| {
                     d.read_seq(|d, len| {
                         let start = edge_list_data.len().try_into().unwrap();
-                        for e in 0..len {
-                            let edge = d.read_seq_elt(e, Decodable::decode)?;
+                        for _ in 0..len {
+                            let edge = d.read_seq_elt(Decodable::decode)?;
                             edge_list_data.push(edge);
                         }
                         let end = edge_list_data.len().try_into().unwrap();
diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs
index 7df3804c986..0d4fb34265c 100644
--- a/compiler/rustc_query_system/src/lib.rs
+++ b/compiler/rustc_query_system/src/lib.rs
@@ -1,12 +1,8 @@
 #![feature(bool_to_option)]
-#![feature(const_panic)]
 #![feature(core_intrinsics)]
-#![feature(drain_filter)]
 #![feature(hash_raw_entry)]
 #![feature(iter_zip)]
 #![feature(min_specialization)]
-#![feature(stmt_expr_attributes)]
-#![feature(trusted_step)]
 
 #[macro_use]
 extern crate tracing;
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index a1eafd65d64..03d94f43897 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -450,7 +450,7 @@ impl<'a> Resolver<'a> {
                 err.span_label(shadowed_binding_span, msg);
                 err
             }
-            ResolutionError::ForwardDeclaredTyParam => {
+            ResolutionError::ForwardDeclaredGenericParam => {
                 let mut err = struct_span_err!(
                     self.session,
                     span,
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 662d39f6ef3..408d9b23921 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -1959,7 +1959,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 if ns == ValueNS {
                     let item_name = path.last().unwrap().ident;
                     let traits = self.traits_in_scope(item_name, ns);
-                    self.r.trait_map.insert(id, traits);
+                    self.r.trait_map.as_mut().unwrap().insert(id, traits);
                 }
 
                 if PrimTy::from_name(path[0].ident.name).is_some() {
@@ -2435,12 +2435,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 // the field name so that we can do some nice error reporting
                 // later on in typeck.
                 let traits = self.traits_in_scope(ident, ValueNS);
-                self.r.trait_map.insert(expr.id, traits);
+                self.r.trait_map.as_mut().unwrap().insert(expr.id, traits);
             }
             ExprKind::MethodCall(ref segment, ..) => {
                 debug!("(recording candidate traits for expr) recording traits for {}", expr.id);
                 let traits = self.traits_in_scope(segment.ident, ValueNS);
-                self.r.trait_map.insert(expr.id, traits);
+                self.r.trait_map.as_mut().unwrap().insert(expr.id, traits);
             }
             _ => {
                 // Nothing to do.
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index efa5d7e7b11..ca7cdc4caf5 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -1841,14 +1841,6 @@ fn object_lifetime_defaults_for_item(
 }
 
 impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
-    // FIXME(#37666) this works around a limitation in the region inferencer
-    fn hack<F>(&mut self, f: F)
-    where
-        F: for<'b> FnOnce(&mut LifetimeContext<'b, 'tcx>),
-    {
-        f(self)
-    }
-
     fn with<F>(&mut self, wrap_scope: Scope<'_>, f: F)
     where
         F: for<'b> FnOnce(ScopeRef<'_>, &mut LifetimeContext<'b, 'tcx>),
@@ -2252,7 +2244,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
         };
         self.with(scope, move |old_scope, this| {
             this.check_lifetime_params(old_scope, &generics.params);
-            this.hack(walk); // FIXME(#37666) workaround in place of `walk(this)`
+            walk(this);
         });
     }
 
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 29d4271c475..fd9b897111a 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -242,7 +242,7 @@ enum ResolutionError<'a> {
         shadowed_binding_span: Span,
     },
     /// Error E0128: generic parameters with a default cannot use forward-declared identifiers.
-    ForwardDeclaredTyParam, // FIXME(const_generics_defaults)
+    ForwardDeclaredGenericParam,
     /// ERROR E0770: the type of const parameters must not depend on other generic parameters.
     ParamInTyOfConstParam(Symbol),
     /// generic parameters must not be used inside const evaluations.
@@ -909,7 +909,7 @@ pub struct Resolver<'a> {
     /// `CrateNum` resolutions of `extern crate` items.
     extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
     export_map: ExportMap<LocalDefId>,
-    trait_map: NodeMap<Vec<TraitCandidate>>,
+    trait_map: Option<NodeMap<Vec<TraitCandidate>>>,
 
     /// A map from nodes to anonymous modules.
     /// Anonymous modules are pseudo-modules that are implicitly created around items
@@ -1138,8 +1138,8 @@ impl ResolverAstLowering for Resolver<'_> {
         self.next_node_id()
     }
 
-    fn trait_map(&self) -> &NodeMap<Vec<TraitCandidate>> {
-        &self.trait_map
+    fn take_trait_map(&mut self) -> NodeMap<Vec<TraitCandidate>> {
+        std::mem::replace(&mut self.trait_map, None).unwrap()
     }
 
     fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {
@@ -1222,7 +1222,7 @@ impl<'a> Resolver<'a> {
         let mut module_map = FxHashMap::default();
         module_map.insert(root_local_def_id, graph_root);
 
-        let definitions = Definitions::new(session.local_stable_crate_id());
+        let definitions = Definitions::new(crate_name, session.local_crate_disambiguator());
         let root = definitions.get_root_def();
 
         let mut visibilities = FxHashMap::default();
@@ -1286,7 +1286,7 @@ impl<'a> Resolver<'a> {
             label_res_map: Default::default(),
             extern_crate_map: Default::default(),
             export_map: FxHashMap::default(),
-            trait_map: Default::default(),
+            trait_map: Some(NodeMap::default()),
             underscore_disambiguator: 0,
             empty_module,
             module_map,
@@ -2608,7 +2608,7 @@ impl<'a> Resolver<'a> {
                 let res_error = if rib_ident.name == kw::SelfUpper {
                     ResolutionError::SelfInTyParamDefault
                 } else {
-                    ResolutionError::ForwardDeclaredTyParam
+                    ResolutionError::ForwardDeclaredGenericParam
                 };
                 self.report_error(span, res_error);
             }
diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs
index 842f7f9deee..54b6a121585 100644
--- a/compiler/rustc_save_analysis/src/dump_visitor.rs
+++ b/compiler/rustc_save_analysis/src/dump_visitor.rs
@@ -142,7 +142,12 @@ impl<'tcx> DumpVisitor<'tcx> {
         let data = CratePreludeData {
             crate_id: GlobalCrateId {
                 name: name.into(),
-                disambiguator: (self.tcx.sess.local_stable_crate_id().to_u64(), 0),
+                disambiguator: self
+                    .tcx
+                    .sess
+                    .local_crate_disambiguator()
+                    .to_fingerprint()
+                    .as_value(),
             },
             crate_root: crate_root.unwrap_or_else(|| "<no source>".to_owned()),
             external_crates: self.save_ctxt.get_external_crates(),
diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs
index bdffdd5311e..297383bfed1 100644
--- a/compiler/rustc_save_analysis/src/lib.rs
+++ b/compiler/rustc_save_analysis/src/lib.rs
@@ -127,10 +127,7 @@ impl<'tcx> SaveContext<'tcx> {
                 num: n.as_u32(),
                 id: GlobalCrateId {
                     name: self.tcx.crate_name(n).to_string(),
-                    disambiguator: (
-                        self.tcx.def_path_hash(n.as_def_id()).stable_crate_id().to_u64(),
-                        0,
-                    ),
+                    disambiguator: self.tcx.crate_disambiguator(n).to_fingerprint().as_value(),
                 },
             });
         }
@@ -826,20 +823,6 @@ impl<'tcx> SaveContext<'tcx> {
                 // FIXME: Should save-analysis beautify doc strings itself or leave it to users?
                 result.push_str(&beautify_doc_string(val).as_str());
                 result.push('\n');
-            } else if self.tcx.sess.check_name(attr, sym::doc) {
-                if let Some(meta_list) = attr.meta_item_list() {
-                    meta_list
-                        .into_iter()
-                        .filter(|it| it.has_name(sym::include))
-                        .filter_map(|it| it.meta_item_list().map(|l| l.to_owned()))
-                        .flat_map(|it| it)
-                        .filter(|meta| meta.has_name(sym::contents))
-                        .filter_map(|meta| meta.value_str())
-                        .for_each(|val| {
-                            result.push_str(&val.as_str());
-                            result.push('\n');
-                        });
-                }
             }
         }
 
diff --git a/compiler/rustc_serialize/src/collection_impls.rs b/compiler/rustc_serialize/src/collection_impls.rs
index ae6d27e037b..80a7f650188 100644
--- a/compiler/rustc_serialize/src/collection_impls.rs
+++ b/compiler/rustc_serialize/src/collection_impls.rs
@@ -21,8 +21,8 @@ impl<D: Decoder, A: Array<Item: Decodable<D>>> Decodable<D> for SmallVec<A> {
         d.read_seq(|d, len| {
             let mut vec = SmallVec::with_capacity(len);
             // FIXME(#48994) - could just be collected into a Result<SmallVec, D::Error>
-            for i in 0..len {
-                vec.push(d.read_seq_elt(i, |d| Decodable::decode(d))?);
+            for _ in 0..len {
+                vec.push(d.read_seq_elt(|d| Decodable::decode(d))?);
             }
             Ok(vec)
         })
@@ -44,8 +44,8 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for LinkedList<T> {
     fn decode(d: &mut D) -> Result<LinkedList<T>, D::Error> {
         d.read_seq(|d, len| {
             let mut list = LinkedList::new();
-            for i in 0..len {
-                list.push_back(d.read_seq_elt(i, |d| Decodable::decode(d))?);
+            for _ in 0..len {
+                list.push_back(d.read_seq_elt(|d| Decodable::decode(d))?);
             }
             Ok(list)
         })
@@ -67,8 +67,8 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for VecDeque<T> {
     fn decode(d: &mut D) -> Result<VecDeque<T>, D::Error> {
         d.read_seq(|d, len| {
             let mut deque: VecDeque<T> = VecDeque::with_capacity(len);
-            for i in 0..len {
-                deque.push_back(d.read_seq_elt(i, |d| Decodable::decode(d))?);
+            for _ in 0..len {
+                deque.push_back(d.read_seq_elt(|d| Decodable::decode(d))?);
             }
             Ok(deque)
         })
@@ -84,7 +84,7 @@ where
         e.emit_map(self.len(), |e| {
             for (i, (key, val)) in self.iter().enumerate() {
                 e.emit_map_elt_key(i, |e| key.encode(e))?;
-                e.emit_map_elt_val(i, |e| val.encode(e))?;
+                e.emit_map_elt_val(|e| val.encode(e))?;
             }
             Ok(())
         })
@@ -99,9 +99,9 @@ where
     fn decode(d: &mut D) -> Result<BTreeMap<K, V>, D::Error> {
         d.read_map(|d, len| {
             let mut map = BTreeMap::new();
-            for i in 0..len {
-                let key = d.read_map_elt_key(i, |d| Decodable::decode(d))?;
-                let val = d.read_map_elt_val(i, |d| Decodable::decode(d))?;
+            for _ in 0..len {
+                let key = d.read_map_elt_key(|d| Decodable::decode(d))?;
+                let val = d.read_map_elt_val(|d| Decodable::decode(d))?;
                 map.insert(key, val);
             }
             Ok(map)
@@ -130,8 +130,8 @@ where
     fn decode(d: &mut D) -> Result<BTreeSet<T>, D::Error> {
         d.read_seq(|d, len| {
             let mut set = BTreeSet::new();
-            for i in 0..len {
-                set.insert(d.read_seq_elt(i, |d| Decodable::decode(d))?);
+            for _ in 0..len {
+                set.insert(d.read_seq_elt(|d| Decodable::decode(d))?);
             }
             Ok(set)
         })
@@ -148,7 +148,7 @@ where
         e.emit_map(self.len(), |e| {
             for (i, (key, val)) in self.iter().enumerate() {
                 e.emit_map_elt_key(i, |e| key.encode(e))?;
-                e.emit_map_elt_val(i, |e| val.encode(e))?;
+                e.emit_map_elt_val(|e| val.encode(e))?;
             }
             Ok(())
         })
@@ -165,9 +165,9 @@ where
         d.read_map(|d, len| {
             let state = Default::default();
             let mut map = HashMap::with_capacity_and_hasher(len, state);
-            for i in 0..len {
-                let key = d.read_map_elt_key(i, |d| Decodable::decode(d))?;
-                let val = d.read_map_elt_val(i, |d| Decodable::decode(d))?;
+            for _ in 0..len {
+                let key = d.read_map_elt_key(|d| Decodable::decode(d))?;
+                let val = d.read_map_elt_val(|d| Decodable::decode(d))?;
                 map.insert(key, val);
             }
             Ok(map)
@@ -209,8 +209,8 @@ where
         d.read_seq(|d, len| {
             let state = Default::default();
             let mut set = HashSet::with_capacity_and_hasher(len, state);
-            for i in 0..len {
-                set.insert(d.read_seq_elt(i, |d| Decodable::decode(d))?);
+            for _ in 0..len {
+                set.insert(d.read_seq_elt(|d| Decodable::decode(d))?);
             }
             Ok(set)
         })
@@ -227,7 +227,7 @@ where
         e.emit_map(self.len(), |e| {
             for (i, (key, val)) in self.iter().enumerate() {
                 e.emit_map_elt_key(i, |e| key.encode(e))?;
-                e.emit_map_elt_val(i, |e| val.encode(e))?;
+                e.emit_map_elt_val(|e| val.encode(e))?;
             }
             Ok(())
         })
@@ -244,9 +244,9 @@ where
         d.read_map(|d, len| {
             let state = Default::default();
             let mut map = indexmap::IndexMap::with_capacity_and_hasher(len, state);
-            for i in 0..len {
-                let key = d.read_map_elt_key(i, |d| Decodable::decode(d))?;
-                let val = d.read_map_elt_val(i, |d| Decodable::decode(d))?;
+            for _ in 0..len {
+                let key = d.read_map_elt_key(|d| Decodable::decode(d))?;
+                let val = d.read_map_elt_val(|d| Decodable::decode(d))?;
                 map.insert(key, val);
             }
             Ok(map)
@@ -278,8 +278,8 @@ where
         d.read_seq(|d, len| {
             let state = Default::default();
             let mut set = indexmap::IndexSet::with_capacity_and_hasher(len, state);
-            for i in 0..len {
-                set.insert(d.read_seq_elt(i, |d| Decodable::decode(d))?);
+            for _ in 0..len {
+                set.insert(d.read_seq_elt(|d| Decodable::decode(d))?);
             }
             Ok(set)
         })
diff --git a/compiler/rustc_serialize/src/json.rs b/compiler/rustc_serialize/src/json.rs
index 78a102c5c23..b79adb6f7bc 100644
--- a/compiler/rustc_serialize/src/json.rs
+++ b/compiler/rustc_serialize/src/json.rs
@@ -560,7 +560,7 @@ impl<'a> crate::Encoder for Encoder<'a> {
         Ok(())
     }
 
-    fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult
+    fn emit_enum<F>(&mut self, f: F) -> EncodeResult
     where
         F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
     {
@@ -589,46 +589,20 @@ impl<'a> crate::Encoder for Encoder<'a> {
         }
     }
 
-    fn emit_enum_variant_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult
+    fn emit_enum_variant_arg<F>(&mut self, first: bool, f: F) -> EncodeResult
     where
         F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
     {
         if self.is_emitting_map_key {
             return Err(EncoderError::BadHashmapKey);
         }
-        if idx != 0 {
+        if !first {
             write!(self.writer, ",")?;
         }
         f(self)
     }
 
-    fn emit_enum_struct_variant<F>(
-        &mut self,
-        name: &str,
-        id: usize,
-        cnt: usize,
-        f: F,
-    ) -> EncodeResult
-    where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
-    {
-        if self.is_emitting_map_key {
-            return Err(EncoderError::BadHashmapKey);
-        }
-        self.emit_enum_variant(name, id, cnt, f)
-    }
-
-    fn emit_enum_struct_variant_field<F>(&mut self, _: &str, idx: usize, f: F) -> EncodeResult
-    where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
-    {
-        if self.is_emitting_map_key {
-            return Err(EncoderError::BadHashmapKey);
-        }
-        self.emit_enum_variant_arg(idx, f)
-    }
-
-    fn emit_struct<F>(&mut self, _: &str, _: usize, f: F) -> EncodeResult
+    fn emit_struct<F>(&mut self, _: bool, f: F) -> EncodeResult
     where
         F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
     {
@@ -641,14 +615,14 @@ impl<'a> crate::Encoder for Encoder<'a> {
         Ok(())
     }
 
-    fn emit_struct_field<F>(&mut self, name: &str, idx: usize, f: F) -> EncodeResult
+    fn emit_struct_field<F>(&mut self, name: &str, first: bool, f: F) -> EncodeResult
     where
         F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
     {
         if self.is_emitting_map_key {
             return Err(EncoderError::BadHashmapKey);
         }
-        if idx != 0 {
+        if !first {
             write!(self.writer, ",")?;
         }
         escape_str(self.writer, name)?;
@@ -675,25 +649,6 @@ impl<'a> crate::Encoder for Encoder<'a> {
         self.emit_seq_elt(idx, f)
     }
 
-    fn emit_tuple_struct<F>(&mut self, _name: &str, len: usize, f: F) -> EncodeResult
-    where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
-    {
-        if self.is_emitting_map_key {
-            return Err(EncoderError::BadHashmapKey);
-        }
-        self.emit_seq(len, f)
-    }
-    fn emit_tuple_struct_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult
-    where
-        F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
-    {
-        if self.is_emitting_map_key {
-            return Err(EncoderError::BadHashmapKey);
-        }
-        self.emit_seq_elt(idx, f)
-    }
-
     fn emit_option<F>(&mut self, f: F) -> EncodeResult
     where
         F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
@@ -774,7 +729,7 @@ impl<'a> crate::Encoder for Encoder<'a> {
         Ok(())
     }
 
-    fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> EncodeResult
+    fn emit_map_elt_val<F>(&mut self, f: F) -> EncodeResult
     where
         F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
     {
@@ -892,7 +847,7 @@ impl<'a> crate::Encoder for PrettyEncoder<'a> {
         Ok(())
     }
 
-    fn emit_enum<F>(&mut self, _name: &str, f: F) -> EncodeResult
+    fn emit_enum<F>(&mut self, f: F) -> EncodeResult
     where
         F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
     {
@@ -930,54 +885,28 @@ impl<'a> crate::Encoder for PrettyEncoder<'a> {
         }
     }
 
-    fn emit_enum_variant_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult
+    fn emit_enum_variant_arg<F>(&mut self, first: bool, f: F) -> EncodeResult
     where
         F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
     {
         if self.is_emitting_map_key {
             return Err(EncoderError::BadHashmapKey);
         }
-        if idx != 0 {
+        if !first {
             writeln!(self.writer, ",")?;
         }
         spaces(self.writer, self.curr_indent)?;
         f(self)
     }
 
-    fn emit_enum_struct_variant<F>(
-        &mut self,
-        name: &str,
-        id: usize,
-        cnt: usize,
-        f: F,
-    ) -> EncodeResult
+    fn emit_struct<F>(&mut self, no_fields: bool, f: F) -> EncodeResult
     where
         F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
     {
         if self.is_emitting_map_key {
             return Err(EncoderError::BadHashmapKey);
         }
-        self.emit_enum_variant(name, id, cnt, f)
-    }
-
-    fn emit_enum_struct_variant_field<F>(&mut self, _: &str, idx: usize, f: F) -> EncodeResult
-    where
-        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
-    {
-        if self.is_emitting_map_key {
-            return Err(EncoderError::BadHashmapKey);
-        }
-        self.emit_enum_variant_arg(idx, f)
-    }
-
-    fn emit_struct<F>(&mut self, _: &str, len: usize, f: F) -> EncodeResult
-    where
-        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
-    {
-        if self.is_emitting_map_key {
-            return Err(EncoderError::BadHashmapKey);
-        }
-        if len == 0 {
+        if no_fields {
             write!(self.writer, "{{}}")?;
         } else {
             write!(self.writer, "{{")?;
@@ -991,14 +920,14 @@ impl<'a> crate::Encoder for PrettyEncoder<'a> {
         Ok(())
     }
 
-    fn emit_struct_field<F>(&mut self, name: &str, idx: usize, f: F) -> EncodeResult
+    fn emit_struct_field<F>(&mut self, name: &str, first: bool, f: F) -> EncodeResult
     where
         F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
     {
         if self.is_emitting_map_key {
             return Err(EncoderError::BadHashmapKey);
         }
-        if idx == 0 {
+        if first {
             writeln!(self.writer)?;
         } else {
             writeln!(self.writer, ",")?;
@@ -1028,25 +957,6 @@ impl<'a> crate::Encoder for PrettyEncoder<'a> {
         self.emit_seq_elt(idx, f)
     }
 
-    fn emit_tuple_struct<F>(&mut self, _: &str, len: usize, f: F) -> EncodeResult
-    where
-        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
-    {
-        if self.is_emitting_map_key {
-            return Err(EncoderError::BadHashmapKey);
-        }
-        self.emit_seq(len, f)
-    }
-    fn emit_tuple_struct_arg<F>(&mut self, idx: usize, f: F) -> EncodeResult
-    where
-        F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
-    {
-        if self.is_emitting_map_key {
-            return Err(EncoderError::BadHashmapKey);
-        }
-        self.emit_seq_elt(idx, f)
-    }
-
     fn emit_option<F>(&mut self, f: F) -> EncodeResult
     where
         F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
@@ -1149,7 +1059,7 @@ impl<'a> crate::Encoder for PrettyEncoder<'a> {
         Ok(())
     }
 
-    fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> EncodeResult
+    fn emit_map_elt_val<F>(&mut self, f: F) -> EncodeResult
     where
         F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,
     {
@@ -2373,7 +2283,7 @@ impl crate::Decoder for Decoder {
         Ok(())
     }
 
-    fn read_enum<T, F>(&mut self, _name: &str, f: F) -> DecodeResult<T>
+    fn read_enum<T, F>(&mut self, f: F) -> DecodeResult<T>
     where
         F: FnOnce(&mut Decoder) -> DecodeResult<T>,
     {
@@ -2410,33 +2320,14 @@ impl crate::Decoder for Decoder {
         f(self, idx)
     }
 
-    fn read_enum_variant_arg<T, F>(&mut self, _idx: usize, f: F) -> DecodeResult<T>
+    fn read_enum_variant_arg<T, F>(&mut self, f: F) -> DecodeResult<T>
     where
         F: FnOnce(&mut Decoder) -> DecodeResult<T>,
     {
         f(self)
     }
 
-    fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F) -> DecodeResult<T>
-    where
-        F: FnMut(&mut Decoder, usize) -> DecodeResult<T>,
-    {
-        self.read_enum_variant(names, f)
-    }
-
-    fn read_enum_struct_variant_field<T, F>(
-        &mut self,
-        _name: &str,
-        idx: usize,
-        f: F,
-    ) -> DecodeResult<T>
-    where
-        F: FnOnce(&mut Decoder) -> DecodeResult<T>,
-    {
-        self.read_enum_variant_arg(idx, f)
-    }
-
-    fn read_struct<T, F>(&mut self, _name: &str, _len: usize, f: F) -> DecodeResult<T>
+    fn read_struct<T, F>(&mut self, f: F) -> DecodeResult<T>
     where
         F: FnOnce(&mut Decoder) -> DecodeResult<T>,
     {
@@ -2445,7 +2336,7 @@ impl crate::Decoder for Decoder {
         Ok(value)
     }
 
-    fn read_struct_field<T, F>(&mut self, name: &str, _idx: usize, f: F) -> DecodeResult<T>
+    fn read_struct_field<T, F>(&mut self, name: &str, f: F) -> DecodeResult<T>
     where
         F: FnOnce(&mut Decoder) -> DecodeResult<T>,
     {
@@ -2483,25 +2374,11 @@ impl crate::Decoder for Decoder {
         })
     }
 
-    fn read_tuple_arg<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T>
-    where
-        F: FnOnce(&mut Decoder) -> DecodeResult<T>,
-    {
-        self.read_seq_elt(idx, f)
-    }
-
-    fn read_tuple_struct<T, F>(&mut self, _name: &str, len: usize, f: F) -> DecodeResult<T>
-    where
-        F: FnOnce(&mut Decoder) -> DecodeResult<T>,
-    {
-        self.read_tuple(len, f)
-    }
-
-    fn read_tuple_struct_arg<T, F>(&mut self, idx: usize, f: F) -> DecodeResult<T>
+    fn read_tuple_arg<T, F>(&mut self, f: F) -> DecodeResult<T>
     where
         F: FnOnce(&mut Decoder) -> DecodeResult<T>,
     {
-        self.read_tuple_arg(idx, f)
+        self.read_seq_elt(f)
     }
 
     fn read_option<T, F>(&mut self, mut f: F) -> DecodeResult<T>
@@ -2527,7 +2404,7 @@ impl crate::Decoder for Decoder {
         f(self, len)
     }
 
-    fn read_seq_elt<T, F>(&mut self, _idx: usize, f: F) -> DecodeResult<T>
+    fn read_seq_elt<T, F>(&mut self, f: F) -> DecodeResult<T>
     where
         F: FnOnce(&mut Decoder) -> DecodeResult<T>,
     {
@@ -2547,14 +2424,14 @@ impl crate::Decoder for Decoder {
         f(self, len)
     }
 
-    fn read_map_elt_key<T, F>(&mut self, _idx: usize, f: F) -> DecodeResult<T>
+    fn read_map_elt_key<T, F>(&mut self, f: F) -> DecodeResult<T>
     where
         F: FnOnce(&mut Decoder) -> DecodeResult<T>,
     {
         f(self)
     }
 
-    fn read_map_elt_val<T, F>(&mut self, _idx: usize, f: F) -> DecodeResult<T>
+    fn read_map_elt_val<T, F>(&mut self, f: F) -> DecodeResult<T>
     where
         F: FnOnce(&mut Decoder) -> DecodeResult<T>,
     {
diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs
index cf5a9118275..c79786a839f 100644
--- a/compiler/rustc_serialize/src/lib.rs
+++ b/compiler/rustc_serialize/src/lib.rs
@@ -14,10 +14,7 @@ Core encoding and decoding interfaces.
 #![feature(nll)]
 #![feature(associated_type_bounds)]
 #![feature(min_specialization)]
-#![feature(vec_spare_capacity)]
 #![feature(core_intrinsics)]
-#![feature(maybe_uninit_array_assume_init)]
-#![feature(maybe_uninit_uninit_array)]
 #![feature(maybe_uninit_slice)]
 #![feature(new_uninit)]
 #![cfg_attr(test, feature(test))]
diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs
index d3e5f306970..bb3c537ef19 100644
--- a/compiler/rustc_serialize/src/serialize.rs
+++ b/compiler/rustc_serialize/src/serialize.rs
@@ -37,7 +37,7 @@ pub trait Encoder {
 
     // Compound types:
     #[inline]
-    fn emit_enum<F>(&mut self, _name: &str, f: F) -> Result<(), Self::Error>
+    fn emit_enum<F>(&mut self, f: F) -> Result<(), Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<(), Self::Error>,
     {
@@ -59,40 +59,15 @@ pub trait Encoder {
     }
 
     #[inline]
-    fn emit_enum_variant_arg<F>(&mut self, _a_idx: usize, f: F) -> Result<(), Self::Error>
+    fn emit_enum_variant_arg<F>(&mut self, _first: bool, f: F) -> Result<(), Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<(), Self::Error>,
     {
         f(self)
     }
 
-    fn emit_enum_struct_variant<F>(
-        &mut self,
-        v_name: &str,
-        v_id: usize,
-        len: usize,
-        f: F,
-    ) -> Result<(), Self::Error>
-    where
-        F: FnOnce(&mut Self) -> Result<(), Self::Error>,
-    {
-        self.emit_enum_variant(v_name, v_id, len, f)
-    }
-
-    fn emit_enum_struct_variant_field<F>(
-        &mut self,
-        _f_name: &str,
-        f_idx: usize,
-        f: F,
-    ) -> Result<(), Self::Error>
-    where
-        F: FnOnce(&mut Self) -> Result<(), Self::Error>,
-    {
-        self.emit_enum_variant_arg(f_idx, f)
-    }
-
     #[inline]
-    fn emit_struct<F>(&mut self, _name: &str, _len: usize, f: F) -> Result<(), Self::Error>
+    fn emit_struct<F>(&mut self, _no_fields: bool, f: F) -> Result<(), Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<(), Self::Error>,
     {
@@ -100,12 +75,7 @@ pub trait Encoder {
     }
 
     #[inline]
-    fn emit_struct_field<F>(
-        &mut self,
-        _f_name: &str,
-        _f_idx: usize,
-        f: F,
-    ) -> Result<(), Self::Error>
+    fn emit_struct_field<F>(&mut self, _f_name: &str, _first: bool, f: F) -> Result<(), Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<(), Self::Error>,
     {
@@ -128,26 +98,12 @@ pub trait Encoder {
         f(self)
     }
 
-    fn emit_tuple_struct<F>(&mut self, _name: &str, len: usize, f: F) -> Result<(), Self::Error>
-    where
-        F: FnOnce(&mut Self) -> Result<(), Self::Error>,
-    {
-        self.emit_tuple(len, f)
-    }
-
-    fn emit_tuple_struct_arg<F>(&mut self, f_idx: usize, f: F) -> Result<(), Self::Error>
-    where
-        F: FnOnce(&mut Self) -> Result<(), Self::Error>,
-    {
-        self.emit_tuple_arg(f_idx, f)
-    }
-
     // Specialized types:
     fn emit_option<F>(&mut self, f: F) -> Result<(), Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<(), Self::Error>,
     {
-        self.emit_enum("Option", f)
+        self.emit_enum(f)
     }
 
     #[inline]
@@ -195,7 +151,7 @@ pub trait Encoder {
     }
 
     #[inline]
-    fn emit_map_elt_val<F>(&mut self, _idx: usize, f: F) -> Result<(), Self::Error>
+    fn emit_map_elt_val<F>(&mut self, f: F) -> Result<(), Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<(), Self::Error>,
     {
@@ -229,7 +185,7 @@ pub trait Decoder {
 
     // Compound types:
     #[inline]
-    fn read_enum<T, F>(&mut self, _name: &str, f: F) -> Result<T, Self::Error>
+    fn read_enum<T, F>(&mut self, f: F) -> Result<T, Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<T, Self::Error>,
     {
@@ -246,34 +202,15 @@ pub trait Decoder {
     }
 
     #[inline]
-    fn read_enum_variant_arg<T, F>(&mut self, _a_idx: usize, f: F) -> Result<T, Self::Error>
+    fn read_enum_variant_arg<T, F>(&mut self, f: F) -> Result<T, Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<T, Self::Error>,
     {
         f(self)
     }
 
-    fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F) -> Result<T, Self::Error>
-    where
-        F: FnMut(&mut Self, usize) -> Result<T, Self::Error>,
-    {
-        self.read_enum_variant(names, f)
-    }
-
-    fn read_enum_struct_variant_field<T, F>(
-        &mut self,
-        _f_name: &str,
-        f_idx: usize,
-        f: F,
-    ) -> Result<T, Self::Error>
-    where
-        F: FnOnce(&mut Self) -> Result<T, Self::Error>,
-    {
-        self.read_enum_variant_arg(f_idx, f)
-    }
-
     #[inline]
-    fn read_struct<T, F>(&mut self, _s_name: &str, _len: usize, f: F) -> Result<T, Self::Error>
+    fn read_struct<T, F>(&mut self, f: F) -> Result<T, Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<T, Self::Error>,
     {
@@ -281,12 +218,7 @@ pub trait Decoder {
     }
 
     #[inline]
-    fn read_struct_field<T, F>(
-        &mut self,
-        _f_name: &str,
-        _f_idx: usize,
-        f: F,
-    ) -> Result<T, Self::Error>
+    fn read_struct_field<T, F>(&mut self, _f_name: &str, f: F) -> Result<T, Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<T, Self::Error>,
     {
@@ -302,33 +234,19 @@ pub trait Decoder {
     }
 
     #[inline]
-    fn read_tuple_arg<T, F>(&mut self, _a_idx: usize, f: F) -> Result<T, Self::Error>
+    fn read_tuple_arg<T, F>(&mut self, f: F) -> Result<T, Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<T, Self::Error>,
     {
         f(self)
     }
 
-    fn read_tuple_struct<T, F>(&mut self, _s_name: &str, len: usize, f: F) -> Result<T, Self::Error>
-    where
-        F: FnOnce(&mut Self) -> Result<T, Self::Error>,
-    {
-        self.read_tuple(len, f)
-    }
-
-    fn read_tuple_struct_arg<T, F>(&mut self, a_idx: usize, f: F) -> Result<T, Self::Error>
-    where
-        F: FnOnce(&mut Self) -> Result<T, Self::Error>,
-    {
-        self.read_tuple_arg(a_idx, f)
-    }
-
     // Specialized types:
     fn read_option<T, F>(&mut self, mut f: F) -> Result<T, Self::Error>
     where
         F: FnMut(&mut Self, bool) -> Result<T, Self::Error>,
     {
-        self.read_enum("Option", move |this| {
+        self.read_enum(move |this| {
             this.read_enum_variant(&["None", "Some"], move |this, idx| match idx {
                 0 => f(this, false),
                 1 => f(this, true),
@@ -346,7 +264,7 @@ pub trait Decoder {
     }
 
     #[inline]
-    fn read_seq_elt<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
+    fn read_seq_elt<T, F>(&mut self, f: F) -> Result<T, Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<T, Self::Error>,
     {
@@ -362,7 +280,7 @@ pub trait Decoder {
     }
 
     #[inline]
-    fn read_map_elt_key<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
+    fn read_map_elt_key<T, F>(&mut self, f: F) -> Result<T, Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<T, Self::Error>,
     {
@@ -370,7 +288,7 @@ pub trait Decoder {
     }
 
     #[inline]
-    fn read_map_elt_val<T, F>(&mut self, _idx: usize, f: F) -> Result<T, Self::Error>
+    fn read_map_elt_val<T, F>(&mut self, f: F) -> Result<T, Self::Error>
     where
         F: FnOnce(&mut Self) -> Result<T, Self::Error>,
     {
@@ -550,8 +468,8 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Vec<T> {
     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 {
-                v.push(d.read_seq_elt(i, |d| Decodable::decode(d))?);
+            for _ in 0..len {
+                v.push(d.read_seq_elt(|d| Decodable::decode(d))?);
             }
             Ok(v)
         })
@@ -571,7 +489,7 @@ impl<D: Decoder, const N: usize> Decodable<D> for [u8; N] {
             assert!(len == N);
             let mut v = [0u8; N];
             for i in 0..len {
-                v[i] = d.read_seq_elt(i, |d| Decodable::decode(d))?;
+                v[i] = d.read_seq_elt(|d| Decodable::decode(d))?;
             }
             Ok(v)
         })
@@ -615,12 +533,12 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Option<T> {
 
 impl<S: Encoder, T1: Encodable<S>, T2: Encodable<S>> Encodable<S> for Result<T1, T2> {
     fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_enum("Result", |s| match *self {
+        s.emit_enum(|s| match *self {
             Ok(ref v) => {
-                s.emit_enum_variant("Ok", 0, 1, |s| s.emit_enum_variant_arg(0, |s| v.encode(s)))
+                s.emit_enum_variant("Ok", 0, 1, |s| s.emit_enum_variant_arg(true, |s| v.encode(s)))
             }
             Err(ref v) => {
-                s.emit_enum_variant("Err", 1, 1, |s| s.emit_enum_variant_arg(0, |s| v.encode(s)))
+                s.emit_enum_variant("Err", 1, 1, |s| s.emit_enum_variant_arg(true, |s| v.encode(s)))
             }
         })
     }
@@ -628,10 +546,10 @@ impl<S: Encoder, T1: Encodable<S>, T2: Encodable<S>> Encodable<S> for Result<T1,
 
 impl<D: Decoder, T1: Decodable<D>, T2: Decodable<D>> Decodable<D> for Result<T1, T2> {
     fn decode(d: &mut D) -> Result<Result<T1, T2>, D::Error> {
-        d.read_enum("Result", |d| {
+        d.read_enum(|d| {
             d.read_enum_variant(&["Ok", "Err"], |d, disr| match disr {
-                0 => Ok(Ok(d.read_enum_variant_arg(0, |d| T1::decode(d))?)),
-                1 => Ok(Err(d.read_enum_variant_arg(0, |d| T2::decode(d))?)),
+                0 => Ok(Ok(d.read_enum_variant_arg(|d| T1::decode(d))?)),
+                1 => Ok(Err(d.read_enum_variant_arg(|d| T2::decode(d))?)),
                 _ => {
                     panic!(
                         "Encountered invalid discriminant while \
@@ -668,8 +586,7 @@ macro_rules! tuple {
             fn decode(d: &mut D) -> Result<($($name,)+), D::Error> {
                 let len: usize = count!($($name)+);
                 d.read_tuple(len, |d| {
-                    let mut i = 0;
-                    let ret = ($(d.read_tuple_arg({ i+=1; i-1 }, |d| -> Result<$name, D::Error> {
+                    let ret = ($(d.read_tuple_arg(|d| -> Result<$name, D::Error> {
                         Decodable::decode(d)
                     })?,)+);
                     Ok(ret)
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 52f8b536f4a..57522582683 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -677,6 +677,7 @@ impl Default for Options {
             optimize: OptLevel::No,
             debuginfo: DebugInfo::None,
             lint_opts: Vec::new(),
+            force_warns: Vec::new(),
             lint_cap: None,
             describe_lints: false,
             output_types: OutputTypes(BTreeMap::new()),
@@ -1092,6 +1093,13 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
              level",
             "LEVEL",
         ),
+        opt::multi_s(
+            "",
+            "force-warns",
+            "Specifiy lints that should warn even if \
+             they are allowed somewhere else",
+            "LINT",
+        ),
         opt::multi_s("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
         opt::flag_s("V", "version", "Print version info and exit"),
         opt::flag_s("v", "verbose", "Use verbose output"),
@@ -1156,7 +1164,8 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
 pub fn get_cmd_lint_options(
     matches: &getopts::Matches,
     error_format: ErrorOutputType,
-) -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>) {
+    debugging_opts: &DebuggingOptions,
+) -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>, Vec<String>) {
     let mut lint_opts_with_position = vec![];
     let mut describe_lints = false;
 
@@ -1189,7 +1198,18 @@ pub fn get_cmd_lint_options(
         lint::Level::from_str(&cap)
             .unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{}`", cap)))
     });
-    (lint_opts, describe_lints, lint_cap)
+
+    if !debugging_opts.unstable_options && matches.opt_present("force-warns") {
+        early_error(
+            error_format,
+            "the `-Z unstable-options` flag must also be passed to enable \
+            the flag `--force-warns=lints`",
+        );
+    }
+
+    let force_warns = matches.opt_strs("force-warns");
+
+    (lint_opts, describe_lints, lint_cap, force_warns)
 }
 
 /// Parses the `--color` flag.
@@ -1926,9 +1946,10 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
     let crate_types = parse_crate_types_from_list(unparsed_crate_types)
         .unwrap_or_else(|e| early_error(error_format, &e[..]));
 
-    let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
-
     let mut debugging_opts = DebuggingOptions::build(matches, error_format);
+    let (lint_opts, describe_lints, lint_cap, force_warns) =
+        get_cmd_lint_options(matches, error_format, &debugging_opts);
+
     check_debug_option_stability(&debugging_opts, error_format, json_rendered);
 
     if !debugging_opts.unstable_options && json_unused_externs {
@@ -2100,6 +2121,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         optimize: opt_level,
         debuginfo,
         lint_opts,
+        force_warns,
         lint_cap,
         describe_lints,
         output_types,
@@ -2427,30 +2449,32 @@ crate mod dep_tracking {
         )+};
     }
 
+    impl<T: DepTrackingHash> DepTrackingHash for Option<T> {
+        fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
+            match self {
+                Some(x) => {
+                    Hash::hash(&1, hasher);
+                    DepTrackingHash::hash(x, hasher, error_format);
+                }
+                None => Hash::hash(&0, hasher),
+            }
+        }
+    }
+
     impl_dep_tracking_hash_via_hash!(
         bool,
         usize,
+        NonZeroUsize,
         u64,
         String,
         PathBuf,
         lint::Level,
-        Option<bool>,
-        Option<u32>,
-        Option<usize>,
-        Option<NonZeroUsize>,
-        Option<String>,
-        Option<(String, u64)>,
-        Option<Vec<String>>,
-        Option<MergeFunctions>,
-        Option<RelocModel>,
-        Option<CodeModel>,
-        Option<TlsModel>,
-        Option<WasiExecModel>,
-        Option<PanicStrategy>,
-        Option<RelroLevel>,
-        Option<InstrumentCoverage>,
-        Option<lint::Level>,
-        Option<PathBuf>,
+        WasiExecModel,
+        u32,
+        RelocModel,
+        CodeModel,
+        TlsModel,
+        InstrumentCoverage,
         CrateType,
         MergeFunctions,
         PanicStrategy,
@@ -2468,10 +2492,10 @@ crate mod dep_tracking {
         TargetTriple,
         Edition,
         LinkerPluginLto,
-        Option<SplitDebuginfo>,
+        SplitDebuginfo,
         SwitchWithOptPath,
-        Option<SymbolManglingVersion>,
-        Option<SourceFileHashAlgorithm>,
+        SymbolManglingVersion,
+        SourceFileHashAlgorithm,
         TrimmedDefPaths,
     );
 
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index bb82cf4c45d..58a53b3de6e 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -130,6 +130,7 @@ top_level_options!(
         debuginfo: DebugInfo [TRACKED],
         lint_opts: Vec<(String, lint::Level)> [TRACKED],
         lint_cap: Option<lint::Level> [TRACKED],
+        force_warns: Vec<String> [TRACKED],
         describe_lints: bool [UNTRACKED],
         output_types: OutputTypes [TRACKED],
         search_paths: Vec<SearchPath> [UNTRACKED],
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 4ba47985ce1..86b8389a670 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -22,7 +22,7 @@ use rustc_errors::json::JsonEmitter;
 use rustc_errors::registry::Registry;
 use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported};
 use rustc_lint_defs::FutureBreakage;
-pub use rustc_span::def_id::StableCrateId;
+pub use rustc_span::crate_disambiguator::CrateDisambiguator;
 use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, Span};
 use rustc_span::{edition::Edition, RealFileName};
 use rustc_span::{sym, SourceFileHashAlgorithm, Symbol};
@@ -133,12 +133,12 @@ pub struct Session {
     /// in order to avoid redundantly verbose output (Issue #24690, #44953).
     pub one_time_diagnostics: Lock<FxHashSet<(DiagnosticMessageId, Option<Span>, String)>>,
     crate_types: OnceCell<Vec<CrateType>>,
-    /// The `stable_crate_id` is constructed out of the crate name and all the
-    /// `-C metadata` arguments passed to the compiler. Its value forms a unique
-    /// global identifier for the crate. It is used to allow multiple crates
-    /// with the same name to coexist. See the
+    /// The `crate_disambiguator` is constructed out of all the `-C metadata`
+    /// arguments passed to the compiler. Its value together with the crate-name
+    /// forms a unique global identifier for the crate. It is used to allow
+    /// multiple crates with the same name to coexist. See the
     /// `rustc_codegen_llvm::back::symbol_names` module for more information.
-    pub stable_crate_id: OnceCell<StableCrateId>,
+    pub crate_disambiguator: OnceCell<CrateDisambiguator>,
 
     features: OnceCell<rustc_feature::Features>,
 
@@ -335,8 +335,8 @@ impl Session {
         self.parse_sess.span_diagnostic.emit_future_breakage_report(diags_and_breakage);
     }
 
-    pub fn local_stable_crate_id(&self) -> StableCrateId {
-        self.stable_crate_id.get().copied().unwrap()
+    pub fn local_crate_disambiguator(&self) -> CrateDisambiguator {
+        self.crate_disambiguator.get().copied().unwrap()
     }
 
     pub fn crate_types(&self) -> &[CrateType] {
@@ -452,6 +452,7 @@ impl Session {
     pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) {
         err.into_diagnostic(self).emit()
     }
+    #[inline]
     pub fn err_count(&self) -> usize {
         self.diagnostic().err_count()
     }
@@ -524,6 +525,7 @@ impl Session {
         self.diagnostic().struct_note_without_error(msg)
     }
 
+    #[inline]
     pub fn diagnostic(&self) -> &rustc_errors::Handler {
         &self.parse_sess.span_diagnostic
     }
@@ -831,12 +833,12 @@ impl Session {
 
     /// Returns the symbol name for the registrar function,
     /// given the crate `Svh` and the function `DefIndex`.
-    pub fn generate_plugin_registrar_symbol(&self, stable_crate_id: StableCrateId) -> String {
-        format!("__rustc_plugin_registrar_{:08x}__", stable_crate_id.to_u64())
+    pub fn generate_plugin_registrar_symbol(&self, disambiguator: CrateDisambiguator) -> String {
+        format!("__rustc_plugin_registrar_{}__", disambiguator.to_fingerprint().to_hex())
     }
 
-    pub fn generate_proc_macro_decls_symbol(&self, stable_crate_id: StableCrateId) -> String {
-        format!("__rustc_proc_macro_decls_{:08x}__", stable_crate_id.to_u64())
+    pub fn generate_proc_macro_decls_symbol(&self, disambiguator: CrateDisambiguator) -> String {
+        format!("__rustc_proc_macro_decls_{}__", disambiguator.to_fingerprint().to_hex())
     }
 
     pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> {
@@ -1395,7 +1397,7 @@ pub fn build_session(
         working_dir,
         one_time_diagnostics: Default::default(),
         crate_types: OnceCell::new(),
-        stable_crate_id: OnceCell::new(),
+        crate_disambiguator: OnceCell::new(),
         features: OnceCell::new(),
         lint_store: OnceCell::new(),
         recursion_limit: OnceCell::new(),
diff --git a/compiler/rustc_span/src/crate_disambiguator.rs b/compiler/rustc_span/src/crate_disambiguator.rs
new file mode 100644
index 00000000000..bd7d8516714
--- /dev/null
+++ b/compiler/rustc_span/src/crate_disambiguator.rs
@@ -0,0 +1,35 @@
+// This is here because `rustc_session` wants to refer to it,
+// and so does `rustc_hir`, but `rustc_hir` shouldn't refer to `rustc_session`.
+
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::{base_n, impl_stable_hash_via_hash};
+
+use std::fmt;
+
+/// Hash value constructed out of all the `-C metadata` arguments passed to the
+/// compiler. Together with the crate-name forms a unique global identifier for
+/// the crate.
+#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy, Encodable, Decodable)]
+pub struct CrateDisambiguator(Fingerprint);
+
+impl CrateDisambiguator {
+    pub fn to_fingerprint(self) -> Fingerprint {
+        self.0
+    }
+}
+
+impl fmt::Display for CrateDisambiguator {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
+        let (a, b) = self.0.as_value();
+        let as_u128 = a as u128 | ((b as u128) << 64);
+        f.write_str(&base_n::encode(as_u128, base_n::CASE_INSENSITIVE))
+    }
+}
+
+impl From<Fingerprint> for CrateDisambiguator {
+    fn from(fingerprint: Fingerprint) -> CrateDisambiguator {
+        CrateDisambiguator(fingerprint)
+    }
+}
+
+impl_stable_hash_via_hash!(CrateDisambiguator);
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index aeb3234315f..6ee75376ad5 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -1,3 +1,4 @@
+use crate::crate_disambiguator::CrateDisambiguator;
 use crate::HashStableContext;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -9,65 +10,23 @@ use std::borrow::Borrow;
 use std::fmt;
 
 rustc_index::newtype_index! {
-    pub struct CrateId {
+    pub struct CrateNum {
         ENCODABLE = custom
+        DEBUG_FORMAT = "crate{}"
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum CrateNum {
-    /// A special `CrateNum` that we use for the `tcx.rcache` when decoding from
-    /// the incr. comp. cache.
-    ReservedForIncrCompCache,
-    Index(CrateId),
-}
-
 /// Item definitions in the currently-compiled crate would have the `CrateNum`
 /// `LOCAL_CRATE` in their `DefId`.
-pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32(0));
-
-impl Idx for CrateNum {
-    #[inline]
-    fn new(value: usize) -> Self {
-        CrateNum::Index(Idx::new(value))
-    }
-
-    #[inline]
-    fn index(self) -> usize {
-        match self {
-            CrateNum::Index(idx) => Idx::index(idx),
-            _ => panic!("Tried to get crate index of {:?}", self),
-        }
-    }
-}
+pub const LOCAL_CRATE: CrateNum = CrateNum::from_u32(0);
 
 impl CrateNum {
+    #[inline]
     pub fn new(x: usize) -> CrateNum {
         CrateNum::from_usize(x)
     }
 
-    pub fn from_usize(x: usize) -> CrateNum {
-        CrateNum::Index(CrateId::from_usize(x))
-    }
-
-    pub fn from_u32(x: u32) -> CrateNum {
-        CrateNum::Index(CrateId::from_u32(x))
-    }
-
-    pub fn as_usize(self) -> usize {
-        match self {
-            CrateNum::Index(id) => id.as_usize(),
-            _ => panic!("tried to get index of non-standard crate {:?}", self),
-        }
-    }
-
-    pub fn as_u32(self) -> u32 {
-        match self {
-            CrateNum::Index(id) => id.as_u32(),
-            _ => panic!("tried to get index of non-standard crate {:?}", self),
-        }
-    }
-
+    #[inline]
     pub fn as_def_id(&self) -> DefId {
         DefId { krate: *self, index: CRATE_DEF_INDEX }
     }
@@ -75,10 +34,7 @@ impl CrateNum {
 
 impl fmt::Display for CrateNum {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            CrateNum::Index(id) => fmt::Display::fmt(&id.private, f),
-            CrateNum::ReservedForIncrCompCache => write!(f, "crate for decoding incr comp cache"),
-        }
+        fmt::Display::fmt(&self.private, f)
     }
 }
 
@@ -96,15 +52,6 @@ impl<D: Decoder> Decodable<D> for CrateNum {
     }
 }
 
-impl ::std::fmt::Debug for CrateNum {
-    fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
-        match self {
-            CrateNum::Index(id) => write!(fmt, "crate{}", id.private),
-            CrateNum::ReservedForIncrCompCache => write!(fmt, "crate for decoding incr comp cache"),
-        }
-    }
-}
-
 /// A `DefPathHash` is a fixed-size representation of a `DefPath` that is
 /// stable across crate and compilation session boundaries. It consists of two
 /// separate 64-bit hashes. The first uniquely identifies the crate this
@@ -180,51 +127,26 @@ impl Borrow<Fingerprint> for DefPathHash {
     }
 }
 
-/// A [StableCrateId] is a 64 bit hash of the crate name combined with all
-/// `-Cmetadata` arguments. It is to [CrateNum] what [DefPathHash] is to
-/// [DefId]. It is stable across compilation sessions.
+/// A [StableCrateId] is a 64 bit hash of `(crate-name, crate-disambiguator)`. It
+/// is to [CrateNum] what [DefPathHash] is to [DefId]. It is stable across
+/// compilation sessions.
 ///
 /// Since the ID is a hash value there is a (very small) chance that two crates
 /// end up with the same [StableCrateId]. The compiler will check for such
 /// collisions when loading crates and abort compilation in order to avoid
 /// further trouble.
-#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
-#[derive(HashStable_Generic, Encodable, Decodable)]
+#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Encodable, Decodable)]
 pub struct StableCrateId(u64);
 
 impl StableCrateId {
-    pub fn to_u64(self) -> u64 {
-        self.0
-    }
-
     /// Computes the stable ID for a crate with the given name and
-    /// `-Cmetadata` arguments.
-    pub fn new(crate_name: &str, is_exe: bool, mut metadata: Vec<String>) -> StableCrateId {
+    /// disambiguator.
+    pub fn new(crate_name: &str, crate_disambiguator: CrateDisambiguator) -> StableCrateId {
         use std::hash::Hash;
-        use std::hash::Hasher;
 
         let mut hasher = StableHasher::new();
         crate_name.hash(&mut hasher);
-
-        // We don't want the stable crate id to dependent on the order
-        // -C metadata arguments, so sort them:
-        metadata.sort();
-        // Every distinct -C metadata value is only incorporated once:
-        metadata.dedup();
-
-        hasher.write(b"metadata");
-        for s in &metadata {
-            // Also incorporate the length of a metadata string, so that we generate
-            // different values for `-Cmetadata=ab -Cmetadata=c` and
-            // `-Cmetadata=a -Cmetadata=bc`
-            hasher.write_usize(s.len());
-            hasher.write(s.as_bytes());
-        }
-
-        // Also incorporate crate type, so that we don't get symbol conflicts when
-        // linking against a library of the same name, if this is an executable.
-        hasher.write(if is_exe { b"exe" } else { b"lib" });
-
+        crate_disambiguator.hash(&mut hasher);
         StableCrateId(hasher.finish())
     }
 }
@@ -295,20 +217,20 @@ impl DefId {
 
 impl<E: Encoder> Encodable<E> for DefId {
     default fn encode(&self, s: &mut E) -> Result<(), E::Error> {
-        s.emit_struct("DefId", 2, |s| {
-            s.emit_struct_field("krate", 0, |s| self.krate.encode(s))?;
+        s.emit_struct(false, |s| {
+            s.emit_struct_field("krate", true, |s| self.krate.encode(s))?;
 
-            s.emit_struct_field("index", 1, |s| self.index.encode(s))
+            s.emit_struct_field("index", false, |s| self.index.encode(s))
         })
     }
 }
 
 impl<D: Decoder> Decodable<D> for DefId {
     default fn decode(d: &mut D) -> Result<DefId, D::Error> {
-        d.read_struct("DefId", 2, |d| {
+        d.read_struct(|d| {
             Ok(DefId {
-                krate: d.read_struct_field("krate", 0, Decodable::decode)?,
-                index: d.read_struct_field("index", 1, Decodable::decode)?,
+                krate: d.read_struct_field("krate", Decodable::decode)?,
+                index: d.read_struct_field("index", Decodable::decode)?,
             })
         })
     }
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index dc15c531d1e..9cf68cbd23e 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -16,12 +16,10 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(array_windows)]
 #![feature(crate_visibility_modifier)]
-#![feature(const_panic)]
 #![feature(negative_impls)]
 #![feature(nll)]
 #![feature(min_specialization)]
 #![feature(thread_local_const_init)]
-#![feature(trusted_step)]
 
 #[macro_use]
 extern crate rustc_macros;
@@ -47,6 +45,8 @@ pub mod lev_distance;
 mod span_encoding;
 pub use span_encoding::{Span, DUMMY_SP};
 
+pub mod crate_disambiguator;
+
 pub mod symbol;
 pub use symbol::{sym, Symbol};
 
@@ -146,11 +146,12 @@ impl Hash for RealFileName {
 // an added assert statement
 impl<S: Encoder> Encodable<S> for RealFileName {
     fn encode(&self, encoder: &mut S) -> Result<(), S::Error> {
-        encoder.emit_enum("RealFileName", |encoder| match *self {
+        encoder.emit_enum(|encoder| match *self {
             RealFileName::LocalPath(ref local_path) => {
                 encoder.emit_enum_variant("LocalPath", 0, 1, |encoder| {
                     Ok({
-                        encoder.emit_enum_variant_arg(0, |encoder| local_path.encode(encoder))?;
+                        encoder
+                            .emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?;
                     })
                 })
             }
@@ -161,8 +162,10 @@ impl<S: Encoder> Encodable<S> for RealFileName {
                     // if they have been remapped by --remap-path-prefix
                     assert!(local_path.is_none());
                     Ok({
-                        encoder.emit_enum_variant_arg(0, |encoder| local_path.encode(encoder))?;
-                        encoder.emit_enum_variant_arg(1, |encoder| virtual_name.encode(encoder))?;
+                        encoder
+                            .emit_enum_variant_arg(true, |encoder| local_path.encode(encoder))?;
+                        encoder
+                            .emit_enum_variant_arg(false, |encoder| virtual_name.encode(encoder))?;
                     })
                 }),
         })
@@ -827,17 +830,17 @@ impl Default for Span {
 impl<E: Encoder> Encodable<E> for Span {
     default fn encode(&self, s: &mut E) -> Result<(), E::Error> {
         let span = self.data();
-        s.emit_struct("Span", 2, |s| {
-            s.emit_struct_field("lo", 0, |s| span.lo.encode(s))?;
-            s.emit_struct_field("hi", 1, |s| span.hi.encode(s))
+        s.emit_struct(false, |s| {
+            s.emit_struct_field("lo", true, |s| span.lo.encode(s))?;
+            s.emit_struct_field("hi", false, |s| span.hi.encode(s))
         })
     }
 }
 impl<D: Decoder> Decodable<D> for Span {
     default fn decode(s: &mut D) -> Result<Span, D::Error> {
-        s.read_struct("Span", 2, |d| {
-            let lo = d.read_struct_field("lo", 0, Decodable::decode)?;
-            let hi = d.read_struct_field("hi", 1, Decodable::decode)?;
+        s.read_struct(|d| {
+            let lo = d.read_struct_field("lo", Decodable::decode)?;
+            let hi = d.read_struct_field("hi", Decodable::decode)?;
 
             Ok(Span::new(lo, hi, SyntaxContext::root()))
         })
@@ -1234,12 +1237,12 @@ pub struct SourceFile {
 
 impl<S: Encoder> Encodable<S> for SourceFile {
     fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_struct("SourceFile", 8, |s| {
-            s.emit_struct_field("name", 0, |s| self.name.encode(s))?;
-            s.emit_struct_field("src_hash", 2, |s| self.src_hash.encode(s))?;
-            s.emit_struct_field("start_pos", 3, |s| self.start_pos.encode(s))?;
-            s.emit_struct_field("end_pos", 4, |s| self.end_pos.encode(s))?;
-            s.emit_struct_field("lines", 5, |s| {
+        s.emit_struct(false, |s| {
+            s.emit_struct_field("name", true, |s| self.name.encode(s))?;
+            s.emit_struct_field("src_hash", false, |s| self.src_hash.encode(s))?;
+            s.emit_struct_field("start_pos", false, |s| self.start_pos.encode(s))?;
+            s.emit_struct_field("end_pos", false, |s| self.end_pos.encode(s))?;
+            s.emit_struct_field("lines", false, |s| {
                 let lines = &self.lines[..];
                 // Store the length.
                 s.emit_u32(lines.len() as u32)?;
@@ -1297,25 +1300,24 @@ impl<S: Encoder> Encodable<S> for SourceFile {
 
                 Ok(())
             })?;
-            s.emit_struct_field("multibyte_chars", 6, |s| self.multibyte_chars.encode(s))?;
-            s.emit_struct_field("non_narrow_chars", 7, |s| self.non_narrow_chars.encode(s))?;
-            s.emit_struct_field("name_hash", 8, |s| self.name_hash.encode(s))?;
-            s.emit_struct_field("normalized_pos", 9, |s| self.normalized_pos.encode(s))?;
-            s.emit_struct_field("cnum", 10, |s| self.cnum.encode(s))
+            s.emit_struct_field("multibyte_chars", false, |s| self.multibyte_chars.encode(s))?;
+            s.emit_struct_field("non_narrow_chars", false, |s| self.non_narrow_chars.encode(s))?;
+            s.emit_struct_field("name_hash", false, |s| self.name_hash.encode(s))?;
+            s.emit_struct_field("normalized_pos", false, |s| self.normalized_pos.encode(s))?;
+            s.emit_struct_field("cnum", false, |s| self.cnum.encode(s))
         })
     }
 }
 
 impl<D: Decoder> Decodable<D> for SourceFile {
     fn decode(d: &mut D) -> Result<SourceFile, D::Error> {
-        d.read_struct("SourceFile", 8, |d| {
-            let name: FileName = d.read_struct_field("name", 0, |d| Decodable::decode(d))?;
+        d.read_struct(|d| {
+            let name: FileName = d.read_struct_field("name", |d| Decodable::decode(d))?;
             let src_hash: SourceFileHash =
-                d.read_struct_field("src_hash", 2, |d| Decodable::decode(d))?;
-            let start_pos: BytePos =
-                d.read_struct_field("start_pos", 3, |d| Decodable::decode(d))?;
-            let end_pos: BytePos = d.read_struct_field("end_pos", 4, |d| Decodable::decode(d))?;
-            let lines: Vec<BytePos> = d.read_struct_field("lines", 5, |d| {
+                d.read_struct_field("src_hash", |d| Decodable::decode(d))?;
+            let start_pos: BytePos = d.read_struct_field("start_pos", |d| Decodable::decode(d))?;
+            let end_pos: BytePos = d.read_struct_field("end_pos", |d| Decodable::decode(d))?;
+            let lines: Vec<BytePos> = d.read_struct_field("lines", |d| {
                 let num_lines: u32 = Decodable::decode(d)?;
                 let mut lines = Vec::with_capacity(num_lines as usize);
 
@@ -1344,13 +1346,13 @@ impl<D: Decoder> Decodable<D> for SourceFile {
                 Ok(lines)
             })?;
             let multibyte_chars: Vec<MultiByteChar> =
-                d.read_struct_field("multibyte_chars", 6, |d| Decodable::decode(d))?;
+                d.read_struct_field("multibyte_chars", |d| Decodable::decode(d))?;
             let non_narrow_chars: Vec<NonNarrowChar> =
-                d.read_struct_field("non_narrow_chars", 7, |d| Decodable::decode(d))?;
-            let name_hash: u128 = d.read_struct_field("name_hash", 8, |d| Decodable::decode(d))?;
+                d.read_struct_field("non_narrow_chars", |d| Decodable::decode(d))?;
+            let name_hash: u128 = d.read_struct_field("name_hash", |d| Decodable::decode(d))?;
             let normalized_pos: Vec<NormalizedPos> =
-                d.read_struct_field("normalized_pos", 9, |d| Decodable::decode(d))?;
-            let cnum: CrateNum = d.read_struct_field("cnum", 10, |d| Decodable::decode(d))?;
+                d.read_struct_field("normalized_pos", |d| Decodable::decode(d))?;
+            let cnum: CrateNum = d.read_struct_field("cnum", |d| Decodable::decode(d))?;
             Ok(SourceFile {
                 name,
                 start_pos,
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 46ef308cbf2..31b425f1a79 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -328,6 +328,7 @@ symbols! {
         box_free,
         box_patterns,
         box_syntax,
+        bpf_target_feature,
         braced_empty_structs,
         branch,
         breakpoint,
@@ -1332,6 +1333,7 @@ symbols! {
         wrapping_add,
         wrapping_mul,
         wrapping_sub,
+        wreg,
         write_bytes,
         xmm_reg,
         ymm_reg,
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index 1addfc8ee67..025eaffcbd3 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -126,9 +126,8 @@ fn get_symbol_hash<'tcx>(
         substs.hash_stable(&mut hcx, &mut hasher);
 
         if let Some(instantiating_crate) = instantiating_crate {
-            tcx.def_path_hash(instantiating_crate.as_def_id())
-                .stable_crate_id()
-                .hash_stable(&mut hcx, &mut hasher);
+            tcx.crate_name(instantiating_crate).as_str().hash_stable(&mut hcx, &mut hasher);
+            tcx.crate_disambiguator(instantiating_crate).hash_stable(&mut hcx, &mut hasher);
         }
 
         // We want to avoid accidental collision between different types of instances.
@@ -254,7 +253,7 @@ impl Printer<'tcx> for SymbolPrinter<'tcx> {
     }
 
     fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
-        self.write_str(&self.tcx.original_crate_name(cnum).as_str())?;
+        self.write_str(&self.tcx.crate_name(cnum).as_str())?;
         Ok(self)
     }
     fn path_qualified(
diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index ba59ff96f65..f716ce1efce 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -165,12 +165,12 @@ fn compute_symbol_name(
     // FIXME(eddyb) Precompute a custom symbol name based on attributes.
     let is_foreign = if let Some(def_id) = def_id.as_local() {
         if tcx.plugin_registrar_fn(()) == Some(def_id) {
-            let stable_crate_id = tcx.sess.local_stable_crate_id();
-            return tcx.sess.generate_plugin_registrar_symbol(stable_crate_id);
+            let disambiguator = tcx.sess.local_crate_disambiguator();
+            return tcx.sess.generate_plugin_registrar_symbol(disambiguator);
         }
         if tcx.proc_macro_decls_static(()) == Some(def_id) {
-            let stable_crate_id = tcx.sess.local_stable_crate_id();
-            return tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id);
+            let disambiguator = tcx.sess.local_crate_disambiguator();
+            return tcx.sess.generate_proc_macro_decls_symbol(disambiguator);
         }
         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
         matches!(tcx.hir().get(hir_id), Node::ForeignItem(_))
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 2ab7461fc60..828f1ac0a79 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -592,9 +592,9 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
 
     fn path_crate(mut self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
         self.push("C");
-        let stable_crate_id = self.tcx.def_path_hash(cnum.as_def_id()).stable_crate_id();
-        self.push_disambiguator(stable_crate_id.to_u64());
-        let name = self.tcx.original_crate_name(cnum).as_str();
+        let fingerprint = self.tcx.crate_disambiguator(cnum).to_fingerprint();
+        self.push_disambiguator(fingerprint.to_smaller_hash());
+        let name = self.tcx.crate_name(cnum).as_str();
         self.push_ident(&name);
         Ok(self)
     }
diff --git a/compiler/rustc_target/src/abi/call/bpf.rs b/compiler/rustc_target/src/abi/call/bpf.rs
new file mode 100644
index 00000000000..466c525531c
--- /dev/null
+++ b/compiler/rustc_target/src/abi/call/bpf.rs
@@ -0,0 +1,31 @@
+// see https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/BPF/BPFCallingConv.td
+use crate::abi::call::{ArgAbi, FnAbi};
+
+fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
+    if ret.layout.is_aggregate() || ret.layout.size.bits() > 64 {
+        ret.make_indirect();
+    } else {
+        ret.extend_integer_width_to(32);
+    }
+}
+
+fn classify_arg<Ty>(arg: &mut ArgAbi<'_, Ty>) {
+    if arg.layout.is_aggregate() || arg.layout.size.bits() > 64 {
+        arg.make_indirect();
+    } else {
+        arg.extend_integer_width_to(32);
+    }
+}
+
+pub fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
+    if !fn_abi.ret.is_ignore() {
+        classify_ret(&mut fn_abi.ret);
+    }
+
+    for arg in &mut fn_abi.args {
+        if arg.is_ignore() {
+            continue;
+        }
+        classify_arg(arg);
+    }
+}
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 0cf2441d84e..6e0e1403740 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -6,6 +6,7 @@ mod aarch64;
 mod amdgpu;
 mod arm;
 mod avr;
+mod bpf;
 mod hexagon;
 mod mips;
 mod mips64;
@@ -654,6 +655,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
                 }
             }
             "asmjs" => wasm::compute_c_abi_info(cx, self),
+            "bpf" => bpf::compute_abi_info(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 dae72e1b2c8..8e71ded3d1d 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -222,6 +222,7 @@ pub trait HasDataLayout {
 }
 
 impl HasDataLayout for TargetDataLayout {
+    #[inline]
     fn data_layout(&self) -> &TargetDataLayout {
         self
     }
@@ -752,11 +753,7 @@ impl FieldsShape {
         match *self {
             FieldsShape::Primitive => 0,
             FieldsShape::Union(count) => count.get(),
-            FieldsShape::Array { count, .. } => {
-                let usize_count = count as usize;
-                assert_eq!(usize_count as u64, count);
-                usize_count
-            }
+            FieldsShape::Array { count, .. } => count.try_into().unwrap(),
             FieldsShape::Arbitrary { ref offsets, .. } => offsets.len(),
         }
     }
@@ -790,11 +787,7 @@ impl FieldsShape {
                 unreachable!("FieldsShape::memory_index: `Primitive`s have no fields")
             }
             FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
-            FieldsShape::Arbitrary { ref memory_index, .. } => {
-                let r = memory_index[i];
-                assert_eq!(r as usize as u32, r);
-                r as usize
-            }
+            FieldsShape::Arbitrary { ref memory_index, .. } => memory_index[i].try_into().unwrap(),
         }
     }
 
@@ -862,6 +855,7 @@ pub enum Abi {
 
 impl Abi {
     /// Returns `true` if the layout corresponds to an unsized type.
+    #[inline]
     pub fn is_unsized(&self) -> bool {
         match *self {
             Abi::Uninhabited | Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false,
@@ -881,11 +875,13 @@ impl Abi {
     }
 
     /// Returns `true` if this is an uninhabited type
+    #[inline]
     pub fn is_uninhabited(&self) -> bool {
         matches!(*self, Abi::Uninhabited)
     }
 
     /// Returns `true` is this is a scalar type
+    #[inline]
     pub fn is_scalar(&self) -> bool {
         matches!(*self, Abi::Scalar(_))
     }
diff --git a/compiler/rustc_target/src/asm/bpf.rs b/compiler/rustc_target/src/asm/bpf.rs
new file mode 100644
index 00000000000..ecb6bdc95ce
--- /dev/null
+++ b/compiler/rustc_target/src/asm/bpf.rs
@@ -0,0 +1,129 @@
+use super::{InlineAsmArch, InlineAsmType, Target};
+use rustc_macros::HashStable_Generic;
+use std::fmt;
+
+def_reg_class! {
+    Bpf BpfInlineAsmRegClass {
+        reg,
+        wreg,
+    }
+}
+
+impl BpfInlineAsmRegClass {
+    pub fn valid_modifiers(self, _arch: InlineAsmArch) -> &'static [char] {
+        &[]
+    }
+
+    pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> {
+        None
+    }
+
+    pub fn suggest_modifier(
+        self,
+        _arch: InlineAsmArch,
+        _ty: InlineAsmType,
+    ) -> Option<(char, &'static str)> {
+        None
+    }
+
+    pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
+        None
+    }
+
+    pub fn supported_types(
+        self,
+        _arch: InlineAsmArch,
+    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
+        match self {
+            Self::reg => types! { _: I8, I16, I32, I64; },
+            Self::wreg => types! { "alu32": I8, I16, I32; },
+        }
+    }
+}
+
+fn only_alu32(
+    _arch: InlineAsmArch,
+    mut has_feature: impl FnMut(&str) -> bool,
+    _target: &Target,
+) -> Result<(), &'static str> {
+    if !has_feature("alu32") {
+        Err("register can't be used without the `alu32` target feature")
+    } else {
+        Ok(())
+    }
+}
+
+def_regs! {
+    Bpf BpfInlineAsmReg BpfInlineAsmRegClass {
+        r0: reg = ["r0"],
+        r1: reg = ["r1"],
+        r2: reg = ["r2"],
+        r3: reg = ["r3"],
+        r4: reg = ["r4"],
+        r5: reg = ["r5"],
+        r6: reg = ["r6"],
+        r7: reg = ["r7"],
+        r8: reg = ["r8"],
+        r9: reg = ["r9"],
+        w0: wreg = ["w0"] % only_alu32,
+        w1: wreg = ["w1"] % only_alu32,
+        w2: wreg = ["w2"] % only_alu32,
+        w3: wreg = ["w3"] % only_alu32,
+        w4: wreg = ["w4"] % only_alu32,
+        w5: wreg = ["w5"] % only_alu32,
+        w6: wreg = ["w6"] % only_alu32,
+        w7: wreg = ["w7"] % only_alu32,
+        w8: wreg = ["w8"] % only_alu32,
+        w9: wreg = ["w9"] % only_alu32,
+
+        #error = ["r10", "w10"] =>
+            "the stack pointer cannot be used as an operand for inline asm",
+    }
+}
+
+impl BpfInlineAsmReg {
+    pub fn emit(
+        self,
+        out: &mut dyn fmt::Write,
+        _arch: InlineAsmArch,
+        _modifier: Option<char>,
+    ) -> fmt::Result {
+        out.write_str(self.name())
+    }
+
+    pub fn overlapping_regs(self, mut cb: impl FnMut(BpfInlineAsmReg)) {
+        cb(self);
+
+        macro_rules! reg_conflicts {
+            (
+                $(
+                    $r:ident : $w:ident
+                ),*
+            ) => {
+                match self {
+                    $(
+                        Self::$r => {
+                            cb(Self::$w);
+                        }
+                        Self::$w => {
+                            cb(Self::$r);
+                        }
+                    )*
+                }
+            };
+        }
+
+        reg_conflicts! {
+            r0 : w0,
+            r1 : w1,
+            r2 : w2,
+            r3 : w3,
+            r4 : w4,
+            r5 : w5,
+            r6 : w6,
+            r7 : w7,
+            r8 : w8,
+            r9 : w9
+        }
+    }
+}
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index c17c2961434..305ea7d50e6 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -148,6 +148,7 @@ macro_rules! types {
 
 mod aarch64;
 mod arm;
+mod bpf;
 mod hexagon;
 mod mips;
 mod nvptx;
@@ -159,6 +160,7 @@ mod x86;
 
 pub use aarch64::{AArch64InlineAsmReg, AArch64InlineAsmRegClass};
 pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass};
+pub use bpf::{BpfInlineAsmReg, BpfInlineAsmRegClass};
 pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass};
 pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass};
 pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass};
@@ -184,6 +186,7 @@ pub enum InlineAsmArch {
     PowerPC64,
     SpirV,
     Wasm32,
+    Bpf,
 }
 
 impl FromStr for InlineAsmArch {
@@ -205,6 +208,7 @@ impl FromStr for InlineAsmArch {
             "mips64" => Ok(Self::Mips64),
             "spirv" => Ok(Self::SpirV),
             "wasm32" => Ok(Self::Wasm32),
+            "bpf" => Ok(Self::Bpf),
             _ => Err(()),
         }
     }
@@ -233,6 +237,7 @@ pub enum InlineAsmReg {
     Mips(MipsInlineAsmReg),
     SpirV(SpirVInlineAsmReg),
     Wasm(WasmInlineAsmReg),
+    Bpf(BpfInlineAsmReg),
     // Placeholder for invalid register constraints for the current target
     Err,
 }
@@ -247,6 +252,7 @@ impl InlineAsmReg {
             Self::PowerPC(r) => r.name(),
             Self::Hexagon(r) => r.name(),
             Self::Mips(r) => r.name(),
+            Self::Bpf(r) => r.name(),
             Self::Err => "<reg>",
         }
     }
@@ -260,6 +266,7 @@ impl InlineAsmReg {
             Self::PowerPC(r) => InlineAsmRegClass::PowerPC(r.reg_class()),
             Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()),
             Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()),
+            Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()),
             Self::Err => InlineAsmRegClass::Err,
         }
     }
@@ -304,6 +311,9 @@ impl InlineAsmReg {
             InlineAsmArch::Wasm32 => {
                 Self::Wasm(WasmInlineAsmReg::parse(arch, has_feature, target, &name)?)
             }
+            InlineAsmArch::Bpf => {
+                Self::Bpf(BpfInlineAsmReg::parse(arch, has_feature, target, &name)?)
+            }
         })
     }
 
@@ -323,6 +333,7 @@ impl InlineAsmReg {
             Self::PowerPC(r) => r.emit(out, arch, modifier),
             Self::Hexagon(r) => r.emit(out, arch, modifier),
             Self::Mips(r) => r.emit(out, arch, modifier),
+            Self::Bpf(r) => r.emit(out, arch, modifier),
             Self::Err => unreachable!("Use of InlineAsmReg::Err"),
         }
     }
@@ -336,6 +347,7 @@ impl InlineAsmReg {
             Self::PowerPC(_) => cb(self),
             Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))),
             Self::Mips(_) => cb(self),
+            Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))),
             Self::Err => unreachable!("Use of InlineAsmReg::Err"),
         }
     }
@@ -364,6 +376,7 @@ pub enum InlineAsmRegClass {
     Mips(MipsInlineAsmRegClass),
     SpirV(SpirVInlineAsmRegClass),
     Wasm(WasmInlineAsmRegClass),
+    Bpf(BpfInlineAsmRegClass),
     // Placeholder for invalid register constraints for the current target
     Err,
 }
@@ -381,6 +394,7 @@ impl InlineAsmRegClass {
             Self::Mips(r) => r.name(),
             Self::SpirV(r) => r.name(),
             Self::Wasm(r) => r.name(),
+            Self::Bpf(r) => r.name(),
             Self::Err => rustc_span::symbol::sym::reg,
         }
     }
@@ -400,6 +414,7 @@ impl InlineAsmRegClass {
             Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips),
             Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV),
             Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm),
+            Self::Bpf(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Bpf),
             Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
         }
     }
@@ -426,6 +441,7 @@ impl InlineAsmRegClass {
             Self::Mips(r) => r.suggest_modifier(arch, ty),
             Self::SpirV(r) => r.suggest_modifier(arch, ty),
             Self::Wasm(r) => r.suggest_modifier(arch, ty),
+            Self::Bpf(r) => r.suggest_modifier(arch, ty),
             Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
         }
     }
@@ -448,6 +464,7 @@ impl InlineAsmRegClass {
             Self::Mips(r) => r.default_modifier(arch),
             Self::SpirV(r) => r.default_modifier(arch),
             Self::Wasm(r) => r.default_modifier(arch),
+            Self::Bpf(r) => r.default_modifier(arch),
             Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
         }
     }
@@ -469,6 +486,7 @@ impl InlineAsmRegClass {
             Self::Mips(r) => r.supported_types(arch),
             Self::SpirV(r) => r.supported_types(arch),
             Self::Wasm(r) => r.supported_types(arch),
+            Self::Bpf(r) => r.supported_types(arch),
             Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
         }
     }
@@ -493,6 +511,7 @@ impl InlineAsmRegClass {
             }
             InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(arch, name)?),
             InlineAsmArch::Wasm32 => Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?),
+            InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(arch, name)?),
         })
     }
 
@@ -510,6 +529,7 @@ impl InlineAsmRegClass {
             Self::Mips(r) => r.valid_modifiers(arch),
             Self::SpirV(r) => r.valid_modifiers(arch),
             Self::Wasm(r) => r.valid_modifiers(arch),
+            Self::Bpf(r) => r.valid_modifiers(arch),
             Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
         }
     }
@@ -679,5 +699,10 @@ pub fn allocatable_registers(
             wasm::fill_reg_map(arch, has_feature, target, &mut map);
             map
         }
+        InlineAsmArch::Bpf => {
+            let mut map = bpf::regclass_map();
+            bpf::fill_reg_map(arch, has_feature, target, &mut map);
+            map
+        }
     }
 }
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index a40de5ef18e..cb8f6b9656c 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -9,13 +9,11 @@
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(bool_to_option)]
-#![feature(const_panic)]
 #![feature(nll)]
 #![feature(never_type)]
 #![feature(associated_type_bounds)]
 #![feature(exhaustive_patterns)]
 #![feature(min_specialization)]
-#![feature(trusted_step)]
 
 use std::path::{Path, PathBuf};
 
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs
index 2218c6c6da7..5682039b865 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios.rs
@@ -10,7 +10,6 @@ pub fn target() -> Target {
         arch: "aarch64".to_string(),
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".to_string(),
-            eliminate_frame_pointer: false,
             max_atomic_width: Some(128),
             unsupported_abis: super::arm_base::unsupported_abis(),
             forces_embed_bitcode: true,
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
index 758950bd344..8a832546d09 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
@@ -10,7 +10,6 @@ pub fn target() -> Target {
         arch: "aarch64".to_string(),
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a12".to_string(),
-            eliminate_frame_pointer: false,
             max_atomic_width: Some(128),
             unsupported_abis: super::arm_base::unsupported_abis(),
             forces_embed_bitcode: true,
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs
index e594ceec1b7..2187015b627 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_sim.rs
@@ -18,7 +18,6 @@ pub fn target() -> Target {
         arch: "aarch64".to_string(),
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".to_string(),
-            eliminate_frame_pointer: false,
             max_atomic_width: Some(128),
             unsupported_abis: super::arm_base::unsupported_abis(),
             forces_embed_bitcode: true,
diff --git a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs
index a83de77dc2a..cb6c06b3711 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_tvos.rs
@@ -10,7 +10,6 @@ pub fn target() -> Target {
         arch: "aarch64".to_string(),
         options: TargetOptions {
             features: "+neon,+fp-armv8,+apple-a7".to_string(),
-            eliminate_frame_pointer: false,
             max_atomic_width: Some(128),
             unsupported_abis: super::arm_base::unsupported_abis(),
             forces_embed_bitcode: true,
diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs
index 45c5c1a16e9..8530db179d9 100644
--- a/compiler/rustc_target/src/spec/apple_base.rs
+++ b/compiler/rustc_target/src/spec/apple_base.rs
@@ -27,6 +27,7 @@ pub fn opts(os: &str) -> TargetOptions {
         families: vec!["unix".to_string()],
         is_like_osx: true,
         dwarf_version: Some(2),
+        eliminate_frame_pointer: false,
         has_rpath: true,
         dll_suffix: ".dylib".to_string(),
         archive_format: "darwin".to_string(),
diff --git a/compiler/rustc_target/src/spec/apple_sdk_base.rs b/compiler/rustc_target/src/spec/apple_sdk_base.rs
index 538c4ca8697..e7f7bb343d0 100644
--- a/compiler/rustc_target/src/spec/apple_sdk_base.rs
+++ b/compiler/rustc_target/src/spec/apple_sdk_base.rs
@@ -44,7 +44,6 @@ pub fn opts(os: &str, arch: Arch) -> TargetOptions {
         executables: true,
         link_env_remove: link_env_remove(arch),
         has_elf_tls: false,
-        eliminate_frame_pointer: false,
         ..super::apple_base::opts(os)
     }
 }
diff --git a/compiler/rustc_target/src/spec/bpf_base.rs b/compiler/rustc_target/src/spec/bpf_base.rs
new file mode 100644
index 00000000000..764cc735d75
--- /dev/null
+++ b/compiler/rustc_target/src/spec/bpf_base.rs
@@ -0,0 +1,42 @@
+use crate::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, TargetOptions};
+use crate::{abi::Endian, spec::abi::Abi};
+
+pub fn opts(endian: Endian) -> TargetOptions {
+    TargetOptions {
+        allow_asm: true,
+        endian,
+        linker_flavor: LinkerFlavor::BpfLinker,
+        atomic_cas: false,
+        executables: true,
+        dynamic_linking: true,
+        no_builtins: true,
+        panic_strategy: PanicStrategy::Abort,
+        position_independent_executables: true,
+        // Disable MergeFunctions since:
+        // - older kernels don't support bpf-to-bpf calls
+        // - on newer kernels, userspace still needs to relocate before calling
+        //   BPF_PROG_LOAD and not all BPF libraries do that yet
+        merge_functions: MergeFunctions::Disabled,
+        obj_is_bitcode: true,
+        requires_lto: false,
+        singlethread: true,
+        max_atomic_width: Some(64),
+        unsupported_abis: vec![
+            Abi::Cdecl,
+            Abi::Stdcall { unwind: false },
+            Abi::Stdcall { unwind: true },
+            Abi::Fastcall,
+            Abi::Vectorcall,
+            Abi::Thiscall { unwind: false },
+            Abi::Thiscall { unwind: true },
+            Abi::Aapcs,
+            Abi::Win64,
+            Abi::SysV64,
+            Abi::PtxKernel,
+            Abi::Msp430Interrupt,
+            Abi::X86Interrupt,
+            Abi::AmdGpuKernel,
+        ],
+        ..Default::default()
+    }
+}
diff --git a/compiler/rustc_target/src/spec/bpfeb_unknown_none.rs b/compiler/rustc_target/src/spec/bpfeb_unknown_none.rs
new file mode 100644
index 00000000000..a45da82eb40
--- /dev/null
+++ b/compiler/rustc_target/src/spec/bpfeb_unknown_none.rs
@@ -0,0 +1,12 @@
+use crate::spec::Target;
+use crate::{abi::Endian, spec::bpf_base};
+
+pub fn target() -> Target {
+    Target {
+        llvm_target: "bpfeb".to_string(),
+        data_layout: "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128".to_string(),
+        pointer_width: 64,
+        arch: "bpf".to_string(),
+        options: bpf_base::opts(Endian::Big),
+    }
+}
diff --git a/compiler/rustc_target/src/spec/bpfel_unknown_none.rs b/compiler/rustc_target/src/spec/bpfel_unknown_none.rs
new file mode 100644
index 00000000000..6c9afdf35ae
--- /dev/null
+++ b/compiler/rustc_target/src/spec/bpfel_unknown_none.rs
@@ -0,0 +1,12 @@
+use crate::spec::Target;
+use crate::{abi::Endian, spec::bpf_base};
+
+pub fn target() -> Target {
+    Target {
+        llvm_target: "bpfel".to_string(),
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".to_string(),
+        pointer_width: 64,
+        arch: "bpf".to_string(),
+        options: bpf_base::opts(Endian::Little),
+    }
+}
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index f1bd8ff237d..0f2aaeb533a 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -57,6 +57,7 @@ mod apple_base;
 mod apple_sdk_base;
 mod arm_base;
 mod avr_gnu_base;
+mod bpf_base;
 mod dragonfly_base;
 mod freebsd_base;
 mod fuchsia_base;
@@ -93,6 +94,7 @@ pub enum LinkerFlavor {
     Msvc,
     Lld(LldFlavor),
     PtxLinker,
+    BpfLinker,
 }
 
 #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
@@ -161,6 +163,7 @@ flavor_mappings! {
     ((LinkerFlavor::Ld), "ld"),
     ((LinkerFlavor::Msvc), "msvc"),
     ((LinkerFlavor::PtxLinker), "ptx-linker"),
+    ((LinkerFlavor::BpfLinker), "bpf-linker"),
     ((LinkerFlavor::Lld(LldFlavor::Wasm)), "wasm-ld"),
     ((LinkerFlavor::Lld(LldFlavor::Ld64)), "ld64.lld"),
     ((LinkerFlavor::Lld(LldFlavor::Ld)), "ld.lld"),
@@ -897,6 +900,9 @@ supported_targets! {
     ("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
     ("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),
     ("aarch64_be-unknown-linux-gnu_ilp32", aarch64_be_unknown_linux_gnu_ilp32),
+
+    ("bpfeb-unknown-none", bpfeb_unknown_none),
+    ("bpfel-unknown-none", bpfel_unknown_none),
 }
 
 /// Everything `rustc` knows about how to compile for a specific target.
@@ -922,6 +928,7 @@ pub trait HasTargetSpec {
 }
 
 impl HasTargetSpec for Target {
+    #[inline]
     fn target_spec(&self) -> &Target {
         self
     }
diff --git a/compiler/rustc_target/src/spec/msp430_none_elf.rs b/compiler/rustc_target/src/spec/msp430_none_elf.rs
index cc2578aa578..6e3a241a86e 100644
--- a/compiler/rustc_target/src/spec/msp430_none_elf.rs
+++ b/compiler/rustc_target/src/spec/msp430_none_elf.rs
@@ -17,6 +17,7 @@ pub fn target() -> Target {
             // dependency on this specific gcc.
             asm_args: vec!["-mcpu=msp430".to_string()],
             linker: Some("msp430-elf-gcc".to_string()),
+            linker_is_gnu: false,
 
             // There are no atomic CAS instructions available in the MSP430
             // instruction set, and the LLVM backend doesn't currently support
diff --git a/compiler/rustc_target/src/spec/wasm_base.rs b/compiler/rustc_target/src/spec/wasm_base.rs
index 87e740de08e..4c954a1e567 100644
--- a/compiler/rustc_target/src/spec/wasm_base.rs
+++ b/compiler/rustc_target/src/spec/wasm_base.rs
@@ -102,12 +102,7 @@ pub fn options() -> TargetOptions {
         // we use the LLD shipped with the Rust toolchain by default
         linker: Some("rust-lld".to_owned()),
         lld_flavor: LldFlavor::Wasm,
-
-        // No need for indirection here, simd types can always be passed by
-        // value as the whole module either has simd or not, which is different
-        // from x86 (for example) where programs can have functions that don't
-        // enable simd features.
-        simd_types_indirect: false,
+        linker_is_gnu: false,
 
         pre_link_args,
 
diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs
index 3f24a33f7d5..ac2e0ebae32 100644
--- a/compiler/rustc_trait_selection/src/autoderef.rs
+++ b/compiler/rustc_trait_selection/src/autoderef.rs
@@ -6,6 +6,7 @@ use rustc_infer::infer::InferCtxt;
 use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt, WithConstness};
 use rustc_middle::ty::{ToPredicate, TypeFoldable};
 use rustc_session::DiagnosticMessageId;
+use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::Span;
 
 #[derive(Copy, Clone, Debug)]
@@ -231,7 +232,8 @@ pub fn report_autoderef_recursion_limit_error<'tcx>(tcx: TyCtxt<'tcx>, span: Spa
         .span_label(span, "deref recursion limit reached")
         .help(&format!(
             "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
-            suggested_limit, tcx.crate_name,
+            suggested_limit,
+            tcx.crate_name(LOCAL_CRATE),
         ))
         .emit();
     }
diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs
index 163df26e9ff..89ec211f262 100644
--- a/compiler/rustc_trait_selection/src/opaque_types.rs
+++ b/compiler/rustc_trait_selection/src/opaque_types.rs
@@ -2,21 +2,22 @@ use crate::infer::InferCtxtExt as _;
 use crate::traits::{self, PredicateObligation};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::vec_map::VecMap;
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::Node;
 use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
 use rustc_infer::infer::free_regions::FreeRegionRelations;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::infer::{self, InferCtxt, InferOk};
 use rustc_middle::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor};
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef};
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst};
+use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt};
 use rustc_span::Span;
 
 use std::ops::ControlFlow;
 
-pub type OpaqueTypeMap<'tcx> = DefIdMap<OpaqueTypeDecl<'tcx>>;
+pub type OpaqueTypeMap<'tcx> = VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>;
 
 /// Information about the opaque types whose values we
 /// are inferring in this function (these are the `impl Trait` that
@@ -26,19 +27,6 @@ pub struct OpaqueTypeDecl<'tcx> {
     /// The opaque type (`ty::Opaque`) for this declaration.
     pub opaque_type: Ty<'tcx>,
 
-    /// The substitutions that we apply to the opaque type that this
-    /// `impl Trait` desugars to. e.g., if:
-    ///
-    ///     fn foo<'a, 'b, T>() -> impl Trait<'a>
-    ///
-    /// winds up desugared to:
-    ///
-    ///     type Foo<'x, X> = impl Trait<'x>
-    ///     fn foo<'a, 'b, T>() -> Foo<'a, T>
-    ///
-    /// then `substs` would be `['a, T]`.
-    pub substs: SubstsRef<'tcx>,
-
     /// The span of this particular definition of the opaque type. So
     /// for example:
     ///
@@ -125,7 +113,7 @@ pub trait InferCtxtExt<'tcx> {
 
     fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
         &self,
-        def_id: DefId,
+        opaque_type_key: OpaqueTypeKey<'tcx>,
         opaque_defn: &OpaqueTypeDecl<'tcx>,
         mode: GenerateMemberConstraints,
         free_region_relations: &FRR,
@@ -136,14 +124,13 @@ pub trait InferCtxtExt<'tcx> {
         &self,
         concrete_ty: Ty<'tcx>,
         opaque_defn: &OpaqueTypeDecl<'tcx>,
-        opaque_type_def_id: DefId,
+        opaque_type_key: OpaqueTypeKey<'tcx>,
         first_own_region_index: usize,
     );
 
     fn infer_opaque_definition_from_instantiation(
         &self,
-        def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        opaque_type_key: OpaqueTypeKey<'tcx>,
         instantiated_ty: Ty<'tcx>,
         span: Span,
     ) -> Ty<'tcx>;
@@ -370,10 +357,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
     ) {
         debug!("constrain_opaque_types()");
 
-        for (&def_id, opaque_defn) in opaque_types {
+        for &(opaque_type_key, opaque_defn) in opaque_types {
             self.constrain_opaque_type(
-                def_id,
-                opaque_defn,
+                opaque_type_key,
+                &opaque_defn,
                 GenerateMemberConstraints::WhenRequired,
                 free_region_relations,
             );
@@ -383,11 +370,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
     /// See `constrain_opaque_types` for documentation.
     fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
         &self,
-        def_id: DefId,
+        opaque_type_key: OpaqueTypeKey<'tcx>,
         opaque_defn: &OpaqueTypeDecl<'tcx>,
         mode: GenerateMemberConstraints,
         free_region_relations: &FRR,
     ) {
+        let def_id = opaque_type_key.def_id;
+
         debug!("constrain_opaque_type()");
         debug!("constrain_opaque_type: def_id={:?}", def_id);
         debug!("constrain_opaque_type: opaque_defn={:#?}", opaque_defn);
@@ -426,9 +415,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             let bounds = tcx.explicit_item_bounds(def_id);
             debug!("constrain_opaque_type: predicates: {:#?}", bounds);
             let bounds: Vec<_> =
-                bounds.iter().map(|(bound, _)| bound.subst(tcx, opaque_defn.substs)).collect();
+                bounds.iter().map(|(bound, _)| bound.subst(tcx, opaque_type_key.substs)).collect();
             debug!("constrain_opaque_type: bounds={:#?}", bounds);
-            let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs);
+            let opaque_type = tcx.mk_opaque(def_id, opaque_type_key.substs);
 
             let required_region_bounds =
                 required_region_bounds(tcx, opaque_type, bounds.into_iter());
@@ -440,7 +429,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 });
             }
             if let GenerateMemberConstraints::IfNoStaticBound = mode {
-                self.generate_member_constraint(concrete_ty, opaque_defn, def_id, first_own_region);
+                self.generate_member_constraint(
+                    concrete_ty,
+                    opaque_defn,
+                    opaque_type_key,
+                    first_own_region,
+                );
             }
             return;
         }
@@ -454,7 +448,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         // second.
         let mut least_region = None;
 
-        for subst_arg in &opaque_defn.substs[first_own_region..] {
+        for subst_arg in &opaque_type_key.substs[first_own_region..] {
             let subst_region = match subst_arg.unpack() {
                 GenericArgKind::Lifetime(r) => r,
                 GenericArgKind::Type(_) | GenericArgKind::Const(_) => continue,
@@ -484,7 +478,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         return self.generate_member_constraint(
                             concrete_ty,
                             opaque_defn,
-                            def_id,
+                            opaque_type_key,
                             first_own_region,
                         );
                     }
@@ -497,7 +491,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
 
         if let GenerateMemberConstraints::IfNoStaticBound = mode {
             if least_region != tcx.lifetimes.re_static {
-                self.generate_member_constraint(concrete_ty, opaque_defn, def_id, first_own_region);
+                self.generate_member_constraint(
+                    concrete_ty,
+                    opaque_defn,
+                    opaque_type_key,
+                    first_own_region,
+                );
             }
         }
         concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
@@ -517,14 +516,14 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         &self,
         concrete_ty: Ty<'tcx>,
         opaque_defn: &OpaqueTypeDecl<'tcx>,
-        opaque_type_def_id: DefId,
+        opaque_type_key: OpaqueTypeKey<'tcx>,
         first_own_region: usize,
     ) {
         // Create the set of choice regions: each region in the hidden
         // type can be equal to any of the region parameters of the
         // opaque type definition.
         let choice_regions: Lrc<Vec<ty::Region<'tcx>>> = Lrc::new(
-            opaque_defn.substs[first_own_region..]
+            opaque_type_key.substs[first_own_region..]
                 .iter()
                 .filter_map(|arg| match arg.unpack() {
                     GenericArgKind::Lifetime(r) => Some(r),
@@ -537,7 +536,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
             op: |r| {
                 self.member_constraint(
-                    opaque_type_def_id,
+                    opaque_type_key.def_id,
                     opaque_defn.definition_span,
                     concrete_ty,
                     r,
@@ -572,11 +571,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
     ///   `opaque_defn.concrete_ty`
     fn infer_opaque_definition_from_instantiation(
         &self,
-        def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        opaque_type_key: OpaqueTypeKey<'tcx>,
         instantiated_ty: Ty<'tcx>,
         span: Span,
     ) -> Ty<'tcx> {
+        let OpaqueTypeKey { def_id, substs } = opaque_type_key;
+
         debug!(
             "infer_opaque_definition_from_instantiation(def_id={:?}, instantiated_ty={:?})",
             def_id, instantiated_ty
@@ -1007,7 +1007,9 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
                             ),
                         };
                         if in_definition_scope {
-                            return self.fold_opaque_ty(ty, def_id.to_def_id(), substs, origin);
+                            let opaque_type_key =
+                                OpaqueTypeKey { def_id: def_id.to_def_id(), substs };
+                            return self.fold_opaque_ty(ty, opaque_type_key, origin);
                         }
 
                         debug!(
@@ -1029,18 +1031,18 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
     fn fold_opaque_ty(
         &mut self,
         ty: Ty<'tcx>,
-        def_id: DefId,
-        substs: SubstsRef<'tcx>,
+        opaque_type_key: OpaqueTypeKey<'tcx>,
         origin: hir::OpaqueTyOrigin,
     ) -> Ty<'tcx> {
         let infcx = self.infcx;
         let tcx = infcx.tcx;
+        let OpaqueTypeKey { def_id, substs } = opaque_type_key;
 
         debug!("instantiate_opaque_types: Opaque(def_id={:?}, substs={:?})", def_id, substs);
 
         // Use the same type variable if the exact same opaque type appears more
         // than once in the return type (e.g., if it's passed to a type alias).
-        if let Some(opaque_defn) = self.opaque_types.get(&def_id) {
+        if let Some(opaque_defn) = self.opaque_types.get(&opaque_type_key) {
             debug!("instantiate_opaque_types: returning concrete ty {:?}", opaque_defn.concrete_ty);
             return opaque_defn.concrete_ty;
         }
@@ -1078,10 +1080,9 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
         let definition_span = self.value_span;
 
         self.opaque_types.insert(
-            def_id,
+            OpaqueTypeKey { def_id, substs },
             OpaqueTypeDecl {
                 opaque_type: ty,
-                substs,
                 definition_span,
                 concrete_ty: ty_var,
                 has_required_region_bounds: !required_region_bounds.is_empty(),
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 db396356d67..19c3385dd4c 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1878,6 +1878,10 @@ impl<'v> Visitor<'v> for FindTypeParam {
         hir::intravisit::NestedVisitorMap::None
     }
 
+    fn visit_where_predicate(&mut self, _: &'v hir::WherePredicate<'v>) {
+        // Skip where-clauses, to avoid suggesting indirection for type parameters found there.
+    }
+
     fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
         // We collect the spans of all uses of the "bare" type param, like in `field: T` or
         // `field: (T, T)` where we could make `T: ?Sized` while skipping cases that are known to be
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 8bbd2da5375..5c35b515f3d 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -21,6 +21,7 @@ use rustc_middle::ty::{
     Infer, InferTy, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
 };
 use rustc_middle::ty::{TypeAndMut, TypeckResults};
+use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP};
 use rustc_target::spec::abi;
@@ -2313,7 +2314,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         let suggested_limit = current_limit * 2;
         err.help(&format!(
             "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
-            suggested_limit, self.tcx.crate_name,
+            suggested_limit,
+            self.tcx.crate_name(LOCAL_CRATE),
         ));
     }
 
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index f38c5d8f2f7..ebc7b0d0d99 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -6,7 +6,7 @@ use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{
     self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness,
 };
-use rustc_span::symbol::Symbol;
+use rustc_session::CrateDisambiguator;
 use rustc_span::Span;
 use rustc_trait_selection::traits;
 
@@ -388,9 +388,9 @@ fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamE
     tcx.param_env(def_id).with_reveal_all_normalized(tcx)
 }
 
-fn original_crate_name(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Symbol {
+fn crate_disambiguator(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateDisambiguator {
     assert_eq!(crate_num, LOCAL_CRATE);
-    tcx.crate_name
+    tcx.sess.local_crate_disambiguator()
 }
 
 fn instance_def_size_estimate<'tcx>(
@@ -538,7 +538,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
         param_env,
         param_env_reveal_all_normalized,
         trait_of_item,
-        original_crate_name,
+        crate_disambiguator,
         instance_def_size_estimate,
         issue33140_self_ty,
         impl_defaultness,
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 3f4c8a72f1d..2d102127dd9 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -1,5 +1,4 @@
 #![feature(min_specialization)]
-#![feature(trusted_step)]
 
 #[macro_use]
 extern crate bitflags;
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 92d7ea26003..70d85796d00 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -16,7 +16,7 @@ use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::layout::MAX_SIMD_LANES;
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
-use rustc_middle::ty::{self, ParamEnv, RegionKind, Ty, TyCtxt};
+use rustc_middle::ty::{self, OpaqueTypeKey, ParamEnv, RegionKind, Ty, TyCtxt};
 use rustc_session::lint::builtin::UNINHABITED_STATIC;
 use rustc_span::symbol::sym;
 use rustc_span::{self, MultiSpan, Span};
@@ -716,10 +716,10 @@ fn check_opaque_meets_bounds<'tcx>(
             infcx.instantiate_opaque_types(def_id, hir_id, param_env, opaque_ty, span),
         );
 
-        for (def_id, opaque_defn) in opaque_type_map {
+        for (OpaqueTypeKey { def_id, substs }, opaque_defn) in opaque_type_map {
             match infcx
                 .at(&misc_cause, param_env)
-                .eq(opaque_defn.concrete_ty, tcx.type_of(def_id).subst(tcx, opaque_defn.substs))
+                .eq(opaque_defn.concrete_ty, tcx.type_of(def_id).subst(tcx, substs))
             {
                 Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok),
                 Err(ty_err) => tcx.sess.delay_span_bug(
@@ -1214,10 +1214,19 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
                 }
             }
 
+            // Check that we use types valid for use in the lanes of a SIMD "vector register"
+            // These are scalar types which directly match a "machine" type
+            // Yes: Integers, floats, "thin" pointers
+            // No: char, "fat" pointers, compound types
             match e.kind() {
-                ty::Param(_) => { /* struct<T>(T, T, T, T) is ok */ }
-                _ if e.is_machine() => { /* struct(u8, u8, u8, u8) is ok */ }
-                ty::Array(ty, _c) if ty.is_machine() => { /* struct([f32; 4]) */ }
+                ty::Param(_) => (), // pass struct<T>(T, T, T, T) through, let monomorphization catch errors
+                ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_) => (), // struct(u8, u8, u8, u8) is ok
+                ty::Array(t, _clen)
+                    if matches!(
+                        t.kind(),
+                        ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_)
+                    ) =>
+                { /* struct([f32; 4]) is ok */ }
                 _ => {
                     struct_span_err!(
                         tcx.sess,
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index e5fcdcfa743..33bc25accb3 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -8,6 +8,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{is_range_literal, Node};
+use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut};
 use rustc_span::symbol::sym;
@@ -16,6 +17,7 @@ use rustc_span::Span;
 use super::method::probe;
 
 use std::fmt;
+use std::iter;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub fn emit_coerce_suggestions(
@@ -412,14 +414,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         checked_ty: Ty<'tcx>,
         expected: Ty<'tcx>,
     ) -> Option<(Span, &'static str, String, Applicability)> {
-        let sm = self.sess().source_map();
+        let sess = self.sess();
         let sp = expr.span;
-        if sm.is_imported(sp) {
-            // Ignore if span is from within a macro #41858, #58298. We previously used the macro
-            // call span, but that breaks down when the type error comes from multiple calls down.
+
+        // If the span is from an external macro, there's no suggestion we can make.
+        if in_external_macro(sess, sp) {
             return None;
         }
 
+        let sm = sess.source_map();
+
         let replace_prefix = |s: &str, old: &str, new: &str| {
             s.strip_prefix(old).map(|stripped| new.to_string() + stripped)
         };
@@ -427,10 +431,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let is_struct_pat_shorthand_field =
             self.is_hir_id_from_struct_pattern_shorthand_field(expr.hir_id, sp);
 
-        // If the span is from a macro, then it's hard to extract the text
-        // and make a good suggestion, so don't bother.
-        let is_macro = sp.from_expansion() && sp.desugaring_kind().is_none();
-
         // `ExprKind::DropTemps` is semantically irrelevant for these suggestions.
         let expr = expr.peel_drop_temps();
 
@@ -570,32 +570,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 hir::ExprKind::AddrOf(hir::BorrowKind::Ref, _, ref expr),
                 _,
                 &ty::Ref(_, checked, _),
-            ) if {
-                self.infcx.can_sub(self.param_env, checked, &expected).is_ok() && !is_macro
-            } =>
-            {
+            ) if self.infcx.can_sub(self.param_env, checked, &expected).is_ok() => {
                 // We have `&T`, check if what was expected was `T`. If so,
                 // we may want to suggest removing a `&`.
                 if sm.is_imported(expr.span) {
-                    if let Ok(src) = sm.span_to_snippet(sp) {
-                        if let Some(src) = src.strip_prefix('&') {
+                    // Go through the spans from which this span was expanded,
+                    // and find the one that's pointing inside `sp`.
+                    //
+                    // E.g. for `&format!("")`, where we want the span to the
+                    // `format!()` invocation instead of its expansion.
+                    if let Some(call_span) =
+                        iter::successors(Some(expr.span), |s| s.parent()).find(|&s| sp.contains(s))
+                    {
+                        if let Ok(code) = sm.span_to_snippet(call_span) {
                             return Some((
                                 sp,
                                 "consider removing the borrow",
-                                src.to_string(),
+                                code,
                                 Applicability::MachineApplicable,
                             ));
                         }
                     }
                     return None;
                 }
-                if let Ok(code) = sm.span_to_snippet(expr.span) {
-                    return Some((
-                        sp,
-                        "consider removing the borrow",
-                        code,
-                        Applicability::MachineApplicable,
-                    ));
+                if sp.contains(expr.span) {
+                    if let Ok(code) = sm.span_to_snippet(expr.span) {
+                        return Some((
+                            sp,
+                            "consider removing the borrow",
+                            code,
+                            Applicability::MachineApplicable,
+                        ));
+                    }
                 }
             }
             (
@@ -643,7 +649,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                 }
             }
-            _ if sp == expr.span && !is_macro => {
+            _ if sp == expr.span => {
                 if let Some(steps) = self.deref_steps(checked_ty, expected) {
                     let expr = expr.peel_blocks();
 
diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_typeck/src/check/dropck.rs
index de6336b254b..01276495c18 100644
--- a/compiler/rustc_typeck/src/check/dropck.rs
+++ b/compiler/rustc_typeck/src/check/dropck.rs
@@ -310,6 +310,7 @@ impl TypeRelation<'tcx> for SimpleEqRelation<'tcx> {
     fn relate_with_variance<T: Relate<'tcx>>(
         &mut self,
         _: ty::Variance,
+        _info: ty::VarianceDiagInfo<'tcx>,
         a: T,
         b: T,
     ) -> RelateResult<'tcx, T> {
diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs
index 1dacbade1bd..2e9bef15f90 100644
--- a/compiler/rustc_typeck/src/check/inherited.rs
+++ b/compiler/rustc_typeck/src/check/inherited.rs
@@ -2,13 +2,14 @@ use super::callee::DeferredCallResolution;
 use super::MaybeInProgressTables;
 
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::vec_map::VecMap;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefIdMap, LocalDefId};
 use rustc_hir::HirIdMap;
 use rustc_infer::infer;
 use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
 use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, OpaqueTypeKey, Ty, TyCtxt};
 use rustc_span::{self, Span};
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::opaque_types::OpaqueTypeDecl;
@@ -58,7 +59,7 @@ pub struct Inherited<'a, 'tcx> {
     // associated fresh inference variable. Writeback resolves these
     // variables to get the concrete type, which can be used to
     // 'de-opaque' OpaqueTypeDecl, after typeck is done with all functions.
-    pub(super) opaque_types: RefCell<DefIdMap<OpaqueTypeDecl<'tcx>>>,
+    pub(super) opaque_types: RefCell<VecMap<OpaqueTypeKey<'tcx>, OpaqueTypeDecl<'tcx>>>,
 
     /// A map from inference variables created from opaque
     /// type instantiations (`ty::Infer`) to the actual opaque
diff --git a/compiler/rustc_typeck/src/check/place_op.rs b/compiler/rustc_typeck/src/check/place_op.rs
index a63aec07ad1..652b82f1063 100644
--- a/compiler/rustc_typeck/src/check/place_op.rs
+++ b/compiler/rustc_typeck/src/check/place_op.rs
@@ -248,7 +248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Clear previous flag; after a pointer indirection it does not apply any more.
                 inside_union = false;
             }
-            if source.ty_adt_def().map_or(false, |adt| adt.is_union()) {
+            if source.is_union() {
                 inside_union = true;
             }
             // Fix up the autoderefs. Autorefs can only occur immediately preceding
diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_typeck/src/check/upvar.rs
index 71e222c560a..6baa185406e 100644
--- a/compiler/rustc_typeck/src/check/upvar.rs
+++ b/compiler/rustc_typeck/src/check/upvar.rs
@@ -1588,6 +1588,11 @@ impl<'a, 'tcx> InferBorrowKind<'a, 'tcx> {
 impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
     fn fake_read(&mut self, place: Place<'tcx>, cause: FakeReadCause, diag_expr_id: hir::HirId) {
         if let PlaceBase::Upvar(_) = place.base {
+            // We need to restrict Fake Read precision to avoid fake reading unsafe code,
+            // such as deref of a raw pointer.
+            let place = restrict_capture_precision(place);
+            let place =
+                restrict_repr_packed_field_ref_capture(self.fcx.tcx, self.fcx.param_env, &place);
             self.fake_reads.push((place, cause, diag_expr_id));
         }
     }
diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs
index e472add6e80..032cc7ee233 100644
--- a/compiler/rustc_typeck/src/check/writeback.rs
+++ b/compiler/rustc_typeck/src/check/writeback.rs
@@ -475,8 +475,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
     }
 
     fn visit_opaque_types(&mut self, span: Span) {
-        for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() {
-            let hir_id = self.tcx().hir().local_def_id_to_hir_id(def_id.expect_local());
+        for &(opaque_type_key, opaque_defn) in self.fcx.opaque_types.borrow().iter() {
+            let hir_id =
+                self.tcx().hir().local_def_id_to_hir_id(opaque_type_key.def_id.expect_local());
             let instantiated_ty = self.resolve(opaque_defn.concrete_ty, &hir_id);
 
             debug_assert!(!instantiated_ty.has_escaping_bound_vars());
@@ -494,50 +495,47 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             // ```
             // figures out the concrete type with `U`, but the stored type is with `T`.
             let definition_ty = self.fcx.infer_opaque_definition_from_instantiation(
-                def_id,
-                opaque_defn.substs,
+                opaque_type_key,
                 instantiated_ty,
                 span,
             );
 
             let mut skip_add = false;
 
-            if let ty::Opaque(defin_ty_def_id, _substs) = *definition_ty.kind() {
+            if let ty::Opaque(definition_ty_def_id, _substs) = *definition_ty.kind() {
                 if let hir::OpaqueTyOrigin::Misc | hir::OpaqueTyOrigin::TyAlias = opaque_defn.origin
                 {
-                    if def_id == defin_ty_def_id {
+                    if opaque_type_key.def_id == definition_ty_def_id {
                         debug!(
                             "skipping adding concrete definition for opaque type {:?} {:?}",
-                            opaque_defn, defin_ty_def_id
+                            opaque_defn, opaque_type_key.def_id
                         );
                         skip_add = true;
                     }
                 }
             }
 
-            if !opaque_defn.substs.needs_infer() {
+            if !opaque_type_key.substs.needs_infer() {
                 // We only want to add an entry into `concrete_opaque_types`
                 // if we actually found a defining usage of this opaque type.
                 // Otherwise, we do nothing - we'll either find a defining usage
                 // in some other location, or we'll end up emitting an error due
                 // to the lack of defining usage
                 if !skip_add {
-                    let new = ty::ResolvedOpaqueTy {
-                        concrete_type: definition_ty,
-                        substs: opaque_defn.substs,
-                    };
-
-                    let old = self.typeck_results.concrete_opaque_types.insert(def_id, new);
-                    if let Some(old) = old {
-                        if old.concrete_type != definition_ty || old.substs != opaque_defn.substs {
+                    let old_concrete_ty = self
+                        .typeck_results
+                        .concrete_opaque_types
+                        .insert(opaque_type_key, definition_ty);
+                    if let Some(old_concrete_ty) = old_concrete_ty {
+                        if old_concrete_ty != definition_ty {
                             span_bug!(
                                 span,
                                 "`visit_opaque_types` tried to write different types for the same \
                                  opaque type: {:?}, {:?}, {:?}, {:?}",
-                                def_id,
+                                opaque_type_key.def_id,
                                 definition_ty,
                                 opaque_defn,
-                                old,
+                                old_concrete_ty,
                             );
                         }
                     }
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 0528f8812f9..ee3ac3b62d9 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -2597,6 +2597,7 @@ fn from_target_feature(
                 Some(sym::rtm_target_feature) => rust_features.rtm_target_feature,
                 Some(sym::f16c_target_feature) => rust_features.f16c_target_feature,
                 Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,
+                Some(sym::bpf_target_feature) => rust_features.bpf_target_feature,
                 Some(name) => bug!("unknown target feature gate {}", name),
                 None => true,
             };
@@ -2770,7 +2771,25 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
             }
         } else if tcx.sess.check_name(attr, sym::target_feature) {
             if !tcx.is_closure(id) && tcx.fn_sig(id).unsafety() == hir::Unsafety::Normal {
-                if !tcx.features().target_feature_11 {
+                if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
+                    // The `#[target_feature]` attribute is allowed on
+                    // WebAssembly targets on all functions, including safe
+                    // ones. Other targets require that `#[target_feature]` is
+                    // only applied to unsafe funtions (pending the
+                    // `target_feature_11` feature) because on most targets
+                    // execution of instructions that are not supported is
+                    // considered undefined behavior. For WebAssembly which is a
+                    // 100% safe target at execution time it's not possible to
+                    // execute undefined instructions, and even if a future
+                    // feature was added in some form for this it would be a
+                    // deterministic trap. There is no undefined behavior when
+                    // executing WebAssembly so `#[target_feature]` is allowed
+                    // on safe functions (but again, only for WebAssembly)
+                    //
+                    // Note that this is also allowed if `actually_rustdoc` so
+                    // if a target is documenting some wasm-specific code then
+                    // it's not spuriously denied.
+                } else if !tcx.features().target_feature_11 {
                     let mut err = feature_err(
                         &tcx.sess.parse_sess,
                         sym::target_feature_11,
diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs
index 5197b620f90..29a87b18a9e 100644
--- a/compiler/rustc_typeck/src/collect/type_of.rs
+++ b/compiler/rustc_typeck/src/collect/type_of.rs
@@ -349,8 +349,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     let concrete_ty = tcx
                         .mir_borrowck(owner.expect_local())
                         .concrete_opaque_types
-                        .get(&def_id.to_def_id())
-                        .map(|opaque| opaque.concrete_type)
+                        .get_by(|(key, _)| key.def_id == def_id.to_def_id())
+                        .map(|concrete_ty| *concrete_ty)
                         .unwrap_or_else(|| {
                             tcx.sess.delay_span_bug(
                                 DUMMY_SP,
@@ -515,7 +515,13 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
             }
             // Calling `mir_borrowck` can lead to cycle errors through
             // const-checking, avoid calling it if we don't have to.
-            if !self.tcx.typeck(def_id).concrete_opaque_types.contains_key(&self.def_id) {
+            if self
+                .tcx
+                .typeck(def_id)
+                .concrete_opaque_types
+                .get_by(|(key, _)| key.def_id == self.def_id)
+                .is_none()
+            {
                 debug!(
                     "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`",
                     self.def_id, def_id,
@@ -523,11 +529,13 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
                 return;
             }
             // Use borrowck to get the type with unerased regions.
-            let ty = self.tcx.mir_borrowck(def_id).concrete_opaque_types.get(&self.def_id);
-            if let Some(ty::ResolvedOpaqueTy { concrete_type, substs }) = ty {
+            let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
+            if let Some((opaque_type_key, concrete_type)) =
+                concrete_opaque_types.iter().find(|(key, _)| key.def_id == self.def_id)
+            {
                 debug!(
                     "find_opaque_ty_constraints: found constraint for `{:?}` at `{:?}`: {:?}",
-                    self.def_id, def_id, ty,
+                    self.def_id, def_id, concrete_type,
                 );
 
                 // FIXME(oli-obk): trace the actual span from inference to improve errors.
@@ -538,7 +546,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
                 // using `delay_span_bug`, just in case `wfcheck` slips up.
                 let opaque_generics = self.tcx.generics_of(self.def_id);
                 let mut used_params: FxHashSet<_> = FxHashSet::default();
-                for (i, arg) in substs.iter().enumerate() {
+                for (i, arg) in opaque_type_key.substs.iter().enumerate() {
                     let arg_is_param = match arg.unpack() {
                         GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
                         GenericArgKind::Lifetime(lt) => {
@@ -699,8 +707,8 @@ fn let_position_impl_trait_type(tcx: TyCtxt<'_>, opaque_ty_id: LocalDefId) -> Ty
     let owner_typeck_results = tcx.typeck(scope_def_id);
     let concrete_ty = owner_typeck_results
         .concrete_opaque_types
-        .get(&opaque_ty_def_id)
-        .map(|opaque| opaque.concrete_type)
+        .get_by(|(key, _)| key.def_id == opaque_ty_def_id)
+        .map(|concrete_ty| *concrete_ty)
         .unwrap_or_else(|| {
             tcx.sess.delay_span_bug(
                 DUMMY_SP,
@@ -766,7 +774,7 @@ fn infer_placeholder_type(
             if !ty.references_error() {
                 diag.span_suggestion(
                     span,
-                    "replace `_` with the correct type",
+                    "replace with the correct type",
                     ty.to_string(),
                     Applicability::MaybeIncorrect,
                 );
diff --git a/config.toml.example b/config.toml.example
index df2fb448b7d..7fa5353d09b 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -94,7 +94,7 @@ changelog-seen = 2
 # support. You'll need to write a target specification at least, and most
 # likely, teach rustc about the C ABI of the target. Get in touch with the
 # Rust team and file an issue if you need assistance in porting!
-#targets = "AArch64;ARM;Hexagon;MSP430;Mips;NVPTX;PowerPC;RISCV;Sparc;SystemZ;WebAssembly;X86"
+#targets = "AArch64;ARM;BPF;Hexagon;MSP430;Mips;NVPTX;PowerPC;RISCV;Sparc;SystemZ;WebAssembly;X86"
 
 # LLVM experimental targets to build support for. These targets are specified in
 # the same format as above, but since these targets are experimental, they are
diff --git a/library/alloc/benches/vec.rs b/library/alloc/benches/vec.rs
index c9bdcaa78f3..91eec10d575 100644
--- a/library/alloc/benches/vec.rs
+++ b/library/alloc/benches/vec.rs
@@ -551,19 +551,13 @@ const LEN: usize = 16384;
 #[bench]
 fn bench_chain_collect(b: &mut Bencher) {
     let data = black_box([0; LEN]);
-    b.iter(|| data.iter().cloned().chain([1].iter().cloned()).collect::<Vec<_>>());
+    b.iter(|| data.iter().cloned().chain([1]).collect::<Vec<_>>());
 }
 
 #[bench]
 fn bench_chain_chain_collect(b: &mut Bencher) {
     let data = black_box([0; LEN]);
-    b.iter(|| {
-        data.iter()
-            .cloned()
-            .chain([1].iter().cloned())
-            .chain([2].iter().cloned())
-            .collect::<Vec<_>>()
-    });
+    b.iter(|| data.iter().cloned().chain([1]).chain([2]).collect::<Vec<_>>());
 }
 
 #[bench]
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index 7d6fbf1c438..5d03be35e46 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -2416,7 +2416,6 @@ impl<T> VecDeque<T> {
     /// found; the fourth could match any position in `[1, 4]`.
     ///
     /// ```
-    /// #![feature(vecdeque_binary_search)]
     /// use std::collections::VecDeque;
     ///
     /// let deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into();
@@ -2432,7 +2431,6 @@ impl<T> VecDeque<T> {
     /// sort order:
     ///
     /// ```
-    /// #![feature(vecdeque_binary_search)]
     /// use std::collections::VecDeque;
     ///
     /// let mut deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into();
@@ -2441,7 +2439,7 @@ impl<T> VecDeque<T> {
     /// deque.insert(idx, num);
     /// assert_eq!(deque, &[0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]);
     /// ```
-    #[unstable(feature = "vecdeque_binary_search", issue = "78021")]
+    #[stable(feature = "vecdeque_binary_search", since = "1.54.0")]
     #[inline]
     pub fn binary_search(&self, x: &T) -> Result<usize, usize>
     where
@@ -2476,7 +2474,6 @@ impl<T> VecDeque<T> {
     /// found; the fourth could match any position in `[1, 4]`.
     ///
     /// ```
-    /// #![feature(vecdeque_binary_search)]
     /// use std::collections::VecDeque;
     ///
     /// let deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into();
@@ -2487,7 +2484,7 @@ impl<T> VecDeque<T> {
     /// let r = deque.binary_search_by(|x| x.cmp(&1));
     /// assert!(matches!(r, Ok(1..=4)));
     /// ```
-    #[unstable(feature = "vecdeque_binary_search", issue = "78021")]
+    #[stable(feature = "vecdeque_binary_search", since = "1.54.0")]
     pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
     where
         F: FnMut(&'a T) -> Ordering,
@@ -2530,7 +2527,6 @@ impl<T> VecDeque<T> {
     /// fourth could match any position in `[1, 4]`.
     ///
     /// ```
-    /// #![feature(vecdeque_binary_search)]
     /// use std::collections::VecDeque;
     ///
     /// let deque: VecDeque<_> = vec![(0, 0), (2, 1), (4, 1), (5, 1),
@@ -2543,7 +2539,7 @@ impl<T> VecDeque<T> {
     /// let r = deque.binary_search_by_key(&1, |&(a, b)| b);
     /// assert!(matches!(r, Ok(1..=4)));
     /// ```
-    #[unstable(feature = "vecdeque_binary_search", issue = "78021")]
+    #[stable(feature = "vecdeque_binary_search", since = "1.54.0")]
     #[inline]
     pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize, usize>
     where
@@ -2574,7 +2570,6 @@ impl<T> VecDeque<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(vecdeque_binary_search)]
     /// use std::collections::VecDeque;
     ///
     /// let deque: VecDeque<_> = vec![1, 2, 3, 3, 5, 6, 7].into();
@@ -2584,7 +2579,7 @@ impl<T> VecDeque<T> {
     /// assert!(deque.iter().take(i).all(|&x| x < 5));
     /// assert!(deque.iter().skip(i).all(|&x| !(x < 5)));
     /// ```
-    #[unstable(feature = "vecdeque_binary_search", issue = "78021")]
+    #[stable(feature = "vecdeque_binary_search", since = "1.54.0")]
     pub fn partition_point<P>(&self, mut pred: P) -> usize
     where
         P: FnMut(&T) -> bool,
diff --git a/library/alloc/src/collections/vec_deque/pair_slices.rs b/library/alloc/src/collections/vec_deque/pair_slices.rs
index 812765d0b0d..7b87090fb07 100644
--- a/library/alloc/src/collections/vec_deque/pair_slices.rs
+++ b/library/alloc/src/collections/vec_deque/pair_slices.rs
@@ -1,4 +1,3 @@
-use core::array;
 use core::cmp::{self};
 use core::mem::replace;
 
@@ -37,7 +36,7 @@ impl<'a, 'b, T> PairSlices<'a, 'b, T> {
     }
 
     pub fn remainder(self) -> impl Iterator<Item = &'b [T]> {
-        array::IntoIter::new([self.b0, self.b1])
+        IntoIterator::into_iter([self.b0, self.b1])
     }
 }
 
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 7bc9aa69be9..a04e7c8a498 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -59,7 +59,6 @@
 #![allow(unused_attributes)]
 #![stable(feature = "alloc", since = "1.36.0")]
 #![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
     html_playground_url = "https://play.rust-lang.org/",
     issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
     test(no_crate_inject, attr(allow(unused_variables), deny(warnings)))
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index dbe5bc1da46..93f5fe45cd6 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -48,7 +48,7 @@ use core::fmt;
 use core::hash;
 #[cfg(not(no_global_oom_handling))]
 use core::iter::FromIterator;
-use core::iter::FusedIterator;
+use core::iter::{from_fn, FusedIterator};
 #[cfg(not(no_global_oom_handling))]
 use core::ops::Add;
 #[cfg(not(no_global_oom_handling))]
@@ -1290,32 +1290,49 @@ impl String {
     {
         use core::str::pattern::Searcher;
 
-        let matches = {
+        let rejections = {
             let mut searcher = pat.into_searcher(self);
-            let mut matches = Vec::new();
-
-            while let Some(m) = searcher.next_match() {
-                matches.push(m);
-            }
-
-            matches
+            // Per Searcher::next:
+            //
+            // A Match result needs to contain the whole matched pattern,
+            // however Reject results may be split up into arbitrary many
+            // adjacent fragments. Both ranges may have zero length.
+            //
+            // In practice the implementation of Searcher::next_match tends to
+            // be more efficient, so we use it here and do some work to invert
+            // matches into rejections since that's what we want to copy below.
+            let mut front = 0;
+            let rejections: Vec<_> = from_fn(|| {
+                let (start, end) = searcher.next_match()?;
+                let prev_front = front;
+                front = end;
+                Some((prev_front, start))
+            })
+            .collect();
+            rejections.into_iter().chain(core::iter::once((front, self.len())))
         };
 
-        let len = self.len();
-        let mut shrunk_by = 0;
+        let mut len = 0;
+        let ptr = self.vec.as_mut_ptr();
+
+        for (start, end) in rejections {
+            let count = end - start;
+            if start != len {
+                // SAFETY: per Searcher::next:
+                //
+                // The stream of Match and Reject values up to a Done will
+                // contain index ranges that are adjacent, non-overlapping,
+                // covering the whole haystack, and laying on utf8
+                // boundaries.
+                unsafe {
+                    ptr::copy(ptr.add(start), ptr.add(len), count);
+                }
+            }
+            len += count;
+        }
 
-        // SAFETY: start and end will be on utf8 byte boundaries per
-        // the Searcher docs
         unsafe {
-            for (start, end) in matches {
-                ptr::copy(
-                    self.vec.as_mut_ptr().add(end - shrunk_by),
-                    self.vec.as_mut_ptr().add(start - shrunk_by),
-                    len - end,
-                );
-                shrunk_by += end - start;
-            }
-            self.vec.set_len(len - shrunk_by);
+            self.vec.set_len(len);
         }
     }
 
@@ -2474,6 +2491,9 @@ impl AsRef<[u8]> for String {
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From<&str> for String {
+    /// Converts a `&str` into a [`String`].
+    ///
+    /// The result is allocated on the heap.
     #[inline]
     fn from(s: &str) -> String {
         s.to_owned()
@@ -2483,7 +2503,7 @@ impl From<&str> for String {
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "from_mut_str_for_string", since = "1.44.0")]
 impl From<&mut str> for String {
-    /// Converts a `&mut str` into a `String`.
+    /// Converts a `&mut str` into a [`String`].
     ///
     /// The result is allocated on the heap.
     #[inline]
@@ -2495,6 +2515,9 @@ impl From<&mut str> for String {
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "from_ref_string", since = "1.35.0")]
 impl From<&String> for String {
+    /// Converts a `&String` into a [`String`].
+    ///
+    /// This clones `s` and returns the clone.
     #[inline]
     fn from(s: &String) -> String {
         s.clone()
@@ -2505,7 +2528,7 @@ impl From<&String> for String {
 #[cfg(not(test))]
 #[stable(feature = "string_from_box", since = "1.18.0")]
 impl From<Box<str>> for String {
-    /// Converts the given boxed `str` slice to a `String`.
+    /// Converts the given boxed `str` slice to a [`String`].
     /// It is notable that the `str` slice is owned.
     ///
     /// # Examples
@@ -2527,7 +2550,7 @@ impl From<Box<str>> for String {
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "box_from_str", since = "1.20.0")]
 impl From<String> for Box<str> {
-    /// Converts the given `String` to a boxed `str` slice that is owned.
+    /// Converts the given [`String`] to a boxed `str` slice that is owned.
     ///
     /// # Examples
     ///
@@ -2548,6 +2571,22 @@ impl From<String> for Box<str> {
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "string_from_cow_str", since = "1.14.0")]
 impl<'a> From<Cow<'a, str>> for String {
+    /// Converts a clone-on-write string to an owned
+    /// instance of [`String`].
+    ///
+    /// This extracts the owned string,
+    /// clones the string if it is not already owned.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// # use std::borrow::Cow;
+    /// // If the string is not owned...
+    /// let cow: Cow<str> = Cow::Borrowed("eggplant");
+    /// // It will allocate on the heap and copy the string.
+    /// let owned: String = String::from(cow);
+    /// assert_eq!(&owned[..], "eggplant");
+    /// ```
     fn from(s: Cow<'a, str>) -> String {
         s.into_owned()
     }
@@ -2556,7 +2595,7 @@ impl<'a> From<Cow<'a, str>> for String {
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> From<&'a str> for Cow<'a, str> {
-    /// Converts a string slice into a Borrowed variant.
+    /// Converts a string slice into a [`Borrowed`] variant.
     /// No heap allocation is performed, and the string
     /// is not copied.
     ///
@@ -2566,6 +2605,8 @@ impl<'a> From<&'a str> for Cow<'a, str> {
     /// # use std::borrow::Cow;
     /// assert_eq!(Cow::from("eggplant"), Cow::Borrowed("eggplant"));
     /// ```
+    ///
+    /// [`Borrowed`]: crate::borrow::Cow::Borrowed
     #[inline]
     fn from(s: &'a str) -> Cow<'a, str> {
         Cow::Borrowed(s)
@@ -2575,7 +2616,7 @@ impl<'a> From<&'a str> for Cow<'a, str> {
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> From<String> for Cow<'a, str> {
-    /// Converts a String into an Owned variant.
+    /// Converts a [`String`] into an [`Owned`] variant.
     /// No heap allocation is performed, and the string
     /// is not copied.
     ///
@@ -2587,6 +2628,8 @@ impl<'a> From<String> for Cow<'a, str> {
     /// let s2 = "eggplant".to_string();
     /// assert_eq!(Cow::from(s), Cow::<'static, str>::Owned(s2));
     /// ```
+    ///
+    /// [`Owned`]: crate::borrow::Cow::Owned
     #[inline]
     fn from(s: String) -> Cow<'a, str> {
         Cow::Owned(s)
@@ -2596,7 +2639,7 @@ impl<'a> From<String> for Cow<'a, str> {
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "cow_from_string_ref", since = "1.28.0")]
 impl<'a> From<&'a String> for Cow<'a, str> {
-    /// Converts a String reference into a Borrowed variant.
+    /// Converts a [`String`] reference into a [`Borrowed`] variant.
     /// No heap allocation is performed, and the string
     /// is not copied.
     ///
@@ -2607,6 +2650,8 @@ impl<'a> From<&'a String> for Cow<'a, str> {
     /// let s = "eggplant".to_string();
     /// assert_eq!(Cow::from(&s), Cow::Borrowed("eggplant"));
     /// ```
+    ///
+    /// [`Borrowed`]: crate::borrow::Cow::Borrowed
     #[inline]
     fn from(s: &'a String) -> Cow<'a, str> {
         Cow::Borrowed(s.as_str())
@@ -2639,7 +2684,7 @@ impl<'a> FromIterator<String> for Cow<'a, str> {
 
 #[stable(feature = "from_string_for_vec_u8", since = "1.14.0")]
 impl From<String> for Vec<u8> {
-    /// Converts the given `String` to a vector `Vec` that holds values of type `u8`.
+    /// Converts the given [`String`] to a vector [`Vec`] that holds values of type [`u8`].
     ///
     /// # Examples
     ///
@@ -2785,6 +2830,14 @@ impl FusedIterator for Drain<'_> {}
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "from_char_for_string", since = "1.46.0")]
 impl From<char> for String {
+    /// Allocates an owned [`String`] from a single character.
+    ///
+    /// # Example
+    /// ```rust
+    /// let c: char = 'a';
+    /// let s: String = String::from(c);
+    /// assert_eq!("a", &s[..]);
+    /// ```
     #[inline]
     fn from(c: char) -> Self {
         c.to_string()
diff --git a/library/alloc/src/vec/cow.rs b/library/alloc/src/vec/cow.rs
index 73d15d30647..64943a273c9 100644
--- a/library/alloc/src/vec/cow.rs
+++ b/library/alloc/src/vec/cow.rs
@@ -5,6 +5,12 @@ use super::Vec;
 
 #[stable(feature = "cow_from_vec", since = "1.8.0")]
 impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> {
+    /// Creates a [`Borrowed`] variant of [`Cow`]
+    /// from a slice.
+    ///
+    /// This conversion does not allocate or clone the data.
+    ///
+    /// [`Borrowed`]: crate::borrow::Cow::Borrowed
     fn from(s: &'a [T]) -> Cow<'a, [T]> {
         Cow::Borrowed(s)
     }
@@ -12,6 +18,12 @@ impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> {
 
 #[stable(feature = "cow_from_vec", since = "1.8.0")]
 impl<'a, T: Clone> From<Vec<T>> for Cow<'a, [T]> {
+    /// Creates an [`Owned`] variant of [`Cow`]
+    /// from an owned instance of [`Vec`].
+    ///
+    /// This conversion does not allocate or clone the data.
+    ///
+    /// [`Owned`]: crate::borrow::Cow::Owned
     fn from(v: Vec<T>) -> Cow<'a, [T]> {
         Cow::Owned(v)
     }
@@ -19,6 +31,12 @@ impl<'a, T: Clone> From<Vec<T>> for Cow<'a, [T]> {
 
 #[stable(feature = "cow_from_vec_ref", since = "1.28.0")]
 impl<'a, T: Clone> From<&'a Vec<T>> for Cow<'a, [T]> {
+    /// Creates a [`Borrowed`] variant of [`Cow`]
+    /// from a reference to [`Vec`].
+    ///
+    /// This conversion does not allocate or clone the data.
+    ///
+    /// [`Borrowed`]: crate::borrow::Cow::Borrowed
     fn from(v: &'a Vec<T>) -> Cow<'a, [T]> {
         Cow::Borrowed(v.as_slice())
     }
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 105c60e7bf0..4a1d564e2ab 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -921,7 +921,7 @@ impl<T, A: Allocator> Vec<T, A> {
     ///
     /// ```
     /// let mut vec = Vec::with_capacity(10);
-    /// vec.extend([1, 2, 3].iter().cloned());
+    /// vec.extend([1, 2, 3]);
     /// assert_eq!(vec.capacity(), 10);
     /// vec.shrink_to_fit();
     /// assert!(vec.capacity() >= 3);
@@ -950,7 +950,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// ```
     /// #![feature(shrink_to)]
     /// let mut vec = Vec::with_capacity(10);
-    /// vec.extend([1, 2, 3].iter().cloned());
+    /// vec.extend([1, 2, 3]);
     /// assert_eq!(vec.capacity(), 10);
     /// vec.shrink_to(4);
     /// assert!(vec.capacity() >= 4);
@@ -984,7 +984,7 @@ impl<T, A: Allocator> Vec<T, A> {
     ///
     /// ```
     /// let mut vec = Vec::with_capacity(10);
-    /// vec.extend([1, 2, 3].iter().cloned());
+    /// vec.extend([1, 2, 3]);
     ///
     /// assert_eq!(vec.capacity(), 10);
     /// let slice = vec.into_boxed_slice();
@@ -2586,7 +2586,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// ```
     /// let mut v = vec![1, 2, 3];
     /// let new = [7, 8];
-    /// let u: Vec<_> = v.splice(..2, new.iter().cloned()).collect();
+    /// let u: Vec<_> = v.splice(..2, new).collect();
     /// assert_eq!(v, &[7, 8, 3]);
     /// assert_eq!(u, &[1, 2]);
     /// ```
diff --git a/library/alloc/src/vec/spec_from_iter.rs b/library/alloc/src/vec/spec_from_iter.rs
index bbfcc68daef..efa6868473e 100644
--- a/library/alloc/src/vec/spec_from_iter.rs
+++ b/library/alloc/src/vec/spec_from_iter.rs
@@ -1,6 +1,5 @@
 use core::mem::ManuallyDrop;
 use core::ptr::{self};
-use core::slice::{self};
 
 use super::{IntoIter, SpecExtend, SpecFromIterNested, Vec};
 
@@ -19,9 +18,7 @@ use super::{IntoIter, SpecExtend, SpecFromIterNested, Vec};
 /// |where I:                      |  |  |where I:             |
 /// |  Iterator (default)----------+  |  |  Iterator (default) |
 /// |  vec::IntoIter               |  |  |  TrustedLen         |
-/// |  SourceIterMarker---fallback-+  |  |                     |
-/// |  slice::Iter                    |  |                     |
-/// |  Iterator<Item = &Clone>        |  +---------------------+
+/// |  SourceIterMarker---fallback-+  |  +---------------------+
 /// +---------------------------------+
 /// ```
 pub(super) trait SpecFromIter<T, I> {
@@ -65,33 +62,3 @@ impl<T> SpecFromIter<T, IntoIter<T>> for Vec<T> {
         vec
     }
 }
-
-impl<'a, T: 'a, I> SpecFromIter<&'a T, I> for Vec<T>
-where
-    I: Iterator<Item = &'a T>,
-    T: Clone,
-{
-    default fn from_iter(iterator: I) -> Self {
-        SpecFromIter::from_iter(iterator.cloned())
-    }
-}
-
-// This utilizes `iterator.as_slice().to_vec()` since spec_extend
-// must take more steps to reason about the final capacity + length
-// and thus do more work. `to_vec()` directly allocates the correct amount
-// and fills it exactly.
-impl<'a, T: 'a + Clone> SpecFromIter<&'a T, slice::Iter<'a, T>> for Vec<T> {
-    #[cfg(not(test))]
-    fn from_iter(iterator: slice::Iter<'a, T>) -> Self {
-        iterator.as_slice().to_vec()
-    }
-
-    // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is
-    // required for this method definition, is not available. Instead use the
-    // `slice::to_vec`  function which is only available with cfg(test)
-    // NB see the slice::hack module in slice.rs for more information
-    #[cfg(test)]
-    fn from_iter(iterator: slice::Iter<'a, T>) -> Self {
-        crate::slice::to_vec(iterator.as_slice(), crate::alloc::Global)
-    }
-}
diff --git a/library/alloc/src/vec/splice.rs b/library/alloc/src/vec/splice.rs
index 0a27b5b62ec..bad765c7f51 100644
--- a/library/alloc/src/vec/splice.rs
+++ b/library/alloc/src/vec/splice.rs
@@ -14,7 +14,7 @@ use super::{Drain, Vec};
 /// ```
 /// let mut v = vec![0, 1, 2];
 /// let new = [7, 8];
-/// let iter: std::vec::Splice<_> = v.splice(1.., new.iter().cloned());
+/// let iter: std::vec::Splice<_> = v.splice(1.., new);
 /// ```
 #[derive(Debug)]
 #[stable(feature = "vec_splice", since = "1.21.0")]
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index 25a83a0b014..3143afa269d 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -17,7 +17,6 @@
 #![feature(binary_heap_as_slice)]
 #![feature(inplace_iteration)]
 #![feature(iter_map_while)]
-#![feature(vecdeque_binary_search)]
 #![feature(slice_group_by)]
 #![feature(slice_partition_dedup)]
 #![feature(vec_spare_capacity)]
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index 36c81b49709..c203cdafecb 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -793,7 +793,7 @@ fn test_drain_leak() {
 fn test_splice() {
     let mut v = vec![1, 2, 3, 4, 5];
     let a = [10, 11, 12];
-    v.splice(2..4, a.iter().cloned());
+    v.splice(2..4, a);
     assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
     v.splice(1..3, Some(20));
     assert_eq!(v, &[1, 20, 11, 12, 5]);
@@ -803,7 +803,7 @@ fn test_splice() {
 fn test_splice_inclusive_range() {
     let mut v = vec![1, 2, 3, 4, 5];
     let a = [10, 11, 12];
-    let t1: Vec<_> = v.splice(2..=3, a.iter().cloned()).collect();
+    let t1: Vec<_> = v.splice(2..=3, a).collect();
     assert_eq!(v, &[1, 2, 10, 11, 12, 5]);
     assert_eq!(t1, &[3, 4]);
     let t2: Vec<_> = v.splice(1..=2, Some(20)).collect();
@@ -816,7 +816,7 @@ fn test_splice_inclusive_range() {
 fn test_splice_out_of_bounds() {
     let mut v = vec![1, 2, 3, 4, 5];
     let a = [10, 11, 12];
-    v.splice(5..6, a.iter().cloned());
+    v.splice(5..6, a);
 }
 
 #[test]
@@ -824,7 +824,7 @@ fn test_splice_out_of_bounds() {
 fn test_splice_inclusive_out_of_bounds() {
     let mut v = vec![1, 2, 3, 4, 5];
     let a = [10, 11, 12];
-    v.splice(5..=5, a.iter().cloned());
+    v.splice(5..=5, a);
 }
 
 #[test]
@@ -848,7 +848,7 @@ fn test_splice_unbounded() {
 fn test_splice_forget() {
     let mut v = vec![1, 2, 3, 4, 5];
     let a = [10, 11, 12];
-    std::mem::forget(v.splice(2..4, a.iter().cloned()));
+    std::mem::forget(v.splice(2..4, a));
     assert_eq!(v, &[1, 2]);
 }
 
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index e25d006d213..37af3557fdd 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -416,7 +416,7 @@ impl<T, const N: usize> [T; N] {
     {
         // SAFETY: we know for certain that this iterator will yield exactly `N`
         // items.
-        unsafe { collect_into_array_unchecked(&mut IntoIter::new(self).map(f)) }
+        unsafe { collect_into_array_unchecked(&mut IntoIterator::into_iter(self).map(f)) }
     }
 
     /// 'Zips up' two arrays into a single array of pairs.
@@ -437,7 +437,7 @@ impl<T, const N: usize> [T; N] {
     /// ```
     #[unstable(feature = "array_zip", issue = "80094")]
     pub fn zip<U>(self, rhs: [U; N]) -> [(T, U); N] {
-        let mut iter = IntoIter::new(self).zip(IntoIter::new(rhs));
+        let mut iter = IntoIterator::into_iter(self).zip(rhs);
 
         // SAFETY: we know for certain that this iterator will yield exactly `N`
         // items.
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index dcab2cd2d9d..2da3d6a72fb 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -58,7 +58,7 @@ impl char {
     /// ];
     ///
     /// assert_eq!(
-    ///     decode_utf16(v.iter().cloned())
+    ///     decode_utf16(v)
     ///         .map(|r| r.map_err(|e| e.unpaired_surrogate()))
     ///         .collect::<Vec<_>>(),
     ///     vec![
@@ -82,7 +82,7 @@ impl char {
     /// ];
     ///
     /// assert_eq!(
-    ///     decode_utf16(v.iter().cloned())
+    ///     decode_utf16(v)
     ///        .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
     ///        .collect::<String>(),
     ///     "𝄞mus�ic�"
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 0034de9ad1b..70ab27cbfac 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1742,157 +1742,6 @@ extern "rust-intrinsic" {
     /// Allocate at compile time. Should not be called at runtime.
     #[rustc_const_unstable(feature = "const_heap", issue = "79597")]
     pub fn const_allocate(size: usize, align: usize) -> *mut u8;
-
-    /// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
-    /// and destination must *not* overlap.
-    ///
-    /// For regions of memory which might overlap, use [`copy`] instead.
-    ///
-    /// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`], but
-    /// with the argument order swapped.
-    ///
-    /// [`memcpy`]: https://en.cppreference.com/w/c/string/byte/memcpy
-    ///
-    /// # Safety
-    ///
-    /// Behavior is undefined if any of the following conditions are violated:
-    ///
-    /// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
-    ///
-    /// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
-    ///
-    /// * Both `src` and `dst` must be properly aligned.
-    ///
-    /// * The region of memory beginning at `src` with a size of `count *
-    ///   size_of::<T>()` bytes must *not* overlap with the region of memory
-    ///   beginning at `dst` with the same size.
-    ///
-    /// Like [`read`], `copy_nonoverlapping` creates a bitwise copy of `T`, regardless of
-    /// whether `T` is [`Copy`]. If `T` is not [`Copy`], using *both* the values
-    /// in the region beginning at `*src` and the region beginning at `*dst` can
-    /// [violate memory safety][read-ownership].
-    ///
-    /// Note that even if the effectively copied size (`count * size_of::<T>()`) is
-    /// `0`, the pointers must be non-null and properly aligned.
-    ///
-    /// [`read`]: crate::ptr::read
-    /// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value
-    /// [valid]: crate::ptr#safety
-    ///
-    /// # Examples
-    ///
-    /// Manually implement [`Vec::append`]:
-    ///
-    /// ```
-    /// use std::ptr;
-    ///
-    /// /// Moves all the elements of `src` into `dst`, leaving `src` empty.
-    /// fn append<T>(dst: &mut Vec<T>, src: &mut Vec<T>) {
-    ///     let src_len = src.len();
-    ///     let dst_len = dst.len();
-    ///
-    ///     // Ensure that `dst` has enough capacity to hold all of `src`.
-    ///     dst.reserve(src_len);
-    ///
-    ///     unsafe {
-    ///         // The call to offset is always safe because `Vec` will never
-    ///         // allocate more than `isize::MAX` bytes.
-    ///         let dst_ptr = dst.as_mut_ptr().offset(dst_len as isize);
-    ///         let src_ptr = src.as_ptr();
-    ///
-    ///         // Truncate `src` without dropping its contents. We do this first,
-    ///         // to avoid problems in case something further down panics.
-    ///         src.set_len(0);
-    ///
-    ///         // The two regions cannot overlap because mutable references do
-    ///         // not alias, and two different vectors cannot own the same
-    ///         // memory.
-    ///         ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len);
-    ///
-    ///         // Notify `dst` that it now holds the contents of `src`.
-    ///         dst.set_len(dst_len + src_len);
-    ///     }
-    /// }
-    ///
-    /// let mut a = vec!['r'];
-    /// let mut b = vec!['u', 's', 't'];
-    ///
-    /// append(&mut a, &mut b);
-    ///
-    /// assert_eq!(a, &['r', 'u', 's', 't']);
-    /// assert!(b.is_empty());
-    /// ```
-    ///
-    /// [`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 = "80697")]
-    pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
-
-    /// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
-    /// and destination may overlap.
-    ///
-    /// If the source and destination will *never* overlap,
-    /// [`copy_nonoverlapping`] can be used instead.
-    ///
-    /// `copy` is semantically equivalent to C's [`memmove`], but with the argument
-    /// order swapped. Copying takes place as if the bytes were copied from `src`
-    /// to a temporary array and then copied from the array to `dst`.
-    ///
-    /// [`memmove`]: https://en.cppreference.com/w/c/string/byte/memmove
-    ///
-    /// # Safety
-    ///
-    /// Behavior is undefined if any of the following conditions are violated:
-    ///
-    /// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
-    ///
-    /// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
-    ///
-    /// * Both `src` and `dst` must be properly aligned.
-    ///
-    /// Like [`read`], `copy` creates a bitwise copy of `T`, regardless of
-    /// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the values
-    /// in the region beginning at `*src` and the region beginning at `*dst` can
-    /// [violate memory safety][read-ownership].
-    ///
-    /// Note that even if the effectively copied size (`count * size_of::<T>()`) is
-    /// `0`, the pointers must be non-null and properly aligned.
-    ///
-    /// [`read`]: crate::ptr::read
-    /// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value
-    /// [valid]: crate::ptr#safety
-    ///
-    /// # Examples
-    ///
-    /// Efficiently create a Rust vector from an unsafe buffer:
-    ///
-    /// ```
-    /// use std::ptr;
-    ///
-    /// /// # Safety
-    /// ///
-    /// /// * `ptr` must be correctly aligned for its type and non-zero.
-    /// /// * `ptr` must be valid for reads of `elts` contiguous elements of type `T`.
-    /// /// * Those elements must not be used after calling this function unless `T: Copy`.
-    /// # #[allow(dead_code)]
-    /// unsafe fn from_buf_raw<T>(ptr: *const T, elts: usize) -> Vec<T> {
-    ///     let mut dst = Vec::with_capacity(elts);
-    ///
-    ///     // SAFETY: Our precondition ensures the source is aligned and valid,
-    ///     // and `Vec::with_capacity` ensures that we have usable space to write them.
-    ///     ptr::copy(ptr, dst.as_mut_ptr(), elts);
-    ///
-    ///     // SAFETY: We created it with this much capacity earlier,
-    ///     // and the previous `copy` has initialized these elements.
-    ///     dst.set_len(elts);
-    ///     dst
-    /// }
-    /// ```
-    #[doc(alias = "memmove")]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
-    pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
 }
 
 // Some functions are defined here because they accidentally got made
@@ -1906,6 +1755,192 @@ pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
     !ptr.is_null() && ptr as usize % mem::align_of::<T>() == 0
 }
 
+/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
+/// and destination must *not* overlap.
+///
+/// For regions of memory which might overlap, use [`copy`] instead.
+///
+/// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`], but
+/// with the argument order swapped.
+///
+/// [`memcpy`]: https://en.cppreference.com/w/c/string/byte/memcpy
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
+///
+/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
+///
+/// * Both `src` and `dst` must be properly aligned.
+///
+/// * The region of memory beginning at `src` with a size of `count *
+///   size_of::<T>()` bytes must *not* overlap with the region of memory
+///   beginning at `dst` with the same size.
+///
+/// Like [`read`], `copy_nonoverlapping` creates a bitwise copy of `T`, regardless of
+/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using *both* the values
+/// in the region beginning at `*src` and the region beginning at `*dst` can
+/// [violate memory safety][read-ownership].
+///
+/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
+/// `0`, the pointers must be non-null and properly aligned.
+///
+/// [`read`]: crate::ptr::read
+/// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value
+/// [valid]: crate::ptr#safety
+///
+/// # Examples
+///
+/// Manually implement [`Vec::append`]:
+///
+/// ```
+/// use std::ptr;
+///
+/// /// Moves all the elements of `src` into `dst`, leaving `src` empty.
+/// fn append<T>(dst: &mut Vec<T>, src: &mut Vec<T>) {
+///     let src_len = src.len();
+///     let dst_len = dst.len();
+///
+///     // Ensure that `dst` has enough capacity to hold all of `src`.
+///     dst.reserve(src_len);
+///
+///     unsafe {
+///         // The call to offset is always safe because `Vec` will never
+///         // allocate more than `isize::MAX` bytes.
+///         let dst_ptr = dst.as_mut_ptr().offset(dst_len as isize);
+///         let src_ptr = src.as_ptr();
+///
+///         // Truncate `src` without dropping its contents. We do this first,
+///         // to avoid problems in case something further down panics.
+///         src.set_len(0);
+///
+///         // The two regions cannot overlap because mutable references do
+///         // not alias, and two different vectors cannot own the same
+///         // memory.
+///         ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len);
+///
+///         // Notify `dst` that it now holds the contents of `src`.
+///         dst.set_len(dst_len + src_len);
+///     }
+/// }
+///
+/// let mut a = vec!['r'];
+/// let mut b = vec!['u', 's', 't'];
+///
+/// append(&mut a, &mut b);
+///
+/// assert_eq!(a, &['r', 'u', 's', 't']);
+/// assert!(b.is_empty());
+/// ```
+///
+/// [`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 = "80697")]
+#[inline]
+pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
+    extern "rust-intrinsic" {
+        #[rustc_const_unstable(feature = "const_intrinsic_copy", issue = "80697")]
+        pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+    }
+
+    // FIXME: Perform these checks only at run time
+    /*if cfg!(debug_assertions)
+        && !(is_aligned_and_not_null(src)
+            && is_aligned_and_not_null(dst)
+            && is_nonoverlapping(src, dst, count))
+    {
+        // Not panicking to keep codegen impact smaller.
+        abort();
+    }*/
+
+    // SAFETY: the safety contract for `copy_nonoverlapping` must be
+    // upheld by the caller.
+    unsafe { copy_nonoverlapping(src, dst, count) }
+}
+
+/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
+/// and destination may overlap.
+///
+/// If the source and destination will *never* overlap,
+/// [`copy_nonoverlapping`] can be used instead.
+///
+/// `copy` is semantically equivalent to C's [`memmove`], but with the argument
+/// order swapped. Copying takes place as if the bytes were copied from `src`
+/// to a temporary array and then copied from the array to `dst`.
+///
+/// [`memmove`]: https://en.cppreference.com/w/c/string/byte/memmove
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
+///
+/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
+///
+/// * Both `src` and `dst` must be properly aligned.
+///
+/// Like [`read`], `copy` creates a bitwise copy of `T`, regardless of
+/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the values
+/// in the region beginning at `*src` and the region beginning at `*dst` can
+/// [violate memory safety][read-ownership].
+///
+/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
+/// `0`, the pointers must be non-null and properly aligned.
+///
+/// [`read`]: crate::ptr::read
+/// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value
+/// [valid]: crate::ptr#safety
+///
+/// # Examples
+///
+/// Efficiently create a Rust vector from an unsafe buffer:
+///
+/// ```
+/// use std::ptr;
+///
+/// /// # Safety
+/// ///
+/// /// * `ptr` must be correctly aligned for its type and non-zero.
+/// /// * `ptr` must be valid for reads of `elts` contiguous elements of type `T`.
+/// /// * Those elements must not be used after calling this function unless `T: Copy`.
+/// # #[allow(dead_code)]
+/// unsafe fn from_buf_raw<T>(ptr: *const T, elts: usize) -> Vec<T> {
+///     let mut dst = Vec::with_capacity(elts);
+///
+///     // SAFETY: Our precondition ensures the source is aligned and valid,
+///     // and `Vec::with_capacity` ensures that we have usable space to write them.
+///     ptr::copy(ptr, dst.as_mut_ptr(), elts);
+///
+///     // SAFETY: We created it with this much capacity earlier,
+///     // and the previous `copy` has initialized these elements.
+///     dst.set_len(elts);
+///     dst
+/// }
+/// ```
+#[doc(alias = "memmove")]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[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 = "80697")]
+        fn copy<T>(src: *const T, dst: *mut T, count: usize);
+    }
+
+    // FIXME: Perform these checks only at run time
+    /*if cfg!(debug_assertions) && !(is_aligned_and_not_null(src) && is_aligned_and_not_null(dst)) {
+        // Not panicking to keep codegen impact smaller.
+        abort();
+    }*/
+
+    // SAFETY: the safety contract for `copy` must be upheld by the caller.
+    unsafe { copy(src, dst, count) }
+}
+
 /// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to
 /// `val`.
 ///
diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs
index 92f82ae2325..beda8c32c6b 100644
--- a/library/core/src/iter/adapters/take.rs
+++ b/library/core/src/iter/adapters/take.rs
@@ -1,8 +1,5 @@
 use crate::cmp;
-use crate::iter::{
-    adapters::zip::try_get_unchecked, adapters::SourceIter, FusedIterator, InPlaceIterable,
-    TrustedLen, TrustedRandomAccess,
-};
+use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen};
 use crate::ops::{ControlFlow, Try};
 
 /// An iterator that only iterates over the first `n` iterations of `iter`.
@@ -114,15 +111,6 @@ where
 
         self.try_fold(init, ok(fold)).unwrap()
     }
-
-    unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> <I as Iterator>::Item
-    where
-        Self: TrustedRandomAccess,
-    {
-        // SAFETY: the caller must uphold the contract for
-        // `Iterator::__iterator_get_unchecked`.
-        unsafe { try_get_unchecked(&mut self.iter, idx) }
-    }
 }
 
 #[unstable(issue = "none", feature = "inplace_iteration")]
@@ -219,12 +207,3 @@ impl<I> FusedIterator for Take<I> where I: FusedIterator {}
 
 #[unstable(feature = "trusted_len", issue = "37572")]
 unsafe impl<I: TrustedLen> TrustedLen for Take<I> {}
-
-#[doc(hidden)]
-#[unstable(feature = "trusted_random_access", issue = "none")]
-unsafe impl<I> TrustedRandomAccess for Take<I>
-where
-    I: TrustedRandomAccess,
-{
-    const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT;
-}
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
index 2f8f504d8fc..c95324c80ba 100644
--- a/library/core/src/iter/adapters/zip.rs
+++ b/library/core/src/iter/adapters/zip.rs
@@ -434,7 +434,7 @@ impl<A: Debug + TrustedRandomAccess, B: Debug + TrustedRandomAccess> ZipFmt<A, B
 ///    called on `self`:
 ///     * `std::clone::Clone::clone()`
 ///     * `std::iter::Iterator::size_hint()`
-///     * `std::iter::Iterator::next_back()`
+///     * `std::iter::DoubleEndedIterator::next_back()`
 ///     * `std::iter::Iterator::__iterator_get_unchecked()`
 ///     * `std::iter::TrustedRandomAccess::size()`
 ///
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index a023edaca9e..d4e4c5b0d3e 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -51,7 +51,6 @@
 #![cfg(not(test))]
 #![stable(feature = "core", since = "1.6.0")]
 #![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
     html_playground_url = "https://play.rust-lang.org/",
     issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
     test(no_crate_inject, attr(deny(warnings))),
@@ -160,7 +159,6 @@
 #![feature(const_fn_transmute)]
 #![feature(abi_unadjusted)]
 #![feature(adx_target_feature)]
-#![feature(external_doc)]
 #![feature(associated_type_bounds)]
 #![feature(const_caller_location)]
 #![feature(slice_ptr_get)]
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 5bf47c3951d..c6750c52d16 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -682,8 +682,7 @@ pub unsafe fn uninitialized<T>() -> T {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
-pub const fn swap<T>(x: &mut T, y: &mut T) {
+pub fn swap<T>(x: &mut T, y: &mut T) {
     // SAFETY: the raw pointers have been created from safe mutable references satisfying all the
     // constraints on `ptr::swap_nonoverlapping_one`
     unsafe {
@@ -813,8 +812,7 @@ pub fn take<T: Default>(dest: &mut T) -> T {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[must_use = "if you don't need the old value, you can just assign the new value directly"]
-#[rustc_const_unstable(feature = "const_replace", issue = "83164")]
-pub const fn replace<T>(dest: &mut T, src: T) -> T {
+pub fn replace<T>(dest: &mut T, src: T) -> T {
     // SAFETY: We read from `dest` but directly write `src` into it afterwards,
     // such that the old value is not duplicated. Nothing is dropped and
     // nothing here can panic.
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 77132cddca2..c47a2e8b05c 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -727,8 +727,8 @@ impl f32 {
     ///
     /// This is currently identical to `transmute::<f32, u32>(self)` on all platforms.
     ///
-    /// See `from_bits` for some discussion of the portability of this operation
-    /// (there are almost no issues).
+    /// See [`from_bits`](Self::from_bits) for some discussion of the
+    /// portability of this operation (there are almost no issues).
     ///
     /// Note that this function is distinct from `as` casting, which attempts to
     /// preserve the *numeric* value, and not the bitwise value.
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 4c3f1fd16a0..cfcc08b9add 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -741,8 +741,8 @@ impl f64 {
     ///
     /// This is currently identical to `transmute::<f64, u64>(self)` on all platforms.
     ///
-    /// See `from_bits` for some discussion of the portability of this operation
-    /// (there are almost no issues).
+    /// See [`from_bits`](Self::from_bits) for some discussion of the
+    /// portability of this operation (there are almost no issues).
     ///
     /// Note that this function is distinct from `as` casting, which attempts to
     /// preserve the *numeric* value, and not the bitwise value.
diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs
index dbeb3912130..bb948376bc7 100644
--- a/library/core/src/ops/range.rs
+++ b/library/core/src/ops/range.rs
@@ -674,10 +674,10 @@ pub enum Bound<T> {
     Unbounded,
 }
 
-#[unstable(feature = "bound_as_ref", issue = "80996")]
 impl<T> Bound<T> {
     /// Converts from `&Bound<T>` to `Bound<&T>`.
     #[inline]
+    #[unstable(feature = "bound_as_ref", issue = "80996")]
     pub fn as_ref(&self) -> Bound<&T> {
         match *self {
             Included(ref x) => Included(x),
@@ -686,8 +686,9 @@ impl<T> Bound<T> {
         }
     }
 
-    /// Converts from `&mut Bound<T>` to `Bound<&T>`.
+    /// Converts from `&mut Bound<T>` to `Bound<&mut T>`.
     #[inline]
+    #[unstable(feature = "bound_as_ref", issue = "80996")]
     pub fn as_mut(&mut self) -> Bound<&mut T> {
         match *self {
             Included(ref mut x) => Included(x),
@@ -695,6 +696,39 @@ impl<T> Bound<T> {
             Unbounded => Unbounded,
         }
     }
+
+    /// Maps a `Bound<T>` to a `Bound<U>` by applying a function to the contained value (including
+    /// both `Included` and `Excluded`), returning a `Bound` of the same kind.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(bound_map)]
+    /// use std::ops::Bound::*;
+    ///
+    /// let bound_string = Included("Hello, World!");
+    ///
+    /// assert_eq!(bound_string.map(|s| s.len()), Included(13));
+    /// ```
+    ///
+    /// ```
+    /// #![feature(bound_map)]
+    /// use std::ops::Bound;
+    /// use Bound::*;
+    ///
+    /// let unbounded_string: Bound<String> = Unbounded;
+    ///
+    /// assert_eq!(unbounded_string.map(|s| s.len()), Unbounded);
+    /// ```
+    #[inline]
+    #[unstable(feature = "bound_map", issue = "86026")]
+    pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Bound<U> {
+        match self {
+            Unbounded => Unbounded,
+            Included(x) => Included(f(x)),
+            Excluded(x) => Excluded(f(x)),
+        }
+    }
 }
 
 impl<T: Clone> Bound<&T> {
diff --git a/library/core/src/prelude/mod.rs b/library/core/src/prelude/mod.rs
index 8f57db49496..79753c1fb66 100644
--- a/library/core/src/prelude/mod.rs
+++ b/library/core/src/prelude/mod.rs
@@ -11,9 +11,9 @@ pub mod v1;
 /// The 2015 version of the core prelude.
 ///
 /// See the [module-level documentation](self) for more.
-#[unstable(feature = "prelude_2015", issue = "none")]
+#[unstable(feature = "prelude_2015", issue = "85684")]
 pub mod rust_2015 {
-    #[unstable(feature = "prelude_2015", issue = "none")]
+    #[unstable(feature = "prelude_2015", issue = "85684")]
     #[doc(no_inline)]
     pub use super::v1::*;
 }
@@ -21,9 +21,9 @@ pub mod rust_2015 {
 /// The 2018 version of the core prelude.
 ///
 /// See the [module-level documentation](self) for more.
-#[unstable(feature = "prelude_2018", issue = "none")]
+#[unstable(feature = "prelude_2018", issue = "85684")]
 pub mod rust_2018 {
-    #[unstable(feature = "prelude_2018", issue = "none")]
+    #[unstable(feature = "prelude_2018", issue = "85684")]
     #[doc(no_inline)]
     pub use super::v1::*;
 }
@@ -31,11 +31,17 @@ pub mod rust_2018 {
 /// The 2021 version of the core prelude.
 ///
 /// See the [module-level documentation](self) for more.
-#[unstable(feature = "prelude_2021", issue = "none")]
+#[unstable(feature = "prelude_2021", issue = "85684")]
 pub mod rust_2021 {
-    #[unstable(feature = "prelude_2021", issue = "none")]
+    #[unstable(feature = "prelude_2021", issue = "85684")]
     #[doc(no_inline)]
     pub use super::v1::*;
 
-    // FIXME: Add more things.
+    #[unstable(feature = "prelude_2021", issue = "85684")]
+    #[doc(no_inline)]
+    pub use crate::iter::FromIterator;
+
+    #[unstable(feature = "prelude_2021", issue = "85684")]
+    #[doc(no_inline)]
+    pub use crate::convert::{TryFrom, TryInto};
 }
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 214d7c8bc15..6a6cee0911f 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -430,8 +430,7 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
 }
 
 #[inline]
-#[rustc_const_unstable(feature = "const_swap", issue = "83163")]
-pub(crate) const unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
+pub(crate) unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
     // NOTE(eddyb) SPIR-V's Logical addressing model doesn't allow for arbitrary
     // reinterpretation of values as (chunkable) byte arrays, and the loop in the
     // block optimization in `swap_nonoverlapping_bytes` is hard to rewrite back
@@ -564,8 +563,7 @@ const unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_replace", issue = "83164")]
-pub const unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
+pub unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
     // SAFETY: the caller must guarantee that `dst` is valid to be
     // cast to a mutable reference (valid for writes, aligned, initialized),
     // and cannot overlap `src` since `dst` must point to a distinct
@@ -871,14 +869,18 @@ pub const unsafe fn read_unaligned<T>(src: *const T) -> T {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature = "const_ptr_write", issue = "none")]
-pub const unsafe fn write<T>(dst: *mut T, src: T) {
+pub unsafe fn write<T>(dst: *mut T, src: T) {
+    // We are calling the intrinsics directly to avoid function calls in the generated code
+    // as `intrinsics::copy_nonoverlapping` is a wrapper function.
+    extern "rust-intrinsic" {
+        fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+    }
+
     // SAFETY: the caller must guarantee that `dst` is valid for writes.
     // `dst` cannot overlap `src` because the caller has mutable access
     // to `dst` while `src` is owned by this function.
     unsafe {
         copy_nonoverlapping(&src as *const T, dst, 1);
-        // We are calling the intrinsic directly to avoid function calls in the generated code.
         intrinsics::forget(src);
     }
 }
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 750279ac0db..a6424041542 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -1002,9 +1002,8 @@ impl<T: ?Sized> *mut T {
     ///
     /// [`ptr::write`]: crate::ptr::write()
     #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[rustc_const_unstable(feature = "const_ptr_write", issue = "none")]
     #[inline(always)]
-    pub const unsafe fn write(self, val: T)
+    pub unsafe fn write(self, val: T)
     where
         T: Sized,
     {
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 3bcea4e6d25..0e5c5ee726e 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -2100,9 +2100,11 @@ impl<T> [T] {
     ///
     /// If the value is found then [`Result::Ok`] is returned, containing the
     /// index of the matching element. If there are multiple matches, then any
-    /// one of the matches could be returned. If the value is not found then
-    /// [`Result::Err`] is returned, containing the index where a matching
-    /// element could be inserted while maintaining sorted order.
+    /// one of the matches could be returned. The index is chosen
+    /// deterministically, but is subject to change in future versions of Rust.
+    /// If the value is not found then [`Result::Err`] is returned, containing
+    /// the index where a matching element could be inserted while maintaining
+    /// sorted order.
     ///
     /// See also [`binary_search_by`], [`binary_search_by_key`], and [`partition_point`].
     ///
@@ -2153,9 +2155,11 @@ impl<T> [T] {
     ///
     /// If the value is found then [`Result::Ok`] is returned, containing the
     /// index of the matching element. If there are multiple matches, then any
-    /// one of the matches could be returned. If the value is not found then
-    /// [`Result::Err`] is returned, containing the index where a matching
-    /// element could be inserted while maintaining sorted order.
+    /// one of the matches could be returned. The index is chosen
+    /// deterministically, but is subject to change in future versions of Rust.
+    /// If the value is not found then [`Result::Err`] is returned, containing
+    /// the index where a matching element could be inserted while maintaining
+    /// sorted order.
     ///
     /// See also [`binary_search`], [`binary_search_by_key`], and [`partition_point`].
     ///
@@ -2224,9 +2228,11 @@ impl<T> [T] {
     ///
     /// If the value is found then [`Result::Ok`] is returned, containing the
     /// index of the matching element. If there are multiple matches, then any
-    /// one of the matches could be returned. If the value is not found then
-    /// [`Result::Err`] is returned, containing the index where a matching
-    /// element could be inserted while maintaining sorted order.
+    /// one of the matches could be returned. The index is chosen
+    /// deterministically, but is subject to change in future versions of Rust.
+    /// If the value is not found then [`Result::Err`] is returned, containing
+    /// the index where a matching element could be inserted while maintaining
+    /// sorted order.
     ///
     /// See also [`binary_search`], [`binary_search_by`], and [`partition_point`].
     ///
diff --git a/library/core/tests/any.rs b/library/core/tests/any.rs
index b0dc9903464..b36d6f0d404 100644
--- a/library/core/tests/any.rs
+++ b/library/core/tests/any.rs
@@ -114,3 +114,16 @@ fn any_unsized() {
     fn is_any<T: Any + ?Sized>() {}
     is_any::<[i32]>();
 }
+
+#[test]
+fn distinct_type_names() {
+    // https://github.com/rust-lang/rust/issues/84666
+
+    struct Velocity(f32, f32);
+
+    fn type_name_of_val<T>(_: T) -> &'static str {
+        type_name::<T>()
+    }
+
+    assert_ne!(type_name_of_val(Velocity), type_name_of_val(Velocity(0.0, -9.8)),);
+}
diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs
index ce7480ce2ee..0ae625bdb68 100644
--- a/library/core/tests/array.rs
+++ b/library/core/tests/array.rs
@@ -1,4 +1,4 @@
-use core::array::{self, IntoIter};
+use core::array;
 use core::convert::TryFrom;
 
 #[test]
@@ -41,14 +41,14 @@ fn array_try_from() {
 #[test]
 fn iterator_collect() {
     let arr = [0, 1, 2, 5, 9];
-    let v: Vec<_> = IntoIter::new(arr.clone()).collect();
+    let v: Vec<_> = IntoIterator::into_iter(arr.clone()).collect();
     assert_eq!(&arr[..], &v[..]);
 }
 
 #[test]
 fn iterator_rev_collect() {
     let arr = [0, 1, 2, 5, 9];
-    let v: Vec<_> = IntoIter::new(arr.clone()).rev().collect();
+    let v: Vec<_> = IntoIterator::into_iter(arr.clone()).rev().collect();
     assert_eq!(&v[..], &[9, 5, 2, 1, 0]);
 }
 
@@ -56,11 +56,11 @@ fn iterator_rev_collect() {
 fn iterator_nth() {
     let v = [0, 1, 2, 3, 4];
     for i in 0..v.len() {
-        assert_eq!(IntoIter::new(v.clone()).nth(i).unwrap(), v[i]);
+        assert_eq!(IntoIterator::into_iter(v.clone()).nth(i).unwrap(), v[i]);
     }
-    assert_eq!(IntoIter::new(v.clone()).nth(v.len()), None);
+    assert_eq!(IntoIterator::into_iter(v.clone()).nth(v.len()), None);
 
-    let mut iter = IntoIter::new(v);
+    let mut iter = IntoIterator::into_iter(v);
     assert_eq!(iter.nth(2).unwrap(), v[2]);
     assert_eq!(iter.nth(1).unwrap(), v[4]);
 }
@@ -68,17 +68,17 @@ fn iterator_nth() {
 #[test]
 fn iterator_last() {
     let v = [0, 1, 2, 3, 4];
-    assert_eq!(IntoIter::new(v).last().unwrap(), 4);
-    assert_eq!(IntoIter::new([0]).last().unwrap(), 0);
+    assert_eq!(IntoIterator::into_iter(v).last().unwrap(), 4);
+    assert_eq!(IntoIterator::into_iter([0]).last().unwrap(), 0);
 
-    let mut it = IntoIter::new([0, 9, 2, 4]);
+    let mut it = IntoIterator::into_iter([0, 9, 2, 4]);
     assert_eq!(it.next_back(), Some(4));
     assert_eq!(it.last(), Some(2));
 }
 
 #[test]
 fn iterator_clone() {
-    let mut it = IntoIter::new([0, 2, 4, 6, 8]);
+    let mut it = IntoIterator::into_iter([0, 2, 4, 6, 8]);
     assert_eq!(it.next(), Some(0));
     assert_eq!(it.next_back(), Some(8));
     let mut clone = it.clone();
@@ -92,7 +92,7 @@ fn iterator_clone() {
 
 #[test]
 fn iterator_fused() {
-    let mut it = IntoIter::new([0, 9, 2]);
+    let mut it = IntoIterator::into_iter([0, 9, 2]);
     assert_eq!(it.next(), Some(0));
     assert_eq!(it.next(), Some(9));
     assert_eq!(it.next(), Some(2));
@@ -105,7 +105,7 @@ fn iterator_fused() {
 
 #[test]
 fn iterator_len() {
-    let mut it = IntoIter::new([0, 1, 2, 5, 9]);
+    let mut it = IntoIterator::into_iter([0, 1, 2, 5, 9]);
     assert_eq!(it.size_hint(), (5, Some(5)));
     assert_eq!(it.len(), 5);
     assert_eq!(it.is_empty(), false);
@@ -121,7 +121,7 @@ fn iterator_len() {
     assert_eq!(it.is_empty(), false);
 
     // Empty
-    let it = IntoIter::new([] as [String; 0]);
+    let it = IntoIterator::into_iter([] as [String; 0]);
     assert_eq!(it.size_hint(), (0, Some(0)));
     assert_eq!(it.len(), 0);
     assert_eq!(it.is_empty(), true);
@@ -130,9 +130,9 @@ fn iterator_len() {
 #[test]
 fn iterator_count() {
     let v = [0, 1, 2, 3, 4];
-    assert_eq!(IntoIter::new(v.clone()).count(), 5);
+    assert_eq!(IntoIterator::into_iter(v.clone()).count(), 5);
 
-    let mut iter2 = IntoIter::new(v);
+    let mut iter2 = IntoIterator::into_iter(v);
     iter2.next();
     iter2.next();
     assert_eq!(iter2.count(), 3);
@@ -140,13 +140,13 @@ fn iterator_count() {
 
 #[test]
 fn iterator_flat_map() {
-    assert!((0..5).flat_map(|i| IntoIter::new([2 * i, 2 * i + 1])).eq(0..10));
+    assert!((0..5).flat_map(|i| IntoIterator::into_iter([2 * i, 2 * i + 1])).eq(0..10));
 }
 
 #[test]
 fn iterator_debug() {
     let arr = [0, 1, 2, 5, 9];
-    assert_eq!(format!("{:?}", IntoIter::new(arr)), "IntoIter([0, 1, 2, 5, 9])",);
+    assert_eq!(format!("{:?}", IntoIterator::into_iter(arr)), "IntoIter([0, 1, 2, 5, 9])",);
 }
 
 #[test]
@@ -176,14 +176,14 @@ fn iterator_drops() {
     // Simple: drop new iterator.
     let i = Cell::new(0);
     {
-        IntoIter::new(five(&i));
+        IntoIterator::into_iter(five(&i));
     }
     assert_eq!(i.get(), 5);
 
     // Call `next()` once.
     let i = Cell::new(0);
     {
-        let mut iter = IntoIter::new(five(&i));
+        let mut iter = IntoIterator::into_iter(five(&i));
         let _x = iter.next();
         assert_eq!(i.get(), 0);
         assert_eq!(iter.count(), 4);
@@ -194,7 +194,7 @@ fn iterator_drops() {
     // Check `clone` and calling `next`/`next_back`.
     let i = Cell::new(0);
     {
-        let mut iter = IntoIter::new(five(&i));
+        let mut iter = IntoIterator::into_iter(five(&i));
         iter.next();
         assert_eq!(i.get(), 1);
         iter.next_back();
@@ -217,7 +217,7 @@ fn iterator_drops() {
     // Check via `nth`.
     let i = Cell::new(0);
     {
-        let mut iter = IntoIter::new(five(&i));
+        let mut iter = IntoIterator::into_iter(five(&i));
         let _x = iter.nth(2);
         assert_eq!(i.get(), 2);
         let _y = iter.last();
@@ -227,13 +227,13 @@ fn iterator_drops() {
 
     // Check every element.
     let i = Cell::new(0);
-    for (index, _x) in IntoIter::new(five(&i)).enumerate() {
+    for (index, _x) in IntoIterator::into_iter(five(&i)).enumerate() {
         assert_eq!(i.get(), index);
     }
     assert_eq!(i.get(), 5);
 
     let i = Cell::new(0);
-    for (index, _x) in IntoIter::new(five(&i)).rev().enumerate() {
+    for (index, _x) in IntoIterator::into_iter(five(&i)).rev().enumerate() {
         assert_eq!(i.get(), index);
     }
     assert_eq!(i.get(), 5);
diff --git a/library/core/tests/const_ptr.rs b/library/core/tests/const_ptr.rs
index 152fed803ec..4acd059ab03 100644
--- a/library/core/tests/const_ptr.rs
+++ b/library/core/tests/const_ptr.rs
@@ -49,53 +49,3 @@ fn mut_ptr_read() {
     const UNALIGNED: u16 = unsafe { UNALIGNED_PTR.read_unaligned() };
     assert_eq!(UNALIGNED, u16::from_ne_bytes([0x23, 0x45]));
 }
-
-#[test]
-fn write() {
-    use core::ptr;
-
-    const fn write_aligned() -> i32 {
-        let mut res = 0;
-        unsafe {
-            ptr::write(&mut res as *mut _, 42);
-        }
-        res
-    }
-    const ALIGNED: i32 = write_aligned();
-    assert_eq!(ALIGNED, 42);
-
-    const fn write_unaligned() -> [u16; 2] {
-        let mut two_aligned = [0u16; 2];
-        unsafe {
-            let unaligned_ptr = (two_aligned.as_mut_ptr() as *mut u8).add(1) as *mut u16;
-            ptr::write_unaligned(unaligned_ptr, u16::from_ne_bytes([0x23, 0x45]));
-        }
-        two_aligned
-    }
-    const UNALIGNED: [u16; 2] = write_unaligned();
-    assert_eq!(UNALIGNED, [u16::from_ne_bytes([0x00, 0x23]), u16::from_ne_bytes([0x45, 0x00])]);
-}
-
-#[test]
-fn mut_ptr_write() {
-    const fn aligned() -> i32 {
-        let mut res = 0;
-        unsafe {
-            (&mut res as *mut i32).write(42);
-        }
-        res
-    }
-    const ALIGNED: i32 = aligned();
-    assert_eq!(ALIGNED, 42);
-
-    const fn write_unaligned() -> [u16; 2] {
-        let mut two_aligned = [0u16; 2];
-        unsafe {
-            let unaligned_ptr = (two_aligned.as_mut_ptr() as *mut u8).add(1) as *mut u16;
-            unaligned_ptr.write_unaligned(u16::from_ne_bytes([0x23, 0x45]));
-        }
-        two_aligned
-    }
-    const UNALIGNED: [u16; 2] = write_unaligned();
-    assert_eq!(UNALIGNED, [u16::from_ne_bytes([0x00, 0x23]), u16::from_ne_bytes([0x45, 0x00])]);
-}
diff --git a/library/core/tests/iter/adapters/zip.rs b/library/core/tests/iter/adapters/zip.rs
index 000c15f72c8..797bfd957f9 100644
--- a/library/core/tests/iter/adapters/zip.rs
+++ b/library/core/tests/iter/adapters/zip.rs
@@ -236,9 +236,7 @@ fn test_zip_trusted_random_access_composition() {
 fn test_double_ended_zip() {
     let xs = [1, 2, 3, 4, 5, 6];
     let ys = [1, 2, 3, 7];
-    let a = xs.iter().cloned();
-    let b = ys.iter().cloned();
-    let mut it = a.zip(b);
+    let mut it = xs.iter().cloned().zip(ys);
     assert_eq!(it.next(), Some((1, 1)));
     assert_eq!(it.next(), Some((2, 2)));
     assert_eq!(it.next_back(), Some((4, 7)));
diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs
index 5dcd1e6af36..d95ea6530c2 100644
--- a/library/panic_abort/src/lib.rs
+++ b/library/panic_abort/src/lib.rs
@@ -5,10 +5,7 @@
 
 #![no_std]
 #![unstable(feature = "panic_abort", issue = "32837")]
-#![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
-    issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/"
-)]
+#![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
 #![panic_runtime]
 #![allow(unused_features)]
 #![feature(core_intrinsics)]
diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs
index 99a0c67fc11..d32a3f1f832 100644
--- a/library/panic_unwind/src/lib.rs
+++ b/library/panic_unwind/src/lib.rs
@@ -13,10 +13,7 @@
 
 #![no_std]
 #![unstable(feature = "panic_unwind", issue = "32837")]
-#![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
-    issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/"
-)]
+#![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
 #![feature(core_intrinsics)]
 #![feature(lang_items)]
 #![feature(nll)]
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index 04a165e09f1..26fbf50e2df 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -12,7 +12,6 @@
 #![stable(feature = "proc_macro_lib", since = "1.15.0")]
 #![deny(missing_docs)]
 #![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
     html_playground_url = "https://play.rust-lang.org/",
     issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
     test(no_crate_inject, attr(deny(warnings))),
@@ -32,6 +31,7 @@
 #![feature(restricted_std)]
 #![feature(rustc_attrs)]
 #![feature(min_specialization)]
+#![feature(bound_cloned)]
 #![recursion_limit = "256"]
 
 #[unstable(feature = "proc_macro_internals", issue = "27812")]
@@ -44,7 +44,7 @@ mod diagnostic;
 pub use diagnostic::{Diagnostic, Level, MultiSpan};
 
 use std::cmp::Ordering;
-use std::ops::{Bound, RangeBounds};
+use std::ops::RangeBounds;
 use std::path::PathBuf;
 use std::str::FromStr;
 use std::{error, fmt, iter, mem};
@@ -1163,16 +1163,7 @@ impl Literal {
     // was 'c' or whether it was '\u{63}'.
     #[unstable(feature = "proc_macro_span", issue = "54725")]
     pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> {
-        // HACK(eddyb) something akin to `Option::cloned`, but for `Bound<&T>`.
-        fn cloned_bound<T: Clone>(bound: Bound<&T>) -> Bound<T> {
-            match bound {
-                Bound::Included(x) => Bound::Included(x.clone()),
-                Bound::Excluded(x) => Bound::Excluded(x.clone()),
-                Bound::Unbounded => Bound::Unbounded,
-            }
-        }
-
-        self.0.subspan(cloned_bound(range.start_bound()), cloned_bound(range.end_bound())).map(Span)
+        self.0.subspan(range.start_bound().cloned(), range.end_bound().cloned()).map(Span)
     }
 }
 
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 922c2c2bb8c..415d874c7fa 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.93", default-features = false, features = ['rustc-dep-of-std'] }
-compiler_builtins = { version = "0.1.43" }
+compiler_builtins = { version = "0.1.44" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.11", default-features = false, features = ['rustc-dep-of-std'] }
diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs
index 6891bd8a664..7a2a49ba7d7 100644
--- a/library/std/src/io/impls.rs
+++ b/library/std/src/io/impls.rs
@@ -87,6 +87,11 @@ impl<S: Seek + ?Sized> Seek for &mut S {
     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
         (**self).seek(pos)
     }
+
+    #[inline]
+    fn stream_position(&mut self) -> io::Result<u64> {
+        (**self).stream_position()
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<B: BufRead + ?Sized> BufRead for &mut B {
@@ -186,6 +191,11 @@ impl<S: Seek + ?Sized> Seek for Box<S> {
     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
         (**self).seek(pos)
     }
+
+    #[inline]
+    fn stream_position(&mut self) -> io::Result<u64> {
+        (**self).stream_position()
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<B: BufRead + ?Sized> BufRead for Box<B> {
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 8e4c63762fd..c4f21587457 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -190,7 +190,6 @@
 #![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))]
 #![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))]
 #![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
     html_playground_url = "https://play.rust-lang.org/",
     issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
     test(no_crate_inject, attr(deny(warnings))),
diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs
index 6c2f2eeabd6..2b6d0d7d5da 100644
--- a/library/std/src/net/ip.rs
+++ b/library/std/src/net/ip.rs
@@ -314,7 +314,7 @@ impl Ipv4Addr {
         Ipv4Addr { inner: c::in_addr { s_addr: u32::from_ne_bytes([a, b, c, d]) } }
     }
 
-    /// An IPv4 address with the address pointing to localhost: 127.0.0.1.
+    /// An IPv4 address with the address pointing to localhost: `127.0.0.1`
     ///
     /// # Examples
     ///
@@ -327,7 +327,7 @@ impl Ipv4Addr {
     #[stable(feature = "ip_constructors", since = "1.30.0")]
     pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
 
-    /// An IPv4 address representing an unspecified address: 0.0.0.0
+    /// An IPv4 address representing an unspecified address: `0.0.0.0`
     ///
     /// This corresponds to the constant `INADDR_ANY` in other languages.
     ///
@@ -343,7 +343,7 @@ impl Ipv4Addr {
     #[stable(feature = "ip_constructors", since = "1.30.0")]
     pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
 
-    /// An IPv4 address representing the broadcast address: 255.255.255.255
+    /// An IPv4 address representing the broadcast address: `255.255.255.255`
     ///
     /// # Examples
     ///
@@ -374,7 +374,7 @@ impl Ipv4Addr {
         self.inner.s_addr.to_ne_bytes()
     }
 
-    /// Returns [`true`] for the special 'unspecified' address (0.0.0.0).
+    /// Returns [`true`] for the special 'unspecified' address (`0.0.0.0`).
     ///
     /// This property is defined in _UNIX Network Programming, Second Edition_,
     /// W. Richard Stevens, p. 891; see also [ip7].
@@ -396,7 +396,7 @@ impl Ipv4Addr {
         self.inner.s_addr == 0
     }
 
-    /// Returns [`true`] if this is a loopback address (127.0.0.0/8).
+    /// Returns [`true`] if this is a loopback address (`127.0.0.0/8`).
     ///
     /// This property is defined by [IETF RFC 1122].
     ///
@@ -421,9 +421,9 @@ impl Ipv4Addr {
     ///
     /// The private address ranges are defined in [IETF RFC 1918] and include:
     ///
-    ///  - 10.0.0.0/8
-    ///  - 172.16.0.0/12
-    ///  - 192.168.0.0/16
+    ///  - `10.0.0.0/8`
+    ///  - `172.16.0.0/12`
+    ///  - `192.168.0.0/16`
     ///
     /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918
     ///
@@ -452,7 +452,7 @@ impl Ipv4Addr {
         }
     }
 
-    /// Returns [`true`] if the address is link-local (169.254.0.0/16).
+    /// Returns [`true`] if the address is link-local (`169.254.0.0/16`).
     ///
     /// This property is defined by [IETF RFC 3927].
     ///
@@ -485,7 +485,7 @@ impl Ipv4Addr {
     /// - the broadcast address (see [`Ipv4Addr::is_broadcast()`])
     /// - addresses used for documentation (see [`Ipv4Addr::is_documentation()`])
     /// - the unspecified address (see [`Ipv4Addr::is_unspecified()`]), and the whole
-    ///   0.0.0.0/8 block
+    ///   `0.0.0.0/8` block
     /// - addresses reserved for future protocols (see
     /// [`Ipv4Addr::is_ietf_protocol_assignment()`], except
     /// `192.0.0.9/32` and `192.0.0.10/32` which are globally routable
@@ -682,9 +682,9 @@ impl Ipv4Addr {
         self.octets()[0] & 240 == 240 && !self.is_broadcast()
     }
 
-    /// Returns [`true`] if this is a multicast address (224.0.0.0/4).
+    /// Returns [`true`] if this is a multicast address (`224.0.0.0/4`).
     ///
-    /// Multicast addresses have a most significant octet between 224 and 239,
+    /// Multicast addresses have a most significant octet between `224` and `239`,
     /// and is defined by [IETF RFC 5771].
     ///
     /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771
@@ -705,9 +705,9 @@ impl Ipv4Addr {
         self.octets()[0] >= 224 && self.octets()[0] <= 239
     }
 
-    /// Returns [`true`] if this is a broadcast address (255.255.255.255).
+    /// Returns [`true`] if this is a broadcast address (`255.255.255.255`).
     ///
-    /// A broadcast address has all octets set to 255 as defined in [IETF RFC 919].
+    /// A broadcast address has all octets set to `255` as defined in [IETF RFC 919].
     ///
     /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919
     ///
@@ -730,9 +730,9 @@ impl Ipv4Addr {
     ///
     /// This is defined in [IETF RFC 5737]:
     ///
-    /// - 192.0.2.0/24 (TEST-NET-1)
-    /// - 198.51.100.0/24 (TEST-NET-2)
-    /// - 203.0.113.0/24 (TEST-NET-3)
+    /// - `192.0.2.0/24` (TEST-NET-1)
+    /// - `198.51.100.0/24` (TEST-NET-2)
+    /// - `203.0.113.0/24` (TEST-NET-3)
     ///
     /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737
     ///
@@ -760,7 +760,7 @@ impl Ipv4Addr {
 
     /// Converts this address to an IPv4-compatible [`IPv6` address].
     ///
-    /// a.b.c.d becomes ::a.b.c.d
+    /// `a.b.c.d` becomes `::a.b.c.d`
     ///
     /// This isn't typically the method you want; these addresses don't typically
     /// function on modern systems. Use `to_ipv6_mapped` instead.
@@ -774,7 +774,7 @@ impl Ipv4Addr {
     ///
     /// assert_eq!(
     ///     Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(),
-    ///     Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 767)
+    ///     Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x2ff)
     /// );
     /// ```
     #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
@@ -789,7 +789,7 @@ impl Ipv4Addr {
 
     /// Converts this address to an IPv4-mapped [`IPv6` address].
     ///
-    /// a.b.c.d becomes ::ffff:a.b.c.d
+    /// `a.b.c.d` becomes `::ffff:a.b.c.d`
     ///
     /// [`IPv6` address]: Ipv6Addr
     ///
@@ -799,7 +799,7 @@ impl Ipv4Addr {
     /// use std::net::{Ipv4Addr, Ipv6Addr};
     ///
     /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(),
-    ///            Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 49152, 767));
+    ///            Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff));
     /// ```
     #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -1172,7 +1172,7 @@ impl Ipv6Addr {
         ]
     }
 
-    /// Returns [`true`] for the special 'unspecified' address (::).
+    /// Returns [`true`] for the special 'unspecified' address (`::`).
     ///
     /// This property is defined in [IETF RFC 4291].
     ///
@@ -1267,6 +1267,34 @@ impl Ipv6Addr {
         (self.segments()[0] & 0xfe00) == 0xfc00
     }
 
+    /// Returns [`true`] if this is a unicast address, as defined by [IETF RFC 4291].
+    /// Any address that is not a [multicast address] (`ff00::/8`) is unicast.
+    ///
+    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+    /// [multicast address]: Ipv6Addr::is_multicast
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    ///
+    /// use std::net::Ipv6Addr;
+    ///
+    /// // The unspecified and loopback addresses are unicast.
+    /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_unicast(), true);
+    /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast(), true);
+    ///
+    /// // Any address that is not a multicast address (`ff00::/8`) is unicast.
+    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast(), true);
+    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_unicast(), false);
+    /// ```
+    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[unstable(feature = "ip", issue = "27709")]
+    #[inline]
+    pub const fn is_unicast(&self) -> bool {
+        !self.is_multicast()
+    }
+
     /// Returns `true` if the address is a unicast address with link-local scope,
     /// as defined in [RFC 4291].
     ///
@@ -1318,7 +1346,7 @@ impl Ipv6Addr {
         (self.segments()[0] & 0xffc0) == 0xfe80
     }
 
-    /// Returns [`true`] if this is a deprecated unicast site-local address (fec0::/10). The
+    /// Returns [`true`] if this is a deprecated unicast site-local address (`fec0::/10`). The
     /// unicast site-local address format is defined in [RFC 4291 section 2.5.7] as:
     ///
     /// ```no_rust
@@ -1347,7 +1375,7 @@ impl Ipv6Addr {
     ///
     /// # Warning
     ///
-    /// As per [RFC 3879], the whole `FEC0::/10` prefix is
+    /// As per [RFC 3879], the whole `fec0::/10` prefix is
     /// deprecated. New software must not support site-local
     /// addresses.
     ///
@@ -1417,7 +1445,7 @@ impl Ipv6Addr {
     #[unstable(feature = "ip", issue = "27709")]
     #[inline]
     pub const fn is_unicast_global(&self) -> bool {
-        !self.is_multicast()
+        self.is_unicast()
             && !self.is_loopback()
             && !self.is_unicast_link_local()
             && !self.is_unique_local()
@@ -1460,7 +1488,7 @@ impl Ipv6Addr {
         }
     }
 
-    /// Returns [`true`] if this is a multicast address (ff00::/8).
+    /// Returns [`true`] if this is a multicast address (`ff00::/8`).
     ///
     /// This property is defined by [IETF RFC 4291].
     ///
@@ -1517,7 +1545,7 @@ impl Ipv6Addr {
     /// Converts this address to an [`IPv4` address]. Returns [`None`] if this address is
     /// neither IPv4-compatible or IPv4-mapped.
     ///
-    /// ::a.b.c.d and ::ffff:a.b.c.d become a.b.c.d
+    /// `::a.b.c.d` and `::ffff:a.b.c.d` become `a.b.c.d`
     ///
     /// [`IPv4` address]: Ipv4Addr
     ///
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 02957e75a74..e591e073e7b 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -193,7 +193,7 @@ fn default_hook(info: &PanicInfo<'_>) {
         Some(s) => *s,
         None => match info.payload().downcast_ref::<String>() {
             Some(s) => &s[..],
-            None => "Box<Any>",
+            None => "Box<dyn Any>",
         },
     };
     let thread = thread_info::current_thread();
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 9c5615f58c4..ede147aca12 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -1420,6 +1420,9 @@ impl Clone for PathBuf {
 
 #[stable(feature = "box_from_path", since = "1.17.0")]
 impl From<&Path> for Box<Path> {
+    /// Creates a boxed [`Path`] from a reference.
+    ///
+    /// This will allocate and clone `path` to it.
     fn from(path: &Path) -> Box<Path> {
         let boxed: Box<OsStr> = path.inner.into();
         let rw = Box::into_raw(boxed) as *mut Path;
@@ -1429,6 +1432,9 @@ impl From<&Path> for Box<Path> {
 
 #[stable(feature = "box_from_cow", since = "1.45.0")]
 impl From<Cow<'_, Path>> for Box<Path> {
+    /// Creates a boxed [`Path`] from a clone-on-write pointer.
+    ///
+    /// Converting from a `Cow::Owned` does not clone or allocate.
     #[inline]
     fn from(cow: Cow<'_, Path>) -> Box<Path> {
         match cow {
@@ -1471,6 +1477,9 @@ impl Clone for Box<Path> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized + AsRef<OsStr>> From<&T> for PathBuf {
+    /// Converts a borrowed `OsStr` to a `PathBuf`.
+    ///
+    /// Allocates a [`PathBuf`] and copies the data into it.
     #[inline]
     fn from(s: &T) -> PathBuf {
         PathBuf::from(s.as_ref().to_os_string())
@@ -1575,6 +1584,10 @@ impl Default for PathBuf {
 
 #[stable(feature = "cow_from_path", since = "1.6.0")]
 impl<'a> From<&'a Path> for Cow<'a, Path> {
+    /// Creates a clone-on-write pointer from a reference to
+    /// [`Path`].
+    ///
+    /// This conversion does not clone or allocate.
     #[inline]
     fn from(s: &'a Path) -> Cow<'a, Path> {
         Cow::Borrowed(s)
@@ -1583,6 +1596,10 @@ impl<'a> From<&'a Path> for Cow<'a, Path> {
 
 #[stable(feature = "cow_from_path", since = "1.6.0")]
 impl<'a> From<PathBuf> for Cow<'a, Path> {
+    /// Creates a clone-on-write pointer from an owned
+    /// instance of [`PathBuf`].
+    ///
+    /// This conversion does not clone or allocate.
     #[inline]
     fn from(s: PathBuf) -> Cow<'a, Path> {
         Cow::Owned(s)
@@ -1591,6 +1608,10 @@ impl<'a> From<PathBuf> for Cow<'a, Path> {
 
 #[stable(feature = "cow_from_pathbuf_ref", since = "1.28.0")]
 impl<'a> From<&'a PathBuf> for Cow<'a, Path> {
+    /// Creates a clone-on-write pointer from a reference to
+    /// [`PathBuf`].
+    ///
+    /// This conversion does not clone or allocate.
     #[inline]
     fn from(p: &'a PathBuf) -> Cow<'a, Path> {
         Cow::Borrowed(p.as_path())
@@ -1599,6 +1620,9 @@ impl<'a> From<&'a PathBuf> for Cow<'a, Path> {
 
 #[stable(feature = "pathbuf_from_cow_path", since = "1.28.0")]
 impl<'a> From<Cow<'a, Path>> for PathBuf {
+    /// Converts a clone-on-write pointer to an owned path.
+    ///
+    /// Converting from a `Cow::Owned` does not clone or allocate.
     #[inline]
     fn from(p: Cow<'a, Path>) -> Self {
         p.into_owned()
@@ -2462,10 +2486,10 @@ impl Path {
     /// Returns `true` if the path points at an existing entity.
     ///
     /// This function will traverse symbolic links to query information about the
-    /// destination file. In case of broken symbolic links this will return `false`.
+    /// destination file.
     ///
-    /// If you cannot access the directory containing the file, e.g., because of a
-    /// permission error, this will return `false`.
+    /// If you cannot access the metadata of the file, e.g. because of a
+    /// permission error or broken symbolic links, this will return `false`.
     ///
     /// # Examples
     ///
@@ -2513,10 +2537,10 @@ impl Path {
     /// Returns `true` if the path exists on disk and is pointing at a regular file.
     ///
     /// This function will traverse symbolic links to query information about the
-    /// destination file. In case of broken symbolic links this will return `false`.
+    /// destination file.
     ///
-    /// If you cannot access the directory containing the file, e.g., because of a
-    /// permission error, this will return `false`.
+    /// If you cannot access the metadata of the file, e.g. because of a
+    /// permission error or broken symbolic links, this will return `false`.
     ///
     /// # Examples
     ///
@@ -2545,10 +2569,10 @@ impl Path {
     /// Returns `true` if the path exists on disk and is pointing at a directory.
     ///
     /// This function will traverse symbolic links to query information about the
-    /// destination file. In case of broken symbolic links this will return `false`.
+    /// destination file.
     ///
-    /// If you cannot access the directory containing the file, e.g., because of a
-    /// permission error, this will return `false`.
+    /// If you cannot access the metadata of the file, e.g. because of a
+    /// permission error or broken symbolic links, this will return `false`.
     ///
     /// # Examples
     ///
diff --git a/library/std/src/prelude/mod.rs b/library/std/src/prelude/mod.rs
index 1b4facdd049..12d52cc8e0b 100644
--- a/library/std/src/prelude/mod.rs
+++ b/library/std/src/prelude/mod.rs
@@ -88,9 +88,9 @@ pub mod v1;
 /// The 2015 version of the prelude of The Rust Standard Library.
 ///
 /// See the [module-level documentation](self) for more.
-#[unstable(feature = "prelude_2015", issue = "none")]
+#[unstable(feature = "prelude_2015", issue = "85684")]
 pub mod rust_2015 {
-    #[unstable(feature = "prelude_2015", issue = "none")]
+    #[unstable(feature = "prelude_2015", issue = "85684")]
     #[doc(no_inline)]
     pub use super::v1::*;
 }
@@ -98,9 +98,9 @@ pub mod rust_2015 {
 /// The 2018 version of the prelude of The Rust Standard Library.
 ///
 /// See the [module-level documentation](self) for more.
-#[unstable(feature = "prelude_2018", issue = "none")]
+#[unstable(feature = "prelude_2018", issue = "85684")]
 pub mod rust_2018 {
-    #[unstable(feature = "prelude_2018", issue = "none")]
+    #[unstable(feature = "prelude_2018", issue = "85684")]
     #[doc(no_inline)]
     pub use super::v1::*;
 }
@@ -108,13 +108,13 @@ pub mod rust_2018 {
 /// The 2021 version of the prelude of The Rust Standard Library.
 ///
 /// See the [module-level documentation](self) for more.
-#[unstable(feature = "prelude_2021", issue = "none")]
+#[unstable(feature = "prelude_2021", issue = "85684")]
 pub mod rust_2021 {
-    #[unstable(feature = "prelude_2021", issue = "none")]
+    #[unstable(feature = "prelude_2021", issue = "85684")]
     #[doc(no_inline)]
     pub use super::v1::*;
 
-    #[unstable(feature = "prelude_2021", issue = "none")]
+    #[unstable(feature = "prelude_2021", issue = "85684")]
     #[doc(no_inline)]
     pub use core::prelude::rust_2021::*;
 }
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index 57d91441b6f..ca9cc8ca7ba 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -210,7 +210,6 @@ cfg_if::cfg_if! {
     if #[cfg(target_os = "android")] {
         #[link(name = "dl")]
         #[link(name = "log")]
-        #[link(name = "gcc")]
         extern "C" {}
     } else if #[cfg(target_os = "freebsd")] {
         #[link(name = "execinfo")]
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index 89addae0789..899cf6841ee 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -82,7 +82,7 @@ pub use core::time::Duration;
 /// Currently, the following system calls are being used to get the current time using `now()`:
 ///
 /// |  Platform |               System call                                            |
-/// |:---------:|:--------------------------------------------------------------------:|
+/// |-----------|----------------------------------------------------------------------|
 /// | SGX       | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
 /// | UNIX      | [clock_gettime (Monotonic Clock)]                                    |
 /// | Darwin    | [mach_absolute_time]                                                 |
@@ -158,7 +158,7 @@ pub struct Instant(time::Instant);
 /// Currently, the following system calls are being used to get the current time using `now()`:
 ///
 /// |  Platform |               System call                                            |
-/// |:---------:|:--------------------------------------------------------------------:|
+/// |-----------|----------------------------------------------------------------------|
 /// | SGX       | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
 /// | UNIX      | [clock_gettime (Realtime Clock)]                                     |
 /// | Darwin    | [gettimeofday]                                                       |
diff --git a/library/term/src/lib.rs b/library/term/src/lib.rs
index 2116b433fce..943b276a220 100644
--- a/library/term/src/lib.rs
+++ b/library/term/src/lib.rs
@@ -30,11 +30,7 @@
 //! [win]: https://docs.microsoft.com/en-us/windows/console/character-mode-applications
 //! [ti]: https://en.wikipedia.org/wiki/Terminfo
 
-#![doc(
-    html_root_url = "https://doc.rust-lang.org/nightly/",
-    html_playground_url = "https://play.rust-lang.org/",
-    test(attr(deny(warnings)))
-)]
+#![doc(html_playground_url = "https://play.rust-lang.org/", test(attr(deny(warnings))))]
 #![deny(missing_docs)]
 #![cfg_attr(windows, feature(libc))]
 
diff --git a/library/test/src/formatters/pretty.rs b/library/test/src/formatters/pretty.rs
index 5e41d6d9692..e17fc08a9ae 100644
--- a/library/test/src/formatters/pretty.rs
+++ b/library/test/src/formatters/pretty.rs
@@ -169,7 +169,11 @@ impl<T: Write> PrettyFormatter<T> {
 
     fn write_test_name(&mut self, desc: &TestDesc) -> io::Result<()> {
         let name = desc.padded_name(self.max_name_len, desc.name.padding());
-        self.write_plain(&format!("test {} ... ", name))?;
+        if let Some(test_mode) = desc.test_mode() {
+            self.write_plain(&format!("test {} - {} ... ", name, test_mode))?;
+        } else {
+            self.write_plain(&format!("test {} ... ", name))?;
+        }
 
         Ok(())
     }
diff --git a/library/test/src/formatters/terse.rs b/library/test/src/formatters/terse.rs
index 6f46f7255a4..a2c223c494c 100644
--- a/library/test/src/formatters/terse.rs
+++ b/library/test/src/formatters/terse.rs
@@ -158,7 +158,11 @@ impl<T: Write> TerseFormatter<T> {
 
     fn write_test_name(&mut self, desc: &TestDesc) -> io::Result<()> {
         let name = desc.padded_name(self.max_name_len, desc.name.padding());
-        self.write_plain(&format!("test {} ... ", name))?;
+        if let Some(test_mode) = desc.test_mode() {
+            self.write_plain(&format!("test {} - {} ... ", name, test_mode))?;
+        } else {
+            self.write_plain(&format!("test {} ... ", name))?;
+        }
 
         Ok(())
     }
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index bda5ed888d7..3da4d434f48 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -19,7 +19,7 @@
 
 #![crate_name = "test"]
 #![unstable(feature = "test", issue = "50297")]
-#![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))]
+#![doc(test(attr(deny(warnings))))]
 #![cfg_attr(unix, feature(libc))]
 #![feature(rustc_private)]
 #![feature(nll)]
diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs
index 6a3f31b74ea..5a4a540b04e 100644
--- a/library/test/src/tests.rs
+++ b/library/test/src/tests.rs
@@ -61,6 +61,10 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> {
                 ignore: true,
                 should_panic: ShouldPanic::No,
                 allow_fail: false,
+                #[cfg(not(bootstrap))]
+                compile_fail: false,
+                #[cfg(not(bootstrap))]
+                no_run: false,
                 test_type: TestType::Unknown,
             },
             testfn: DynTestFn(Box::new(move || {})),
@@ -71,6 +75,10 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> {
                 ignore: false,
                 should_panic: ShouldPanic::No,
                 allow_fail: false,
+                #[cfg(not(bootstrap))]
+                compile_fail: false,
+                #[cfg(not(bootstrap))]
+                no_run: false,
                 test_type: TestType::Unknown,
             },
             testfn: DynTestFn(Box::new(move || {})),
@@ -89,6 +97,10 @@ pub fn do_not_run_ignored_tests() {
             ignore: true,
             should_panic: ShouldPanic::No,
             allow_fail: false,
+            #[cfg(not(bootstrap))]
+            compile_fail: false,
+            #[cfg(not(bootstrap))]
+            no_run: false,
             test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
@@ -108,6 +120,10 @@ pub fn ignored_tests_result_in_ignored() {
             ignore: true,
             should_panic: ShouldPanic::No,
             allow_fail: false,
+            #[cfg(not(bootstrap))]
+            compile_fail: false,
+            #[cfg(not(bootstrap))]
+            no_run: false,
             test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
@@ -131,6 +147,10 @@ fn test_should_panic() {
             ignore: false,
             should_panic: ShouldPanic::Yes,
             allow_fail: false,
+            #[cfg(not(bootstrap))]
+            compile_fail: false,
+            #[cfg(not(bootstrap))]
+            no_run: false,
             test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
@@ -154,6 +174,10 @@ fn test_should_panic_good_message() {
             ignore: false,
             should_panic: ShouldPanic::YesWithMessage("error message"),
             allow_fail: false,
+            #[cfg(not(bootstrap))]
+            compile_fail: false,
+            #[cfg(not(bootstrap))]
+            no_run: false,
             test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
@@ -182,6 +206,10 @@ fn test_should_panic_bad_message() {
             ignore: false,
             should_panic: ShouldPanic::YesWithMessage(expected),
             allow_fail: false,
+            #[cfg(not(bootstrap))]
+            compile_fail: false,
+            #[cfg(not(bootstrap))]
+            no_run: false,
             test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
@@ -214,6 +242,10 @@ fn test_should_panic_non_string_message_type() {
             ignore: false,
             should_panic: ShouldPanic::YesWithMessage(expected),
             allow_fail: false,
+            #[cfg(not(bootstrap))]
+            compile_fail: false,
+            #[cfg(not(bootstrap))]
+            no_run: false,
             test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
@@ -238,6 +270,10 @@ fn test_should_panic_but_succeeds() {
                 ignore: false,
                 should_panic,
                 allow_fail: false,
+                #[cfg(not(bootstrap))]
+                compile_fail: false,
+                #[cfg(not(bootstrap))]
+                no_run: false,
                 test_type: TestType::Unknown,
             },
             testfn: DynTestFn(Box::new(f)),
@@ -270,6 +306,10 @@ fn report_time_test_template(report_time: bool) -> Option<TestExecTime> {
             ignore: false,
             should_panic: ShouldPanic::No,
             allow_fail: false,
+            #[cfg(not(bootstrap))]
+            compile_fail: false,
+            #[cfg(not(bootstrap))]
+            no_run: false,
             test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(f)),
@@ -303,6 +343,10 @@ fn time_test_failure_template(test_type: TestType) -> TestResult {
             ignore: false,
             should_panic: ShouldPanic::No,
             allow_fail: false,
+            #[cfg(not(bootstrap))]
+            compile_fail: false,
+            #[cfg(not(bootstrap))]
+            no_run: false,
             test_type,
         },
         testfn: DynTestFn(Box::new(f)),
@@ -340,6 +384,10 @@ fn typed_test_desc(test_type: TestType) -> TestDesc {
         ignore: false,
         should_panic: ShouldPanic::No,
         allow_fail: false,
+        #[cfg(not(bootstrap))]
+        compile_fail: false,
+        #[cfg(not(bootstrap))]
+        no_run: false,
         test_type,
     }
 }
@@ -451,6 +499,10 @@ pub fn exclude_should_panic_option() {
             ignore: false,
             should_panic: ShouldPanic::Yes,
             allow_fail: false,
+            #[cfg(not(bootstrap))]
+            compile_fail: false,
+            #[cfg(not(bootstrap))]
+            no_run: false,
             test_type: TestType::Unknown,
         },
         testfn: DynTestFn(Box::new(move || {})),
@@ -473,6 +525,10 @@ pub fn exact_filter_match() {
                     ignore: false,
                     should_panic: ShouldPanic::No,
                     allow_fail: false,
+                    #[cfg(not(bootstrap))]
+                    compile_fail: false,
+                    #[cfg(not(bootstrap))]
+                    no_run: false,
                     test_type: TestType::Unknown,
                 },
                 testfn: DynTestFn(Box::new(move || {})),
@@ -565,6 +621,10 @@ pub fn sort_tests() {
                     ignore: false,
                     should_panic: ShouldPanic::No,
                     allow_fail: false,
+                    #[cfg(not(bootstrap))]
+                    compile_fail: false,
+                    #[cfg(not(bootstrap))]
+                    no_run: false,
                     test_type: TestType::Unknown,
                 },
                 testfn: DynTestFn(Box::new(testfn)),
@@ -642,6 +702,10 @@ pub fn test_bench_no_iter() {
         ignore: false,
         should_panic: ShouldPanic::No,
         allow_fail: false,
+        #[cfg(not(bootstrap))]
+        compile_fail: false,
+        #[cfg(not(bootstrap))]
+        no_run: false,
         test_type: TestType::Unknown,
     };
 
@@ -662,6 +726,10 @@ pub fn test_bench_iter() {
         ignore: false,
         should_panic: ShouldPanic::No,
         allow_fail: false,
+        #[cfg(not(bootstrap))]
+        compile_fail: false,
+        #[cfg(not(bootstrap))]
+        no_run: false,
         test_type: TestType::Unknown,
     };
 
@@ -676,6 +744,10 @@ fn should_sort_failures_before_printing_them() {
         ignore: false,
         should_panic: ShouldPanic::No,
         allow_fail: false,
+        #[cfg(not(bootstrap))]
+        compile_fail: false,
+        #[cfg(not(bootstrap))]
+        no_run: false,
         test_type: TestType::Unknown,
     };
 
@@ -684,6 +756,10 @@ fn should_sort_failures_before_printing_them() {
         ignore: false,
         should_panic: ShouldPanic::No,
         allow_fail: false,
+        #[cfg(not(bootstrap))]
+        compile_fail: false,
+        #[cfg(not(bootstrap))]
+        no_run: false,
         test_type: TestType::Unknown,
     };
 
diff --git a/library/test/src/types.rs b/library/test/src/types.rs
index c5d91f653b3..63907c71ea7 100644
--- a/library/test/src/types.rs
+++ b/library/test/src/types.rs
@@ -124,6 +124,10 @@ pub struct TestDesc {
     pub ignore: bool,
     pub should_panic: options::ShouldPanic,
     pub allow_fail: bool,
+    #[cfg(not(bootstrap))]
+    pub compile_fail: bool,
+    #[cfg(not(bootstrap))]
+    pub no_run: bool,
     pub test_type: TestType,
 }
 
@@ -140,6 +144,36 @@ impl TestDesc {
             }
         }
     }
+
+    /// Returns None for ignored test or that that are just run, otherwise give a description of the type of test.
+    /// Descriptions include "should panic", "compile fail" and "compile".
+    #[cfg(not(bootstrap))]
+    pub fn test_mode(&self) -> Option<&'static str> {
+        if self.ignore {
+            return None;
+        }
+        match self.should_panic {
+            options::ShouldPanic::Yes | options::ShouldPanic::YesWithMessage(_) => {
+                return Some("should panic");
+            }
+            options::ShouldPanic::No => {}
+        }
+        if self.allow_fail {
+            return Some("allow fail");
+        }
+        if self.compile_fail {
+            return Some("compile fail");
+        }
+        if self.no_run {
+            return Some("compile");
+        }
+        None
+    }
+
+    #[cfg(bootstrap)]
+    pub fn test_mode(&self) -> Option<&'static str> {
+        None
+    }
 }
 
 #[derive(Debug)]
diff --git a/library/unwind/build.rs b/library/unwind/build.rs
index 96df3fc5ac4..0529d24a274 100644
--- a/library/unwind/build.rs
+++ b/library/unwind/build.rs
@@ -20,6 +20,20 @@ fn main() {
         // linking for Linux is handled in lib.rs
         if target.contains("musl") {
             llvm_libunwind::compile();
+        } else if target.contains("android") {
+            let build = cc::Build::new();
+
+            // Since ndk r23 beta 3 `libgcc` was replaced with `libunwind` thus
+            // check if we have `libunwind` available and if so use it. Otherwise
+            // fall back to `libgcc` to support older ndk versions.
+            let has_unwind =
+                build.is_flag_supported("-lunwind").expect("Unable to invoke compiler");
+
+            if has_unwind {
+                println!("cargo:rustc-link-lib=unwind");
+            } else {
+                println!("cargo:rustc-link-lib=gcc");
+            }
         }
     } else if target.contains("freebsd") {
         println!("cargo:rustc-link-lib=gcc_s");
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index 4b98abfb308..ac8bbfe102d 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -124,6 +124,13 @@ fn main() {
                 cmd.arg("-C").arg("target-feature=-crt-static");
             }
         }
+
+        if stage == "0" {
+            // Cargo doesn't pass RUSTFLAGS to proc_macros:
+            // https://github.com/rust-lang/cargo/issues/4423
+            // Set `--cfg=bootstrap` explicitly instead.
+            cmd.arg("--cfg=bootstrap");
+        }
     }
 
     if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") {
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 149a899cef7..7c7f162b82c 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -648,18 +648,20 @@ class RustBuild(object):
         rev_parse = ["git", "rev-parse", "--show-toplevel"]
         top_level = subprocess.check_output(rev_parse, universal_newlines=True).strip()
         compiler = "{}/compiler/".format(top_level)
+        library = "{}/library/".format(top_level)
 
         # Look for a version to compare to based on the current commit.
         # Only commits merged by bors will have CI artifacts.
         merge_base = ["git", "log", "--author=bors", "--pretty=%H", "-n1"]
         commit = subprocess.check_output(merge_base, universal_newlines=True).strip()
 
-        # Warn if there were changes to the compiler since the ancestor commit.
-        status = subprocess.call(["git", "diff-index", "--quiet", commit, "--", compiler])
+        # Warn if there were changes to the compiler or standard library since the ancestor commit.
+        status = subprocess.call(["git", "diff-index", "--quiet", commit, "--", compiler, library])
         if status != 0:
             if download_rustc == "if-unchanged":
                 return None
-            print("warning: `download-rustc` is enabled, but there are changes to compiler/")
+            print("warning: `download-rustc` is enabled, but there are changes to \
+                   compiler/ or library/")
 
         if self.verbose:
             print("using downloaded stage1 artifacts from CI (commit {})".format(commit))
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index f3049a74757..06f8bf89dae 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -574,6 +574,18 @@ impl<'a> Builder<'a> {
         self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), paths);
     }
 
+    /// NOTE: keep this in sync with `rustdoc::clean::utils::doc_rust_lang_org_channel`, or tests will fail on beta/stable.
+    pub fn doc_rust_lang_org_channel(&self) -> String {
+        let channel = match &*self.config.channel {
+            "stable" => &self.version,
+            "beta" => "beta",
+            "nightly" | "dev" => "nightly",
+            // custom build of rustdoc maybe? link to the latest stable docs just in case
+            _ => "stable",
+        };
+        "https://doc.rust-lang.org/".to_owned() + channel
+    }
+
     fn run_step_descriptions(&self, v: &[StepDescription], paths: &[PathBuf]) {
         StepDescription::run(v, self, paths);
     }
@@ -709,7 +721,15 @@ impl<'a> Builder<'a> {
             return;
         }
 
-        add_dylib_path(vec![self.rustc_libdir(compiler)], cmd);
+        let mut dylib_dirs = vec![self.rustc_libdir(compiler)];
+
+        // Ensure that the downloaded LLVM libraries can be found.
+        if self.config.llvm_from_ci {
+            let ci_llvm_lib = self.out.join(&*compiler.host.triple).join("ci-llvm").join("lib");
+            dylib_dirs.push(ci_llvm_lib);
+        }
+
+        add_dylib_path(dylib_dirs, cmd);
     }
 
     /// Gets a path to the compiler specified.
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index e5258d08956..ed311e273b1 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -269,7 +269,9 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
 
     if builder.no_std(target) == Some(true) {
         let mut features = "compiler-builtins-mem".to_string();
-        features.push_str(compiler_builtins_c_feature);
+        if !target.starts_with("bpf") {
+            features.push_str(compiler_builtins_c_feature);
+        }
 
         // for no-std targets we only compile a few no_std crates
         cargo
@@ -326,6 +328,11 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
     if target.contains("riscv") {
         cargo.rustflag("-Cforce-unwind-tables=yes");
     }
+
+    let html_root =
+        format!("-Zcrate-attr=doc(html_root_url=\"{}/\")", builder.doc_rust_lang_org_channel(),);
+    cargo.rustflag(&html_root);
+    cargo.rustdocflag(&html_root);
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -629,8 +636,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
     cargo
         .env("CFG_RELEASE", builder.rust_release())
         .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
-        .env("CFG_VERSION", builder.rust_version())
-        .env("CFG_PREFIX", builder.config.prefix.clone().unwrap_or_default());
+        .env("CFG_VERSION", builder.rust_version());
 
     let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
     cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 2960dd3df6b..21c7dd11d24 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -444,8 +444,13 @@ impl Build {
 
         build.verbose("finding compilers");
         cc_detect::find(&mut build);
-        build.verbose("running sanity check");
-        sanity::check(&mut build);
+        // When running `setup`, the profile is about to change, so any requirements we have now may
+        // be different on the next invocation. Don't check for them until the next time x.py is
+        // run. This is ok because `setup` never runs any build commands, so it won't fail if commands are missing.
+        if !matches!(build.config.cmd, Subcommand::Setup { .. }) {
+            build.verbose("running sanity check");
+            sanity::check(&mut build);
+        }
 
         // If local-rust is the same major.minor as the current version, then force a
         // local-rebuild
@@ -1366,7 +1371,7 @@ impl Build {
                 eprintln!(
                     "
 Couldn't find required command: ninja
-You should install ninja, or set ninja=false in config.toml
+You should install ninja, or set `ninja=false` in config.toml in the `[llvm]` section.
 "
                 );
                 std::process::exit(1);
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 4f33a13c253..449fdb87b02 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -153,7 +153,7 @@ impl Step for Llvm {
         let llvm_targets = match &builder.config.llvm_targets {
             Some(s) => s,
             None => {
-                "AArch64;ARM;Hexagon;MSP430;Mips;NVPTX;PowerPC;RISCV;\
+                "AArch64;ARM;BPF;Hexagon;MSP430;Mips;NVPTX;PowerPC;RISCV;\
                      Sparc;SystemZ;WebAssembly;X86"
             }
         };
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 16b3c6419e8..cc7c143d474 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -449,6 +449,7 @@ impl Step for Miri {
                 SourceType::Submodule,
                 &[],
             );
+            cargo.add_rustc_lib_path(builder, compiler);
             cargo.arg("--").arg("miri").arg("setup");
 
             // Tell `cargo miri setup` where to find the sources.
@@ -500,6 +501,7 @@ impl Step for Miri {
                 SourceType::Submodule,
                 &[],
             );
+            cargo.add_rustc_lib_path(builder, compiler);
 
             // miri tests need to know about the stage sysroot
             cargo.env("MIRI_SYSROOT", miri_sysroot);
@@ -508,8 +510,6 @@ impl Step for Miri {
 
             cargo.arg("--").args(builder.config.cmd.test_args());
 
-            cargo.add_rustc_lib_path(builder, compiler);
-
             let mut cargo = Command::from(cargo);
             if !try_run(builder, &mut cargo) {
                 return;
@@ -1486,6 +1486,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
             }
         }
         cmd.env("RUSTC_BOOTSTRAP", "1");
+        cmd.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
         builder.add_rust_test_threads(&mut cmd);
 
         if builder.config.sanitizers_enabled(target) {
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 64e4be6863a..9d75ad0918a 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -263,6 +263,7 @@ pub fn prepare_tool_cargo(
     cargo.env("CFG_RELEASE_CHANNEL", &builder.config.channel);
     cargo.env("CFG_VERSION", builder.rust_version());
     cargo.env("CFG_RELEASE_NUM", &builder.version);
+    cargo.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
 
     let info = GitInfo::new(builder.config.ignore_git, &dir);
     if let Some(sha) = info.sha() {
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index b4421a82714..112979b0beb 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -45,6 +45,7 @@ pub fn libdir(target: TargetSelection) -> &'static str {
 }
 
 /// Adds a list of lookup paths to `cmd`'s dynamic library lookup path.
+/// If The dylib_path_par is already set for this cmd, the old value will be overwritten!
 pub fn add_dylib_path(path: Vec<PathBuf>, cmd: &mut Command) {
     let mut list = dylib_path();
     for path in path {
@@ -306,5 +307,6 @@ pub fn use_host_linker(target: TargetSelection) -> bool {
         || target.contains("wasm32")
         || target.contains("nvptx")
         || target.contains("fortanix")
-        || target.contains("fuchsia"))
+        || target.contains("fuchsia")
+        || target.contains("bpf"))
 }
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 9c68af3ce6ccca2395e1868addef26a0542e9dd
+Subproject 8f598e2af6c25b4a7ee88ef6a8196d9b8ea50ca
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject 50de7f0682adc5d95ce858fe6318d19b4b95155
+Subproject c8da5bfd1c7c71d90ef1646f5e0a9f6609d5c78
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index 077c322bd77..05384117ac1 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -149,8 +149,7 @@ values:
 
 * `y`, `yes`, `on`, or no value: Unwind tables are forced to be generated.
 * `n`, `no`, or `off`: Unwind tables are not forced to be generated. If unwind
-  tables are required by the target or `-C panic=unwind`, an error will be
-  emitted.
+  tables are required by the target an error will be emitted.
 
 The default if not specified depends on the target.
 
@@ -234,6 +233,8 @@ flavor. Valid options are:
 * `ptx-linker`: use
   [`rust-ptx-linker`](https://github.com/denzp/rust-ptx-linker) for Nvidia
   NVPTX GPGPU support.
+* `bpf-linker`: use
+  [`bpf-linker`](https://github.com/alessandrod/bpf-linker) for eBPF support.
 * `wasm-ld`: use the [`wasm-ld`](https://lld.llvm.org/WebAssembly.html)
   executable, a port of LLVM `lld` for WebAssembly.
 * `ld64.lld`: use the LLVM `lld` executable with the [`-flavor darwin`
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 321d3c5c44e..3225e95941c 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -219,6 +219,8 @@ target | std | host | notes
 `armv7a-none-eabihf` | * | | ARM Cortex-A, hardfloat
 `armv7s-apple-ios` | ✓ |  |
 `avr-unknown-gnu-atmega328` | * |  | AVR. Requires `-Z build-std=core`
+`bpfeb-unknown-none` | * |  | BPF (big endian)
+`bpfel-unknown-none` | * |  | BPF (little endian)
 `hexagon-unknown-linux-musl` | ? |  |
 `i386-apple-ios` | ✓ |  | 32-bit x86 iOS
 `i686-apple-darwin` | ✓ | ✓ | 32-bit macOS (10.7+, Lion+)
diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/documentation-tests.md
index 8e3c6228189..cb7b85655b5 100644
--- a/src/doc/rustdoc/src/documentation-tests.md
+++ b/src/doc/rustdoc/src/documentation-tests.md
@@ -424,9 +424,7 @@ without including it in your main documentation. For example, you could write th
 `lib.rs` to test your README as part of your doctests:
 
 ```rust,no_run
-#![feature(external_doc)]
-
-#[doc(include = "../README.md")]
+#[doc = include_str!("../README.md")]
 #[cfg(doctest)]
 pub struct ReadmeDoctests;
 ```
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index 28b81a40265..e9b15666bb3 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -131,22 +131,6 @@ Book][unstable-masked] and [its tracking issue][issue-masked].
 [unstable-masked]: ../unstable-book/language-features/doc-masked.html
 [issue-masked]: https://github.com/rust-lang/rust/issues/44027
 
-### Include external files as API documentation
-
-As designed in [RFC 1990], Rustdoc can read an external file to use as a type's documentation. This
-is useful if certain documentation is so long that it would break the flow of reading the source.
-Instead of writing it all inline, writing `#[doc(include = "sometype.md")]` will ask Rustdoc to
-instead read that file and use it as if it were written inline.
-
-[RFC 1990]: https://github.com/rust-lang/rfcs/pull/1990
-
-`#[doc(include = "...")]` currently requires the `#![feature(external_doc)]` feature gate. For more
-information, see [its chapter in the Unstable Book][unstable-include] and [its tracking
-issue][issue-include].
-
-[unstable-include]: ../unstable-book/language-features/external-doc.html
-[issue-include]: https://github.com/rust-lang/rust/issues/44732
-
 ## Unstable command-line arguments
 
 These features are enabled by passing a command-line flag to Rustdoc, but the flags in question are
diff --git a/src/doc/unstable-book/src/compiler-flags/force-warns.md b/src/doc/unstable-book/src/compiler-flags/force-warns.md
new file mode 100644
index 00000000000..0a205be096c
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/force-warns.md
@@ -0,0 +1,21 @@
+# `force-warns`
+
+The tracking issue for this feature is: [#85512](https://github.com/rust-lang/rust/issues/85512).
+
+------------------------
+
+This feature allows you to cause any lint to produce a warning even if the lint has a different level by default or another level is set somewhere else. For instance, the `force-warns` option can be used to make a lint (e.g., `dead_code`) produce a warning even if that lint is allowed in code with `#![allow(dead_code)]`.
+
+## Example
+
+```rust,ignore (partial-example)
+#![allow(dead_code)]
+
+fn dead_function() {}
+// This would normally not produce a warning even though the
+// function is not used, because dead code is being allowed
+
+fn main() {}
+```
+
+We can force a warning to be produced by providing `--force-warns dead_code` to rustc.
diff --git a/src/doc/unstable-book/src/language-features/external-doc.md b/src/doc/unstable-book/src/language-features/external-doc.md
deleted file mode 100644
index effae5d2999..00000000000
--- a/src/doc/unstable-book/src/language-features/external-doc.md
+++ /dev/null
@@ -1,40 +0,0 @@
-# `external_doc`
-
-The tracking issue for this feature is: [#44732]
-
-The `external_doc` feature allows the use of the `include` parameter to the `#[doc]` attribute, to
-include external files in documentation. Use the attribute in place of, or in addition to, regular
-doc comments and `#[doc]` attributes, and `rustdoc` will load the given file when it renders
-documentation for your crate.
-
-With the following files in the same directory:
-
-`external-doc.md`:
-
-```markdown
-# My Awesome Type
-
-This is the documentation for this spectacular type.
-```
-
-`lib.rs`:
-
-```no_run (needs-external-files)
-#![feature(external_doc)]
-
-#[doc(include = "external-doc.md")]
-pub struct MyAwesomeType;
-```
-
-`rustdoc` will load the file `external-doc.md` and use it as the documentation for the `MyAwesomeType`
-struct.
-
-When locating files, `rustdoc` will base paths in the `src/` directory, as if they were alongside the
-`lib.rs` for your crate. So if you want a `docs/` folder to live alongside the `src/` directory,
-start your paths with `../docs/` for `rustdoc` to properly find the file.
-
-This feature was proposed in [RFC #1990] and initially implemented in PR [#44781].
-
-[#44732]: https://github.com/rust-lang/rust/issues/44732
-[RFC #1990]: https://github.com/rust-lang/rfcs/pull/1990
-[#44781]: https://github.com/rust-lang/rust/pull/44781
diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md
index 5503b3b4b32..03dbf4fb617 100644
--- a/src/doc/unstable-book/src/library-features/asm.md
+++ b/src/doc/unstable-book/src/library-features/asm.md
@@ -30,6 +30,7 @@ Inline assembly is currently supported on the following architectures:
 - Hexagon
 - MIPS32r2 and MIPS64r2
 - wasm32
+- BPF
 
 ## Basic usage
 
@@ -570,6 +571,8 @@ Here is the list of currently supported register classes:
 | PowerPC | `reg_nonzero` | | `r[1-31]` | `b` |
 | PowerPC | `freg` | `f[0-31]` | `f` |
 | wasm32 | `local` | None\* | `r` |
+| BPF | `reg` | `r[0-10]` | `r` |
+| BPF | `wreg` | `w[0-10]` | `w` |
 
 > **Note**: On x86 we treat `reg_byte` differently from `reg` because the compiler can allocate `al` and `ah` separately whereas `reg` reserves the whole register.
 >
@@ -615,6 +618,8 @@ Each register class has constraints on which value types they can be used with.
 | PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` |
 | PowerPC | `freg` | None | `f32`, `f64` |
 | wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` |
+| BPF | `reg` | None | `i8` `i16` `i32` `i64` |
+| BPF | `wreg` | `alu32` | `i8` `i16` `i32` |
 
 > **Note**: For the purposes of the above table pointers, function pointers and `isize`/`usize` are treated as the equivalent integer type (`i16`/`i32`/`i64` depending on the target).
 
@@ -674,6 +679,7 @@ Some registers have multiple names. These are all treated by the compiler as ide
 | Hexagon | `r29` | `sp` |
 | Hexagon | `r30` | `fr` |
 | Hexagon | `r31` | `lr` |
+| BPF | `r[0-10]` | `w[0-10]` |
 
 Some registers cannot be used for input or output operands:
 
diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py
index 2f7233685db..8647db5a45d 100644
--- a/src/etc/htmldocck.py
+++ b/src/etc/htmldocck.py
@@ -135,6 +135,8 @@ except NameError:
     unichr = chr
 
 
+channel = os.environ["DOC_RUST_LANG_ORG_CHANNEL"]
+
 class CustomHTMLParser(HTMLParser):
     """simplified HTML parser.
 
@@ -270,6 +272,7 @@ def flatten(node):
 
 
 def normalize_xpath(path):
+    path = path.replace("{{channel}}", channel)
     if path.startswith('//'):
         return '.' + path  # avoid warnings
     elif path.startswith('.//'):
@@ -334,6 +337,7 @@ class CachedFiles(object):
 
 
 def check_string(data, pat, regexp):
+    pat = pat.replace("{{channel}}", channel)
     if not pat:
         return True  # special case a presence testing
     elif regexp:
diff --git a/src/etc/natvis/intrinsic.natvis b/src/etc/natvis/intrinsic.natvis
index 030892a432b..89280149a03 100644
--- a/src/etc/natvis/intrinsic.natvis
+++ b/src/etc/natvis/intrinsic.natvis
@@ -149,4 +149,57 @@
       <Synthetic Name="[...]"><DisplayString>...</DisplayString></Synthetic>
     </Expand>
   </Type>
+  <Type Name="enum$&lt;*&gt;">
+    <Intrinsic Name="tag" Expression="variant0.variant$" />
+    <DisplayString Condition="tag() == 0">{tag(),en}</DisplayString>
+    <DisplayString Condition="tag() == 1" Optional="true">{tag(),en}</DisplayString>
+    <DisplayString Condition="tag() == 2" Optional="true">{tag(),en}</DisplayString>
+    <DisplayString Condition="tag() == 3" Optional="true">{tag(),en}</DisplayString>
+    <DisplayString Condition="tag() == 4" Optional="true">{tag(),en}</DisplayString>
+    <DisplayString Condition="tag() == 5" Optional="true">{tag(),en}</DisplayString>
+    <DisplayString Condition="tag() == 6" Optional="true">{tag(),en}</DisplayString>
+    <DisplayString Condition="tag() == 7" Optional="true">{tag(),en}</DisplayString>
+    <DisplayString Condition="tag() == 8" Optional="true">{tag(),en}</DisplayString>
+    <DisplayString Condition="tag() == 9" Optional="true">{tag(),en}</DisplayString>
+    <DisplayString Condition="tag() == 10" Optional="true">{tag(),en}</DisplayString>
+    <DisplayString Condition="tag() == 11" Optional="true">{tag(),en}</DisplayString>
+    <DisplayString Condition="tag() == 12" Optional="true">{tag(),en}</DisplayString>
+    <DisplayString Condition="tag() == 13" Optional="true">{tag(),en}</DisplayString>
+    <DisplayString Condition="tag() == 14" Optional="true">{tag(),en}</DisplayString>
+    <DisplayString Condition="tag() == 15" Optional="true">{tag(),en}</DisplayString>
+
+    <Expand>
+      <ExpandedItem Condition="tag() == 0">variant0</ExpandedItem>
+      <ExpandedItem Condition="tag() == 1" Optional="true">variant1</ExpandedItem>
+      <ExpandedItem Condition="tag() == 2" Optional="true">variant2</ExpandedItem>
+      <ExpandedItem Condition="tag() == 3" Optional="true">variant3</ExpandedItem>
+      <ExpandedItem Condition="tag() == 4" Optional="true">variant4</ExpandedItem>
+      <ExpandedItem Condition="tag() == 5" Optional="true">variant5</ExpandedItem>
+      <ExpandedItem Condition="tag() == 6" Optional="true">variant6</ExpandedItem>
+      <ExpandedItem Condition="tag() == 7" Optional="true">variant7</ExpandedItem>
+      <ExpandedItem Condition="tag() == 8" Optional="true">variant8</ExpandedItem>
+      <ExpandedItem Condition="tag() == 9" Optional="true">variant9</ExpandedItem>
+      <ExpandedItem Condition="tag() == 10" Optional="true">variant10</ExpandedItem>
+      <ExpandedItem Condition="tag() == 11" Optional="true">variant11</ExpandedItem>
+      <ExpandedItem Condition="tag() == 12" Optional="true">variant12</ExpandedItem>
+      <ExpandedItem Condition="tag() == 13" Optional="true">variant13</ExpandedItem>
+      <ExpandedItem Condition="tag() == 14" Optional="true">variant14</ExpandedItem>
+      <ExpandedItem Condition="tag() == 15" Optional="true">variant15</ExpandedItem>
+    </Expand>
+  </Type>
+
+  <!-- $T1 is the name of the enum, $T2 is the low value of the dataful variant tag,
+       $T3 is the high value of the dataful variant tag, $T4 is the name of the dataful variant -->
+  <Type Name="enum$&lt;*, *, *, *&gt;">
+    <Intrinsic Name="tag" Expression="discriminant" />
+    <Intrinsic Name="is_dataful" Expression="tag() &gt;= $T2 &amp;&amp; tag() &lt;= $T3" />
+    <DisplayString Condition="is_dataful()">{"$T4",sb}({dataful_variant})</DisplayString>
+    <DisplayString Condition="!is_dataful()">{discriminant,en}</DisplayString>
+    <Expand>
+      <ExpandedItem Condition="is_dataful()">dataful_variant</ExpandedItem>
+      <Synthetic Condition="is_dataful()" Name="[variant]">
+        <DisplayString>{"$T4",sb}</DisplayString>
+      </Synthetic>
+    </Expand>
+  </Type>
 </AutoVisualizer>
diff --git a/src/etc/natvis/libcore.natvis b/src/etc/natvis/libcore.natvis
index 9c3c26f5978..17667770520 100644
--- a/src/etc/natvis/libcore.natvis
+++ b/src/etc/natvis/libcore.natvis
@@ -14,14 +14,6 @@
     </Expand>
   </Type>
 
-  <Type Name="core::option::Option&lt;*&gt;">
-    <DisplayString Condition="RUST$ENUM$DISR == 0x0">None</DisplayString>
-    <DisplayString Condition="RUST$ENUM$DISR == 0x1">Some({__0})</DisplayString>
-    <Expand>
-      <Item Name="[value]" ExcludeView="simple" Condition="RUST$ENUM$DISR == 1">__0</Item>
-    </Expand>
-  </Type>
-
   <Type Name="core::option::Option&lt;*&gt;" Priority="MediumLow">
     <DisplayString Condition="*(void**)this == nullptr">None</DisplayString>
     <DisplayString>Some({($T1 *)this})</DisplayString>
@@ -30,15 +22,6 @@
     </Expand>
   </Type>
 
-  <Type Name="core::result::Result&lt;*&gt;">
-    <DisplayString Condition="RUST$ENUM$DISR == 0x0">Ok({__0})</DisplayString>
-    <DisplayString Condition="RUST$ENUM$DISR == 0x1">Err({(*($T2*) &amp;__0)})</DisplayString>
-    <Expand>
-      <Item Name="[value]" Condition="RUST$ENUM$DISR == 0x0">__0</Item>
-      <Item Name="[value]" Condition="RUST$ENUM$DISR == 0x1">(*($T2*) &amp;__0)</Item>
-    </Expand>
-  </Type>
-
   <Type Name="core::ptr::non_null::NonNull&lt;*&gt;">
     <DisplayString>{(void*) pointer}</DisplayString>
     <Expand>
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 35ff57f85a5..a3f63ea1046 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -664,7 +664,10 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                     }
                 }
                 GenericParamDefKind::Lifetime => {}
-                GenericParamDefKind::Const { .. } => {}
+                GenericParamDefKind::Const { ref mut default, .. } => {
+                    // We never want something like `impl<const N: usize = 10>`
+                    default.take();
+                }
             }
         }
 
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index a14eefaf571..111827aacdf 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -527,7 +527,7 @@ fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::St
 }
 
 fn build_macro(cx: &mut DocContext<'_>, did: DefId, name: Symbol) -> clean::ItemKind {
-    let imported_from = cx.tcx.original_crate_name(did.krate);
+    let imported_from = cx.tcx.crate_name(did.krate);
     match cx.enter_resolver(|r| r.cstore().load_macro_untracked(did, cx.sess())) {
         LoadedMacro::MacroDef(def, _) => {
             let matchers: Vec<Span> = if let ast::ItemKind::MacroDef(ref def) = def.kind {
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 231f13adeb6..d1c18821ea6 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -445,11 +445,15 @@ impl Clean<GenericParamDef> for ty::GenericParamDef {
                     },
                 )
             }
-            ty::GenericParamDefKind::Const { .. } => (
+            ty::GenericParamDefKind::Const { has_default, .. } => (
                 self.name,
                 GenericParamDefKind::Const {
                     did: self.def_id,
                     ty: cx.tcx.type_of(self.def_id).clean(cx),
+                    default: match has_default {
+                        true => Some(cx.tcx.const_param_default(self.def_id).to_string()),
+                        false => None,
+                    },
                 },
             ),
         };
@@ -487,12 +491,15 @@ impl Clean<GenericParamDef> for hir::GenericParam<'_> {
                     synthetic,
                 },
             ),
-            hir::GenericParamKind::Const { ref ty, default: _ } => (
+            hir::GenericParamKind::Const { ref ty, default } => (
                 self.name.ident().name,
                 GenericParamDefKind::Const {
                     did: cx.tcx.hir().local_def_id(self.hir_id).to_def_id(),
                     ty: ty.clean(cx),
-                    // FIXME(const_generics_defaults): add `default` field here for docs
+                    default: default.map(|ct| {
+                        let def_id = cx.tcx.hir().local_def_id(ct.hir_id);
+                        ty::Const::from_anon_const(cx.tcx, def_id).to_string()
+                    }),
                 },
             ),
         };
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index de88e249b67..6a7c3f8caa4 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -499,7 +499,7 @@ impl Item {
                                     format!("{}/std/", s.trim_end_matches('/'))
                                 }
                                 Some(ExternalLocation::Unknown) | None => {
-                                    "https://doc.rust-lang.org/nightly/std/".to_string()
+                                    format!("{}/std/", crate::DOC_RUST_LANG_ORG_CHANNEL)
                                 }
                             };
                             // This is a primitive so the url is done "by hand".
@@ -526,7 +526,6 @@ impl Item {
     crate fn is_crate(&self) -> bool {
         self.is_mod() && self.def_id.as_real().map_or(false, |did| did.index == CRATE_DEF_INDEX)
     }
-
     crate fn is_mod(&self) -> bool {
         self.type_() == ItemType::Module
     }
@@ -810,7 +809,7 @@ impl AttributesExt for [ast::Attribute] {
                 // #[doc(...)]
                 if let Some(list) = attr.meta().as_ref().and_then(|mi| mi.meta_item_list()) {
                     for item in list {
-                        // #[doc(include)]
+                        // #[doc(hidden)]
                         if !item.has_name(sym::cfg) {
                             continue;
                         }
@@ -895,9 +894,6 @@ crate enum DocFragmentKind {
     SugaredDoc,
     /// A doc fragment created from a "raw" `#[doc=""]` attribute.
     RawDoc,
-    /// A doc fragment created from a `#[doc(include="filename")]` attribute. Contains both the
-    /// given filename and the file contents.
-    Include { filename: Symbol },
 }
 
 // The goal of this function is to apply the `DocFragment` transformations that are required when
@@ -931,18 +927,8 @@ 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()
-                && prev_kind
-                    .take()
-                    .map(|p| matches!(p, DocFragmentKind::Include { .. }) && p != frag.kind)
-                    .unwrap_or(false)
-            {
-                acc.push('\n');
-            }
             add_doc_fragment(&mut acc, &frag);
-            prev_kind = Some(frag.kind);
             acc
         })
     }
@@ -989,45 +975,6 @@ impl Attributes {
         self.other_attrs.lists(name)
     }
 
-    /// 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<(Symbol, Symbol)> {
-        mi.meta_item_list().and_then(|list| {
-            for meta in list {
-                if meta.has_name(sym::include) {
-                    // the actual compiled `#[doc(include="filename")]` gets expanded to
-                    // `#[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<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);
-                                }
-                            } else if it.has_name(sym::contents) {
-                                if let Some(docs) = it.value_str() {
-                                    contents = Some(docs);
-                                }
-                            }
-                        }
-
-                        if let (Some(filename), Some(contents)) = (filename, contents) {
-                            Some((filename, contents))
-                        } else {
-                            None
-                        }
-                    });
-                }
-            }
-
-            None
-        })
-    }
-
     crate fn has_doc_flag(&self, flag: Symbol) -> bool {
         for attr in &self.other_attrs {
             if !attr.has_name(sym::doc) {
@@ -1051,18 +998,9 @@ impl Attributes {
         let mut doc_strings: Vec<DocFragment> = vec![];
         let mut doc_line = 0;
 
-        fn update_need_backline(doc_strings: &mut Vec<DocFragment>, frag: &DocFragment) {
+        fn update_need_backline(doc_strings: &mut Vec<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;
-                }
+                prev.need_backline = true;
             }
         }
 
@@ -1088,31 +1026,12 @@ impl Attributes {
                     indent: 0,
                 };
 
-                update_need_backline(&mut doc_strings, &frag);
+                update_need_backline(&mut doc_strings);
 
                 doc_strings.push(frag);
 
                 None
             } else {
-                if attr.has_name(sym::doc) {
-                    if let Some(mi) = attr.meta() {
-                        if let Some((filename, contents)) = Attributes::extract_include(&mi) {
-                            let line = doc_line;
-                            doc_line += contents.as_str().lines().count();
-                            let frag = DocFragment {
-                                line,
-                                span: attr.span,
-                                doc: contents,
-                                kind: DocFragmentKind::Include { filename },
-                                parent_module,
-                                need_backline: false,
-                                indent: 0,
-                            };
-                            update_need_backline(&mut doc_strings, &frag);
-                            doc_strings.push(frag);
-                        }
-                    }
-                }
                 Some(attr.clone())
             }
         };
@@ -1138,10 +1057,7 @@ impl Attributes {
         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
-            {
+            if new_frag.kind != ori.kind || new_frag.parent_module != ori.parent_module {
                 break;
             }
             add_doc_fragment(&mut out, &new_frag);
@@ -1304,6 +1220,7 @@ crate enum GenericParamDefKind {
     Const {
         did: DefId,
         ty: Type,
+        default: Option<String>,
     },
 }
 
@@ -1768,37 +1685,6 @@ impl PrimitiveType {
         }
     }
 
-    crate fn as_str(&self) -> &'static str {
-        use self::PrimitiveType::*;
-        match *self {
-            Isize => "isize",
-            I8 => "i8",
-            I16 => "i16",
-            I32 => "i32",
-            I64 => "i64",
-            I128 => "i128",
-            Usize => "usize",
-            U8 => "u8",
-            U16 => "u16",
-            U32 => "u32",
-            U64 => "u64",
-            U128 => "u128",
-            F32 => "f32",
-            F64 => "f64",
-            Str => "str",
-            Bool => "bool",
-            Char => "char",
-            Array => "array",
-            Slice => "slice",
-            Tuple => "tuple",
-            Unit => "unit",
-            RawPointer => "pointer",
-            Reference => "reference",
-            Fn => "fn",
-            Never => "never",
-        }
-    }
-
     crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static ArrayVec<DefId, 4> {
         Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
     }
@@ -1861,10 +1747,6 @@ impl PrimitiveType {
         })
     }
 
-    crate fn to_url_str(&self) -> &'static str {
-        self.as_str()
-    }
-
     crate fn as_sym(&self) -> Symbol {
         use PrimitiveType::*;
         match self {
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 2c31a502565..706a56fbcbf 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -2,7 +2,7 @@ use crate::clean::auto_trait::AutoTraitFinder;
 use crate::clean::blanket_impl::BlanketImplFinder;
 use crate::clean::{
     inline, Clean, Crate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime,
-    MacroKind, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding,
+    Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding,
 };
 use crate::core::DocContext;
 use crate::formats::item_type::ItemType;
@@ -451,35 +451,48 @@ crate fn get_auto_trait_and_blanket_impls(
     auto_impls.into_iter().chain(blanket_impls)
 }
 
+/// If `res` has a documentation page associated, store it in the cache.
+///
+/// This is later used by [`href()`] to determine the HTML link for the item.
+///
+/// [`href()`]: crate::html::format::href
 crate fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId {
+    use DefKind::*;
     debug!("register_res({:?})", res);
 
     let (did, kind) = match res {
-        Res::Def(DefKind::Fn, i) => (i, ItemType::Function),
-        Res::Def(DefKind::TyAlias, i) => (i, ItemType::Typedef),
-        Res::Def(DefKind::Enum, i) => (i, ItemType::Enum),
-        Res::Def(DefKind::Trait, i) => (i, ItemType::Trait),
         Res::Def(DefKind::AssocTy | DefKind::AssocFn | DefKind::AssocConst, i) => {
+            // associated items are documented, but on the page of their parent
             (cx.tcx.parent(i).unwrap(), ItemType::Trait)
         }
-        Res::Def(DefKind::Struct, i) => (i, ItemType::Struct),
-        Res::Def(DefKind::Union, i) => (i, ItemType::Union),
-        Res::Def(DefKind::Mod, i) => (i, ItemType::Module),
-        Res::Def(DefKind::ForeignTy, i) => (i, ItemType::ForeignType),
-        Res::Def(DefKind::Const, i) => (i, ItemType::Constant),
-        Res::Def(DefKind::Static, i) => (i, ItemType::Static),
         Res::Def(DefKind::Variant, i) => {
+            // variant items are documented, but on the page of their parent
             (cx.tcx.parent(i).expect("cannot get parent def id"), ItemType::Enum)
         }
-        Res::Def(DefKind::Macro(mac_kind), i) => match mac_kind {
-            MacroKind::Bang => (i, ItemType::Macro),
-            MacroKind::Attr => (i, ItemType::ProcAttribute),
-            MacroKind::Derive => (i, ItemType::ProcDerive),
-        },
-        Res::Def(DefKind::TraitAlias, i) => (i, ItemType::TraitAlias),
-        Res::SelfTy(Some(def_id), _) => (def_id, ItemType::Trait),
-        Res::SelfTy(_, Some((impl_def_id, _))) => return impl_def_id,
-        _ => return res.def_id(),
+        // Each of these have their own page.
+        Res::Def(
+            kind
+            @
+            (Fn | TyAlias | Enum | Trait | Struct | Union | Mod | ForeignTy | Const | Static
+            | Macro(..) | TraitAlias),
+            i,
+        ) => (i, kind.into()),
+        // This is part of a trait definition; document the trait.
+        Res::SelfTy(Some(trait_def_id), _) => (trait_def_id, ItemType::Trait),
+        // This is an inherent impl; it doesn't have its own page.
+        Res::SelfTy(None, Some((impl_def_id, _))) => return impl_def_id,
+        Res::SelfTy(None, None)
+        | Res::PrimTy(_)
+        | Res::ToolMod
+        | Res::SelfCtor(_)
+        | Res::Local(_)
+        | Res::NonMacroAttr(_)
+        | Res::Err => return res.def_id(),
+        Res::Def(
+            TyParam | ConstParam | Ctor(..) | ExternCrate | Use | ForeignMod | AnonConst | OpaqueTy
+            | Field | LifetimeParam | GlobalAsm | Impl | Closure | Generator,
+            id,
+        ) => return id,
     };
     if did.is_local() {
         return did;
@@ -543,3 +556,9 @@ crate fn has_doc_flag(attrs: ty::Attributes<'_>, flag: Symbol) -> bool {
             && attr.meta_item_list().map_or(false, |l| rustc_attr::list_contains_name(&l, flag))
     })
 }
+
+/// A link to `doc.rust-lang.org` that includes the channel name. Use this instead of manual links
+/// so that the channel is consistent.
+///
+/// Set by `bootstrap::Builder::doc_rust_lang_org_channel` in order to keep tests passing on beta/stable.
+crate const DOC_RUST_LANG_ORG_CHANNEL: &'static str = env!("DOC_RUST_LANG_ORG_CHANNEL");
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 90b37338216..1b5a00dde59 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -628,7 +628,8 @@ impl Options {
         let generate_redirect_map = matches.opt_present("generate-redirect-map");
         let show_type_layout = matches.opt_present("show-type-layout");
 
-        let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
+        let (lint_opts, describe_lints, lint_cap, _) =
+            get_cmd_lint_options(matches, error_format, &debugging_opts);
 
         Ok(Options {
             input,
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 3dd13a8f170..c3d9c4ea7f2 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -217,8 +217,9 @@ crate fn create_config(
     // By default, rustdoc ignores all lints.
     // Specifically unblock lints relevant to documentation or the lint machinery itself.
     let mut lints_to_show = vec![
-        // it's unclear whether this should be part of rustdoc directly (#77364)
+        // it's unclear whether these should be part of rustdoc directly (#77364)
         rustc_lint::builtin::MISSING_DOCS.name.to_string(),
+        rustc_lint::builtin::INVALID_DOC_ATTRIBUTES.name.to_string(),
         // these are definitely not part of rustdoc, but we want to warn on them anyway.
         rustc_lint::builtin::RENAMED_AND_REMOVED_LINTS.name.to_string(),
         rustc_lint::builtin::UNKNOWN_LINTS.name.to_string(),
@@ -399,15 +400,18 @@ crate fn run_global_ctxt(
     let mut krate = tcx.sess.time("clean_crate", || clean::krate(&mut ctxt));
 
     if krate.module.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";
+        let help = format!(
+            "The following guide may be of use:\n\
+            {}/rustdoc/how-to-write-documentation.html",
+            crate::DOC_RUST_LANG_ORG_CHANNEL
+        );
         tcx.struct_lint_node(
             crate::lint::MISSING_CRATE_LEVEL_DOCS,
             DocContext::as_local_hir_id(tcx, krate.module.def_id).unwrap(),
             |lint| {
                 let mut diag =
                     lint.build("no documentation found for this crate's top-level module");
-                diag.help(help);
+                diag.help(&help);
                 diag.emit();
             },
         );
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 3a4d39e1d7f..88e2f6048e9 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -880,6 +880,7 @@ impl Tester for Collector {
         let target = self.options.target.clone();
         let target_str = target.to_string();
         let unused_externs = self.unused_extern_reports.clone();
+        let no_run = config.no_run || options.no_run;
         if !config.compile_fail {
             self.compiling_test_count.fetch_add(1, Ordering::SeqCst);
         }
@@ -941,13 +942,16 @@ impl Tester for Collector {
                 // compiler failures are test failures
                 should_panic: testing::ShouldPanic::No,
                 allow_fail: config.allow_fail,
+                #[cfg(not(bootstrap))]
+                compile_fail: config.compile_fail,
+                #[cfg(not(bootstrap))]
+                no_run,
                 test_type: testing::TestType::DocTest,
             },
             testfn: testing::DynTestFn(box move || {
                 let report_unused_externs = |uext| {
                     unused_externs.lock().unwrap().push(uext);
                 };
-                let no_run = config.no_run || options.no_run;
                 let res = run_test(
                     &test,
                     &cratename,
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 3c1d03a78f1..918a5cb5094 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -177,12 +177,22 @@ impl clean::GenericParamDef {
 
                 Ok(())
             }
-            clean::GenericParamDefKind::Const { ref ty, .. } => {
+            clean::GenericParamDefKind::Const { ref ty, ref default, .. } => {
                 if f.alternate() {
-                    write!(f, "const {}: {:#}", self.name, ty.print(cx))
+                    write!(f, "const {}: {:#}", self.name, ty.print(cx))?;
                 } else {
-                    write!(f, "const {}:&nbsp;{}", self.name, ty.print(cx))
+                    write!(f, "const {}:&nbsp;{}", self.name, ty.print(cx))?;
                 }
+
+                if let Some(default) = default {
+                    if f.alternate() {
+                        write!(f, " = {:#}", default)?;
+                    } else {
+                        write!(f, "&nbsp;=&nbsp;{}", default)?;
+                    }
+                }
+
+                Ok(())
             }
         })
     }
@@ -574,7 +584,7 @@ fn primitive_link(
                     f,
                     "<a class=\"primitive\" href=\"{}primitive.{}.html\">",
                     "../".repeat(len),
-                    prim.to_url_str()
+                    prim.as_sym()
                 )?;
                 needs_termination = true;
             }
@@ -603,7 +613,7 @@ fn primitive_link(
                         f,
                         "<a class=\"primitive\" href=\"{}/primitive.{}.html\">",
                         loc.join("/"),
-                        prim.to_url_str()
+                        prim.as_sym()
                     )?;
                     needs_termination = true;
                 }
@@ -677,7 +687,7 @@ fn fmt_type<'cx>(
             fmt::Display::fmt(&tybounds(param_names, cx), f)
         }
         clean::Infer => write!(f, "_"),
-        clean::Primitive(prim) => primitive_link(f, prim, prim.as_str(), cx),
+        clean::Primitive(prim) => primitive_link(f, prim, &*prim.as_sym().as_str(), cx),
         clean::BareFunction(ref decl) => {
             if f.alternate() {
                 write!(
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index ec04c94dc11..d2d1757b900 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -87,7 +87,7 @@ crate fn render<T: Print, S: Print>(
         {sidebar}\
     </nav>\
     <div class=\"theme-picker\">\
-        <button id=\"theme-picker\" aria-label=\"Pick another theme!\" aria-haspopup=\"menu\">\
+        <button id=\"theme-picker\" aria-label=\"Pick another theme!\" aria-haspopup=\"menu\" title=\"themes\">\
             <img src=\"{static_root_path}brush{suffix}.svg\" \
                  width=\"18\" height=\"18\" \
                  alt=\"Pick another theme!\">\
@@ -105,8 +105,8 @@ crate fn render<T: Print, S: Print>(
                            placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \
                            type=\"search\">\
                 </div>\
-                <button type=\"button\" id=\"help-button\">?</button>
-                <a id=\"settings-menu\" href=\"{root_path}settings.html\">\
+                <button type=\"button\" id=\"help-button\" title=\"help\">?</button>\
+                <a id=\"settings-menu\" href=\"{root_path}settings.html\" title=\"settings\">\
                     <img src=\"{static_root_path}wheel{suffix}.svg\" \
                          width=\"18\" height=\"18\" \
                          alt=\"Change settings\">\
@@ -119,7 +119,7 @@ crate fn render<T: Print, S: Print>(
     {after_content}\
     <div id=\"rustdoc-vars\" data-root-path=\"{root_path}\" data-current-crate=\"{krate}\" \
        data-search-index-js=\"{root_path}search-index{suffix}.js\" \
-       data-search-js=\"{static_root_path}search{suffix}.js\"></div>
+       data-search-js=\"{static_root_path}search{suffix}.js\"></div>\
     <script src=\"{static_root_path}main{suffix}.js\"></script>\
     {extra_scripts}\
 </body>\
@@ -161,7 +161,7 @@ crate fn render<T: Print, S: Print>(
             }
         },
         title = page.title,
-        description = page.description,
+        description = Escape(page.description),
         keywords = page.keywords,
         favicon = if layout.favicon.is_empty() {
             format!(
@@ -235,6 +235,7 @@ crate fn redirect(url: &str) -> String {
 <html lang="en">
 <head>
     <meta http-equiv="refresh" content="0;URL={url}">
+    <title>Redirection</title>
 </head>
 <body>
     <p>Redirecting to <a href="{url}">{url}</a>...</p>
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 8676efd9fa8..d80b2db00ac 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -200,8 +200,15 @@ impl<'tcx> Context<'tcx> {
             )
         };
         let keywords = make_item_keywords(it);
+        let name;
+        let tyname_s = if it.is_crate() {
+            name = format!("{} crate", tyname);
+            name.as_str()
+        } else {
+            tyname.as_str()
+        };
         let page = layout::Page {
-            css_class: tyname.as_str(),
+            css_class: tyname_s,
             root_path: &self.root_path(),
             static_root_path: self.shared.static_root_path.as_deref(),
             title: &title,
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index fa63286e4f5..2e940a31c2a 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -322,7 +322,13 @@ impl AllTypes {
             if !e.is_empty() {
                 let mut e: Vec<&ItemEntry> = e.iter().collect();
                 e.sort();
-                write!(f, "<h3 id=\"{}\">{}</h3><ul class=\"{} docblock\">", title, title, class);
+                write!(
+                    f,
+                    "<h3 id=\"{}\">{}</h3><ul class=\"{} docblock\">",
+                    title.replace(' ', "-"), // IDs cannot contain whitespaces.
+                    title,
+                    class
+                );
 
                 for s in e.iter() {
                     write!(f, "<li>{}</li>", s.print());
@@ -346,7 +352,7 @@ impl AllTypes {
              </h1>",
         );
         // Note: print_entries does not escape the title, because we know the current set of titles
-        // don't require escaping.
+        // doesn't require escaping.
         print_entries(f, &self.structs, "Structs", "structs");
         print_entries(f, &self.enums, "Enums", "enums");
         print_entries(f, &self.unions, "Unions", "unions");
@@ -1280,7 +1286,6 @@ fn render_impl(
     // in documentation pages for trait with automatic implementations like "Send" and "Sync".
     aliases: &[String],
 ) {
-    let tcx = cx.tcx();
     let cache = cx.cache();
     let traits = &cache.traits;
     let trait_ = i.trait_did_full(cache).map(|did| &traits[&did]);
@@ -1369,7 +1374,11 @@ fn render_impl(
                             })
                         })
                         .map(|item| format!("{}.{}", item.type_(), name));
-                    write!(w, "<h4 id=\"{}\" class=\"{}{}\">", id, item_type, in_trait_class,);
+                    write!(
+                        w,
+                        "<div id=\"{}\" class=\"{}{} has-srclink\">",
+                        id, item_type, in_trait_class,
+                    );
                     w.write_str("<code>");
                     render_assoc_item(
                         w,
@@ -1388,13 +1397,17 @@ fn render_impl(
                     );
                     write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
                     write_srclink(cx, item, w);
-                    w.write_str("</h4>");
+                    w.write_str("</div>");
                 }
             }
             clean::TypedefItem(ref tydef, _) => {
                 let source_id = format!("{}.{}", ItemType::AssocType, name);
                 let id = cx.derive_id(source_id.clone());
-                write!(w, "<h4 id=\"{}\" class=\"{}{}\"><code>", id, item_type, in_trait_class);
+                write!(
+                    w,
+                    "<div id=\"{}\" class=\"{}{} has-srclink\"><code>",
+                    id, item_type, in_trait_class
+                );
                 assoc_type(
                     w,
                     item,
@@ -1406,12 +1419,16 @@ fn render_impl(
                 );
                 w.write_str("</code>");
                 write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
-                w.write_str("</h4>");
+                w.write_str("</div>");
             }
             clean::AssocConstItem(ref ty, ref default) => {
                 let source_id = format!("{}.{}", item_type, name);
                 let id = cx.derive_id(source_id.clone());
-                write!(w, "<h4 id=\"{}\" class=\"{}{}\"><code>", id, item_type, in_trait_class);
+                write!(
+                    w,
+                    "<div id=\"{}\" class=\"{}{} has-srclink\"><code>",
+                    id, item_type, in_trait_class
+                );
                 assoc_const(
                     w,
                     item,
@@ -1431,12 +1448,12 @@ fn render_impl(
                 );
                 write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
                 write_srclink(cx, item, w);
-                w.write_str("</h4>");
+                w.write_str("</div>");
             }
             clean::AssocTypeItem(ref bounds, ref default) => {
                 let source_id = format!("{}.{}", item_type, name);
                 let id = cx.derive_id(source_id.clone());
-                write!(w, "<h4 id=\"{}\" class=\"{}{}\"><code>", id, item_type, in_trait_class);
+                write!(w, "<div id=\"{}\" class=\"{}{}\"><code>", id, item_type, in_trait_class,);
                 assoc_type(
                     w,
                     item,
@@ -1448,7 +1465,7 @@ fn render_impl(
                 );
                 w.write_str("</code>");
                 write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
-                w.write_str("</h4>");
+                w.write_str("</div>");
             }
             clean::StrippedItem(..) => return,
             _ => panic!("can't make docs for trait item with name {:?}", item.name),
@@ -1540,92 +1557,34 @@ fn render_impl(
             );
         }
     }
-    let toggled = !impl_items.is_empty() || !default_impl_items.is_empty();
-    let open_details = |close_tags: &mut String, is_collapsed: bool| {
+    if render_mode == RenderMode::Normal {
+        let is_implementing_trait = i.inner_impl().trait_.is_some();
+        let toggled = !impl_items.is_empty() || !default_impl_items.is_empty();
         if toggled {
             close_tags.insert_str(0, "</details>");
-            if is_collapsed {
-                "<details class=\"rustdoc-toggle implementors-toggle\"><summary>"
+            if is_implementing_trait {
+                write!(w, "<details class=\"rustdoc-toggle implementors-toggle\">");
             } else {
-                "<details class=\"rustdoc-toggle implementors-toggle\" open><summary>"
+                write!(w, "<details class=\"rustdoc-toggle implementors-toggle\" open>");
             }
-        } else {
-            ""
         }
-    };
-    if render_mode == RenderMode::Normal {
-        let is_implementing_trait;
-        let id = cx.derive_id(match i.inner_impl().trait_ {
-            Some(ref t) => {
-                is_implementing_trait = true;
-                if is_on_foreign_type {
-                    get_id_for_impl_on_foreign_type(&i.inner_impl().for_, t, cx)
-                } else {
-                    format!("impl-{}", small_url_encode(format!("{:#}", t.print(cx))))
-                }
-            }
-            None => {
-                is_implementing_trait = false;
-                "impl".to_string()
-            }
-        });
-        let aliases = if aliases.is_empty() {
-            String::new()
-        } else {
-            format!(" data-aliases=\"{}\"", aliases.join(","))
-        };
-        if let Some(use_absolute) = use_absolute {
-            write!(
-                w,
-                "{}<h3 id=\"{}\" class=\"impl\"{}><code class=\"in-band\">",
-                open_details(&mut close_tags, is_implementing_trait),
-                id,
-                aliases
-            );
-            write!(w, "{}", i.inner_impl().print(use_absolute, cx));
-            if show_def_docs {
-                for it in &i.inner_impl().items {
-                    if let clean::TypedefItem(ref tydef, _) = *it.kind {
-                        w.write_str("<span class=\"where fmt-newline\">  ");
-                        assoc_type(
-                            w,
-                            it,
-                            &[],
-                            Some(&tydef.type_),
-                            AssocItemLink::Anchor(None),
-                            "",
-                            cx,
-                        );
-                        w.write_str(";</span>");
-                    }
-                }
-            }
-            w.write_str("</code>");
-        } else {
-            write!(
-                w,
-                "{}<h3 id=\"{}\" class=\"impl\"{}><code class=\"in-band\">{}</code>",
-                open_details(&mut close_tags, is_implementing_trait),
-                id,
-                aliases,
-                i.inner_impl().print(false, cx)
-            );
+        if toggled {
+            write!(w, "<summary>")
         }
-        write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
-        render_stability_since_raw(
+        render_impl_summary(
             w,
-            i.impl_item.stable_since(tcx).as_deref(),
-            i.impl_item.const_stable_since(tcx).as_deref(),
+            cx,
+            i,
             outer_version,
             outer_const_version,
+            show_def_docs,
+            use_absolute,
+            is_on_foreign_type,
+            aliases,
         );
-        write_srclink(cx, &i.impl_item, w);
-        if !toggled {
-            w.write_str("</h3>");
-        } else {
-            w.write_str("</h3></summary>");
+        if toggled {
+            write!(w, "</summary>")
         }
-
         if trait_.is_some() {
             if let Some(portability) = portability(&i.impl_item, Some(parent)) {
                 write!(w, "<div class=\"item-info\">{}</div>", portability);
@@ -1649,13 +1608,84 @@ fn render_impl(
             );
         }
     }
-    w.write_str("<div class=\"impl-items\">");
-    w.push_buffer(default_impl_items);
-    w.push_buffer(impl_items);
-    close_tags.insert_str(0, "</div>");
+    if !default_impl_items.is_empty() || !impl_items.is_empty() {
+        w.write_str("<div class=\"impl-items\">");
+        w.push_buffer(default_impl_items);
+        w.push_buffer(impl_items);
+        close_tags.insert_str(0, "</div>");
+    }
     w.write_str(&close_tags);
 }
 
+fn render_impl_summary(
+    w: &mut Buffer,
+    cx: &Context<'_>,
+    i: &Impl,
+    outer_version: Option<&str>,
+    outer_const_version: Option<&str>,
+    show_def_docs: bool,
+    use_absolute: Option<bool>,
+    is_on_foreign_type: bool,
+    // This argument is used to reference same type with different paths to avoid duplication
+    // in documentation pages for trait with automatic implementations like "Send" and "Sync".
+    aliases: &[String],
+) {
+    let tcx = cx.tcx();
+    let id = cx.derive_id(match i.inner_impl().trait_ {
+        Some(ref t) => {
+            if is_on_foreign_type {
+                get_id_for_impl_on_foreign_type(&i.inner_impl().for_, t, cx)
+            } else {
+                format!("impl-{}", small_url_encode(format!("{:#}", t.print(cx))))
+            }
+        }
+        None => "impl".to_string(),
+    });
+    let aliases = if aliases.is_empty() {
+        String::new()
+    } else {
+        format!(" data-aliases=\"{}\"", aliases.join(","))
+    };
+    if let Some(use_absolute) = use_absolute {
+        write!(
+            w,
+            "<div id=\"{}\" class=\"impl has-srclink\"{}>\
+                     <code class=\"in-band\">",
+            id, aliases
+        );
+        write!(w, "{}", i.inner_impl().print(use_absolute, cx));
+        if show_def_docs {
+            for it in &i.inner_impl().items {
+                if let clean::TypedefItem(ref tydef, _) = *it.kind {
+                    w.write_str("<span class=\"where fmt-newline\">  ");
+                    assoc_type(w, it, &[], Some(&tydef.type_), AssocItemLink::Anchor(None), "", cx);
+                    w.write_str(";</span>");
+                }
+            }
+        }
+        w.write_str("</code>");
+    } else {
+        write!(
+            w,
+            "<div id=\"{}\" class=\"impl has-srclink\"{}>\
+                     <code class=\"in-band\">{}</code>",
+            id,
+            aliases,
+            i.inner_impl().print(false, cx)
+        );
+    }
+    write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
+    render_stability_since_raw(
+        w,
+        i.impl_item.stable_since(tcx).as_deref(),
+        i.impl_item.const_stable_since(tcx).as_deref(),
+        outer_version,
+        outer_const_version,
+    );
+    write_srclink(cx, &i.impl_item, w);
+    w.write_str("</div>");
+}
+
 fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
     let parentlen = cx.current.len() - if it.is_mod() { 1 } else { 0 };
 
@@ -1697,7 +1727,7 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
                 "<div class=\"block version\">\
                      <p>Version {}</p>\
                  </div>",
-                Escape(version)
+                Escape(version),
             );
         }
     }
@@ -1707,9 +1737,10 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
         write!(
             buffer,
             "<a id=\"all-types\" href=\"all.html\"><p>See all {}'s items</p></a>",
-            it.name.as_ref().expect("crates always have a name")
+            it.name.as_ref().expect("crates always have a name"),
         );
     }
+
     match *it.kind {
         clean::StructItem(ref s) => sidebar_struct(cx, buffer, it, s),
         clean::TraitItem(ref t) => sidebar_trait(cx, buffer, it, t),
@@ -1719,7 +1750,7 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
         clean::TypedefItem(_, _) => sidebar_typedef(cx, buffer, it),
         clean::ModuleItem(ref m) => sidebar_module(buffer, &m.items),
         clean::ForeignTypeItem => sidebar_foreign_type(cx, buffer, it),
-        _ => (),
+        _ => {}
     }
 
     // The sidebar is designed to display sibling functions, modules and
@@ -1730,22 +1761,24 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
     // as much HTML as possible in order to allow non-JS-enabled browsers
     // to navigate the documentation (though slightly inefficiently).
 
-    buffer.write_str("<p class=\"location\">");
-    for (i, name) in cx.current.iter().take(parentlen).enumerate() {
-        if i > 0 {
-            buffer.write_str("::<wbr>");
+    if !it.is_mod() {
+        buffer.write_str("<p class=\"location\">Other items in<br>");
+        for (i, name) in cx.current.iter().take(parentlen).enumerate() {
+            if i > 0 {
+                buffer.write_str("::<wbr>");
+            }
+            write!(
+                buffer,
+                "<a href=\"{}index.html\">{}</a>",
+                &cx.root_path()[..(cx.current.len() - i - 1) * 3],
+                *name
+            );
         }
-        write!(
-            buffer,
-            "<a href=\"{}index.html\">{}</a>",
-            &cx.root_path()[..(cx.current.len() - i - 1) * 3],
-            *name
-        );
+        buffer.write_str("</p>");
     }
-    buffer.write_str("</p>");
 
     // Sidebar refers to the enclosing module, not this module.
-    let relpath = if it.is_mod() { "../" } else { "" };
+    let relpath = if it.is_mod() && parentlen != 0 { "./" } else { "" };
     write!(
         buffer,
         "<div id=\"sidebar-vars\" data-name=\"{name}\" data-ty=\"{ty}\" data-relpath=\"{path}\">\
@@ -1754,17 +1787,7 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
         ty = it.type_(),
         path = relpath
     );
-
-    if parentlen == 0 {
-        write!(
-            buffer,
-            "<script defer src=\"{}sidebar-items{}.js\"></script>",
-            relpath, cx.shared.resource_suffix
-        );
-    } else {
-        write!(buffer, "<script defer src=\"{}sidebar-items.js\"></script>", relpath);
-    }
-
+    write!(buffer, "<script defer src=\"{}sidebar-items.js\"></script>", relpath);
     // Closes sidebar-elems div.
     buffer.write_str("</div>");
 }
@@ -2272,8 +2295,8 @@ fn sidebar_enum(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, e: &clean:
     }
 }
 
-fn item_ty_to_strs(ty: &ItemType) -> (&'static str, &'static str) {
-    match *ty {
+fn item_ty_to_strs(ty: ItemType) -> (&'static str, &'static str) {
+    match ty {
         ItemType::ExternCrate | ItemType::Import => ("reexports", "Re-exports"),
         ItemType::Module => ("modules", "Modules"),
         ItemType::Struct => ("structs", "Structs"),
@@ -2305,10 +2328,14 @@ fn item_ty_to_strs(ty: &ItemType) -> (&'static str, &'static str) {
 fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) {
     let mut sidebar = String::new();
 
+    // Re-exports are handled a bit differently because they can be extern crates or imports.
     if items.iter().any(|it| {
-        it.type_() == ItemType::ExternCrate || (it.type_() == ItemType::Import && !it.is_stripped())
+        it.name.is_some()
+            && (it.type_() == ItemType::ExternCrate
+                || (it.type_() == ItemType::Import && !it.is_stripped()))
     }) {
-        sidebar.push_str("<li><a href=\"#reexports\">Re-exports</a></li>");
+        let (id, name) = item_ty_to_strs(ItemType::Import);
+        sidebar.push_str(&format!("<li><a href=\"#{}\">{}</a></li>", id, name));
     }
 
     // ordering taken from item_module, reorder, where it prioritized elements in a certain order
@@ -2335,13 +2362,9 @@ fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) {
         ItemType::ForeignType,
         ItemType::Keyword,
     ] {
-        if items.iter().any(|it| !it.is_stripped() && it.type_() == myty) {
-            let (short, name) = item_ty_to_strs(&myty);
-            sidebar.push_str(&format!(
-                "<li><a href=\"#{id}\">{name}</a></li>",
-                id = short,
-                name = name
-            ));
+        if items.iter().any(|it| !it.is_stripped() && it.type_() == myty && it.name.is_some()) {
+            let (id, name) = item_ty_to_strs(myty);
+            sidebar.push_str(&format!("<li><a href=\"#{}\">{}</a></li>", id, name));
         }
     }
 
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 42d7e9c8c93..04464b622d7 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -75,10 +75,10 @@ pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer,
             );
         }
     }
-    write!(buf, "<a class=\"{}\" href=\"\">{}</a>", item.type_(), item.name.as_ref().unwrap());
+    write!(buf, "<a class=\"{}\" href=\"#\">{}</a>", item.type_(), item.name.as_ref().unwrap());
     write!(
         buf,
-        "<button id=\"copy-path\" onclick=\"copy_path(this)\">\
+        "<button id=\"copy-path\" onclick=\"copy_path(this)\" title=\"copy path\">\
             <img src=\"{static_root_path}clipboard{suffix}.svg\" \
                 width=\"19\" height=\"18\" \
                 alt=\"Copy item import\" \
@@ -263,7 +263,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
                 w.write_str("</table>");
             }
             curty = myty;
-            let (short, name) = item_ty_to_strs(&myty.unwrap());
+            let (short, name) = item_ty_to_strs(myty.unwrap());
             write!(
                 w,
                 "<h2 id=\"{id}\" class=\"section-header\">\
@@ -585,12 +585,12 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
         if toggled {
             write!(w, "<details class=\"rustdoc-toggle\" open><summary>");
         }
-        write!(w, "<h3 id=\"{id}\" class=\"method\"><code>", id = id);
+        write!(w, "<div id=\"{}\" class=\"method has-srclink\"><code>", id);
         render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl, cx);
         w.write_str("</code>");
         render_stability_since(w, m, t, cx.tcx());
         write_srclink(cx, m, w);
-        w.write_str("</h3>");
+        w.write_str("</div>");
         if toggled {
             write!(w, "</summary>");
             w.push_buffer(content);
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index 73ffec0dd4e..a4188e6b203 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -227,7 +227,6 @@ pub(super) fn write_shared(
     )?;
     write_minify("search.js", static_files::SEARCH_JS)?;
     write_minify("settings.js", static_files::SETTINGS_JS)?;
-    write_minify("sidebar-items.js", static_files::sidebar::ITEMS)?;
 
     if cx.shared.include_sources {
         write_minify("source-script.js", static_files::sidebar::SOURCE_SCRIPT)?;
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index a96b0c87108..1a15a444a70 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -561,41 +561,40 @@ function hideThemeButtonState() {
         }
     }());
 
-    function addSidebarCrates(crates) {
-        // Draw a convenient sidebar of known crates if we have a listing
-        if (window.rootPath === "../" || window.rootPath === "./") {
-            var sidebar = document.getElementsByClassName("sidebar-elems")[0];
-            if (sidebar) {
-                var div = document.createElement("div");
-                div.className = "block crate";
-                div.innerHTML = "<h3>Crates</h3>";
-                var ul = document.createElement("ul");
-                div.appendChild(ul);
-
-                for (var i = 0; i < crates.length; ++i) {
-                    var klass = "crate";
-                    if (window.rootPath !== "./" && crates[i] === window.currentCrate) {
-                        klass += " current";
-                    }
-                    var link = document.createElement("a");
-                    link.href = window.rootPath + crates[i] + "/index.html";
-                    link.className = klass;
-                    link.textContent = crates[i];
-
-                    var li = document.createElement("li");
-                    li.appendChild(link);
-                    ul.appendChild(li);
-                }
-                sidebar.appendChild(div);
-            }
-        }
-    }
-
     // delayed sidebar rendering.
     window.initSidebarItems = function(items) {
         var sidebar = document.getElementsByClassName("sidebar-elems")[0];
         var current = window.sidebarCurrent;
 
+        function addSidebarCrates(crates) {
+            if (!hasClass(document.body, "crate")) {
+                // We only want to list crates on the crate page.
+                return;
+            }
+            // Draw a convenient sidebar of known crates if we have a listing
+            var div = document.createElement("div");
+            div.className = "block crate";
+            div.innerHTML = "<h3>Crates</h3>";
+            var ul = document.createElement("ul");
+            div.appendChild(ul);
+
+            for (var i = 0; i < crates.length; ++i) {
+                var klass = "crate";
+                if (window.rootPath !== "./" && crates[i] === window.currentCrate) {
+                    klass += " current";
+                }
+                var link = document.createElement("a");
+                link.href = window.rootPath + crates[i] + "/index.html";
+                link.className = klass;
+                link.textContent = crates[i];
+
+                var li = document.createElement("li");
+                li.appendChild(link);
+                ul.appendChild(li);
+            }
+            sidebar.appendChild(div);
+        }
+
         function block(shortty, longty) {
             var filtered = items[shortty];
             if (!filtered) {
@@ -634,28 +633,32 @@ function hideThemeButtonState() {
                 ul.appendChild(li);
             }
             div.appendChild(ul);
-            if (sidebar) {
-                sidebar.appendChild(div);
-            }
+            sidebar.appendChild(div);
         }
 
-        block("primitive", "Primitive Types");
-        block("mod", "Modules");
-        block("macro", "Macros");
-        block("struct", "Structs");
-        block("enum", "Enums");
-        block("union", "Unions");
-        block("constant", "Constants");
-        block("static", "Statics");
-        block("trait", "Traits");
-        block("fn", "Functions");
-        block("type", "Type Definitions");
-        block("foreigntype", "Foreign Types");
-        block("keyword", "Keywords");
-        block("traitalias", "Trait Aliases");
-
-        // `crates{version}.js` should always be loaded before this script, so we can use it safely.
-        addSidebarCrates(window.ALL_CRATES);
+        if (sidebar) {
+            var isModule = hasClass(document.body, "mod");
+            if (!isModule) {
+                block("primitive", "Primitive Types");
+                block("mod", "Modules");
+                block("macro", "Macros");
+                block("struct", "Structs");
+                block("enum", "Enums");
+                block("union", "Unions");
+                block("constant", "Constants");
+                block("static", "Statics");
+                block("trait", "Traits");
+                block("fn", "Functions");
+                block("type", "Type Definitions");
+                block("foreigntype", "Foreign Types");
+                block("keyword", "Keywords");
+                block("traitalias", "Trait Aliases");
+            }
+
+            // `crates{version}.js` should always be loaded before this script, so we can use
+            // it safely.
+            addSidebarCrates(window.ALL_CRATES);
+        }
     };
 
     window.register_implementors = function(imp) {
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 2623ff27a25..d8684641a30 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -117,8 +117,7 @@ h2 {
 h3 {
 	font-size: 1.3em;
 }
-h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod):not(.notable),
-h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant):not(.associatedtype) {
+h1, h2, h3, h4 {
 	font-weight: 500;
 	margin: 20px 0 15px 0;
 	padding-bottom: 6px;
@@ -135,30 +134,38 @@ h1.fqn {
 h1.fqn > .in-band > a:hover {
 	text-decoration: underline;
 }
-h2, h3:not(.impl):not(.method):not(.type):not(.tymethod),
-h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant):not(.associatedtype) {
+h2, h3, h4 {
 	border-bottom: 1px solid;
 }
-h3.impl, h3.method, h4.method, h3.type, h4.type, h4.associatedconstant, h4.associatedtype {
+.impl, .method,
+.type:not(.container-rustdoc), .associatedconstant,
+.associatedtype {
 	flex-basis: 100%;
 	font-weight: 600;
 	margin-top: 16px;
 	margin-bottom: 10px;
 	position: relative;
 }
-h3.impl, h3.method, h4.method.trait-impl, h3.type,
-h4.type.trait-impl, h4.associatedconstant.trait-impl, h4.associatedtype.trait-impl {
+.impl, .method.trait-impl,
+.type.trait-impl,
+.associatedconstant.trait-impl,
+.associatedtype.trait-impl {
 	padding-left: 15px;
 }
 
+div.impl-items > div {
+	padding-left: 0;
+}
+
 h1, h2, h3, h4,
 .sidebar, a.source, .search-input, .search-results .result-name,
 .content table td:first-child > a,
-div.item-list .out-of-band,
+div.item-list .out-of-band, span.since,
 #source-sidebar, #sidebar-toggle,
 details.rustdoc-toggle > summary::before,
 details.undocumented > summary::before,
-.content ul.crate a.crate,
+div.impl-items > div:not(.docblock):not(.item-info),
+.content ul.crate a.crate, a.srclink,
 /* This selector is for the items listed in the "all items" page. */
 #main > ul.docblock > li > a {
 	font-family: "Fira Sans", Arial, sans-serif;
@@ -304,17 +311,18 @@ nav.sub {
 	border: none;
 }
 
-.location a:first-child {
+.location a:first-of-type {
 	font-weight: 500;
 }
+.location a:hover {
+	text-decoration: underline;
+}
 
 .block {
 	padding: 0;
 	margin-bottom: 14px;
 }
 .block h2, .block h3 {
-	margin-top: 0;
-	margin-bottom: 8px;
 	text-align: center;
 }
 .block ul, .block li {
@@ -462,15 +470,7 @@ nav.sub {
 	font-weight: normal;
 }
 
-h3.impl > .out-of-band {
-	font-size: 21px;
-}
-
-h4.method > .out-of-band {
-	font-size: 19px;
-}
-
-h4 > code, h3 > code, .invisible > code {
+.method > code, .trait-impl > code, .invisible > code {
 	max-width: calc(100% - 41px);
 	display: block;
 }
@@ -543,7 +543,7 @@ h4 > code, h3 > code, .invisible > code {
 }
 .content .multi-column li { width: 100%; display: inline-block; }
 
-.content .method {
+.content > .methods > .method {
 	font-size: 1em;
 	position: relative;
 }
@@ -555,7 +555,7 @@ h4 > code, h3 > code, .invisible > code {
 	font-size: 0.8em;
 }
 
-.content .methods > div:not(.notable-traits):not(.methods) {
+.content .methods > div:not(.notable-traits):not(.method) {
 	margin-left: 40px;
 	margin-bottom: 15px;
 }
@@ -564,9 +564,6 @@ h4 > code, h3 > code, .invisible > code {
 	margin-left: 20px;
 	margin-top: -34px;
 }
-.content .docblock > .impl-items > h4 {
-	border-bottom: 0;
-}
 .content .docblock >.impl-items .table-display {
 	margin: 0;
 }
@@ -688,7 +685,8 @@ a {
 	text-decoration: underline;
 }
 
-.invisible > .srclink, h4 > code + .srclink, h3 > code + .srclink {
+.invisible > .srclink,
+.method > code + .srclink {
 	position: absolute;
 	top: 0;
 	right: 0;
@@ -802,6 +800,8 @@ a {
 
 .search-results .result-name > span {
 	display: inline-block;
+	margin: 0;
+	font-weight: normal;
 }
 
 body.blur > :not(#help) {
@@ -923,7 +923,7 @@ body.blur > :not(#help) {
 	flex-grow: 1;
 }
 
-.impl-items h4, h4.impl, h3.impl, .methods h3 {
+.has-srclink {
 	display: flex;
 	flex-basis: 100%;
 	font-size: 16px;
@@ -1134,6 +1134,13 @@ a.test-arrow:hover{
 	margin: 0;
 }
 
+.notable-traits .notable {
+	margin: 0;
+	margin-bottom: 13px;
+	font-size: 19px;
+	font-weight: 600;
+}
+
 .notable-traits .docblock code.content{
 	margin: 0;
 	padding: 0;
@@ -1197,12 +1204,6 @@ pre.rust {
 	margin-left: 5px;
 }
 
-h4 > .notable-traits {
-	position: absolute;
-	left: -44px;
-	top: 2px;
-}
-
 #all-types {
 	text-align: center;
 	border: 1px solid;
@@ -1316,14 +1317,6 @@ h4 > .notable-traits {
 	border-top: 1px solid;
 }
 
-
-
-h3.notable {
-	margin: 0;
-	margin-bottom: 13px;
-	font-size: 19px;
-}
-
 kbd {
 	display: inline-block;
 	padding: 3px 5px;
@@ -1615,10 +1608,6 @@ details.undocumented[open] > summary::before {
 		padding: 0;
 	}
 
-	.content h4 > .out-of-band {
-		position: inherit;
-	}
-
 	#search {
 		margin-left: 0;
 	}
@@ -1638,7 +1627,7 @@ details.undocumented[open] > summary::before {
 		z-index: 1;
 	}
 
-	h4 > .notable-traits {
+	.notable-traits {
 		position: absolute;
 		left: -22px;
 		top: 24px;
diff --git a/src/librustdoc/html/static/search.js b/src/librustdoc/html/static/search.js
index b3242bf4df9..35be246b5bf 100644
--- a/src/librustdoc/html/static/search.js
+++ b/src/librustdoc/html/static/search.js
@@ -1024,7 +1024,7 @@ window.initSearch = function(rawSearchIndex) {
                 var description = document.createElement("div");
                 description.className = "desc";
                 var spanDesc = document.createElement("span");
-                spanDesc.innerText = item.desc + "\u00A0";
+                spanDesc.insertAdjacentHTML("beforeend", item.desc);
 
                 description.appendChild(spanDesc);
                 wrapper.appendChild(description);
diff --git a/src/librustdoc/html/static/sidebar-items.js b/src/librustdoc/html/static/sidebar-items.js
deleted file mode 100644
index 256cd2740a0..00000000000
--- a/src/librustdoc/html/static/sidebar-items.js
+++ /dev/null
@@ -1,2 +0,0 @@
-/* global initSidebarItems */
-initSidebarItems({});
diff --git a/src/librustdoc/html/static/themes/ayu.css b/src/librustdoc/html/static/themes/ayu.css
index fd47c085b84..d220d8708a1 100644
--- a/src/librustdoc/html/static/themes/ayu.css
+++ b/src/librustdoc/html/static/themes/ayu.css
@@ -10,8 +10,7 @@ body {
 	color: #c5c5c5;
 }
 
-h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod),
-h4:not(.method):not(.type):not(.tymethod) {
+h1, h2, h3, h4 {
 	color: white;
 }
 h1.fqn {
@@ -20,10 +19,10 @@ h1.fqn {
 h1.fqn  a {
 	color: #fff;
 }
-h2, h3:not(.impl):not(.method):not(.type):not(.tymethod) {
+h2, h3, h4 {
 	border-bottom-color: #5c6773;
 }
-h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant) {
+h4 {
 	border: none;
 }
 
@@ -407,6 +406,10 @@ pre.ignore:hover, .information:hover + pre.ignore {
 	border-color: #5c6773;
 }
 
+.notable-traits-tooltiptext .notable {
+	border-bottom-color: #5c6773;
+}
+
 #titles > button.selected {
 	background-color: #141920 !important;
 	border-bottom: 1px solid #ffb44c !important;
diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css
index d6e1a880a4e..6385a763f2e 100644
--- a/src/librustdoc/html/static/themes/dark.css
+++ b/src/librustdoc/html/static/themes/dark.css
@@ -3,15 +3,13 @@ body {
 	color: #ddd;
 }
 
-h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod),
-h4:not(.method):not(.type):not(.tymethod) {
+h1, h2, h3, h4 {
 	color: #ddd;
 }
 h1.fqn {
 	border-bottom-color: #d2d2d2;
 }
-h2, h3:not(.impl):not(.method):not(.type):not(.tymethod),
-h4:not(.method):not(.type):not(.tymethod) {
+h2, h3, h4 {
 	border-bottom-color: #d2d2d2;
 }
 
@@ -356,6 +354,10 @@ pre.ignore:hover, .information:hover + pre.ignore {
 	border-color: #777;
 }
 
+.notable-traits-tooltiptext .notable {
+	border-bottom-color: #d2d2d2;
+}
+
 #titles > button:not(.selected) {
 	background-color: #252525;
 	border-top-color: #252525;
diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css
index c8151f1cf97..c19d5bfc317 100644
--- a/src/librustdoc/html/static/themes/light.css
+++ b/src/librustdoc/html/static/themes/light.css
@@ -5,15 +5,13 @@ body {
 	color: black;
 }
 
-h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod),
-h4:not(.method):not(.type):not(.tymethod) {
+h1, h2, h3, h4 {
 	color: black;
 }
 h1.fqn {
 	border-bottom-color: #D5D5D5;
 }
-h2, h3:not(.impl):not(.method):not(.type):not(.tymethod),
-h4:not(.method):not(.type):not(.tymethod) {
+h2, h3, h4 {
 	border-bottom-color: #DDDDDD;
 }
 
@@ -348,6 +346,10 @@ pre.ignore:hover, .information:hover + pre.ignore {
 	border-color: #999;
 }
 
+.notable-traits-tooltiptext .notable {
+	border-bottom-color: #DDDDDD;
+}
+
 #titles > button:not(.selected) {
 	background-color: #e6e6e6;
 	border-top-color: #e6e6e6;
diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs
index 0e4fb086a15..ca7e5ef8150 100644
--- a/src/librustdoc/html/static_files.rs
+++ b/src/librustdoc/html/static_files.rs
@@ -141,7 +141,4 @@ crate mod noto_sans_kr {
 crate mod sidebar {
     /// File script to handle sidebar.
     crate static SOURCE_SCRIPT: &str = include_str!("static/source-script.js");
-
-    /// Top Level sidebar items script which will load a sidebar without items.
-    crate static ITEMS: &str = include_str!("static/sidebar-items.js");
 }
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index c6646ba9ae4..7086dd8c4d2 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -317,7 +317,9 @@ impl FromWithTcx<clean::GenericParamDefKind> for GenericParamDefKind {
                 bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
                 default: default.map(|x| x.into_tcx(tcx)),
             },
-            Const { did: _, ty } => GenericParamDefKind::Const(ty.into_tcx(tcx)),
+            Const { did: _, ty, default } => {
+                GenericParamDefKind::Const { ty: ty.into_tcx(tcx), default }
+            }
         }
     }
 }
@@ -379,7 +381,7 @@ impl FromWithTcx<clean::Type> for Type {
                     .unwrap_or_default(),
             },
             Generic(s) => Type::Generic(s.to_string()),
-            Primitive(p) => Type::Primitive(p.as_str().to_string()),
+            Primitive(p) => Type::Primitive(p.as_sym().to_string()),
             BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))),
             Tuple(t) => Type::Tuple(t.into_iter().map(|x| x.into_tcx(tcx)).collect()),
             Slice(t) => Type::Slice(Box::new((*t).into_tcx(tcx))),
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index f8bd9710813..0d84bf250c9 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -234,7 +234,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
                     )
                 })
                 .collect(),
-            format_version: 5,
+            format_version: 6,
         };
         let mut p = self.out_path.clone();
         p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index bf0be626356..ee7a716655b 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -81,6 +81,8 @@ use rustc_session::config::{make_crate_type_option, ErrorOutputType, RustcOptGro
 use rustc_session::getopts;
 use rustc_session::{early_error, early_warn};
 
+use crate::clean::utils::DOC_RUST_LANG_ORG_CHANNEL;
+
 /// A macro to create a FxHashMap.
 ///
 /// Example:
@@ -510,6 +512,14 @@ fn opts() -> Vec<RustcOptGroup> {
                 "LEVEL",
             )
         }),
+        unstable("force-warns", |o| {
+            o.optopt(
+                "",
+                "force-warns",
+                "Lints that will warn even if allowed somewhere else",
+                "LINTS",
+            )
+        }),
         unstable("index-page", |o| {
             o.optopt("", "index-page", "Markdown file to be used as index page", "PATH")
         }),
@@ -603,7 +613,10 @@ fn usage(argv0: &str) {
     }
     println!("{}", options.usage(&format!("{} [options] <input>", argv0)));
     println!("    @path               Read newline separated options from `path`\n");
-    println!("More information available at https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html")
+    println!(
+        "More information available at {}/rustdoc/what-is-rustdoc.html",
+        DOC_RUST_LANG_ORG_CHANNEL
+    );
 }
 
 /// A result type used by several functions under `main()`.
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 81c90f4eaa7..247a020f2a2 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -91,10 +91,10 @@ impl Res {
         }
     }
 
-    fn name(self, tcx: TyCtxt<'_>) -> String {
+    fn name(self, tcx: TyCtxt<'_>) -> Symbol {
         match self {
-            Res::Def(_, id) => tcx.item_name(id).to_string(),
-            Res::Primitive(prim) => prim.as_str().to_string(),
+            Res::Def(_, id) => tcx.item_name(id),
+            Res::Primitive(prim) => prim.as_sym(),
         }
     }
 
@@ -388,7 +388,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                         ty::AssocKind::Const => "associatedconstant",
                         ty::AssocKind::Type => "associatedtype",
                     };
-                    let fragment = format!("{}#{}.{}", prim_ty.as_str(), out, item_name);
+                    let fragment = format!("{}#{}.{}", prim_ty.as_sym(), out, item_name);
                     (Res::Primitive(prim_ty), fragment, Some((kind.as_def_kind(), item.def_id)))
                 })
         })
@@ -481,7 +481,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                             AnchorFailure::RustdocAnchorConflict(res),
                         ));
                     }
-                    return Ok((res, Some(ty.as_str().to_owned())));
+                    return Ok((res, Some(ty.as_sym().to_string())));
                 }
                 _ => return Ok((res, extra_fragment.clone())),
             }
@@ -1148,7 +1148,7 @@ impl LinkCollector<'_, '_> {
                         return None;
                     }
                     res = prim;
-                    fragment = Some(prim.name(self.cx.tcx));
+                    fragment = Some(prim.name(self.cx.tcx).to_string());
                 } else {
                     // `[char]` when a `char` module is in scope
                     let candidates = vec![res, prim];
@@ -1999,8 +1999,11 @@ fn disambiguator_error(
 ) {
     diag_info.link_range = disambiguator_range;
     report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, _sp| {
-        let msg = "see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators";
-        diag.note(msg);
+        let msg = format!(
+            "see {}/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators",
+            crate::DOC_RUST_LANG_ORG_CHANNEL
+        );
+        diag.note(&msg);
     });
 }
 
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 191d8d5a2ea..b563c4f4799 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -9,6 +9,7 @@ use rustc_hir::Node;
 use rustc_middle::middle::privacy::AccessLevel;
 use rustc_middle::ty::TyCtxt;
 use rustc_span;
+use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Symbol};
 
@@ -76,7 +77,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             &Spanned { span, node: hir::VisibilityKind::Public },
             hir::CRATE_HIR_ID,
             &krate.item,
-            self.cx.tcx.crate_name,
+            self.cx.tcx.crate_name(LOCAL_CRATE),
         );
         // 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
diff --git a/src/llvm-project b/src/llvm-project
-Subproject 5f67a5715771b7d29e4713e8d68338602d216dc
+Subproject 39c5555872cc5d379cc3535a31dc0cdac969466
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index 72a4d9a1830..6d9a5cb515a 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -324,7 +324,7 @@ pub struct GenericParamDef {
 pub enum GenericParamDefKind {
     Lifetime,
     Type { bounds: Vec<GenericBound>, default: Option<Type> },
-    Const(Type),
+    Const { ty: Type, default: Option<String> },
 }
 
 #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
diff --git a/src/test/assembly/asm/bpf-types.rs b/src/test/assembly/asm/bpf-types.rs
new file mode 100644
index 00000000000..cc3863d03cd
--- /dev/null
+++ b/src/test/assembly/asm/bpf-types.rs
@@ -0,0 +1,154 @@
+// min-llvm-version: 10.0.1
+// assembly-output: emit-asm
+// compile-flags: --target bpfel-unknown-none -C target_feature=+alu32
+// needs-llvm-components: bpf
+
+#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! stringify {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+type ptr = *const u64;
+
+impl Copy for i8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+impl Copy for i64 {}
+impl Copy for ptr {}
+
+macro_rules! check {
+    ($func:ident $ty:ident $class:ident) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!("{} = {}", out($class) y, in($class) x);
+            y
+        }
+    };
+}
+
+macro_rules! check_reg {
+    ($func:ident $ty:ident $reg:tt) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!(concat!($reg, " = ", $reg), lateout($reg) y, in($reg) x);
+            y
+        }
+    };
+}
+
+extern "C" {
+    fn extern_func();
+}
+
+// CHECK-LABEL: sym_fn
+// CHECK: #APP
+// CHECK: call extern_func
+// CHECK: #NO_APP
+#[no_mangle]
+pub unsafe fn sym_fn() {
+    asm!("call {}", sym extern_func);
+}
+
+// CHECK-LABEL: reg_i8:
+// CHECK: #APP
+// CHECK: r{{[0-9]+}} = r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i8 i8 reg);
+
+// CHECK-LABEL: reg_i16:
+// CHECK: #APP
+// CHECK: r{{[0-9]+}} = r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i16 i16 reg);
+
+// CHECK-LABEL: reg_i32:
+// CHECK: #APP
+// CHECK: r{{[0-9]+}} = r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i32 i32 reg);
+
+// CHECK-LABEL: reg_i64:
+// CHECK: #APP
+// CHECK: r{{[0-9]+}} = r{{[0-9]+}}
+// CHECK: #NO_APP
+check!(reg_i64 i64 reg);
+
+// CHECK-LABEL: wreg_i8:
+// CHECK: #APP
+// CHECK: w{{[0-9]+}} = w{{[0-9]+}}
+// CHECK: #NO_APP
+check!(wreg_i8 i8 wreg);
+
+// CHECK-LABEL: wreg_i16:
+// CHECK: #APP
+// CHECK: w{{[0-9]+}} = w{{[0-9]+}}
+// CHECK: #NO_APP
+check!(wreg_i16 i16 wreg);
+
+// CHECK-LABEL: wreg_i32:
+// CHECK: #APP
+// CHECK: w{{[0-9]+}} = w{{[0-9]+}}
+// CHECK: #NO_APP
+check!(wreg_i32 i32 wreg);
+
+// CHECK-LABEL: r0_i8:
+// CHECK: #APP
+// CHECK: r0 = r0
+// CHECK: #NO_APP
+check_reg!(r0_i8 i8 "r0");
+
+// CHECK-LABEL: r0_i16:
+// CHECK: #APP
+// CHECK: r0 = r0
+// CHECK: #NO_APP
+check_reg!(r0_i16 i16 "r0");
+
+// CHECK-LABEL: r0_i32:
+// CHECK: #APP
+// CHECK: r0 = r0
+// CHECK: #NO_APP
+check_reg!(r0_i32 i32 "r0");
+
+// CHECK-LABEL: r0_i64:
+// CHECK: #APP
+// CHECK: r0 = r0
+// CHECK: #NO_APP
+check_reg!(r0_i64 i64 "r0");
+
+// CHECK-LABEL: w0_i8:
+// CHECK: #APP
+// CHECK: w0 = w0
+// CHECK: #NO_APP
+check_reg!(w0_i8 i8 "w0");
+
+// CHECK-LABEL: w0_i16:
+// CHECK: #APP
+// CHECK: w0 = w0
+// CHECK: #NO_APP
+check_reg!(w0_i16 i16 "w0");
+
+// CHECK-LABEL: w0_i32:
+// CHECK: #APP
+// CHECK: w0 = w0
+// CHECK: #NO_APP
+check_reg!(w0_i32 i32 "w0");
diff --git a/src/test/codegen/async-fn-debug-msvc.rs b/src/test/codegen/async-fn-debug-msvc.rs
index f2641404aae..e410180bfff 100644
--- a/src/test/codegen/async-fn-debug-msvc.rs
+++ b/src/test/codegen/async-fn-debug-msvc.rs
@@ -17,33 +17,33 @@ async fn async_fn_test() {
 // FIXME: No way to reliably check the filename.
 
 // CHECK-DAG:  [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test"
-// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0", scope: [[ASYNC_FN]]
-// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
+// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0"
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]],
 // For brevity, we only check the struct name and members of the last variant.
 // CHECK-SAME: file: [[FILE:![0-9]*]], line: 11,
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
-// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant1", scope: [[GEN]],
 // CHECK-SAME: file: [[FILE]], line: 15,
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
-// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant2", scope: [[GEN]],
 // CHECK-SAME: file: [[FILE]], line: 15,
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
-// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant3", scope: [[GEN]],
 // CHECK-SAME: file: [[FILE]], line: 12,
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
-// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant4", scope: [[GEN]],
 // CHECK-SAME: file: [[FILE]], line: 14,
 // CHECK-SAME: baseType: [[VARIANT:![0-9]*]]
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
-// CHECK:      [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[ASYNC_FN]],
+// CHECK:      [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]],
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
-// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "RUST$ENUM$DISR", scope: [[S1]],
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant$", scope: [[S1]],
 // CHECK-SAME: flags: DIFlagArtificial
 // CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]]
 // CHECK-NOT:  flags: DIFlagArtificial
diff --git a/src/test/codegen/bpf-alu32.rs b/src/test/codegen/bpf-alu32.rs
new file mode 100644
index 00000000000..c68bffd03e2
--- /dev/null
+++ b/src/test/codegen/bpf-alu32.rs
@@ -0,0 +1,11 @@
+// only-bpf
+#![crate_type = "lib"]
+#![feature(bpf_target_feature)]
+#![no_std]
+
+#[no_mangle]
+#[target_feature(enable = "alu32")]
+// CHECK: define i8 @foo(i8 returned %arg) unnamed_addr #0 {
+pub unsafe fn foo(arg: u8) -> u8 {
+    arg
+}
diff --git a/src/test/codegen/generator-debug-msvc.rs b/src/test/codegen/generator-debug-msvc.rs
index 44be71f3b9b..7edb07d224c 100644
--- a/src/test/codegen/generator-debug-msvc.rs
+++ b/src/test/codegen/generator-debug-msvc.rs
@@ -21,33 +21,33 @@ fn generator_test() -> impl Generator<Yield = i32, Return = ()> {
 // FIXME: No way to reliably check the filename.
 
 // CHECK-DAG:  [[GEN_FN:!.*]] = !DINamespace(name: "generator_test"
-// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0", scope: [[GEN_FN]]
-// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
+// CHECK-DAG:  [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0"
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant0", scope: [[GEN]],
 // For brevity, we only check the struct name and members of the last variant.
 // CHECK-SAME: file: [[FILE:![0-9]*]], line: 14,
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
-// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant1", scope: [[GEN]],
 // CHECK-SAME: file: [[FILE]], line: 18,
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
-// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant2", scope: [[GEN]],
 // CHECK-SAME: file: [[FILE]], line: 18,
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
-// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant3", scope: [[GEN]],
 // CHECK-SAME: file: [[FILE]], line: 15,
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
-// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]],
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant4", scope: [[GEN]],
 // CHECK-SAME: file: [[FILE]], line: 17,
 // CHECK-SAME: baseType: [[VARIANT:![0-9]*]]
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
-// CHECK:      [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN_FN]],
+// CHECK:      [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]],
 // CHECK-NOT:  flags: DIFlagArtificial
 // CHECK-SAME: )
-// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "RUST$ENUM$DISR", scope: [[S1]],
+// CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "variant$", scope: [[S1]],
 // CHECK-SAME: flags: DIFlagArtificial
 // CHECK:      {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]]
 // CHECK-NOT:  flags: DIFlagArtificial
diff --git a/src/test/debuginfo/msvc-pretty-enums.rs b/src/test/debuginfo/msvc-pretty-enums.rs
new file mode 100644
index 00000000000..550cc66f389
--- /dev/null
+++ b/src/test/debuginfo/msvc-pretty-enums.rs
@@ -0,0 +1,97 @@
+// only-cdb
+// ignore-tidy-linelength
+// compile-flags:-g
+
+// cdb-command: g
+
+// Note: The natvis used to visualize niche-layout enums don't work correctly in cdb
+//       so the best we can do is to make sure we are generating the right debuginfo
+
+// cdb-command: dx -r2 a,!
+// cdb-check:a,!              [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>]
+// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Some]
+// cdb-check:        [+0x000] __0              : Low (0x2) [Type: msvc_pretty_enums::CStyleEnum]
+// cdb-check:    [+0x000] discriminant     : 0x2 [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Discriminant$]
+
+// cdb-command: dx -r2 b,!
+// cdb-check:b,!              [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>]
+// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Some]
+// cdb-check:        [+0x000] __0              : 0x11 [Type: msvc_pretty_enums::CStyleEnum]
+// cdb-check:    [+0x000] discriminant     : None (0x11) [Type: enum$<core::option::Option<enum$<msvc_pretty_enums::CStyleEnum>>, 2, 16, Some>::Discriminant$]
+
+// cdb-command: dx -r2 c,!
+// cdb-check:c,!              [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
+// cdb-check:    [+0x000] dataful_variant  [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Data]
+// cdb-check:        [+0x000] my_data          : 0x11 [Type: msvc_pretty_enums::CStyleEnum]
+// cdb-check:    [+0x000] discriminant     : Tag1 (0x11) [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$]
+
+// cdb-command: dx -r2 d,!
+// cdb-check:d,!              [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
+// cdb-check:    [+0x000] dataful_variant  [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Data]
+// cdb-check:        [+0x000] my_data          : High (0x10) [Type: msvc_pretty_enums::CStyleEnum]
+// cdb-check:    [+0x000] discriminant     : 0x10 [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$]
+
+// cdb-command: dx -r2 e,!
+// cdb-check:e,!              [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>]
+// cdb-check:    [+0x000] dataful_variant  [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Data]
+// cdb-check:        [+0x000] my_data          : 0x13 [Type: msvc_pretty_enums::CStyleEnum]
+// cdb-check:    [+0x000] discriminant     : Tag2 (0x13) [Type: enum$<msvc_pretty_enums::NicheLayoutEnum, 2, 16, Data>::Discriminant$]
+
+// cdb-command: dx -r2 f,!
+// cdb-check:f,!              [Type: enum$<core::option::Option<u32*>, 1, [...], Some>]
+// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Some]
+// cdb-check:        [+0x000] __0              : 0x[...] : 0x1 [Type: unsigned int *]
+// cdb-check:    [+0x000] discriminant     : 0x[...] [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Discriminant$]
+
+// cdb-command: dx -r2 g,!
+// cdb-check:g,!              [Type: enum$<core::option::Option<u32*>, 1, [...], Some>]
+// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Some]
+// cdb-check:        [+0x000] __0              : 0x0 [Type: unsigned int *]
+// cdb-check:    [+0x000] discriminant     : None (0x0) [Type: enum$<core::option::Option<u32*>, 1, [...], Some>::Discriminant$]
+
+// cdb-command: dx h
+// cdb-check:h                : Some [Type: enum$<core::option::Option<u32>>]
+// cdb-check:    [+0x000] variant$         : Some (0x1) [Type: core::option::Option]
+// cdb-check:    [+0x004] __0              : 0xc [Type: unsigned int]
+
+// cdb-command: dx i
+// cdb-check:i                : None [Type: enum$<core::option::Option<u32>>]
+// cdb-check:    [+0x000] variant$         : None (0x0) [Type: core::option::Option]
+
+// cdb-command: dx j
+// cdb-check:j                : High (0x10) [Type: msvc_pretty_enums::CStyleEnum]
+
+// cdb-command: dx -r2 k,!
+// cdb-check:k,!              [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
+// cdb-check:    [+0x000] dataful_variant  [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>::Some]
+// cdb-check:        [+0x000] __0              [Type: alloc::string::String]
+// cdb-check:    [+0x000] discriminant     : 0x[...] [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>::Discriminant$]
+
+pub enum CStyleEnum {
+    Low = 2,
+    High = 16,
+}
+
+pub enum NicheLayoutEnum {
+    Tag1,
+    Data { my_data: CStyleEnum },
+    Tag2,
+}
+
+fn main() {
+    let a = Some(CStyleEnum::Low);
+    let b = Option::<CStyleEnum>::None;
+    let c = NicheLayoutEnum::Tag1;
+    let d = NicheLayoutEnum::Data { my_data: CStyleEnum::High };
+    let e = NicheLayoutEnum::Tag2;
+    let f = Some(&1u32);
+    let g = Option::<&'static u32>::None;
+    let h = Some(12u32);
+    let i = Option::<u32>::None;
+    let j = CStyleEnum::High;
+    let k = Some("IAMA optional string!".to_string());
+
+    zzz(); // #break
+}
+
+fn zzz() { () }
diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs
index 1a99f841250..68e73b5f38d 100644
--- a/src/test/debuginfo/pretty-std.rs
+++ b/src/test/debuginfo/pretty-std.rs
@@ -1,6 +1,7 @@
 // ignore-freebsd: gdb package too new
 // only-cdb // "Temporarily" ignored on GDB/LLDB due to debuginfo tests being disabled, see PR 47155
 // ignore-android: FIXME(#10381)
+// ignore-tidy-linelength
 // compile-flags:-g
 // min-gdb-version: 7.7
 // min-lldb-version: 310
@@ -111,11 +112,11 @@
 // NOTE: OsString doesn't have a .natvis entry yet.
 
 // cdb-command: dx some
-// cdb-check:some             : Some(8) [Type: [...]::Option<i16>]
+// cdb-check:some             : Some [Type: enum$<core::option::Option<i16>>]
 // cdb-command: dx none
-// cdb-check:none             : None [Type: [...]::Option<i64>]
+// cdb-check:none             : None [Type: enum$<core::option::Option<i64>>]
 // cdb-command: dx some_string
-// cdb-check:some_string      : Some("IAMA optional string!") [[...]::Option<[...]::String>]
+// cdb-check:some_string      [Type: enum$<core::option::Option<alloc::string::String>, 1, [...], Some>]
 
 #![allow(unused_variables)]
 use std::ffi::OsString;
diff --git a/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs b/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs
index f698f8835a2..ea1ea1943e9 100644
--- a/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs
+++ b/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs
@@ -24,7 +24,7 @@ extern crate point;
 pub mod fn_calls_methods_in_same_impl {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         x.distance_from_origin();
@@ -35,7 +35,7 @@ pub mod fn_calls_methods_in_same_impl {
 pub mod fn_calls_free_fn {
     use point::{self, Point};
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         point::distance_squared(&x);
@@ -46,7 +46,7 @@ pub mod fn_calls_free_fn {
 pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
@@ -56,7 +56,7 @@ pub mod fn_make_struct {
 pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
@@ -66,7 +66,7 @@ pub mod fn_read_field {
 pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
diff --git a/src/test/incremental/callee_caller_cross_crate/b.rs b/src/test/incremental/callee_caller_cross_crate/b.rs
index 02453740079..084ed232a55 100644
--- a/src/test/incremental/callee_caller_cross_crate/b.rs
+++ b/src/test/incremental/callee_caller_cross_crate/b.rs
@@ -6,12 +6,12 @@
 
 extern crate a;
 
-#[rustc_dirty(label="typeck", cfg="rpass2")]
+#[rustc_clean(except="typeck", cfg="rpass2")]
 pub fn call_function0() {
     a::function0(77);
 }
 
-#[rustc_clean(label="typeck", cfg="rpass2")]
+#[rustc_clean(cfg="rpass2")]
 pub fn call_function1() {
     a::function1(77);
 }
diff --git a/src/test/incremental/change_add_field/struct_point.rs b/src/test/incremental/change_add_field/struct_point.rs
index 8d98cfac8a4..3308ea56222 100644
--- a/src/test/incremental/change_add_field/struct_point.rs
+++ b/src/test/incremental/change_add_field/struct_point.rs
@@ -70,7 +70,7 @@ pub mod point {
 pub mod fn_with_type_in_sig {
     use point::Point;
 
-    #[rustc_dirty(label="typeck", cfg="cfail2")]
+    #[rustc_clean(except="typeck,fn_sig,optimized_mir", cfg="cfail2")]
     pub fn boop(p: Option<&Point>) -> f32 {
         p.map(|p| p.total()).unwrap_or(0.0)
     }
@@ -86,7 +86,7 @@ pub mod fn_with_type_in_sig {
 pub mod call_fn_with_type_in_sig {
     use fn_with_type_in_sig;
 
-    #[rustc_dirty(label="typeck", cfg="cfail2")]
+    #[rustc_clean(except="typeck,optimized_mir", cfg="cfail2")]
     pub fn bip() -> f32 {
         fn_with_type_in_sig::boop(None)
     }
@@ -102,7 +102,7 @@ pub mod call_fn_with_type_in_sig {
 pub mod fn_with_type_in_body {
     use point::Point;
 
-    #[rustc_dirty(label="typeck", cfg="cfail2")]
+    #[rustc_clean(except="typeck,optimized_mir", cfg="cfail2")]
     pub fn boop() -> f32 {
         Point::origin().total()
     }
@@ -115,7 +115,7 @@ pub mod fn_with_type_in_body {
 pub mod call_fn_with_type_in_body {
     use fn_with_type_in_body;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn bip() -> f32 {
         fn_with_type_in_body::boop()
     }
@@ -125,7 +125,7 @@ pub mod call_fn_with_type_in_body {
 pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_dirty(label="typeck", cfg="cfail2")]
+    #[rustc_clean(except="typeck,fn_sig,optimized_mir", cfg="cfail2")]
     pub fn make_origin(p: Point) -> Point {
         Point { ..p }
     }
@@ -135,7 +135,7 @@ pub mod fn_make_struct {
 pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_dirty(label="typeck", cfg="cfail2")]
+    #[rustc_clean(except="typeck,fn_sig,optimized_mir", cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
@@ -145,7 +145,7 @@ pub mod fn_read_field {
 pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_dirty(label="typeck", cfg="cfail2")]
+    #[rustc_clean(except="typeck,fn_sig,optimized_mir", cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
diff --git a/src/test/incremental/change_private_fn/struct_point.rs b/src/test/incremental/change_private_fn/struct_point.rs
index ba4bf4e7b7d..1791c089cfa 100644
--- a/src/test/incremental/change_private_fn/struct_point.rs
+++ b/src/test/incremental/change_private_fn/struct_point.rs
@@ -51,7 +51,7 @@ pub mod point {
 pub mod fn_calls_methods_in_same_impl {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         x.distance_from_origin();
@@ -62,7 +62,7 @@ pub mod fn_calls_methods_in_same_impl {
 pub mod fn_calls_methods_in_another_impl {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn check() {
         let mut x = Point { x: 2.0, y: 2.0 };
         x.translate(3.0, 3.0);
@@ -73,7 +73,7 @@ pub mod fn_calls_methods_in_another_impl {
 pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
@@ -83,7 +83,7 @@ pub mod fn_make_struct {
 pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
@@ -93,7 +93,7 @@ pub mod fn_read_field {
 pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
diff --git a/src/test/incremental/change_private_fn_cc/struct_point.rs b/src/test/incremental/change_private_fn_cc/struct_point.rs
index 5072ef609e2..1c27ec3a3f7 100644
--- a/src/test/incremental/change_private_fn_cc/struct_point.rs
+++ b/src/test/incremental/change_private_fn_cc/struct_point.rs
@@ -23,7 +23,7 @@ extern crate point;
 pub mod fn_calls_methods_in_same_impl {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         x.distance_from_origin();
@@ -34,7 +34,7 @@ pub mod fn_calls_methods_in_same_impl {
 pub mod fn_calls_methods_in_another_impl {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn check() {
         let mut x = Point { x: 2.0, y: 2.0 };
         x.translate(3.0, 3.0);
@@ -45,7 +45,7 @@ pub mod fn_calls_methods_in_another_impl {
 pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
@@ -55,7 +55,7 @@ pub mod fn_make_struct {
 pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
@@ -65,7 +65,7 @@ pub mod fn_read_field {
 pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
diff --git a/src/test/incremental/change_private_impl_method/struct_point.rs b/src/test/incremental/change_private_impl_method/struct_point.rs
index 11ba96a8c8d..cf43e4757cb 100644
--- a/src/test/incremental/change_private_impl_method/struct_point.rs
+++ b/src/test/incremental/change_private_impl_method/struct_point.rs
@@ -51,7 +51,7 @@ pub mod point {
 pub mod fn_calls_methods_in_same_impl {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         x.distance_from_origin();
@@ -62,7 +62,7 @@ pub mod fn_calls_methods_in_same_impl {
 pub mod fn_calls_methods_in_another_impl {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn check() {
         let mut x = Point { x: 2.0, y: 2.0 };
         x.translate(3.0, 3.0);
@@ -73,7 +73,7 @@ pub mod fn_calls_methods_in_another_impl {
 pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
@@ -83,7 +83,7 @@ pub mod fn_make_struct {
 pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
@@ -93,7 +93,7 @@ pub mod fn_read_field {
 pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
diff --git a/src/test/incremental/change_private_impl_method_cc/struct_point.rs b/src/test/incremental/change_private_impl_method_cc/struct_point.rs
index 2aeecfc89d5..9fe8b5df93a 100644
--- a/src/test/incremental/change_private_impl_method_cc/struct_point.rs
+++ b/src/test/incremental/change_private_impl_method_cc/struct_point.rs
@@ -24,7 +24,7 @@ extern crate point;
 pub mod fn_calls_methods_in_same_impl {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn check() {
         let x = Point { x: 2.0, y: 2.0 };
         x.distance_from_origin();
@@ -35,7 +35,7 @@ pub mod fn_calls_methods_in_same_impl {
 pub mod fn_calls_methods_in_another_impl {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn dirty() {
         let mut x = Point { x: 2.0, y: 2.0 };
         x.translate(3.0, 3.0);
@@ -46,7 +46,7 @@ pub mod fn_calls_methods_in_another_impl {
 pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
@@ -56,7 +56,7 @@ pub mod fn_make_struct {
 pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
@@ -66,7 +66,7 @@ pub mod fn_read_field {
 pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
diff --git a/src/test/incremental/change_pub_inherent_method_body/struct_point.rs b/src/test/incremental/change_pub_inherent_method_body/struct_point.rs
index a192dff19e9..1b87b18fcd4 100644
--- a/src/test/incremental/change_pub_inherent_method_body/struct_point.rs
+++ b/src/test/incremental/change_pub_inherent_method_body/struct_point.rs
@@ -42,7 +42,7 @@ pub mod point {
 pub mod fn_calls_changed_method {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn check() {
         let p = Point { x: 2.0, y: 2.0 };
         p.distance_from_origin();
@@ -53,7 +53,7 @@ pub mod fn_calls_changed_method {
 pub mod fn_calls_another_method {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn check() {
         let p = Point { x: 2.0, y: 2.0 };
         p.x();
@@ -64,7 +64,7 @@ pub mod fn_calls_another_method {
 pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
@@ -74,7 +74,7 @@ pub mod fn_make_struct {
 pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
@@ -84,7 +84,7 @@ pub mod fn_read_field {
 pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
diff --git a/src/test/incremental/change_pub_inherent_method_sig/struct_point.rs b/src/test/incremental/change_pub_inherent_method_sig/struct_point.rs
index b0476168555..0a672956768 100644
--- a/src/test/incremental/change_pub_inherent_method_sig/struct_point.rs
+++ b/src/test/incremental/change_pub_inherent_method_sig/struct_point.rs
@@ -52,7 +52,7 @@ pub mod point {
 pub mod fn_calls_changed_method {
     use point::Point;
 
-    #[rustc_dirty(label="typeck", cfg="cfail2")]
+    #[rustc_clean(except="typeck,optimized_mir", cfg="cfail2")]
     pub fn check() {
         let p = Point { x: 2.0, y: 2.0 };
         p.distance_from_point(None);
@@ -63,7 +63,7 @@ pub mod fn_calls_changed_method {
 pub mod fn_calls_another_method {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn check() {
         let p = Point { x: 2.0, y: 2.0 };
         p.x();
@@ -74,7 +74,7 @@ pub mod fn_calls_another_method {
 pub mod fn_make_struct {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn make_origin() -> Point {
         Point { x: 2.0, y: 2.0 }
     }
@@ -84,7 +84,7 @@ pub mod fn_make_struct {
 pub mod fn_read_field {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn get_x(p: Point) -> f32 {
         p.x
     }
@@ -94,7 +94,7 @@ pub mod fn_read_field {
 pub mod fn_write_field {
     use point::Point;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn inc_x(p: &mut Point) {
         p.x += 1.0;
     }
diff --git a/src/test/incremental/crate_hash_reorder.rs b/src/test/incremental/crate_hash_reorder.rs
index 6e06e67b668..ca476b4d2db 100644
--- a/src/test/incremental/crate_hash_reorder.rs
+++ b/src/test/incremental/crate_hash_reorder.rs
@@ -7,9 +7,9 @@
 
 // Check that reordering otherwise identical items is not considered a
 // change at all.
-#[rustc_clean(label = "hir_crate", cfg = "rpass2")]
+#[rustc_clean(cfg = "rpass2")]
 // But removing an item, naturally, is.
-#[rustc_dirty(label = "hir_crate", cfg = "rpass3")]
+#[rustc_clean(except="hir_crate", cfg = "rpass3")]
 #[cfg(rpass1)]
 pub struct X {
     pub x: u32,
diff --git a/src/test/incremental/dirty_clean.rs b/src/test/incremental/dirty_clean.rs
index 02c9a0c5798..11d999ab328 100644
--- a/src/test/incremental/dirty_clean.rs
+++ b/src/test/incremental/dirty_clean.rs
@@ -25,15 +25,24 @@ mod x {
 mod y {
     use x;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
+    #[rustc_clean(
+        except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig",
+        cfg="cfail2",
+    )]
     pub fn y() {
-        //[cfail2]~^ ERROR `typeck(y)` should be clean but is not
+        //[cfail2]~^ ERROR `hir_owner(y)` should be dirty but is not
+        //[cfail2]~| ERROR `hir_owner_nodes(y)` should be dirty but is not
+        //[cfail2]~| ERROR `generics_of(y)` should be dirty but is not
+        //[cfail2]~| ERROR `predicates_of(y)` should be dirty but is not
+        //[cfail2]~| ERROR `type_of(y)` should be dirty but is not
+        //[cfail2]~| ERROR `fn_sig(y)` should be dirty but is not
+        //[cfail2]~| ERROR `typeck(y)` should be clean but is not
         x::x();
     }
 }
 
 mod z {
-    #[rustc_dirty(label="typeck", cfg="cfail2")]
+    #[rustc_clean(except="typeck", cfg="cfail2")]
     pub fn z() {
         //[cfail2]~^ ERROR `typeck(z)` should be dirty but is not
     }
diff --git a/src/test/incremental/hashes/call_expressions.rs b/src/test/incremental/hashes/call_expressions.rs
index d4511cee75b..d4201400f0f 100644
--- a/src/test/incremental/hashes/call_expressions.rs
+++ b/src/test/incremental/hashes/call_expressions.rs
@@ -55,12 +55,8 @@ mod change_callee_indirectly_function {
     #[cfg(not(cfail1))]
     use super::callee2 as callee;
 
-    #[rustc_clean(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
-    #[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-
-
+    #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     pub fn change_callee_indirectly_function() {
         callee(1, 2)
     }
diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs
index c73c03ca14e..76bff3cad38 100644
--- a/src/test/incremental/hashes/enum_defs.rs
+++ b/src/test/incremental/hashes/enum_defs.rs
@@ -370,7 +370,7 @@ enum EnumChangeNameOfTypeParameter<S> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeNameOfTypeParameter<T> {
     Variant1(T),
@@ -386,7 +386,7 @@ enum EnumAddTypeParameter<S> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddTypeParameter<S, T> {
     Variant1(S),
@@ -402,7 +402,7 @@ enum EnumChangeNameOfLifetimeParameter<'a> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2", except="predicates_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumChangeNameOfLifetimeParameter<'b> {
     Variant1(&'b u32),
@@ -418,7 +418,7 @@ enum EnumAddLifetimeParameter<'a> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2", except="predicates_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddLifetimeParameter<'a, 'b> {
     Variant1(&'a u32),
@@ -435,7 +435,7 @@ enum EnumAddLifetimeParameterBound<'a, 'b> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2", except="generics_of,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddLifetimeParameterBound<'a, 'b: 'a> {
     Variant1(&'a u32),
@@ -450,7 +450,7 @@ enum EnumAddLifetimeBoundToParameter<'a, T> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2", except="type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddLifetimeBoundToParameter<'a, T: 'a> {
     Variant1(T),
@@ -466,7 +466,7 @@ enum EnumAddTraitBound<S> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddTraitBound<T: Sync> {
     Variant1(T),
@@ -482,7 +482,7 @@ enum EnumAddLifetimeParameterBoundWhere<'a, 'b> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2", except="generics_of,type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddLifetimeParameterBoundWhere<'a, 'b> where 'b: 'a {
     Variant1(&'a u32),
@@ -499,7 +499,7 @@ enum EnumAddLifetimeBoundToParameterWhere<'a, T> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2", except="type_of")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddLifetimeBoundToParameterWhere<'a, T> where T: 'a {
     Variant1(T),
@@ -515,7 +515,7 @@ enum EnumAddTraitBoundWhere<S> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg="cfail2")]
+#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
 #[rustc_clean(cfg="cfail3")]
 enum EnumAddTraitBoundWhere<T> where T: Sync {
     Variant1(T),
diff --git a/src/test/incremental/hashes/extern_mods.rs b/src/test/incremental/hashes/extern_mods.rs
index 93e70d3792c..1160bc376c4 100644
--- a/src/test/incremental/hashes/extern_mods.rs
+++ b/src/test/incremental/hashes/extern_mods.rs
@@ -21,7 +21,7 @@ extern "C" {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg = "cfail2", except = "hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner")]
 #[rustc_clean(cfg = "cfail3")]
 extern "C" {
     pub fn change_function_name2(c: i64) -> i32;
@@ -34,7 +34,7 @@ extern "C" {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
 extern "C" {
     pub fn change_parameter_name(d: i64) -> i32;
@@ -47,7 +47,7 @@ extern "C" {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
 extern "C" {
     pub fn change_parameter_type(c: i32) -> i32;
@@ -60,7 +60,7 @@ extern "C" {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
 extern "C" {
     pub fn change_return_type(c: i32) -> i8;
@@ -73,7 +73,7 @@ extern "C" {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
 extern "C" {
     pub fn add_parameter(c: i32, d: i32) -> i32;
@@ -86,7 +86,7 @@ extern "C" {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
 extern "C" {
     pub fn add_return_type(c: i32) -> i32;
@@ -99,7 +99,7 @@ extern "C" {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
 extern "C" {
     pub fn make_function_variadic(c: i32, ...);
@@ -112,7 +112,7 @@ extern "C" {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg = "cfail2", except = "hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner")]
 #[rustc_clean(cfg = "cfail3")]
 extern "rust-call" {
     pub fn change_calling_convention(c: i32);
@@ -125,7 +125,7 @@ extern "C" {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg = "cfail2", except = "hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner")]
 #[rustc_clean(cfg = "cfail3")]
 extern "C" {
     pub fn make_function_public(c: i32);
@@ -138,7 +138,7 @@ extern "C" {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg = "cfail2", except = "hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail2", except = "hir_owner")]
 #[rustc_clean(cfg = "cfail3")]
 extern "C" {
     pub fn add_function1(c: i32);
@@ -153,7 +153,7 @@ extern "C" {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
 #[link(name = "bar")]
 extern "C" {
@@ -170,7 +170,7 @@ mod indirectly_change_parameter_type {
     #[cfg(not(cfail1))]
     use super::c_i64 as c_int;
 
-    #[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+    #[rustc_clean(cfg = "cfail2")]
     #[rustc_clean(cfg = "cfail3")]
     extern "C" {
         pub fn indirectly_change_parameter_type(c: c_int);
@@ -184,7 +184,7 @@ mod indirectly_change_return_type {
     #[cfg(not(cfail1))]
     use super::c_i64 as c_int;
 
-    #[rustc_dirty(cfg = "cfail2", except = "hir_owner,hir_owner_nodes")]
+    #[rustc_clean(cfg = "cfail2")]
     #[rustc_clean(cfg = "cfail3")]
     extern "C" {
         pub fn indirectly_change_return_type() -> c_int;
diff --git a/src/test/incremental/hashes/indexing_expressions.rs b/src/test/incremental/hashes/indexing_expressions.rs
index 7a8cbc3566e..49ee7a9cac0 100644
--- a/src/test/incremental/hashes/indexing_expressions.rs
+++ b/src/test/incremental/hashes/indexing_expressions.rs
@@ -20,10 +20,8 @@ fn change_simple_index(slice: &[u32]) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 fn change_simple_index(slice: &[u32]) -> u32 {
     slice[4]
 }
@@ -37,10 +35,8 @@ fn change_lower_bound(slice: &[u32]) -> &[u32] {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 fn change_lower_bound(slice: &[u32]) -> &[u32] {
     &slice[2..5]
 }
@@ -54,10 +50,8 @@ fn change_upper_bound(slice: &[u32]) -> &[u32] {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 fn change_upper_bound(slice: &[u32]) -> &[u32] {
     &slice[3..7]
 }
@@ -71,10 +65,8 @@ fn add_lower_bound(slice: &[u32]) -> &[u32] {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 fn add_lower_bound(slice: &[u32]) -> &[u32] {
     &slice[3..4]
 }
@@ -88,10 +80,8 @@ fn add_upper_bound(slice: &[u32]) -> &[u32] {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 fn add_upper_bound(slice: &[u32]) -> &[u32] {
     &slice[3..7]
 }
@@ -105,10 +95,8 @@ fn change_mutability(slice: &mut [u32]) -> u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 fn change_mutability(slice: &mut [u32]) -> u32 {
     (&slice[3..5])[0]
 }
@@ -122,10 +110,8 @@ fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
     &slice[3..=7]
 }
diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs
index 70ce81bd473..284a95f1a68 100644
--- a/src/test/incremental/hashes/inherent_impls.rs
+++ b/src/test/incremental/hashes/inherent_impls.rs
@@ -103,7 +103,10 @@ impl Foo {
 #[rustc_clean(cfg="cfail2", except="hir_owner")]
 #[rustc_clean(cfg="cfail3")]
 impl Foo {
-    #[rustc_dirty(cfg="cfail2", except="type_of,predicates_of,promoted_mir")]
+    #[rustc_clean(
+        cfg="cfail2",
+        except="hir_owner,hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir",
+    )]
     #[rustc_clean(cfg="cfail3")]
     pub fn method_selfness(&self) { }
 }
diff --git a/src/test/incremental/hashes/struct_defs.rs b/src/test/incremental/hashes/struct_defs.rs
index 1339a1e5bf2..0ce5aeaaf50 100644
--- a/src/test/incremental/hashes/struct_defs.rs
+++ b/src/test/incremental/hashes/struct_defs.rs
@@ -24,16 +24,8 @@
 pub struct LayoutPacked;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_dirty(label="type_of", cfg="cfail2")]
-#[rustc_clean(label="generics_of", cfg="cfail2")]
-#[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-#[rustc_clean(label="type_of", cfg="cfail3")]
-#[rustc_clean(label="generics_of", cfg="cfail3")]
-#[rustc_clean(label="predicates_of", cfg="cfail3")]
+#[rustc_clean(except="type_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 #[repr(packed)]
 pub struct LayoutPacked;
 
@@ -41,16 +33,8 @@ pub struct LayoutPacked;
 struct LayoutC;
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_dirty(label="type_of", cfg="cfail2")]
-#[rustc_clean(label="generics_of", cfg="cfail2")]
-#[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-#[rustc_clean(label="type_of", cfg="cfail3")]
-#[rustc_clean(label="generics_of", cfg="cfail3")]
-#[rustc_clean(label="predicates_of", cfg="cfail3")]
+#[rustc_clean(except="type_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 #[repr(C)]
 struct LayoutC;
 
@@ -61,16 +45,8 @@ struct LayoutC;
 struct TupleStructFieldType(i32);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_clean(label="type_of", cfg="cfail2")]
-#[rustc_clean(label="generics_of", cfg="cfail2")]
-#[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-#[rustc_clean(label="type_of", cfg="cfail3")]
-#[rustc_clean(label="generics_of", cfg="cfail3")]
-#[rustc_clean(label="predicates_of", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 // Note that changing the type of a field does not change the type of the struct or enum, but
 // adding/removing fields or changing a fields name or visibility does.
 struct TupleStructFieldType(
@@ -84,16 +60,8 @@ struct TupleStructFieldType(
 struct TupleStructAddField(i32);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_dirty(label="type_of", cfg="cfail2")]
-#[rustc_clean(label="generics_of", cfg="cfail2")]
-#[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-#[rustc_clean(label="type_of", cfg="cfail3")]
-#[rustc_clean(label="generics_of", cfg="cfail3")]
-#[rustc_clean(label="predicates_of", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 struct TupleStructAddField(
     i32,
     u32
@@ -106,16 +74,8 @@ struct TupleStructAddField(
 struct TupleStructFieldVisibility(char);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_dirty(label="type_of", cfg="cfail2")]
-#[rustc_clean(label="generics_of", cfg="cfail2")]
-#[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-#[rustc_clean(label="type_of", cfg="cfail3")]
-#[rustc_clean(label="generics_of", cfg="cfail3")]
-#[rustc_clean(label="predicates_of", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 struct TupleStructFieldVisibility(pub char);
 
 
@@ -125,16 +85,8 @@ struct TupleStructFieldVisibility(pub char);
 struct RecordStructFieldType { x: f32 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_clean(label="type_of", cfg="cfail2")]
-#[rustc_clean(label="generics_of", cfg="cfail2")]
-#[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-#[rustc_clean(label="type_of", cfg="cfail3")]
-#[rustc_clean(label="generics_of", cfg="cfail3")]
-#[rustc_clean(label="predicates_of", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 // Note that changing the type of a field does not change the type of the struct or enum, but
 // adding/removing fields or changing a fields name or visibility does.
 struct RecordStructFieldType {
@@ -148,16 +100,8 @@ struct RecordStructFieldType {
 struct RecordStructFieldName { x: f32 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_dirty(label="type_of", cfg="cfail2")]
-#[rustc_clean(label="generics_of", cfg="cfail2")]
-#[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-#[rustc_clean(label="type_of", cfg="cfail3")]
-#[rustc_clean(label="generics_of", cfg="cfail3")]
-#[rustc_clean(label="predicates_of", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 struct RecordStructFieldName { y: f32 }
 
 
@@ -167,16 +111,8 @@ struct RecordStructFieldName { y: f32 }
 struct RecordStructAddField { x: f32 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_dirty(label="type_of", cfg="cfail2")]
-#[rustc_clean(label="generics_of", cfg="cfail2")]
-#[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-#[rustc_clean(label="type_of", cfg="cfail3")]
-#[rustc_clean(label="generics_of", cfg="cfail3")]
-#[rustc_clean(label="predicates_of", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 struct RecordStructAddField {
     x: f32,
     y: () }
@@ -188,16 +124,8 @@ struct RecordStructAddField {
 struct RecordStructFieldVisibility { x: f32 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_dirty(label="type_of", cfg="cfail2")]
-#[rustc_clean(label="generics_of", cfg="cfail2")]
-#[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-#[rustc_clean(label="type_of", cfg="cfail3")]
-#[rustc_clean(label="generics_of", cfg="cfail3")]
-#[rustc_clean(label="predicates_of", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 struct RecordStructFieldVisibility {
     pub x: f32
 }
@@ -209,16 +137,8 @@ struct RecordStructFieldVisibility {
 struct AddLifetimeParameter<'a>(&'a f32, &'a f64);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_dirty(label="type_of", cfg="cfail2")]
-#[rustc_dirty(label="generics_of", cfg="cfail2")]
-#[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-#[rustc_clean(label="type_of", cfg="cfail3")]
-#[rustc_clean(label="generics_of", cfg="cfail3")]
-#[rustc_clean(label="predicates_of", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 struct AddLifetimeParameter<'a, 'b>(&'a f32, &'b f64);
 
 
@@ -228,16 +148,8 @@ struct AddLifetimeParameter<'a, 'b>(&'a f32, &'b f64);
 struct AddLifetimeParameterBound<'a, 'b>(&'a f32, &'b f64);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_clean(label="type_of", cfg="cfail2")]
-#[rustc_clean(label="generics_of", cfg="cfail2")]
-#[rustc_dirty(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-#[rustc_clean(label="type_of", cfg="cfail3")]
-#[rustc_clean(label="generics_of", cfg="cfail3")]
-#[rustc_clean(label="predicates_of", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 struct AddLifetimeParameterBound<'a, 'b: 'a>(
     &'a f32,
     &'b f64
@@ -247,16 +159,8 @@ struct AddLifetimeParameterBound<'a, 'b: 'a>(
 struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_clean(label="type_of", cfg="cfail2")]
-#[rustc_clean(label="generics_of", cfg="cfail2")]
-#[rustc_dirty(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-#[rustc_clean(label="type_of", cfg="cfail3")]
-#[rustc_clean(label="generics_of", cfg="cfail3")]
-#[rustc_clean(label="predicates_of", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 struct AddLifetimeParameterBoundWhereClause<'a, 'b>(
     &'a f32,
     &'b f64)
@@ -269,16 +173,8 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>(
 struct AddTypeParameter<T1>(T1, T1);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_dirty(label="type_of", cfg="cfail2")]
-#[rustc_dirty(label="generics_of", cfg="cfail2")]
-#[rustc_dirty(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-#[rustc_clean(label="type_of", cfg="cfail3")]
-#[rustc_clean(label="generics_of", cfg="cfail3")]
-#[rustc_clean(label="predicates_of", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 struct AddTypeParameter<T1, T2>(
      // The field contains the parent's Generics, so it's dirty even though its
      // type hasn't changed.
@@ -293,16 +189,8 @@ struct AddTypeParameter<T1, T2>(
 struct AddTypeParameterBound<T>(T);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_clean(label="type_of", cfg="cfail2")]
-#[rustc_clean(label="generics_of", cfg="cfail2")]
-#[rustc_dirty(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-#[rustc_clean(label="type_of", cfg="cfail3")]
-#[rustc_clean(label="generics_of", cfg="cfail3")]
-#[rustc_clean(label="predicates_of", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 struct AddTypeParameterBound<T: Send>(
     T
 );
@@ -312,16 +200,8 @@ struct AddTypeParameterBound<T: Send>(
 struct AddTypeParameterBoundWhereClause<T>(T);
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_clean(label="type_of", cfg="cfail2")]
-#[rustc_clean(label="generics_of", cfg="cfail2")]
-#[rustc_dirty(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-#[rustc_clean(label="type_of", cfg="cfail3")]
-#[rustc_clean(label="generics_of", cfg="cfail3")]
-#[rustc_clean(label="predicates_of", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 struct AddTypeParameterBoundWhereClause<T>(
     T
 ) where T: Sync;
@@ -332,16 +212,8 @@ struct AddTypeParameterBoundWhereClause<T>(
 // fingerprint is stable (i.e., that there are no random influences like memory
 // addresses taken into account by the hashing algorithm).
 // Note: there is no #[cfg(...)], so this is ALWAYS compiled
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_clean(label="type_of", cfg="cfail2")]
-#[rustc_clean(label="generics_of", cfg="cfail2")]
-#[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-#[rustc_clean(label="type_of", cfg="cfail3")]
-#[rustc_clean(label="generics_of", cfg="cfail3")]
-#[rustc_clean(label="predicates_of", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 pub struct EmptyStruct;
 
 
@@ -351,16 +223,8 @@ pub struct EmptyStruct;
 struct Visibility;
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-#[rustc_clean(label="type_of", cfg="cfail2")]
-#[rustc_clean(label="generics_of", cfg="cfail2")]
-#[rustc_clean(label="predicates_of", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
-#[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-#[rustc_clean(label="type_of", cfg="cfail3")]
-#[rustc_clean(label="generics_of", cfg="cfail3")]
-#[rustc_clean(label="predicates_of", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 pub struct Visibility;
 
 struct ReferencedType1;
@@ -373,16 +237,8 @@ mod tuple_struct_change_field_type_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as FieldType;
 
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-    #[rustc_clean(label="type_of", cfg="cfail2")]
-    #[rustc_clean(label="generics_of", cfg="cfail2")]
-    #[rustc_clean(label="predicates_of", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
-    #[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-    #[rustc_clean(label="type_of", cfg="cfail3")]
-    #[rustc_clean(label="generics_of", cfg="cfail3")]
-    #[rustc_clean(label="predicates_of", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     struct TupleStruct(
         FieldType
     );
@@ -396,16 +252,8 @@ mod record_struct_change_field_type_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedType2 as FieldType;
 
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-    #[rustc_clean(label="type_of", cfg="cfail2")]
-    #[rustc_clean(label="generics_of", cfg="cfail2")]
-    #[rustc_clean(label="predicates_of", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
-    #[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-    #[rustc_clean(label="type_of", cfg="cfail3")]
-    #[rustc_clean(label="generics_of", cfg="cfail3")]
-    #[rustc_clean(label="predicates_of", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     struct RecordStruct {
         _x: FieldType
     }
@@ -424,16 +272,8 @@ mod change_trait_bound_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-    #[rustc_clean(label="type_of", cfg="cfail2")]
-    #[rustc_clean(label="generics_of", cfg="cfail2")]
-    #[rustc_dirty(label="predicates_of", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
-    #[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-    #[rustc_clean(label="type_of", cfg="cfail3")]
-    #[rustc_clean(label="generics_of", cfg="cfail3")]
-    #[rustc_clean(label="predicates_of", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     struct Struct<T: Trait>(T);
 }
 
@@ -444,15 +284,7 @@ mod change_trait_bound_indirectly_in_where_clause {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait2 as Trait;
 
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-    #[rustc_clean(label="type_of", cfg="cfail2")]
-    #[rustc_clean(label="generics_of", cfg="cfail2")]
-    #[rustc_dirty(label="predicates_of", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
-    #[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
-    #[rustc_clean(label="type_of", cfg="cfail3")]
-    #[rustc_clean(label="generics_of", cfg="cfail3")]
-    #[rustc_clean(label="predicates_of", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     struct Struct<T>(T) where T : Trait;
 }
diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs
index 4dab032e47f..a604ca5ca82 100644
--- a/src/test/incremental/hashes/trait_defs.rs
+++ b/src/test/incremental/hashes/trait_defs.rs
@@ -25,8 +25,8 @@
 trait TraitVisibility { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 pub trait TraitVisibility { }
 
 
@@ -36,8 +36,8 @@ pub trait TraitVisibility { }
 trait TraitUnsafety { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 unsafe trait TraitUnsafety { }
 
 
@@ -48,8 +48,8 @@ trait TraitAddMethod {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 pub trait TraitAddMethod {
     fn method();
 }
@@ -63,8 +63,8 @@ trait TraitChangeMethodName {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitChangeMethodName {
     fn methodChanged();
 }
@@ -78,11 +78,11 @@ trait TraitAddReturnType {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddReturnType {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method() -> u32;
 }
 
@@ -95,11 +95,11 @@ trait TraitChangeReturnType {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitChangeReturnType {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method() -> u64;
 }
 
@@ -112,11 +112,11 @@ trait TraitAddParameterToMethod {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddParameterToMethod {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method(a: u32);
 }
 
@@ -130,18 +130,16 @@ trait TraitChangeMethodParameterName {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitChangeMethodParameterName {
     // FIXME(#38501) This should preferably always be clean.
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method(b: u32);
 
-    #[rustc_clean(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
-    #[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn with_default(y: i32) {}
 }
 
@@ -154,11 +152,11 @@ trait TraitChangeMethodParameterType {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitChangeMethodParameterType {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method(a: i64);
 }
 
@@ -171,11 +169,11 @@ trait TraitChangeMethodParameterTypeRef {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitChangeMethodParameterTypeRef {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method(a: &mut i32);
 }
 
@@ -188,11 +186,11 @@ trait TraitChangeMethodParametersOrder {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitChangeMethodParametersOrder {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method(b: i64, a: i32);
 }
 
@@ -205,11 +203,11 @@ trait TraitAddMethodAutoImplementation {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddMethodAutoImplementation {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,associated_item", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method() { }
 }
 
@@ -223,8 +221,8 @@ trait TraitChangeOrderOfMethods {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitChangeOrderOfMethods {
     fn method1();
     fn method0();
@@ -239,11 +237,11 @@ trait TraitChangeModeSelfRefToMut {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitChangeModeSelfRefToMut {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method(&mut self);
 }
 
@@ -255,13 +253,11 @@ trait TraitChangeModeSelfOwnToMut: Sized {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitChangeModeSelfOwnToMut: Sized {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
-    #[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method(mut self) {}
 }
 
@@ -273,11 +269,11 @@ trait TraitChangeModeSelfOwnToRef {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitChangeModeSelfOwnToRef {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig,generics_of", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method(&self);
 }
 
@@ -290,11 +286,11 @@ trait TraitAddUnsafeModifier {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddUnsafeModifier {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     unsafe fn method();
 }
 
@@ -307,11 +303,11 @@ trait TraitAddExternModifier {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddExternModifier {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     extern "C" fn method();
 }
 
@@ -324,11 +320,11 @@ trait TraitChangeExternCToRustIntrinsic {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitChangeExternCToRustIntrinsic {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     extern "stdcall" fn method();
 }
 
@@ -341,11 +337,11 @@ trait TraitAddTypeParameterToMethod {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddTypeParameterToMethod {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,generics_of,predicates_of,type_of", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method<T>();
 }
 
@@ -358,11 +354,11 @@ trait TraitAddLifetimeParameterToMethod {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddLifetimeParameterToMethod {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig,generics_of", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method<'a>();
 }
 
@@ -379,11 +375,11 @@ trait TraitAddTraitBoundToMethodTypeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddTraitBoundToMethodTypeParameter {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method<T: ReferencedTrait0>();
 }
 
@@ -396,11 +392,11 @@ trait TraitAddBuiltinBoundToMethodTypeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddBuiltinBoundToMethodTypeParameter {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method<T: Sized>();
 }
 
@@ -413,11 +409,14 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddLifetimeBoundToMethodLifetimeParameter {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(
+        except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of",
+        cfg="cfail2",
+    )]
+    #[rustc_clean(cfg="cfail3")]
     fn method<'a, 'b: 'a>(a: &'a u32, b: &'b u32);
 }
 
@@ -430,11 +429,11 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddSecondTraitBoundToMethodTypeParameter {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method<T: ReferencedTrait0 + ReferencedTrait1>();
 }
 
@@ -447,11 +446,11 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method<T: Sized + Sync>();
 }
 
@@ -464,11 +463,14 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(
+        except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of",
+        cfg="cfail2",
+    )]
+    #[rustc_clean(cfg="cfail3")]
     fn method<'a, 'b, 'c: 'a + 'b>(a: &'a u32, b: &'b u32, c: &'c u32);
 }
 
@@ -478,14 +480,14 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
 #[cfg(cfail1)]
 trait TraitAddAssociatedType {
 
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method();
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddAssociatedType {
     type Associated;
 
@@ -506,11 +508,11 @@ trait TraitAddTraitBoundToAssociatedType {
 // Apparently the type bound contributes to the predicates of the trait, but
 // does not change the associated item itself.
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddTraitBoundToAssociatedType {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     type Associated: ReferencedTrait0;
 
     fn method();
@@ -527,11 +529,11 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddLifetimeBoundToAssociatedType<'a> {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     type Associated: 'a;
 
     fn method();
@@ -548,11 +550,11 @@ trait TraitAddDefaultToAssociatedType {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddDefaultToAssociatedType {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,associated_item", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     type Associated = ReferenceType0;
 
     fn method();
@@ -567,8 +569,8 @@ trait TraitAddAssociatedConstant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddAssociatedConstant {
     const Value: u32;
 
@@ -586,15 +588,15 @@ trait TraitAddInitializerToAssociatedConstant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddInitializerToAssociatedConstant {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,associated_item", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     const Value: u32 = 1;
 
-    #[rustc_clean(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method();
 }
 
@@ -609,15 +611,15 @@ trait TraitChangeTypeOfAssociatedConstant {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitChangeTypeOfAssociatedConstant {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,type_of", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     const Value: f64;
 
-    #[rustc_clean(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method();
 }
 
@@ -628,8 +630,8 @@ trait TraitChangeTypeOfAssociatedConstant {
 trait TraitAddSuperTrait { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddSuperTrait : ReferencedTrait0 { }
 
 
@@ -639,8 +641,8 @@ trait TraitAddSuperTrait : ReferencedTrait0 { }
 trait TraitAddBuiltiBound { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddBuiltiBound : Send { }
 
 
@@ -650,8 +652,8 @@ trait TraitAddBuiltiBound : Send { }
 trait TraitAddStaticLifetimeBound { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddStaticLifetimeBound : 'static { }
 
 
@@ -661,16 +663,16 @@ trait TraitAddStaticLifetimeBound : 'static { }
 trait TraitAddTraitAsSecondBound : ReferencedTrait0 { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddTraitAsSecondBound : ReferencedTrait0 + ReferencedTrait1 { }
 
 #[cfg(cfail1)]
 trait TraitAddTraitAsSecondBoundFromBuiltin : Send { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { }
 
 
@@ -680,16 +682,16 @@ trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { }
 trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 + Send { }
 
 #[cfg(cfail1)]
 trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin : Send { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { }
 
 
@@ -699,16 +701,16 @@ trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { }
 trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 + 'static { }
 
 #[cfg(cfail1)]
 trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { }
 
 
@@ -718,8 +720,8 @@ trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { }
 trait TraitAddTypeParameterToTrait { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,generics_of,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddTypeParameterToTrait<T> { }
 
 
@@ -729,8 +731,8 @@ trait TraitAddTypeParameterToTrait<T> { }
 trait TraitAddLifetimeParameterToTrait { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,generics_of,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddLifetimeParameterToTrait<'a> { }
 
 
@@ -740,8 +742,8 @@ trait TraitAddLifetimeParameterToTrait<'a> { }
 trait TraitAddTraitBoundToTypeParameterOfTrait<T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0> { }
 
 
@@ -751,8 +753,8 @@ trait TraitAddTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0> { }
 trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { }
 
 
@@ -762,8 +764,8 @@ trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { }
 trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a, 'b> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { }
 
 
@@ -773,8 +775,8 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { }
 trait TraitAddBuiltinBoundToTypeParameterOfTrait<T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddBuiltinBoundToTypeParameterOfTrait<T: Send> { }
 
 
@@ -784,8 +786,8 @@ trait TraitAddBuiltinBoundToTypeParameterOfTrait<T: Send> { }
 trait TraitAddSecondTypeParameterToTrait<T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddSecondTypeParameterToTrait<T, S> { }
 
 
@@ -795,8 +797,8 @@ trait TraitAddSecondTypeParameterToTrait<T, S> { }
 trait TraitAddSecondLifetimeParameterToTrait<'a> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { }
 
 
@@ -806,8 +808,8 @@ trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { }
 trait TraitAddSecondTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddSecondTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0 + ReferencedTrait1> { }
 
 
@@ -817,8 +819,8 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0 + Refer
 trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { }
 
 
@@ -828,8 +830,8 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { }
 trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b, 'c> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> { }
 
 
@@ -839,8 +841,8 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c>
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait<T: Send> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait<T: Send + Sync> { }
 
 
@@ -855,8 +857,8 @@ struct ReferenceType1 {}
 trait TraitAddTraitBoundToTypeParameterOfTraitWhere<T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddTraitBoundToTypeParameterOfTraitWhere<T> where T: ReferencedTrait0 { }
 
 
@@ -866,8 +868,8 @@ trait TraitAddTraitBoundToTypeParameterOfTraitWhere<T> where T: ReferencedTrait0
 trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { }
 
 
@@ -877,8 +879,8 @@ trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { }
 trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b { }
 
 
@@ -888,8 +890,8 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b
 trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere<T> { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { }
 
 
@@ -899,8 +901,8 @@ trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { }
 trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere<T> where T: ReferencedTrait0 { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere<T>
     where T: ReferencedTrait0 + ReferencedTrait1 { }
 
@@ -911,8 +913,8 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere<T>
 trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a + 'b { }
 
 
@@ -922,8 +924,8 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T:
 trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b + 'c { }
 
 
@@ -933,8 +935,8 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> whe
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send + Sync { }
 
 
@@ -945,11 +947,11 @@ mod change_return_type_of_method_indirectly_use {
     #[cfg(not(cfail1))]
     use super::ReferenceType1 as ReturnType;
 
-    #[rustc_clean(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     trait TraitChangeReturnType {
-        #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-        #[rustc_clean(label="hir_owner", cfg="cfail3")]
+        #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")]
+        #[rustc_clean(cfg="cfail3")]
         fn method() -> ReturnType;
     }
 }
@@ -963,11 +965,11 @@ mod change_method_parameter_type_indirectly_by_use {
     #[cfg(not(cfail1))]
     use super::ReferenceType1 as ArgType;
 
-    #[rustc_clean(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     trait TraitChangeArgType {
-        #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-        #[rustc_clean(label="hir_owner", cfg="cfail3")]
+        #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
+        #[rustc_clean(cfg="cfail3")]
         fn method(a: ArgType);
     }
 }
@@ -981,11 +983,11 @@ mod change_method_parameter_type_bound_indirectly_by_use {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait1 as Bound;
 
-    #[rustc_clean(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     trait TraitChangeBoundOfMethodTypeParameter {
-        #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-        #[rustc_clean(label="hir_owner", cfg="cfail3")]
+        #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+        #[rustc_clean(cfg="cfail3")]
         fn method<T: Bound>(a: T);
     }
 }
@@ -1000,11 +1002,11 @@ mod change_method_parameter_type_bound_indirectly_by_use_where {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait1 as Bound;
 
-    #[rustc_clean(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     trait TraitChangeBoundOfMethodTypeParameterWhere {
-        #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-        #[rustc_clean(label="hir_owner", cfg="cfail3")]
+        #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+        #[rustc_clean(cfg="cfail3")]
         fn method<T>(a: T) where T: Bound;
     }
 }
@@ -1018,8 +1020,8 @@ mod change_method_type_parameter_bound_indirectly {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait1 as Bound;
 
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     trait TraitChangeTraitBound<T: Bound> {
         fn method(a: T);
     }
@@ -1035,8 +1037,8 @@ mod change_method_type_parameter_bound_indirectly_where {
     #[cfg(not(cfail1))]
     use super::ReferencedTrait1 as Bound;
 
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     trait TraitChangeTraitBoundWhere<T> where T: Bound {
         fn method(a: T);
     }
diff --git a/src/test/incremental/hashes/trait_impls.rs b/src/test/incremental/hashes/trait_impls.rs
index e9118da5a61..c9a3de1f6ae 100644
--- a/src/test/incremental/hashes/trait_impls.rs
+++ b/src/test/incremental/hashes/trait_impls.rs
@@ -30,18 +30,18 @@ impl ChangeMethodNameTrait for Foo {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 pub trait ChangeMethodNameTrait {
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(cfg="cfail3")]
     fn method_name2();
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 impl ChangeMethodNameTrait for Foo {
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(cfg="cfail3")]
     fn method_name2() { }
 }
 
@@ -59,13 +59,11 @@ impl ChangeMethodBodyTrait for Foo {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 impl ChangeMethodBodyTrait for Foo {
-    #[rustc_clean(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
-    #[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method_name() {
         ()
     }
@@ -86,13 +84,11 @@ impl ChangeMethodBodyTraitInlined for Foo {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 impl ChangeMethodBodyTraitInlined for Foo {
-    #[rustc_clean(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
-    #[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner_nodes", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     #[inline]
     fn method_name() {
         panic!()
@@ -117,11 +113,14 @@ pub trait ChangeMethodSelfnessTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 impl ChangeMethodSelfnessTrait for Foo {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(
+        except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir",
+        cfg="cfail2",
+    )]
+    #[rustc_clean(cfg="cfail3")]
     fn method_name(&self) {
         ()
     }
@@ -145,11 +144,14 @@ pub trait RemoveMethodSelfnessTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 impl RemoveMethodSelfnessTrait for Foo {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(
+        except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir",
+        cfg="cfail2",
+    )]
+    #[rustc_clean(cfg="cfail3")]
     fn method_name() {}
 }
 
@@ -171,11 +173,11 @@ pub trait ChangeMethodSelfmutnessTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 impl ChangeMethodSelfmutnessTrait for Foo {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method_name(&mut self) {}
 }
 
@@ -197,8 +199,8 @@ pub trait ChangeItemKindTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 impl ChangeItemKindTrait for Foo {
     type name = ();
 }
@@ -223,8 +225,8 @@ pub trait RemoveItemTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 impl RemoveItemTrait for Foo {
     type TypeName = ();
 }
@@ -248,8 +250,8 @@ pub trait AddItemTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 impl AddItemTrait for Foo {
     type TypeName = ();
     fn method_name() { }
@@ -268,17 +270,17 @@ impl ChangeHasValueTrait for Foo {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 pub trait ChangeHasValueTrait {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,associated_item", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method_name() { }
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 impl ChangeHasValueTrait for Foo {
     fn method_name() { }
 }
@@ -295,11 +297,11 @@ impl AddDefaultTrait for Foo {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 impl AddDefaultTrait for Foo {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     default fn method_name() { }
 }
 
@@ -321,11 +323,11 @@ pub trait AddArgumentTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 impl AddArgumentTrait for Foo {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method_name(&self, _x: u32) { }
 }
 
@@ -347,11 +349,11 @@ pub trait ChangeArgumentTypeTrait {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 impl ChangeArgumentTypeTrait for Foo {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn method_name(&self, _x: char) { }
 }
 
@@ -370,11 +372,14 @@ impl AddTypeParameterToImpl<u32> for Bar<u32> {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,generics_of,impl_trait_ref", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 impl<T> AddTypeParameterToImpl<T> for Bar<T> {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(
+        except="hir_owner,hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir",
+        cfg="cfail2",
+    )]
+    #[rustc_clean(cfg="cfail3")]
     fn id(t: T) -> T { t }
 }
 
@@ -391,11 +396,11 @@ impl ChangeSelfTypeOfImpl for u32 {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,impl_trait_ref", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 impl ChangeSelfTypeOfImpl for u64 {
-    #[rustc_clean(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(except="fn_sig,typeck,optimized_mir", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn id(self) -> Self { self }
 }
 
@@ -412,11 +417,11 @@ impl<T> AddLifetimeBoundToImplParameter for T {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 impl<T: 'static> AddLifetimeBoundToImplParameter for T {
-    #[rustc_clean(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn id(self) -> Self { self }
 }
 
@@ -433,11 +438,11 @@ impl<T> AddTraitBoundToImplParameter for T {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_dirty(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 impl<T: Clone> AddTraitBoundToImplParameter for T {
-    #[rustc_clean(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     fn id(self) -> Self { self }
 }
 
@@ -454,11 +459,11 @@ impl AddNoMangleToMethod for Foo {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 impl AddNoMangleToMethod for Foo {
-    #[rustc_clean(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     #[no_mangle]
     fn add_no_mangle_to_method(&self) { }
 }
@@ -475,11 +480,11 @@ impl MakeMethodInline for Foo {
 }
 
 #[cfg(not(cfail1))]
-#[rustc_clean(label="hir_owner", cfg="cfail2")]
-#[rustc_clean(label="hir_owner", cfg="cfail3")]
+#[rustc_clean(cfg="cfail2")]
+#[rustc_clean(cfg="cfail3")]
 impl MakeMethodInline for Foo {
-    #[rustc_clean(label="hir_owner", cfg="cfail2")]
-    #[rustc_clean(label="hir_owner", cfg="cfail3")]
+    #[rustc_clean(cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
     #[inline]
     fn make_method_inline(&self) -> u8 { 0 }
 }
diff --git a/src/test/incremental/hello_world.rs b/src/test/incremental/hello_world.rs
index 4c60d7bd9d5..d5ec6e92bc0 100644
--- a/src/test/incremental/hello_world.rs
+++ b/src/test/incremental/hello_world.rs
@@ -21,7 +21,7 @@ mod x {
 mod y {
     use x;
 
-    #[rustc_clean(label="typeck", cfg="rpass2")]
+    #[rustc_clean(cfg="rpass2")]
     pub fn yyyy() {
         x::xxxx();
     }
@@ -30,7 +30,7 @@ mod y {
 mod z {
     use y;
 
-    #[rustc_clean(label="typeck", cfg="rpass2")]
+    #[rustc_clean(cfg="rpass2")]
     pub fn z() {
         y::yyyy();
     }
diff --git a/src/test/incremental/hygiene/auxiliary/cached_hygiene.rs b/src/test/incremental/hygiene/auxiliary/cached_hygiene.rs
index 91a9f63d39b..b31f60e972b 100644
--- a/src/test/incremental/hygiene/auxiliary/cached_hygiene.rs
+++ b/src/test/incremental/hygiene/auxiliary/cached_hygiene.rs
@@ -13,7 +13,7 @@ macro_rules! first_macro {
     }
 }
 
-#[rustc_dirty(label="typeck", cfg="rpass2")]
+#[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir,promoted_mir", cfg="rpass2")]
 #[inline(always)]
 pub fn changed_fn() {
     // This will cause additional hygiene to be generate,
diff --git a/src/test/incremental/ich_method_call_trait_scope.rs b/src/test/incremental/ich_method_call_trait_scope.rs
index 6d7d446cb7c..5566506c039 100644
--- a/src/test/incremental/ich_method_call_trait_scope.rs
+++ b/src/test/incremental/ich_method_call_trait_scope.rs
@@ -26,16 +26,12 @@ mod mod3 {
     #[cfg(rpass2)]
     use Trait2;
 
-    #[rustc_clean(label="hir_owner", cfg="rpass2")]
-    #[rustc_clean(label="hir_owner_nodes", cfg="rpass2")]
-    #[rustc_dirty(label="typeck", cfg="rpass2")]
+    #[rustc_clean(except="typeck", cfg="rpass2")]
     fn bar() {
         ().method();
     }
 
-    #[rustc_clean(label="hir_owner", cfg="rpass2")]
-    #[rustc_clean(label="hir_owner_nodes", cfg="rpass2")]
-    #[rustc_clean(label="typeck", cfg="rpass2")]
+    #[rustc_clean(cfg="rpass2")]
     fn baz() {
         22; // no method call, traits in scope don't matter
     }
diff --git a/src/test/incremental/ich_nested_items.rs b/src/test/incremental/ich_nested_items.rs
index 8df54467e5e..379c09575ed 100644
--- a/src/test/incremental/ich_nested_items.rs
+++ b/src/test/incremental/ich_nested_items.rs
@@ -8,14 +8,12 @@
 #![crate_type = "rlib"]
 #![feature(rustc_attrs)]
 
-#[rustc_clean(label = "hir_owner", cfg = "cfail2")]
-#[rustc_dirty(label = "hir_owner_nodes", cfg = "cfail2")]
+#[rustc_clean(except = "hir_owner_nodes", cfg = "cfail2")]
 pub fn foo() {
     #[cfg(cfail1)]
     pub fn baz() {} // order is different...
 
-    #[rustc_clean(label = "hir_owner", cfg = "cfail2")]
-    #[rustc_clean(label = "hir_owner_nodes", cfg = "cfail2")]
+    #[rustc_clean(cfg = "cfail2")]
     pub fn bar() {} // but that doesn't matter.
 
     #[cfg(cfail2)]
diff --git a/src/test/incremental/ich_resolve_results.rs b/src/test/incremental/ich_resolve_results.rs
index 1fb0f8aa84d..e6ab6bcebae 100644
--- a/src/test/incremental/ich_resolve_results.rs
+++ b/src/test/incremental/ich_resolve_results.rs
@@ -29,18 +29,14 @@ mod mod3 {
     #[cfg(rpass3)]
     use mod2::Foo;
 
-    #[rustc_clean(label="hir_owner", cfg="rpass2")]
-    #[rustc_clean(label="hir_owner_nodes", cfg="rpass2")]
-    #[rustc_clean(label="hir_owner", cfg="rpass3")]
-    #[rustc_dirty(label="hir_owner_nodes", cfg="rpass3")]
+    #[rustc_clean(cfg="rpass2")]
+    #[rustc_clean(except="hir_owner_nodes,typeck", cfg="rpass3")]
     fn in_expr() {
         Foo(0);
     }
 
-    #[rustc_clean(label="hir_owner", cfg="rpass2")]
-    #[rustc_clean(label="hir_owner_nodes", cfg="rpass2")]
-    #[rustc_clean(label="hir_owner", cfg="rpass3")]
-    #[rustc_dirty(label="hir_owner_nodes", cfg="rpass3")]
+    #[rustc_clean(cfg="rpass2")]
+    #[rustc_clean(except="hir_owner_nodes,typeck", cfg="rpass3")]
     fn in_type() {
         test::<Foo>();
     }
diff --git a/src/test/incremental/rlib_cross_crate/b.rs b/src/test/incremental/rlib_cross_crate/b.rs
index 73846712b59..639cfc918cb 100644
--- a/src/test/incremental/rlib_cross_crate/b.rs
+++ b/src/test/incremental/rlib_cross_crate/b.rs
@@ -12,15 +12,15 @@
 
 extern crate a;
 
-#[rustc_dirty(label="typeck", cfg="rpass2")]
-#[rustc_clean(label="typeck", cfg="rpass3")]
+#[rustc_clean(except="typeck,optimized_mir", cfg="rpass2")]
+#[rustc_clean(cfg="rpass3")]
 pub fn use_X() -> u32 {
     let x: a::X = 22;
     x as u32
 }
 
-#[rustc_clean(label="typeck", cfg="rpass2")]
-#[rustc_clean(label="typeck", cfg="rpass3")]
+#[rustc_clean(cfg="rpass2")]
+#[rustc_clean(cfg="rpass3")]
 pub fn use_Y() {
     let x: a::Y = 'c';
 }
diff --git a/src/test/incremental/source_loc_macros.rs b/src/test/incremental/source_loc_macros.rs
index f18d2fdaf0a..e5f04e5dc58 100644
--- a/src/test/incremental/source_loc_macros.rs
+++ b/src/test/incremental/source_loc_macros.rs
@@ -7,26 +7,22 @@
 
 #![feature(rustc_attrs)]
 
-#[rustc_clean(label="hir_owner", cfg="rpass2")]
-#[rustc_clean(label="hir_owner_nodes", cfg="rpass2")]
+#[rustc_clean(cfg="rpass2")]
 fn line_same() {
     let _ = line!();
 }
 
-#[rustc_clean(label="hir_owner", cfg="rpass2")]
-#[rustc_clean(label="hir_owner_nodes", cfg="rpass2")]
+#[rustc_clean(cfg="rpass2")]
 fn col_same() {
     let _ = column!();
 }
 
-#[rustc_clean(label="hir_owner", cfg="rpass2")]
-#[rustc_clean(label="hir_owner_nodes", cfg="rpass2")]
+#[rustc_clean(cfg="rpass2")]
 fn file_same() {
     let _ = file!();
 }
 
-#[rustc_clean(label="hir_owner", cfg="rpass2")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="rpass2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="rpass2")]
 fn line_different() {
     #[cfg(rpass1)]
     {
@@ -38,8 +34,7 @@ fn line_different() {
     }
 }
 
-#[rustc_clean(label="hir_owner", cfg="rpass2")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="rpass2")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="rpass2")]
 fn col_different() {
     #[cfg(rpass1)]
     {
diff --git a/src/test/incremental/span_hash_stable/auxiliary/sub1.rs b/src/test/incremental/span_hash_stable/auxiliary/sub1.rs
index 2927ddec4e5..70e2ea06b7e 100644
--- a/src/test/incremental/span_hash_stable/auxiliary/sub1.rs
+++ b/src/test/incremental/span_hash_stable/auxiliary/sub1.rs
@@ -1,4 +1,4 @@
-#[rustc_clean(label="hir_owner", cfg="rpass2")]
+#[rustc_clean(cfg="rpass2")]
 pub struct SomeType {
     pub x: u32,
     pub y: i64,
diff --git a/src/test/incremental/span_hash_stable/auxiliary/sub2.rs b/src/test/incremental/span_hash_stable/auxiliary/sub2.rs
index aa635077db8..1167cdb0a82 100644
--- a/src/test/incremental/span_hash_stable/auxiliary/sub2.rs
+++ b/src/test/incremental/span_hash_stable/auxiliary/sub2.rs
@@ -1,4 +1,4 @@
-#[rustc_clean(label="hir_owner", cfg="rpass2")]
+#[rustc_clean(cfg="rpass2")]
 pub struct SomeOtherType {
     pub a: i32,
     pub b: u64,
diff --git a/src/test/incremental/spans_significant_w_debuginfo.rs b/src/test/incremental/spans_significant_w_debuginfo.rs
index aff2be830ff..8506636e22b 100644
--- a/src/test/incremental/spans_significant_w_debuginfo.rs
+++ b/src/test/incremental/spans_significant_w_debuginfo.rs
@@ -12,6 +12,5 @@
 pub fn main() {}
 
 #[cfg(rpass2)]
-#[rustc_dirty(label="hir_owner", cfg="rpass2")]
-#[rustc_dirty(label="hir_owner_nodes", cfg="rpass2")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,optimized_mir", cfg="rpass2")]
 pub fn main() {}
diff --git a/src/test/incremental/spans_significant_w_panic.rs b/src/test/incremental/spans_significant_w_panic.rs
index 37728af9516..a29b61ab153 100644
--- a/src/test/incremental/spans_significant_w_panic.rs
+++ b/src/test/incremental/spans_significant_w_panic.rs
@@ -13,7 +13,7 @@ pub fn main() {
 }
 
 #[cfg(rpass2)]
-#[rustc_dirty(label="optimized_mir", cfg="rpass2")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,optimized_mir", cfg="rpass2")]
 pub fn main() {
     let _ = 0u8 + 1;
 }
diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs
index 2fc72529431..866f51d759e 100644
--- a/src/test/incremental/string_constant.rs
+++ b/src/test/incremental/string_constant.rs
@@ -18,8 +18,7 @@ pub mod x {
     }
 
     #[cfg(cfail2)]
-    #[rustc_dirty(label="hir_owner_nodes", cfg="cfail2")]
-    #[rustc_dirty(label="optimized_mir", cfg="cfail2")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,optimized_mir,promoted_mir", cfg="cfail2")]
     pub fn x() {
         println!("{}", "2");
     }
@@ -28,8 +27,7 @@ pub mod x {
 pub mod y {
     use x;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
-    #[rustc_clean(label="optimized_mir", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn y() {
         x::x();
     }
@@ -38,8 +36,7 @@ pub mod y {
 pub mod z {
     use y;
 
-    #[rustc_clean(label="typeck", cfg="cfail2")]
-    #[rustc_clean(label="optimized_mir", cfg="cfail2")]
+    #[rustc_clean(cfg="cfail2")]
     pub fn z() {
         y::y();
     }
diff --git a/src/test/incremental/struct_add_field.rs b/src/test/incremental/struct_add_field.rs
index 4c29f196f67..720854f1605 100644
--- a/src/test/incremental/struct_add_field.rs
+++ b/src/test/incremental/struct_add_field.rs
@@ -21,17 +21,17 @@ pub struct Y {
     pub y: char
 }
 
-#[rustc_dirty(label="typeck", cfg="rpass2")]
+#[rustc_clean(except="fn_sig,typeck", cfg="rpass2")]
 pub fn use_X(x: X) -> u32 {
     x.x as u32
 }
 
-#[rustc_dirty(label="typeck", cfg="rpass2")]
+#[rustc_clean(except="typeck", cfg="rpass2")]
 pub fn use_EmbedX(embed: EmbedX) -> u32 {
     embed.x.x as u32
 }
 
-#[rustc_clean(label="typeck", cfg="rpass2")]
+#[rustc_clean(cfg="rpass2")]
 pub fn use_Y() {
     let x: Y = Y { y: 'c' };
 }
diff --git a/src/test/incremental/struct_change_field_name.rs b/src/test/incremental/struct_change_field_name.rs
index ee88fbdf592..7498d0305e0 100644
--- a/src/test/incremental/struct_change_field_name.rs
+++ b/src/test/incremental/struct_change_field_name.rs
@@ -24,7 +24,7 @@ pub struct Y {
     pub y: char
 }
 
-#[rustc_dirty(label="typeck", cfg="cfail2")]
+#[rustc_clean(except="typeck", cfg="cfail2")]
 pub fn use_X() -> u32 {
     let x: X = X { x: 22 };
     //[cfail2]~^ ERROR struct `X` has no field named `x`
@@ -32,13 +32,13 @@ pub fn use_X() -> u32 {
     //[cfail2]~^ ERROR no field `x` on type `X`
 }
 
-#[rustc_dirty(label="typeck", cfg="cfail2")]
+#[rustc_clean(except="typeck", cfg="cfail2")]
 pub fn use_EmbedX(embed: EmbedX) -> u32 {
     embed.x.x as u32
     //[cfail2]~^ ERROR no field `x` on type `X`
 }
 
-#[rustc_clean(label="typeck", cfg="cfail2")]
+#[rustc_clean(cfg="cfail2")]
 pub fn use_Y() {
     let x: Y = Y { y: 'c' };
 }
diff --git a/src/test/incremental/struct_change_field_type.rs b/src/test/incremental/struct_change_field_type.rs
index b60b4b311ee..37d2fba9901 100644
--- a/src/test/incremental/struct_change_field_type.rs
+++ b/src/test/incremental/struct_change_field_type.rs
@@ -24,19 +24,19 @@ pub struct Y {
     pub y: char
 }
 
-#[rustc_dirty(label="typeck", cfg="rpass2")]
+#[rustc_clean(except="typeck", cfg="rpass2")]
 pub fn use_X() -> u32 {
     let x: X = X { x: 22 };
     x.x as u32
 }
 
-#[rustc_dirty(label="typeck", cfg="rpass2")]
+#[rustc_clean(except="typeck", cfg="rpass2")]
 pub fn use_EmbedX(x: EmbedX) -> u32 {
     let x: X = X { x: 22 };
     x.x as u32
 }
 
-#[rustc_clean(label="typeck", cfg="rpass2")]
+#[rustc_clean(cfg="rpass2")]
 pub fn use_Y() {
     let x: Y = Y { y: 'c' };
 }
diff --git a/src/test/incremental/struct_change_field_type_cross_crate/b.rs b/src/test/incremental/struct_change_field_type_cross_crate/b.rs
index 0221d510eab..c78207bcb1a 100644
--- a/src/test/incremental/struct_change_field_type_cross_crate/b.rs
+++ b/src/test/incremental/struct_change_field_type_cross_crate/b.rs
@@ -8,18 +8,18 @@ extern crate a;
 
 use a::*;
 
-#[rustc_dirty(label="typeck", cfg="rpass2")]
+#[rustc_clean(except="typeck", cfg="rpass2")]
 pub fn use_X() -> u32 {
     let x: X = X { x: 22 };
     x.x as u32
 }
 
-#[rustc_dirty(label="typeck", cfg="rpass2")]
+#[rustc_clean(except="typeck", cfg="rpass2")]
 pub fn use_EmbedX(embed: EmbedX) -> u32 {
     embed.x.x as u32
 }
 
-#[rustc_clean(label="typeck", cfg="rpass2")]
+#[rustc_clean(cfg="rpass2")]
 pub fn use_Y() {
     let x: Y = Y { y: 'c' };
 }
diff --git a/src/test/incremental/struct_change_nothing.rs b/src/test/incremental/struct_change_nothing.rs
index 3ab90e966fb..de30c818cfe 100644
--- a/src/test/incremental/struct_change_nothing.rs
+++ b/src/test/incremental/struct_change_nothing.rs
@@ -24,19 +24,19 @@ pub struct Y {
     pub y: char
 }
 
-#[rustc_clean(label="typeck", cfg="rpass2")]
+#[rustc_clean(cfg="rpass2")]
 pub fn use_X() -> u32 {
     let x: X = X { x: 22 };
     x.x as u32
 }
 
-#[rustc_clean(label="typeck", cfg="rpass2")]
+#[rustc_clean(cfg="rpass2")]
 pub fn use_EmbedX(x: EmbedX) -> u32 {
     let x: X = X { x: 22 };
     x.x as u32
 }
 
-#[rustc_clean(label="typeck", cfg="rpass2")]
+#[rustc_clean(cfg="rpass2")]
 pub fn use_Y() {
     let x: Y = Y { y: 'c' };
 }
diff --git a/src/test/incremental/struct_remove_field.rs b/src/test/incremental/struct_remove_field.rs
index f6017b1b1c3..b97a87e0962 100644
--- a/src/test/incremental/struct_remove_field.rs
+++ b/src/test/incremental/struct_remove_field.rs
@@ -25,17 +25,17 @@ pub struct Y {
     pub y: char
 }
 
-#[rustc_dirty(label="typeck", cfg="rpass2")]
+#[rustc_clean(except="typeck,fn_sig", cfg="rpass2")]
 pub fn use_X(x: X) -> u32 {
     x.x as u32
 }
 
-#[rustc_dirty(label="typeck", cfg="rpass2")]
+#[rustc_clean(except="typeck", cfg="rpass2")]
 pub fn use_EmbedX(embed: EmbedX) -> u32 {
     embed.x.x as u32
 }
 
-#[rustc_clean(label="typeck", cfg="rpass2")]
+#[rustc_clean(cfg="rpass2")]
 pub fn use_Y() {
     let x: Y = Y { y: 'c' };
 }
diff --git a/src/test/incremental/type_alias_cross_crate/b.rs b/src/test/incremental/type_alias_cross_crate/b.rs
index 05c926fdded..f6c2526841c 100644
--- a/src/test/incremental/type_alias_cross_crate/b.rs
+++ b/src/test/incremental/type_alias_cross_crate/b.rs
@@ -6,15 +6,15 @@
 
 extern crate a;
 
-#[rustc_dirty(label="typeck", cfg="rpass2")]
-#[rustc_clean(label="typeck", cfg="rpass3")]
+#[rustc_clean(except="typeck", cfg="rpass2")]
+#[rustc_clean(cfg="rpass3")]
 pub fn use_X() -> u32 {
     let x: a::X = 22;
     x as u32
 }
 
-#[rustc_clean(label="typeck", cfg="rpass2")]
-#[rustc_clean(label="typeck", cfg="rpass3")]
+#[rustc_clean(cfg="rpass2")]
+#[rustc_clean(cfg="rpass3")]
 pub fn use_Y() {
     let x: a::Y = 'c';
 }
diff --git a/src/test/incremental/unchecked_dirty_clean.rs b/src/test/incremental/unchecked_dirty_clean.rs
index 3bc8818aa6f..3c8692a302d 100644
--- a/src/test/incremental/unchecked_dirty_clean.rs
+++ b/src/test/incremental/unchecked_dirty_clean.rs
@@ -4,31 +4,31 @@
 #![allow(warnings)]
 #![feature(rustc_attrs)]
 
-// Sanity check for the dirty-clean system. We add #[rustc_dirty]/#[rustc_clean]
+// Sanity check for the dirty-clean system. We add #[rustc_clean]
 // attributes in places that are not checked and make sure that this causes an
 // error.
 
 fn main() {
 
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    //[cfail2]~^ ERROR found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute
+    #[rustc_clean(except="hir_owner", cfg="cfail2")]
+    //[cfail2]~^ ERROR found unchecked `#[rustc_clean]` attribute
     {
         // empty block
     }
 
-    #[rustc_clean(label="hir_owner", cfg="cfail2")]
-    //[cfail2]~^ ERROR found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute
+    #[rustc_clean(cfg="cfail2")]
+    //[cfail2]~^ ERROR found unchecked `#[rustc_clean]` attribute
     {
         // empty block
     }
 }
 
 struct _Struct {
-    #[rustc_dirty(label="hir_owner", cfg="cfail2")]
-    //[cfail2]~^ ERROR found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute
+    #[rustc_clean(except="hir_owner", cfg="cfail2")]
+    //[cfail2]~^ ERROR found unchecked `#[rustc_clean]` attribute
     _field1: i32,
 
-    #[rustc_clean(label="hir_owner", cfg="cfail2")]
-    //[cfail2]~^ ERROR found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute
+    #[rustc_clean(cfg="cfail2")]
+    //[cfail2]~^ ERROR found unchecked `#[rustc_clean]` attribute
     _field2: i32,
 }
diff --git a/src/test/mir-opt/bool_compare.opt1.InstCombine.diff b/src/test/mir-opt/bool_compare.opt1.InstCombine.diff
new file mode 100644
index 00000000000..a14f64467a6
--- /dev/null
+++ b/src/test/mir-opt/bool_compare.opt1.InstCombine.diff
@@ -0,0 +1,35 @@
+- // MIR for `opt1` before InstCombine
++ // MIR for `opt1` after InstCombine
+  
+  fn opt1(_1: bool) -> u32 {
+      debug x => _1;                       // in scope 0 at $DIR/bool_compare.rs:2:9: 2:10
+      let mut _0: u32;                     // return place in scope 0 at $DIR/bool_compare.rs:2:21: 2:24
+      let mut _2: bool;                    // in scope 0 at $DIR/bool_compare.rs:3:8: 3:17
+      let mut _3: bool;                    // in scope 0 at $DIR/bool_compare.rs:3:8: 3:9
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/bool_compare.rs:3:8: 3:17
+          StorageLive(_3);                 // scope 0 at $DIR/bool_compare.rs:3:8: 3:9
+          _3 = _1;                         // scope 0 at $DIR/bool_compare.rs:3:8: 3:9
+-         _2 = Ne(move _3, const true);    // scope 0 at $DIR/bool_compare.rs:3:8: 3:17
++         _2 = Not(move _3);               // scope 0 at $DIR/bool_compare.rs:3:8: 3:17
+          StorageDead(_3);                 // scope 0 at $DIR/bool_compare.rs:3:16: 3:17
+          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:3:5: 3:34
+      }
+  
+      bb1: {
+          _0 = const 0_u32;                // scope 0 at $DIR/bool_compare.rs:3:20: 3:21
+          goto -> bb3;                     // scope 0 at $DIR/bool_compare.rs:3:5: 3:34
+      }
+  
+      bb2: {
+          _0 = const 1_u32;                // scope 0 at $DIR/bool_compare.rs:3:31: 3:32
+          goto -> bb3;                     // scope 0 at $DIR/bool_compare.rs:3:5: 3:34
+      }
+  
+      bb3: {
+          StorageDead(_2);                 // scope 0 at $DIR/bool_compare.rs:3:33: 3:34
+          return;                          // scope 0 at $DIR/bool_compare.rs:4:2: 4:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/bool_compare.opt2.InstCombine.diff b/src/test/mir-opt/bool_compare.opt2.InstCombine.diff
new file mode 100644
index 00000000000..4e9c255ad62
--- /dev/null
+++ b/src/test/mir-opt/bool_compare.opt2.InstCombine.diff
@@ -0,0 +1,35 @@
+- // MIR for `opt2` before InstCombine
++ // MIR for `opt2` after InstCombine
+  
+  fn opt2(_1: bool) -> u32 {
+      debug x => _1;                       // in scope 0 at $DIR/bool_compare.rs:7:9: 7:10
+      let mut _0: u32;                     // return place in scope 0 at $DIR/bool_compare.rs:7:21: 7:24
+      let mut _2: bool;                    // in scope 0 at $DIR/bool_compare.rs:8:8: 8:17
+      let mut _3: bool;                    // in scope 0 at $DIR/bool_compare.rs:8:16: 8:17
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/bool_compare.rs:8:8: 8:17
+          StorageLive(_3);                 // scope 0 at $DIR/bool_compare.rs:8:16: 8:17
+          _3 = _1;                         // scope 0 at $DIR/bool_compare.rs:8:16: 8:17
+-         _2 = Ne(const true, move _3);    // scope 0 at $DIR/bool_compare.rs:8:8: 8:17
++         _2 = Not(move _3);               // scope 0 at $DIR/bool_compare.rs:8:8: 8:17
+          StorageDead(_3);                 // scope 0 at $DIR/bool_compare.rs:8:16: 8:17
+          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:8:5: 8:34
+      }
+  
+      bb1: {
+          _0 = const 0_u32;                // scope 0 at $DIR/bool_compare.rs:8:20: 8:21
+          goto -> bb3;                     // scope 0 at $DIR/bool_compare.rs:8:5: 8:34
+      }
+  
+      bb2: {
+          _0 = const 1_u32;                // scope 0 at $DIR/bool_compare.rs:8:31: 8:32
+          goto -> bb3;                     // scope 0 at $DIR/bool_compare.rs:8:5: 8:34
+      }
+  
+      bb3: {
+          StorageDead(_2);                 // scope 0 at $DIR/bool_compare.rs:8:33: 8:34
+          return;                          // scope 0 at $DIR/bool_compare.rs:9:2: 9:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/bool_compare.opt3.InstCombine.diff b/src/test/mir-opt/bool_compare.opt3.InstCombine.diff
new file mode 100644
index 00000000000..2048c97a9e1
--- /dev/null
+++ b/src/test/mir-opt/bool_compare.opt3.InstCombine.diff
@@ -0,0 +1,35 @@
+- // MIR for `opt3` before InstCombine
++ // MIR for `opt3` after InstCombine
+  
+  fn opt3(_1: bool) -> u32 {
+      debug x => _1;                       // in scope 0 at $DIR/bool_compare.rs:12:9: 12:10
+      let mut _0: u32;                     // return place in scope 0 at $DIR/bool_compare.rs:12:21: 12:24
+      let mut _2: bool;                    // in scope 0 at $DIR/bool_compare.rs:13:8: 13:18
+      let mut _3: bool;                    // in scope 0 at $DIR/bool_compare.rs:13:8: 13:9
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/bool_compare.rs:13:8: 13:18
+          StorageLive(_3);                 // scope 0 at $DIR/bool_compare.rs:13:8: 13:9
+          _3 = _1;                         // scope 0 at $DIR/bool_compare.rs:13:8: 13:9
+-         _2 = Eq(move _3, const false);   // scope 0 at $DIR/bool_compare.rs:13:8: 13:18
++         _2 = Not(move _3);               // scope 0 at $DIR/bool_compare.rs:13:8: 13:18
+          StorageDead(_3);                 // scope 0 at $DIR/bool_compare.rs:13:17: 13:18
+          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:13:5: 13:35
+      }
+  
+      bb1: {
+          _0 = const 0_u32;                // scope 0 at $DIR/bool_compare.rs:13:21: 13:22
+          goto -> bb3;                     // scope 0 at $DIR/bool_compare.rs:13:5: 13:35
+      }
+  
+      bb2: {
+          _0 = const 1_u32;                // scope 0 at $DIR/bool_compare.rs:13:32: 13:33
+          goto -> bb3;                     // scope 0 at $DIR/bool_compare.rs:13:5: 13:35
+      }
+  
+      bb3: {
+          StorageDead(_2);                 // scope 0 at $DIR/bool_compare.rs:13:34: 13:35
+          return;                          // scope 0 at $DIR/bool_compare.rs:14:2: 14:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/bool_compare.opt4.InstCombine.diff b/src/test/mir-opt/bool_compare.opt4.InstCombine.diff
new file mode 100644
index 00000000000..efcaa2766a9
--- /dev/null
+++ b/src/test/mir-opt/bool_compare.opt4.InstCombine.diff
@@ -0,0 +1,35 @@
+- // MIR for `opt4` before InstCombine
++ // MIR for `opt4` after InstCombine
+  
+  fn opt4(_1: bool) -> u32 {
+      debug x => _1;                       // in scope 0 at $DIR/bool_compare.rs:17:9: 17:10
+      let mut _0: u32;                     // return place in scope 0 at $DIR/bool_compare.rs:17:21: 17:24
+      let mut _2: bool;                    // in scope 0 at $DIR/bool_compare.rs:18:8: 18:18
+      let mut _3: bool;                    // in scope 0 at $DIR/bool_compare.rs:18:17: 18:18
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/bool_compare.rs:18:8: 18:18
+          StorageLive(_3);                 // scope 0 at $DIR/bool_compare.rs:18:17: 18:18
+          _3 = _1;                         // scope 0 at $DIR/bool_compare.rs:18:17: 18:18
+-         _2 = Eq(const false, move _3);   // scope 0 at $DIR/bool_compare.rs:18:8: 18:18
++         _2 = Not(move _3);               // scope 0 at $DIR/bool_compare.rs:18:8: 18:18
+          StorageDead(_3);                 // scope 0 at $DIR/bool_compare.rs:18:17: 18:18
+          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:18:5: 18:35
+      }
+  
+      bb1: {
+          _0 = const 0_u32;                // scope 0 at $DIR/bool_compare.rs:18:21: 18:22
+          goto -> bb3;                     // scope 0 at $DIR/bool_compare.rs:18:5: 18:35
+      }
+  
+      bb2: {
+          _0 = const 1_u32;                // scope 0 at $DIR/bool_compare.rs:18:32: 18:33
+          goto -> bb3;                     // scope 0 at $DIR/bool_compare.rs:18:5: 18:35
+      }
+  
+      bb3: {
+          StorageDead(_2);                 // scope 0 at $DIR/bool_compare.rs:18:34: 18:35
+          return;                          // scope 0 at $DIR/bool_compare.rs:19:2: 19:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/bool_compare.rs b/src/test/mir-opt/bool_compare.rs
new file mode 100644
index 00000000000..3ff046325dc
--- /dev/null
+++ b/src/test/mir-opt/bool_compare.rs
@@ -0,0 +1,26 @@
+// EMIT_MIR bool_compare.opt1.InstCombine.diff
+fn opt1(x: bool) -> u32 {
+    if x != true { 0 } else { 1 }
+}
+
+// EMIT_MIR bool_compare.opt2.InstCombine.diff
+fn opt2(x: bool) -> u32 {
+    if true != x { 0 } else { 1 }
+}
+
+// EMIT_MIR bool_compare.opt3.InstCombine.diff
+fn opt3(x: bool) -> u32 {
+    if x == false { 0 } else { 1 }
+}
+
+// EMIT_MIR bool_compare.opt4.InstCombine.diff
+fn opt4(x: bool) -> u32 {
+    if false == x { 0 } else { 1 }
+}
+
+fn main() {
+    opt1(false);
+    opt2(false);
+    opt3(false);
+    opt4(false);
+}
diff --git a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
index 8bb5dbc48fe..2566d745ecd 100644
--- a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
+++ b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
@@ -30,7 +30,7 @@
 -         _3 = [move _4];                  // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
 -         _2 = &_3;                        // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
 +                                          // + span: $DIR/const-promotion-extern-static.rs:9:31: 9:35
-+                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[55e6]::BAR), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
++                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[317d]::BAR), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
 +         _2 = &(*_6);                     // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
           _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
 -         StorageDead(_4);                 // scope 0 at $DIR/const-promotion-extern-static.rs:9:34: 9:35
diff --git a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
index 54f1200a21f..093e228a0ce 100644
--- a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
+++ b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
@@ -32,7 +32,7 @@
 -         _3 = [move _4];                  // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
 -         _2 = &_3;                        // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
 +                                          // + span: $DIR/const-promotion-extern-static.rs:13:31: 13:46
-+                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[55e6]::FOO), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
++                                          // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[317d]::FOO), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
 +         _2 = &(*_6);                     // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
           _1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
 -         StorageDead(_4);                 // scope 0 at $DIR/const-promotion-extern-static.rs:13:45: 13:46
diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
index db6e1369161..0517e7fac40 100644
--- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
+++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
@@ -31,7 +31,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
-                                           // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[8240]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _3 = _9;                         // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
           _2 = &raw const (*_3);           // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
           _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
index db6e1369161..0517e7fac40 100644
--- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
+++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
@@ -31,7 +31,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
-                                           // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[8240]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _3 = _9;                         // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
           _2 = &raw const (*_3);           // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
           _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
index d7bc035e667..28c80b346e7 100644
--- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
@@ -22,7 +22,7 @@
                                            // + val: Unevaluated(FOO, [], None)
                                            // mir::Constant
                                            // + span: $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[2706]::main::FOO), const_param_did: None }, substs: [], promoted: None }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[317d]::main::FOO), const_param_did: None }, substs: [], promoted: None }) }
           _2 = &raw const (*_3);           // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
           _1 = move _2 as usize (Misc);    // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:39
           StorageDead(_2);                 // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:38: 7:39
diff --git a/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff
index 4e19465189c..ae77443e019 100644
--- a/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff
@@ -17,7 +17,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/ref_deref.rs:5:6: 5:10
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[cb9b]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _2 = _4;                         // scope 0 at $DIR/ref_deref.rs:5:6: 5:10
 -         _1 = (*_2);                      // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
 +         _1 = const 4_i32;                // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
diff --git a/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff b/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff
index a58dabdaa41..402a28f3f9f 100644
--- a/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff
+++ b/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff
@@ -20,7 +20,7 @@
 +                                          // + val: Unevaluated(main, [], Some(promoted[0]))
 +                                          // mir::Constant
 +                                          // + span: $DIR/ref_deref.rs:5:6: 5:10
-+                                          // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[cb9b]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
++                                          // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
 +         _2 = &(*_4);                     // scope 0 at $DIR/ref_deref.rs:5:6: 5:10
           _1 = (*_2);                      // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
 -         StorageDead(_3);                 // scope 0 at $DIR/ref_deref.rs:5:10: 5:11
diff --git a/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff
index bb265b2af7d..b97d7d1be15 100644
--- a/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff
@@ -17,7 +17,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/ref_deref_project.rs:5:6: 5:17
-                                           // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[e8c3]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _2 = &((*_4).1: i32);            // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17
           _1 = (*_2);                      // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17
           StorageDead(_2);                 // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18
diff --git a/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff b/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff
index bb7570fabbb..48ede27112c 100644
--- a/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff
+++ b/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff
@@ -20,7 +20,7 @@
 +                                          // + val: Unevaluated(main, [], Some(promoted[0]))
 +                                          // mir::Constant
 +                                          // + span: $DIR/ref_deref_project.rs:5:6: 5:17
-+                                          // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[e8c3]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
++                                          // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
 +         _2 = &((*_4).1: i32);            // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17
           _1 = (*_2);                      // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17
 -         StorageDead(_3);                 // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18
diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
index d5a36182e35..27791852d6d 100644
--- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
+++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
@@ -24,7 +24,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/slice_len.rs:5:6: 5:19
-                                           // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[6547]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _4 = _9;                         // scope 0 at $DIR/slice_len.rs:5:6: 5:19
           _3 = _4;                         // scope 0 at $DIR/slice_len.rs:5:6: 5:19
           _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:5:6: 5:19
diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
index d5a36182e35..27791852d6d 100644
--- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
+++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
@@ -24,7 +24,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/slice_len.rs:5:6: 5:19
-                                           // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[6547]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _4 = _9;                         // scope 0 at $DIR/slice_len.rs:5:6: 5:19
           _3 = _4;                         // scope 0 at $DIR/slice_len.rs:5:6: 5:19
           _2 = move _3 as &[u32] (Pointer(Unsize)); // scope 0 at $DIR/slice_len.rs:5:6: 5:19
diff --git a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
index 5ceefce6114..1aabee83be6 100644
--- a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
@@ -38,7 +38,7 @@ fn bar() -> bool {
                                          // + val: Unevaluated(bar, [], Some(promoted[1]))
                                          // mir::Constant
                                          // + span: $DIR/inline-retag.rs:12:7: 12:9
-                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[a78c]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[1]) }) }
+                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[1]) }) }
         Retag(_10);                      // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
         _4 = &(*_10);                    // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
         Retag(_4);                       // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
@@ -52,7 +52,7 @@ fn bar() -> bool {
                                          // + val: Unevaluated(bar, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $DIR/inline-retag.rs:12:11: 12:14
-                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[a78c]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[317d]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
         Retag(_9);                       // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
         _7 = &(*_9);                     // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
         Retag(_7);                       // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
index e955feb7d1f..95a8ef997fa 100644
--- a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
+++ b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
@@ -66,7 +66,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _8 = _20;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_6.0: &i32) = move _7;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_6.1: &i32) = move _8;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
index e955feb7d1f..95a8ef997fa 100644
--- a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
+++ b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
@@ -66,7 +66,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _8 = _20;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_6.0: &i32) = move _7;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_6.1: &i32) = move _8;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
index ff8c410a726..261eb3b27ea 100644
--- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
+++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
@@ -87,7 +87,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _11 = _28;                       // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_9.0: &i32) = move _10;         // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_9.1: &i32) = move _11;         // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
index ff8c410a726..261eb3b27ea 100644
--- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
+++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
@@ -87,7 +87,7 @@
                                            // + val: Unevaluated(main, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[2d0f]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
           _11 = _28;                       // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_9.0: &i32) = move _10;         // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           (_9.1: &i32) = move _11;         // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
diff --git a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
index acb8aca7590..a37df4da9ae 100644
--- a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
+++ b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
@@ -50,7 +50,7 @@
                                            // + val: Unevaluated(discriminant, [T], Some(promoted[2]))
                                            // mir::Constant
                                            // + span: $DIR/lower_intrinsics.rs:70:42: 70:44
-                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[2]) }) }
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[2]) }) }
           _7 = &(*_19);                    // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
           _6 = &(*_7);                     // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
 -         _5 = discriminant_value::<i32>(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45
@@ -74,7 +74,7 @@
                                            // + val: Unevaluated(discriminant, [T], Some(promoted[1]))
                                            // mir::Constant
                                            // + span: $DIR/lower_intrinsics.rs:71:42: 71:45
-                                           // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[1]) }) }
+                                           // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[1]) }) }
           _11 = &(*_18);                   // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
           _10 = &(*_11);                   // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
 -         _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46
@@ -98,7 +98,7 @@
                                            // + val: Unevaluated(discriminant, [T], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $DIR/lower_intrinsics.rs:72:42: 72:47
-                                           // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[0]) }) }
+                                           // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:27 ~ lower_intrinsics[8787]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[0]) }) }
           _15 = &(*_17);                   // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
           _14 = &(*_15);                   // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
 -         _13 = discriminant_value::<E>(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48
diff --git a/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir b/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir
index c27ee528b80..5af242376c9 100644
--- a/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir
+++ b/src/test/mir-opt/match_false_edges.full_tested_match.PromoteTemps.after.mir
@@ -57,7 +57,7 @@ fn full_tested_match() -> () {
                                          // + val: Unevaluated(full_tested_match, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $DIR/match_false_edges.rs:16:14: 16:15
-                                         // + literal: Const { ty: &std::option::Option<i32>, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ match_false_edges[4011]::full_tested_match), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                         // + literal: Const { ty: &std::option::Option<i32>, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ match_false_edges[317d]::full_tested_match), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
         _6 = &(((*_11) as Some).0: i32); // scope 0 at $DIR/match_false_edges.rs:16:14: 16:15
         _4 = &shallow _2;                // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27
         StorageLive(_7);                 // scope 0 at $DIR/match_false_edges.rs:16:20: 16:27
diff --git a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
index 787310d072a..c6ef403c3c1 100644
--- a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
@@ -127,7 +127,7 @@ fn array_casts() -> () {
                                          // + val: Unevaluated(array_casts, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                                         // + literal: Const { ty: &usize, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:15 ~ retag[13e7]::array_casts), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                         // + literal: Const { ty: &usize, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:15 ~ retag[317d]::array_casts), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
         Retag(_35);                      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _18 = &(*_35);                   // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         Retag(_18);                      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
diff --git a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
index 8abc6a3e4b5..4bab5a97488 100644
--- a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
@@ -113,7 +113,7 @@ fn main() -> () {
         StorageLive(_14);                // scope 1 at $DIR/retag.rs:40:31: 43:6
         _14 = [closure@main::{closure#0}]; // scope 1 at $DIR/retag.rs:40:31: 43:6
                                          // closure
-                                         // + def_id: DefId(0:14 ~ retag[13e7]::main::{closure#0})
+                                         // + def_id: DefId(0:14 ~ retag[317d]::main::{closure#0})
                                          // + substs: [
                                          //     i8,
                                          //     for<'r> extern "rust-call" fn((&'r i32,)) -> &'r i32,
@@ -153,7 +153,7 @@ fn main() -> () {
                                          // + val: Unevaluated(main, [], Some(promoted[0]))
                                          // mir::Constant
                                          // + span: $DIR/retag.rs:47:21: 47:23
-                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:13 ~ retag[13e7]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+                                         // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:13 ~ retag[317d]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
         Retag(_28);                      // scope 7 at $DIR/retag.rs:47:21: 47:23
         _23 = &(*_28);                   // scope 7 at $DIR/retag.rs:47:21: 47:23
         Retag(_23);                      // scope 7 at $DIR/retag.rs:47:21: 47:23
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async2.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async2.txt
index 322f5681b3f..dc06a485a8f 100644
--- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async2.txt
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.async2.txt
@@ -12,6 +12,7 @@
    12|      1|    if b {
    13|      1|        println!("non_async_func println in block");
    14|      1|    }
+                   ^0
    15|      1|}
    16|       |
    17|       |
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.conditions.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.conditions.txt
index 656a2659775..2d8a98a5d0c 100644
--- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.conditions.txt
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.conditions.txt
@@ -5,6 +5,7 @@
     5|      1|    if true {
     6|      1|        countdown = 10;
     7|      1|    }
+                   ^0
     8|       |
     9|       |    const B: u32 = 100;
    10|      1|    let x = if countdown > 7 {
@@ -24,6 +25,7 @@
    24|      1|    if true {
    25|      1|        countdown = 10;
    26|      1|    }
+                   ^0
    27|       |
    28|      1|    if countdown > 7 {
    29|      1|        countdown -= 4;
@@ -42,6 +44,7 @@
    41|      1|        if true {
    42|      1|            countdown = 10;
    43|      1|        }
+                       ^0
    44|       |
    45|      1|        if countdown > 7 {
    46|      1|            countdown -= 4;
@@ -54,13 +57,14 @@
    53|       |        } else {
    54|      0|            return;
    55|       |        }
-   56|       |    } // Note: closing brace shows uncovered (vs. `0` for implicit else) because condition literal
-   57|       |      // `true` was const-evaluated. The compiler knows the `if` block will be executed.
+   56|      0|    }
+   57|       |
    58|       |
    59|      1|    let mut countdown = 0;
    60|      1|    if true {
    61|      1|        countdown = 1;
    62|      1|    }
+                   ^0
    63|       |
    64|      1|    let z = if countdown > 7 {
                       ^0
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 1b6bb9ff889..7ae0e978808 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
@@ -9,7 +9,7 @@
     8|      1|//!     assert_eq!(1, 1);
     9|       |//! } else {
    10|       |//!     // this is not!
-   11|       |//!     assert_eq!(1, 2);
+   11|      0|//!     assert_eq!(1, 2);
    12|       |//! }
    13|      1|//! ```
    14|       |//!
@@ -84,7 +84,7 @@
    74|      1|    if true {
    75|      1|        assert_eq!(1, 1);
    76|       |    } else {
-   77|       |        assert_eq!(1, 2);
+   77|      0|        assert_eq!(1, 2);
    78|       |    }
    79|      1|}
    80|       |
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.drop_trait.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.drop_trait.txt
index fab5be41901..fe6a9e93cbf 100644
--- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.drop_trait.txt
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.drop_trait.txt
@@ -19,11 +19,11 @@
    19|      1|    if true {
    20|      1|        println!("Exiting with error...");
    21|      1|        return Err(1);
-   22|       |    }
-   23|       |
-   24|       |    let _ = Firework { strength: 1000 };
-   25|       |
-   26|       |    Ok(())
+   22|      0|    }
+   23|      0|
+   24|      0|    let _ = Firework { strength: 1000 };
+   25|      0|
+   26|      0|    Ok(())
    27|      1|}
    28|       |
    29|       |// Expected program output:
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generator.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generator.txt
new file mode 100644
index 00000000000..0fb3808ff2e
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generator.txt
@@ -0,0 +1,32 @@
+    1|       |#![feature(generators, generator_trait)]
+    2|       |
+    3|       |use std::ops::{Generator, GeneratorState};
+    4|       |use std::pin::Pin;
+    5|       |
+    6|       |// The following implementation of a function called from a `yield` statement
+    7|       |// (apparently requiring the Result and the `String` type or constructor)
+    8|       |// creates conditions where the `generator::StateTransform` MIR transform will
+    9|       |// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic
+   10|       |// to handle this condition, and still report dead block coverage.
+   11|      1|fn get_u32(val: bool) -> Result<u32, String> {
+   12|      1|    if val { Ok(1) } else { Err(String::from("some error")) }
+                                          ^0
+   13|      1|}
+   14|       |
+   15|      1|fn main() {
+   16|      1|    let is_true = std::env::args().len() == 1;
+   17|      1|    let mut generator = || {
+   18|      1|        yield get_u32(is_true);
+   19|      1|        return "foo";
+   20|      1|    };
+   21|       |
+   22|      1|    match Pin::new(&mut generator).resume(()) {
+   23|      1|        GeneratorState::Yielded(Ok(1)) => {}
+   24|      0|        _ => panic!("unexpected return from resume"),
+   25|       |    }
+   26|      1|    match Pin::new(&mut generator).resume(()) {
+   27|      1|        GeneratorState::Complete("foo") => {}
+   28|      0|        _ => panic!("unexpected return from resume"),
+   29|       |    }
+   30|      1|}
+
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generics.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generics.txt
index 7b38ffb87cb..8569513e842 100644
--- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generics.txt
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.generics.txt
@@ -11,16 +11,16 @@
    11|      3|        self.strength = new_strength;
    12|      3|    }
   ------------------
-  | <generics::Firework<f64>>::set_strength:
-  |   10|      2|    fn set_strength(&mut self, new_strength: T) {
-  |   11|      2|        self.strength = new_strength;
-  |   12|      2|    }
-  ------------------
   | <generics::Firework<i32>>::set_strength:
   |   10|      1|    fn set_strength(&mut self, new_strength: T) {
   |   11|      1|        self.strength = new_strength;
   |   12|      1|    }
   ------------------
+  | <generics::Firework<f64>>::set_strength:
+  |   10|      2|    fn set_strength(&mut self, new_strength: T) {
+  |   11|      2|        self.strength = new_strength;
+  |   12|      2|    }
+  ------------------
    13|       |}
    14|       |
    15|       |impl<T> Drop for Firework<T> where T: Copy + std::fmt::Display {
@@ -52,15 +52,15 @@
    30|      1|    if true {
    31|      1|        println!("Exiting with error...");
    32|      1|        return Err(1);
-   33|       |    } // The remaining lines below have no coverage because `if true` (with the constant literal
-   34|       |      // `true`) is guaranteed to execute the `then` block, which is also guaranteed to `return`.
-   35|       |      // Thankfully, in the normal case, conditions are not guaranteed ahead of time, and as shown
-   36|       |      // in other tests, the lines below would have coverage (which would show they had `0`
-   37|       |      // executions, assuming the condition still evaluated to `true`).
-   38|       |
-   39|       |    let _ = Firework { strength: 1000 };
-   40|       |
-   41|       |    Ok(())
+   33|      0|    }
+   34|      0|
+   35|      0|
+   36|      0|
+   37|      0|
+   38|      0|
+   39|      0|    let _ = Firework { strength: 1000 };
+   40|      0|
+   41|      0|    Ok(())
    42|      1|}
    43|       |
    44|       |// Expected program output:
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.loops_branches.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.loops_branches.txt
index 81d5c7d9034..5d572db7cc6 100644
--- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.loops_branches.txt
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.loops_branches.txt
@@ -9,23 +9,23 @@
     9|      1|    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
    10|      1|        if true {
    11|      1|            if false {
-   12|       |                while true {
-   13|       |                }
+   12|      0|                while true {
+   13|      0|                }
    14|      1|            }
-   15|      1|            write!(f, "error")?;
-                                            ^0
-   16|       |        } else {
-   17|       |        }
+   15|      1|            write!(f, "cool")?;
+                                           ^0
+   16|      0|        } else {
+   17|      0|        }
    18|       |
    19|     10|        for i in 0..10 {
    20|     10|            if true {
    21|     10|                if false {
-   22|       |                    while true {}
+   22|      0|                    while true {}
    23|     10|                }
-   24|     10|                write!(f, "error")?;
-                                                ^0
-   25|       |            } else {
-   26|       |            }
+   24|     10|                write!(f, "cool")?;
+                                               ^0
+   25|      0|            } else {
+   26|      0|            }
    27|       |        }
    28|      1|        Ok(())
    29|      1|    }
@@ -36,21 +36,21 @@
    34|       |impl std::fmt::Display for DisplayTest {
    35|      1|    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
    36|      1|        if false {
-   37|       |        } else {
+   37|      0|        } else {
    38|      1|            if false {
-   39|       |                while true {}
+   39|      0|                while true {}
    40|      1|            }
-   41|      1|            write!(f, "error")?;
-                                            ^0
+   41|      1|            write!(f, "cool")?;
+                                           ^0
    42|       |        }
    43|     10|        for i in 0..10 {
    44|     10|            if false {
-   45|       |            } else {
+   45|      0|            } else {
    46|     10|                if false {
-   47|       |                    while true {}
+   47|      0|                    while true {}
    48|     10|                }
-   49|     10|                write!(f, "error")?;
-                                                ^0
+   49|     10|                write!(f, "cool")?;
+                                               ^0
    50|       |            }
    51|       |        }
    52|      1|        Ok(())
diff --git a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.tight_inf_loop.txt b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.tight_inf_loop.txt
index 5adeef7d085..2d4c57f451a 100644
--- a/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.tight_inf_loop.txt
+++ b/src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.tight_inf_loop.txt
@@ -1,6 +1,6 @@
     1|      1|fn main() {
     2|      1|    if false {
-    3|       |        loop {}
+    3|      0|        loop {}
     4|      1|    }
     5|      1|}
 
diff --git a/src/test/run-make-fulldeps/coverage/conditions.rs b/src/test/run-make-fulldeps/coverage/conditions.rs
index 8a2a0b53e58..057599d1b47 100644
--- a/src/test/run-make-fulldeps/coverage/conditions.rs
+++ b/src/test/run-make-fulldeps/coverage/conditions.rs
@@ -53,8 +53,8 @@ fn main() {
         } else {
             return;
         }
-    } // Note: closing brace shows uncovered (vs. `0` for implicit else) because condition literal
-      // `true` was const-evaluated. The compiler knows the `if` block will be executed.
+    }
+
 
     let mut countdown = 0;
     if true {
diff --git a/src/test/run-make-fulldeps/coverage/generator.rs b/src/test/run-make-fulldeps/coverage/generator.rs
new file mode 100644
index 00000000000..4319991021e
--- /dev/null
+++ b/src/test/run-make-fulldeps/coverage/generator.rs
@@ -0,0 +1,30 @@
+#![feature(generators, generator_trait)]
+
+use std::ops::{Generator, GeneratorState};
+use std::pin::Pin;
+
+// The following implementation of a function called from a `yield` statement
+// (apparently requiring the Result and the `String` type or constructor)
+// creates conditions where the `generator::StateTransform` MIR transform will
+// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic
+// to handle this condition, and still report dead block coverage.
+fn get_u32(val: bool) -> Result<u32, String> {
+    if val { Ok(1) } else { Err(String::from("some error")) }
+}
+
+fn main() {
+    let is_true = std::env::args().len() == 1;
+    let mut generator = || {
+        yield get_u32(is_true);
+        return "foo";
+    };
+
+    match Pin::new(&mut generator).resume(()) {
+        GeneratorState::Yielded(Ok(1)) => {}
+        _ => panic!("unexpected return from resume"),
+    }
+    match Pin::new(&mut generator).resume(()) {
+        GeneratorState::Complete("foo") => {}
+        _ => panic!("unexpected return from resume"),
+    }
+}
diff --git a/src/test/run-make-fulldeps/coverage/generics.rs b/src/test/run-make-fulldeps/coverage/generics.rs
index cbeda35d3b8..18b38868496 100644
--- a/src/test/run-make-fulldeps/coverage/generics.rs
+++ b/src/test/run-make-fulldeps/coverage/generics.rs
@@ -30,11 +30,11 @@ fn main() -> Result<(),u8> {
     if true {
         println!("Exiting with error...");
         return Err(1);
-    } // The remaining lines below have no coverage because `if true` (with the constant literal
-      // `true`) is guaranteed to execute the `then` block, which is also guaranteed to `return`.
-      // Thankfully, in the normal case, conditions are not guaranteed ahead of time, and as shown
-      // in other tests, the lines below would have coverage (which would show they had `0`
-      // executions, assuming the condition still evaluated to `true`).
+    }
+
+
+
+
 
     let _ = Firework { strength: 1000 };
 
diff --git a/src/test/run-make-fulldeps/coverage/loops_branches.rs b/src/test/run-make-fulldeps/coverage/loops_branches.rs
index 4d9bbad3367..7116ce47f4b 100644
--- a/src/test/run-make-fulldeps/coverage/loops_branches.rs
+++ b/src/test/run-make-fulldeps/coverage/loops_branches.rs
@@ -12,7 +12,7 @@ impl std::fmt::Debug for DebugTest {
                 while true {
                 }
             }
-            write!(f, "error")?;
+            write!(f, "cool")?;
         } else {
         }
 
@@ -21,7 +21,7 @@ impl std::fmt::Debug for DebugTest {
                 if false {
                     while true {}
                 }
-                write!(f, "error")?;
+                write!(f, "cool")?;
             } else {
             }
         }
@@ -38,7 +38,7 @@ impl std::fmt::Display for DisplayTest {
             if false {
                 while true {}
             }
-            write!(f, "error")?;
+            write!(f, "cool")?;
         }
         for i in 0..10 {
             if false {
@@ -46,7 +46,7 @@ impl std::fmt::Display for DisplayTest {
                 if false {
                     while true {}
                 }
-                write!(f, "error")?;
+                write!(f, "cool")?;
             }
         }
         Ok(())
diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
index a9e99d3c10e..443e2df357f 100644
--- a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
+++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
@@ -1,4 +1,5 @@
 #![feature(rustc_private)]
+#![deny(warnings)]
 
 extern crate rustc_codegen_ssa;
 extern crate rustc_errors;
@@ -15,44 +16,28 @@ use rustc_codegen_ssa::back::linker::LinkerInfo;
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_codegen_ssa::{CodegenResults, CrateInfo};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::MetadataRef;
 use rustc_errors::ErrorReported;
-use rustc_middle::dep_graph::DepGraph;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
-use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader, MetadataLoaderDyn};
-use rustc_middle::ty::query::Providers;
+use rustc_middle::middle::cstore::EncodedMetadata;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::OutputFilenames;
 use rustc_session::Session;
-use rustc_target::spec::Target;
 use std::any::Any;
-use std::path::Path;
 
 struct TheBackend;
 
 impl CodegenBackend for TheBackend {
-    fn metadata_loader(&self) -> Box<MetadataLoaderDyn> {
-        Box::new(rustc_codegen_ssa::back::metadata::DefaultMetadataLoader)
-    }
-
-    fn provide(&self, providers: &mut Providers) {}
-    fn provide_extern(&self, providers: &mut Providers) {}
-
     fn codegen_crate<'a, 'tcx>(
         &self,
         tcx: TyCtxt<'tcx>,
         metadata: EncodedMetadata,
         _need_metadata_module: bool,
     ) -> Box<dyn Any> {
-        use rustc_hir::def_id::LOCAL_CRATE;
-
         Box::new(CodegenResults {
-            crate_name: tcx.crate_name(LOCAL_CRATE),
             modules: vec![],
             allocator_module: None,
             metadata_module: None,
             metadata,
-            windows_subsystem: None,
             linker_info: LinkerInfo::new(tcx, "fake_target_cpu".to_string()),
             crate_info: CrateInfo::new(tcx),
         })
@@ -77,7 +62,7 @@ impl CodegenBackend for TheBackend {
     ) -> Result<(), ErrorReported> {
         use rustc_session::{config::CrateType, output::out_filename};
         use std::io::Write;
-        let crate_name = codegen_results.crate_name;
+        let crate_name = codegen_results.crate_info.local_crate_name;
         for &crate_type in sess.opts.crate_types.iter() {
             if crate_type != CrateType::Rlib {
                 sess.fatal(&format!("Crate type is {:?}", crate_type));
diff --git a/src/test/run-make-fulldeps/include_bytes_deps/main.rs b/src/test/run-make-fulldeps/include_bytes_deps/main.rs
index 00ad0eb8d50..2fd55699d44 100644
--- a/src/test/run-make-fulldeps/include_bytes_deps/main.rs
+++ b/src/test/run-make-fulldeps/include_bytes_deps/main.rs
@@ -1,6 +1,4 @@
-#![feature(external_doc)]
-
-#[doc(include="input.md")]
+#[doc = include_str!("input.md")]
 pub struct SomeStruct;
 
 pub fn main() {
diff --git a/src/test/run-make-fulldeps/save-analysis/foo.rs b/src/test/run-make-fulldeps/save-analysis/foo.rs
index 483eeed0b39..dd70675032f 100644
--- a/src/test/run-make-fulldeps/save-analysis/foo.rs
+++ b/src/test/run-make-fulldeps/save-analysis/foo.rs
@@ -2,7 +2,6 @@
 #![feature(box_syntax)]
 #![feature(rustc_private)]
 #![feature(associated_type_defaults)]
-#![feature(external_doc)]
 
 extern crate rustc_graphviz;
 // A simple rust project
@@ -454,9 +453,9 @@ impl Iterator for SilenceGenerator {
     }
 }
 
+#[doc = include_str!("extra-docs.md")]
+struct StructWithDocs;
+
 trait Foo {
     type Bar = FrameBuffer;
 }
-
-#[doc(include = "extra-docs.md")]
-struct StructWithDocs;
diff --git a/src/test/run-make/raw-dylib/Makefile b/src/test/run-make/raw-dylib/Makefile
new file mode 100644
index 00000000000..7ce46fd9331
--- /dev/null
+++ b/src/test/run-make/raw-dylib/Makefile
@@ -0,0 +1,21 @@
+# Test the behavior of #[link(.., kind = "raw-dylib")] on windows-msvc
+
+# only-windows
+# only-msvc
+
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+	$(call COMPILE_OBJ,"$(TMPDIR)"/extern_1.obj,extern_1.c)
+	$(call COMPILE_OBJ,"$(TMPDIR)"/extern_2.obj,extern_2.c)
+	$(CC) "$(TMPDIR)"/extern_1.obj -link -dll -out:"$(TMPDIR)"/extern_1.dll
+	$(CC) "$(TMPDIR)"/extern_2.obj -link -dll -out:"$(TMPDIR)"/extern_2.dll
+	$(RUSTC) --crate-type lib --crate-name raw_dylib_test lib.rs
+	$(RUSTC) --crate-type bin driver.rs -L "$(TMPDIR)"
+	"$(TMPDIR)"/driver > "$(TMPDIR)"/output.txt
+
+ifdef RUSTC_BLESS_TEST
+	cp "$(TMPDIR)"/output.txt output.txt
+else
+	$(DIFF) output.txt "$(TMPDIR)"/output.txt
+endif
diff --git a/src/test/run-make/raw-dylib/driver.rs b/src/test/run-make/raw-dylib/driver.rs
new file mode 100644
index 00000000000..4059ede11fc
--- /dev/null
+++ b/src/test/run-make/raw-dylib/driver.rs
@@ -0,0 +1,5 @@
+extern crate raw_dylib_test;
+
+fn main() {
+    raw_dylib_test::library_function();
+}
diff --git a/src/test/run-make/raw-dylib/extern_1.c b/src/test/run-make/raw-dylib/extern_1.c
new file mode 100644
index 00000000000..72737c086eb
--- /dev/null
+++ b/src/test/run-make/raw-dylib/extern_1.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+__declspec(dllexport) void extern_fn_1() {
+    printf("extern_fn_1\n");
+    fflush(stdout);
+}
+
+__declspec(dllexport) void extern_fn_2() {
+    printf("extern_fn_2; didn't get the rename\n");
+    fflush(stdout);
+}
+
+__declspec(dllexport) void extern_fn_with_long_name() {
+    printf("extern_fn_with_long_name; got the rename\n");
+    fflush(stdout);
+}
diff --git a/src/test/run-make/raw-dylib/extern_2.c b/src/test/run-make/raw-dylib/extern_2.c
new file mode 100644
index 00000000000..ae87fc3f821
--- /dev/null
+++ b/src/test/run-make/raw-dylib/extern_2.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+__declspec(dllexport) void extern_fn_3() {
+    printf("extern_fn_3\n");
+    fflush(stdout);
+}
diff --git a/src/test/run-make/raw-dylib/lib.rs b/src/test/run-make/raw-dylib/lib.rs
new file mode 100644
index 00000000000..d8e6301f38e
--- /dev/null
+++ b/src/test/run-make/raw-dylib/lib.rs
@@ -0,0 +1,22 @@
+#![feature(raw_dylib, native_link_modifiers, native_link_modifiers_verbatim)]
+
+#[link(name = "extern_1.dll", kind = "raw-dylib", modifiers = "+verbatim")]
+extern {
+    fn extern_fn_1();
+}
+
+#[link(name = "extern_2", kind = "raw-dylib")]
+extern {
+    fn extern_fn_3();
+}
+
+pub fn library_function() {
+    #[link(name = "extern_1", kind = "raw-dylib")]
+    extern { fn extern_fn_2(); }
+
+    unsafe {
+        extern_fn_1();
+        extern_fn_2();
+        extern_fn_3();
+    }
+}
diff --git a/src/test/run-make/raw-dylib/output.txt b/src/test/run-make/raw-dylib/output.txt
new file mode 100644
index 00000000000..7800cba1872
--- /dev/null
+++ b/src/test/run-make/raw-dylib/output.txt
@@ -0,0 +1,3 @@
+extern_fn_1
+extern_fn_2; didn't get the rename
+extern_fn_3
diff --git a/src/test/run-make/unstable-flag-required/Makefile b/src/test/run-make/unstable-flag-required/Makefile
index b8769d5f690..aa20d6aa4bf 100644
--- a/src/test/run-make/unstable-flag-required/Makefile
+++ b/src/test/run-make/unstable-flag-required/Makefile
@@ -2,3 +2,4 @@
 
 all:
 	$(RUSTDOC) --output-format=json x.html 2>&1 | diff - output-format-json.stderr
+	$(RUSTC) --force-warns dead_code x.rs 2>&1 | diff - force-warns.stderr
diff --git a/src/test/run-make/unstable-flag-required/force-warns.stderr b/src/test/run-make/unstable-flag-required/force-warns.stderr
new file mode 100644
index 00000000000..e0936196a11
--- /dev/null
+++ b/src/test/run-make/unstable-flag-required/force-warns.stderr
@@ -0,0 +1,2 @@
+error: the `-Z unstable-options` flag must also be passed to enable the flag `--force-warns=lints`
+
diff --git a/src/test/rustdoc-gui/search-result-description.goml b/src/test/rustdoc-gui/search-result-description.goml
new file mode 100644
index 00000000000..a50d03cf489
--- /dev/null
+++ b/src/test/rustdoc-gui/search-result-description.goml
@@ -0,0 +1,5 @@
+// This test is to ensure that the codeblocks are correctly rendered in the search results.
+goto: file://|DOC_PATH|/test_docs/index.html?search=some_more_function
+// Waiting for the search results to appear...
+wait-for: "#titles"
+assert: (".search-results .desc code", "format!")
diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml
new file mode 100644
index 00000000000..7703677154e
--- /dev/null
+++ b/src/test/rustdoc-gui/sidebar.goml
@@ -0,0 +1,57 @@
+goto: file://|DOC_PATH|/test_docs/index.html
+assert: (".sidebar > .location", "Crate test_docs")
+// In modules, we only have one "location" element.
+assert: (".sidebar .location", 1)
+assert: (".sidebar-elems > #all-types", "See all test_docs's items")
+// We check that we have the crates list and that the "current" on is "test_docs".
+assert: (".sidebar-elems > .crate > ul > li > a.current", "test_docs")
+// And we're also supposed to have the list of items in the current module.
+assert: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
+assert: (".sidebar-elems > .items > ul > li:nth-child(2)", "Structs")
+assert: (".sidebar-elems > .items > ul > li:nth-child(3)", "Enums")
+assert: (".sidebar-elems > .items > ul > li:nth-child(4)", "Traits")
+assert: (".sidebar-elems > .items > ul > li:nth-child(5)", "Functions")
+assert: (".sidebar-elems > .items > ul > li:nth-child(6)", "Type Definitions")
+assert: (".sidebar-elems > .items > ul > li:nth-child(7)", "Keywords")
+assert: ("#structs + table td > a", "Foo")
+click: "#structs + table td > a"
+
+// PAGE: struct.Foo.html
+assert: (".sidebar .location", 2)
+// We check that there is no crate listed outside of the top level.
+assert-false: ".sidebar-elems > .crate"
+// We now go back to the crate page to click on the "lib2" crate link.
+goto: file://|DOC_PATH|/test_docs/index.html
+click: ".sidebar-elems > .crate > ul > li:first-child > a"
+
+// PAGE: lib2/index.html
+goto: file://|DOC_PATH|/lib2/index.html
+assert: (".sidebar > .location", "Crate lib2")
+// We check that we have the crates list and that the "current" on is now "lib2".
+assert: (".sidebar-elems > .crate > ul > li > a.current", "lib2")
+// We now go to the "foobar" function page.
+assert: (".sidebar-elems > .items > ul > li:nth-child(1)", "Modules")
+assert: (".sidebar-elems > .items > ul > li:nth-child(2)", "Functions")
+assert:	("#functions + table td > a", "foobar")
+click: "#functions + table td > a"
+
+// PAGE: fn.foobar.html
+// In items containing no items (like functions or constants) and in modules, we have one
+// "location" elements.
+assert: (".sidebar .location", 1)
+// There is a "<br>" tag between "in" and "lib2", but it doesn't count as a space.
+assert: (".sidebar .sidebar-elems .location", "Other items inlib2")
+// We check that we don't have the crate list.
+assert-false: ".sidebar-elems > .crate"
+
+goto: ./module/index.html
+assert: (".sidebar > .location", "Module module")
+// We check that we don't have the crate list.
+assert-false: ".sidebar-elems > .crate"
+
+goto: ./sub_module/sub_sub_module/index.html
+assert: (".sidebar > .location", "Module sub_sub_module")
+// We check that we don't have the crate list.
+assert-false: ".sidebar-elems > .crate"
+assert: (".sidebar-elems > .items > ul > li:nth-child(1)", "Functions")
+assert: ("#functions + table td > a", "foo")
diff --git a/src/test/rustdoc-gui/src/lib.rs b/src/test/rustdoc-gui/src/lib.rs
index 272b1d05452..5141b6d1920 100644
--- a/src/test/rustdoc-gui/src/lib.rs
+++ b/src/test/rustdoc-gui/src/lib.rs
@@ -96,3 +96,6 @@ pub enum AnEnum {
 
 #[doc(keyword = "CookieMonster")]
 pub mod keyword {}
+
+/// Just some type alias.
+pub type SomeType = u32;
diff --git a/src/test/rustdoc-gui/src/lib2.rs b/src/test/rustdoc-gui/src/lib2.rs
new file mode 100644
index 00000000000..73384cbf906
--- /dev/null
+++ b/src/test/rustdoc-gui/src/lib2.rs
@@ -0,0 +1,11 @@
+pub mod module {
+    pub mod sub_module {
+        pub mod sub_sub_module {
+            pub fn foo() {}
+        }
+        pub fn bar() {}
+    }
+    pub fn whatever() {}
+}
+
+pub fn foobar() {}
diff --git a/src/test/rustdoc-gui/type-weight.rs b/src/test/rustdoc-gui/type-weight.rs
new file mode 100644
index 00000000000..8b6518e7f31
--- /dev/null
+++ b/src/test/rustdoc-gui/type-weight.rs
@@ -0,0 +1,2 @@
+goto: file://|DOC_PATH|/test_docs/type.SomeType.html
+assert-all: (".top-block .docblock p", {"font-weight": "400"})
diff --git a/src/test/rustdoc-ui/check.rs b/src/test/rustdoc-ui/check.rs
index 65a56e03d9d..2b44ba24b44 100644
--- a/src/test/rustdoc-ui/check.rs
+++ b/src/test/rustdoc-ui/check.rs
@@ -1,5 +1,6 @@
 // check-pass
 // compile-flags: -Z unstable-options --check
+// normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
 
 #![warn(missing_docs)]
 //~^ WARN
diff --git a/src/test/rustdoc-ui/check.stderr b/src/test/rustdoc-ui/check.stderr
index 2e1fc1eca4d..8c9e70e57fe 100644
--- a/src/test/rustdoc-ui/check.stderr
+++ b/src/test/rustdoc-ui/check.stderr
@@ -1,5 +1,5 @@
 warning: missing documentation for the crate
-  --> $DIR/check.rs:4:1
+  --> $DIR/check.rs:5:1
    |
 LL | / #![warn(missing_docs)]
 LL | |
@@ -10,13 +10,13 @@ LL | | pub fn foo() {}
    | |_______________^
    |
 note: the lint level is defined here
-  --> $DIR/check.rs:4:9
+  --> $DIR/check.rs:5:9
    |
 LL | #![warn(missing_docs)]
    |         ^^^^^^^^^^^^
 
 warning: missing documentation for a function
-  --> $DIR/check.rs:9:1
+  --> $DIR/check.rs:10:1
    |
 LL | pub fn foo() {}
    | ^^^^^^^^^^^^
@@ -24,16 +24,16 @@ LL | pub fn foo() {}
 warning: no documentation found for this crate's top-level module
    |
 note: the lint level is defined here
-  --> $DIR/check.rs:7:9
+  --> $DIR/check.rs:8:9
    |
 LL | #![warn(rustdoc::all)]
    |         ^^^^^^^^^^^^
    = note: `#[warn(rustdoc::missing_crate_level_docs)]` implied by `#[warn(rustdoc::all)]`
    = help: The following guide may be of use:
-           https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html
+           https://doc.rust-lang.org/$CHANNEL/rustdoc/how-to-write-documentation.html
 
 warning: missing code example in this documentation
-  --> $DIR/check.rs:4:1
+  --> $DIR/check.rs:5:1
    |
 LL | / #![warn(missing_docs)]
 LL | |
@@ -44,14 +44,14 @@ LL | | pub fn foo() {}
    | |_______________^
    |
 note: the lint level is defined here
-  --> $DIR/check.rs:7:9
+  --> $DIR/check.rs:8:9
    |
 LL | #![warn(rustdoc::all)]
    |         ^^^^^^^^^^^^
    = note: `#[warn(rustdoc::missing_doc_code_examples)]` implied by `#[warn(rustdoc::all)]`
 
 warning: missing code example in this documentation
-  --> $DIR/check.rs:9:1
+  --> $DIR/check.rs:10:1
    |
 LL | pub fn foo() {}
    | ^^^^^^^^^^^^^^^
diff --git a/src/test/rustdoc-ui/doc-include-suggestion.rs b/src/test/rustdoc-ui/doc-include-suggestion.rs
new file mode 100644
index 00000000000..0c010073551
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-include-suggestion.rs
@@ -0,0 +1,10 @@
+// check-pass
+
+#[doc(include = "external-cross-doc.md")]
+//~^ WARNING unknown `doc` attribute `include`
+//~| HELP use `doc = include_str!` instead
+// FIXME(#85497): make this a deny instead so it's more clear what's happening
+//~| NOTE on by default
+//~| WARNING previously accepted
+//~| NOTE see issue #82730
+pub struct NeedMoreDocs;
diff --git a/src/test/rustdoc-ui/doc-include-suggestion.stderr b/src/test/rustdoc-ui/doc-include-suggestion.stderr
new file mode 100644
index 00000000000..870b7efa2ac
--- /dev/null
+++ b/src/test/rustdoc-ui/doc-include-suggestion.stderr
@@ -0,0 +1,12 @@
+warning: unknown `doc` attribute `include`
+  --> $DIR/doc-include-suggestion.rs:3:7
+   |
+LL | #[doc(include = "external-cross-doc.md")]
+   | ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- help: use `doc = include_str!` instead: `#[doc = include_str!("external-cross-doc.md")]`
+   |
+   = note: `#[warn(invalid_doc_attributes)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+warning: 1 warning emitted
+
diff --git a/src/test/rustdoc-ui/doc-spotlight.fixed b/src/test/rustdoc-ui/doc-spotlight.fixed
index 94b69a99879..4b58778eacd 100644
--- a/src/test/rustdoc-ui/doc-spotlight.fixed
+++ b/src/test/rustdoc-ui/doc-spotlight.fixed
@@ -1,9 +1,8 @@
-// check-pass
 // run-rustfix
-
+#![deny(warnings)]
 #![feature(doc_notable_trait)]
 
 #[doc(notable_trait)]
-//~^ WARN unknown `doc` attribute `spotlight`
+//~^ ERROR unknown `doc` attribute `spotlight`
 //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 trait MyTrait {}
diff --git a/src/test/rustdoc-ui/doc-spotlight.rs b/src/test/rustdoc-ui/doc-spotlight.rs
index cc5f159a809..16e38724580 100644
--- a/src/test/rustdoc-ui/doc-spotlight.rs
+++ b/src/test/rustdoc-ui/doc-spotlight.rs
@@ -1,9 +1,8 @@
-// check-pass
 // run-rustfix
-
+#![deny(warnings)]
 #![feature(doc_notable_trait)]
 
 #[doc(spotlight)]
-//~^ WARN unknown `doc` attribute `spotlight`
+//~^ ERROR unknown `doc` attribute `spotlight`
 //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 trait MyTrait {}
diff --git a/src/test/rustdoc-ui/doc-spotlight.stderr b/src/test/rustdoc-ui/doc-spotlight.stderr
index e5fa6293f3d..8e7831139a8 100644
--- a/src/test/rustdoc-ui/doc-spotlight.stderr
+++ b/src/test/rustdoc-ui/doc-spotlight.stderr
@@ -1,14 +1,19 @@
-warning: unknown `doc` attribute `spotlight`
-  --> $DIR/doc-spotlight.rs:6:7
+error: unknown `doc` attribute `spotlight`
+  --> $DIR/doc-spotlight.rs:5:7
    |
 LL | #[doc(spotlight)]
    |       ^^^^^^^^^ help: use `notable_trait` instead
    |
-   = note: `#[warn(invalid_doc_attributes)]` on by default
+note: the lint level is defined here
+  --> $DIR/doc-spotlight.rs:2:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
    = note: `doc(spotlight)` was renamed to `doc(notable_trait)`
    = note: `doc(spotlight)` is now a no-op
 
-warning: 1 warning emitted
+error: aborting due to previous error
 
diff --git a/src/test/rustdoc-ui/failed-doctest-compile-fail.stdout b/src/test/rustdoc-ui/failed-doctest-compile-fail.stdout
index b8bb5ccb403..af3a90a7410 100644
--- a/src/test/rustdoc-ui/failed-doctest-compile-fail.stdout
+++ b/src/test/rustdoc-ui/failed-doctest-compile-fail.stdout
@@ -1,6 +1,6 @@
 
 running 1 test
-test $DIR/failed-doctest-compile-fail.rs - Foo (line 9) ... FAILED
+test $DIR/failed-doctest-compile-fail.rs - Foo (line 9) - compile fail ... FAILED
 
 failures:
 
diff --git a/src/test/rustdoc-ui/failed-doctest-missing-codes.stdout b/src/test/rustdoc-ui/failed-doctest-missing-codes.stdout
index 7367a7d6519..bacbb47b5f9 100644
--- a/src/test/rustdoc-ui/failed-doctest-missing-codes.stdout
+++ b/src/test/rustdoc-ui/failed-doctest-missing-codes.stdout
@@ -1,6 +1,6 @@
 
 running 1 test
-test $DIR/failed-doctest-missing-codes.rs - Foo (line 9) ... FAILED
+test $DIR/failed-doctest-missing-codes.rs - Foo (line 9) - compile fail ... FAILED
 
 failures:
 
diff --git a/src/test/rustdoc-ui/intra-doc/email-address-localhost.rs b/src/test/rustdoc-ui/intra-doc/email-address-localhost.rs
index 417618c7458..9465e8e7ab9 100644
--- a/src/test/rustdoc-ui/intra-doc/email-address-localhost.rs
+++ b/src/test/rustdoc-ui/intra-doc/email-address-localhost.rs
@@ -1,3 +1,4 @@
+// normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
 #![deny(warnings)]
 
 //! Email me at <hello@localhost>.
diff --git a/src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr b/src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr
index f287f87408c..1b07828fc6e 100644
--- a/src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr
+++ b/src/test/rustdoc-ui/intra-doc/email-address-localhost.stderr
@@ -1,16 +1,16 @@
 error: unknown disambiguator `hello`
-  --> $DIR/email-address-localhost.rs:3:18
+  --> $DIR/email-address-localhost.rs:4:18
    |
 LL | //! Email me at <hello@localhost>.
    |                  ^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/email-address-localhost.rs:1:9
+  --> $DIR/email-address-localhost.rs:2:9
    |
 LL | #![deny(warnings)]
    |         ^^^^^^^^
    = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: aborting due to previous error
 
diff --git a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs
index 925fc515a3e..0aa1e5a415a 100644
--- a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs
+++ b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.rs
@@ -1,3 +1,4 @@
+// normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
 #![deny(warnings)]
 
 //! Linking to [foo@banana] and [`bar@banana!()`].
diff --git a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
index 94d6d461651..d280e6497e0 100644
--- a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
+++ b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
@@ -1,56 +1,56 @@
 error: unknown disambiguator `foo`
-  --> $DIR/unknown-disambiguator.rs:3:17
+  --> $DIR/unknown-disambiguator.rs:4:17
    |
 LL | //! Linking to [foo@banana] and [`bar@banana!()`].
    |                 ^^^
    |
 note: the lint level is defined here
-  --> $DIR/unknown-disambiguator.rs:1:9
+  --> $DIR/unknown-disambiguator.rs:2:9
    |
 LL | #![deny(warnings)]
    |         ^^^^^^^^
    = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: unknown disambiguator `bar`
-  --> $DIR/unknown-disambiguator.rs:3:35
+  --> $DIR/unknown-disambiguator.rs:4:35
    |
 LL | //! Linking to [foo@banana] and [`bar@banana!()`].
    |                                   ^^^
    |
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: unknown disambiguator `foo`
-  --> $DIR/unknown-disambiguator.rs:9:34
+  --> $DIR/unknown-disambiguator.rs:10:34
    |
 LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello].
    |                                  ^^^
    |
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: unknown disambiguator `foo`
-  --> $DIR/unknown-disambiguator.rs:9:48
+  --> $DIR/unknown-disambiguator.rs:10:48
    |
 LL | //! And with weird backticks: [``foo@hello``] [foo`@`hello].
    |                                                ^^^
    |
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: unknown disambiguator ``
-  --> $DIR/unknown-disambiguator.rs:6:31
+  --> $DIR/unknown-disambiguator.rs:7:31
    |
 LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()).
    |                               ^
    |
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: unknown disambiguator ``
-  --> $DIR/unknown-disambiguator.rs:6:57
+  --> $DIR/unknown-disambiguator.rs:7:57
    |
 LL | //! And to [no disambiguator](@nectarine) and [another](@apricot!()).
    |                                                         ^
    |
-   = note: see https://doc.rust-lang.org/nightly/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
+   = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/rustdoc-ui/issue-80992.stdout b/src/test/rustdoc-ui/issue-80992.stdout
index 1dd19f46827..d2b1cd1d550 100644
--- a/src/test/rustdoc-ui/issue-80992.stdout
+++ b/src/test/rustdoc-ui/issue-80992.stdout
@@ -1,6 +1,6 @@
 
 running 1 test
-test $DIR/issue-80992.rs - test (line 7) ... ok
+test $DIR/issue-80992.rs - test (line 7) - compile fail ... ok
 
 test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
 
diff --git a/src/test/rustdoc-ui/no-crate-level-doc-lint.rs b/src/test/rustdoc-ui/no-crate-level-doc-lint.rs
index 3939ec6827a..a186410acf4 100644
--- a/src/test/rustdoc-ui/no-crate-level-doc-lint.rs
+++ b/src/test/rustdoc-ui/no-crate-level-doc-lint.rs
@@ -1,4 +1,5 @@
 // error-pattern: no documentation found
+// normalize-stderr-test: "nightly|beta|1\.[0-9][0-9]\.[0-9]" -> "$$CHANNEL"
 #![deny(rustdoc::missing_crate_level_docs)]
 //^~ NOTE defined here
 
diff --git a/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr b/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr
index 55ead1a55cf..1a1f8085a1b 100644
--- a/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr
+++ b/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr
@@ -1,12 +1,12 @@
 error: no documentation found for this crate's top-level module
    |
 note: the lint level is defined here
-  --> $DIR/no-crate-level-doc-lint.rs:2:9
+  --> $DIR/no-crate-level-doc-lint.rs:3:9
    |
 LL | #![deny(rustdoc::missing_crate_level_docs)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: The following guide may be of use:
-           https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html
+           https://doc.rust-lang.org/$CHANNEL/rustdoc/how-to-write-documentation.html
 
 error: aborting due to previous error
 
diff --git a/src/test/rustdoc-ui/no-run-flag.stdout b/src/test/rustdoc-ui/no-run-flag.stdout
index d92f5da8335..02f28aaf60d 100644
--- a/src/test/rustdoc-ui/no-run-flag.stdout
+++ b/src/test/rustdoc-ui/no-run-flag.stdout
@@ -1,12 +1,12 @@
 
 running 7 tests
-test $DIR/no-run-flag.rs - f (line 11) ... ok
+test $DIR/no-run-flag.rs - f (line 11) - compile ... ok
 test $DIR/no-run-flag.rs - f (line 14) ... ignored
-test $DIR/no-run-flag.rs - f (line 17) ... ok
-test $DIR/no-run-flag.rs - f (line 23) ... ok
-test $DIR/no-run-flag.rs - f (line 28) ... ok
-test $DIR/no-run-flag.rs - f (line 32) ... ok
-test $DIR/no-run-flag.rs - f (line 8) ... ok
+test $DIR/no-run-flag.rs - f (line 17) - compile ... ok
+test $DIR/no-run-flag.rs - f (line 23) - compile fail ... ok
+test $DIR/no-run-flag.rs - f (line 28) - compile ... ok
+test $DIR/no-run-flag.rs - f (line 32) - compile ... ok
+test $DIR/no-run-flag.rs - f (line 8) - compile ... ok
 
 test result: ok. 6 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in $TIME
 
diff --git a/src/test/rustdoc-ui/test-type.rs b/src/test/rustdoc-ui/test-type.rs
new file mode 100644
index 00000000000..882da5c2503
--- /dev/null
+++ b/src/test/rustdoc-ui/test-type.rs
@@ -0,0 +1,26 @@
+// compile-flags: --test --test-args=--test-threads=1
+// check-pass
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```
+/// let a = true;
+/// ```
+/// ```should_panic
+/// panic!()
+/// ```
+/// ```ignore (incomplete-code)
+/// fn foo() {
+/// ```
+/// ```no_run
+/// loop {
+///     println!("Hello, world");
+/// }
+/// ```
+/// fails to compile
+/// ```compile_fail
+/// let x = 5;
+/// x += 2; // shouldn't compile!
+/// ```
+
+pub fn f() {}
diff --git a/src/test/rustdoc-ui/test-type.stdout b/src/test/rustdoc-ui/test-type.stdout
new file mode 100644
index 00000000000..a66fd240d34
--- /dev/null
+++ b/src/test/rustdoc-ui/test-type.stdout
@@ -0,0 +1,10 @@
+
+running 5 tests
+test $DIR/test-type.rs - f (line 12) ... ignored
+test $DIR/test-type.rs - f (line 15) - compile ... ok
+test $DIR/test-type.rs - f (line 21) - compile fail ... ok
+test $DIR/test-type.rs - f (line 6) ... ok
+test $DIR/test-type.rs - f (line 9) ... ok
+
+test result: ok. 4 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/wasm-safe.rs b/src/test/rustdoc-ui/wasm-safe.rs
new file mode 100644
index 00000000000..80b15ace0ee
--- /dev/null
+++ b/src/test/rustdoc-ui/wasm-safe.rs
@@ -0,0 +1,7 @@
+// check-pass
+
+#![feature(wasm_target_feature)]
+
+#[cfg(any(target_arch = "wasm32", doc))]
+#[target_feature(enable = "simd128")]
+pub fn foo() {}
diff --git a/src/test/rustdoc/async-fn.rs b/src/test/rustdoc/async-fn.rs
index 4b66b5271c5..9f95d9a994b 100644
--- a/src/test/rustdoc/async-fn.rs
+++ b/src/test/rustdoc/async-fn.rs
@@ -77,12 +77,12 @@ struct AsyncFdReadyGuard<'a, T> { x: &'a T }
 
 impl Foo {
     // @has async_fn/struct.Foo.html
-    // @has - '//h4[@class="method"]' 'pub async fn complicated_lifetimes( &self, context: &impl Bar) -> impl Iterator<Item = &usize>'
+    // @has - '//div[@class="method has-srclink"]' 'pub async fn complicated_lifetimes( &self, context: &impl Bar) -> impl Iterator<Item = &usize>'
     pub async fn complicated_lifetimes(&self, context: &impl Bar) -> impl Iterator<Item = &usize> {}
     // taken from `tokio` as an example of a method that was particularly bad before
-    // @has - '//h4[@class="method"]' "pub async fn readable<T>(&self) -> Result<AsyncFdReadyGuard<'_, T>, ()>"
+    // @has - '//div[@class="method has-srclink"]' "pub async fn readable<T>(&self) -> Result<AsyncFdReadyGuard<'_, T>, ()>"
     pub async fn readable<T>(&self) -> Result<AsyncFdReadyGuard<'_, T>, ()> {}
-    // @has - '//h4[@class="method"]' "pub async fn mut_self(&mut self)"
+    // @has - '//div[@class="method has-srclink"]' "pub async fn mut_self(&mut self)"
     pub async fn mut_self(&mut self) {}
 }
 
diff --git a/src/test/rustdoc/auto_aliases.rs b/src/test/rustdoc/auto_aliases.rs
index 56e0770ab5c..01ea09a9461 100644
--- a/src/test/rustdoc/auto_aliases.rs
+++ b/src/test/rustdoc/auto_aliases.rs
@@ -1,6 +1,6 @@
 #![feature(auto_traits)]
 
-// @has auto_aliases/trait.Bar.html '//h3[@data-aliases="auto_aliases::Foo"]' 'impl Bar for Foo'
+// @has auto_aliases/trait.Bar.html '//div[@data-aliases="auto_aliases::Foo"]' 'impl Bar for Foo'
 pub struct Foo;
 
 pub auto trait Bar {}
diff --git a/src/test/rustdoc/auxiliary/external-cross-doc.md b/src/test/rustdoc/auxiliary/external-cross-doc.md
index 8b4e6edc699..d3c85326559 100644
--- a/src/test/rustdoc/auxiliary/external-cross-doc.md
+++ b/src/test/rustdoc/auxiliary/external-cross-doc.md
@@ -1,4 +1,4 @@
 # Cross-crate imported docs
 
-This file is to make sure `#[doc(include="file.md")]` works when you re-export an item with included
+This file is to make sure `#[doc = include_str!("file.md")]` works when you re-export an item with included
 docs.
diff --git a/src/test/rustdoc/auxiliary/external-cross.rs b/src/test/rustdoc/auxiliary/external-cross.rs
index 473d4ec99f0..5de63cdabc6 100644
--- a/src/test/rustdoc/auxiliary/external-cross.rs
+++ b/src/test/rustdoc/auxiliary/external-cross.rs
@@ -1,5 +1,3 @@
-#![feature(external_doc)]
-#![deny(missing_doc)]
-
-#[doc(include="external-cross-doc.md")]
+#[deny(missing_docs)]
+#[doc = include_str!("external-cross-doc.md")]
 pub struct NeedMoreDocs;
diff --git a/src/test/rustdoc/auxiliary/external-doc.md b/src/test/rustdoc/auxiliary/external-doc.md
index 38478c1635a..babde0a05ad 100644
--- a/src/test/rustdoc/auxiliary/external-doc.md
+++ b/src/test/rustdoc/auxiliary/external-doc.md
@@ -1,3 +1,3 @@
 # External Docs
 
-This file is here to test the `#[doc(include="file")]` attribute.
+This file is here to test the `#[doc = include_str!("file")]` attribute.
diff --git a/src/test/rustdoc/blanket-reexport-item.rs b/src/test/rustdoc/blanket-reexport-item.rs
index f247ee637b9..6f0c15cb5ac 100644
--- a/src/test/rustdoc/blanket-reexport-item.rs
+++ b/src/test/rustdoc/blanket-reexport-item.rs
@@ -1,6 +1,6 @@
 #![crate_name = "foo"]
 
-// @has foo/struct.S.html '//h3[@id="impl-Into%3CU%3E"]//code' 'impl<T, U> Into<U> for T'
+// @has foo/struct.S.html '//div[@id="impl-Into%3CU%3E"]//code' 'impl<T, U> Into<U> for T'
 pub struct S2 {}
 mod m {
     pub struct S {}
diff --git a/src/test/rustdoc/const-display.rs b/src/test/rustdoc/const-display.rs
index fb5c8517f6c..2761f92ef57 100644
--- a/src/test/rustdoc/const-display.rs
+++ b/src/test/rustdoc/const-display.rs
@@ -38,12 +38,12 @@ pub const unsafe fn bar_not_gated() -> u32 { 42 }
 pub struct Foo;
 
 impl Foo {
-    // @has 'foo/struct.Foo.html' '//h4[@id="method.gated"]/code' 'pub unsafe fn gated() -> u32'
+    // @has 'foo/struct.Foo.html' '//div[@id="method.gated"]/code' 'pub unsafe fn gated() -> u32'
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature="foo", issue = "none")]
     pub const unsafe fn gated() -> u32 { 42 }
 
-    // @has 'foo/struct.Foo.html' '//h4[@id="method.stable_impl"]/code' 'pub const fn stable_impl() -> u32'
+    // @has 'foo/struct.Foo.html' '//div[@id="method.stable_impl"]/code' 'pub const fn stable_impl() -> u32'
     // @has - '//span[@class="since"]' '1.0.0 (const: 1.2.0)'
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "rust1", since = "1.2.0")]
diff --git a/src/test/rustdoc/const-fn.rs b/src/test/rustdoc/const-fn.rs
index 9ea7343e075..28eba849ace 100644
--- a/src/test/rustdoc/const-fn.rs
+++ b/src/test/rustdoc/const-fn.rs
@@ -8,7 +8,7 @@ pub const fn bar() -> usize {
 }
 
 // @has foo/struct.Foo.html
-// @has - '//*[@class="method"]' 'const fn new()'
+// @has - '//*[@class="method has-srclink"]' 'const fn new()'
 pub struct Foo(usize);
 
 impl Foo {
diff --git a/src/test/rustdoc/const-generics/add-impl.rs b/src/test/rustdoc/const-generics/add-impl.rs
index 77432ba1539..8f412aa8c40 100644
--- a/src/test/rustdoc/const-generics/add-impl.rs
+++ b/src/test/rustdoc/const-generics/add-impl.rs
@@ -8,7 +8,7 @@ pub struct Simd<T, const WIDTH: usize> {
     inner: T,
 }
 
-// @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]//h3/code' 'impl Add<Simd<u8, 16_usize>> for Simd<u8, 16>'
+// @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]//div/code' 'impl Add<Simd<u8, 16_usize>> for Simd<u8, 16>'
 impl Add for Simd<u8, 16> {
     type Output = Self;
 
diff --git a/src/test/rustdoc/const-generics/const-generic-defaults.rs b/src/test/rustdoc/const-generics/const-generic-defaults.rs
new file mode 100644
index 00000000000..efe35bf7aa4
--- /dev/null
+++ b/src/test/rustdoc/const-generics/const-generic-defaults.rs
@@ -0,0 +1,6 @@
+#![crate_name = "foo"]
+#![feature(const_generics_defaults)]
+
+// @has foo/struct.Foo.html '//pre[@class="rust struct"]' \
+//      'pub struct Foo<const M: usize = 10_usize, const N: usize = M, T = i32>(_);'
+pub struct Foo<const M: usize = 10, const N: usize = M, T = i32>(T);
diff --git a/src/test/rustdoc/const-generics/const-generic-slice.rs b/src/test/rustdoc/const-generics/const-generic-slice.rs
index 60d96770f7e..626a9e2b210 100644
--- a/src/test/rustdoc/const-generics/const-generic-slice.rs
+++ b/src/test/rustdoc/const-generics/const-generic-slice.rs
@@ -6,7 +6,7 @@ pub trait Array {
 }
 
 // @has foo/trait.Array.html
-// @has - '//h3[@class="impl"]' 'impl<T, const N: usize> Array for [T; N]'
+// @has - '//div[@class="impl has-srclink"]' 'impl<T, const N: usize> Array for [T; N]'
 impl <T, const N: usize> Array for [T; N] {
     type Item = T;
 }
diff --git a/src/test/rustdoc/const-generics/const-generics-docs.rs b/src/test/rustdoc/const-generics/const-generics-docs.rs
index 21bf216c304..7c4c70432c7 100644
--- a/src/test/rustdoc/const-generics/const-generics-docs.rs
+++ b/src/test/rustdoc/const-generics/const-generics-docs.rs
@@ -36,7 +36,7 @@ pub struct Foo<const N: usize> where u8: Trait<N>;
 // @has foo/struct.Bar.html '//pre[@class="rust struct"]' 'pub struct Bar<T, const N: usize>(_)'
 pub struct Bar<T, const N: usize>([T; N]);
 
-// @has foo/struct.Foo.html '//h3[@id="impl"]/code' 'impl<const M: usize> Foo<M> where u8: Trait<M>'
+// @has foo/struct.Foo.html '//div[@id="impl"]/code' 'impl<const M: usize> Foo<M> where u8: Trait<M>'
 impl<const M: usize> Foo<M> where u8: Trait<M> {
     // @has - '//*[@id="associatedconstant.FOO_ASSOC"]' 'pub const FOO_ASSOC: usize'
     pub const FOO_ASSOC: usize = M + 13;
@@ -47,7 +47,7 @@ impl<const M: usize> Foo<M> where u8: Trait<M> {
     }
 }
 
-// @has foo/struct.Bar.html '//h3[@id="impl"]/code' 'impl<const M: usize> Bar<u8, M>'
+// @has foo/struct.Bar.html '//div[@id="impl"]/code' 'impl<const M: usize> Bar<u8, M>'
 impl<const M: usize> Bar<u8, M> {
     // @has - '//*[@id="method.hey"]' \
     //      'pub fn hey<const N: usize>(&self) -> Foo<N> where u8: Trait<N>'
diff --git a/src/test/rustdoc/const-generics/const-impl.rs b/src/test/rustdoc/const-generics/const-impl.rs
index 04fb3395333..e4e504dd83b 100644
--- a/src/test/rustdoc/const-generics/const-impl.rs
+++ b/src/test/rustdoc/const-generics/const-impl.rs
@@ -9,20 +9,20 @@ pub enum Order {
 }
 
 // @has foo/struct.VSet.html '//pre[@class="rust struct"]' 'pub struct VSet<T, const ORDER: Order>'
-// @has foo/struct.VSet.html '//h3[@id="impl-Send"]/code' 'impl<T, const ORDER: Order> Send for VSet<T, ORDER>'
-// @has foo/struct.VSet.html '//h3[@id="impl-Sync"]/code' 'impl<T, const ORDER: Order> Sync for VSet<T, ORDER>'
+// @has foo/struct.VSet.html '//div[@id="impl-Send"]/code' 'impl<T, const ORDER: Order> Send for VSet<T, ORDER>'
+// @has foo/struct.VSet.html '//div[@id="impl-Sync"]/code' 'impl<T, const ORDER: Order> Sync for VSet<T, ORDER>'
 pub struct VSet<T, const ORDER: Order> {
     inner: Vec<T>,
 }
 
-// @has foo/struct.VSet.html '//h3[@id="impl"]/code' 'impl<T> VSet<T, {Order::Sorted}>'
+// @has foo/struct.VSet.html '//div[@id="impl"]/code' 'impl<T> VSet<T, {Order::Sorted}>'
 impl <T> VSet<T, {Order::Sorted}> {
     pub fn new() -> Self {
         Self { inner: Vec::new() }
     }
 }
 
-// @has foo/struct.VSet.html '//h3[@id="impl-1"]/code' 'impl<T> VSet<T, {Order::Unsorted}>'
+// @has foo/struct.VSet.html '//div[@id="impl-1"]/code' 'impl<T> VSet<T, {Order::Unsorted}>'
 impl <T> VSet<T, {Order::Unsorted}> {
     pub fn new() -> Self {
         Self { inner: Vec::new() }
@@ -31,7 +31,7 @@ impl <T> VSet<T, {Order::Unsorted}> {
 
 pub struct Escape<const S: &'static str>;
 
-// @has foo/struct.Escape.html '//h3[@id="impl"]/code' 'impl Escape<{ r#"<script>alert("Escape");</script>"# }>'
+// @has foo/struct.Escape.html '//div[@id="impl"]/code' 'impl Escape<{ r#"<script>alert("Escape");</script>"# }>'
 impl Escape<{ r#"<script>alert("Escape");</script>"# }> {
     pub fn f() {}
 }
diff --git a/src/test/rustdoc/doc-assoc-item.rs b/src/test/rustdoc/doc-assoc-item.rs
index 4d5c9f83e1e..4f15418650c 100644
--- a/src/test/rustdoc/doc-assoc-item.rs
+++ b/src/test/rustdoc/doc-assoc-item.rs
@@ -8,7 +8,7 @@ pub trait Bar {
     fn foo(foo: Self::Fuu);
 }
 
-// @has doc_assoc_item/struct.Foo.html '//*[@class="impl"]' 'impl<T: Bar<Fuu = u32>> Foo<T>'
+// @has doc_assoc_item/struct.Foo.html '//*[@class="impl has-srclink"]' 'impl<T: Bar<Fuu = u32>> Foo<T>'
 impl<T: Bar<Fuu = u32>> Foo<T> {
     pub fn new(t: T) -> Foo<T> {
         Foo {
diff --git a/src/test/rustdoc/duplicate_impls/issue-33054.rs b/src/test/rustdoc/duplicate_impls/issue-33054.rs
index 1e644bb9739..15c3444606c 100644
--- a/src/test/rustdoc/duplicate_impls/issue-33054.rs
+++ b/src/test/rustdoc/duplicate_impls/issue-33054.rs
@@ -1,8 +1,8 @@
 // @has issue_33054/impls/struct.Foo.html
 // @has - '//code' 'impl Foo'
 // @has - '//code' 'impl Bar for Foo'
-// @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1
-// @count - '//*[@id="main"]/details/summary/*[@class="impl"]' 1
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1
+// @count - '//*[@id="main"]/details/summary/*[@class="impl has-srclink"]' 1
 // @has issue_33054/impls/bar/trait.Bar.html
 // @has - '//code' 'impl Bar for Foo'
 // @count - '//*[@class="struct"]' 1
diff --git a/src/test/rustdoc/empty-impls.rs b/src/test/rustdoc/empty-impls.rs
index 86dec32e625..2eed1cc9d74 100644
--- a/src/test/rustdoc/empty-impls.rs
+++ b/src/test/rustdoc/empty-impls.rs
@@ -1,19 +1,19 @@
 #![crate_name = "foo"]
 
 // @has foo/struct.Foo.html
-// @has - '//div[@id="synthetic-implementations-list"]/h3[@id="impl-Send"]' 'impl Send for Foo'
+// @has - '//div[@id="synthetic-implementations-list"]/div[@id="impl-Send"]' 'impl Send for Foo'
 pub struct Foo;
 
 pub trait EmptyTrait {}
 
-// @has - '//div[@id="trait-implementations-list"]/h3[@id="impl-EmptyTrait"]' 'impl EmptyTrait for Foo'
+// @has - '//div[@id="trait-implementations-list"]/div[@id="impl-EmptyTrait"]' 'impl EmptyTrait for Foo'
 impl EmptyTrait for Foo {}
 
 pub trait NotEmpty {
     fn foo(&self);
 }
 
-// @has - '//div[@id="trait-implementations-list"]/details/summary/h3[@id="impl-NotEmpty"]' 'impl NotEmpty for Foo'
+// @has - '//div[@id="trait-implementations-list"]/details/summary/div[@id="impl-NotEmpty"]' 'impl NotEmpty for Foo'
 impl NotEmpty for Foo {
     fn foo(&self) {}
 }
diff --git a/src/test/rustdoc/ensure-src-link.rs b/src/test/rustdoc/ensure-src-link.rs
index b7e7b11d27a..4b6270b26da 100644
--- a/src/test/rustdoc/ensure-src-link.rs
+++ b/src/test/rustdoc/ensure-src-link.rs
@@ -2,5 +2,5 @@
 
 // This test ensures that the [src] link is present on traits items.
 
-// @has foo/trait.Iterator.html '//h3[@id="method.zip"]/a[@class="srclink"]' "[src]"
+// @has foo/trait.Iterator.html '//div[@id="method.zip"]/a[@class="srclink"]' "[src]"
 pub use std::iter::Iterator;
diff --git a/src/test/rustdoc/external-doc.rs b/src/test/rustdoc/external-doc.rs
index 0dadca551a9..fc29cb252e2 100644
--- a/src/test/rustdoc/external-doc.rs
+++ b/src/test/rustdoc/external-doc.rs
@@ -1,12 +1,3 @@
-#![feature(external_doc)]
-
-// @has external_doc/struct.CanHasDocs.html
-// @has - '//h1' 'External Docs'
-// @has - '//h2' 'Inline Docs'
-#[doc(include = "auxiliary/external-doc.md")]
-/// ## Inline Docs
-pub struct CanHasDocs;
-
 // @has external_doc/struct.IncludeStrDocs.html
 // @has - '//h1' 'External Docs'
 // @has - '//h2' 'Inline Docs'
diff --git a/src/test/rustdoc/generic-impl.rs b/src/test/rustdoc/generic-impl.rs
index 03a4d197499..96ced021041 100644
--- a/src/test/rustdoc/generic-impl.rs
+++ b/src/test/rustdoc/generic-impl.rs
@@ -2,10 +2,10 @@
 
 use std::fmt;
 
-// @!has foo/struct.Bar.html '//h3[@id="impl-ToString"]//code' 'impl<T> ToString for T'
+// @!has foo/struct.Bar.html '//div[@id="impl-ToString"]//code' 'impl<T> ToString for T'
 pub struct Bar;
 
-// @has foo/struct.Foo.html '//h3[@id="impl-ToString"]//code' 'impl<T> ToString for T'
+// @has foo/struct.Foo.html '//div[@id="impl-ToString"]//code' 'impl<T> ToString for T'
 pub struct Foo;
 // @has foo/struct.Foo.html '//div[@class="sidebar-links"]/a[@href="#impl-ToString"]' 'ToString'
 
diff --git a/src/test/rustdoc/impl-parts.rs b/src/test/rustdoc/impl-parts.rs
index 90110babea7..e4039eecb71 100644
--- a/src/test/rustdoc/impl-parts.rs
+++ b/src/test/rustdoc/impl-parts.rs
@@ -5,7 +5,7 @@ pub auto trait AnAutoTrait {}
 
 pub struct Foo<T> { field: T }
 
-// @has impl_parts/struct.Foo.html '//*[@class="impl"]//code' \
+// @has impl_parts/struct.Foo.html '//*[@class="impl has-srclink"]//code' \
 //     "impl<T: Clone> !AnAutoTrait for Foo<T> where T: Sync,"
 // @has impl_parts/trait.AnAutoTrait.html '//*[@class="item-list"]//code' \
 //     "impl<T: Clone> !AnAutoTrait for Foo<T> where T: Sync,"
diff --git a/src/test/rustdoc/inline_cross/issue-31948-1.rs b/src/test/rustdoc/inline_cross/issue-31948-1.rs
index f47056223fe..390f0b845e0 100644
--- a/src/test/rustdoc/inline_cross/issue-31948-1.rs
+++ b/src/test/rustdoc/inline_cross/issue-31948-1.rs
@@ -5,8 +5,8 @@
 extern crate rustdoc_nonreachable_impls;
 
 // @has issue_31948_1/struct.Wobble.html
-// @has - '//*[@class="impl"]//code' 'Bark for'
-// @has - '//*[@class="impl"]//code' 'Woof for'
+// @has - '//*[@class="impl has-srclink"]//code' 'Bark for'
+// @has - '//*[@class="impl has-srclink"]//code' 'Woof for'
 // @!has - '//*[@class="impl"]//code' 'Bar for'
 // @!has - '//*[@class="impl"]//code' 'Qux for'
 pub use rustdoc_nonreachable_impls::hidden::Wobble;
diff --git a/src/test/rustdoc/inline_cross/issue-31948-2.rs b/src/test/rustdoc/inline_cross/issue-31948-2.rs
index 282f0679e98..013e777440f 100644
--- a/src/test/rustdoc/inline_cross/issue-31948-2.rs
+++ b/src/test/rustdoc/inline_cross/issue-31948-2.rs
@@ -5,9 +5,9 @@
 extern crate rustdoc_nonreachable_impls;
 
 // @has issue_31948_2/struct.Wobble.html
-// @has - '//*[@class="impl"]//code' 'Qux for'
-// @has - '//*[@class="impl"]//code' 'Bark for'
-// @has - '//*[@class="impl"]//code' 'Woof for'
+// @has - '//*[@class="impl has-srclink"]//code' 'Qux for'
+// @has - '//*[@class="impl has-srclink"]//code' 'Bark for'
+// @has - '//*[@class="impl has-srclink"]//code' 'Woof for'
 // @!has - '//*[@class="impl"]//code' 'Bar for'
 pub use rustdoc_nonreachable_impls::hidden::Wobble;
 
diff --git a/src/test/rustdoc/inline_cross/issue-31948.rs b/src/test/rustdoc/inline_cross/issue-31948.rs
index d5725175e3f..82dcc2d2cc3 100644
--- a/src/test/rustdoc/inline_cross/issue-31948.rs
+++ b/src/test/rustdoc/inline_cross/issue-31948.rs
@@ -5,9 +5,9 @@
 extern crate rustdoc_nonreachable_impls;
 
 // @has issue_31948/struct.Foo.html
-// @has - '//*[@class="impl"]//code' 'Bark for'
-// @has - '//*[@class="impl"]//code' 'Woof for'
-// @!has - '//*[@class="impl"]//code' 'Bar for'
+// @has - '//*[@class="impl has-srclink"]//code' 'Bark for'
+// @has - '//*[@class="impl has-srclink"]//code' 'Woof for'
+// @!has - '//*[@class="impl has-srclink"]//code' 'Bar for'
 // @!has - '//*[@class="impl"]//code' 'Qux for'
 pub use rustdoc_nonreachable_impls::Foo;
 
diff --git a/src/test/rustdoc/intra-doc/associated-items.rs b/src/test/rustdoc/intra-doc/associated-items.rs
index 2757418bc64..d9fed2d6951 100644
--- a/src/test/rustdoc/intra-doc/associated-items.rs
+++ b/src/test/rustdoc/intra-doc/associated-items.rs
@@ -3,9 +3,9 @@
 /// [`std::collections::BTreeMap::into_iter`]
 /// [`String::from`] is ambiguous as to which `From` impl
 /// [Vec::into_iter()] uses a disambiguator
-// @has 'associated_items/fn.foo.html' '//a[@href="https://doc.rust-lang.org/nightly/alloc/collections/btree/map/struct.BTreeMap.html#method.into_iter"]' 'std::collections::BTreeMap::into_iter'
-// @has 'associated_items/fn.foo.html' '//a[@href="https://doc.rust-lang.org/nightly/alloc/string/struct.String.html#method.from"]' 'String::from'
-// @has 'associated_items/fn.foo.html' '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.into_iter"]' 'Vec::into_iter'
+// @has 'associated_items/fn.foo.html' '//a[@href="{{channel}}/alloc/collections/btree/map/struct.BTreeMap.html#method.into_iter"]' 'std::collections::BTreeMap::into_iter'
+// @has 'associated_items/fn.foo.html' '//a[@href="{{channel}}/alloc/string/struct.String.html#method.from"]' 'String::from'
+// @has 'associated_items/fn.foo.html' '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.into_iter"]' 'Vec::into_iter'
 pub fn foo() {}
 
 /// Link to [MyStruct], [link from struct][MyStruct::method], [MyStruct::clone], [MyStruct::Input]
diff --git a/src/test/rustdoc/intra-doc/builtin-macros.rs b/src/test/rustdoc/intra-doc/builtin-macros.rs
index 74216a587e1..bbdbe246bbc 100644
--- a/src/test/rustdoc/intra-doc/builtin-macros.rs
+++ b/src/test/rustdoc/intra-doc/builtin-macros.rs
@@ -1,3 +1,3 @@
 // @has builtin_macros/index.html
-// @has - '//a/@href' 'https://doc.rust-lang.org/nightly/core/macro.cfg.html'
+// @has - '//a/@href' '{{channel}}/core/macro.cfg.html'
 //! [cfg]
diff --git a/src/test/rustdoc/intra-doc/field.rs b/src/test/rustdoc/intra-doc/field.rs
new file mode 100644
index 00000000000..c67c40a77ed
--- /dev/null
+++ b/src/test/rustdoc/intra-doc/field.rs
@@ -0,0 +1,4 @@
+// @has field/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/ops/range/struct.Range.html#structfield.start"]' 'start'
+// @has field/index.html '//a[@href="https://doc.rust-lang.org/nightly/std/io/error/enum.ErrorKind.html#variant.NotFound"]' 'not_found'
+//! [start][std::ops::Range::start]
+//! [not_found][std::io::ErrorKind::NotFound]
diff --git a/src/test/rustdoc/intra-doc/generic-params.rs b/src/test/rustdoc/intra-doc/generic-params.rs
index 1de6410f10c..fbc9fc6a9bc 100644
--- a/src/test/rustdoc/intra-doc/generic-params.rs
+++ b/src/test/rustdoc/intra-doc/generic-params.rs
@@ -5,40 +5,40 @@
 //! Here's a link to [`Vec<T>`] and one to [`Box<Vec<Option<T>>>`].
 //! Here's a link to [`Iterator<Box<T>>::Item`].
 //!
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html"]' 'Vec<T>'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/boxed/struct.Box.html"]' 'Box<Vec<Option<T>>>'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/iter/traits/iterator/trait.Iterator.html#associatedtype.Item"]' 'Iterator<Box<T>>::Item'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/vec/struct.Vec.html"]' 'Vec<T>'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/boxed/struct.Box.html"]' 'Box<Vec<Option<T>>>'
+// @has foo/index.html '//a[@href="{{channel}}/core/iter/traits/iterator/trait.Iterator.html#associatedtype.Item"]' 'Iterator<Box<T>>::Item'
 
 //! And what about a link to [just `Option`](Option) and, [with the generic, `Option<T>`](Option<T>)?
 //!
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/option/enum.Option.html"]' 'just Option'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/option/enum.Option.html"]' 'with the generic, Option<T>'
+// @has foo/index.html '//a[@href="{{channel}}/core/option/enum.Option.html"]' 'just Option'
+// @has foo/index.html '//a[@href="{{channel}}/core/option/enum.Option.html"]' 'with the generic, Option<T>'
 
 //! We should also try linking to [`Result<T, E>`]; it has *two* generics!
 //! And [`Result<T, !>`] and [`Result<!, E>`].
 //!
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html"]' 'Result<T, E>'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html"]' 'Result<T, !>'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/result/enum.Result.html"]' 'Result<!, E>'
+// @has foo/index.html '//a[@href="{{channel}}/core/result/enum.Result.html"]' 'Result<T, E>'
+// @has foo/index.html '//a[@href="{{channel}}/core/result/enum.Result.html"]' 'Result<T, !>'
+// @has foo/index.html '//a[@href="{{channel}}/core/result/enum.Result.html"]' 'Result<!, E>'
 
 //! Now let's test a trickier case: [`Vec::<T>::new`], or you could write it
 //! [with parentheses as `Vec::<T>::new()`][Vec::<T>::new()].
 //! And what about something even harder? That would be [`Vec::<Box<T>>::new()`].
 //!
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.new"]' 'Vec::<T>::new'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.new"]' 'with parentheses as Vec::<T>::new()'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.new"]' 'Vec::<Box<T>>::new()'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.new"]' 'Vec::<T>::new'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.new"]' 'with parentheses as Vec::<T>::new()'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.new"]' 'Vec::<Box<T>>::new()'
 
 //! This is also pretty tricky: [`TypeId::of::<String>()`].
 //! And this too: [`Vec::<std::error::Error>::len`].
 //!
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/core/any/struct.TypeId.html#method.of"]' 'TypeId::of::<String>()'
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/vec/struct.Vec.html#method.len"]' 'Vec::<std::error::Error>::len'
+// @has foo/index.html '//a[@href="{{channel}}/core/any/struct.TypeId.html#method.of"]' 'TypeId::of::<String>()'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/vec/struct.Vec.html#method.len"]' 'Vec::<std::error::Error>::len'
 
 //! We unofficially and implicitly support things that aren't valid in the actual Rust syntax, like
 //! [`Box::<T>new()`]. We may not support them in the future!
 //!
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/alloc/boxed/struct.Box.html#method.new"]' 'Box::<T>new()'
+// @has foo/index.html '//a[@href="{{channel}}/alloc/boxed/struct.Box.html#method.new"]' 'Box::<T>new()'
 
 //! These will be resolved as regular links:
 //! - [`this is <invalid syntax> first`](https://www.rust-lang.org)
diff --git a/src/test/rustdoc/intra-doc/non-path-primitives.rs b/src/test/rustdoc/intra-doc/non-path-primitives.rs
index ee71537d155..be4b44b3142 100644
--- a/src/test/rustdoc/intra-doc/non-path-primitives.rs
+++ b/src/test/rustdoc/intra-doc/non-path-primitives.rs
@@ -2,45 +2,45 @@
 #![feature(intra_doc_pointers)]
 #![deny(rustdoc::broken_intra_doc_links)]
 
-// @has foo/index.html '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.slice.html#method.rotate_left"]' 'slice::rotate_left'
+// @has foo/index.html '//a[@href="{{channel}}/std/primitive.slice.html#method.rotate_left"]' 'slice::rotate_left'
 //! [slice::rotate_left]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.array.html#method.map"]' 'array::map'
+// @has - '//a[@href="{{channel}}/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'
+// @has - '//a[@href="{{channel}}/std/primitive.str.html"]' 'owned str'
+// @has - '//a[@href="{{channel}}/std/primitive.str.html"]' 'str ref'
+// @has - '//a[@href="{{channel}}/std/primitive.str.html#method.is_empty"]' 'str::is_empty'
+// @has - '//a[@href="{{channel}}/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="{{channel}}/std/primitive.pointer.html#method.is_null"]' 'pointer::is_null'
+// @has - '//a[@href="{{channel}}/std/primitive.pointer.html#method.is_null"]' '*const::is_null'
+// @has - '//a[@href="{{channel}}/std/primitive.pointer.html#method.is_null"]' '*mut::is_null'
 //! [pointer::is_null]
 //! [*const::is_null]
 //! [*mut::is_null]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.unit.html"]' 'unit'
+// @has - '//a[@href="{{channel}}/std/primitive.unit.html"]' 'unit'
 //! [unit]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.tuple.html"]' 'tuple'
+// @has - '//a[@href="{{channel}}/std/primitive.tuple.html"]' 'tuple'
 //! [tuple]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.reference.html"]' 'reference'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.reference.html"]' '&'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.reference.html"]' '&mut'
+// @has - '//a[@href="{{channel}}/std/primitive.reference.html"]' 'reference'
+// @has - '//a[@href="{{channel}}/std/primitive.reference.html"]' '&'
+// @has - '//a[@href="{{channel}}/std/primitive.reference.html"]' '&mut'
 //! [reference]
 //! [&]
 //! [&mut]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.fn.html"]' 'fn'
+// @has - '//a[@href="{{channel}}/std/primitive.fn.html"]' 'fn'
 //! [fn]
 
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.never.html"]' 'never'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.never.html"]' '!'
+// @has - '//a[@href="{{channel}}/std/primitive.never.html"]' 'never'
+// @has - '//a[@href="{{channel}}/std/primitive.never.html"]' '!'
 //! [never]
 //! [!]
diff --git a/src/test/rustdoc/intra-doc/prim-assoc.rs b/src/test/rustdoc/intra-doc/prim-assoc.rs
index 4099ececfaf..c73140420ff 100644
--- a/src/test/rustdoc/intra-doc/prim-assoc.rs
+++ b/src/test/rustdoc/intra-doc/prim-assoc.rs
@@ -1,4 +1,4 @@
 #![deny(broken_intra_doc_links)]
 
 //! [i32::MAX]
-// @has prim_assoc/index.html '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html#associatedconstant.MAX"]' "i32::MAX"
+// @has prim_assoc/index.html '//a[@href="{{channel}}/std/primitive.i32.html#associatedconstant.MAX"]' "i32::MAX"
diff --git a/src/test/rustdoc/intra-doc/prim-methods-external-core.rs b/src/test/rustdoc/intra-doc/prim-methods-external-core.rs
index 695a7fbfb53..9347d7bb428 100644
--- a/src/test/rustdoc/intra-doc/prim-methods-external-core.rs
+++ b/src/test/rustdoc/intra-doc/prim-methods-external-core.rs
@@ -9,8 +9,8 @@
 #![crate_type = "rlib"]
 
 // @has prim_methods_external_core/index.html
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char'
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html"]' 'char'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
 
 //! A [`char`] and its [`char::len_utf8`].
 
diff --git a/src/test/rustdoc/intra-doc/prim-methods-local.rs b/src/test/rustdoc/intra-doc/prim-methods-local.rs
index f0b939a468c..124faa9a636 100644
--- a/src/test/rustdoc/intra-doc/prim-methods-local.rs
+++ b/src/test/rustdoc/intra-doc/prim-methods-local.rs
@@ -5,8 +5,8 @@
 
 
 // @has prim_methods_local/index.html
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char'
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html"]' 'char'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
 
 //! A [`char`] and its [`char::len_utf8`].
 
diff --git a/src/test/rustdoc/intra-doc/prim-methods.rs b/src/test/rustdoc/intra-doc/prim-methods.rs
index 6de15e76d15..076117359d2 100644
--- a/src/test/rustdoc/intra-doc/prim-methods.rs
+++ b/src/test/rustdoc/intra-doc/prim-methods.rs
@@ -2,7 +2,7 @@
 
 
 // @has prim_methods/index.html
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char'
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html"]' 'char'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
 
 //! A [`char`] and its [`char::len_utf8`].
diff --git a/src/test/rustdoc/intra-doc/prim-precedence.rs b/src/test/rustdoc/intra-doc/prim-precedence.rs
index 478b40b0b51..fcd86a99f1d 100644
--- a/src/test/rustdoc/intra-doc/prim-precedence.rs
+++ b/src/test/rustdoc/intra-doc/prim-precedence.rs
@@ -2,12 +2,12 @@
 
 pub mod char {
     /// [char]
-    // @has prim_precedence/char/struct.Inner.html '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.char.html'
+    // @has prim_precedence/char/struct.Inner.html '//a/@href' '{{channel}}/std/primitive.char.html'
     pub struct Inner;
 }
 
 /// See [prim@char]
-// @has prim_precedence/struct.MyString.html '//a/@href' 'https://doc.rust-lang.org/nightly/std/primitive.char.html'
+// @has prim_precedence/struct.MyString.html '//a/@href' '{{channel}}/std/primitive.char.html'
 pub struct MyString;
 
 /// See also [crate::char] and [mod@char]
diff --git a/src/test/rustdoc/intra-doc/primitive-disambiguators.rs b/src/test/rustdoc/intra-doc/primitive-disambiguators.rs
index acdd07566c9..9b3b6983240 100644
--- a/src/test/rustdoc/intra-doc/primitive-disambiguators.rs
+++ b/src/test/rustdoc/intra-doc/primitive-disambiguators.rs
@@ -1,4 +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'
+// @has - '//a/@href' '{{channel}}/std/primitive.str.html#method.trim'
 //! [str::trim()]
diff --git a/src/test/rustdoc/intra-doc/primitive-non-default-impl.rs b/src/test/rustdoc/intra-doc/primitive-non-default-impl.rs
index cf83ead4db7..f8a824bd08f 100644
--- a/src/test/rustdoc/intra-doc/primitive-non-default-impl.rs
+++ b/src/test/rustdoc/intra-doc/primitive-non-default-impl.rs
@@ -3,29 +3,29 @@
 
 // @has primitive_non_default_impl/fn.str_methods.html
 /// [`str::trim`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim"]' 'str::trim'
+// @has - '//*[@href="{{channel}}/std/primitive.str.html#method.trim"]' 'str::trim'
 /// [`str::to_lowercase`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.to_lowercase"]' 'str::to_lowercase'
+// @has - '//*[@href="{{channel}}/std/primitive.str.html#method.to_lowercase"]' 'str::to_lowercase'
 /// [`str::into_boxed_bytes`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.into_boxed_bytes"]' 'str::into_boxed_bytes'
+// @has - '//*[@href="{{channel}}/std/primitive.str.html#method.into_boxed_bytes"]' 'str::into_boxed_bytes'
 /// [`str::replace`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.replace"]' 'str::replace'
+// @has - '//*[@href="{{channel}}/std/primitive.str.html#method.replace"]' 'str::replace'
 pub fn str_methods() {}
 
 // @has primitive_non_default_impl/fn.f32_methods.html
 /// [f32::powi]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f32.html#method.powi"]' 'f32::powi'
+// @has - '//*[@href="{{channel}}/std/primitive.f32.html#method.powi"]' 'f32::powi'
 /// [f32::sqrt]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f32.html#method.sqrt"]' 'f32::sqrt'
+// @has - '//*[@href="{{channel}}/std/primitive.f32.html#method.sqrt"]' 'f32::sqrt'
 /// [f32::mul_add]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f32.html#method.mul_add"]' 'f32::mul_add'
+// @has - '//*[@href="{{channel}}/std/primitive.f32.html#method.mul_add"]' 'f32::mul_add'
 pub fn f32_methods() {}
 
 // @has primitive_non_default_impl/fn.f64_methods.html
 /// [`f64::powi`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f64.html#method.powi"]' 'f64::powi'
+// @has - '//*[@href="{{channel}}/std/primitive.f64.html#method.powi"]' 'f64::powi'
 /// [`f64::sqrt`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f64.html#method.sqrt"]' 'f64::sqrt'
+// @has - '//*[@href="{{channel}}/std/primitive.f64.html#method.sqrt"]' 'f64::sqrt'
 /// [`f64::mul_add`]
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f64.html#method.mul_add"]' 'f64::mul_add'
+// @has - '//*[@href="{{channel}}/std/primitive.f64.html#method.mul_add"]' 'f64::mul_add'
 pub fn f64_methods() {}
diff --git a/src/test/rustdoc/intra-doc/pub-use.rs b/src/test/rustdoc/intra-doc/pub-use.rs
index 579fa68cee8..b4f2d6b0617 100644
--- a/src/test/rustdoc/intra-doc/pub-use.rs
+++ b/src/test/rustdoc/intra-doc/pub-use.rs
@@ -12,7 +12,7 @@ extern crate inner;
 // documenting the re-export.
 
 // @has outer/index.html
-// @ has - '//a[@href="https://doc.rust-lang.org/nightly/std/env/fn.var.html"]' "std::env"
+// @ has - '//a[@href="{{channel}}/std/env/fn.var.html"]' "std::env"
 // @ has - '//a[@href="fn.f.html"]' "g"
 pub use f as g;
 
@@ -23,5 +23,5 @@ extern crate self as _;
 // Make sure the documentation is actually correct by documenting an inlined re-export
 /// [mod@std::env]
 // @has outer/fn.f.html
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/env/index.html"]' "std::env"
+// @has - '//a[@href="{{channel}}/std/env/index.html"]' "std::env"
 pub use inner::f;
diff --git a/src/test/rustdoc/intra-doc/trait-item.rs b/src/test/rustdoc/intra-doc/trait-item.rs
index 7602aced564..0be368d051e 100644
--- a/src/test/rustdoc/intra-doc/trait-item.rs
+++ b/src/test/rustdoc/intra-doc/trait-item.rs
@@ -3,7 +3,7 @@
 /// Link to [S::assoc_fn()]
 /// Link to [Default::default()]
 // @has trait_item/struct.S.html '//*[@href="struct.S.html#method.assoc_fn"]' 'S::assoc_fn()'
-// @has - '//*[@href="https://doc.rust-lang.org/nightly/core/default/trait.Default.html#tymethod.default"]' 'Default::default()'
+// @has - '//*[@href="{{channel}}/core/default/trait.Default.html#tymethod.default"]' 'Default::default()'
 pub struct S;
 
 impl S {
diff --git a/src/test/rustdoc/intra-doc/true-false.rs b/src/test/rustdoc/intra-doc/true-false.rs
index db637ece369..44aac688413 100644
--- a/src/test/rustdoc/intra-doc/true-false.rs
+++ b/src/test/rustdoc/intra-doc/true-false.rs
@@ -3,7 +3,7 @@
 
 
 // @has foo/index.html
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.bool.html"]' 'true'
-// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.bool.html"]' 'false'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.bool.html"]' 'true'
+// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.bool.html"]' 'false'
 
 //! A `bool` is either [`true`] or [`false`].
diff --git a/src/test/rustdoc/intra-link-prim-self.rs b/src/test/rustdoc/intra-link-prim-self.rs
index 1189d266c53..4744c84b622 100644
--- a/src/test/rustdoc/intra-link-prim-self.rs
+++ b/src/test/rustdoc/intra-link-prim-self.rs
@@ -1,4 +1,3 @@
-// ignore-tidy-linelength
 #![deny(broken_intra_doc_links)]
 #![feature(lang_items)]
 #![feature(no_core)]
@@ -8,8 +7,8 @@
 /// [Self::f]
 /// [Self::MAX]
 // @has intra_link_prim_self/primitive.usize.html
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.usize.html#method.f"]' 'Self::f'
-// @has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.usize.html#associatedconstant.MAX"]' 'Self::MAX'
+// @has - '//a[@href="{{channel}}/std/primitive.usize.html#method.f"]' 'Self::f'
+// @has - '//a[@href="{{channel}}/std/primitive.usize.html#associatedconstant.MAX"]' 'Self::MAX'
 impl usize {
     /// Some docs
     pub fn f() {}
@@ -18,7 +17,7 @@ impl usize {
     pub const MAX: usize = 10;
 
     // FIXME(#8995) uncomment this when associated types in inherent impls are supported
-    // @ has - '//a[@href="https://doc.rust-lang.org/nightly/std/primitive.usize.html#associatedtype.ME"]' 'Self::ME'
+    // @ has - '//a[@href="{{channel}}/std/primitive.usize.html#associatedtype.ME"]' 'Self::ME'
     // / [Self::ME]
     //pub type ME = usize;
 }
diff --git a/src/test/rustdoc/issue-21474.rs b/src/test/rustdoc/issue-21474.rs
index 5de26abace6..43ce13fd9b1 100644
--- a/src/test/rustdoc/issue-21474.rs
+++ b/src/test/rustdoc/issue-21474.rs
@@ -7,5 +7,5 @@ mod inner {
 pub trait Blah { }
 
 // @count issue_21474/struct.What.html \
-//        '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1
+//        '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1
 pub struct What;
diff --git a/src/test/rustdoc/issue-29503.rs b/src/test/rustdoc/issue-29503.rs
index 2b25da77d7e..23d9e73b567 100644
--- a/src/test/rustdoc/issue-29503.rs
+++ b/src/test/rustdoc/issue-29503.rs
@@ -5,7 +5,7 @@ pub trait MyTrait {
     fn my_string(&self) -> String;
 }
 
-// @has - "//div[@id='implementors-list']//h3[@id='impl-MyTrait']//code" "impl<T> MyTrait for T where T: Debug"
+// @has - "//div[@id='implementors-list']//div[@id='impl-MyTrait']//code" "impl<T> MyTrait for T where T: Debug"
 impl<T> MyTrait for T where T: fmt::Debug {
     fn my_string(&self) -> String {
         format!("{:?}", self)
diff --git a/src/test/rustdoc/issue-33302.rs b/src/test/rustdoc/issue-33302.rs
index 21356b513ee..1777744c0fc 100644
--- a/src/test/rustdoc/issue-33302.rs
+++ b/src/test/rustdoc/issue-33302.rs
@@ -23,7 +23,7 @@ macro_rules! make {
         }
 
         // @has issue_33302/struct.S.html \
-        //        '//h3[@class="impl"]' 'impl T<[i32; 16]> for S'
+        //        '//div[@class="impl has-srclink"]' 'impl T<[i32; 16]> for S'
         // @has - '//*[@id="associatedconstant.C"]' 'const C: [i32; 16]'
         // @has - '//*[@id="associatedconstant.D"]' 'const D: i32'
         impl T<[i32; ($n * $n)]> for S {
@@ -31,7 +31,7 @@ macro_rules! make {
         }
 
         // @has issue_33302/struct.S.html \
-        //        '//h3[@class="impl"]' 'impl T<[i32; 16]> for S'
+        //        '//div[@class="impl has-srclink"]' 'impl T<[i32; 16]> for S'
         // @has - '//*[@id="associatedconstant.C-1"]' 'const C: (i32,)'
         // @has - '//*[@id="associatedconstant.D-1"]' 'const D: i32'
         impl T<(i32,)> for S {
@@ -39,7 +39,7 @@ macro_rules! make {
         }
 
         // @has issue_33302/struct.S.html \
-        //        '//h3[@class="impl"]' 'impl T<(i32, i32)> for S'
+        //        '//div[@class="impl has-srclink"]' 'impl T<(i32, i32)> for S'
         // @has - '//*[@id="associatedconstant.C-2"]' 'const C: (i32, i32)'
         // @has - '//*[@id="associatedconstant.D-2"]' 'const D: i32'
         impl T<(i32, i32)> for S {
diff --git a/src/test/rustdoc/issue-45584.rs b/src/test/rustdoc/issue-45584.rs
index 8a5f0413826..86479e6fb2e 100644
--- a/src/test/rustdoc/issue-45584.rs
+++ b/src/test/rustdoc/issue-45584.rs
@@ -4,12 +4,12 @@ pub trait Bar<T, U> {}
 
 // @has 'foo/struct.Foo1.html'
 pub struct Foo1;
-// @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1
-// @has - '//*[@class="impl"]' "impl Bar<Foo1, &'static Foo1> for Foo1"
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1
+// @has - '//*[@class="impl has-srclink"]' "impl Bar<Foo1, &'static Foo1> for Foo1"
 impl Bar<Foo1, &'static Foo1> for Foo1 {}
 
 // @has 'foo/struct.Foo2.html'
 pub struct Foo2;
-// @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1
-// @has - '//*[@class="impl"]' "impl Bar<&'static Foo2, Foo2> for u8"
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1
+// @has - '//*[@class="impl has-srclink"]' "impl Bar<&'static Foo2, Foo2> for u8"
 impl Bar<&'static Foo2, Foo2> for u8 {}
diff --git a/src/test/rustdoc/issue-50159.rs b/src/test/rustdoc/issue-50159.rs
index 0820512e521..69774aa351f 100644
--- a/src/test/rustdoc/issue-50159.rs
+++ b/src/test/rustdoc/issue-50159.rs
@@ -14,7 +14,7 @@ impl<B, C> Signal2 for B where B: Signal<Item = C> {
 // @has - '//code' 'impl<B> Send for Switch<B> where <B as Signal>::Item: Send'
 // @has - '//code' 'impl<B> Sync for Switch<B> where <B as Signal>::Item: Sync'
 // @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0
-// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5
+// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5
 pub struct Switch<B: Signal> {
     pub inner: <B as Signal2>::Item2,
 }
diff --git a/src/test/rustdoc/issue-51236.rs b/src/test/rustdoc/issue-51236.rs
index d018c948162..e01dae6c7f1 100644
--- a/src/test/rustdoc/issue-51236.rs
+++ b/src/test/rustdoc/issue-51236.rs
@@ -7,8 +7,8 @@ pub mod traits {
 }
 
 // @has issue_51236/struct.Owned.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<T> Send for \
-// Owned<T> where <T as Owned<'static>>::Reader: Send"
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// "impl<T> Send for Owned<T> where <T as Owned<'static>>::Reader: Send"
 pub struct Owned<T> where T: for<'a> ::traits::Owned<'a> {
     marker: PhantomData<<T as ::traits::Owned<'static>>::Reader>,
 }
diff --git a/src/test/rustdoc/issue-53812.rs b/src/test/rustdoc/issue-53812.rs
index ddc14e68675..0b1f2f2c93f 100644
--- a/src/test/rustdoc/issue-53812.rs
+++ b/src/test/rustdoc/issue-53812.rs
@@ -12,9 +12,10 @@ macro_rules! array_impls {
     }
 }
 
-// @has issue_53812/trait.MyIterator.html '//*[@id="implementors-list"]/h3[1]' 'MyStruct<[T; 0]>'
-// @has - '//*[@id="implementors-list"]/h3[2]' 'MyStruct<[T; 1]>'
-// @has - '//*[@id="implementors-list"]/h3[3]' 'MyStruct<[T; 2]>'
-// @has - '//*[@id="implementors-list"]/h3[4]' 'MyStruct<[T; 3]>'
-// @has - '//*[@id="implementors-list"]/h3[5]' 'MyStruct<[T; 10]>'
+// @has issue_53812/trait.MyIterator.html
+// @has - '//*[@id="implementors-list"]/div[@class="impl has-srclink"][1]' 'MyStruct<[T; 0]>'
+// @has - '//*[@id="implementors-list"]/div[@class="impl has-srclink"][2]' 'MyStruct<[T; 1]>'
+// @has - '//*[@id="implementors-list"]/div[@class="impl has-srclink"][3]' 'MyStruct<[T; 2]>'
+// @has - '//*[@id="implementors-list"]/div[@class="impl has-srclink"][4]' 'MyStruct<[T; 3]>'
+// @has - '//*[@id="implementors-list"]/div[@class="impl has-srclink"][5]' 'MyStruct<[T; 10]>'
 array_impls! { 10 3 2 1 0 }
diff --git a/src/test/rustdoc/issue-54705.rs b/src/test/rustdoc/issue-54705.rs
index 47da94a4ccf..5a94d36ed70 100644
--- a/src/test/rustdoc/issue-54705.rs
+++ b/src/test/rustdoc/issue-54705.rs
@@ -3,11 +3,11 @@ pub trait ScopeHandle<'scope> {}
 
 
 // @has issue_54705/struct.ScopeFutureContents.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'scope, S> \
-// Send for ScopeFutureContents<'scope, S> where S: Sync"
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// "impl<'scope, S> Send for ScopeFutureContents<'scope, S> where S: Sync"
 //
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'scope, S> \
-// Sync for ScopeFutureContents<'scope, S> where S: Sync"
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// "impl<'scope, S> Sync for ScopeFutureContents<'scope, S> where S: Sync"
 pub struct ScopeFutureContents<'scope, S>
     where S: ScopeHandle<'scope>,
 {
diff --git a/src/test/rustdoc/issue-55321.rs b/src/test/rustdoc/issue-55321.rs
index d1877f39ba7..b664733487b 100644
--- a/src/test/rustdoc/issue-55321.rs
+++ b/src/test/rustdoc/issue-55321.rs
@@ -1,16 +1,18 @@
 #![feature(negative_impls)]
 
 // @has issue_55321/struct.A.html
-// @has - '//*[@id="trait-implementations-list"]//*[@class="impl"]//code' "impl !Send for A"
-// @has - '//*[@id="trait-implementations-list"]//*[@class="impl"]//code' "impl !Sync for A"
+// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// "impl !Send for A"
+// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// "impl !Sync for A"
 pub struct A();
 
 impl !Send for A {}
 impl !Sync for A {}
 
 // @has issue_55321/struct.B.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<T> !Send for \
-// B<T>"
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<T> !Sync for \
-// B<T>"
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// "impl<T> !Send for B<T>"
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// "impl<T> !Sync for B<T>"
 pub struct B<T: ?Sized>(A, Box<T>);
diff --git a/src/test/rustdoc/issue-56822.rs b/src/test/rustdoc/issue-56822.rs
index b932a3d3474..977596e0b90 100644
--- a/src/test/rustdoc/issue-56822.rs
+++ b/src/test/rustdoc/issue-56822.rs
@@ -17,8 +17,8 @@ impl<'a, T> MyTrait for Inner<'a, T> {
 }
 
 // @has issue_56822/struct.Parser.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'a> Send for \
-// Parser<'a>"
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// "impl<'a> Send for Parser<'a>"
 pub struct Parser<'a> {
     field: <Wrapper<Inner<'a, u8>> as MyTrait>::Output
 }
diff --git a/src/test/rustdoc/issue-60726.rs b/src/test/rustdoc/issue-60726.rs
index 79b8b70c545..e0417f1a4f4 100644
--- a/src/test/rustdoc/issue-60726.rs
+++ b/src/test/rustdoc/issue-60726.rs
@@ -26,10 +26,10 @@ where
 {}
 
 // @has issue_60726/struct.IntoIter.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<T> !Send for \
-// IntoIter<T>"
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<T> !Sync for \
-// IntoIter<T>"
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// "impl<T> !Send for IntoIter<T>"
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// "impl<T> !Sync for IntoIter<T>"
 pub struct IntoIter<T>{
     hello:DynTrait<FooInterface<T>>,
 }
diff --git a/src/test/rustdoc/issue-76501.rs b/src/test/rustdoc/issue-76501.rs
index d468f35e280..a90e0fea092 100644
--- a/src/test/rustdoc/issue-76501.rs
+++ b/src/test/rustdoc/issue-76501.rs
@@ -8,7 +8,8 @@ pub const fn bloop() -> i32 {
 pub struct Struct {}
 
 impl Struct {
-    // @has 'issue_76501/struct.Struct.html' '//*[@class="method"]' 'pub const fn blurp() -> i32'
+    // @has 'issue_76501/struct.Struct.html' '//*[@class="method has-srclink"]' \
+    // 'pub const fn blurp() -> i32'
     /// A useless function that always returns 1.
     pub const fn blurp() -> i32 {
         1
diff --git a/src/test/rustdoc/issue-78673.rs b/src/test/rustdoc/issue-78673.rs
index d09141c3204..2e4bec2544c 100644
--- a/src/test/rustdoc/issue-78673.rs
+++ b/src/test/rustdoc/issue-78673.rs
@@ -7,8 +7,8 @@ pub trait AnAmazingTrait {}
 impl<T: Something> AnAmazingTrait for T {}
 
 // @has 'issue_78673/struct.MyStruct.html'
-// @has  - '//*[@class="impl"]' 'AnAmazingTrait for MyStruct'
-// @!has - '//*[@class="impl"]' 'AnAmazingTrait for T'
+// @has  - '//*[@class="impl has-srclink"]' 'AnAmazingTrait for MyStruct'
+// @!has - '//*[@class="impl has-srclink"]' 'AnAmazingTrait for T'
 pub struct MyStruct;
 
 impl AnAmazingTrait for MyStruct {}
@@ -16,8 +16,8 @@ impl AnAmazingTrait for MyStruct {}
 // generic structs may have _both_ specific and blanket impls that apply
 
 // @has 'issue_78673/struct.AnotherStruct.html'
-// @has - '//*[@class="impl"]' 'AnAmazingTrait for AnotherStruct<()>'
-// @has - '//*[@class="impl"]' 'AnAmazingTrait for T'
+// @has - '//*[@class="impl has-srclink"]' 'AnAmazingTrait for AnotherStruct<()>'
+// @has - '//*[@class="impl has-srclink"]' 'AnAmazingTrait for T'
 pub struct AnotherStruct<T>(T);
 
 impl<T: Something> Something for AnotherStruct<T> {}
diff --git a/src/test/rustdoc/keyword.rs b/src/test/rustdoc/keyword.rs
index 25e8b7912e7..652517c5c90 100644
--- a/src/test/rustdoc/keyword.rs
+++ b/src/test/rustdoc/keyword.rs
@@ -4,7 +4,8 @@
 
 // @has foo/index.html '//h2[@id="keywords"]' 'Keywords'
 // @has foo/index.html '//a[@href="keyword.match.html"]' 'match'
-// @has foo/index.html '//div[@class="block items"]//a/@href' '#keywords'
+// @has foo/index.html '//div[@class="sidebar-elems"]//li/a' 'Keywords'
+// @has foo/index.html '//div[@class="sidebar-elems"]//li/a/@href' '#keywords'
 // @has foo/keyword.match.html '//a[@class="keyword"]' 'match'
 // @has foo/keyword.match.html '//span[@class="in-band"]' 'Keyword match'
 // @has foo/keyword.match.html '//section[@id="main"]//div[@class="docblock"]//p' 'this is a test!'
diff --git a/src/test/rustdoc/mut-params.rs b/src/test/rustdoc/mut-params.rs
index 1ef7e304fa2..f3ea6995839 100644
--- a/src/test/rustdoc/mut-params.rs
+++ b/src/test/rustdoc/mut-params.rs
@@ -5,7 +5,7 @@
 
 pub struct Foo;
 
-// @count foo/struct.Foo.html '//*[@class="impl-items"]//*[@class="method"]' 2
+// @count foo/struct.Foo.html '//*[@class="impl-items"]//*[@class="method has-srclink"]' 2
 // @!has - '//*[@class="impl-items"]//*[@class="method"]' 'mut'
 impl Foo {
     pub fn foo(mut self) {}
diff --git a/src/test/rustdoc/negative-impl.rs b/src/test/rustdoc/negative-impl.rs
index d76aac6906c..ee65a7d5f39 100644
--- a/src/test/rustdoc/negative-impl.rs
+++ b/src/test/rustdoc/negative-impl.rs
@@ -5,8 +5,10 @@ pub struct Alpha;
 // @matches negative_impl/struct.Bravo.html '//pre' "pub struct Bravo<B>"
 pub struct Bravo<B>(B);
 
-// @matches negative_impl/struct.Alpha.html '//*[@class="impl"]//code' "impl !Send for Alpha"
+// @matches negative_impl/struct.Alpha.html '//*[@class="impl has-srclink"]//code' \
+// "impl !Send for Alpha"
 impl !Send for Alpha {}
 
-// @matches negative_impl/struct.Bravo.html '//*[@class="impl"]//code' "impl<B> !Send for Bravo<B>"
+// @matches negative_impl/struct.Bravo.html '//*[@class="impl has-srclink"]//code' "\
+// impl<B> !Send for Bravo<B>"
 impl<B> !Send for Bravo<B> {}
diff --git a/src/test/rustdoc/primitive-generic-impl.rs b/src/test/rustdoc/primitive-generic-impl.rs
index 5794322ba1d..2951f5128e0 100644
--- a/src/test/rustdoc/primitive-generic-impl.rs
+++ b/src/test/rustdoc/primitive-generic-impl.rs
@@ -2,4 +2,4 @@
 
 include!("primitive/primitive-generic-impl.rs");
 
-// @has foo/primitive.i32.html '//h3[@id="impl-ToString"]//code' 'impl<T> ToString for T'
+// @has foo/primitive.i32.html '//div[@id="impl-ToString"]//code' 'impl<T> ToString for T'
diff --git a/src/test/rustdoc/primitive-link.rs b/src/test/rustdoc/primitive-link.rs
index dd455e45bfc..125e0c84973 100644
--- a/src/test/rustdoc/primitive-link.rs
+++ b/src/test/rustdoc/primitive-link.rs
@@ -1,12 +1,12 @@
 #![crate_name = "foo"]
 
 
-// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.u32.html"]' 'u32'
-// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i64.html"]' 'i64'
-// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html"]' 'std::primitive::i32'
-// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html"]' 'std::primitive::str'
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.u32.html"]' 'u32'
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.i64.html"]' 'i64'
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.i32.html"]' 'std::primitive::i32'
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.str.html"]' 'std::primitive::str'
 
-// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html#associatedconstant.MAX"]' 'std::primitive::i32::MAX'
+// @has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.i32.html#associatedconstant.MAX"]' 'std::primitive::i32::MAX'
 
 /// It contains [`u32`] and [i64].
 /// It also links to [std::primitive::i32], [std::primitive::str],
diff --git a/src/test/rustdoc/primitive-reexport.rs b/src/test/rustdoc/primitive-reexport.rs
index de18360d407..10a8a47db52 100644
--- a/src/test/rustdoc/primitive-reexport.rs
+++ b/src/test/rustdoc/primitive-reexport.rs
@@ -5,24 +5,24 @@
 
 // @has bar/p/index.html
 // @has - '//code' 'pub use bool;'
-// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.bool.html"]' 'bool'
+// @has - '//code/a[@href="{{channel}}/std/primitive.bool.html"]' 'bool'
 // @has - '//code' 'pub use char as my_char;'
-// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char'
+// @has - '//code/a[@href="{{channel}}/std/primitive.char.html"]' 'char'
 pub mod p {
     pub use foo::bar::*;
 }
 
 // @has bar/baz/index.html
 // @has - '//code' 'pub use bool;'
-// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.bool.html"]' 'bool'
+// @has - '//code/a[@href="{{channel}}/std/primitive.bool.html"]' 'bool'
 // @has - '//code' 'pub use char as my_char;'
-// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.char.html"]' 'char'
+// @has - '//code/a[@href="{{channel}}/std/primitive.char.html"]' 'char'
 pub use foo::bar as baz;
 
 // @has bar/index.html
 // @has - '//code' 'pub use str;'
-// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html"]' 'str'
+// @has - '//code/a[@href="{{channel}}/std/primitive.str.html"]' 'str'
 // @has - '//code' 'pub use i32 as my_i32;'
-// @has - '//code/a[@href="https://doc.rust-lang.org/nightly/std/primitive.i32.html"]' 'i32'
+// @has - '//code/a[@href="{{channel}}/std/primitive.i32.html"]' 'i32'
 pub use str;
 pub use i32 as my_i32;
diff --git a/src/test/rustdoc/pub-method.rs b/src/test/rustdoc/pub-method.rs
index 8e88b2b5901..fa7de0aff6a 100644
--- a/src/test/rustdoc/pub-method.rs
+++ b/src/test/rustdoc/pub-method.rs
@@ -10,8 +10,8 @@ pub fn bar() -> usize {
 }
 
 // @has foo/struct.Foo.html
-// @has - '//*[@class="method"]' 'pub fn new()'
-// @has - '//*[@class="method"]' 'fn not_pub()'
+// @has - '//*[@class="method has-srclink"]' 'pub fn new()'
+// @has - '//*[@class="method has-srclink"]' 'fn not_pub()'
 pub struct Foo(usize);
 
 impl Foo {
diff --git a/src/test/rustdoc/sidebar-links-to-foreign-impl.rs b/src/test/rustdoc/sidebar-links-to-foreign-impl.rs
index 6219a2c3b90..d256fbe8de0 100644
--- a/src/test/rustdoc/sidebar-links-to-foreign-impl.rs
+++ b/src/test/rustdoc/sidebar-links-to-foreign-impl.rs
@@ -6,9 +6,9 @@
 // @has - '//*[@class="sidebar-title"][@href="#foreign-impls"]' 'Implementations on Foreign Types'
 // @has - '//h2[@id="foreign-impls"]' 'Implementations on Foreign Types'
 // @has - '//*[@class="sidebar-links"]/a[@href="#impl-Foo-for-u32"]' 'u32'
-// @has - '//h3[@id="impl-Foo-for-u32"]//code' 'impl Foo for u32'
+// @has - '//div[@id="impl-Foo-for-u32"]//code' 'impl Foo for u32'
 // @has - '//*[@class="sidebar-links"]/a[@href="#impl-Foo-for-%26%27a%20str"]' "&'a str"
-// @has - '//h3[@id="impl-Foo-for-%26%27a%20str"]//code' "impl<'a> Foo for &'a str"
+// @has - '//div[@id="impl-Foo-for-%26%27a%20str"]//code' "impl<'a> Foo for &'a str"
 pub trait Foo {}
 
 impl Foo for u32 {}
diff --git a/src/test/rustdoc/sized_trait.rs b/src/test/rustdoc/sized_trait.rs
index 26d12817afc..6730c71e90f 100644
--- a/src/test/rustdoc/sized_trait.rs
+++ b/src/test/rustdoc/sized_trait.rs
@@ -1,17 +1,17 @@
 #![crate_name = "foo"]
 
 // @has foo/struct.Bar.html
-// @!has - '//h3[@id="impl-Sized"]'
+// @!has - '//div[@id="impl-Sized"]'
 pub struct Bar {
     a: u16,
 }
 
 // @has foo/struct.Foo.html
-// @!has - '//h3[@id="impl-Sized"]'
+// @!has - '//div[@id="impl-Sized"]'
 pub struct Foo<T: ?Sized>(T);
 
 // @has foo/struct.Unsized.html
-// @has - '//h3[@id="impl-Sized"]/code' 'impl !Sized for Unsized'
+// @has - '//div[@id="impl-Sized"]/code' 'impl !Sized for Unsized'
 pub struct Unsized {
     data: [u8],
 }
diff --git a/src/test/rustdoc/spotlight-from-dependency.rs b/src/test/rustdoc/spotlight-from-dependency.rs
index ed42c435945..864cb0c400b 100644
--- a/src/test/rustdoc/spotlight-from-dependency.rs
+++ b/src/test/rustdoc/spotlight-from-dependency.rs
@@ -3,7 +3,7 @@
 use std::iter::Iterator;
 
 // @has foo/struct.Odd.html
-// @has - '//h4[@id="method.new"]//span[@class="notable-traits"]//code/span' 'impl Iterator for Odd'
+// @has - '//div[@id="method.new"]//span[@class="notable-traits"]//code/span' 'impl Iterator for Odd'
 pub struct Odd {
     current: usize,
 }
diff --git a/src/test/rustdoc/src-links-auto-impls.rs b/src/test/rustdoc/src-links-auto-impls.rs
index a1d183df0f1..6f609e080d3 100644
--- a/src/test/rustdoc/src-links-auto-impls.rs
+++ b/src/test/rustdoc/src-links-auto-impls.rs
@@ -1,12 +1,12 @@
 #![crate_name = "foo"]
 
 // @has foo/struct.Unsized.html
-// @has - '//h3[@id="impl-Sized"]/code' 'impl !Sized for Unsized'
-// @!has - '//h3[@id="impl-Sized"]/a[@class="srclink"]' '[src]'
-// @has - '//h3[@id="impl-Sync"]/code' 'impl Sync for Unsized'
-// @!has - '//h3[@id="impl-Sync"]/a[@class="srclink"]' '[src]'
-// @has - '//h3[@id="impl-Any"]/code' 'impl<T> Any for T'
-// @has - '//h3[@id="impl-Any"]/a[@class="srclink"]' '[src]'
+// @has - '//div[@id="impl-Sized"]/code' 'impl !Sized for Unsized'
+// @!has - '//div[@id="impl-Sized"]/a[@class="srclink"]' '[src]'
+// @has - '//div[@id="impl-Sync"]/code' 'impl Sync for Unsized'
+// @!has - '//div[@id="impl-Sync"]/a[@class="srclink"]' '[src]'
+// @has - '//div[@id="impl-Any"]/code' 'impl<T> Any for T'
+// @has - '//div[@id="impl-Any"]/a[@class="srclink"]' '[src]'
 pub struct Unsized {
     data: [u8],
 }
diff --git a/src/test/rustdoc/synthetic_auto/basic.rs b/src/test/rustdoc/synthetic_auto/basic.rs
index 0dd3a3f7a86..943596a0c85 100644
--- a/src/test/rustdoc/synthetic_auto/basic.rs
+++ b/src/test/rustdoc/synthetic_auto/basic.rs
@@ -1,8 +1,8 @@
 // @has basic/struct.Foo.html
 // @has - '//code' 'impl<T> Send for Foo<T> where T: Send'
 // @has - '//code' 'impl<T> Sync for Foo<T> where T: Sync'
-// @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0
-// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5
+// @count - '//*[@id="implementations-list"]//*[@class="impl has-srclink"]' 0
+// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 5
 pub struct Foo<T> {
     field: T,
 }
diff --git a/src/test/rustdoc/synthetic_auto/complex.rs b/src/test/rustdoc/synthetic_auto/complex.rs
index d951a20e2de..0213142266f 100644
--- a/src/test/rustdoc/synthetic_auto/complex.rs
+++ b/src/test/rustdoc/synthetic_auto/complex.rs
@@ -20,8 +20,8 @@ mod foo {
 }
 
 // @has complex/struct.NotOuter.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'a, T, K: \
-// ?Sized> Send for Outer<'a, T, K> where K: for<'b> Fn((&'b bool, &'a u8)) \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// "impl<'a, T, K: ?Sized> Send for Outer<'a, T, K> where K: for<'b> Fn((&'b bool, &'a u8)) \
 // -> &'b i8, T: MyTrait<'a>, <T as MyTrait<'a>>::MyItem: Copy, 'a: 'static"
 
 pub use foo::{Foo, Inner as NotInner, MyTrait as NotMyTrait, Outer as NotOuter};
diff --git a/src/test/rustdoc/synthetic_auto/lifetimes.rs b/src/test/rustdoc/synthetic_auto/lifetimes.rs
index 05c88f10822..c2e9b6f4046 100644
--- a/src/test/rustdoc/synthetic_auto/lifetimes.rs
+++ b/src/test/rustdoc/synthetic_auto/lifetimes.rs
@@ -9,11 +9,11 @@ where
 {}
 
 // @has lifetimes/struct.Foo.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'c, K> Send \
-// for Foo<'c, K> where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static"
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// "impl<'c, K> Send for Foo<'c, K> where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static"
 //
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'c, K> Sync \
-// for Foo<'c, K> where K: Sync"
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// "impl<'c, K> Sync for Foo<'c, K> where K: Sync"
 pub struct Foo<'c, K: 'c> {
     inner_field: Inner<'c, K>,
 }
diff --git a/src/test/rustdoc/synthetic_auto/manual.rs b/src/test/rustdoc/synthetic_auto/manual.rs
index 88ddd57349a..91fe6c351c5 100644
--- a/src/test/rustdoc/synthetic_auto/manual.rs
+++ b/src/test/rustdoc/synthetic_auto/manual.rs
@@ -1,12 +1,12 @@
 // @has manual/struct.Foo.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' 'impl<T> Sync for \
-// Foo<T> where T: Sync'
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// 'impl<T> Sync for Foo<T> where T: Sync'
 //
-// @has - '//*[@id="trait-implementations-list"]//*[@class="impl"]//code' \
+// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//code' \
 // 'impl<T> Send for Foo<T>'
 //
-// @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1
-// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 4
+// @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1
+// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]' 4
 pub struct Foo<T> {
     field: T,
 }
diff --git a/src/test/rustdoc/synthetic_auto/negative.rs b/src/test/rustdoc/synthetic_auto/negative.rs
index 53801542c95..16b36b56b68 100644
--- a/src/test/rustdoc/synthetic_auto/negative.rs
+++ b/src/test/rustdoc/synthetic_auto/negative.rs
@@ -3,11 +3,11 @@ pub struct Inner<T: Copy> {
 }
 
 // @has negative/struct.Outer.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<T> !Send for \
-// Outer<T>"
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// "impl<T> !Send for Outer<T>"
 //
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<T> \
-// !Sync for Outer<T>"
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// "impl<T> !Sync for Outer<T>"
 pub struct Outer<T: Copy> {
     inner_field: Inner<T>,
 }
diff --git a/src/test/rustdoc/synthetic_auto/nested.rs b/src/test/rustdoc/synthetic_auto/nested.rs
index d4d93a87ffc..a6cf5890dca 100644
--- a/src/test/rustdoc/synthetic_auto/nested.rs
+++ b/src/test/rustdoc/synthetic_auto/nested.rs
@@ -9,10 +9,10 @@ where
 }
 
 // @has nested/struct.Foo.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' 'impl<T> Send for \
-// Foo<T> where T: Copy'
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// 'impl<T> Send for Foo<T> where T: Copy'
 //
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
 // 'impl<T> Sync for Foo<T> where T: Sync'
 pub struct Foo<T> {
     inner_field: Inner<T>,
diff --git a/src/test/rustdoc/synthetic_auto/no-redundancy.rs b/src/test/rustdoc/synthetic_auto/no-redundancy.rs
index 3a23dc2cf95..5c744e3eb3c 100644
--- a/src/test/rustdoc/synthetic_auto/no-redundancy.rs
+++ b/src/test/rustdoc/synthetic_auto/no-redundancy.rs
@@ -9,8 +9,8 @@ where
 }
 
 // @has no_redundancy/struct.Outer.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<T> Send for \
-// Outer<T> where T: Copy + Send"
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// "impl<T> Send for Outer<T> where T: Copy + Send"
 pub struct Outer<T> {
     inner_field: Inner<T>,
 }
diff --git a/src/test/rustdoc/synthetic_auto/project.rs b/src/test/rustdoc/synthetic_auto/project.rs
index 060491e3cf1..baf9924b1ae 100644
--- a/src/test/rustdoc/synthetic_auto/project.rs
+++ b/src/test/rustdoc/synthetic_auto/project.rs
@@ -23,11 +23,12 @@ where
 }
 
 // @has project/struct.Foo.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'c, K> Send \
-// for Foo<'c, K> where K: MyTrait<MyItem = bool>, 'c: 'static"
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// "impl<'c, K> Send for Foo<'c, K> where K: MyTrait<MyItem = bool>, 'c: 'static"
 //
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<'c, K> Sync \
-// for Foo<'c, K> where K: MyTrait, <K as MyTrait>::MyItem: OtherTrait, 'c: 'static,"
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// "impl<'c, K> Sync for Foo<'c, K> where K: MyTrait, <K as MyTrait>::MyItem: OtherTrait, \
+// 'c: 'static,"
 pub struct Foo<'c, K: 'c> {
     inner_field: Inner<'c, K>,
 }
diff --git a/src/test/rustdoc/synthetic_auto/self-referential.rs b/src/test/rustdoc/synthetic_auto/self-referential.rs
index ecdbdf41b20..e96187e2c96 100644
--- a/src/test/rustdoc/synthetic_auto/self-referential.rs
+++ b/src/test/rustdoc/synthetic_auto/self-referential.rs
@@ -23,7 +23,7 @@ impl<T> Pattern for Wrapper<T> {
 
 
 // @has self_referential/struct.WriteAndThen.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<P1> Send for \
-// WriteAndThen<P1>  where  <P1 as Pattern>::Value: Send"
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// "impl<P1> Send for WriteAndThen<P1>  where  <P1 as Pattern>::Value: Send"
 pub struct WriteAndThen<P1>(pub P1::Value,pub <Constrain<P1, Wrapper<P1::Value>> as Pattern>::Value)
     where P1: Pattern;
diff --git a/src/test/rustdoc/synthetic_auto/static-region.rs b/src/test/rustdoc/synthetic_auto/static-region.rs
index a10e694c1b2..fc732a08ed4 100644
--- a/src/test/rustdoc/synthetic_auto/static-region.rs
+++ b/src/test/rustdoc/synthetic_auto/static-region.rs
@@ -3,8 +3,8 @@ pub trait OwnedTrait<'a> {
 }
 
 // @has static_region/struct.Owned.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]//code' "impl<T> Send for \
-// Owned<T> where <T as OwnedTrait<'static>>::Reader: Send"
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//code' \
+// "impl<T> Send for Owned<T> where <T as OwnedTrait<'static>>::Reader: Send"
 pub struct Owned<T> where T: OwnedTrait<'static> {
     marker: <T as OwnedTrait<'static>>::Reader,
 }
diff --git a/src/test/rustdoc/trait-attributes.rs b/src/test/rustdoc/trait-attributes.rs
index 2bb24a82193..d0dfb8759e6 100644
--- a/src/test/rustdoc/trait-attributes.rs
+++ b/src/test/rustdoc/trait-attributes.rs
@@ -2,7 +2,7 @@
 
 
 pub trait Foo {
-    // @has foo/trait.Foo.html '//h3[@id="tymethod.foo"]//div[@class="code-attribute"]' '#[must_use]'
+    // @has foo/trait.Foo.html '//div[@id="tymethod.foo"]//div[@class="code-attribute"]' '#[must_use]'
     #[must_use]
     fn foo();
 }
@@ -11,11 +11,11 @@ pub trait Foo {
 pub struct Bar;
 
 impl Bar {
-    // @has foo/struct.Bar.html '//h4[@id="method.bar"]//div[@class="code-attribute"]' '#[must_use]'
+    // @has foo/struct.Bar.html '//div[@id="method.bar"]//div[@class="code-attribute"]' '#[must_use]'
     #[must_use]
     pub fn bar() {}
 
-    // @has foo/struct.Bar.html '//h4[@id="method.bar2"]//div[@class="code-attribute"]' '#[must_use]'
+    // @has foo/struct.Bar.html '//div[@id="method.bar2"]//div[@class="code-attribute"]' '#[must_use]'
     #[must_use]
     pub fn bar2() {}
 }
diff --git a/src/test/rustdoc/trait-impl-items-links-and-anchors.rs b/src/test/rustdoc/trait-impl-items-links-and-anchors.rs
index c6a9313e821..5b7c04c0d44 100644
--- a/src/test/rustdoc/trait-impl-items-links-and-anchors.rs
+++ b/src/test/rustdoc/trait-impl-items-links-and-anchors.rs
@@ -8,58 +8,58 @@ pub trait MyTrait {
 
 
 impl MyTrait for String {
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedtype.Assoc-1"]//a[@class="type"]/@href' #associatedtype.Assoc
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedtype.Assoc-1"]//a[@class="anchor"]/@href' #associatedtype.Assoc-1
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedtype.Assoc-1"]//a[@class="type"]/@href' #associatedtype.Assoc
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedtype.Assoc-1"]//a[@class="anchor"]/@href' #associatedtype.Assoc-1
     type Assoc = ();
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedconstant.VALUE-1"]//a[@class="constant"]/@href' #associatedconstant.VALUE
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedconstant.VALUE-1"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-1
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-1"]//a[@class="constant"]/@href' #associatedconstant.VALUE
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-1"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-1
     const VALUE: u32 = 5;
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.trait_function"]//a[@class="fnname"]/@href' #tymethod.trait_function
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.trait_function"]//a[@class="anchor"]/@href' #method.trait_function
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.trait_function"]//a[@class="fnname"]/@href' #tymethod.trait_function
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.trait_function"]//a[@class="anchor"]/@href' #method.trait_function
     fn trait_function(&self) {}
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.defaulted_override-1"]//a[@class="fnname"]/@href' #method.defaulted_override
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.defaulted_override-1"]//a[@class="anchor"]/@href' #method.defaulted_override-1
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.defaulted_override-1"]//a[@class="fnname"]/@href' #method.defaulted_override
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.defaulted_override-1"]//a[@class="anchor"]/@href' #method.defaulted_override-1
     fn defaulted_override(&self) {}
 }
 
 impl MyTrait for Vec<u8> {
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedtype.Assoc-2"]//a[@class="type"]/@href' #associatedtype.Assoc
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedtype.Assoc-2"]//a[@class="anchor"]/@href' #associatedtype.Assoc-2
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedtype.Assoc-2"]//a[@class="type"]/@href' #associatedtype.Assoc
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedtype.Assoc-2"]//a[@class="anchor"]/@href' #associatedtype.Assoc-2
     type Assoc = ();
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedconstant.VALUE-2"]//a[@class="constant"]/@href' #associatedconstant.VALUE
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedconstant.VALUE-2"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-2
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-2"]//a[@class="constant"]/@href' #associatedconstant.VALUE
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-2"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-2
     const VALUE: u32 = 5;
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.trait_function"]//a[@class="fnname"]/@href' #tymethod.trait_function
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.trait_function-1"]//a[@class="anchor"]/@href' #method.trait_function-1
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.trait_function"]//a[@class="fnname"]/@href' #tymethod.trait_function
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.trait_function-1"]//a[@class="anchor"]/@href' #method.trait_function-1
     fn trait_function(&self) {}
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.defaulted_override-2"]//a[@class="fnname"]/@href' #method.defaulted_override
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.defaulted_override-2"]//a[@class="anchor"]/@href' #method.defaulted_override-2
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.defaulted_override-2"]//a[@class="fnname"]/@href' #method.defaulted_override
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.defaulted_override-2"]//a[@class="anchor"]/@href' #method.defaulted_override-2
     fn defaulted_override(&self) {}
 }
 
 impl MyTrait for MyStruct {
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedtype.Assoc-3"]//a[@class="type"]/@href' #associatedtype.Assoc
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedtype.Assoc-3"]//a[@class="anchor"]/@href' #associatedtype.Assoc-3
-    // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="associatedtype.Assoc"]//a[@class="type"]/@href' trait.MyTrait.html#associatedtype.Assoc
-    // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="associatedtype.Assoc"]//a[@class="anchor"]/@href' #associatedtype.Assoc
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedtype.Assoc-3"]//a[@class="type"]/@href' #associatedtype.Assoc
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedtype.Assoc-3"]//a[@class="anchor"]/@href' #associatedtype.Assoc-3
+    // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="associatedtype.Assoc"]//a[@class="type"]/@href' trait.MyTrait.html#associatedtype.Assoc
+    // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="associatedtype.Assoc"]//a[@class="anchor"]/@href' #associatedtype.Assoc
     type Assoc = bool;
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedconstant.VALUE-3"]//a[@class="constant"]/@href' #associatedconstant.VALUE
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="associatedconstant.VALUE-3"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-3
-    // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="associatedconstant.VALUE"]//a[@class="constant"]/@href' trait.MyTrait.html#associatedconstant.VALUE
-    // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="associatedconstant.VALUE"]//a[@class="anchor"]/@href' #associatedconstant.VALUE
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-3"]//a[@class="constant"]/@href' #associatedconstant.VALUE
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="associatedconstant.VALUE-3"]//a[@class="anchor"]/@href' #associatedconstant.VALUE-3
+    // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="associatedconstant.VALUE"]//a[@class="constant"]/@href' trait.MyTrait.html#associatedconstant.VALUE
+    // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="associatedconstant.VALUE"]//a[@class="anchor"]/@href' #associatedconstant.VALUE
     const VALUE: u32 = 20;
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.trait_function-2"]//a[@class="fnname"]/@href' #tymethod.trait_function
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.trait_function-2"]//a[@class="anchor"]/@href' #method.trait_function-2
-    // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="method.trait_function"]//a[@class="fnname"]/@href' trait.MyTrait.html#tymethod.trait_function
-    // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="method.trait_function"]//a[@class="anchor"]/@href' #method.trait_function
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.trait_function-2"]//a[@class="fnname"]/@href' #tymethod.trait_function
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.trait_function-2"]//a[@class="anchor"]/@href' #method.trait_function-2
+    // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="method.trait_function"]//a[@class="fnname"]/@href' trait.MyTrait.html#tymethod.trait_function
+    // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="method.trait_function"]//a[@class="anchor"]/@href' #method.trait_function
     fn trait_function(&self) {}
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.defaulted_override-3"]//a[@class="fnname"]/@href' #method.defaulted_override
-    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//h4[@id="method.defaulted_override-3"]//a[@class="anchor"]/@href' #method.defaulted_override-3
-    // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="method.defaulted_override"]//a[@class="fnname"]/@href' trait.MyTrait.html#method.defaulted_override
-    // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="method.defaulted_override"]//a[@class="anchor"]/@href' #method.defaulted_override
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.defaulted_override-3"]//a[@class="fnname"]/@href' #method.defaulted_override
+    // @has trait_impl_items_links_and_anchors/trait.MyTrait.html '//div[@id="method.defaulted_override-3"]//a[@class="anchor"]/@href' #method.defaulted_override-3
+    // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="method.defaulted_override"]//a[@class="fnname"]/@href' trait.MyTrait.html#method.defaulted_override
+    // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="method.defaulted_override"]//a[@class="anchor"]/@href' #method.defaulted_override
     fn defaulted_override(&self) {}
-    // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="method.defaulted"]//a[@class="fnname"]/@href' trait.MyTrait.html#method.defaulted
-    // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//h4[@id="method.defaulted"]//a[@class="anchor"]/@href' #method.defaulted
+    // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="method.defaulted"]//a[@class="fnname"]/@href' trait.MyTrait.html#method.defaulted
+    // @has trait_impl_items_links_and_anchors/struct.MyStruct.html '//div[@id="method.defaulted"]//a[@class="anchor"]/@href' #method.defaulted
 }
 
 pub struct MyStruct;
diff --git a/src/test/rustdoc/typedef.rs b/src/test/rustdoc/typedef.rs
index 7f834d3d5a5..21a7fdda769 100644
--- a/src/test/rustdoc/typedef.rs
+++ b/src/test/rustdoc/typedef.rs
@@ -9,8 +9,8 @@ impl MyStruct {
 }
 
 // @has typedef/type.MyAlias.html
-// @has - '//*[@class="impl"]//code' 'impl MyAlias'
-// @has - '//*[@class="impl"]//code' 'impl MyTrait for MyAlias'
+// @has - '//*[@class="impl has-srclink"]//code' 'impl MyAlias'
+// @has - '//*[@class="impl has-srclink"]//code' 'impl MyTrait for MyAlias'
 // @has - 'Alias docstring'
 // @has - '//*[@class="sidebar"]//p[@class="location"]' 'Type Definition MyAlias'
 // @has - '//*[@class="sidebar"]//a[@href="#implementations"]' 'Methods'
diff --git a/src/test/rustdoc/unindent.rs b/src/test/rustdoc/unindent.rs
index d10e1ec89c5..372af5f4672 100644
--- a/src/test/rustdoc/unindent.rs
+++ b/src/test/rustdoc/unindent.rs
@@ -1,5 +1,3 @@
-#![feature(external_doc)]
-
 #![crate_name = "foo"]
 
 // @has foo/struct.Example.html
@@ -51,7 +49,7 @@ pub struct I;
 // @matches - '//div[@class="docblock"]/p' '(?m)a\nno whitespace\nJust some text.\Z'
 ///a
 ///no whitespace
-#[doc(include = "unindent.md")]
+#[doc = include_str!("unindent.md")]
 pub struct J;
 
 // @has foo/struct.K.html
@@ -60,5 +58,5 @@ pub struct J;
 ///
 ///    4 whitespaces!
 ///
-#[doc(include = "unindent.md")]
+#[doc = include_str!("unindent.md")]
 pub struct K;
diff --git a/src/test/rustdoc/where.rs b/src/test/rustdoc/where.rs
index 992cddfe72a..f204a27d7d3 100644
--- a/src/test/rustdoc/where.rs
+++ b/src/test/rustdoc/where.rs
@@ -11,7 +11,7 @@ pub fn charlie<C>() where C: MyTrait {}
 
 pub struct Delta<D>(D);
 
-// @has foo/struct.Delta.html '//*[@class="impl"]//code' \
+// @has foo/struct.Delta.html '//*[@class="impl has-srclink"]//code' \
 //          "impl<D> Delta<D> where D: MyTrait"
 impl<D> Delta<D> where D: MyTrait {
     pub fn delta() {}
@@ -19,7 +19,7 @@ impl<D> Delta<D> where D: MyTrait {
 
 pub struct Echo<E>(E);
 
-// @has foo/struct.Echo.html '//*[@class="impl"]//code' \
+// @has foo/struct.Echo.html '//*[@class="impl has-srclink"]//code' \
 //          "impl<E> MyTrait for Echo<E> where E: MyTrait"
 // @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//code' \
 //          "impl<E> MyTrait for Echo<E> where E: MyTrait"
@@ -27,7 +27,7 @@ impl<E> MyTrait for Echo<E> where E: MyTrait {}
 
 pub enum Foxtrot<F> { Foxtrot1(F) }
 
-// @has foo/enum.Foxtrot.html '//*[@class="impl"]//code' \
+// @has foo/enum.Foxtrot.html '//*[@class="impl has-srclink"]//code' \
 //          "impl<F> MyTrait for Foxtrot<F> where F: MyTrait"
 // @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//code' \
 //          "impl<F> MyTrait for Foxtrot<F> where F: MyTrait"
diff --git a/src/test/ui/c-variadic/variadic-ffi-4.stderr b/src/test/ui/c-variadic/variadic-ffi-4.stderr
index dd67514d02a..cf73403bbae 100644
--- a/src/test/ui/c-variadic/variadic-ffi-4.stderr
+++ b/src/test/ui/c-variadic/variadic-ffi-4.stderr
@@ -64,6 +64,10 @@ LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut
    |                                               has type `&mut VaListImpl<'1>`
 LL |     ap0 = &mut ap1;
    |     ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2`
+   |
+   = note: requirement occurs because of a mutable reference to VaListImpl<'_>
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: lifetime may not live long enough
   --> $DIR/variadic-ffi-4.rs:28:5
@@ -74,6 +78,10 @@ LL | pub unsafe extern "C" fn no_escape4(_: usize, mut ap0: &mut VaListImpl, mut
    |                                               has type `&mut VaListImpl<'1>`
 LL |     ap0 = &mut ap1;
    |     ^^^^^^^^^^^^^^ assignment requires that `'2` must outlive `'1`
+   |
+   = note: requirement occurs because of a mutable reference to VaListImpl<'_>
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error[E0597]: `ap1` does not live long enough
   --> $DIR/variadic-ffi-4.rs:28:11
diff --git a/src/test/ui/const-generics/array-impls/into-iter-impls-length-32.rs b/src/test/ui/const-generics/array-impls/into-iter-impls-length-32.rs
index 6ba1b2813a1..457e5ae6049 100644
--- a/src/test/ui/const-generics/array-impls/into-iter-impls-length-32.rs
+++ b/src/test/ui/const-generics/array-impls/into-iter-impls-length-32.rs
@@ -9,31 +9,31 @@ use std::{
 };
 
 pub fn yes_iterator() -> impl Iterator<Item = i32> {
-    IntoIter::new([0i32; 32])
+    IntoIterator::into_iter([0i32; 32])
 }
 
 pub fn yes_double_ended_iterator() -> impl DoubleEndedIterator {
-    IntoIter::new([0i32; 32])
+    IntoIterator::into_iter([0i32; 32])
 }
 
 pub fn yes_exact_size_iterator() -> impl ExactSizeIterator {
-    IntoIter::new([0i32; 32])
+    IntoIterator::into_iter([0i32; 32])
 }
 
 pub fn yes_fused_iterator() -> impl FusedIterator {
-    IntoIter::new([0i32; 32])
+    IntoIterator::into_iter([0i32; 32])
 }
 
 pub fn yes_trusted_len() -> impl TrustedLen {
-    IntoIter::new([0i32; 32])
+    IntoIterator::into_iter([0i32; 32])
 }
 
 pub fn yes_clone() -> impl Clone {
-    IntoIter::new([0i32; 32])
+    IntoIterator::into_iter([0i32; 32])
 }
 
 pub fn yes_debug() -> impl Debug {
-    IntoIter::new([0i32; 32])
+    IntoIterator::into_iter([0i32; 32])
 }
 
 
diff --git a/src/test/ui/const-generics/array-impls/into-iter-impls-length-33.rs b/src/test/ui/const-generics/array-impls/into-iter-impls-length-33.rs
index deafde2912b..4f343f3f97e 100644
--- a/src/test/ui/const-generics/array-impls/into-iter-impls-length-33.rs
+++ b/src/test/ui/const-generics/array-impls/into-iter-impls-length-33.rs
@@ -9,31 +9,31 @@ use std::{
 };
 
 pub fn yes_iterator() -> impl Iterator<Item = i32> {
-    IntoIter::new([0i32; 33])
+    IntoIterator::into_iter([0i32; 33])
 }
 
 pub fn yes_double_ended_iterator() -> impl DoubleEndedIterator {
-    IntoIter::new([0i32; 33])
+    IntoIterator::into_iter([0i32; 33])
 }
 
 pub fn yes_exact_size_iterator() -> impl ExactSizeIterator {
-    IntoIter::new([0i32; 33])
+    IntoIterator::into_iter([0i32; 33])
 }
 
 pub fn yes_fused_iterator() -> impl FusedIterator {
-    IntoIter::new([0i32; 33])
+    IntoIterator::into_iter([0i32; 33])
 }
 
 pub fn yes_trusted_len() -> impl TrustedLen {
-    IntoIter::new([0i32; 33])
+    IntoIterator::into_iter([0i32; 33])
 }
 
 pub fn yes_clone() -> impl Clone {
-    IntoIter::new([0i32; 33])
+    IntoIterator::into_iter([0i32; 33])
 }
 
 pub fn yes_debug() -> impl Debug {
-    IntoIter::new([0i32; 33])
+    IntoIterator::into_iter([0i32; 33])
 }
 
 
diff --git a/src/test/ui/const-generics/defaults/forward-declared.rs b/src/test/ui/const-generics/defaults/forward-declared.rs
new file mode 100644
index 00000000000..09fc105320e
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/forward-declared.rs
@@ -0,0 +1,15 @@
+#![feature(const_generics_defaults)]
+
+struct Foo<const N: usize = M, const M: usize = 10>;
+//~^ ERROR generic parameters with a default cannot use forward declared identifiers
+
+enum Bar<const N: usize = M, const M: usize = 10> {}
+//~^ ERROR generic parameters with a default cannot use forward declared identifiers
+
+struct Foo2<const N: usize = N>;
+//~^ ERROR generic parameters with a default cannot use forward declared identifiers
+
+enum Bar2<const N: usize = N> {}
+//~^ ERROR generic parameters with a default cannot use forward declared identifiers
+
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/forward-declared.stderr b/src/test/ui/const-generics/defaults/forward-declared.stderr
new file mode 100644
index 00000000000..a6c4a7ae4ef
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/forward-declared.stderr
@@ -0,0 +1,27 @@
+error[E0128]: generic parameters with a default cannot use forward declared identifiers
+  --> $DIR/forward-declared.rs:3:29
+   |
+LL | struct Foo<const N: usize = M, const M: usize = 10>;
+   |                             ^ defaulted generic parameters cannot be forward declared
+
+error[E0128]: generic parameters with a default cannot use forward declared identifiers
+  --> $DIR/forward-declared.rs:6:27
+   |
+LL | enum Bar<const N: usize = M, const M: usize = 10> {}
+   |                           ^ defaulted generic parameters cannot be forward declared
+
+error[E0128]: generic parameters with a default cannot use forward declared identifiers
+  --> $DIR/forward-declared.rs:9:30
+   |
+LL | struct Foo2<const N: usize = N>;
+   |                              ^ defaulted generic parameters cannot be forward declared
+
+error[E0128]: generic parameters with a default cannot use forward declared identifiers
+  --> $DIR/forward-declared.rs:12:28
+   |
+LL | enum Bar2<const N: usize = N> {}
+   |                            ^ defaulted generic parameters cannot be forward declared
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0128`.
diff --git a/src/test/ui/const-ptr/out_of_bounds_read.rs b/src/test/ui/const-ptr/out_of_bounds_read.rs
deleted file mode 100644
index 183aa9e5122..00000000000
--- a/src/test/ui/const-ptr/out_of_bounds_read.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-// error-pattern: any use of this value will cause an error
-
-#![feature(const_ptr_read)]
-#![feature(const_ptr_offset)]
-
-fn main() {
-    use std::ptr;
-
-    const DATA: [u32; 1] = [42];
-
-    const PAST_END_PTR: *const u32 = unsafe { DATA.as_ptr().add(1) };
-
-    const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) };
-    const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() };
-    const _MUT_READ: u32 = unsafe { (PAST_END_PTR as *mut u32).read() };
-}
diff --git a/src/test/ui/const-ptr/out_of_bounds_read.stderr b/src/test/ui/const-ptr/out_of_bounds_read.stderr
deleted file mode 100644
index 6c4092e3e5c..00000000000
--- a/src/test/ui/const-ptr/out_of_bounds_read.stderr
+++ /dev/null
@@ -1,59 +0,0 @@
-error: any use of this value will cause an error
-  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         memory access failed: pointer must be in-bounds at offset 8, but is outside bounds of alloc6 which has size 4
-   |         inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |         inside `_READ` at $DIR/out_of_bounds_read.rs:13:33
-   | 
-  ::: $DIR/out_of_bounds_read.rs:13:5
-   |
-LL |     const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) };
-   |     ------------------------------------------------------
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: any use of this value will cause an error
-  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         memory access failed: pointer must be in-bounds at offset 8, but is outside bounds of alloc6 which has size 4
-   |         inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |         inside `ptr::const_ptr::<impl *const u32>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |         inside `_CONST_READ` at $DIR/out_of_bounds_read.rs:14:39
-   | 
-  ::: $DIR/out_of_bounds_read.rs:14:5
-   |
-LL |     const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() };
-   |     --------------------------------------------------------
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: any use of this value will cause an error
-  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |
-LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         memory access failed: pointer must be in-bounds at offset 8, but is outside bounds of alloc6 which has size 4
-   |         inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   |         inside `ptr::mut_ptr::<impl *mut u32>::read` at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-   |         inside `_MUT_READ` at $DIR/out_of_bounds_read.rs:15:37
-   | 
-  ::: $DIR/out_of_bounds_read.rs:15:5
-   |
-LL |     const _MUT_READ: u32 = unsafe { (PAST_END_PTR as *mut u32).read() };
-   |     --------------------------------------------------------------------
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: aborting due to 3 previous errors
-
diff --git a/src/test/ui/consts/copy-intrinsic.rs b/src/test/ui/consts/copy-intrinsic.rs
deleted file mode 100644
index 9dc595f37fa..00000000000
--- a/src/test/ui/consts/copy-intrinsic.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-// ignore-tidy-linelength
-#![feature(const_mut_refs, const_intrinsic_copy, const_ptr_offset)]
-use std::{ptr, mem};
-
-const COPY_ZERO: () = unsafe {
-    // Since we are not copying anything, this should be allowed.
-    let src = ();
-    let mut dst = ();
-    ptr::copy_nonoverlapping(&src as *const _ as *const i32, &mut dst as *mut _ as *mut i32, 0);
-};
-
-const COPY_OOB_1: () = unsafe {
-    let mut x = 0i32;
-    let dangle = (&mut x as *mut i32).wrapping_add(10);
-    // Even if the first ptr is an int ptr and this is a ZST copy, we should detect dangling 2nd ptrs.
-    ptr::copy_nonoverlapping(0x100 as *const i32, dangle, 0); //~ ERROR any use of this value will cause an error
-    //~| memory access failed: pointer must be in-bounds
-    //~| previously accepted
-};
-const COPY_OOB_2: () = unsafe {
-    let x = 0i32;
-    let dangle = (&x as *const i32).wrapping_add(10);
-    // Even if the second ptr is an int ptr and this is a ZST copy, we should detect dangling 1st ptrs.
-    ptr::copy_nonoverlapping(dangle, 0x100 as *mut i32, 0); //~ ERROR any use of this value will cause an error
-    //~| memory access failed: pointer must be in-bounds
-    //~| previously accepted
-};
-
-const COPY_SIZE_OVERFLOW: () = unsafe {
-    let x = 0;
-    let mut y = 0;
-    ptr::copy(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1)); //~ ERROR any use of this value will cause an error
-    //~| overflow computing total size of `copy`
-    //~| previously accepted
-};
-const COPY_NONOVERLAPPING_SIZE_OVERFLOW: () = unsafe {
-    let x = 0;
-    let mut y = 0;
-    ptr::copy_nonoverlapping(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1)); //~ ERROR any use of this value will cause an error
-    //~| overflow computing total size of `copy_nonoverlapping`
-    //~| previously accepted
-};
-
-fn main() {
-}
diff --git a/src/test/ui/consts/copy-intrinsic.stderr b/src/test/ui/consts/copy-intrinsic.stderr
deleted file mode 100644
index 2736cdeac69..00000000000
--- a/src/test/ui/consts/copy-intrinsic.stderr
+++ /dev/null
@@ -1,69 +0,0 @@
-error: any use of this value will cause an error
-  --> $DIR/copy-intrinsic.rs:16:5
-   |
-LL | / const COPY_OOB_1: () = unsafe {
-LL | |     let mut x = 0i32;
-LL | |     let dangle = (&mut x as *mut i32).wrapping_add(10);
-LL | |     // Even if the first ptr is an int ptr and this is a ZST copy, we should detect dangling 2nd ptrs.
-LL | |     ptr::copy_nonoverlapping(0x100 as *const i32, dangle, 0);
-   | |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: pointer must be in-bounds at offset 40, but is outside bounds of alloc4 which has size 4
-LL | |
-LL | |
-LL | | };
-   | |__-
-   |
-   = note: `#[deny(const_err)]` on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: any use of this value will cause an error
-  --> $DIR/copy-intrinsic.rs:24:5
-   |
-LL | / const COPY_OOB_2: () = unsafe {
-LL | |     let x = 0i32;
-LL | |     let dangle = (&x as *const i32).wrapping_add(10);
-LL | |     // Even if the second ptr is an int ptr and this is a ZST copy, we should detect dangling 1st ptrs.
-LL | |     ptr::copy_nonoverlapping(dangle, 0x100 as *mut i32, 0);
-   | |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: pointer must be in-bounds at offset 40, but is outside bounds of alloc6 which has size 4
-LL | |
-LL | |
-LL | | };
-   | |__-
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: any use of this value will cause an error
-  --> $DIR/copy-intrinsic.rs:32:5
-   |
-LL | / const COPY_SIZE_OVERFLOW: () = unsafe {
-LL | |     let x = 0;
-LL | |     let mut y = 0;
-LL | |     ptr::copy(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1));
-   | |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy`
-LL | |
-LL | |
-LL | | };
-   | |__-
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: any use of this value will cause an error
-  --> $DIR/copy-intrinsic.rs:39:5
-   |
-LL | / const COPY_NONOVERLAPPING_SIZE_OVERFLOW: () = unsafe {
-LL | |     let x = 0;
-LL | |     let mut y = 0;
-LL | |     ptr::copy_nonoverlapping(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1));
-   | |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy_nonoverlapping`
-LL | |
-LL | |
-LL | | };
-   | |__-
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error: aborting due to 4 previous errors
-
diff --git a/src/test/ui/consts/miri_unleashed/tls.stderr b/src/test/ui/consts/miri_unleashed/tls.stderr
index 30309da499f..62e2dc71210 100644
--- a/src/test/ui/consts/miri_unleashed/tls.stderr
+++ b/src/test/ui/consts/miri_unleashed/tls.stderr
@@ -2,13 +2,13 @@ error[E0080]: could not evaluate static initializer
   --> $DIR/tls.rs:12:25
    |
 LL |     unsafe { let _val = A; }
-   |                         ^ cannot access thread local static (DefId(0:6 ~ tls[f423]::A))
+   |                         ^ cannot access thread local static (DefId(0:6 ~ tls[317d]::A))
 
 error[E0080]: could not evaluate static initializer
   --> $DIR/tls.rs:19:26
    |
 LL |     unsafe { let _val = &A; }
-   |                          ^ cannot access thread local static (DefId(0:6 ~ tls[f423]::A))
+   |                          ^ cannot access thread local static (DefId(0:6 ~ tls[317d]::A))
 
 warning: skipping const checks
    |
diff --git a/src/test/ui/dep-graph/dep-graph-check-attr.rs b/src/test/ui/dep-graph/dep-graph-check-attr.rs
index 1026efc1b1d..a45bf24f8c1 100644
--- a/src/test/ui/dep-graph/dep-graph-check-attr.rs
+++ b/src/test/ui/dep-graph/dep-graph-check-attr.rs
@@ -5,7 +5,7 @@
 #![allow(dead_code)]
 #![allow(unused_variables)]
 
-#[rustc_dirty(hir_owner)] //~ ERROR attribute requires -Z query-dep-graph
+#[rustc_clean(hir_owner)] //~ ERROR attribute requires -Z query-dep-graph
 fn main() {}
 
 #[rustc_if_this_changed(hir_owner)] //~ ERROR attribute requires -Z query-dep-graph
diff --git a/src/test/ui/dep-graph/dep-graph-check-attr.stderr b/src/test/ui/dep-graph/dep-graph-check-attr.stderr
index 945a4237c12..46f4e4358cf 100644
--- a/src/test/ui/dep-graph/dep-graph-check-attr.stderr
+++ b/src/test/ui/dep-graph/dep-graph-check-attr.stderr
@@ -1,7 +1,7 @@
 error: attribute requires -Z query-dep-graph to be enabled
   --> $DIR/dep-graph-check-attr.rs:8:1
    |
-LL | #[rustc_dirty(hir_owner)]
+LL | #[rustc_clean(hir_owner)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: attribute requires -Z query-dep-graph to be enabled
diff --git a/src/test/ui/deprecation/deprecation-lint.rs b/src/test/ui/deprecation/deprecation-lint.rs
index b6c791c15fd..35e42a6857f 100644
--- a/src/test/ui/deprecation/deprecation-lint.rs
+++ b/src/test/ui/deprecation/deprecation-lint.rs
@@ -430,6 +430,24 @@ mod this_crate2 {
             // the patterns are all fine:
             (..) = x;
     }
+
+    #[derive(Debug)]
+    #[deprecated(note = "Use something else instead")]
+    enum DeprecatedDebugEnum {
+        Variant1 { value: Option<String> },
+    }
+
+    #[allow(deprecated)]
+    impl DeprecatedDebugEnum {
+        fn new() -> Self {
+            DeprecatedDebugEnum::Variant1 { value: None }
+        }
+    }
+
+    #[allow(deprecated)]
+    pub fn allow_dep() {
+        let _ = DeprecatedDebugEnum::new();
+    }
 }
 
 fn main() {}
diff --git a/src/test/ui/error-codes/E0121.stderr b/src/test/ui/error-codes/E0121.stderr
index ad854837ae5..246f69558ff 100644
--- a/src/test/ui/error-codes/E0121.stderr
+++ b/src/test/ui/error-codes/E0121.stderr
@@ -14,7 +14,7 @@ LL | static BAR: _ = "test";
    |             ^
    |             |
    |             not allowed in type signatures
-   |             help: replace `_` with the correct type: `&str`
+   |             help: replace with the correct type: `&str`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/extern/external-doc-error.rs b/src/test/ui/extern/external-doc-error.rs
deleted file mode 100644
index 4e89f7464da..00000000000
--- a/src/test/ui/extern/external-doc-error.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-// normalize-stderr-test: "not-a-file.md:.*\(" -> "not-a-file.md: $$FILE_NOT_FOUND_MSG ("
-
-#![feature(external_doc)]
-
-#[doc(include = "not-a-file.md")]
-pub struct SomeStruct; //~^ ERROR couldn't read
-
-#[doc(include = "auxiliary/invalid-utf8.txt")]
-pub struct InvalidUtf8; //~^ ERROR wasn't a utf-8 file
-
-#[doc(include)]
-pub struct MissingPath; //~^ ERROR expected path
-                        //~| HELP provide a file path with `=`
-                        //~| SUGGESTION include = "<path>"
-
-#[doc(include("../README.md"))]
-pub struct InvalidPathSyntax; //~^ ERROR expected path
-                              //~| HELP provide a file path with `=`
-                              //~| SUGGESTION include = "../README.md"
-
-#[doc(include = 123)]
-pub struct InvalidPathType; //~^ ERROR expected path
-                            //~| HELP provide a file path with `=`
-                            //~| SUGGESTION include = "<path>"
-
-#[doc(include(123))]
-pub struct InvalidPathSyntaxAndType; //~^ ERROR expected path
-                                     //~| HELP provide a file path with `=`
-                                     //~| SUGGESTION include = "<path>"
-
-fn main() {}
diff --git a/src/test/ui/extern/external-doc-error.stderr b/src/test/ui/extern/external-doc-error.stderr
deleted file mode 100644
index b180cd66c52..00000000000
--- a/src/test/ui/extern/external-doc-error.stderr
+++ /dev/null
@@ -1,38 +0,0 @@
-error: couldn't read $DIR/not-a-file.md: $FILE_NOT_FOUND_MSG (os error 2)
-  --> $DIR/external-doc-error.rs:5:17
-   |
-LL | #[doc(include = "not-a-file.md")]
-   |                 ^^^^^^^^^^^^^^^ couldn't read file
-
-error: $DIR/auxiliary/invalid-utf8.txt wasn't a utf-8 file
-  --> $DIR/external-doc-error.rs:8:17
-   |
-LL | #[doc(include = "auxiliary/invalid-utf8.txt")]
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ contains invalid utf-8
-
-error: expected path to external documentation
-  --> $DIR/external-doc-error.rs:11:7
-   |
-LL | #[doc(include)]
-   |       ^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
-
-error: expected path to external documentation
-  --> $DIR/external-doc-error.rs:16:7
-   |
-LL | #[doc(include("../README.md"))]
-   |       ^^^^^^^^^^^^^^^^^^^^^^^ help: provide a file path with `=`: `include = "../README.md"`
-
-error: expected path to external documentation
-  --> $DIR/external-doc-error.rs:21:7
-   |
-LL | #[doc(include = 123)]
-   |       ^^^^^^^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
-
-error: expected path to external documentation
-  --> $DIR/external-doc-error.rs:26:7
-   |
-LL | #[doc(include(123))]
-   |       ^^^^^^^^^^^^ help: provide a file path with `=`: `include = "<path>"`
-
-error: aborting due to 6 previous errors
-
diff --git a/src/test/ui/feature-gates/feature-gate-external_doc.rs b/src/test/ui/feature-gates/feature-gate-external_doc.rs
deleted file mode 100644
index 4e6e293846c..00000000000
--- a/src/test/ui/feature-gates/feature-gate-external_doc.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-#[doc(include="asdf.md")] //~ ERROR: `#[doc(include)]` is experimental
-                          //~| ERROR: `#[doc(include)]` is experimental
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-external_doc.stderr b/src/test/ui/feature-gates/feature-gate-external_doc.stderr
deleted file mode 100644
index bd2aefe90c1..00000000000
--- a/src/test/ui/feature-gates/feature-gate-external_doc.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0658]: `#[doc(include)]` is experimental
-  --> $DIR/feature-gate-external_doc.rs:1:1
-   |
-LL | #[doc(include="asdf.md")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #44732 <https://github.com/rust-lang/rust/issues/44732> for more information
-   = help: add `#![feature(external_doc)]` to the crate attributes to enable
-
-error[E0658]: `#[doc(include)]` is experimental
-  --> $DIR/feature-gate-external_doc.rs:1:1
-   |
-LL | #[doc(include="asdf.md")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #44732 <https://github.com/rust-lang/rust/issues/44732> for more information
-   = help: add `#![feature(external_doc)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.rs b/src/test/ui/feature-gates/feature-gate-raw-dylib-2.rs
index 518aa20dd68..518aa20dd68 100644
--- a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.rs
+++ b/src/test/ui/feature-gates/feature-gate-raw-dylib-2.rs
diff --git a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.stderr b/src/test/ui/feature-gates/feature-gate-raw-dylib-2.stderr
index dbee5f316b0..dbee5f316b0 100644
--- a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.stderr
+++ b/src/test/ui/feature-gates/feature-gate-raw-dylib-2.stderr
diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-gnu.rs b/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-gnu.rs
new file mode 100644
index 00000000000..33f9c539313
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-gnu.rs
@@ -0,0 +1,8 @@
+// gate-test-raw_dylib
+// only-windows-gnu
+#[link(name = "foo", kind = "raw-dylib")]
+//~^ ERROR: kind="raw-dylib" is unstable
+//~| WARNING: `#[link(...)]` with `kind = "raw-dylib"` not supported on windows-gnu
+extern "C" {}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-gnu.stderr b/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-gnu.stderr
new file mode 100644
index 00000000000..14dfadf4126
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-gnu.stderr
@@ -0,0 +1,18 @@
+warning: `#[link(...)]` with `kind = "raw-dylib"` not supported on windows-gnu
+  --> $DIR/feature-gate-raw-dylib-windows-gnu.rs:3:1
+   |
+LL | #[link(name = "foo", kind = "raw-dylib")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0658]: kind="raw-dylib" is unstable
+  --> $DIR/feature-gate-raw-dylib-windows-gnu.rs:3:1
+   |
+LL | #[link(name = "foo", kind = "raw-dylib")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
+   = help: add `#![feature(raw_dylib)]` to the crate attributes to enable
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.rs b/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-msvc.rs
index 29edd0f9ef9..49de24ea9ab 100644
--- a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.rs
+++ b/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-msvc.rs
@@ -1,3 +1,5 @@
+// gate-test-raw_dylib
+// only-windows-msvc
 #[link(name = "foo", kind = "raw-dylib")]
 //~^ ERROR: kind="raw-dylib" is unstable
 extern "C" {}
diff --git a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.stderr b/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-msvc.stderr
index a670b6c6c2a..11988080812 100644
--- a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.stderr
+++ b/src/test/ui/feature-gates/feature-gate-raw-dylib-windows-msvc.stderr
@@ -1,5 +1,5 @@
 error[E0658]: kind="raw-dylib" is unstable
-  --> $DIR/feature-gate-raw-dylib.rs:1:1
+  --> $DIR/feature-gate-raw-dylib-windows-msvc.rs:3:1
    |
 LL | #[link(name = "foo", kind = "raw-dylib")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/generator/print/generator-print-verbose-1.stderr b/src/test/ui/generator/print/generator-print-verbose-1.stderr
index bd0d27ff3e9..78100318dc3 100644
--- a/src/test/ui/generator/print/generator-print-verbose-1.stderr
+++ b/src/test/ui/generator/print/generator-print-verbose-1.stderr
@@ -12,7 +12,7 @@ note: generator is not `Send` as this value is used across a yield
   --> $DIR/generator-print-verbose-1.rs:35:9
    |
 LL |         let _non_send_gen = make_non_send_generator();
-   |             ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[70c9]::make_non_send_generator::{opaque#0}), [])` which is not `Send`
+   |             ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[317d]::make_non_send_generator::{opaque#0}), [])` which is not `Send`
 LL |         yield;
    |         ^^^^^ yield occurs here, with `_non_send_gen` maybe used later
 LL |     };
@@ -30,10 +30,10 @@ LL |     require_send(send_gen);
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
    = note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>`
    = note: required because it appears within the type `[make_gen2<Arc<RefCell<i32>>>::{closure#0} upvar_tys=(Arc<RefCell<i32>>) {()}]`
-   = note: required because it appears within the type `Opaque(DefId(0:39 ~ generator_print_verbose_1[70c9]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])`
-   = note: required because it appears within the type `Opaque(DefId(0:42 ~ generator_print_verbose_1[70c9]::make_non_send_generator2::{opaque#0}), [])`
-   = note: required because it appears within the type `{Opaque(DefId(0:42 ~ generator_print_verbose_1[70c9]::make_non_send_generator2::{opaque#0}), []), ()}`
-   = note: required because it appears within the type `[test2::{closure#0} upvar_tys=() {Opaque(DefId(0:42 ~ generator_print_verbose_1[70c9]::make_non_send_generator2::{opaque#0}), []), ()}]`
+   = note: required because it appears within the type `Opaque(DefId(0:39 ~ generator_print_verbose_1[317d]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])`
+   = note: required because it appears within the type `Opaque(DefId(0:42 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), [])`
+   = note: required because it appears within the type `{Opaque(DefId(0:42 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), []), ()}`
+   = note: required because it appears within the type `[test2::{closure#0} upvar_tys=() {Opaque(DefId(0:42 ~ generator_print_verbose_1[317d]::make_non_send_generator2::{opaque#0}), []), ()}]`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/intrinsics/issue-84297-reifying-copy.rs b/src/test/ui/intrinsics/issue-84297-reifying-copy.rs
new file mode 100644
index 00000000000..08ba9ce7ecb
--- /dev/null
+++ b/src/test/ui/intrinsics/issue-84297-reifying-copy.rs
@@ -0,0 +1,9 @@
+// check-pass
+
+fn main() {
+    let _unused = if true {
+        core::ptr::copy::<i32>
+    } else {
+        core::ptr::copy_nonoverlapping::<i32>
+    };
+}
diff --git a/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr
index 6a744812e41..a84c048fab9 100644
--- a/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr
+++ b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr
@@ -37,7 +37,7 @@ LL |               const A = "A".$fn();
    |                     ^
    |                     |
    |                     not allowed in type signatures
-   |                     help: replace `_` with the correct type: `bool`
+   |                     help: replace with the correct type: `bool`
 ...
 LL | / suite! {
 LL | |     len;
diff --git a/src/test/ui/layout/issue-84108.rs b/src/test/ui/layout/issue-84108.rs
new file mode 100644
index 00000000000..dd025c9b443
--- /dev/null
+++ b/src/test/ui/layout/issue-84108.rs
@@ -0,0 +1,14 @@
+// See issue #84108 -- this is a test to ensure we do not ICE
+// on this invalid code.
+
+#![crate_type = "lib"]
+
+static FOO: (dyn AsRef<OsStr>, u8) = ("hello", 42);
+//~^ ERROR cannot find type `OsStr` in this scope
+
+const BAR: (&Path, [u8], usize) = ("hello", [], 42);
+//~^ ERROR cannot find type `Path` in this scope
+//~| ERROR the size for values of type `[u8]` cannot be known at compilation time
+
+static BAZ: ([u8], usize) = ([], 0);
+//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
diff --git a/src/test/ui/layout/issue-84108.stderr b/src/test/ui/layout/issue-84108.stderr
new file mode 100644
index 00000000000..36be6424110
--- /dev/null
+++ b/src/test/ui/layout/issue-84108.stderr
@@ -0,0 +1,44 @@
+error[E0412]: cannot find type `OsStr` in this scope
+  --> $DIR/issue-84108.rs:6:24
+   |
+LL | static FOO: (dyn AsRef<OsStr>, u8) = ("hello", 42);
+   |                        ^^^^^ not found in this scope
+   |
+help: consider importing this struct
+   |
+LL | use std::ffi::OsStr;
+   |
+
+error[E0412]: cannot find type `Path` in this scope
+  --> $DIR/issue-84108.rs:9:14
+   |
+LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42);
+   |              ^^^^ not found in this scope
+   |
+help: consider importing this struct
+   |
+LL | use std::path::Path;
+   |
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/issue-84108.rs:9:12
+   |
+LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42);
+   |            ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+   = note: only the last element of a tuple may have a dynamically sized type
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/issue-84108.rs:13:13
+   |
+LL | static BAZ: ([u8], usize) = ([], 0);
+   |             ^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+   = note: only the last element of a tuple may have a dynamically sized type
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0277, E0412.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/lint/force-warn/force-allowed-by-default-lint.rs b/src/test/ui/lint/force-warn/force-allowed-by-default-lint.rs
new file mode 100644
index 00000000000..d4a5056ddf3
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-allowed-by-default-lint.rs
@@ -0,0 +1,11 @@
+// compile-flags: --force-warns elided_lifetimes_in_paths
+// check-pass
+
+struct Foo<'a> {
+    x: &'a u32,
+}
+
+fn foo(x: &Foo) {}
+//~^ WARN hidden lifetime parameters in types are deprecated
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-allowed-by-default-lint.stderr b/src/test/ui/lint/force-warn/force-allowed-by-default-lint.stderr
new file mode 100644
index 00000000000..0e0e934c765
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-allowed-by-default-lint.stderr
@@ -0,0 +1,10 @@
+warning: hidden lifetime parameters in types are deprecated
+  --> $DIR/force-allowed-by-default-lint.rs:8:12
+   |
+LL | fn foo(x: &Foo) {}
+   |            ^^^- help: indicate the anonymous lifetime: `<'_>`
+   |
+   = note: warning forced by `force-warns` commandline option
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.rs b/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.rs
new file mode 100644
index 00000000000..afd2d6ec322
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.rs
@@ -0,0 +1,9 @@
+// compile-flags: --force-warns const_err
+// check-pass
+
+#![allow(const_err)]
+const C: i32 = 1 / 0;
+//~^ WARN any use of this value will cause an error
+//~| WARN this was previously accepted by the compiler
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.stderr b/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.stderr
new file mode 100644
index 00000000000..bad12f94b18
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-allowed-deny-by-default-lint.stderr
@@ -0,0 +1,14 @@
+warning: any use of this value will cause an error
+  --> $DIR/force-allowed-deny-by-default-lint.rs:5:16
+   |
+LL | const C: i32 = 1 / 0;
+   | ---------------^^^^^-
+   |                |
+   |                attempt to divide `1_i32` by zero
+   |
+   = note: warning forced by `force-warns` commandline option
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/force-warn/force-allowed-warning.rs b/src/test/ui/lint/force-warn/force-allowed-warning.rs
new file mode 100644
index 00000000000..5c83c525e38
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-allowed-warning.rs
@@ -0,0 +1,9 @@
+// compile-flags: --force-warns dead_code
+// check-pass
+
+#![allow(dead_code)]
+
+fn dead_function() {}
+//~^ WARN function is never used
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-allowed-warning.stderr b/src/test/ui/lint/force-warn/force-allowed-warning.stderr
new file mode 100644
index 00000000000..145798a32a9
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-allowed-warning.stderr
@@ -0,0 +1,10 @@
+warning: function is never used: `dead_function`
+  --> $DIR/force-allowed-warning.rs:6:4
+   |
+LL | fn dead_function() {}
+   |    ^^^^^^^^^^^^^
+   |
+   = note: warning forced by `force-warns` commandline option
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/force-warn/force-deny-by-default-lint.rs b/src/test/ui/lint/force-warn/force-deny-by-default-lint.rs
new file mode 100644
index 00000000000..4f267f085d5
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-deny-by-default-lint.rs
@@ -0,0 +1,8 @@
+// compile-flags: --force-warns const_err
+// check-pass
+
+const C: i32 = 1 / 0;
+//~^ WARN any use of this value will cause an error
+//~| WARN this was previously accepted by the compiler
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-deny-by-default-lint.stderr b/src/test/ui/lint/force-warn/force-deny-by-default-lint.stderr
new file mode 100644
index 00000000000..4b004cf367d
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-deny-by-default-lint.stderr
@@ -0,0 +1,14 @@
+warning: any use of this value will cause an error
+  --> $DIR/force-deny-by-default-lint.rs:4:16
+   |
+LL | const C: i32 = 1 / 0;
+   | ---------------^^^^^-
+   |                |
+   |                attempt to divide `1_i32` by zero
+   |
+   = note: warning forced by `force-warns` commandline option
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.rs b/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.rs
new file mode 100644
index 00000000000..5501faa437a
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.rs
@@ -0,0 +1,9 @@
+// compile-flags: --force-warns dead_code
+// check-pass
+
+#![allow(warnings)]
+
+fn dead_function() {}
+//~^ WARN function is never used
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.stderr b/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.stderr
new file mode 100644
index 00000000000..577dbe1fea8
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-lint-allow-all-warnings.stderr
@@ -0,0 +1,10 @@
+warning: function is never used: `dead_function`
+  --> $DIR/force-lint-allow-all-warnings.rs:6:4
+   |
+LL | fn dead_function() {}
+   |    ^^^^^^^^^^^^^
+   |
+   = note: warning forced by `force-warns` commandline option
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.rs b/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.rs
new file mode 100644
index 00000000000..9009971f0cf
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.rs
@@ -0,0 +1,9 @@
+// compile-flags: --force-warns nonstandard_style
+// check-pass
+
+#![allow(warnings)]
+
+pub fn FUNCTION() {}
+//~^ WARN function `FUNCTION` should have a snake case name
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.stderr b/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.stderr
new file mode 100644
index 00000000000..8665fa2610a
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-lint-group-allow-all-warnings.stderr
@@ -0,0 +1,10 @@
+warning: function `FUNCTION` should have a snake case name
+  --> $DIR/force-lint-group-allow-all-warnings.rs:6:8
+   |
+LL | pub fn FUNCTION() {}
+   |        ^^^^^^^^ help: convert the identifier to snake case: `function`
+   |
+   = note: warning forced by `force-warns` commandline option
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/force-warn/force-lint-in-allowed-group.rs b/src/test/ui/lint/force-warn/force-lint-in-allowed-group.rs
new file mode 100644
index 00000000000..b68b979ca11
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-lint-in-allowed-group.rs
@@ -0,0 +1,12 @@
+// compile-flags: --force-warns bare_trait_objects
+// check-pass
+
+#![allow(rust_2018_idioms)]
+
+pub trait SomeTrait {}
+
+pub fn function(_x: Box<SomeTrait>) {}
+//~^ WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN this was previously accepted by the compiler
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-lint-in-allowed-group.stderr b/src/test/ui/lint/force-warn/force-lint-in-allowed-group.stderr
new file mode 100644
index 00000000000..40750ffea8c
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-lint-in-allowed-group.stderr
@@ -0,0 +1,12 @@
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/force-lint-in-allowed-group.rs:8:25
+   |
+LL | pub fn function(_x: Box<SomeTrait>) {}
+   |                         ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
+   |
+   = note: warning forced by `force-warns` commandline option
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/force-warn/force-warn-group-allow-warning.rs b/src/test/ui/lint/force-warn/force-warn-group-allow-warning.rs
new file mode 100644
index 00000000000..357a79b383d
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-warn-group-allow-warning.rs
@@ -0,0 +1,12 @@
+// compile-flags: --force-warns rust_2018_idioms
+// check-pass
+
+#![allow(bare_trait_objects)]
+
+pub trait SomeTrait {}
+
+pub fn function(_x: Box<SomeTrait>) {}
+//~^ WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN this was previously accepted by the compiler
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-warn-group-allow-warning.stderr b/src/test/ui/lint/force-warn/force-warn-group-allow-warning.stderr
new file mode 100644
index 00000000000..88ae846caa0
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-warn-group-allow-warning.stderr
@@ -0,0 +1,12 @@
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/force-warn-group-allow-warning.rs:8:25
+   |
+LL | pub fn function(_x: Box<SomeTrait>) {}
+   |                         ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
+   |
+   = note: warning forced by `force-warns` commandline option
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/force-warn/force-warn-group.rs b/src/test/ui/lint/force-warn/force-warn-group.rs
new file mode 100644
index 00000000000..a4615df42de
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-warn-group.rs
@@ -0,0 +1,12 @@
+// compile-flags: --force-warns rust_2018_idioms
+// check-pass
+
+#![allow(rust_2018_idioms)]
+
+pub trait SomeTrait {}
+
+pub fn function(_x: Box<SomeTrait>) {}
+//~^ WARN trait objects without an explicit `dyn` are deprecated
+//~| WARN this was previously accepted by the compiler
+
+fn main() {}
diff --git a/src/test/ui/lint/force-warn/force-warn-group.stderr b/src/test/ui/lint/force-warn/force-warn-group.stderr
new file mode 100644
index 00000000000..f808727991e
--- /dev/null
+++ b/src/test/ui/lint/force-warn/force-warn-group.stderr
@@ -0,0 +1,12 @@
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/force-warn-group.rs:8:25
+   |
+LL | pub fn function(_x: Box<SomeTrait>) {}
+   |                         ^^^^^^^^^ help: use `dyn`: `dyn SomeTrait`
+   |
+   = note: warning forced by `force-warns` commandline option
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2021 edition!
+   = note: for more information, see issue #80165 <https://github.com/rust-lang/rust/issues/80165>
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/lint/lint-ctypes-fn.rs b/src/test/ui/lint/lint-ctypes-fn.rs
index e69d0dab496..c18cb881032 100644
--- a/src/test/ui/lint/lint-ctypes-fn.rs
+++ b/src/test/ui/lint/lint-ctypes-fn.rs
@@ -8,6 +8,8 @@ extern crate libc;
 use std::default::Default;
 use std::marker::PhantomData;
 
+trait Trait {}
+
 trait Mirror { type It: ?Sized; }
 
 impl<T: ?Sized> Mirror for T { type It = Self; }
@@ -74,6 +76,15 @@ pub extern "C" fn box_type(p: Box<u32>) { }
 
 pub extern "C" fn opt_box_type(p: Option<Box<u32>>) { }
 
+pub extern "C" fn boxed_slice(p: Box<[u8]>) { }
+//~^ ERROR: uses type `Box<[u8]>`
+
+pub extern "C" fn boxed_string(p: Box<str>) { }
+//~^ ERROR: uses type `Box<str>`
+
+pub extern "C" fn boxed_trait(p: Box<dyn Trait>) { }
+//~^ ERROR: uses type `Box<dyn Trait>`
+
 pub extern "C" fn char_type(p: char) { }
 //~^ ERROR uses type `char`
 
diff --git a/src/test/ui/lint/lint-ctypes-fn.stderr b/src/test/ui/lint/lint-ctypes-fn.stderr
index e6a0778ddb2..d591d4ad292 100644
--- a/src/test/ui/lint/lint-ctypes-fn.stderr
+++ b/src/test/ui/lint/lint-ctypes-fn.stderr
@@ -1,5 +1,5 @@
 error: `extern` fn uses type `[u32]`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:67:33
+  --> $DIR/lint-ctypes-fn.rs:69:33
    |
 LL | pub extern "C" fn slice_type(p: &[u32]) { }
    |                                 ^^^^^^ not FFI-safe
@@ -13,7 +13,7 @@ LL | #![deny(improper_ctypes_definitions)]
    = note: slices have no C equivalent
 
 error: `extern` fn uses type `str`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:70:31
+  --> $DIR/lint-ctypes-fn.rs:72:31
    |
 LL | pub extern "C" fn str_type(p: &str) { }
    |                               ^^^^ not FFI-safe
@@ -21,8 +21,32 @@ LL | pub extern "C" fn str_type(p: &str) { }
    = help: consider using `*const u8` and a length instead
    = note: string slices have no C equivalent
 
+error: `extern` fn uses type `Box<[u8]>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-fn.rs:79:34
+   |
+LL | pub extern "C" fn boxed_slice(p: Box<[u8]>) { }
+   |                                  ^^^^^^^^^ not FFI-safe
+   |
+   = note: box cannot be represented as a single pointer
+
+error: `extern` fn uses type `Box<str>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-fn.rs:82:35
+   |
+LL | pub extern "C" fn boxed_string(p: Box<str>) { }
+   |                                   ^^^^^^^^ not FFI-safe
+   |
+   = note: box cannot be represented as a single pointer
+
+error: `extern` fn uses type `Box<dyn Trait>`, which is not FFI-safe
+  --> $DIR/lint-ctypes-fn.rs:85:34
+   |
+LL | pub extern "C" fn boxed_trait(p: Box<dyn Trait>) { }
+   |                                  ^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = note: box cannot be represented as a single pointer
+
 error: `extern` fn uses type `char`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:77:32
+  --> $DIR/lint-ctypes-fn.rs:88:32
    |
 LL | pub extern "C" fn char_type(p: char) { }
    |                                ^^^^ not FFI-safe
@@ -31,7 +55,7 @@ LL | pub extern "C" fn char_type(p: char) { }
    = note: the `char` type has no C equivalent
 
 error: `extern` fn uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:80:32
+  --> $DIR/lint-ctypes-fn.rs:91:32
    |
 LL | pub extern "C" fn i128_type(p: i128) { }
    |                                ^^^^ not FFI-safe
@@ -39,7 +63,7 @@ LL | pub extern "C" fn i128_type(p: i128) { }
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` fn uses type `u128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:83:32
+  --> $DIR/lint-ctypes-fn.rs:94:32
    |
 LL | pub extern "C" fn u128_type(p: u128) { }
    |                                ^^^^ not FFI-safe
@@ -47,7 +71,7 @@ LL | pub extern "C" fn u128_type(p: u128) { }
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:86:33
+  --> $DIR/lint-ctypes-fn.rs:97:33
    |
 LL | pub extern "C" fn tuple_type(p: (i32, i32)) { }
    |                                 ^^^^^^^^^^ not FFI-safe
@@ -56,7 +80,7 @@ LL | pub extern "C" fn tuple_type(p: (i32, i32)) { }
    = note: tuples have unspecified layout
 
 error: `extern` fn uses type `(i32, i32)`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:89:34
+  --> $DIR/lint-ctypes-fn.rs:100:34
    |
 LL | pub extern "C" fn tuple_type2(p: I32Pair) { }
    |                                  ^^^^^^^ not FFI-safe
@@ -65,7 +89,7 @@ LL | pub extern "C" fn tuple_type2(p: I32Pair) { }
    = note: tuples have unspecified layout
 
 error: `extern` fn uses type `ZeroSize`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:92:32
+  --> $DIR/lint-ctypes-fn.rs:103:32
    |
 LL | pub extern "C" fn zero_size(p: ZeroSize) { }
    |                                ^^^^^^^^ not FFI-safe
@@ -73,26 +97,26 @@ LL | pub extern "C" fn zero_size(p: ZeroSize) { }
    = help: consider adding a member to this struct
    = note: this struct has no fields
 note: the type is defined here
-  --> $DIR/lint-ctypes-fn.rs:26:1
+  --> $DIR/lint-ctypes-fn.rs:28:1
    |
 LL | pub struct ZeroSize;
    | ^^^^^^^^^^^^^^^^^^^^
 
 error: `extern` fn uses type `ZeroSizeWithPhantomData`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:95:40
+  --> $DIR/lint-ctypes-fn.rs:106:40
    |
 LL | pub extern "C" fn zero_size_phantom(p: ZeroSizeWithPhantomData) { }
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
    |
    = note: composed only of `PhantomData`
 note: the type is defined here
-  --> $DIR/lint-ctypes-fn.rs:61:1
+  --> $DIR/lint-ctypes-fn.rs:63:1
    |
 LL | pub struct ZeroSizeWithPhantomData(PhantomData<i32>);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `extern` fn uses type `PhantomData<bool>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:98:51
+  --> $DIR/lint-ctypes-fn.rs:109:51
    |
 LL | pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData<bool> {
    |                                                   ^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -100,7 +124,7 @@ LL | pub extern "C" fn zero_size_phantom_toplevel() -> PhantomData<bool> {
    = note: composed only of `PhantomData`
 
 error: `extern` fn uses type `fn()`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:103:30
+  --> $DIR/lint-ctypes-fn.rs:114:30
    |
 LL | pub extern "C" fn fn_type(p: RustFn) { }
    |                              ^^^^^^ not FFI-safe
@@ -109,7 +133,7 @@ LL | pub extern "C" fn fn_type(p: RustFn) { }
    = note: this function pointer has Rust-specific calling convention
 
 error: `extern` fn uses type `fn()`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:106:31
+  --> $DIR/lint-ctypes-fn.rs:117:31
    |
 LL | pub extern "C" fn fn_type2(p: fn()) { }
    |                               ^^^^ not FFI-safe
@@ -118,7 +142,7 @@ LL | pub extern "C" fn fn_type2(p: fn()) { }
    = note: this function pointer has Rust-specific calling convention
 
 error: `extern` fn uses type `i128`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:111:39
+  --> $DIR/lint-ctypes-fn.rs:122:39
    |
 LL | pub extern "C" fn transparent_i128(p: TransparentI128) { }
    |                                       ^^^^^^^^^^^^^^^ not FFI-safe
@@ -126,7 +150,7 @@ LL | pub extern "C" fn transparent_i128(p: TransparentI128) { }
    = note: 128-bit integers don't currently have a known stable ABI
 
 error: `extern` fn uses type `str`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:114:38
+  --> $DIR/lint-ctypes-fn.rs:125:38
    |
 LL | pub extern "C" fn transparent_str(p: TransparentStr) { }
    |                                      ^^^^^^^^^^^^^^ not FFI-safe
@@ -135,7 +159,7 @@ LL | pub extern "C" fn transparent_str(p: TransparentStr) { }
    = note: string slices have no C equivalent
 
 error: `extern` fn uses type `PhantomData<bool>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:160:43
+  --> $DIR/lint-ctypes-fn.rs:171:43
    |
 LL | pub extern "C" fn unused_generic2<T>() -> PhantomData<bool> {
    |                                           ^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -143,7 +167,7 @@ LL | pub extern "C" fn unused_generic2<T>() -> PhantomData<bool> {
    = note: composed only of `PhantomData`
 
 error: `extern` fn uses type `Vec<T>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:173:39
+  --> $DIR/lint-ctypes-fn.rs:184:39
    |
 LL | pub extern "C" fn used_generic4<T>(x: Vec<T>) { }
    |                                       ^^^^^^ not FFI-safe
@@ -152,7 +176,7 @@ LL | pub extern "C" fn used_generic4<T>(x: Vec<T>) { }
    = note: this struct has unspecified layout
 
 error: `extern` fn uses type `Vec<T>`, which is not FFI-safe
-  --> $DIR/lint-ctypes-fn.rs:176:41
+  --> $DIR/lint-ctypes-fn.rs:187:41
    |
 LL | pub extern "C" fn used_generic5<T>() -> Vec<T> {
    |                                         ^^^^^^ not FFI-safe
@@ -160,5 +184,5 @@ LL | pub extern "C" fn used_generic5<T>() -> Vec<T> {
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
    = note: this struct has unspecified layout
 
-error: aborting due to 17 previous errors
+error: aborting due to 20 previous errors
 
diff --git a/src/test/ui/lto-duplicate-symbols.stderr b/src/test/ui/lto-duplicate-symbols.stderr
index 891cda8016c..713b79bae32 100644
--- a/src/test/ui/lto-duplicate-symbols.stderr
+++ b/src/test/ui/lto-duplicate-symbols.stderr
@@ -1,6 +1,6 @@
 warning: Linking globals named 'foo': symbol multiply defined!
 
-error: failed to load bc of "lto-duplicate-symbols2.lto_duplicate_symbols2.288b404e693a75b4-cgu.0.rcgu.o": 
+error: failed to load bc of "lto-duplicate-symbols2.lto_duplicate_symbols2.3a1fbbbh-cgu.0.rcgu.o": 
 
 error: aborting due to previous error; 1 warning emitted
 
diff --git a/src/test/ui/macros/local-ambiguity-multiple-parsing-options.stderr b/src/test/ui/macros/local-ambiguity-multiple-parsing-options.stderr
index 0ae56c42221..68b278fd3c8 100644
--- a/src/test/ui/macros/local-ambiguity-multiple-parsing-options.stderr
+++ b/src/test/ui/macros/local-ambiguity-multiple-parsing-options.stderr
@@ -1,10 +1,10 @@
-error: local ambiguity: multiple parsing options: built-in NTs ident ('i') or ident ('j').
+error: local ambiguity when calling macro `ambiguity`: multiple parsing options: built-in NTs ident ('i') or ident ('j').
   --> $DIR/local-ambiguity-multiple-parsing-options.rs:7:12
    |
 LL | ambiguity!(error);
    |            ^^^^^
 
-error: local ambiguity: multiple parsing options: built-in NTs ident ('i') or ident ('j').
+error: local ambiguity when calling macro `ambiguity`: multiple parsing options: built-in NTs ident ('i') or ident ('j').
   --> $DIR/local-ambiguity-multiple-parsing-options.rs:8:12
    |
 LL | ambiguity!(error);
diff --git a/src/test/ui/manual/manual-link-unsupported-kind.rs b/src/test/ui/manual/manual-link-unsupported-kind.rs
new file mode 100644
index 00000000000..34814db593f
--- /dev/null
+++ b/src/test/ui/manual/manual-link-unsupported-kind.rs
@@ -0,0 +1,5 @@
+// compile-flags:-l raw-dylib=foo
+// error-pattern: unknown library kind `raw-dylib`, expected one of dylib, framework, or static
+
+fn main() {
+}
diff --git a/src/test/ui/manual/manual-link-unsupported-kind.stderr b/src/test/ui/manual/manual-link-unsupported-kind.stderr
new file mode 100644
index 00000000000..acb4463cb04
--- /dev/null
+++ b/src/test/ui/manual/manual-link-unsupported-kind.stderr
@@ -0,0 +1,2 @@
+error: unknown library kind `raw-dylib`, expected one of dylib, framework, or static
+
diff --git a/src/test/ui/match/match-ref-mut-invariance.nll.stderr b/src/test/ui/match/match-ref-mut-invariance.nll.stderr
index 1658efa28bf..1dc29d2088c 100644
--- a/src/test/ui/match/match-ref-mut-invariance.nll.stderr
+++ b/src/test/ui/match/match-ref-mut-invariance.nll.stderr
@@ -9,6 +9,9 @@ LL |         match self.0 { ref mut x => x }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a mutable reference to &i32
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/match/match-ref-mut-let-invariance.nll.stderr b/src/test/ui/match/match-ref-mut-let-invariance.nll.stderr
index dc227a36566..8b87c3da28b 100644
--- a/src/test/ui/match/match-ref-mut-let-invariance.nll.stderr
+++ b/src/test/ui/match/match-ref-mut-let-invariance.nll.stderr
@@ -10,6 +10,9 @@ LL |         x
    |         ^ returning this value requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a mutable reference to &i32
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/type-check-pointer-coercions.stderr b/src/test/ui/nll/type-check-pointer-coercions.stderr
index 39fd98f7151..ccb3d33ac40 100644
--- a/src/test/ui/nll/type-check-pointer-coercions.stderr
+++ b/src/test/ui/nll/type-check-pointer-coercions.stderr
@@ -34,6 +34,9 @@ LL |     x
    |     ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable pointer to &i32
+   = note: mutable pointers are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-coercions.rs:13:5
@@ -47,6 +50,9 @@ LL |     x
    |     ^ returning this value requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a mutable pointer to &i32
+   = note: mutable pointers are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 help: `'b` and `'a` must be the same: replace one with the other
 
diff --git a/src/test/ui/nll/type-check-pointer-comparisons.stderr b/src/test/ui/nll/type-check-pointer-comparisons.stderr
index f350b861eb6..b488af820b8 100644
--- a/src/test/ui/nll/type-check-pointer-comparisons.stderr
+++ b/src/test/ui/nll/type-check-pointer-comparisons.stderr
@@ -9,6 +9,9 @@ LL |     x == y;
    |     ^ requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a mutable reference to &i32
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-comparisons.rs:6:10
@@ -21,6 +24,9 @@ LL |     x == y;
    |          ^ requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable reference to &i32
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 help: `'a` and `'b` must be the same: replace one with the other
 
@@ -35,6 +41,9 @@ LL |     x == y;
    |     ^ requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a mutable pointer to &i32
+   = note: mutable pointers are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-comparisons.rs:12:10
@@ -47,6 +56,9 @@ LL |     x == y;
    |          ^ requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable pointer to &i32
+   = note: mutable pointers are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 help: `'a` and `'b` must be the same: replace one with the other
 
@@ -61,6 +73,9 @@ LL |     f == g;
    |     ^ requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a mutable reference to &i32
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: lifetime may not live long enough
   --> $DIR/type-check-pointer-comparisons.rs:18:10
@@ -73,6 +88,9 @@ LL |     f == g;
    |          ^ requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable reference to &i32
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 help: `'a` and `'b` must be the same: replace one with the other
 
diff --git a/src/test/ui/panics/panic-macro-any-wrapped.rs b/src/test/ui/panics/panic-macro-any-wrapped.rs
index 95ae6ffe8be..100ac10c767 100644
--- a/src/test/ui/panics/panic-macro-any-wrapped.rs
+++ b/src/test/ui/panics/panic-macro-any-wrapped.rs
@@ -1,5 +1,5 @@
 // run-fail
-// error-pattern:panicked at 'Box<Any>'
+// error-pattern:panicked at 'Box<dyn Any>'
 // ignore-emscripten no processes
 
 #![allow(non_fmt_panic)]
diff --git a/src/test/ui/panics/panic-macro-any.rs b/src/test/ui/panics/panic-macro-any.rs
index d2a7ba3713a..a5ba30220e8 100644
--- a/src/test/ui/panics/panic-macro-any.rs
+++ b/src/test/ui/panics/panic-macro-any.rs
@@ -1,5 +1,5 @@
 // run-fail
-// error-pattern:panicked at 'Box<Any>'
+// error-pattern:panicked at 'Box<dyn Any>'
 // ignore-emscripten no processes
 
 #![feature(box_syntax)]
diff --git a/src/test/ui/parser/issue-84104.rs b/src/test/ui/parser/issue-84104.rs
new file mode 100644
index 00000000000..998949b94a4
--- /dev/null
+++ b/src/test/ui/parser/issue-84104.rs
@@ -0,0 +1,3 @@
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: expected one of
+#[i=i::<ښܖ<
diff --git a/src/test/ui/parser/issue-84104.stderr b/src/test/ui/parser/issue-84104.stderr
new file mode 100644
index 00000000000..aff31f2c971
--- /dev/null
+++ b/src/test/ui/parser/issue-84104.stderr
@@ -0,0 +1,16 @@
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-84104.rs:3:13
+   |
+LL | #[i=i::<ښܖ<
+   |  -          ^
+   |  |
+   |  unclosed delimiter
+
+error: expected one of `>`, a const expression, lifetime, or type, found `]`
+  --> $DIR/issue-84104.rs:3:13
+   |
+LL | #[i=i::<ښܖ<
+   |             ^ expected one of `>`, a const expression, lifetime, or type
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/parser/issue-84148-1.rs b/src/test/ui/parser/issue-84148-1.rs
new file mode 100644
index 00000000000..25f7ba4d1f8
--- /dev/null
+++ b/src/test/ui/parser/issue-84148-1.rs
@@ -0,0 +1,4 @@
+fn f(t:for<>t?)
+//~^ ERROR: expected parameter name
+//~| ERROR: expected one of
+//~| ERROR: expected one of
diff --git a/src/test/ui/parser/issue-84148-1.stderr b/src/test/ui/parser/issue-84148-1.stderr
new file mode 100644
index 00000000000..98506568d82
--- /dev/null
+++ b/src/test/ui/parser/issue-84148-1.stderr
@@ -0,0 +1,23 @@
+error: expected parameter name, found `?`
+  --> $DIR/issue-84148-1.rs:1:14
+   |
+LL | fn f(t:for<>t?)
+   |              ^ expected parameter name
+
+error: expected one of `(`, `)`, `+`, `,`, `::`, or `<`, found `?`
+  --> $DIR/issue-84148-1.rs:1:14
+   |
+LL | fn f(t:for<>t?)
+   |              ^
+   |              |
+   |              expected one of `(`, `)`, `+`, `,`, `::`, or `<`
+   |              help: missing `,`
+
+error: expected one of `->`, `;`, `where`, or `{`, found `<eof>`
+  --> $DIR/issue-84148-1.rs:1:15
+   |
+LL | fn f(t:for<>t?)
+   |               ^ expected one of `->`, `;`, `where`, or `{`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/parser/issue-84148-2.rs b/src/test/ui/parser/issue-84148-2.rs
new file mode 100644
index 00000000000..257a3fd6720
--- /dev/null
+++ b/src/test/ui/parser/issue-84148-2.rs
@@ -0,0 +1,4 @@
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: expected parameter name
+// error-pattern: expected one of
+fn f(t:for<>t?
diff --git a/src/test/ui/parser/issue-84148-2.stderr b/src/test/ui/parser/issue-84148-2.stderr
new file mode 100644
index 00000000000..6f314da4360
--- /dev/null
+++ b/src/test/ui/parser/issue-84148-2.stderr
@@ -0,0 +1,31 @@
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-84148-2.rs:4:16
+   |
+LL | fn f(t:for<>t?
+   |     -          ^
+   |     |
+   |     unclosed delimiter
+
+error: expected parameter name, found `?`
+  --> $DIR/issue-84148-2.rs:4:14
+   |
+LL | fn f(t:for<>t?
+   |              ^ expected parameter name
+
+error: expected one of `(`, `)`, `+`, `,`, `::`, or `<`, found `?`
+  --> $DIR/issue-84148-2.rs:4:14
+   |
+LL | fn f(t:for<>t?
+   |              ^
+   |              |
+   |              expected one of `(`, `)`, `+`, `,`, `::`, or `<`
+   |              help: missing `,`
+
+error: expected one of `->`, `;`, `where`, or `{`, found `<eof>`
+  --> $DIR/issue-84148-2.rs:4:16
+   |
+LL | fn f(t:for<>t?
+   |                ^ expected one of `->`, `;`, `where`, or `{`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/parser/unmatched-langle-1.rs b/src/test/ui/parser/unmatched-langle-1.rs
new file mode 100644
index 00000000000..fdf2ae39801
--- /dev/null
+++ b/src/test/ui/parser/unmatched-langle-1.rs
@@ -0,0 +1,9 @@
+// Check that a suggestion is issued if there are too many `<`s in a
+// generic argument list, and that the parser recovers properly.
+
+fn main() {
+    foo::<<<<Ty<i32>>();
+    //~^ ERROR: unmatched angle brackets
+    //~| ERROR: cannot find function `foo` in this scope [E0425]
+    //~| ERROR: cannot find type `Ty` in this scope [E0412]
+}
diff --git a/src/test/ui/parser/unmatched-langle-1.stderr b/src/test/ui/parser/unmatched-langle-1.stderr
new file mode 100644
index 00000000000..c8072b4c59a
--- /dev/null
+++ b/src/test/ui/parser/unmatched-langle-1.stderr
@@ -0,0 +1,22 @@
+error: unmatched angle brackets
+  --> $DIR/unmatched-langle-1.rs:5:10
+   |
+LL |     foo::<<<<Ty<i32>>();
+   |          ^^^ help: remove extra angle brackets
+
+error[E0425]: cannot find function `foo` in this scope
+  --> $DIR/unmatched-langle-1.rs:5:5
+   |
+LL |     foo::<<<<Ty<i32>>();
+   |     ^^^ not found in this scope
+
+error[E0412]: cannot find type `Ty` in this scope
+  --> $DIR/unmatched-langle-1.rs:5:14
+   |
+LL |     foo::<<<<Ty<i32>>();
+   |              ^^ not found in this scope
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0412, E0425.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/parser/unmatched-langle-2.rs b/src/test/ui/parser/unmatched-langle-2.rs
new file mode 100644
index 00000000000..8de0d7d89e4
--- /dev/null
+++ b/src/test/ui/parser/unmatched-langle-2.rs
@@ -0,0 +1,15 @@
+// When there are too many opening `<`s, the compiler would previously
+// suggest nonsense if the `<`s were interspersed with other tokens:
+//
+//   error: unmatched angle brackets
+//    --> unmatched-langle.rs:2:10
+//     |
+//   2 |     foo::<Ty<<<i32>();
+//     |          ^^^ help: remove extra angle brackets
+//
+// This test makes sure that this is no longer happening.
+
+fn main() {
+    foo::<Ty<<<i32>();
+    //~^ ERROR: expected `::`, found `(`
+}
diff --git a/src/test/ui/parser/unmatched-langle-2.stderr b/src/test/ui/parser/unmatched-langle-2.stderr
new file mode 100644
index 00000000000..773bb33d8d3
--- /dev/null
+++ b/src/test/ui/parser/unmatched-langle-2.stderr
@@ -0,0 +1,8 @@
+error: expected `::`, found `(`
+  --> $DIR/unmatched-langle-2.rs:13:20
+   |
+LL |     foo::<Ty<<<i32>();
+   |                    ^ expected `::`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/prelude2021.rs b/src/test/ui/prelude2021.rs
new file mode 100644
index 00000000000..3a9fd693228
--- /dev/null
+++ b/src/test/ui/prelude2021.rs
@@ -0,0 +1,7 @@
+// check-pass
+// edition:2021
+// compile-flags: -Zunstable-options
+
+fn main() {
+    let _: u16 = 123i32.try_into().unwrap();
+}
diff --git a/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.rs b/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.rs
new file mode 100644
index 00000000000..d4067a33592
--- /dev/null
+++ b/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.rs
@@ -0,0 +1,37 @@
+// check-pass
+// aux-build:test-macros.rs
+
+#![feature(decl_macro)]
+#![feature(stmt_expr_attributes)]
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use]
+extern crate test_macros;
+
+macro mac {
+    (expr $expr:expr) => {
+        #[derive(Print)]
+        enum E {
+            V = { let _ = $expr; 0 },
+        }
+    },
+    (stmt $stmt:stmt) => {
+        #[derive(Print)]
+        enum E {
+            V = { let _ = { $stmt }; 0 },
+        }
+    },
+}
+
+const PATH: u8 = 2;
+
+fn main() {
+    mac!(expr #[allow(warnings)] 0);
+    mac!(stmt 0);
+    mac!(stmt {});
+    mac!(stmt PATH);
+    mac!(stmt 0 + 1);
+    mac!(stmt PATH + 1);
+}
diff --git a/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout b/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout
new file mode 100644
index 00000000000..e37a483cb87
--- /dev/null
+++ b/src/test/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout
@@ -0,0 +1,540 @@
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = #[allow(warnings)] 0 ; 0 }, }
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = #[allow(warnings)] #[allow(warnings)] 0 ; 0 }, }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "enum",
+        span: #4 bytes(299..303),
+    },
+    Ident {
+        ident: "E",
+        span: #4 bytes(304..305),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [
+            Ident {
+                ident: "V",
+                span: #4 bytes(320..321),
+            },
+            Punct {
+                ch: '=',
+                spacing: Alone,
+                span: #4 bytes(322..323),
+            },
+            Group {
+                delimiter: Brace,
+                stream: TokenStream [
+                    Ident {
+                        ident: "let",
+                        span: #4 bytes(326..329),
+                    },
+                    Ident {
+                        ident: "_",
+                        span: #4 bytes(330..331),
+                    },
+                    Punct {
+                        ch: '=',
+                        spacing: Alone,
+                        span: #4 bytes(332..333),
+                    },
+                    Group {
+                        delimiter: None,
+                        stream: TokenStream [
+                            Punct {
+                                ch: '#',
+                                spacing: Alone,
+                                span: #0 bytes(541..542),
+                            },
+                            Group {
+                                delimiter: Bracket,
+                                stream: TokenStream [
+                                    Ident {
+                                        ident: "allow",
+                                        span: #0 bytes(543..548),
+                                    },
+                                    Group {
+                                        delimiter: Parenthesis,
+                                        stream: TokenStream [
+                                            Ident {
+                                                ident: "warnings",
+                                                span: #0 bytes(549..557),
+                                            },
+                                        ],
+                                        span: #0 bytes(548..558),
+                                    },
+                                ],
+                                span: #0 bytes(542..559),
+                            },
+                            Punct {
+                                ch: '#',
+                                spacing: Alone,
+                                span: #0 bytes(541..542),
+                            },
+                            Group {
+                                delimiter: Bracket,
+                                stream: TokenStream [
+                                    Ident {
+                                        ident: "allow",
+                                        span: #0 bytes(543..548),
+                                    },
+                                    Group {
+                                        delimiter: Parenthesis,
+                                        stream: TokenStream [
+                                            Ident {
+                                                ident: "warnings",
+                                                span: #0 bytes(549..557),
+                                            },
+                                        ],
+                                        span: #0 bytes(548..558),
+                                    },
+                                ],
+                                span: #0 bytes(542..559),
+                            },
+                            Literal {
+                                kind: Integer,
+                                symbol: "0",
+                                suffix: None,
+                                span: #0 bytes(560..561),
+                            },
+                        ],
+                        span: #4 bytes(334..339),
+                    },
+                    Punct {
+                        ch: ';',
+                        spacing: Alone,
+                        span: #4 bytes(339..340),
+                    },
+                    Literal {
+                        kind: Integer,
+                        symbol: "0",
+                        suffix: None,
+                        span: #4 bytes(341..342),
+                    },
+                ],
+                span: #4 bytes(324..344),
+            },
+            Punct {
+                ch: ',',
+                spacing: Alone,
+                span: #4 bytes(344..345),
+            },
+        ],
+        span: #4 bytes(306..355),
+    },
+]
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0; } ; 0 }, }
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { 0 } ; 0 }, }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "enum",
+        span: #8 bytes(423..427),
+    },
+    Ident {
+        ident: "E",
+        span: #8 bytes(428..429),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [
+            Ident {
+                ident: "V",
+                span: #8 bytes(444..445),
+            },
+            Punct {
+                ch: '=',
+                spacing: Alone,
+                span: #8 bytes(446..447),
+            },
+            Group {
+                delimiter: Brace,
+                stream: TokenStream [
+                    Ident {
+                        ident: "let",
+                        span: #8 bytes(450..453),
+                    },
+                    Ident {
+                        ident: "_",
+                        span: #8 bytes(454..455),
+                    },
+                    Punct {
+                        ch: '=',
+                        spacing: Alone,
+                        span: #8 bytes(456..457),
+                    },
+                    Group {
+                        delimiter: Brace,
+                        stream: TokenStream [
+                            Group {
+                                delimiter: None,
+                                stream: TokenStream [
+                                    Literal {
+                                        kind: Integer,
+                                        symbol: "0",
+                                        suffix: None,
+                                        span: #0 bytes(578..579),
+                                    },
+                                ],
+                                span: #8 bytes(460..465),
+                            },
+                        ],
+                        span: #8 bytes(458..467),
+                    },
+                    Punct {
+                        ch: ';',
+                        spacing: Alone,
+                        span: #8 bytes(467..468),
+                    },
+                    Literal {
+                        kind: Integer,
+                        symbol: "0",
+                        suffix: None,
+                        span: #8 bytes(469..470),
+                    },
+                ],
+                span: #8 bytes(448..472),
+            },
+            Punct {
+                ch: ',',
+                spacing: Alone,
+                span: #8 bytes(472..473),
+            },
+        ],
+        span: #8 bytes(430..483),
+    },
+]
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { { } } ; 0 }, }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "enum",
+        span: #12 bytes(423..427),
+    },
+    Ident {
+        ident: "E",
+        span: #12 bytes(428..429),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [
+            Ident {
+                ident: "V",
+                span: #12 bytes(444..445),
+            },
+            Punct {
+                ch: '=',
+                spacing: Alone,
+                span: #12 bytes(446..447),
+            },
+            Group {
+                delimiter: Brace,
+                stream: TokenStream [
+                    Ident {
+                        ident: "let",
+                        span: #12 bytes(450..453),
+                    },
+                    Ident {
+                        ident: "_",
+                        span: #12 bytes(454..455),
+                    },
+                    Punct {
+                        ch: '=',
+                        spacing: Alone,
+                        span: #12 bytes(456..457),
+                    },
+                    Group {
+                        delimiter: Brace,
+                        stream: TokenStream [
+                            Group {
+                                delimiter: None,
+                                stream: TokenStream [
+                                    Group {
+                                        delimiter: Brace,
+                                        stream: TokenStream [],
+                                        span: #0 bytes(596..598),
+                                    },
+                                ],
+                                span: #12 bytes(460..465),
+                            },
+                        ],
+                        span: #12 bytes(458..467),
+                    },
+                    Punct {
+                        ch: ';',
+                        spacing: Alone,
+                        span: #12 bytes(467..468),
+                    },
+                    Literal {
+                        kind: Integer,
+                        symbol: "0",
+                        suffix: None,
+                        span: #12 bytes(469..470),
+                    },
+                ],
+                span: #12 bytes(448..472),
+            },
+            Punct {
+                ch: ',',
+                spacing: Alone,
+                span: #12 bytes(472..473),
+            },
+        ],
+        span: #12 bytes(430..483),
+    },
+]
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH; } ; 0 }, }
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { PATH } ; 0 }, }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "enum",
+        span: #16 bytes(423..427),
+    },
+    Ident {
+        ident: "E",
+        span: #16 bytes(428..429),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [
+            Ident {
+                ident: "V",
+                span: #16 bytes(444..445),
+            },
+            Punct {
+                ch: '=',
+                spacing: Alone,
+                span: #16 bytes(446..447),
+            },
+            Group {
+                delimiter: Brace,
+                stream: TokenStream [
+                    Ident {
+                        ident: "let",
+                        span: #16 bytes(450..453),
+                    },
+                    Ident {
+                        ident: "_",
+                        span: #16 bytes(454..455),
+                    },
+                    Punct {
+                        ch: '=',
+                        spacing: Alone,
+                        span: #16 bytes(456..457),
+                    },
+                    Group {
+                        delimiter: Brace,
+                        stream: TokenStream [
+                            Group {
+                                delimiter: None,
+                                stream: TokenStream [
+                                    Ident {
+                                        ident: "PATH",
+                                        span: #0 bytes(615..619),
+                                    },
+                                ],
+                                span: #16 bytes(460..465),
+                            },
+                        ],
+                        span: #16 bytes(458..467),
+                    },
+                    Punct {
+                        ch: ';',
+                        spacing: Alone,
+                        span: #16 bytes(467..468),
+                    },
+                    Literal {
+                        kind: Integer,
+                        symbol: "0",
+                        suffix: None,
+                        span: #16 bytes(469..470),
+                    },
+                ],
+                span: #16 bytes(448..472),
+            },
+            Punct {
+                ch: ',',
+                spacing: Alone,
+                span: #16 bytes(472..473),
+            },
+        ],
+        span: #16 bytes(430..483),
+    },
+]
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0 + 1; } ; 0 }, }
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { 0 + 1 } ; 0 }, }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "enum",
+        span: #20 bytes(423..427),
+    },
+    Ident {
+        ident: "E",
+        span: #20 bytes(428..429),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [
+            Ident {
+                ident: "V",
+                span: #20 bytes(444..445),
+            },
+            Punct {
+                ch: '=',
+                spacing: Alone,
+                span: #20 bytes(446..447),
+            },
+            Group {
+                delimiter: Brace,
+                stream: TokenStream [
+                    Ident {
+                        ident: "let",
+                        span: #20 bytes(450..453),
+                    },
+                    Ident {
+                        ident: "_",
+                        span: #20 bytes(454..455),
+                    },
+                    Punct {
+                        ch: '=',
+                        spacing: Alone,
+                        span: #20 bytes(456..457),
+                    },
+                    Group {
+                        delimiter: Brace,
+                        stream: TokenStream [
+                            Group {
+                                delimiter: None,
+                                stream: TokenStream [
+                                    Literal {
+                                        kind: Integer,
+                                        symbol: "0",
+                                        suffix: None,
+                                        span: #0 bytes(636..637),
+                                    },
+                                    Punct {
+                                        ch: '+',
+                                        spacing: Alone,
+                                        span: #0 bytes(638..639),
+                                    },
+                                    Literal {
+                                        kind: Integer,
+                                        symbol: "1",
+                                        suffix: None,
+                                        span: #0 bytes(640..641),
+                                    },
+                                ],
+                                span: #20 bytes(460..465),
+                            },
+                        ],
+                        span: #20 bytes(458..467),
+                    },
+                    Punct {
+                        ch: ';',
+                        spacing: Alone,
+                        span: #20 bytes(467..468),
+                    },
+                    Literal {
+                        kind: Integer,
+                        symbol: "0",
+                        suffix: None,
+                        span: #20 bytes(469..470),
+                    },
+                ],
+                span: #20 bytes(448..472),
+            },
+            Punct {
+                ch: ',',
+                spacing: Alone,
+                span: #20 bytes(472..473),
+            },
+        ],
+        span: #20 bytes(430..483),
+    },
+]
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH + 1; } ; 0 }, }
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { PATH + 1 } ; 0 }, }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+    Ident {
+        ident: "enum",
+        span: #24 bytes(423..427),
+    },
+    Ident {
+        ident: "E",
+        span: #24 bytes(428..429),
+    },
+    Group {
+        delimiter: Brace,
+        stream: TokenStream [
+            Ident {
+                ident: "V",
+                span: #24 bytes(444..445),
+            },
+            Punct {
+                ch: '=',
+                spacing: Alone,
+                span: #24 bytes(446..447),
+            },
+            Group {
+                delimiter: Brace,
+                stream: TokenStream [
+                    Ident {
+                        ident: "let",
+                        span: #24 bytes(450..453),
+                    },
+                    Ident {
+                        ident: "_",
+                        span: #24 bytes(454..455),
+                    },
+                    Punct {
+                        ch: '=',
+                        spacing: Alone,
+                        span: #24 bytes(456..457),
+                    },
+                    Group {
+                        delimiter: Brace,
+                        stream: TokenStream [
+                            Group {
+                                delimiter: None,
+                                stream: TokenStream [
+                                    Ident {
+                                        ident: "PATH",
+                                        span: #0 bytes(658..662),
+                                    },
+                                    Punct {
+                                        ch: '+',
+                                        spacing: Alone,
+                                        span: #0 bytes(663..664),
+                                    },
+                                    Literal {
+                                        kind: Integer,
+                                        symbol: "1",
+                                        suffix: None,
+                                        span: #0 bytes(665..666),
+                                    },
+                                ],
+                                span: #24 bytes(460..465),
+                            },
+                        ],
+                        span: #24 bytes(458..467),
+                    },
+                    Punct {
+                        ch: ';',
+                        spacing: Alone,
+                        span: #24 bytes(467..468),
+                    },
+                    Literal {
+                        kind: Integer,
+                        symbol: "0",
+                        suffix: None,
+                        span: #24 bytes(469..470),
+                    },
+                ],
+                span: #24 bytes(448..472),
+            },
+            Punct {
+                ch: ',',
+                spacing: Alone,
+                span: #24 bytes(472..473),
+            },
+        ],
+        span: #24 bytes(430..483),
+    },
+]
diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr
index 695f5506d5e..4ddea2c27b2 100644
--- a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr
+++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.nll.stderr
@@ -23,6 +23,9 @@ LL |     a(x, y);
    |     ^^^^^^^ argument requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable reference to &isize
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: higher-ranked subtype error
   --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:12
diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr
index a28f7aa3e08..a9cf128bb62 100644
--- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr
+++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.nll.stderr
@@ -23,6 +23,9 @@ LL |     a(x, y, z);
    |     ^^^^^^^^^^ argument requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable reference to &isize
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: higher-ranked subtype error
   --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:12
diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr b/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr
index 37f7fcf2e33..db86572f1cf 100644
--- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr
+++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.nll.stderr
@@ -23,6 +23,9 @@ LL |     a(x, y);
    |     ^^^^^^^ argument requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable reference to &isize
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: higher-ranked subtype error
   --> $DIR/regions-lifetime-bounds-on-fns.rs:20:12
diff --git a/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr b/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr
index f92923a1125..bf325d56013 100644
--- a/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr
+++ b/src/test/ui/regions/regions-trait-object-subtyping.nll.stderr
@@ -10,6 +10,9 @@ LL |     x
    |     ^ returning this value requires that `'a` must outlive `'b`
    |
    = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of a mutable reference to dyn Dummy
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: lifetime may not live long enough
   --> $DIR/regions-trait-object-subtyping.rs:22:5
@@ -23,6 +26,9 @@ LL |     x
    |     ^ returning this value requires that `'b` must outlive `'a`
    |
    = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of a mutable reference to dyn Dummy
+   = note: mutable references are invariant over their type parameter
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/reify-intrinsic.rs b/src/test/ui/reify-intrinsic.rs
index 05535b92cca..9eb2f724017 100644
--- a/src/test/ui/reify-intrinsic.rs
+++ b/src/test/ui/reify-intrinsic.rs
@@ -1,6 +1,6 @@
 // check-fail
 
-#![feature(intrinsics)]
+#![feature(core_intrinsics, intrinsics)]
 
 fn a() {
     let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute;
@@ -14,8 +14,8 @@ fn b() {
 
 fn c() {
     let _ = [
-        std::intrinsics::copy_nonoverlapping::<i32>,
-        std::intrinsics::copy::<i32>,
+        std::intrinsics::likely,
+        std::intrinsics::unlikely,
         //~^ ERROR cannot coerce
     ];
 }
diff --git a/src/test/ui/reify-intrinsic.stderr b/src/test/ui/reify-intrinsic.stderr
index 5d82fdbd311..69c11b5c56f 100644
--- a/src/test/ui/reify-intrinsic.stderr
+++ b/src/test/ui/reify-intrinsic.stderr
@@ -22,11 +22,11 @@ LL |     let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize)
 error[E0308]: cannot coerce intrinsics to function pointers
   --> $DIR/reify-intrinsic.rs:18:9
    |
-LL |         std::intrinsics::copy::<i32>,
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers
+LL |         std::intrinsics::unlikely,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers
    |
-   = note: expected type `unsafe extern "rust-intrinsic" fn(_, _, _) {copy_nonoverlapping::<i32>}`
-           found fn item `unsafe extern "rust-intrinsic" fn(_, _, _) {std::intrinsics::copy::<i32>}`
+   = note: expected type `extern "rust-intrinsic" fn(_) -> _ {likely}`
+           found fn item `extern "rust-intrinsic" fn(_) -> _ {unlikely}`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/rfc-2627-raw-dylib/raw-dylib-msvc-only.rs b/src/test/ui/rfc-2627-raw-dylib/raw-dylib-msvc-only.rs
new file mode 100644
index 00000000000..e9690f03f45
--- /dev/null
+++ b/src/test/ui/rfc-2627-raw-dylib/raw-dylib-msvc-only.rs
@@ -0,0 +1,8 @@
+// only-windows-gnu
+// check-pass
+// compile-flags: --crate-type lib
+#![feature(raw_dylib)]
+//~^ WARNING: the feature `raw_dylib` is incomplete
+#[link(name = "foo", kind = "raw-dylib")]
+//~^ WARNING: `#[link(...)]` with `kind = "raw-dylib"` not supported on windows-gnu
+extern "C" {}
diff --git a/src/test/ui/rfc-2627-raw-dylib/raw-dylib-msvc-only.stderr b/src/test/ui/rfc-2627-raw-dylib/raw-dylib-msvc-only.stderr
new file mode 100644
index 00000000000..6e24112b3c3
--- /dev/null
+++ b/src/test/ui/rfc-2627-raw-dylib/raw-dylib-msvc-only.stderr
@@ -0,0 +1,17 @@
+warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/raw-dylib-msvc-only.rs:4:12
+   |
+LL | #![feature(raw_dylib)]
+   |            ^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
+
+warning: `#[link(...)]` with `kind = "raw-dylib"` not supported on windows-gnu
+  --> $DIR/raw-dylib-msvc-only.rs:6:1
+   |
+LL | #[link(name = "foo", kind = "raw-dylib")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.rs b/src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.rs
new file mode 100644
index 00000000000..7a5d7ac2934
--- /dev/null
+++ b/src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.rs
@@ -0,0 +1,7 @@
+// ignore-windows
+// compile-flags: --crate-type lib
+#![feature(raw_dylib)]
+//~^ WARNING: the feature `raw_dylib` is incomplete
+#[link(name = "foo", kind = "raw-dylib")]
+//~^ ERROR: `#[link(...)]` with `kind = "raw-dylib"` only supported on Windows
+extern "C" {}
diff --git a/src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr b/src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr
new file mode 100644
index 00000000000..f3879b63f91
--- /dev/null
+++ b/src/test/ui/rfc-2627-raw-dylib/raw-dylib-windows-only.stderr
@@ -0,0 +1,17 @@
+warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/raw-dylib-windows-only.rs:3:12
+   |
+LL | #![feature(raw_dylib)]
+   |            ^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #58713 <https://github.com/rust-lang/rust/issues/58713> for more information
+
+error: `#[link(...)]` with `kind = "raw-dylib"` only supported on Windows
+  --> $DIR/raw-dylib-windows-only.rs:5:1
+   |
+LL | #[link(name = "foo", kind = "raw-dylib")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/src/test/ui/rustdoc/deny-invalid-doc-attrs.rs b/src/test/ui/rustdoc/deny-invalid-doc-attrs.rs
new file mode 100644
index 00000000000..02e9c67915f
--- /dev/null
+++ b/src/test/ui/rustdoc/deny-invalid-doc-attrs.rs
@@ -0,0 +1,7 @@
+#![deny(invalid_doc_attributes)]
+//~^ NOTE defined here
+#![doc(x)]
+//~^ ERROR unknown `doc` attribute `x`
+//~| WARNING will become a hard error
+//~| NOTE see issue #82730
+fn main() {}
diff --git a/src/test/ui/rustdoc/deny-invalid-doc-attrs.stderr b/src/test/ui/rustdoc/deny-invalid-doc-attrs.stderr
new file mode 100644
index 00000000000..a14ab8fe4bc
--- /dev/null
+++ b/src/test/ui/rustdoc/deny-invalid-doc-attrs.stderr
@@ -0,0 +1,16 @@
+error: unknown `doc` attribute `x`
+  --> $DIR/deny-invalid-doc-attrs.rs:3:8
+   |
+LL | #![doc(x)]
+   |        ^
+   |
+note: the lint level is defined here
+  --> $DIR/deny-invalid-doc-attrs.rs:1:9
+   |
+LL | #![deny(invalid_doc_attributes)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rustdoc/doc-inline-extern-crate.rs b/src/test/ui/rustdoc/doc-inline-extern-crate.rs
new file mode 100644
index 00000000000..0eb4c149060
--- /dev/null
+++ b/src/test/ui/rustdoc/doc-inline-extern-crate.rs
@@ -0,0 +1,9 @@
+#[doc(inline)]
+//~^ ERROR conflicting
+#[doc(no_inline)]
+pub extern crate core;
+
+// no warning
+pub extern crate alloc;
+
+fn main() {}
diff --git a/src/test/ui/rustdoc/doc-inline-extern-crate.stderr b/src/test/ui/rustdoc/doc-inline-extern-crate.stderr
new file mode 100644
index 00000000000..41518295b12
--- /dev/null
+++ b/src/test/ui/rustdoc/doc-inline-extern-crate.stderr
@@ -0,0 +1,13 @@
+error: conflicting doc inlining attributes
+  --> $DIR/doc-inline-extern-crate.rs:1:7
+   |
+LL | #[doc(inline)]
+   |       ^^^^^^ this attribute...
+LL |
+LL | #[doc(no_inline)]
+   |       ^^^^^^^^^ ...conflicts with this attribute
+   |
+   = help: remove one of the conflicting attributes
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/simd/issue-85915-simd-ptrs.rs b/src/test/ui/simd/issue-85915-simd-ptrs.rs
new file mode 100644
index 00000000000..6fe415545f8
--- /dev/null
+++ b/src/test/ui/simd/issue-85915-simd-ptrs.rs
@@ -0,0 +1,67 @@
+// run-pass
+// ignore-emscripten
+
+// Short form of the generic gather/scatter tests,
+// verifying simd([*const T; N]) and simd([*mut T; N]) pass typeck and work.
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct cptrx4<T>([*const T; 4]);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct mptrx4<T>([*mut T; 4]);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct f32x4([f32; 4]);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+struct i32x4([i32; 4]);
+
+extern "platform-intrinsic" {
+    fn simd_gather<T, U, V>(x: T, y: U, z: V) -> T;
+    fn simd_scatter<T, U, V>(x: T, y: U, z: V) -> ();
+}
+
+fn main() {
+    let mut x = [0_f32, 1., 2., 3., 4., 5., 6., 7.];
+
+    let default = f32x4([-3_f32, -3., -3., -3.]);
+    let s_strided = f32x4([0_f32, 2., -3., 6.]);
+    let mask = i32x4([-1_i32, -1, 0, -1]);
+
+    // reading from *const
+    unsafe {
+        let pointer = &x as *const f32;
+        let pointers =  cptrx4([
+            pointer.offset(0) as *const f32,
+            pointer.offset(2),
+            pointer.offset(4),
+            pointer.offset(6)
+        ]);
+
+        let r_strided = simd_gather(default, pointers, mask);
+
+        assert_eq!(r_strided, s_strided);
+    }
+
+    // writing to *mut
+    unsafe {
+        let pointer = &mut x as *mut f32;
+        let pointers = mptrx4([
+            pointer.offset(0) as *mut f32,
+            pointer.offset(2),
+            pointer.offset(4),
+            pointer.offset(6)
+        ]);
+
+        let values = f32x4([42_f32, 43_f32, 44_f32, 45_f32]);
+        simd_scatter(values, pointers, mask);
+
+        assert_eq!(x, [42., 1., 43., 3., 4., 5., 45., 7.]);
+    }
+}
diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation-extern-nonnull-ptr.rs b/src/test/ui/simd/simd-type-generic-monomorphisation-extern-nonnull-ptr.rs
new file mode 100644
index 00000000000..ae321c974b9
--- /dev/null
+++ b/src/test/ui/simd/simd-type-generic-monomorphisation-extern-nonnull-ptr.rs
@@ -0,0 +1,23 @@
+// run-pass
+// ignore-emscripten
+
+#![feature(extern_types)]
+#![feature(repr_simd)]
+
+use std::ptr::NonNull;
+
+extern {
+    type Extern;
+}
+
+#[repr(simd)]
+struct S<T>(T);
+
+#[inline(never)]
+fn identity<T>(v: T) -> T {
+    v
+}
+
+fn main() {
+    let _v: S<[Option<NonNull<Extern>>; 4]> = identity(S([None; 4]));
+}
diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation-wide-ptr.rs b/src/test/ui/simd/simd-type-generic-monomorphisation-wide-ptr.rs
new file mode 100644
index 00000000000..3e02b08ce5d
--- /dev/null
+++ b/src/test/ui/simd/simd-type-generic-monomorphisation-wide-ptr.rs
@@ -0,0 +1,12 @@
+// build-fail
+
+#![feature(repr_simd)]
+
+// error-pattern:monomorphising SIMD type `S<[*mut [u8]; 4]>` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]`
+
+#[repr(simd)]
+struct S<T>(T);
+
+fn main() {
+    let _v: Option<S<[*mut [u8]; 4]>> = None;
+}
diff --git a/src/test/ui/simd/simd-type-generic-monomorphisation-wide-ptr.stderr b/src/test/ui/simd/simd-type-generic-monomorphisation-wide-ptr.stderr
new file mode 100644
index 00000000000..3888e7a0f38
--- /dev/null
+++ b/src/test/ui/simd/simd-type-generic-monomorphisation-wide-ptr.stderr
@@ -0,0 +1,4 @@
+error: monomorphising SIMD type `S<[*mut [u8]; 4]>` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/simd/simd-type-wide-ptr.rs b/src/test/ui/simd/simd-type-wide-ptr.rs
new file mode 100644
index 00000000000..88f62a07ea0
--- /dev/null
+++ b/src/test/ui/simd/simd-type-wide-ptr.rs
@@ -0,0 +1,12 @@
+// build-fail
+
+#![feature(repr_simd)]
+
+// error-pattern:monomorphising SIMD type `S` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]`
+
+#[repr(simd)]
+struct S([*mut [u8]; 4]);
+
+fn main() {
+    let _v: Option<S> = None;
+}
diff --git a/src/test/ui/simd/simd-type-wide-ptr.stderr b/src/test/ui/simd/simd-type-wide-ptr.stderr
new file mode 100644
index 00000000000..51d3c005072
--- /dev/null
+++ b/src/test/ui/simd/simd-type-wide-ptr.stderr
@@ -0,0 +1,4 @@
+error: monomorphising SIMD type `S` with a non-primitive-scalar (integer/float/pointer) element type `*mut [u8]`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/simd/wasm-simd-indirect.rs b/src/test/ui/simd/wasm-simd-indirect.rs
new file mode 100644
index 00000000000..deac593df43
--- /dev/null
+++ b/src/test/ui/simd/wasm-simd-indirect.rs
@@ -0,0 +1,33 @@
+// build-pass
+
+#![cfg_attr(target_arch = "wasm32", feature(wasm_simd, wasm_target_feature))]
+
+#[cfg(target_arch = "wasm32")]
+fn main() {
+    unsafe {
+        a::api_with_simd_feature();
+    }
+}
+
+#[cfg(target_arch = "wasm32")]
+mod a {
+    use std::arch::wasm32::*;
+
+    #[target_feature(enable = "simd128")]
+    pub unsafe fn api_with_simd_feature() {
+        crate::b::api_takes_v128(u64x2(0, 1));
+    }
+}
+
+#[cfg(target_arch = "wasm32")]
+mod b {
+    use std::arch::wasm32::*;
+
+    #[inline(never)]
+    pub fn api_takes_v128(a: v128) -> v128 {
+        a
+    }
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+fn main() {}
diff --git a/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr b/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr
index b251e8a438a..723c4a7a1fb 100644
--- a/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr
+++ b/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr
@@ -1,11 +1,11 @@
-error: lifetime parameter `'a` only used once
-  --> $DIR/one-use-in-fn-argument-in-band.rs:11:10
+error: lifetime parameter `'b` only used once
+  --> $DIR/one-use-in-fn-argument-in-band.rs:11:22
    |
 LL | fn a(x: &'a u32, y: &'b u32) {
-   |          ^^-
-   |          |
-   |          this lifetime is only used here
-   |          help: elide the single-use lifetime
+   |                      ^^-
+   |                      |
+   |                      this lifetime is only used here
+   |                      help: elide the single-use lifetime
    |
 note: the lint level is defined here
   --> $DIR/one-use-in-fn-argument-in-band.rs:4:9
@@ -13,14 +13,14 @@ note: the lint level is defined here
 LL | #![deny(single_use_lifetimes)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: lifetime parameter `'b` only used once
-  --> $DIR/one-use-in-fn-argument-in-band.rs:11:22
+error: lifetime parameter `'a` only used once
+  --> $DIR/one-use-in-fn-argument-in-band.rs:11:10
    |
 LL | fn a(x: &'a u32, y: &'b u32) {
-   |                      ^^-
-   |                      |
-   |                      this lifetime is only used here
-   |                      help: elide the single-use lifetime
+   |          ^^-
+   |          |
+   |          this lifetime is only used here
+   |          help: elide the single-use lifetime
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
index d2eea15f398..fa59d7a0313 100644
--- a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
+++ b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr
@@ -1,4 +1,4 @@
-error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[b09c]::Id::This) }, (I,)), [])`
+error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id::This) }, (I,)), [])`
   --> $DIR/repeated_projection_type.rs:19:1
    |
 LL | / impl<I, V: Id<This = (I,)>> X for V {
diff --git a/src/test/ui/suggestions/auxiliary/proc-macro-type-error.rs b/src/test/ui/suggestions/auxiliary/proc-macro-type-error.rs
new file mode 100644
index 00000000000..d71747f9687
--- /dev/null
+++ b/src/test/ui/suggestions/auxiliary/proc-macro-type-error.rs
@@ -0,0 +1,18 @@
+// force-host
+// no-prefer-dynamic
+#![crate_type = "proc-macro"]
+#![feature(proc_macro_quote)]
+
+extern crate proc_macro;
+
+use proc_macro::{quote, TokenStream};
+
+#[proc_macro_attribute]
+pub fn hello(_: TokenStream, _: TokenStream) -> TokenStream {
+    quote!(
+        fn f(_: &mut i32) {}
+        fn g() {
+            f(123);
+        }
+    )
+}
diff --git a/src/test/ui/suggestions/format-borrow.rs b/src/test/ui/suggestions/format-borrow.rs
index 63930e7f787..599a79fc08a 100644
--- a/src/test/ui/suggestions/format-borrow.rs
+++ b/src/test/ui/suggestions/format-borrow.rs
@@ -3,4 +3,8 @@ fn main() {
     //~^ ERROR mismatched types
     let b: String = &format!("b");
     //~^ ERROR mismatched types
+    let c: String = &mut format!("c");
+    //~^ ERROR mismatched types
+    let d: String = &mut (format!("d"));
+    //~^ ERROR mismatched types
 }
diff --git a/src/test/ui/suggestions/format-borrow.stderr b/src/test/ui/suggestions/format-borrow.stderr
index 05d8fcd3ed6..0881b024712 100644
--- a/src/test/ui/suggestions/format-borrow.stderr
+++ b/src/test/ui/suggestions/format-borrow.stderr
@@ -18,6 +18,26 @@ LL |     let b: String = &format!("b");
    |            |        help: consider removing the borrow: `format!("b")`
    |            expected due to this
 
-error: aborting due to 2 previous errors
+error[E0308]: mismatched types
+  --> $DIR/format-borrow.rs:6:21
+   |
+LL |     let c: String = &mut format!("c");
+   |            ------   ^^^^^^^^^^^^^^^^^
+   |            |        |
+   |            |        expected struct `String`, found `&mut String`
+   |            |        help: consider removing the borrow: `format!("c")`
+   |            expected due to this
+
+error[E0308]: mismatched types
+  --> $DIR/format-borrow.rs:8:21
+   |
+LL |     let d: String = &mut (format!("d"));
+   |            ------   ^^^^^^^^^^^^^^^^^^^
+   |            |        |
+   |            |        expected struct `String`, found `&mut String`
+   |            |        help: consider removing the borrow: `format!("d")`
+   |            expected due to this
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs b/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs
new file mode 100644
index 00000000000..390d8bbdd53
--- /dev/null
+++ b/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs
@@ -0,0 +1,9 @@
+// Regression test for #85943: should not emit suggestions for adding
+// indirection to type parameters in where-clauses when suggesting
+// adding `?Sized`.
+struct A<T>(T) where T: Send;
+struct B(A<[u8]>);
+//~^ ERROR the size for values of type
+
+pub fn main() {
+}
diff --git a/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr b/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr
new file mode 100644
index 00000000000..735aeb0e0e7
--- /dev/null
+++ b/src/test/ui/suggestions/issue-85943-no-suggest-unsized-indirection-in-where-clause.stderr
@@ -0,0 +1,20 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:5:10
+   |
+LL | struct A<T>(T) where T: Send;
+   |          - required by this bound in `A`
+LL | struct B(A<[u8]>);
+   |          ^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+help: you could relax the implicit `Sized` bound on `T` if it were used through indirection like `&T` or `Box<T>`
+  --> $DIR/issue-85943-no-suggest-unsized-indirection-in-where-clause.rs:4:10
+   |
+LL | struct A<T>(T) where T: Send;
+   |          ^  - ...if indirection were used here: `Box<T>`
+   |          |
+   |          this could be changed to `T: ?Sized`...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/suggest-ref-macro.rs b/src/test/ui/suggestions/suggest-ref-macro.rs
new file mode 100644
index 00000000000..6f780f32a14
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-ref-macro.rs
@@ -0,0 +1,29 @@
+// run-check
+// aux-build:proc-macro-type-error.rs
+
+extern crate proc_macro_type_error;
+
+use proc_macro_type_error::hello;
+
+#[hello] //~ERROR mismatched types
+fn abc() {}
+
+fn x(_: &mut i32) {}
+
+macro_rules! bla {
+    () => {
+        x(123);
+        //~^ ERROR mismatched types
+        //~| SUGGESTION &mut 123
+    };
+    ($v:expr) => {
+        x($v)
+    }
+}
+
+fn main() {
+    bla!();
+    bla!(456);
+    //~^ ERROR mismatched types
+    //~| SUGGESTION &mut 456
+}
diff --git a/src/test/ui/suggestions/suggest-ref-macro.stderr b/src/test/ui/suggestions/suggest-ref-macro.stderr
new file mode 100644
index 00000000000..147001f0c94
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-ref-macro.stderr
@@ -0,0 +1,34 @@
+error[E0308]: mismatched types
+  --> $DIR/suggest-ref-macro.rs:8:1
+   |
+LL | #[hello]
+   | ^^^^^^^^ expected `&mut i32`, found integer
+   |
+   = note: this error originates in the attribute macro `hello` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/suggest-ref-macro.rs:15:11
+   |
+LL |         x(123);
+   |           ^^^
+   |           |
+   |           expected `&mut i32`, found integer
+   |           help: consider mutably borrowing here: `&mut 123`
+...
+LL |     bla!();
+   |     ------- in this macro invocation
+   |
+   = note: this error originates in the macro `bla` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/suggest-ref-macro.rs:26:10
+   |
+LL |     bla!(456);
+   |          ^^^
+   |          |
+   |          expected `&mut i32`, found integer
+   |          help: consider mutably borrowing here: `&mut 456`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/symbol-names/basic.legacy.stderr b/src/test/ui/symbol-names/basic.legacy.stderr
index de4d35e261c..3dd2b19fbf9 100644
--- a/src/test/ui/symbol-names/basic.legacy.stderr
+++ b/src/test/ui/symbol-names/basic.legacy.stderr
@@ -1,10 +1,10 @@
-error: symbol-name(_ZN5basic4main17hd75b915511563828E)
+error: symbol-name(_ZN5basic4main17h6c535bbea2051f85E)
   --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(basic::main::hd75b915511563828)
+error: demangling(basic::main::h6c535bbea2051f85)
   --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
diff --git a/src/test/ui/symbol-names/basic.rs b/src/test/ui/symbol-names/basic.rs
index d871a4ee829..bd107c10207 100644
--- a/src/test/ui/symbol-names/basic.rs
+++ b/src/test/ui/symbol-names/basic.rs
@@ -9,8 +9,8 @@
 //[legacy]~^ ERROR symbol-name(_ZN5basic4main
 //[legacy]~| ERROR demangling(basic::main
 //[legacy]~| ERROR demangling-alt(basic::main)
- //[v0]~^^^^ ERROR symbol-name(_RNvCsj6j3mjPNGKx_5basic4main)
-    //[v0]~| ERROR demangling(basic[de7d5b6b69c71f37]::main)
+ //[v0]~^^^^ ERROR symbol-name(_RNvCs21hi0yVfW1J_5basic4main)
+    //[v0]~| ERROR demangling(basic[17891616a171812d]::main)
     //[v0]~| ERROR demangling-alt(basic::main)
 #[rustc_def_path]
 //[legacy]~^ ERROR def-path(main)
diff --git a/src/test/ui/symbol-names/basic.v0.stderr b/src/test/ui/symbol-names/basic.v0.stderr
index e30fa6f66d5..519efc9d7b4 100644
--- a/src/test/ui/symbol-names/basic.v0.stderr
+++ b/src/test/ui/symbol-names/basic.v0.stderr
@@ -1,10 +1,10 @@
-error: symbol-name(_RNvCsj6j3mjPNGKx_5basic4main)
+error: symbol-name(_RNvCs21hi0yVfW1J_5basic4main)
   --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(basic[de7d5b6b69c71f37]::main)
+error: demangling(basic[17891616a171812d]::main)
   --> $DIR/basic.rs:8:1
    |
 LL | #[rustc_symbol_name]
diff --git a/src/test/ui/symbol-names/const-generics-demangling.rs b/src/test/ui/symbol-names/const-generics-demangling.rs
index 05c6b8352de..bd7e1c0f336 100644
--- a/src/test/ui/symbol-names/const-generics-demangling.rs
+++ b/src/test/ui/symbol-names/const-generics-demangling.rs
@@ -5,32 +5,32 @@
 pub struct Unsigned<const F: u8>;
 
 #[rustc_symbol_name]
-//~^ ERROR symbol-name(_RMCsaP8qXevlYG3_25const_generics_demanglingINtB0_8UnsignedKhb_E)
-//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Unsigned<11: u8>>)
+//~^ ERROR symbol-name(_RMCs21hi0yVfW1J_25const_generics_demanglingINtB0_8UnsignedKhb_E)
+//~| ERROR demangling(<const_generics_demangling[17891616a171812d]::Unsigned<11: u8>>)
 //~| ERROR demangling-alt(<const_generics_demangling::Unsigned<11>>)
 impl Unsigned<11> {}
 
 pub struct Signed<const F: i16>;
 
 #[rustc_symbol_name]
-//~^ ERROR symbol-name(_RMs_CsaP8qXevlYG3_25const_generics_demanglingINtB2_6SignedKsn98_E)
-//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Signed<-152: i16>>)
+//~^ ERROR symbol-name(_RMs_Cs21hi0yVfW1J_25const_generics_demanglingINtB2_6SignedKsn98_E)
+//~| ERROR demangling(<const_generics_demangling[17891616a171812d]::Signed<-152: i16>>)
 //~| ERROR demangling-alt(<const_generics_demangling::Signed<-152>>)
 impl Signed<-152> {}
 
 pub struct Bool<const F: bool>;
 
 #[rustc_symbol_name]
-//~^ ERROR symbol-name(_RMs0_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4BoolKb1_E)
-//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Bool<true: bool>>)
+//~^ ERROR symbol-name(_RMs0_Cs21hi0yVfW1J_25const_generics_demanglingINtB3_4BoolKb1_E)
+//~| ERROR demangling(<const_generics_demangling[17891616a171812d]::Bool<true: bool>>)
 //~| ERROR demangling-alt(<const_generics_demangling::Bool<true>>)
 impl Bool<true> {}
 
 pub struct Char<const F: char>;
 
 #[rustc_symbol_name]
-//~^ ERROR symbol-name(_RMs1_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4CharKc2202_E)
-//~| ERROR demangling(<const_generics_demangling[7e153590edc26969]::Char<'∂': char>>)
+//~^ ERROR symbol-name(_RMs1_Cs21hi0yVfW1J_25const_generics_demanglingINtB3_4CharKc2202_E)
+//~| ERROR demangling(<const_generics_demangling[17891616a171812d]::Char<'∂': char>>)
 //~| ERROR demangling-alt(<const_generics_demangling::Char<'∂'>>)
 impl Char<'∂'> {}
 
diff --git a/src/test/ui/symbol-names/const-generics-demangling.stderr b/src/test/ui/symbol-names/const-generics-demangling.stderr
index 05c485d001f..13995403f77 100644
--- a/src/test/ui/symbol-names/const-generics-demangling.stderr
+++ b/src/test/ui/symbol-names/const-generics-demangling.stderr
@@ -1,10 +1,10 @@
-error: symbol-name(_RMCsaP8qXevlYG3_25const_generics_demanglingINtB0_8UnsignedKhb_E)
+error: symbol-name(_RMCs21hi0yVfW1J_25const_generics_demanglingINtB0_8UnsignedKhb_E)
   --> $DIR/const-generics-demangling.rs:7:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<const_generics_demangling[7e153590edc26969]::Unsigned<11: u8>>)
+error: demangling(<const_generics_demangling[17891616a171812d]::Unsigned<11: u8>>)
   --> $DIR/const-generics-demangling.rs:7:1
    |
 LL | #[rustc_symbol_name]
@@ -16,13 +16,13 @@ error: demangling-alt(<const_generics_demangling::Unsigned<11>>)
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_RMs_CsaP8qXevlYG3_25const_generics_demanglingINtB2_6SignedKsn98_E)
+error: symbol-name(_RMs_Cs21hi0yVfW1J_25const_generics_demanglingINtB2_6SignedKsn98_E)
   --> $DIR/const-generics-demangling.rs:15:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<const_generics_demangling[7e153590edc26969]::Signed<-152: i16>>)
+error: demangling(<const_generics_demangling[17891616a171812d]::Signed<-152: i16>>)
   --> $DIR/const-generics-demangling.rs:15:1
    |
 LL | #[rustc_symbol_name]
@@ -34,13 +34,13 @@ error: demangling-alt(<const_generics_demangling::Signed<-152>>)
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_RMs0_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4BoolKb1_E)
+error: symbol-name(_RMs0_Cs21hi0yVfW1J_25const_generics_demanglingINtB3_4BoolKb1_E)
   --> $DIR/const-generics-demangling.rs:23:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<const_generics_demangling[7e153590edc26969]::Bool<true: bool>>)
+error: demangling(<const_generics_demangling[17891616a171812d]::Bool<true: bool>>)
   --> $DIR/const-generics-demangling.rs:23:1
    |
 LL | #[rustc_symbol_name]
@@ -52,13 +52,13 @@ error: demangling-alt(<const_generics_demangling::Bool<true>>)
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_RMs1_CsaP8qXevlYG3_25const_generics_demanglingINtB3_4CharKc2202_E)
+error: symbol-name(_RMs1_Cs21hi0yVfW1J_25const_generics_demanglingINtB3_4CharKc2202_E)
   --> $DIR/const-generics-demangling.rs:31:1
    |
 LL | #[rustc_symbol_name]
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<const_generics_demangling[7e153590edc26969]::Char<'∂': char>>)
+error: demangling(<const_generics_demangling[17891616a171812d]::Char<'∂': char>>)
   --> $DIR/const-generics-demangling.rs:31:1
    |
 LL | #[rustc_symbol_name]
diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs
index 960049be793..b0b31a57d06 100644
--- a/src/test/ui/symbol-names/impl1.rs
+++ b/src/test/ui/symbol-names/impl1.rs
@@ -15,8 +15,8 @@ mod foo {
         //[legacy]~^ ERROR symbol-name(_ZN5impl13foo3Foo3bar
         //[legacy]~| ERROR demangling(impl1::foo::Foo::bar
         //[legacy]~| ERROR demangling-alt(impl1::foo::Foo::bar)
-         //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs2qSCrjELJET_5impl13fooNtB2_3Foo3bar)
-            //[v0]~| ERROR demangling(<impl1[1c5860ab79c9e305]::foo::Foo>::bar)
+         //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13fooNtB2_3Foo3bar)
+            //[v0]~| ERROR demangling(<impl1[17891616a171812d]::foo::Foo>::bar)
             //[v0]~| ERROR demangling-alt(<impl1::foo::Foo>::bar)
         #[rustc_def_path]
         //[legacy]~^ ERROR def-path(foo::Foo::bar)
@@ -33,8 +33,8 @@ mod bar {
         //[legacy]~^ ERROR symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz
         //[legacy]~| ERROR demangling(impl1::bar::<impl impl1::foo::Foo>::baz
         //[legacy]~| ERROR demangling-alt(impl1::bar::<impl impl1::foo::Foo>::baz)
-         //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs2qSCrjELJET_5impl13barNtNtB4_3foo3Foo3baz)
-            //[v0]~| ERROR demangling(<impl1[1c5860ab79c9e305]::foo::Foo>::baz)
+         //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13barNtNtB4_3foo3Foo3baz)
+            //[v0]~| ERROR demangling(<impl1[17891616a171812d]::foo::Foo>::baz)
             //[v0]~| ERROR demangling-alt(<impl1::foo::Foo>::baz)
         #[rustc_def_path]
         //[legacy]~^ ERROR def-path(bar::<impl foo::Foo>::baz)
@@ -63,8 +63,8 @@ fn main() {
             //[legacy]~^ ERROR symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$3$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method
             //[legacy]~| ERROR demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method
             //[legacy]~| ERROR demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method)
-             //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs2qSCrjELJET_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
-                //[v0]~| ERROR demangling(<[&dyn impl1[1c5860ab79c9e305]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[1c5860ab79c9e305]::AutoTrait; 3: usize] as impl1[1c5860ab79c9e305]::main::{closure#1}::Bar>::method)
+             //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs21hi0yVfW1J_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
+                //[v0]~| ERROR demangling(<[&dyn impl1[17891616a171812d]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[17891616a171812d]::AutoTrait; 3: usize] as impl1[17891616a171812d]::main::{closure#1}::Bar>::method)
                 //[v0]~| ERROR demangling-alt(<[&dyn impl1::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method)
             #[rustc_def_path]
             //[legacy]~^ ERROR def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method)
diff --git a/src/test/ui/symbol-names/impl1.v0.stderr b/src/test/ui/symbol-names/impl1.v0.stderr
index a7c3a389909..e5b0deee36e 100644
--- a/src/test/ui/symbol-names/impl1.v0.stderr
+++ b/src/test/ui/symbol-names/impl1.v0.stderr
@@ -1,10 +1,10 @@
-error: symbol-name(_RNvMNtCs2qSCrjELJET_5impl13fooNtB2_3Foo3bar)
+error: symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13fooNtB2_3Foo3bar)
   --> $DIR/impl1.rs:14:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<impl1[1c5860ab79c9e305]::foo::Foo>::bar)
+error: demangling(<impl1[17891616a171812d]::foo::Foo>::bar)
   --> $DIR/impl1.rs:14:9
    |
 LL |         #[rustc_symbol_name]
@@ -22,13 +22,13 @@ error: def-path(foo::Foo::bar)
 LL |         #[rustc_def_path]
    |         ^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_RNvMNtCs2qSCrjELJET_5impl13barNtNtB4_3foo3Foo3baz)
+error: symbol-name(_RNvMNtCs21hi0yVfW1J_5impl13barNtNtB4_3foo3Foo3baz)
   --> $DIR/impl1.rs:32:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<impl1[1c5860ab79c9e305]::foo::Foo>::baz)
+error: demangling(<impl1[17891616a171812d]::foo::Foo>::baz)
   --> $DIR/impl1.rs:32:9
    |
 LL |         #[rustc_symbol_name]
@@ -46,13 +46,13 @@ error: def-path(bar::<impl foo::Foo>::baz)
 LL |         #[rustc_def_path]
    |         ^^^^^^^^^^^^^^^^^
 
-error: symbol-name(_RNvXNCNvCs2qSCrjELJET_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
+error: symbol-name(_RNvXNCNvCs21hi0yVfW1J_5impl14mains_0ARDNtB6_3Foop5AssocFG_KCRL0_hvEuNtB6_9AutoTraitEL_j3_NtB2_3Bar6method)
   --> $DIR/impl1.rs:62:13
    |
 LL |             #[rustc_symbol_name]
    |             ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<[&dyn impl1[1c5860ab79c9e305]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[1c5860ab79c9e305]::AutoTrait; 3: usize] as impl1[1c5860ab79c9e305]::main::{closure#1}::Bar>::method)
+error: demangling(<[&dyn impl1[17891616a171812d]::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1[17891616a171812d]::AutoTrait; 3: usize] as impl1[17891616a171812d]::main::{closure#1}::Bar>::method)
   --> $DIR/impl1.rs:62:13
    |
 LL |             #[rustc_symbol_name]
diff --git a/src/test/ui/symbol-names/issue-60925.legacy.stderr b/src/test/ui/symbol-names/issue-60925.legacy.stderr
index 52d0c666398..83576783992 100644
--- a/src/test/ui/symbol-names/issue-60925.legacy.stderr
+++ b/src/test/ui/symbol-names/issue-60925.legacy.stderr
@@ -1,10 +1,10 @@
-error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h18eaa05e22e59176E)
+error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h6244e5288326926aE)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h18eaa05e22e59176)
+error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h6244e5288326926a)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
diff --git a/src/test/ui/symbol-names/issue-60925.rs b/src/test/ui/symbol-names/issue-60925.rs
index a313c1ef383..3238eb1e579 100644
--- a/src/test/ui/symbol-names/issue-60925.rs
+++ b/src/test/ui/symbol-names/issue-60925.rs
@@ -22,8 +22,8 @@ mod foo {
         //[legacy]~^ ERROR symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo
         //[legacy]~| ERROR demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo
         //[legacy]~| ERROR demangling-alt(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo)
-         //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs8dUWfuENynB_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo)
-            //[v0]~| ERROR demangling(<issue_60925[5fcbb46c6fac4139]::foo::Foo<issue_60925[5fcbb46c6fac4139]::llvm::Foo>>::foo)
+         //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs21hi0yVfW1J_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo)
+            //[v0]~| ERROR demangling(<issue_60925[17891616a171812d]::foo::Foo<issue_60925[17891616a171812d]::llvm::Foo>>::foo)
             //[v0]~| ERROR demangling-alt(<issue_60925::foo::Foo<issue_60925::llvm::Foo>>::foo)
         pub(crate) fn foo() {
             for _ in 0..0 {
diff --git a/src/test/ui/symbol-names/issue-60925.v0.stderr b/src/test/ui/symbol-names/issue-60925.v0.stderr
index 5d99abff59a..6a5885e1ea3 100644
--- a/src/test/ui/symbol-names/issue-60925.v0.stderr
+++ b/src/test/ui/symbol-names/issue-60925.v0.stderr
@@ -1,10 +1,10 @@
-error: symbol-name(_RNvMNtCs8dUWfuENynB_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo)
+error: symbol-name(_RNvMNtCs21hi0yVfW1J_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<issue_60925[5fcbb46c6fac4139]::foo::Foo<issue_60925[5fcbb46c6fac4139]::llvm::Foo>>::foo)
+error: demangling(<issue_60925[17891616a171812d]::foo::Foo<issue_60925[17891616a171812d]::llvm::Foo>>::foo)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
diff --git a/src/test/ui/symbol-names/issue-75326.rs b/src/test/ui/symbol-names/issue-75326.rs
index 0f721fc1f89..4d061cafef3 100644
--- a/src/test/ui/symbol-names/issue-75326.rs
+++ b/src/test/ui/symbol-names/issue-75326.rs
@@ -42,8 +42,8 @@ where
     //[legacy]~^ ERROR symbol-name(_ZN72_$LT$issue_75326..Foo$LT$I$C$E$GT$$u20$as$u20$issue_75326..Iterator2$GT$4next
     //[legacy]~| ERROR demangling(<issue_75326::Foo<I,E> as issue_75326::Iterator2>::next
     //[legacy]~| ERROR demangling-alt(<issue_75326::Foo<I,E> as issue_75326::Iterator2>::next)
-    //[v0]~^^^^  ERROR symbol-name(_RNvXINICsiMBouZZ1iuD_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_)
-    //[v0]~|     ERROR demangling(<issue_75326[dac9b7624645f95d]::Foo<_, _> as issue_75326[dac9b7624645f95d]::Iterator2>::next)
+    //[v0]~^^^^  ERROR symbol-name(_RNvXINICs21hi0yVfW1J_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_)
+    //[v0]~|     ERROR demangling(<issue_75326[17891616a171812d]::Foo<_, _> as issue_75326[17891616a171812d]::Iterator2>::next)
     //[v0]~|     ERROR demangling-alt(<issue_75326::Foo<_, _> as issue_75326::Iterator2>::next)
     fn next(&mut self) -> Option<Self::Item> {
         self.find(|_| true)
diff --git a/src/test/ui/symbol-names/issue-75326.v0.stderr b/src/test/ui/symbol-names/issue-75326.v0.stderr
index 093ba8c8576..98844aafb65 100644
--- a/src/test/ui/symbol-names/issue-75326.v0.stderr
+++ b/src/test/ui/symbol-names/issue-75326.v0.stderr
@@ -1,10 +1,10 @@
-error: symbol-name(_RNvXINICsiMBouZZ1iuD_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_)
+error: symbol-name(_RNvXINICs21hi0yVfW1J_11issue_75326s_0pppEINtB5_3FooppENtB5_9Iterator24nextB5_)
   --> $DIR/issue-75326.rs:41:5
    |
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<issue_75326[dac9b7624645f95d]::Foo<_, _> as issue_75326[dac9b7624645f95d]::Iterator2>::next)
+error: demangling(<issue_75326[17891616a171812d]::Foo<_, _> as issue_75326[17891616a171812d]::Iterator2>::next)
   --> $DIR/issue-75326.rs:41:5
    |
 LL |     #[rustc_symbol_name]
diff --git a/src/test/ui/symbol-names/trait-objects.v0.stderr b/src/test/ui/symbol-names/trait-objects.v0.stderr
index 5ada82dfb2d..2b09318f06c 100644
--- a/src/test/ui/symbol-names/trait-objects.v0.stderr
+++ b/src/test/ui/symbol-names/trait-objects.v0.stderr
@@ -4,7 +4,7 @@ error: symbol-name(_RNvXCRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3ops8
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[3f8b57f879016e18]::Bar>::method)
+error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[17891616a171812d]::Bar>::method)
   --> $DIR/trait-objects.rs:16:5
    |
 LL |     #[rustc_symbol_name]
@@ -22,7 +22,7 @@ error: symbol-name(_RNvXs_CRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3op
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[3f8b57f879016e18]::Foo>::method)
+error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[17891616a171812d]::Foo>::method)
   --> $DIR/trait-objects.rs:28:5
    |
 LL |     #[rustc_symbol_name]
@@ -40,7 +40,7 @@ error: symbol-name(_RNvXs0_CRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3o
 LL |     #[rustc_symbol_name]
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[3f8b57f879016e18]::Baz>::method)
+error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[17891616a171812d]::Baz>::method)
   --> $DIR/trait-objects.rs:40:5
    |
 LL |     #[rustc_symbol_name]
diff --git a/src/test/ui/target-feature/gate.rs b/src/test/ui/target-feature/gate.rs
index 164830fecee..7cdf404242d 100644
--- a/src/test/ui/target-feature/gate.rs
+++ b/src/test/ui/target-feature/gate.rs
@@ -27,6 +27,7 @@
 // gate-test-f16c_target_feature
 // gate-test-riscv_target_feature
 // gate-test-ermsb_target_feature
+// gate-test-bpf_target_feature
 
 #[target_feature(enable = "avx512bw")]
 //~^ ERROR: currently unstable
diff --git a/src/test/ui/target-feature/gate.stderr b/src/test/ui/target-feature/gate.stderr
index 2d6abcc0a01..ee542b60a26 100644
--- a/src/test/ui/target-feature/gate.stderr
+++ b/src/test/ui/target-feature/gate.stderr
@@ -1,5 +1,5 @@
 error[E0658]: the target feature `avx512bw` is currently unstable
-  --> $DIR/gate.rs:31:18
+  --> $DIR/gate.rs:32:18
    |
 LL | #[target_feature(enable = "avx512bw")]
    |                  ^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/target-feature/wasm-safe.rs b/src/test/ui/target-feature/wasm-safe.rs
new file mode 100644
index 00000000000..4b868684a52
--- /dev/null
+++ b/src/test/ui/target-feature/wasm-safe.rs
@@ -0,0 +1,44 @@
+// only-wasm32
+// check-pass
+
+#![feature(wasm_target_feature)]
+#![allow(dead_code)]
+
+#[target_feature(enable = "nontrapping-fptoint")]
+fn foo() {}
+
+#[target_feature(enable = "nontrapping-fptoint")]
+extern "C" fn bar() {}
+
+trait A {
+    fn foo();
+    fn bar(&self);
+}
+
+struct B;
+
+impl B {
+    #[target_feature(enable = "nontrapping-fptoint")]
+    fn foo() {}
+    #[target_feature(enable = "nontrapping-fptoint")]
+    fn bar(&self) {}
+}
+
+impl A for B {
+    #[target_feature(enable = "nontrapping-fptoint")]
+    fn foo() {}
+    #[target_feature(enable = "nontrapping-fptoint")]
+    fn bar(&self) {}
+}
+
+fn no_features_enabled_on_this_function() {
+    bar();
+    foo();
+    B.bar();
+    B::foo();
+    <B as A>::foo();
+    <B as A>::bar(&B);
+}
+
+#[target_feature(enable = "nontrapping-fptoint")]
+fn main() {}
diff --git a/src/test/ui/test-attrs/test-type.rs b/src/test/ui/test-attrs/test-type.rs
new file mode 100644
index 00000000000..3f0fa81373f
--- /dev/null
+++ b/src/test/ui/test-attrs/test-type.rs
@@ -0,0 +1,28 @@
+// compile-flags: --test
+// run-flags: --test-threads=1
+// check-run-results
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+// ignore-emscripten no threads support
+// run-pass
+
+
+#[test]
+fn test_ok() {
+    let _a = true;
+}
+
+#[test]
+#[should_panic]
+fn test_panic() {
+    panic!();
+}
+
+#[test]
+#[ignore]
+fn test_no_run() {
+    loop{
+        println!("Hello, world");
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/test-attrs/test-type.run.stdout b/src/test/ui/test-attrs/test-type.run.stdout
new file mode 100644
index 00000000000..be2fd8ae68c
--- /dev/null
+++ b/src/test/ui/test-attrs/test-type.run.stdout
@@ -0,0 +1,8 @@
+
+running 3 tests
+test test_no_run ... ignored
+test test_ok ... ok
+test test_panic - should panic ... ok
+
+test result: ok. 2 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/ui/test-panic-abort-nocapture.run.stdout b/src/test/ui/test-panic-abort-nocapture.run.stdout
index 15b19676a7c..8a91732a754 100644
--- a/src/test/ui/test-panic-abort-nocapture.run.stdout
+++ b/src/test/ui/test-panic-abort-nocapture.run.stdout
@@ -2,7 +2,7 @@
 running 4 tests
 test it_fails ... about to fail
 FAILED
-test it_panics ... about to panic
+test it_panics - should panic ... about to panic
 ok
 test it_works ... about to succeed
 ok
diff --git a/src/test/ui/test-panic-abort.run.stdout b/src/test/ui/test-panic-abort.run.stdout
index 467f834afec..f608a8cdc55 100644
--- a/src/test/ui/test-panic-abort.run.stdout
+++ b/src/test/ui/test-panic-abort.run.stdout
@@ -2,7 +2,7 @@
 running 5 tests
 test it_exits ... FAILED
 test it_fails ... FAILED
-test it_panics ... ok
+test it_panics - should panic ... ok
 test it_works ... ok
 test no_residual_environment ... ok
 
diff --git a/src/test/ui/thread-local-static.rs b/src/test/ui/thread-local-static.rs
new file mode 100644
index 00000000000..dc542fe2db9
--- /dev/null
+++ b/src/test/ui/thread-local-static.rs
@@ -0,0 +1,17 @@
+// edition:2018
+
+#![feature(thread_local)]
+#![feature(const_swap)]
+#[thread_local]
+static mut STATIC_VAR_2: [u32; 8] = [4; 8];
+const fn g(x: &mut [u32; 8]) {
+    //~^ ERROR mutable references are not allowed
+    std::mem::swap(x, &mut STATIC_VAR_2)
+    //~^ ERROR thread-local statics cannot be accessed
+    //~| ERROR mutable references are not allowed
+    //~| ERROR use of mutable static is unsafe
+    //~| constant functions cannot refer to statics
+    //~| ERROR calls in constant functions are limited to constant functions
+}
+
+fn main() {}
diff --git a/src/test/ui/thread-local-static.stderr b/src/test/ui/thread-local-static.stderr
new file mode 100644
index 00000000000..a213282eb85
--- /dev/null
+++ b/src/test/ui/thread-local-static.stderr
@@ -0,0 +1,50 @@
+error[E0658]: mutable references are not allowed in constant functions
+  --> $DIR/thread-local-static.rs:7:12
+   |
+LL | const fn g(x: &mut [u32; 8]) {
+   |            ^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0625]: thread-local statics cannot be accessed at compile-time
+  --> $DIR/thread-local-static.rs:9:28
+   |
+LL |     std::mem::swap(x, &mut STATIC_VAR_2)
+   |                            ^^^^^^^^^^^^
+
+error[E0013]: constant functions cannot refer to statics
+  --> $DIR/thread-local-static.rs:9:28
+   |
+LL |     std::mem::swap(x, &mut STATIC_VAR_2)
+   |                            ^^^^^^^^^^^^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error[E0658]: mutable references are not allowed in constant functions
+  --> $DIR/thread-local-static.rs:9:23
+   |
+LL |     std::mem::swap(x, &mut STATIC_VAR_2)
+   |                       ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/thread-local-static.rs:9:5
+   |
+LL |     std::mem::swap(x, &mut STATIC_VAR_2)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0133]: use of mutable static is unsafe and requires unsafe function or block
+  --> $DIR/thread-local-static.rs:9:23
+   |
+LL |     std::mem::swap(x, &mut STATIC_VAR_2)
+   |                       ^^^^^^^^^^^^^^^^^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0013, E0015, E0133, E0658.
+For more information about an error, try `rustc --explain E0013`.
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs
new file mode 100644
index 00000000000..ecad910f7d5
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs
@@ -0,0 +1,12 @@
+// check-pass
+#![feature(min_type_alias_impl_trait)]
+
+type X<A: ToString + Clone, B: ToString + Clone> = impl ToString;
+
+fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
+    (a.clone(), a)
+}
+
+fn main() {
+    println!("{}", <X<_, _> as ToString>::to_string(&f(42_i32, String::new()).1));
+}
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs
new file mode 100644
index 00000000000..67351e20159
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs
@@ -0,0 +1,16 @@
+// https://github.com/rust-lang/rust/issues/73481
+// This test used to cause unsoundness, since one of the two possible
+// resolutions was chosen at random instead of erroring due to conflicts.
+
+#![feature(min_type_alias_impl_trait)]
+
+type X<A, B> = impl Into<&'static A>;
+//~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied
+
+fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
+    (a, a)
+}
+
+fn main() {
+    println!("{}", <X<_, _> as Into<&String>>::into(f(&[1isize, 2, 3], String::new()).1));
+}
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
new file mode 100644
index 00000000000..731c6e2788d
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `&'static B: From<&A>` is not satisfied
+  --> $DIR/multiple-def-uses-in-one-fn.rs:7:16
+   |
+LL | type X<A, B> = impl Into<&'static A>;
+   |                ^^^^^^^^^^^^^^^^^^^^^ the trait `From<&A>` is not implemented for `&'static B`
+   |
+   = note: required because of the requirements on the impl of `Into<&'static B>` for `&A`
+help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
+   |
+LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) where &'static B: From<&A> {
+   |                                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs
new file mode 100644
index 00000000000..38aa18fe40e
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs
@@ -0,0 +1,16 @@
+// https://github.com/rust-lang/rust/issues/73481
+// This test used to cause unsoundness, since one of the two possible
+// resolutions was chosen at random instead of erroring due to conflicts.
+
+#![feature(min_type_alias_impl_trait)]
+
+type X<A: ToString + Clone, B: ToString + Clone> = impl ToString;
+//~^ ERROR could not find defining uses
+
+fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
+    (a.clone(), a)
+}
+
+fn main() {
+    println!("{}", <X<_, _> as ToString>::to_string(&f(42_i32, String::new()).1));
+}
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr
new file mode 100644
index 00000000000..c00973c0761
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr
@@ -0,0 +1,8 @@
+error: could not find defining uses
+  --> $DIR/multiple-def-uses-in-one-fn2.rs:7:52
+   |
+LL | type X<A: ToString + Clone, B: ToString + Clone> = impl ToString;
+   |                                                    ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs
new file mode 100644
index 00000000000..17e90005811
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs
@@ -0,0 +1,18 @@
+// https://github.com/rust-lang/rust/issues/73481
+// This test used to cause unsoundness, since one of the two possible
+// resolutions was chosen at random instead of erroring due to conflicts.
+
+#![feature(min_type_alias_impl_trait)]
+
+type X<A: ToString + Clone, B: ToString + Clone> = impl ToString;
+
+fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
+    (a, b)
+}
+
+fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
+    (a, b)
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr
new file mode 100644
index 00000000000..bbe709dccab
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/multiple-def-uses-in-one-fn3.rs:14:9
+   |
+LL | fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
+   |      -                    - found type parameter
+   |      |
+   |      expected type parameter
+LL |     (a, b)
+   |         ^ expected type parameter `A`, found type parameter `B`
+   |
+   = note: expected type parameter `A`
+              found type parameter `B`
+   = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
+   = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.full_tait.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.full_tait.stderr
index 75e4cb3e2d8..bd7cbd444d7 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_item.full_tait.stderr
+++ b/src/test/ui/typeck/typeck_type_placeholder_item.full_tait.stderr
@@ -79,7 +79,7 @@ LL | static TEST3: _ = "test";
    |               ^
    |               |
    |               not allowed in type signatures
-   |               help: replace `_` with the correct type: `&str`
+   |               help: replace with the correct type: `&str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:19:15
@@ -88,7 +88,7 @@ LL | static TEST4: _ = 145;
    |               ^
    |               |
    |               not allowed in type signatures
-   |               help: replace `_` with the correct type: `i32`
+   |               help: replace with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:22:15
@@ -210,7 +210,7 @@ LL |     static B: _ = 42;
    |               ^
    |               |
    |               not allowed in type signatures
-   |               help: replace `_` with the correct type: `i32`
+   |               help: replace with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:80:15
@@ -244,7 +244,7 @@ LL |     static FN_TEST3: _ = "test";
    |                      ^
    |                      |
    |                      not allowed in type signatures
-   |                      help: replace `_` with the correct type: `&str`
+   |                      help: replace with the correct type: `&str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:92:22
@@ -253,7 +253,7 @@ LL |     static FN_TEST4: _ = 145;
    |                      ^
    |                      |
    |                      not allowed in type signatures
-   |                      help: replace `_` with the correct type: `i32`
+   |                      help: replace with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:95:22
@@ -435,7 +435,7 @@ LL | const _: Option<_> = map(value);
    |          ^^^^^^^^^
    |          |
    |          not allowed in type signatures
-   |          help: replace `_` with the correct type: `Option<u8>`
+   |          help: replace with the correct type: `Option<u8>`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:144:31
@@ -526,7 +526,7 @@ LL |     const D: _ = 42;
    |              ^
    |              |
    |              not allowed in type signatures
-   |              help: replace `_` with the correct type: `i32`
+   |              help: replace with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:201:26
@@ -639,7 +639,7 @@ LL |     const D: _ = 42;
    |              ^
    |              |
    |              not allowed in type signatures
-   |              help: replace `_` with the correct type: `i32`
+   |              help: replace with the correct type: `i32`
 
 error: aborting due to 69 previous errors; 1 warning emitted
 
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.min_tait.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.min_tait.stderr
index c6758c52a91..afd6aaf4e55 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_item.min_tait.stderr
+++ b/src/test/ui/typeck/typeck_type_placeholder_item.min_tait.stderr
@@ -70,7 +70,7 @@ LL | static TEST3: _ = "test";
    |               ^
    |               |
    |               not allowed in type signatures
-   |               help: replace `_` with the correct type: `&str`
+   |               help: replace with the correct type: `&str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:19:15
@@ -79,7 +79,7 @@ LL | static TEST4: _ = 145;
    |               ^
    |               |
    |               not allowed in type signatures
-   |               help: replace `_` with the correct type: `i32`
+   |               help: replace with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:22:15
@@ -201,7 +201,7 @@ LL |     static B: _ = 42;
    |               ^
    |               |
    |               not allowed in type signatures
-   |               help: replace `_` with the correct type: `i32`
+   |               help: replace with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:80:15
@@ -235,7 +235,7 @@ LL |     static FN_TEST3: _ = "test";
    |                      ^
    |                      |
    |                      not allowed in type signatures
-   |                      help: replace `_` with the correct type: `&str`
+   |                      help: replace with the correct type: `&str`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:92:22
@@ -244,7 +244,7 @@ LL |     static FN_TEST4: _ = 145;
    |                      ^
    |                      |
    |                      not allowed in type signatures
-   |                      help: replace `_` with the correct type: `i32`
+   |                      help: replace with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:95:22
@@ -426,7 +426,7 @@ LL | const _: Option<_> = map(value);
    |          ^^^^^^^^^
    |          |
    |          not allowed in type signatures
-   |          help: replace `_` with the correct type: `Option<u8>`
+   |          help: replace with the correct type: `Option<u8>`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:144:31
@@ -517,7 +517,7 @@ LL |     const D: _ = 42;
    |              ^
    |              |
    |              not allowed in type signatures
-   |              help: replace `_` with the correct type: `i32`
+   |              help: replace with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item.rs:201:26
@@ -630,7 +630,7 @@ LL |     const D: _ = 42;
    |              ^
    |              |
    |              not allowed in type signatures
-   |              help: replace `_` with the correct type: `i32`
+   |              help: replace with the correct type: `i32`
 
 error: aborting due to 69 previous errors
 
diff --git a/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr b/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr
index f868c8d4834..2b64df774b0 100644
--- a/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr
+++ b/src/test/ui/typeck/typeck_type_placeholder_item_help.stderr
@@ -14,7 +14,7 @@ LL | const TEST2: _ = 42u32;
    |              ^
    |              |
    |              not allowed in type signatures
-   |              help: replace `_` with the correct type: `u32`
+   |              help: replace with the correct type: `u32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item_help.rs:10:14
@@ -23,7 +23,7 @@ LL | const TEST3: _ = Some(42);
    |              ^
    |              |
    |              not allowed in type signatures
-   |              help: replace `_` with the correct type: `Option<i32>`
+   |              help: replace with the correct type: `Option<i32>`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item_help.rs:13:22
@@ -38,7 +38,7 @@ LL |     const TEST5: _ = 42;
    |                  ^
    |                  |
    |                  not allowed in type signatures
-   |                  help: replace `_` with the correct type: `i32`
+   |                  help: replace with the correct type: `i32`
 
 error[E0121]: the type placeholder `_` is not allowed within types on item signatures
   --> $DIR/typeck_type_placeholder_item_help.rs:24:18
@@ -47,7 +47,7 @@ LL |     const TEST6: _ = 13;
    |                  ^
    |                  |
    |                  not allowed in type signatures
-   |                  help: replace `_` with the correct type: `i32`
+   |                  help: replace with the correct type: `i32`
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/where-clauses/where-for-self.stderr b/src/test/ui/where-clauses/where-for-self.stderr
index 84430ffcf88..d06afc1e423 100644
--- a/src/test/ui/where-clauses/where-for-self.stderr
+++ b/src/test/ui/where-clauses/where-for-self.stderr
@@ -6,3 +6,4 @@ LL |     where for<'a> &'a T: for<'b> Bar<'b>
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0316`.
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 4e605caafe2..1e19b7b21d8 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -85,6 +85,8 @@ static TARGETS: &[&str] = &[
     "armv7r-none-eabihf",
     "armv7s-apple-ios",
     "asmjs-unknown-emscripten",
+    "bpfeb-unknown-none",
+    "bpfel-unknown-none",
     "i386-apple-ios",
     "i586-pc-windows-msvc",
     "i586-unknown-linux-gnu",
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject e931e4796b61de593aa1097649445e535c9c7ee
+Subproject aa8b09297bb3156b849e73db48af4cd050492fe
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index da5a0712c95..41af8e190dd 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -2493,6 +2493,7 @@ Released 2018-09-13
 [`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or
 [`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains
 [`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic
+[`manual_str_repeat`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat
 [`manual_strip`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_strip
 [`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap
 [`manual_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or
@@ -2622,6 +2623,7 @@ Released 2018-09-13
 [`redundant_pub_crate`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pub_crate
 [`redundant_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_slicing
 [`redundant_static_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_static_lifetimes
+[`ref_binding_to_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_binding_to_reference
 [`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref
 [`ref_option_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_option_ref
 [`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro
@@ -2670,6 +2672,7 @@ Released 2018-09-13
 [`suspicious_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_map
 [`suspicious_op_assign_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_op_assign_impl
 [`suspicious_operation_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_operation_groupings
+[`suspicious_splitn`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_splitn
 [`suspicious_unary_op_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_unary_op_formatting
 [`tabs_in_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#tabs_in_doc_comments
 [`temporary_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_assignment
diff --git a/src/tools/clippy/COPYRIGHT b/src/tools/clippy/COPYRIGHT
index 80d64472c70..238c919b69d 100644
--- a/src/tools/clippy/COPYRIGHT
+++ b/src/tools/clippy/COPYRIGHT
@@ -1,4 +1,4 @@
-Copyright 2014-2020 The Rust Project Developers
+Copyright 2014-2021 The Rust Project Developers
 
 Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index 848476a9d05..b003b15a11d 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -33,12 +33,13 @@ tempfile = { version = "3.1.0", optional = true }
 cargo_metadata = "0.12"
 compiletest_rs = { version = "0.6.0", features = ["tmp"] }
 tester = "0.9"
-clippy-mini-macro-test = { version = "0.2", path = "mini-macro" }
 serde = { version = "1.0", features = ["derive"] }
 derive-new = "0.5"
 regex = "1.4"
 quote = "1"
 syn = { version = "1", features = ["full"] }
+# This is used by the `collect-metadata` alias.
+filetime = "0.2"
 
 # A noop dependency that changes in the Rust repository, it's a bit of a hack.
 # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust`
diff --git a/src/tools/clippy/LICENSE-APACHE b/src/tools/clippy/LICENSE-APACHE
index d821a4de2be..04169a42b8b 100644
--- a/src/tools/clippy/LICENSE-APACHE
+++ b/src/tools/clippy/LICENSE-APACHE
@@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work.
    same "printed page" as the copyright notice for easier
    identification within third-party archives.
 
-Copyright 2014-2020 The Rust Project Developers
+Copyright 2014-2021 The Rust Project Developers
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
diff --git a/src/tools/clippy/LICENSE-MIT b/src/tools/clippy/LICENSE-MIT
index b7c70dd4026..90a2d3950d1 100644
--- a/src/tools/clippy/LICENSE-MIT
+++ b/src/tools/clippy/LICENSE-MIT
@@ -1,6 +1,6 @@
 MIT License
 
-Copyright (c) 2014-2020 The Rust Project Developers
+Copyright (c) 2014-2021 The Rust Project Developers
 
 Permission is hereby granted, free of charge, to any
 person obtaining a copy of this software and associated
diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md
index 8c0c16c443d..6c556f579ca 100644
--- a/src/tools/clippy/README.md
+++ b/src/tools/clippy/README.md
@@ -147,6 +147,7 @@ Some lints can be configured in a TOML file named `clippy.toml` or `.clippy.toml
 value` mapping eg.
 
 ```toml
+avoid-breaking-exported-api = false
 blacklisted-names = ["toto", "tata", "titi"]
 cognitive-complexity-threshold = 30
 ```
@@ -236,7 +237,7 @@ If you want to contribute to Clippy, you can find more information in [CONTRIBUT
 
 ## License
 
-Copyright 2014-2020 The Rust Project Developers
+Copyright 2014-2021 The Rust Project Developers
 
 Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)> or the MIT license
diff --git a/src/tools/clippy/build.rs b/src/tools/clippy/build.rs
index 018375dbada..b5484bec3c8 100644
--- a/src/tools/clippy/build.rs
+++ b/src/tools/clippy/build.rs
@@ -14,6 +14,6 @@ fn main() {
     );
     println!(
         "cargo:rustc-env=RUSTC_RELEASE_CHANNEL={}",
-        rustc_tools_util::get_channel().unwrap_or_default()
+        rustc_tools_util::get_channel()
     );
 }
diff --git a/src/tools/clippy/clippy.toml b/src/tools/clippy/clippy.toml
new file mode 100644
index 00000000000..cda8d17eed4
--- /dev/null
+++ b/src/tools/clippy/clippy.toml
@@ -0,0 +1 @@
+avoid-breaking-exported-api = false
diff --git a/src/tools/clippy/clippy_lints/src/absurd_extreme_comparisons.rs b/src/tools/clippy/clippy_lints/src/absurd_extreme_comparisons.rs
index 5fbf4bdbd18..49d4350123f 100644
--- a/src/tools/clippy/clippy_lints/src/absurd_extreme_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/absurd_extreme_comparisons.rs
@@ -3,9 +3,8 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
-use crate::consts::{constant, Constant};
-
 use clippy_utils::comparisons::{normalize_comparison, Rel};
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_isize_or_usize;
diff --git a/src/tools/clippy/clippy_lints/src/arithmetic.rs b/src/tools/clippy/clippy_lints/src/arithmetic.rs
index c560f545d6a..24c2a972811 100644
--- a/src/tools/clippy/clippy_lints/src/arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/arithmetic.rs
@@ -1,4 +1,4 @@
-use crate::consts::constant_simple;
+use clippy_utils::consts::constant_simple;
 use clippy_utils::diagnostics::span_lint;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
index c565e29d078..5235b2642d1 100644
--- a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
+++ b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
@@ -1,4 +1,4 @@
-use crate::consts::{constant, Constant};
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::{is_direct_expn_of, is_expn_of, match_panic_call};
@@ -63,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants {
                 &format!("`assert!(false, {})` should probably be replaced", panic_message),
                 None,
                 &format!("use `panic!({})` or `unreachable!({})`", panic_message, panic_message),
-            )
+            );
         };
 
         if let Some(debug_assert_span) = is_expn_of(e.span, "debug_assert") {
diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs
index c5b01461c1c..932cd58bf62 100644
--- a/src/tools/clippy/clippy_lints/src/attrs.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs.rs
@@ -273,7 +273,7 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
         let attrs = cx.tcx.hir().attrs(item.hir_id());
         if is_relevant_item(cx, item) {
-            check_attrs(cx, item.span, item.ident.name, attrs)
+            check_attrs(cx, item.span, item.ident.name, attrs);
         }
         match item.kind {
             ItemKind::ExternCrate(..) | ItemKind::Use(..) => {
@@ -343,13 +343,13 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
         if is_relevant_impl(cx, item) {
-            check_attrs(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()))
+            check_attrs(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()));
         }
     }
 
     fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
         if is_relevant_trait(cx, item) {
-            check_attrs(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()))
+            check_attrs(cx, item.span, item.ident.name, cx.tcx.hir().attrs(item.hir_id()));
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/bit_mask.rs b/src/tools/clippy/clippy_lints/src/bit_mask.rs
index f7daf3dab49..991ed94572c 100644
--- a/src/tools/clippy/clippy_lints/src/bit_mask.rs
+++ b/src/tools/clippy/clippy_lints/src/bit_mask.rs
@@ -1,4 +1,4 @@
-use crate::consts::{constant, Constant};
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use clippy_utils::sugg::Sugg;
 use if_chain::if_chain;
@@ -115,9 +115,9 @@ impl<'tcx> LateLintPass<'tcx> for BitMask {
         if let ExprKind::Binary(cmp, left, right) = &e.kind {
             if cmp.node.is_comparison() {
                 if let Some(cmp_opt) = fetch_int_literal(cx, right) {
-                    check_compare(cx, left, cmp.node, cmp_opt, e.span)
+                    check_compare(cx, left, cmp.node, cmp_opt, e.span);
                 } else if let Some(cmp_val) = fetch_int_literal(cx, left) {
-                    check_compare(cx, right, invert_cmp(cmp.node), cmp_val, e.span)
+                    check_compare(cx, right, invert_cmp(cmp.node), cmp_val, e.span);
                 }
             }
         }
@@ -171,7 +171,7 @@ fn check_compare(cx: &LateContext<'_>, bit_op: &Expr<'_>, cmp_op: BinOpKind, cmp
         }
         fetch_int_literal(cx, right)
             .or_else(|| fetch_int_literal(cx, left))
-            .map_or((), |mask| check_bit_mask(cx, op.node, cmp_op, mask, cmp_value, span))
+            .map_or((), |mask| check_bit_mask(cx, op.node, cmp_op, mask, cmp_value, span));
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs
index 67f0e0c7870..e72399af232 100644
--- a/src/tools/clippy/clippy_lints/src/booleans.rs
+++ b/src/tools/clippy/clippy_lints/src/booleans.rs
@@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for NonminimalBool {
         _: Span,
         _: HirId,
     ) {
-        NonminimalBoolVisitor { cx }.visit_body(body)
+        NonminimalBoolVisitor { cx }.visit_body(body);
     }
 }
 
@@ -184,7 +184,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> {
                 Term(n) => {
                     let terminal = self.terminals[n as usize];
                     if let Some(str) = simplify_not(self.cx, terminal) {
-                        self.output.push_str(&str)
+                        self.output.push_str(&str);
                     } else {
                         self.output.push('!');
                         let snip = snippet_opt(self.cx, terminal.span)?;
@@ -452,7 +452,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
         }
         match &e.kind {
             ExprKind::Binary(binop, _, _) if binop.node == BinOpKind::Or || binop.node == BinOpKind::And => {
-                self.bool_expr(e)
+                self.bool_expr(e);
             },
             ExprKind::Unary(UnOp::Not, inner) => {
                 if self.cx.typeck_results().node_types()[inner.hir_id].is_bool() {
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
index 040e0ca8864..c9c111a2847 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
@@ -1,4 +1,4 @@
-use crate::consts::{constant, Constant};
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::{method_chain_args, sext};
 use if_chain::if_chain;
diff --git a/src/tools/clippy/clippy_lints/src/collapsible_if.rs b/src/tools/clippy/clippy_lints/src/collapsible_if.rs
index dae5c86bd44..6e950738239 100644
--- a/src/tools/clippy/clippy_lints/src/collapsible_if.rs
+++ b/src/tools/clippy/clippy_lints/src/collapsible_if.rs
@@ -92,7 +92,7 @@ declare_lint_pass!(CollapsibleIf => [COLLAPSIBLE_IF, COLLAPSIBLE_ELSE_IF]);
 impl EarlyLintPass for CollapsibleIf {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
         if !expr.span.from_expansion() {
-            check_if(cx, expr)
+            check_if(cx, expr);
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/comparison_chain.rs b/src/tools/clippy/clippy_lints/src/comparison_chain.rs
index 2a61d58e653..b6999bef6e7 100644
--- a/src/tools/clippy/clippy_lints/src/comparison_chain.rs
+++ b/src/tools/clippy/clippy_lints/src/comparison_chain.rs
@@ -120,7 +120,7 @@ impl<'tcx> LateLintPass<'tcx> for ComparisonChain {
             "`if` chain can be rewritten with `match`",
             None,
             "consider rewriting the `if` chain to use `cmp` and `match`",
-        )
+        );
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/consts.rs b/src/tools/clippy/clippy_lints/src/consts.rs
deleted file mode 100644
index 7e87f53e3fb..00000000000
--- a/src/tools/clippy/clippy_lints/src/consts.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub use clippy_utils::consts::*;
diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs
index f956d171bfb..376a14b8181 100644
--- a/src/tools/clippy/clippy_lints/src/copies.rs
+++ b/src/tools/clippy/clippy_lints/src/copies.rs
@@ -476,7 +476,7 @@ fn emit_branches_sharing_code_lint(
         }
 
         suggestions.push(("end", span, suggestion.to_string()));
-        add_expr_note = !cx.typeck_results().expr_ty(if_expr).is_unit()
+        add_expr_note = !cx.typeck_results().expr_ty(if_expr).is_unit();
     }
 
     let add_optional_msgs = |diag: &mut DiagnosticBuilder<'_>| {
diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
index 6e883942680..759f7d4062d 100644
--- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
+++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
@@ -181,9 +181,9 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
         match stmt.kind {
             StmtKind::Local(local) => {
                 if local.ty.is_some() {
-                    self.ty_bounds.push(TyBound::Any)
+                    self.ty_bounds.push(TyBound::Any);
                 } else {
-                    self.ty_bounds.push(TyBound::Nothing)
+                    self.ty_bounds.push(TyBound::Nothing);
                 }
             },
 
diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
index 50ffc2e3f19..04f3d77464f 100644
--- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs
@@ -141,3 +141,22 @@ declare_deprecated_lint! {
     pub FILTER_MAP,
     "this lint has been replaced by `manual_filter_map`, a more specific lint"
 }
+
+declare_deprecated_lint! {
+    /// **What it does:** Nothing. This lint has been deprecated.
+    ///
+    /// **Deprecation reason:** The `avoid_breaking_exported_api` config option was added, which
+    /// enables the `enum_variant_names` lint for public items.
+    /// ```
+    pub PUB_ENUM_VARIANT_NAMES,
+    "set the `avoid_breaking_exported_api` config option to `false` to enable the `enum_variant_names` lint for public items"
+}
+
+declare_deprecated_lint! {
+    /// **What it does:** Nothing. This lint has been deprecated.
+    ///
+    /// **Deprecation reason:** The `avoid_breaking_exported_api` config option was added, which
+    /// enables the `wrong_self_conversion` lint for public items.
+    pub WRONG_PUB_SELF_CONVENTION,
+    "set the `avoid_breaking_exported_api` config option to `false` to enable the `wrong_self_convention` lint for public items"
+}
diff --git a/src/tools/clippy/clippy_lints/src/double_comparison.rs b/src/tools/clippy/clippy_lints/src/double_comparison.rs
index 58543ae6e4e..4966638cb1b 100644
--- a/src/tools/clippy/clippy_lints/src/double_comparison.rs
+++ b/src/tools/clippy/clippy_lints/src/double_comparison.rs
@@ -70,16 +70,16 @@ impl<'tcx> DoubleComparisons {
         #[rustfmt::skip]
         match (op, lkind, rkind) {
             (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Lt) | (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Eq) => {
-                lint_double_comparison!(<=)
+                lint_double_comparison!(<=);
             },
             (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Eq) => {
-                lint_double_comparison!(>=)
+                lint_double_comparison!(>=);
             },
             (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Gt) | (BinOpKind::Or, BinOpKind::Gt, BinOpKind::Lt) => {
-                lint_double_comparison!(!=)
+                lint_double_comparison!(!=);
             },
             (BinOpKind::And, BinOpKind::Le, BinOpKind::Ge) | (BinOpKind::And, BinOpKind::Ge, BinOpKind::Le) => {
-                lint_double_comparison!(==)
+                lint_double_comparison!(==);
             },
             _ => (),
         };
diff --git a/src/tools/clippy/clippy_lints/src/duration_subsec.rs b/src/tools/clippy/clippy_lints/src/duration_subsec.rs
index 529807770f3..94b09bf7173 100644
--- a/src/tools/clippy/clippy_lints/src/duration_subsec.rs
+++ b/src/tools/clippy/clippy_lints/src/duration_subsec.rs
@@ -7,7 +7,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Spanned;
 
-use crate::consts::{constant, Constant};
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::paths;
 
diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs
index 8db5050a5ac..2eb8b1422ed 100644
--- a/src/tools/clippy/clippy_lints/src/entry.rs
+++ b/src/tools/clippy/clippy_lints/src/entry.rs
@@ -469,7 +469,7 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
                     let mut is_map_used = self.is_map_used;
                     for arm in arms {
                         if let Some(Guard::If(guard) | Guard::IfLet(_, guard)) = arm.guard {
-                            self.visit_non_tail_expr(guard)
+                            self.visit_non_tail_expr(guard);
                         }
                         is_map_used |= self.visit_cond_arm(arm.body);
                     }
diff --git a/src/tools/clippy/clippy_lints/src/enum_clike.rs b/src/tools/clippy/clippy_lints/src/enum_clike.rs
index 7a98ae39d3a..021136ac5e0 100644
--- a/src/tools/clippy/clippy_lints/src/enum_clike.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_clike.rs
@@ -1,7 +1,7 @@
 //! lint on C-like enums that are `repr(isize/usize)` and have values that
 //! don't fit into an `i32`
 
-use crate::consts::{miri_to_const, Constant};
+use clippy_utils::consts::{miri_to_const, Constant};
 use clippy_utils::diagnostics::span_lint;
 use rustc_hir::{Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/enum_variants.rs b/src/tools/clippy/clippy_lints/src/enum_variants.rs
index 0ecc0bc3eb6..b1a105a51c1 100644
--- a/src/tools/clippy/clippy_lints/src/enum_variants.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_variants.rs
@@ -3,8 +3,8 @@
 use clippy_utils::camel_case;
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
 use clippy_utils::source::is_present_in_source;
-use rustc_ast::ast::{EnumDef, Item, ItemKind, VisibilityKind};
-use rustc_lint::{EarlyContext, EarlyLintPass, Lint};
+use rustc_hir::{EnumDef, Item, ItemKind};
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
 use rustc_span::symbol::Symbol;
@@ -40,36 +40,6 @@ declare_clippy_lint! {
 }
 
 declare_clippy_lint! {
-    /// **What it does:** Detects public enumeration variants that are
-    /// prefixed or suffixed by the same characters.
-    ///
-    /// **Why is this bad?** Public enumeration variant names should specify their variant,
-    /// not repeat the enumeration name.
-    ///
-    /// **Known problems:** None.
-    ///
-    /// **Example:**
-    /// ```rust
-    /// pub enum Cake {
-    ///     BlackForestCake,
-    ///     HummingbirdCake,
-    ///     BattenbergCake,
-    /// }
-    /// ```
-    /// Could be written as:
-    /// ```rust
-    /// pub enum Cake {
-    ///     BlackForest,
-    ///     Hummingbird,
-    ///     Battenberg,
-    /// }
-    /// ```
-    pub PUB_ENUM_VARIANT_NAMES,
-    pedantic,
-    "public enums where all variants share a prefix/postfix"
-}
-
-declare_clippy_lint! {
     /// **What it does:** Detects type names that are prefixed or suffixed by the
     /// containing module's name.
     ///
@@ -127,21 +97,22 @@ declare_clippy_lint! {
 pub struct EnumVariantNames {
     modules: Vec<(Symbol, String)>,
     threshold: u64,
+    avoid_breaking_exported_api: bool,
 }
 
 impl EnumVariantNames {
     #[must_use]
-    pub fn new(threshold: u64) -> Self {
+    pub fn new(threshold: u64, avoid_breaking_exported_api: bool) -> Self {
         Self {
             modules: Vec::new(),
             threshold,
+            avoid_breaking_exported_api,
         }
     }
 }
 
 impl_lint_pass!(EnumVariantNames => [
     ENUM_VARIANT_NAMES,
-    PUB_ENUM_VARIANT_NAMES,
     MODULE_NAME_REPETITIONS,
     MODULE_INCEPTION
 ]);
@@ -167,33 +138,42 @@ fn partial_rmatch(post: &str, name: &str) -> usize {
 }
 
 fn check_variant(
-    cx: &EarlyContext<'_>,
+    cx: &LateContext<'_>,
     threshold: u64,
-    def: &EnumDef,
+    def: &EnumDef<'_>,
     item_name: &str,
     item_name_chars: usize,
     span: Span,
-    lint: &'static Lint,
 ) {
     if (def.variants.len() as u64) < threshold {
         return;
     }
-    for var in &def.variants {
+    for var in def.variants {
         let name = var.ident.name.as_str();
         if partial_match(item_name, &name) == item_name_chars
             && name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase())
             && name.chars().nth(item_name_chars + 1).map_or(false, |c| !c.is_numeric())
         {
-            span_lint(cx, lint, var.span, "variant name starts with the enum's name");
+            span_lint(
+                cx,
+                ENUM_VARIANT_NAMES,
+                var.span,
+                "variant name starts with the enum's name",
+            );
         }
         if partial_rmatch(item_name, &name) == item_name_chars {
-            span_lint(cx, lint, var.span, "variant name ends with the enum's name");
+            span_lint(
+                cx,
+                ENUM_VARIANT_NAMES,
+                var.span,
+                "variant name ends with the enum's name",
+            );
         }
     }
     let first = &def.variants[0].ident.name.as_str();
     let mut pre = &first[..camel_case::until(&*first)];
     let mut post = &first[camel_case::from(&*first)..];
-    for var in &def.variants {
+    for var in def.variants {
         let name = var.ident.name.as_str();
 
         let pre_match = partial_match(pre, &name);
@@ -226,7 +206,7 @@ fn check_variant(
     };
     span_lint_and_help(
         cx,
-        lint,
+        ENUM_VARIANT_NAMES,
         span,
         &format!("all variants have the same {}fix: `{}`", what, value),
         None,
@@ -261,14 +241,14 @@ fn to_camel_case(item_name: &str) -> String {
     s
 }
 
-impl EarlyLintPass for EnumVariantNames {
-    fn check_item_post(&mut self, _cx: &EarlyContext<'_>, _item: &Item) {
+impl LateLintPass<'_> for EnumVariantNames {
+    fn check_item_post(&mut self, _cx: &LateContext<'_>, _item: &Item<'_>) {
         let last = self.modules.pop();
         assert!(last.is_some());
     }
 
     #[allow(clippy::similar_names)]
-    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
+    fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
         let item_name = item.ident.name.as_str();
         let item_name_chars = item_name.chars().count();
         let item_camel = to_camel_case(&item_name);
@@ -286,7 +266,7 @@ impl EarlyLintPass for EnumVariantNames {
                             );
                         }
                     }
-                    if item.vis.kind.is_pub() {
+                    if item.vis.node.is_pub() {
                         let matching = partial_match(mod_camel, &item_camel);
                         let rmatching = partial_rmatch(mod_camel, &item_camel);
                         let nchars = mod_camel.chars().count();
@@ -317,11 +297,9 @@ impl EarlyLintPass for EnumVariantNames {
             }
         }
         if let ItemKind::Enum(ref def, _) = item.kind {
-            let lint = match item.vis.kind {
-                VisibilityKind::Public => PUB_ENUM_VARIANT_NAMES,
-                _ => ENUM_VARIANT_NAMES,
-            };
-            check_variant(cx, self.threshold, def, &item_name, item_name_chars, item.span, lint);
+            if !(self.avoid_breaking_exported_api && cx.access_levels.is_exported(item.hir_id())) {
+                check_variant(cx, self.threshold, def, &item_name, item_name_chars, item.span);
+            }
         }
         self.modules.push((item.ident.name, item_camel));
     }
diff --git a/src/tools/clippy/clippy_lints/src/eq_op.rs b/src/tools/clippy/clippy_lints/src/eq_op.rs
index 90f391b5f5c..a3a8e748d99 100644
--- a/src/tools/clippy/clippy_lints/src/eq_op.rs
+++ b/src/tools/clippy/clippy_lints/src/eq_op.rs
@@ -156,7 +156,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp {
                                         vec![(left.span, lsnip), (right.span, rsnip)],
                                     );
                                 },
-                            )
+                            );
                         } else if lcpy
                             && !rcpy
                             && implements_trait(cx, lty, trait_id, &[cx.typeck_results().expr_ty(right).into()])
@@ -175,7 +175,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp {
                                         Applicability::MaybeIncorrect, // FIXME #2597
                                     );
                                 },
-                            )
+                            );
                         } else if !lcpy
                             && rcpy
                             && implements_trait(cx, cx.typeck_results().expr_ty(left), trait_id, &[rty.into()])
@@ -194,7 +194,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp {
                                         Applicability::MaybeIncorrect, // FIXME #2597
                                     );
                                 },
-                            )
+                            );
                         }
                     },
                     // &foo == bar
@@ -218,7 +218,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp {
                                         Applicability::MaybeIncorrect, // FIXME #2597
                                     );
                                 },
-                            )
+                            );
                         }
                     },
                     // foo == &bar
@@ -236,7 +236,7 @@ impl<'tcx> LateLintPass<'tcx> for EqOp {
                                     rsnip,
                                     Applicability::MaybeIncorrect, // FIXME #2597
                                 );
-                            })
+                            });
                         }
                     },
                     _ => {},
diff --git a/src/tools/clippy/clippy_lints/src/erasing_op.rs b/src/tools/clippy/clippy_lints/src/erasing_op.rs
index f95ca86a2d0..4aa9c25b1b0 100644
--- a/src/tools/clippy/clippy_lints/src/erasing_op.rs
+++ b/src/tools/clippy/clippy_lints/src/erasing_op.rs
@@ -1,11 +1,10 @@
+use clippy_utils::consts::{constant_simple, Constant};
 use clippy_utils::diagnostics::span_lint;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
 
-use crate::consts::{constant_simple, Constant};
-
 declare_clippy_lint! {
     /// **What it does:** Checks for erasing operations, e.g., `x * 0`.
     ///
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index 2f1aa53236d..8d066f305ee 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -77,7 +77,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
                 for arg in args {
                     // skip `foo(macro!())`
                     if arg.span.ctxt() == expr.span.ctxt() {
-                        check_closure(cx, arg)
+                        check_closure(cx, arg);
                     }
                 }
             },
@@ -92,17 +92,19 @@ fn check_closure(cx: &LateContext<'_>, expr: &Expr<'_>) {
         let ex = &body.value;
 
         if ex.span.ctxt() != expr.span.ctxt() {
-            if let Some(VecArgs::Vec(&[])) = higher::vec_macro(cx, ex) {
-                // replace `|| vec![]` with `Vec::new`
-                span_lint_and_sugg(
-                    cx,
-                    REDUNDANT_CLOSURE,
-                    expr.span,
-                    "redundant closure",
-                    "replace the closure with `Vec::new`",
-                    "std::vec::Vec::new".into(),
-                    Applicability::MachineApplicable,
-                );
+            if decl.inputs.is_empty() {
+                if let Some(VecArgs::Vec(&[])) = higher::vec_macro(cx, ex) {
+                    // replace `|| vec![]` with `Vec::new`
+                    span_lint_and_sugg(
+                        cx,
+                        REDUNDANT_CLOSURE,
+                        expr.span,
+                        "redundant closure",
+                        "replace the closure with `Vec::new`",
+                        "std::vec::Vec::new".into(),
+                        Applicability::MachineApplicable,
+                    );
+                }
             }
             // skip `foo(|| macro!())`
             return;
@@ -188,9 +190,10 @@ fn get_ufcs_type_name(cx: &LateContext<'_>, method_def_id: def_id::DefId, self_a
     cx.tcx.impl_of_method(method_def_id).and_then(|_| {
         //a type may implicitly implement other type's methods (e.g. Deref)
         if match_types(expected_type_of_self, actual_type_of_self) {
-            return Some(get_type_name(cx, actual_type_of_self));
+            Some(get_type_name(cx, actual_type_of_self))
+        } else {
+            None
         }
-        None
     })
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs b/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs
index 41acf55dd7d..5fdf5bc9e9d 100644
--- a/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs
+++ b/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs
@@ -110,7 +110,7 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
                 self.visit_expr(e);
                 for arm in arms {
                     if let Some(Guard::If(if_expr)) = arm.guard {
-                        self.visit_expr(if_expr)
+                        self.visit_expr(if_expr);
                     }
                     // make sure top level arm expressions aren't linted
                     self.maybe_walk_expr(&*arm.body);
diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
index 08f28cd54c5..e38384b01d4 100644
--- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
@@ -1,4 +1,4 @@
-use crate::consts::{
+use clippy_utils::consts::{
     constant, constant_simple, Constant,
     Constant::{Int, F32, F64},
 };
diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
index 20288427b4a..7f4fb68cf2f 100644
--- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
@@ -240,7 +240,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> {
                 }
             },
             Assign(target, ..) | AssignOp(_, target, _) | AddrOf(_, hir::Mutability::Mut, target) => {
-                self.mutates_static |= is_mutated_static(target)
+                self.mutates_static |= is_mutated_static(target);
             },
             _ => {},
         }
diff --git a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
index b8ea6990866..af759a48e10 100644
--- a/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs
@@ -116,7 +116,7 @@ impl<'a, 'tcx> DerefVisitor<'a, 'tcx> {
                     self.cx,
                     NOT_UNSAFE_PTR_ARG_DEREF,
                     ptr.span,
-                    "this public function dereferences a raw pointer but is not marked `unsafe`",
+                    "this public function might dereference a raw pointer but is not marked `unsafe`",
                 );
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs b/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs
index aa5494d5a7d..a666fee1a4a 100644
--- a/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs
@@ -4,7 +4,7 @@ use rustc_middle::lint::in_external_macro;
 use rustc_span::Span;
 
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::source::snippet;
+use clippy_utils::source::snippet_opt;
 
 use super::TOO_MANY_LINES;
 
@@ -13,15 +13,25 @@ pub(super) fn check_fn(cx: &LateContext<'_>, span: Span, body: &'tcx hir::Body<'
         return;
     }
 
-    let code_snippet = snippet(cx, body.value.span, "..");
+    let code_snippet = match snippet_opt(cx, body.value.span) {
+        Some(s) => s,
+        _ => return,
+    };
     let mut line_count: u64 = 0;
     let mut in_comment = false;
     let mut code_in_line;
 
-    // Skip the surrounding function decl.
-    let start_brace_idx = code_snippet.find('{').map_or(0, |i| i + 1);
-    let end_brace_idx = code_snippet.rfind('}').unwrap_or_else(|| code_snippet.len());
-    let function_lines = code_snippet[start_brace_idx..end_brace_idx].lines();
+    let function_lines = if matches!(body.value.kind, hir::ExprKind::Block(..))
+        && code_snippet.as_bytes().first().copied() == Some(b'{')
+        && code_snippet.as_bytes().last().copied() == Some(b'}')
+    {
+        // Removing the braces from the enclosing block
+        &code_snippet[1..code_snippet.len() - 1]
+    } else {
+        &code_snippet
+    }
+    .trim() // Remove leading and trailing blank lines
+    .lines();
 
     for mut line in function_lines {
         code_in_line = false;
@@ -63,6 +73,6 @@ pub(super) fn check_fn(cx: &LateContext<'_>, span: Span, body: &'tcx hir::Body<'
                 "this function has too many lines ({}/{})",
                 line_count, too_many_lines_threshold
             ),
-        )
+        );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs
index 04730ace887..515b8887453 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
                                         ));
                                     }
                                 }
-                            })
+                            });
                         },
                     );
                 }
diff --git a/src/tools/clippy/clippy_lints/src/identity_op.rs b/src/tools/clippy/clippy_lints/src/identity_op.rs
index 366b3b46a8a..99c461930e4 100644
--- a/src/tools/clippy/clippy_lints/src/identity_op.rs
+++ b/src/tools/clippy/clippy_lints/src/identity_op.rs
@@ -6,7 +6,7 @@ use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
 
-use crate::consts::{constant_simple, Constant};
+use clippy_utils::consts::{constant_simple, Constant};
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::{clip, unsext};
 
diff --git a/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs
index 260a8f50157..f2f830ca5c0 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_return.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_return.rs
@@ -67,7 +67,7 @@ fn lint_break(cx: &LateContext<'_>, break_span: Span, expr_span: Span) {
         "change `break` to `return` as shown",
         format!("return {}", snip),
         app,
-    )
+    );
 }
 
 #[derive(Clone, Copy, PartialEq, Eq)]
diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
index 1c54599abc4..bfa284f333a 100644
--- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
@@ -1,6 +1,6 @@
 //! lint on indexing and slicing operations
 
-use crate::consts::{constant, Constant};
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
 use clippy_utils::higher;
 use rustc_ast::ast::RangeLimits;
diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
index afee20ce43e..6b887da2630 100644
--- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
@@ -54,7 +54,7 @@ impl<'tcx> LateLintPass<'tcx> for InfiniteIter {
                 return;
             },
         };
-        span_lint(cx, lint, expr.span, msg)
+        span_lint(cx, lint, expr.span, msg);
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
index c67c02eefa5..37011f5578d 100644
--- a/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
@@ -7,9 +7,8 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::Span;
 use rustc_target::abi::LayoutOf;
 
-use crate::consts::{constant, Constant};
-
 use clippy_utils::comparisons::Rel;
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::source::snippet;
 use clippy_utils::{comparisons, sext};
@@ -177,7 +176,7 @@ fn upcast_comparison_bounds_err<'tcx>(
                 },
                 Rel::Eq | Rel::Ne => unreachable!(),
             } {
-                err_upcast_comparison(cx, span, lhs, true)
+                err_upcast_comparison(cx, span, lhs, true);
             } else if match rel {
                 Rel::Lt => {
                     if invert {
@@ -195,7 +194,7 @@ fn upcast_comparison_bounds_err<'tcx>(
                 },
                 Rel::Eq | Rel::Ne => unreachable!(),
             } {
-                err_upcast_comparison(cx, span, lhs, false)
+                err_upcast_comparison(cx, span, lhs, false);
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index bb57adff7be..583514b22f9 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -380,9 +380,9 @@ fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>
             }
         }
 
-        check_len(cx, span, method_path.ident.name, args, &lit.node, op, compare_to)
+        check_len(cx, span, method_path.ident.name, args, &lit.node, op, compare_to);
     } else {
-        check_empty_expr(cx, span, method, lit, op)
+        check_empty_expr(cx, span, method, lit, op);
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs
index 17e23781db7..e627b1385bc 100644
--- a/src/tools/clippy/clippy_lints/src/let_underscore.rs
+++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs
@@ -135,7 +135,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
                         None,
                         "consider using an underscore-prefixed named \
                             binding or dropping explicitly with `std::mem::drop`"
-                    )
+                    );
                 } else if init_ty.needs_drop(cx.tcx, cx.param_env) {
                     span_lint_and_help(
                         cx,
@@ -145,7 +145,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
                         None,
                         "consider using an underscore-prefixed named \
                             binding or dropping explicitly with `std::mem::drop`"
-                    )
+                    );
                 } else if is_must_use_ty(cx, cx.typeck_results().expr_ty(init)) {
                     span_lint_and_help(
                         cx,
@@ -154,7 +154,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
                         "non-binding let on an expression with `#[must_use]` type",
                         None,
                         "consider explicitly using expression value"
-                    )
+                    );
                 } else if is_must_use_func_call(cx, init) {
                     span_lint_and_help(
                         cx,
@@ -163,7 +163,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
                         "non-binding let on a result of a `#[must_use]` function",
                         None,
                         "consider explicitly using function result"
-                    )
+                    );
                 }
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 2c83409b402..e7dd3952b3a 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -41,6 +41,9 @@ extern crate rustc_target;
 extern crate rustc_trait_selection;
 extern crate rustc_typeck;
 
+#[macro_use]
+extern crate clippy_utils;
+
 use clippy_utils::parse_msrv;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_lint::LintId;
@@ -145,25 +148,9 @@ macro_rules! declare_clippy_lint {
     };
 }
 
-#[macro_export]
-macro_rules! sym {
-    ( $($x:tt)* ) => { clippy_utils::sym!($($x)*) }
-}
-
-#[macro_export]
-macro_rules! unwrap_cargo_metadata {
-    ( $($x:tt)* ) => { clippy_utils::unwrap_cargo_metadata!($($x)*) }
-}
-
-macro_rules! extract_msrv_attr {
-    ( $($x:tt)* ) => { clippy_utils::extract_msrv_attr!($($x)*); }
-}
-
-mod consts;
-#[macro_use]
-mod utils;
 #[cfg(feature = "metadata-collector-lint")]
 mod deprecated_lints;
+mod utils;
 
 // begin lints modules, do not remove this comment, it’s used in `update_lints`
 mod absurd_extreme_comparisons;
@@ -405,7 +392,6 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore) {
 
 #[doc(hidden)]
 pub fn read_conf(sess: &Session) -> Conf {
-    use std::path::Path;
     let file_name = match utils::conf::lookup_conf_file() {
         Ok(Some(path)) => path,
         Ok(None) => return Conf::default(),
@@ -416,16 +402,6 @@ pub fn read_conf(sess: &Session) -> Conf {
         },
     };
 
-    let file_name = if file_name.is_relative() {
-        sess.local_crate_source_file
-            .as_deref()
-            .and_then(Path::parent)
-            .unwrap_or_else(|| Path::new(""))
-            .join(file_name)
-    } else {
-        file_name
-    };
-
     let TryConf { conf, errors } = utils::conf::read(&file_name);
     // all conf errors are non-fatal, we just use the default conf in case of error
     for error in errors {
@@ -505,6 +481,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         "clippy::filter_map",
         "this lint has been replaced by `manual_filter_map`, a more specific lint",
     );
+    store.register_removed(
+        "clippy::pub_enum_variant_names",
+        "set the `avoid_breaking_exported_api` config option to `false` to enable the `enum_variant_names` lint for public items",
+    );
+    store.register_removed(
+        "clippy::wrong_pub_self_convention",
+        "set the `avoid_breaking_exported_api` config option to `false` to enable the `wrong_self_convention` lint for public items",
+    );
     // end deprecated lints, do not remove this comment, it’s used in `update_lints`
 
     // begin register lints, do not remove this comment, it’s used in `update_lints`
@@ -618,7 +602,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         enum_variants::ENUM_VARIANT_NAMES,
         enum_variants::MODULE_INCEPTION,
         enum_variants::MODULE_NAME_REPETITIONS,
-        enum_variants::PUB_ENUM_VARIANT_NAMES,
         eq_op::EQ_OP,
         eq_op::OP_REF,
         erasing_op::ERASING_OP,
@@ -779,6 +762,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         methods::MANUAL_FILTER_MAP,
         methods::MANUAL_FIND_MAP,
         methods::MANUAL_SATURATING_ARITHMETIC,
+        methods::MANUAL_STR_REPEAT,
         methods::MAP_COLLECT_RESULT_UNIT,
         methods::MAP_FLATTEN,
         methods::MAP_UNWRAP_OR,
@@ -796,13 +780,13 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         methods::SKIP_WHILE_NEXT,
         methods::STRING_EXTEND_CHARS,
         methods::SUSPICIOUS_MAP,
+        methods::SUSPICIOUS_SPLITN,
         methods::UNINIT_ASSUMED_INIT,
         methods::UNNECESSARY_FILTER_MAP,
         methods::UNNECESSARY_FOLD,
         methods::UNNECESSARY_LAZY_EVALUATIONS,
         methods::UNWRAP_USED,
         methods::USELESS_ASREF,
-        methods::WRONG_PUB_SELF_CONVENTION,
         methods::WRONG_SELF_CONVENTION,
         methods::ZST_OFFSET,
         minmax::MIN_MAX,
@@ -841,6 +825,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         needless_bool::BOOL_COMPARISON,
         needless_bool::NEEDLESS_BOOL,
         needless_borrow::NEEDLESS_BORROW,
+        needless_borrow::REF_BINDING_TO_REFERENCE,
         needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE,
         needless_continue::NEEDLESS_CONTINUE,
         needless_for_each::NEEDLESS_FOR_EACH,
@@ -995,291 +980,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     ]);
     // end register lints, do not remove this comment, it’s used in `update_lints`
 
-    // all the internal lints
-    #[cfg(feature = "internal-lints")]
-    {
-        store.register_early_pass(|| box utils::internal_lints::ClippyLintsInternal);
-        store.register_early_pass(|| box utils::internal_lints::ProduceIce);
-        store.register_late_pass(|| box utils::inspector::DeepCodeInspector);
-        store.register_late_pass(|| box utils::internal_lints::CollapsibleCalls);
-        store.register_late_pass(|| box utils::internal_lints::CompilerLintFunctions::new());
-        store.register_late_pass(|| box utils::internal_lints::IfChainStyle);
-        store.register_late_pass(|| box utils::internal_lints::InvalidPaths);
-        store.register_late_pass(|| box utils::internal_lints::InterningDefinedSymbol::default());
-        store.register_late_pass(|| box utils::internal_lints::LintWithoutLintPass::default());
-        store.register_late_pass(|| box utils::internal_lints::MatchTypeOnDiagItem);
-        store.register_late_pass(|| box utils::internal_lints::OuterExpnDataPass);
-    }
-    #[cfg(feature = "metadata-collector-lint")]
-    {
-        if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) {
-            store.register_late_pass(|| box utils::internal_lints::metadata_collector::MetadataCollector::new());
-        }
-    }
-
-    store.register_late_pass(|| box utils::author::Author);
-    store.register_late_pass(|| box await_holding_invalid::AwaitHolding);
-    store.register_late_pass(|| box serde_api::SerdeApi);
-    let vec_box_size_threshold = conf.vec_box_size_threshold;
-    let type_complexity_threshold = conf.type_complexity_threshold;
-    store.register_late_pass(move || box types::Types::new(vec_box_size_threshold, type_complexity_threshold));
-    store.register_late_pass(|| box booleans::NonminimalBool);
-    store.register_late_pass(|| box needless_bitwise_bool::NeedlessBitwiseBool);
-    store.register_late_pass(|| box eq_op::EqOp);
-    store.register_late_pass(|| box enum_clike::UnportableVariant);
-    store.register_late_pass(|| box float_literal::FloatLiteral);
-    let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold;
-    store.register_late_pass(move || box bit_mask::BitMask::new(verbose_bit_mask_threshold));
-    store.register_late_pass(|| box ptr::Ptr);
-    store.register_late_pass(|| box ptr_eq::PtrEq);
-    store.register_late_pass(|| box needless_bool::NeedlessBool);
-    store.register_late_pass(|| box needless_bool::BoolComparison);
-    store.register_late_pass(|| box needless_for_each::NeedlessForEach);
-    store.register_late_pass(|| box approx_const::ApproxConstant);
-    store.register_late_pass(|| box misc::MiscLints);
-    store.register_late_pass(|| box eta_reduction::EtaReduction);
-    store.register_late_pass(|| box identity_op::IdentityOp);
-    store.register_late_pass(|| box erasing_op::ErasingOp);
-    store.register_late_pass(|| box mut_mut::MutMut);
-    store.register_late_pass(|| box mut_reference::UnnecessaryMutPassed);
-    store.register_late_pass(|| box len_zero::LenZero);
-    store.register_late_pass(|| box attrs::Attributes);
-    store.register_late_pass(|| box blocks_in_if_conditions::BlocksInIfConditions);
-    store.register_late_pass(|| box collapsible_match::CollapsibleMatch);
-    store.register_late_pass(|| box unicode::Unicode);
-    store.register_late_pass(|| box unit_return_expecting_ord::UnitReturnExpectingOrd);
-    store.register_late_pass(|| box strings::StringAdd);
-    store.register_late_pass(|| box implicit_return::ImplicitReturn);
-    store.register_late_pass(|| box implicit_saturating_sub::ImplicitSaturatingSub);
-    store.register_late_pass(|| box default_numeric_fallback::DefaultNumericFallback);
-    store.register_late_pass(|| box inconsistent_struct_constructor::InconsistentStructConstructor);
-    store.register_late_pass(|| box non_octal_unix_permissions::NonOctalUnixPermissions);
-    store.register_early_pass(|| box unnecessary_self_imports::UnnecessarySelfImports);
-
-    let msrv = conf.msrv.as_ref().and_then(|s| {
-        parse_msrv(s, None, None).or_else(|| {
-            sess.err(&format!("error reading Clippy's configuration file. `{}` is not a valid Rust version", s));
-            None
-        })
-    });
-
-    store.register_late_pass(move || box methods::Methods::new(msrv));
-    store.register_late_pass(move || box matches::Matches::new(msrv));
-    store.register_early_pass(move || box manual_non_exhaustive::ManualNonExhaustive::new(msrv));
-    store.register_late_pass(move || box manual_strip::ManualStrip::new(msrv));
-    store.register_early_pass(move || box redundant_static_lifetimes::RedundantStaticLifetimes::new(msrv));
-    store.register_early_pass(move || box redundant_field_names::RedundantFieldNames::new(msrv));
-    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));
-    store.register_late_pass(move || box needless_question_mark::NeedlessQuestionMark);
-    store.register_late_pass(move || box casts::Casts::new(msrv));
-    store.register_early_pass(move || box unnested_or_patterns::UnnestedOrPatterns::new(msrv));
-
-    store.register_late_pass(|| box size_of_in_element_count::SizeOfInElementCount);
-    store.register_late_pass(|| box map_clone::MapClone);
-    store.register_late_pass(|| box map_err_ignore::MapErrIgnore);
-    store.register_late_pass(|| box shadow::Shadow);
-    store.register_late_pass(|| box unit_types::UnitTypes);
-    store.register_late_pass(|| box loops::Loops);
-    store.register_late_pass(|| box main_recursion::MainRecursion::default());
-    store.register_late_pass(|| box lifetimes::Lifetimes);
-    store.register_late_pass(|| box entry::HashMapPass);
-    store.register_late_pass(|| box minmax::MinMaxPass);
-    store.register_late_pass(|| box open_options::OpenOptions);
-    store.register_late_pass(|| box zero_div_zero::ZeroDiv);
-    store.register_late_pass(|| box mutex_atomic::Mutex);
-    store.register_late_pass(|| box needless_update::NeedlessUpdate);
-    store.register_late_pass(|| box needless_borrow::NeedlessBorrow::default());
-    store.register_late_pass(|| box needless_borrowed_ref::NeedlessBorrowedRef);
-    store.register_late_pass(|| box no_effect::NoEffect);
-    store.register_late_pass(|| box temporary_assignment::TemporaryAssignment);
-    store.register_late_pass(|| box transmute::Transmute);
-    let cognitive_complexity_threshold = conf.cognitive_complexity_threshold;
-    store.register_late_pass(move || box cognitive_complexity::CognitiveComplexity::new(cognitive_complexity_threshold));
-    let too_large_for_stack = conf.too_large_for_stack;
-    store.register_late_pass(move || box escape::BoxedLocal{too_large_for_stack});
-    store.register_late_pass(move || box vec::UselessVec{too_large_for_stack});
-    store.register_late_pass(|| box panic_unimplemented::PanicUnimplemented);
-    store.register_late_pass(|| box strings::StringLitAsBytes);
-    store.register_late_pass(|| box derive::Derive);
-    store.register_late_pass(|| box get_last_with_len::GetLastWithLen);
-    store.register_late_pass(|| box drop_forget_ref::DropForgetRef);
-    store.register_late_pass(|| box empty_enum::EmptyEnum);
-    store.register_late_pass(|| box absurd_extreme_comparisons::AbsurdExtremeComparisons);
-    store.register_late_pass(|| box invalid_upcast_comparisons::InvalidUpcastComparisons);
-    store.register_late_pass(|| box regex::Regex::default());
-    store.register_late_pass(|| box copies::CopyAndPaste);
-    store.register_late_pass(|| box copy_iterator::CopyIterator);
-    store.register_late_pass(|| box format::UselessFormat);
-    store.register_late_pass(|| box swap::Swap);
-    store.register_late_pass(|| box overflow_check_conditional::OverflowCheckConditional);
-    store.register_late_pass(|| box new_without_default::NewWithoutDefault::default());
-    let blacklisted_names = conf.blacklisted_names.iter().cloned().collect::<FxHashSet<_>>();
-    store.register_late_pass(move || box blacklisted_name::BlacklistedName::new(blacklisted_names.clone()));
-    let too_many_arguments_threshold = conf.too_many_arguments_threshold;
-    let too_many_lines_threshold = conf.too_many_lines_threshold;
-    store.register_late_pass(move || box functions::Functions::new(too_many_arguments_threshold, too_many_lines_threshold));
-    let doc_valid_idents = conf.doc_valid_idents.iter().cloned().collect::<FxHashSet<_>>();
-    store.register_late_pass(move || box doc::DocMarkdown::new(doc_valid_idents.clone()));
-    store.register_late_pass(|| box neg_multiply::NegMultiply);
-    store.register_late_pass(|| box mem_discriminant::MemDiscriminant);
-    store.register_late_pass(|| box mem_forget::MemForget);
-    store.register_late_pass(|| box arithmetic::Arithmetic::default());
-    store.register_late_pass(|| box assign_ops::AssignOps);
-    store.register_late_pass(|| box let_if_seq::LetIfSeq);
-    store.register_late_pass(|| box eval_order_dependence::EvalOrderDependence);
-    store.register_late_pass(|| box missing_doc::MissingDoc::new());
-    store.register_late_pass(|| box missing_inline::MissingInline);
-    store.register_late_pass(move || box exhaustive_items::ExhaustiveItems);
-    store.register_late_pass(|| box if_let_some_result::OkIfLet);
-    store.register_late_pass(|| box partialeq_ne_impl::PartialEqNeImpl);
-    store.register_late_pass(|| box unused_io_amount::UnusedIoAmount);
-    let enum_variant_size_threshold = conf.enum_variant_size_threshold;
-    store.register_late_pass(move || box large_enum_variant::LargeEnumVariant::new(enum_variant_size_threshold));
-    store.register_late_pass(|| box explicit_write::ExplicitWrite);
-    store.register_late_pass(|| box needless_pass_by_value::NeedlessPassByValue);
-    let pass_by_ref_or_value = pass_by_ref_or_value::PassByRefOrValue::new(
-        conf.trivial_copy_size_limit,
-        conf.pass_by_value_size_limit,
-        &sess.target,
-    );
-    store.register_late_pass(move || box pass_by_ref_or_value);
-    store.register_late_pass(|| box ref_option_ref::RefOptionRef);
-    store.register_late_pass(|| box try_err::TryErr);
-    store.register_late_pass(|| box bytecount::ByteCount);
-    store.register_late_pass(|| box infinite_iter::InfiniteIter);
-    store.register_late_pass(|| box inline_fn_without_body::InlineFnWithoutBody);
-    store.register_late_pass(|| box useless_conversion::UselessConversion::default());
-    store.register_late_pass(|| box implicit_hasher::ImplicitHasher);
-    store.register_late_pass(|| box fallible_impl_from::FallibleImplFrom);
-    store.register_late_pass(|| box double_comparison::DoubleComparisons);
-    store.register_late_pass(|| box question_mark::QuestionMark);
-    store.register_early_pass(|| box suspicious_operation_groupings::SuspiciousOperationGroupings);
-    store.register_late_pass(|| box suspicious_trait_impl::SuspiciousImpl);
-    store.register_late_pass(|| box map_unit_fn::MapUnit);
-    store.register_late_pass(|| box inherent_impl::MultipleInherentImpl);
-    store.register_late_pass(|| box neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd);
-    store.register_late_pass(|| box unwrap::Unwrap);
-    store.register_late_pass(|| box duration_subsec::DurationSubsec);
-    store.register_late_pass(|| box indexing_slicing::IndexingSlicing);
-    store.register_late_pass(|| box non_copy_const::NonCopyConst);
-    store.register_late_pass(|| box ptr_offset_with_cast::PtrOffsetWithCast);
-    store.register_late_pass(|| box redundant_clone::RedundantClone);
-    store.register_late_pass(|| box slow_vector_initialization::SlowVectorInit);
-    store.register_late_pass(|| box unnecessary_sort_by::UnnecessarySortBy);
-    store.register_late_pass(|| box unnecessary_wraps::UnnecessaryWraps);
-    store.register_late_pass(|| box assertions_on_constants::AssertionsOnConstants);
-    store.register_late_pass(|| box transmuting_null::TransmutingNull);
-    store.register_late_pass(|| box path_buf_push_overwrite::PathBufPushOverwrite);
-    store.register_late_pass(|| box integer_division::IntegerDivision);
-    store.register_late_pass(|| box inherent_to_string::InherentToString);
-    let max_trait_bounds = conf.max_trait_bounds;
-    store.register_late_pass(move || box trait_bounds::TraitBounds::new(max_trait_bounds));
-    store.register_late_pass(|| box comparison_chain::ComparisonChain);
-    store.register_late_pass(|| box mut_key::MutableKeyType);
-    store.register_late_pass(|| box modulo_arithmetic::ModuloArithmetic);
-    store.register_early_pass(|| box reference::DerefAddrOf);
-    store.register_early_pass(|| box reference::RefInDeref);
-    store.register_early_pass(|| box double_parens::DoubleParens);
-    store.register_late_pass(|| box to_string_in_display::ToStringInDisplay::new());
-    store.register_early_pass(|| box unsafe_removed_from_name::UnsafeNameRemoval);
-    store.register_early_pass(|| box if_not_else::IfNotElse);
-    store.register_early_pass(|| box else_if_without_else::ElseIfWithoutElse);
-    store.register_early_pass(|| box int_plus_one::IntPlusOne);
-    store.register_early_pass(|| box formatting::Formatting);
-    store.register_early_pass(|| box misc_early::MiscEarlyLints);
-    store.register_early_pass(|| box redundant_closure_call::RedundantClosureCall);
-    store.register_late_pass(|| box redundant_closure_call::RedundantClosureCall);
-    store.register_early_pass(|| box unused_unit::UnusedUnit);
-    store.register_late_pass(|| box returns::Return);
-    store.register_early_pass(|| box collapsible_if::CollapsibleIf);
-    store.register_early_pass(|| box items_after_statements::ItemsAfterStatements);
-    store.register_early_pass(|| box precedence::Precedence);
-    store.register_early_pass(|| box needless_continue::NeedlessContinue);
-    store.register_early_pass(|| box redundant_else::RedundantElse);
-    store.register_late_pass(|| box create_dir::CreateDir);
-    store.register_early_pass(|| box needless_arbitrary_self_type::NeedlessArbitrarySelfType);
-    let cargo_ignore_publish = conf.cargo_ignore_publish;
-    store.register_late_pass(move || box cargo_common_metadata::CargoCommonMetadata::new(cargo_ignore_publish));
-    store.register_late_pass(|| box multiple_crate_versions::MultipleCrateVersions);
-    store.register_late_pass(|| box wildcard_dependencies::WildcardDependencies);
-    let literal_representation_lint_fraction_readability = conf.unreadable_literal_lint_fractions;
-    store.register_early_pass(move || box literal_representation::LiteralDigitGrouping::new(literal_representation_lint_fraction_readability));
-    let literal_representation_threshold = conf.literal_representation_threshold;
-    store.register_early_pass(move || box literal_representation::DecimalLiteralRepresentation::new(literal_representation_threshold));
-    let enum_variant_name_threshold = conf.enum_variant_name_threshold;
-    store.register_early_pass(move || box enum_variants::EnumVariantNames::new(enum_variant_name_threshold));
-    store.register_early_pass(|| box tabs_in_doc_comments::TabsInDocComments);
-    let upper_case_acronyms_aggressive = conf.upper_case_acronyms_aggressive;
-    store.register_early_pass(move || box upper_case_acronyms::UpperCaseAcronyms::new(upper_case_acronyms_aggressive));
-    store.register_late_pass(|| box default::Default::default());
-    store.register_late_pass(|| box unused_self::UnusedSelf);
-    store.register_late_pass(|| box mutable_debug_assertion::DebugAssertWithMutCall);
-    store.register_late_pass(|| box exit::Exit);
-    store.register_late_pass(|| box to_digit_is_some::ToDigitIsSome);
-    let array_size_threshold = conf.array_size_threshold;
-    store.register_late_pass(move || box large_stack_arrays::LargeStackArrays::new(array_size_threshold));
-    store.register_late_pass(move || box large_const_arrays::LargeConstArrays::new(array_size_threshold));
-    store.register_late_pass(|| box floating_point_arithmetic::FloatingPointArithmetic);
-    store.register_early_pass(|| box as_conversions::AsConversions);
-    store.register_late_pass(|| box let_underscore::LetUnderscore);
-    store.register_late_pass(|| box atomic_ordering::AtomicOrdering);
-    store.register_early_pass(|| box single_component_path_imports::SingleComponentPathImports);
-    let max_fn_params_bools = conf.max_fn_params_bools;
-    let max_struct_bools = conf.max_struct_bools;
-    store.register_early_pass(move || box excessive_bools::ExcessiveBools::new(max_struct_bools, max_fn_params_bools));
-    store.register_early_pass(|| box option_env_unwrap::OptionEnvUnwrap);
-    let warn_on_all_wildcard_imports = conf.warn_on_all_wildcard_imports;
-    store.register_late_pass(move || box wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports));
-    store.register_late_pass(|| box verbose_file_reads::VerboseFileReads);
-    store.register_late_pass(|| box redundant_pub_crate::RedundantPubCrate::default());
-    store.register_late_pass(|| box unnamed_address::UnnamedAddress);
-    store.register_late_pass(|| box dereference::Dereferencing::default());
-    store.register_late_pass(|| box option_if_let_else::OptionIfLetElse);
-    store.register_late_pass(|| box future_not_send::FutureNotSend);
-    store.register_late_pass(|| box if_let_mutex::IfLetMutex);
-    store.register_late_pass(|| box mut_mutex_lock::MutMutexLock);
-    store.register_late_pass(|| box match_on_vec_items::MatchOnVecItems);
-    store.register_late_pass(|| box manual_async_fn::ManualAsyncFn);
-    store.register_late_pass(|| box vec_resize_to_zero::VecResizeToZero);
-    store.register_late_pass(|| box panic_in_result_fn::PanicInResultFn);
-    let single_char_binding_names_threshold = conf.single_char_binding_names_threshold;
-    store.register_early_pass(move || box non_expressive_names::NonExpressiveNames {
-        single_char_binding_names_threshold,
-    });
-    store.register_late_pass(|| box macro_use::MacroUseImports::default());
-    store.register_late_pass(|| box map_identity::MapIdentity);
-    store.register_late_pass(|| box pattern_type_mismatch::PatternTypeMismatch);
-    store.register_late_pass(|| box stable_sort_primitive::StableSortPrimitive);
-    store.register_late_pass(|| box repeat_once::RepeatOnce);
-    store.register_late_pass(|| box unwrap_in_result::UnwrapInResult);
-    store.register_late_pass(|| box self_assignment::SelfAssignment);
-    store.register_late_pass(|| box manual_unwrap_or::ManualUnwrapOr);
-    store.register_late_pass(|| box manual_ok_or::ManualOkOr);
-    store.register_late_pass(|| box float_equality_without_abs::FloatEqualityWithoutAbs);
-    store.register_late_pass(|| box semicolon_if_nothing_returned::SemicolonIfNothingReturned);
-    store.register_late_pass(|| box async_yields_async::AsyncYieldsAsync);
-    let disallowed_methods = conf.disallowed_methods.iter().cloned().collect::<FxHashSet<_>>();
-    store.register_late_pass(move || box disallowed_method::DisallowedMethod::new(&disallowed_methods));
-    store.register_early_pass(|| box asm_syntax::InlineAsmX86AttSyntax);
-    store.register_early_pass(|| box asm_syntax::InlineAsmX86IntelSyntax);
-    store.register_late_pass(|| box undropped_manually_drops::UndroppedManuallyDrops);
-    store.register_late_pass(|| box strings::StrToString);
-    store.register_late_pass(|| box strings::StringToString);
-    store.register_late_pass(|| box zero_sized_map_values::ZeroSizedMapValues);
-    store.register_late_pass(|| box vec_init_then_push::VecInitThenPush::default());
-    store.register_late_pass(|| box case_sensitive_file_extension_comparisons::CaseSensitiveFileExtensionComparisons);
-    store.register_late_pass(|| box redundant_slicing::RedundantSlicing);
-    store.register_late_pass(|| box from_str_radix_10::FromStrRadix10);
-    store.register_late_pass(|| box manual_map::ManualMap);
-    store.register_late_pass(move || box if_then_some_else_none::IfThenSomeElseNone::new(msrv));
-    store.register_early_pass(|| box bool_assert_comparison::BoolAssertComparison);
-    store.register_late_pass(|| box unused_async::UnusedAsync);
-
     store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
         LintId::of(arithmetic::FLOAT_ARITHMETIC),
         LintId::of(arithmetic::INTEGER_ARITHMETIC),
@@ -1310,7 +1010,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(methods::FILETYPE_IS_FILE),
         LintId::of(methods::GET_UNWRAP),
         LintId::of(methods::UNWRAP_USED),
-        LintId::of(methods::WRONG_PUB_SELF_CONVENTION),
         LintId::of(misc::FLOAT_CMP_CONST),
         LintId::of(misc_early::UNNEEDED_FIELD_PATTERN),
         LintId::of(missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS),
@@ -1322,7 +1021,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(panic_unimplemented::UNIMPLEMENTED),
         LintId::of(panic_unimplemented::UNREACHABLE),
         LintId::of(pattern_type_mismatch::PATTERN_TYPE_MISMATCH),
-        LintId::of(semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED),
         LintId::of(shadow::SHADOW_REUSE),
         LintId::of(shadow::SHADOW_SAME),
         LintId::of(strings::STRING_ADD),
@@ -1363,7 +1061,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(doc::MISSING_PANICS_DOC),
         LintId::of(empty_enum::EMPTY_ENUM),
         LintId::of(enum_variants::MODULE_NAME_REPETITIONS),
-        LintId::of(enum_variants::PUB_ENUM_VARIANT_NAMES),
         LintId::of(eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS),
         LintId::of(excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS),
         LintId::of(excessive_bools::STRUCT_EXCESSIVE_BOOLS),
@@ -1401,6 +1098,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(misc_early::UNSEPARATED_LITERAL_SUFFIX),
         LintId::of(mut_mut::MUT_MUT),
         LintId::of(needless_bitwise_bool::NEEDLESS_BITWISE_BOOL),
+        LintId::of(needless_borrow::REF_BINDING_TO_REFERENCE),
         LintId::of(needless_continue::NEEDLESS_CONTINUE),
         LintId::of(needless_for_each::NEEDLESS_FOR_EACH),
         LintId::of(needless_pass_by_value::NEEDLESS_PASS_BY_VALUE),
@@ -1412,6 +1110,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(ranges::RANGE_PLUS_ONE),
         LintId::of(redundant_else::REDUNDANT_ELSE),
         LintId::of(ref_option_ref::REF_OPTION_REF),
+        LintId::of(semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED),
         LintId::of(shadow::SHADOW_UNRELATED),
         LintId::of(strings::STRING_ADD_ASSIGN),
         LintId::of(trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS),
@@ -1600,6 +1299,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(methods::MANUAL_FILTER_MAP),
         LintId::of(methods::MANUAL_FIND_MAP),
         LintId::of(methods::MANUAL_SATURATING_ARITHMETIC),
+        LintId::of(methods::MANUAL_STR_REPEAT),
         LintId::of(methods::MAP_COLLECT_RESULT_UNIT),
         LintId::of(methods::NEW_RET_NO_SELF),
         LintId::of(methods::OK_EXPECT),
@@ -1615,6 +1315,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(methods::SKIP_WHILE_NEXT),
         LintId::of(methods::STRING_EXTEND_CHARS),
         LintId::of(methods::SUSPICIOUS_MAP),
+        LintId::of(methods::SUSPICIOUS_SPLITN),
         LintId::of(methods::UNINIT_ASSUMED_INIT),
         LintId::of(methods::UNNECESSARY_FILTER_MAP),
         LintId::of(methods::UNNECESSARY_FOLD),
@@ -1644,6 +1345,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(needless_arbitrary_self_type::NEEDLESS_ARBITRARY_SELF_TYPE),
         LintId::of(needless_bool::BOOL_COMPARISON),
         LintId::of(needless_bool::NEEDLESS_BOOL),
+        LintId::of(needless_borrow::NEEDLESS_BORROW),
         LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE),
         LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK),
         LintId::of(needless_update::NEEDLESS_UPDATE),
@@ -1690,7 +1392,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
         LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE),
         LintId::of(strings::STRING_FROM_UTF8_AS_BYTES),
-        LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS),
         LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
         LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
         LintId::of(swap::ALMOST_SWAPPED),
@@ -1827,6 +1528,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(misc_early::REDUNDANT_PATTERN),
         LintId::of(mut_mutex_lock::MUT_MUTEX_LOCK),
         LintId::of(mut_reference::UNNECESSARY_MUT_PASSED),
+        LintId::of(needless_borrow::NEEDLESS_BORROW),
         LintId::of(neg_multiply::NEG_MULTIPLY),
         LintId::of(new_without_default::NEW_WITHOUT_DEFAULT),
         LintId::of(non_copy_const::BORROW_INTERIOR_MUTABLE_CONST),
@@ -1843,7 +1545,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(returns::LET_AND_RETURN),
         LintId::of(returns::NEEDLESS_RETURN),
         LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
-        LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS),
         LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS),
         LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME),
         LintId::of(try_err::TRY_ERR),
@@ -1991,6 +1692,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(mem_replace::MEM_REPLACE_WITH_UNINIT),
         LintId::of(methods::CLONE_DOUBLE_REF),
         LintId::of(methods::ITERATOR_STEP_BY_ZERO),
+        LintId::of(methods::SUSPICIOUS_SPLITN),
         LintId::of(methods::UNINIT_ASSUMED_INIT),
         LintId::of(methods::ZST_OFFSET),
         LintId::of(minmax::MIN_MAX),
@@ -2035,6 +1737,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(loops::NEEDLESS_COLLECT),
         LintId::of(methods::EXPECT_FUN_CALL),
         LintId::of(methods::ITER_NTH),
+        LintId::of(methods::MANUAL_STR_REPEAT),
         LintId::of(methods::OR_FUN_CALL),
         LintId::of(methods::SINGLE_CHAR_PATTERN),
         LintId::of(misc::CMP_OWNED),
@@ -2066,14 +1769,304 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(missing_const_for_fn::MISSING_CONST_FOR_FN),
         LintId::of(mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL),
         LintId::of(mutex_atomic::MUTEX_INTEGER),
-        LintId::of(needless_borrow::NEEDLESS_BORROW),
         LintId::of(path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE),
         LintId::of(redundant_pub_crate::REDUNDANT_PUB_CRATE),
         LintId::of(regex::TRIVIAL_REGEX),
         LintId::of(strings::STRING_LIT_AS_BYTES),
+        LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS),
         LintId::of(transmute::USELESS_TRANSMUTE),
         LintId::of(use_self::USE_SELF),
     ]);
+
+    #[cfg(feature = "metadata-collector-lint")]
+    {
+        if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) {
+            store.register_late_pass(|| box utils::internal_lints::metadata_collector::MetadataCollector::new());
+            return;
+        }
+    }
+
+    // all the internal lints
+    #[cfg(feature = "internal-lints")]
+    {
+        store.register_early_pass(|| box utils::internal_lints::ClippyLintsInternal);
+        store.register_early_pass(|| box utils::internal_lints::ProduceIce);
+        store.register_late_pass(|| box utils::inspector::DeepCodeInspector);
+        store.register_late_pass(|| box utils::internal_lints::CollapsibleCalls);
+        store.register_late_pass(|| box utils::internal_lints::CompilerLintFunctions::new());
+        store.register_late_pass(|| box utils::internal_lints::IfChainStyle);
+        store.register_late_pass(|| box utils::internal_lints::InvalidPaths);
+        store.register_late_pass(|| box utils::internal_lints::InterningDefinedSymbol::default());
+        store.register_late_pass(|| box utils::internal_lints::LintWithoutLintPass::default());
+        store.register_late_pass(|| box utils::internal_lints::MatchTypeOnDiagItem);
+        store.register_late_pass(|| box utils::internal_lints::OuterExpnDataPass);
+    }
+
+    store.register_late_pass(|| box utils::author::Author);
+    store.register_late_pass(|| box await_holding_invalid::AwaitHolding);
+    store.register_late_pass(|| box serde_api::SerdeApi);
+    let vec_box_size_threshold = conf.vec_box_size_threshold;
+    let type_complexity_threshold = conf.type_complexity_threshold;
+    store.register_late_pass(move || box types::Types::new(vec_box_size_threshold, type_complexity_threshold));
+    store.register_late_pass(|| box booleans::NonminimalBool);
+    store.register_late_pass(|| box needless_bitwise_bool::NeedlessBitwiseBool);
+    store.register_late_pass(|| box eq_op::EqOp);
+    store.register_late_pass(|| box enum_clike::UnportableVariant);
+    store.register_late_pass(|| box float_literal::FloatLiteral);
+    let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold;
+    store.register_late_pass(move || box bit_mask::BitMask::new(verbose_bit_mask_threshold));
+    store.register_late_pass(|| box ptr::Ptr);
+    store.register_late_pass(|| box ptr_eq::PtrEq);
+    store.register_late_pass(|| box needless_bool::NeedlessBool);
+    store.register_late_pass(|| box needless_bool::BoolComparison);
+    store.register_late_pass(|| box needless_for_each::NeedlessForEach);
+    store.register_late_pass(|| box approx_const::ApproxConstant);
+    store.register_late_pass(|| box misc::MiscLints);
+    store.register_late_pass(|| box eta_reduction::EtaReduction);
+    store.register_late_pass(|| box identity_op::IdentityOp);
+    store.register_late_pass(|| box erasing_op::ErasingOp);
+    store.register_late_pass(|| box mut_mut::MutMut);
+    store.register_late_pass(|| box mut_reference::UnnecessaryMutPassed);
+    store.register_late_pass(|| box len_zero::LenZero);
+    store.register_late_pass(|| box attrs::Attributes);
+    store.register_late_pass(|| box blocks_in_if_conditions::BlocksInIfConditions);
+    store.register_late_pass(|| box collapsible_match::CollapsibleMatch);
+    store.register_late_pass(|| box unicode::Unicode);
+    store.register_late_pass(|| box unit_return_expecting_ord::UnitReturnExpectingOrd);
+    store.register_late_pass(|| box strings::StringAdd);
+    store.register_late_pass(|| box implicit_return::ImplicitReturn);
+    store.register_late_pass(|| box implicit_saturating_sub::ImplicitSaturatingSub);
+    store.register_late_pass(|| box default_numeric_fallback::DefaultNumericFallback);
+    store.register_late_pass(|| box inconsistent_struct_constructor::InconsistentStructConstructor);
+    store.register_late_pass(|| box non_octal_unix_permissions::NonOctalUnixPermissions);
+    store.register_early_pass(|| box unnecessary_self_imports::UnnecessarySelfImports);
+
+    let msrv = conf.msrv.as_ref().and_then(|s| {
+        parse_msrv(s, None, None).or_else(|| {
+            sess.err(&format!("error reading Clippy's configuration file. `{}` is not a valid Rust version", s));
+            None
+        })
+    });
+
+    let avoid_breaking_exported_api = conf.avoid_breaking_exported_api;
+    store.register_late_pass(move || box methods::Methods::new(avoid_breaking_exported_api, msrv));
+    store.register_late_pass(move || box matches::Matches::new(msrv));
+    store.register_early_pass(move || box manual_non_exhaustive::ManualNonExhaustive::new(msrv));
+    store.register_late_pass(move || box manual_strip::ManualStrip::new(msrv));
+    store.register_early_pass(move || box redundant_static_lifetimes::RedundantStaticLifetimes::new(msrv));
+    store.register_early_pass(move || box redundant_field_names::RedundantFieldNames::new(msrv));
+    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));
+    store.register_late_pass(move || box needless_question_mark::NeedlessQuestionMark);
+    store.register_late_pass(move || box casts::Casts::new(msrv));
+    store.register_early_pass(move || box unnested_or_patterns::UnnestedOrPatterns::new(msrv));
+
+    store.register_late_pass(|| box size_of_in_element_count::SizeOfInElementCount);
+    store.register_late_pass(|| box map_clone::MapClone);
+    store.register_late_pass(|| box map_err_ignore::MapErrIgnore);
+    store.register_late_pass(|| box shadow::Shadow);
+    store.register_late_pass(|| box unit_types::UnitTypes);
+    store.register_late_pass(|| box loops::Loops);
+    store.register_late_pass(|| box main_recursion::MainRecursion::default());
+    store.register_late_pass(|| box lifetimes::Lifetimes);
+    store.register_late_pass(|| box entry::HashMapPass);
+    store.register_late_pass(|| box minmax::MinMaxPass);
+    store.register_late_pass(|| box open_options::OpenOptions);
+    store.register_late_pass(|| box zero_div_zero::ZeroDiv);
+    store.register_late_pass(|| box mutex_atomic::Mutex);
+    store.register_late_pass(|| box needless_update::NeedlessUpdate);
+    store.register_late_pass(|| box needless_borrow::NeedlessBorrow::default());
+    store.register_late_pass(|| box needless_borrowed_ref::NeedlessBorrowedRef);
+    store.register_late_pass(|| box no_effect::NoEffect);
+    store.register_late_pass(|| box temporary_assignment::TemporaryAssignment);
+    store.register_late_pass(|| box transmute::Transmute);
+    let cognitive_complexity_threshold = conf.cognitive_complexity_threshold;
+    store.register_late_pass(move || box cognitive_complexity::CognitiveComplexity::new(cognitive_complexity_threshold));
+    let too_large_for_stack = conf.too_large_for_stack;
+    store.register_late_pass(move || box escape::BoxedLocal{too_large_for_stack});
+    store.register_late_pass(move || box vec::UselessVec{too_large_for_stack});
+    store.register_late_pass(|| box panic_unimplemented::PanicUnimplemented);
+    store.register_late_pass(|| box strings::StringLitAsBytes);
+    store.register_late_pass(|| box derive::Derive);
+    store.register_late_pass(|| box get_last_with_len::GetLastWithLen);
+    store.register_late_pass(|| box drop_forget_ref::DropForgetRef);
+    store.register_late_pass(|| box empty_enum::EmptyEnum);
+    store.register_late_pass(|| box absurd_extreme_comparisons::AbsurdExtremeComparisons);
+    store.register_late_pass(|| box invalid_upcast_comparisons::InvalidUpcastComparisons);
+    store.register_late_pass(|| box regex::Regex::default());
+    store.register_late_pass(|| box copies::CopyAndPaste);
+    store.register_late_pass(|| box copy_iterator::CopyIterator);
+    store.register_late_pass(|| box format::UselessFormat);
+    store.register_late_pass(|| box swap::Swap);
+    store.register_late_pass(|| box overflow_check_conditional::OverflowCheckConditional);
+    store.register_late_pass(|| box new_without_default::NewWithoutDefault::default());
+    let blacklisted_names = conf.blacklisted_names.iter().cloned().collect::<FxHashSet<_>>();
+    store.register_late_pass(move || box blacklisted_name::BlacklistedName::new(blacklisted_names.clone()));
+    let too_many_arguments_threshold = conf.too_many_arguments_threshold;
+    let too_many_lines_threshold = conf.too_many_lines_threshold;
+    store.register_late_pass(move || box functions::Functions::new(too_many_arguments_threshold, too_many_lines_threshold));
+    let doc_valid_idents = conf.doc_valid_idents.iter().cloned().collect::<FxHashSet<_>>();
+    store.register_late_pass(move || box doc::DocMarkdown::new(doc_valid_idents.clone()));
+    store.register_late_pass(|| box neg_multiply::NegMultiply);
+    store.register_late_pass(|| box mem_discriminant::MemDiscriminant);
+    store.register_late_pass(|| box mem_forget::MemForget);
+    store.register_late_pass(|| box arithmetic::Arithmetic::default());
+    store.register_late_pass(|| box assign_ops::AssignOps);
+    store.register_late_pass(|| box let_if_seq::LetIfSeq);
+    store.register_late_pass(|| box eval_order_dependence::EvalOrderDependence);
+    store.register_late_pass(|| box missing_doc::MissingDoc::new());
+    store.register_late_pass(|| box missing_inline::MissingInline);
+    store.register_late_pass(move || box exhaustive_items::ExhaustiveItems);
+    store.register_late_pass(|| box if_let_some_result::OkIfLet);
+    store.register_late_pass(|| box partialeq_ne_impl::PartialEqNeImpl);
+    store.register_late_pass(|| box unused_io_amount::UnusedIoAmount);
+    let enum_variant_size_threshold = conf.enum_variant_size_threshold;
+    store.register_late_pass(move || box large_enum_variant::LargeEnumVariant::new(enum_variant_size_threshold));
+    store.register_late_pass(|| box explicit_write::ExplicitWrite);
+    store.register_late_pass(|| box needless_pass_by_value::NeedlessPassByValue);
+    let pass_by_ref_or_value = pass_by_ref_or_value::PassByRefOrValue::new(
+        conf.trivial_copy_size_limit,
+        conf.pass_by_value_size_limit,
+        conf.avoid_breaking_exported_api,
+        &sess.target,
+    );
+    store.register_late_pass(move || box pass_by_ref_or_value);
+    store.register_late_pass(|| box ref_option_ref::RefOptionRef);
+    store.register_late_pass(|| box try_err::TryErr);
+    store.register_late_pass(|| box bytecount::ByteCount);
+    store.register_late_pass(|| box infinite_iter::InfiniteIter);
+    store.register_late_pass(|| box inline_fn_without_body::InlineFnWithoutBody);
+    store.register_late_pass(|| box useless_conversion::UselessConversion::default());
+    store.register_late_pass(|| box implicit_hasher::ImplicitHasher);
+    store.register_late_pass(|| box fallible_impl_from::FallibleImplFrom);
+    store.register_late_pass(|| box double_comparison::DoubleComparisons);
+    store.register_late_pass(|| box question_mark::QuestionMark);
+    store.register_early_pass(|| box suspicious_operation_groupings::SuspiciousOperationGroupings);
+    store.register_late_pass(|| box suspicious_trait_impl::SuspiciousImpl);
+    store.register_late_pass(|| box map_unit_fn::MapUnit);
+    store.register_late_pass(|| box inherent_impl::MultipleInherentImpl);
+    store.register_late_pass(|| box neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd);
+    store.register_late_pass(|| box unwrap::Unwrap);
+    store.register_late_pass(|| box duration_subsec::DurationSubsec);
+    store.register_late_pass(|| box indexing_slicing::IndexingSlicing);
+    store.register_late_pass(|| box non_copy_const::NonCopyConst);
+    store.register_late_pass(|| box ptr_offset_with_cast::PtrOffsetWithCast);
+    store.register_late_pass(|| box redundant_clone::RedundantClone);
+    store.register_late_pass(|| box slow_vector_initialization::SlowVectorInit);
+    store.register_late_pass(|| box unnecessary_sort_by::UnnecessarySortBy);
+    store.register_late_pass(move || box unnecessary_wraps::UnnecessaryWraps::new(avoid_breaking_exported_api));
+    store.register_late_pass(|| box assertions_on_constants::AssertionsOnConstants);
+    store.register_late_pass(|| box transmuting_null::TransmutingNull);
+    store.register_late_pass(|| box path_buf_push_overwrite::PathBufPushOverwrite);
+    store.register_late_pass(|| box integer_division::IntegerDivision);
+    store.register_late_pass(|| box inherent_to_string::InherentToString);
+    let max_trait_bounds = conf.max_trait_bounds;
+    store.register_late_pass(move || box trait_bounds::TraitBounds::new(max_trait_bounds));
+    store.register_late_pass(|| box comparison_chain::ComparisonChain);
+    store.register_late_pass(|| box mut_key::MutableKeyType);
+    store.register_late_pass(|| box modulo_arithmetic::ModuloArithmetic);
+    store.register_early_pass(|| box reference::DerefAddrOf);
+    store.register_early_pass(|| box reference::RefInDeref);
+    store.register_early_pass(|| box double_parens::DoubleParens);
+    store.register_late_pass(|| box to_string_in_display::ToStringInDisplay::new());
+    store.register_early_pass(|| box unsafe_removed_from_name::UnsafeNameRemoval);
+    store.register_early_pass(|| box if_not_else::IfNotElse);
+    store.register_early_pass(|| box else_if_without_else::ElseIfWithoutElse);
+    store.register_early_pass(|| box int_plus_one::IntPlusOne);
+    store.register_early_pass(|| box formatting::Formatting);
+    store.register_early_pass(|| box misc_early::MiscEarlyLints);
+    store.register_early_pass(|| box redundant_closure_call::RedundantClosureCall);
+    store.register_late_pass(|| box redundant_closure_call::RedundantClosureCall);
+    store.register_early_pass(|| box unused_unit::UnusedUnit);
+    store.register_late_pass(|| box returns::Return);
+    store.register_early_pass(|| box collapsible_if::CollapsibleIf);
+    store.register_early_pass(|| box items_after_statements::ItemsAfterStatements);
+    store.register_early_pass(|| box precedence::Precedence);
+    store.register_early_pass(|| box needless_continue::NeedlessContinue);
+    store.register_early_pass(|| box redundant_else::RedundantElse);
+    store.register_late_pass(|| box create_dir::CreateDir);
+    store.register_early_pass(|| box needless_arbitrary_self_type::NeedlessArbitrarySelfType);
+    let cargo_ignore_publish = conf.cargo_ignore_publish;
+    store.register_late_pass(move || box cargo_common_metadata::CargoCommonMetadata::new(cargo_ignore_publish));
+    store.register_late_pass(|| box multiple_crate_versions::MultipleCrateVersions);
+    store.register_late_pass(|| box wildcard_dependencies::WildcardDependencies);
+    let literal_representation_lint_fraction_readability = conf.unreadable_literal_lint_fractions;
+    store.register_early_pass(move || box literal_representation::LiteralDigitGrouping::new(literal_representation_lint_fraction_readability));
+    let literal_representation_threshold = conf.literal_representation_threshold;
+    store.register_early_pass(move || box literal_representation::DecimalLiteralRepresentation::new(literal_representation_threshold));
+    let enum_variant_name_threshold = conf.enum_variant_name_threshold;
+    store.register_late_pass(move || box enum_variants::EnumVariantNames::new(enum_variant_name_threshold, avoid_breaking_exported_api));
+    store.register_early_pass(|| box tabs_in_doc_comments::TabsInDocComments);
+    let upper_case_acronyms_aggressive = conf.upper_case_acronyms_aggressive;
+    store.register_late_pass(move || box upper_case_acronyms::UpperCaseAcronyms::new(avoid_breaking_exported_api, upper_case_acronyms_aggressive));
+    store.register_late_pass(|| box default::Default::default());
+    store.register_late_pass(|| box unused_self::UnusedSelf);
+    store.register_late_pass(|| box mutable_debug_assertion::DebugAssertWithMutCall);
+    store.register_late_pass(|| box exit::Exit);
+    store.register_late_pass(|| box to_digit_is_some::ToDigitIsSome);
+    let array_size_threshold = conf.array_size_threshold;
+    store.register_late_pass(move || box large_stack_arrays::LargeStackArrays::new(array_size_threshold));
+    store.register_late_pass(move || box large_const_arrays::LargeConstArrays::new(array_size_threshold));
+    store.register_late_pass(|| box floating_point_arithmetic::FloatingPointArithmetic);
+    store.register_early_pass(|| box as_conversions::AsConversions);
+    store.register_late_pass(|| box let_underscore::LetUnderscore);
+    store.register_late_pass(|| box atomic_ordering::AtomicOrdering);
+    store.register_early_pass(|| box single_component_path_imports::SingleComponentPathImports);
+    let max_fn_params_bools = conf.max_fn_params_bools;
+    let max_struct_bools = conf.max_struct_bools;
+    store.register_early_pass(move || box excessive_bools::ExcessiveBools::new(max_struct_bools, max_fn_params_bools));
+    store.register_early_pass(|| box option_env_unwrap::OptionEnvUnwrap);
+    let warn_on_all_wildcard_imports = conf.warn_on_all_wildcard_imports;
+    store.register_late_pass(move || box wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports));
+    store.register_late_pass(|| box verbose_file_reads::VerboseFileReads);
+    store.register_late_pass(|| box redundant_pub_crate::RedundantPubCrate::default());
+    store.register_late_pass(|| box unnamed_address::UnnamedAddress);
+    store.register_late_pass(|| box dereference::Dereferencing::default());
+    store.register_late_pass(|| box option_if_let_else::OptionIfLetElse);
+    store.register_late_pass(|| box future_not_send::FutureNotSend);
+    store.register_late_pass(|| box if_let_mutex::IfLetMutex);
+    store.register_late_pass(|| box mut_mutex_lock::MutMutexLock);
+    store.register_late_pass(|| box match_on_vec_items::MatchOnVecItems);
+    store.register_late_pass(|| box manual_async_fn::ManualAsyncFn);
+    store.register_late_pass(|| box vec_resize_to_zero::VecResizeToZero);
+    store.register_late_pass(|| box panic_in_result_fn::PanicInResultFn);
+    let single_char_binding_names_threshold = conf.single_char_binding_names_threshold;
+    store.register_early_pass(move || box non_expressive_names::NonExpressiveNames {
+        single_char_binding_names_threshold,
+    });
+    store.register_late_pass(|| box macro_use::MacroUseImports::default());
+    store.register_late_pass(|| box map_identity::MapIdentity);
+    store.register_late_pass(|| box pattern_type_mismatch::PatternTypeMismatch);
+    store.register_late_pass(|| box stable_sort_primitive::StableSortPrimitive);
+    store.register_late_pass(|| box repeat_once::RepeatOnce);
+    store.register_late_pass(|| box unwrap_in_result::UnwrapInResult);
+    store.register_late_pass(|| box self_assignment::SelfAssignment);
+    store.register_late_pass(|| box manual_unwrap_or::ManualUnwrapOr);
+    store.register_late_pass(|| box manual_ok_or::ManualOkOr);
+    store.register_late_pass(|| box float_equality_without_abs::FloatEqualityWithoutAbs);
+    store.register_late_pass(|| box semicolon_if_nothing_returned::SemicolonIfNothingReturned);
+    store.register_late_pass(|| box async_yields_async::AsyncYieldsAsync);
+    let disallowed_methods = conf.disallowed_methods.iter().cloned().collect::<FxHashSet<_>>();
+    store.register_late_pass(move || box disallowed_method::DisallowedMethod::new(&disallowed_methods));
+    store.register_early_pass(|| box asm_syntax::InlineAsmX86AttSyntax);
+    store.register_early_pass(|| box asm_syntax::InlineAsmX86IntelSyntax);
+    store.register_late_pass(|| box undropped_manually_drops::UndroppedManuallyDrops);
+    store.register_late_pass(|| box strings::StrToString);
+    store.register_late_pass(|| box strings::StringToString);
+    store.register_late_pass(|| box zero_sized_map_values::ZeroSizedMapValues);
+    store.register_late_pass(|| box vec_init_then_push::VecInitThenPush::default());
+    store.register_late_pass(|| box case_sensitive_file_extension_comparisons::CaseSensitiveFileExtensionComparisons);
+    store.register_late_pass(|| box redundant_slicing::RedundantSlicing);
+    store.register_late_pass(|| box from_str_radix_10::FromStrRadix10);
+    store.register_late_pass(|| box manual_map::ManualMap);
+    store.register_late_pass(move || box if_then_some_else_none::IfThenSomeElseNone::new(msrv));
+    store.register_early_pass(|| box bool_assert_comparison::BoolAssertComparison);
+    store.register_late_pass(|| box unused_async::UnusedAsync);
+
 }
 
 #[rustfmt::skip]
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index 116ad072837..5ae68ba5b2f 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -205,7 +205,7 @@ fn could_use_elision<'tcx>(
         output_visitor.visit_ty(ty);
     }
     for lt in named_generics {
-        input_visitor.visit_generic_param(lt)
+        input_visitor.visit_generic_param(lt);
     }
 
     if input_visitor.abort() || output_visitor.abort() {
@@ -463,7 +463,7 @@ impl<'tcx> Visitor<'tcx> for LifetimeChecker {
         // `'b` in `'a: 'b` is useless unless used elsewhere in
         // a non-lifetime bound
         if let GenericParamKind::Type { .. } = param.kind {
-            walk_generic_param(self, param)
+            walk_generic_param(self, param);
         }
     }
     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
diff --git a/src/tools/clippy/clippy_lints/src/literal_representation.rs b/src/tools/clippy/clippy_lints/src/literal_representation.rs
index e93b2e36b86..e0c5578bd60 100644
--- a/src/tools/clippy/clippy_lints/src/literal_representation.rs
+++ b/src/tools/clippy/clippy_lints/src/literal_representation.rs
@@ -231,7 +231,7 @@ impl EarlyLintPass for LiteralDigitGrouping {
         }
 
         if let ExprKind::Lit(ref lit) = expr.kind {
-            self.check_lit(cx, lit)
+            self.check_lit(cx, lit);
         }
     }
 }
@@ -294,7 +294,7 @@ impl LiteralDigitGrouping {
                         }
                     };
                     if should_warn {
-                        warning_type.display(num_lit.format(), cx, lit.span)
+                        warning_type.display(num_lit.format(), cx, lit.span);
                     }
                 }
             }
@@ -424,7 +424,7 @@ impl EarlyLintPass for DecimalLiteralRepresentation {
         }
 
         if let ExprKind::Lit(ref lit) = expr.kind {
-            self.check_lit(cx, lit)
+            self.check_lit(cx, lit);
         }
     }
 }
@@ -446,7 +446,7 @@ impl DecimalLiteralRepresentation {
                 let hex = format!("{:#X}", val);
                 let num_lit = NumericLiteral::new(&hex, num_lit.suffix, false);
                 let _ = Self::do_lint(num_lit.integer).map_err(|warning_type| {
-                    warning_type.display(num_lit.format(), cx, lit.span)
+                    warning_type.display(num_lit.format(), cx, lit.span);
                 });
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
index ce02ad013be..f0327b5d777 100644
--- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
@@ -43,7 +43,7 @@ pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, arg: &Expr<'_>, m
         "to write this more concisely, try",
         format!("&{}{}", muta, object),
         applicability,
-    )
+    );
 }
 
 /// Returns `true` if the type of expr is one that provides `IntoIterator` impls
diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
index 1425d50f560..d07b5a93b67 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
@@ -88,10 +88,10 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
         if let ty::BorrowKind::MutBorrow = bk {
             if let PlaceBase::Local(id) = cmt.place.base {
                 if Some(id) == self.hir_id_low {
-                    self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id))
+                    self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id));
                 }
                 if Some(id) == self.hir_id_high {
-                    self.span_high = Some(self.cx.tcx.hir().span(diag_expr_id))
+                    self.span_high = Some(self.cx.tcx.hir().span(diag_expr_id));
                 }
             }
         }
@@ -100,10 +100,10 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
     fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
         if let PlaceBase::Local(id) = cmt.place.base {
             if Some(id) == self.hir_id_low {
-                self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id))
+                self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id));
             }
             if Some(id) == self.hir_id_high {
-                self.span_high = Some(self.cx.tcx.hir().span(diag_expr_id))
+                self.span_high = Some(self.cx.tcx.hir().span(diag_expr_id));
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs b/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
index d3406780888..eb82c9c27c3 100644
--- a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
@@ -1,5 +1,5 @@
 use super::NEEDLESS_COLLECT;
-use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
 use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::is_type_diagnostic_item;
@@ -116,9 +116,10 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
                     // Suggest replacing iter_call with iter_replacement, and removing stmt
                     let mut span = MultiSpan::from_span(collect_span);
                     span.push_span_label(iter_call.span, "the iterator could be used here instead".into());
-                    span_lint_and_then(
+                    span_lint_hir_and_then(
                         cx,
                         super::NEEDLESS_COLLECT,
+                        init_expr.hir_id,
                         span,
                         NEEDLESS_COLLECT_MSG,
                         |diag| {
diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
index cb2c83e9029..0f6cd5de761 100644
--- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
@@ -35,7 +35,7 @@ pub(super) fn check<'tcx>(
                 "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})",
                 item_str, vec_str, item_str
             ),
-        )
+        );
     }
 
     if !matches!(pat.kind, PatKind::Wild) {
diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs
index 4db6644b9d7..2f7360210ba 100644
--- a/src/tools/clippy/clippy_lints/src/loops/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs
@@ -80,10 +80,10 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
                         }
                     },
                     ExprKind::Assign(lhs, _, _) if lhs.hir_id == expr.hir_id => {
-                        *state = IncrementVisitorVarState::DontWarn
+                        *state = IncrementVisitorVarState::DontWarn;
                     },
                     ExprKind::AddrOf(BorrowKind::Ref, mutability, _) if mutability == Mutability::Mut => {
-                        *state = IncrementVisitorVarState::DontWarn
+                        *state = IncrementVisitorVarState::DontWarn;
                     },
                     _ => (),
                 }
@@ -207,7 +207,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
                         }
                     },
                     ExprKind::AddrOf(BorrowKind::Ref, mutability, _) if mutability == Mutability::Mut => {
-                        self.state = InitializeVisitorState::DontWarn
+                        self.state = InitializeVisitorState::DontWarn;
                     },
                     _ => (),
                 }
@@ -292,7 +292,7 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor {
                 return;
             }
         }
-        walk_pat(self, pat)
+        walk_pat(self, pat);
     }
 
     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs
index 55404b87ec9..5f9ebad25e8 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_immutable_condition.rs
@@ -1,5 +1,5 @@
 use super::WHILE_IMMUTABLE_CONDITION;
-use crate::consts::constant;
+use clippy_utils::consts::constant;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::usage::mutated_variables;
 use if_chain::if_chain;
diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs
index 914b583186c..66479ae264e 100644
--- a/src/tools/clippy/clippy_lints/src/macro_use.rs
+++ b/src/tools/clippy/clippy_lints/src/macro_use.rs
@@ -212,9 +212,9 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
         let mut suggestions = vec![];
         for ((root, span), path) in used {
             if path.len() == 1 {
-                suggestions.push((span, format!("{}::{}", root, path[0])))
+                suggestions.push((span, format!("{}::{}", root, path[0])));
             } else {
-                suggestions.push((span, format!("{}::{{{}}}", root, path.join(", "))))
+                suggestions.push((span, format!("{}::{{{}}}", root, path.join(", "))));
             }
         }
 
@@ -231,7 +231,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
                     "remove the attribute and import the macro directly, try",
                     help,
                     Applicability::MaybeIncorrect,
-                )
+                );
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs
index 23428524dee..61b5fe81fa9 100644
--- a/src/tools/clippy/clippy_lints/src/manual_strip.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs
@@ -1,4 +1,4 @@
-use crate::consts::{constant, Constant};
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
 use clippy_utils::source::snippet;
 use clippy_utils::usage::mutated_variables;
@@ -123,7 +123,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
                                           kind_word,
                                           snippet(cx, pattern.span, "..")))]
                             .into_iter().chain(strippings.into_iter().map(|span| (span, "<stripped>".into()))),
-                        )
+                        );
                     });
                 }
             }
diff --git a/src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs
index 2f579edd6ad..18038dd7819 100644
--- a/src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_unwrap_or.rs
@@ -1,4 +1,4 @@
-use crate::consts::constant_simple;
+use clippy_utils::consts::constant_simple;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
 use clippy_utils::ty::is_type_diagnostic_item;
diff --git a/src/tools/clippy/clippy_lints/src/map_clone.rs b/src/tools/clippy/clippy_lints/src/map_clone.rs
index 99c35ae3bbf..e1f80ab025c 100644
--- a/src/tools/clippy/clippy_lints/src/map_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/map_clone.rs
@@ -125,7 +125,7 @@ fn lint_needless_cloning(cx: &LateContext<'_>, root: Span, receiver: Span) {
         "remove the `map` call",
         String::new(),
         Applicability::MachineApplicable,
-    )
+    );
 }
 
 fn lint(cx: &LateContext<'_>, replace: Span, root: Span, copied: bool) {
@@ -142,7 +142,7 @@ fn lint(cx: &LateContext<'_>, replace: Span, root: Span, copied: bool) {
                 snippet_with_applicability(cx, root, "..", &mut applicability)
             ),
             applicability,
-        )
+        );
     } else {
         span_lint_and_sugg(
             cx,
@@ -155,6 +155,6 @@ fn lint(cx: &LateContext<'_>, replace: Span, root: Span, copied: bool) {
                 snippet_with_applicability(cx, root, "..", &mut applicability)
             ),
             applicability,
-        )
+        );
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/matches.rs b/src/tools/clippy/clippy_lints/src/matches.rs
index fcd37687010..cd3e3b97928 100644
--- a/src/tools/clippy/clippy_lints/src/matches.rs
+++ b/src/tools/clippy/clippy_lints/src/matches.rs
@@ -1,4 +1,4 @@
-use crate::consts::{constant, miri_to_const, Constant};
+use clippy_utils::consts::{constant, miri_to_const, Constant};
 use clippy_utils::diagnostics::{
     multispan_sugg, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then,
 };
@@ -1144,7 +1144,7 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
                 "try this",
                 suggestions.join(" | "),
                 Applicability::MaybeIncorrect,
-            )
+            );
         },
     };
 }
@@ -1242,7 +1242,7 @@ fn check_match_as_ref(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], exp
                     cast,
                 ),
                 applicability,
-            )
+            );
         }
     }
 }
@@ -1494,7 +1494,7 @@ fn check_match_single_binding<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[A
                     "consider using the scrutinee and body instead",
                     sugg,
                     applicability,
-                )
+                );
             } else {
                 span_lint_and_sugg(
                     cx,
@@ -1747,7 +1747,7 @@ mod redundant_pattern_match {
             match match_source {
                 MatchSource::Normal => find_sugg_for_match(cx, expr, op, arms),
                 MatchSource::IfLetDesugar { contains_else_clause } => {
-                    find_sugg_for_if_let(cx, expr, op, &arms[0], "if", *contains_else_clause)
+                    find_sugg_for_if_let(cx, expr, op, &arms[0], "if", *contains_else_clause);
                 },
                 MatchSource::WhileLetDesugar => find_sugg_for_if_let(cx, expr, op, &arms[0], "while", false),
                 _ => {},
@@ -1876,7 +1876,7 @@ mod redundant_pattern_match {
                             {
                                 self.res = true;
                             } else {
-                                self.visit_expr(self_arg)
+                                self.visit_expr(self_arg);
                             }
                         }
                         args.iter().for_each(|arg| self.visit_expr(arg));
diff --git a/src/tools/clippy/clippy_lints/src/mem_discriminant.rs b/src/tools/clippy/clippy_lints/src/mem_discriminant.rs
index a735c616f6e..aca96e06ef2 100644
--- a/src/tools/clippy/clippy_lints/src/mem_discriminant.rs
+++ b/src/tools/clippy/clippy_lints/src/mem_discriminant.rs
@@ -7,7 +7,6 @@ use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
-use std::iter;
 
 declare_clippy_lint! {
     /// **What it does:** Checks for calls of `mem::discriminant()` on a non-enum type.
@@ -67,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for MemDiscriminant {
                                 }
                             }
 
-                            let derefs: String = iter::repeat('*').take(derefs_needed).collect();
+                            let derefs = "*".repeat(derefs_needed);
                             diag.span_suggestion(
                                 param.span,
                                 "try dereferencing",
diff --git a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
index 287bff886bf..da428a7b487 100644
--- a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
@@ -135,7 +135,7 @@ pub(crate) trait BindInsteadOfMap {
                         .into_iter()
                         .map(|(span1, span2)| (span1, snippet(cx, span2, "_").into())),
                 ),
-            )
+            );
         });
         true
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
index ce2e8fa8b10..1a32af5dc7a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
@@ -8,7 +8,6 @@ use rustc_hir::{BindingAnnotation, Expr, ExprKind, MatchSource, Node, PatKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, adjustment::Adjust};
 use rustc_span::symbol::{sym, Symbol};
-use std::iter;
 
 use super::CLONE_DOUBLE_REF;
 use super::CLONE_ON_COPY;
@@ -54,8 +53,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symbol,
                             ty = inner;
                             n += 1;
                         }
-                        let refs: String = iter::repeat('&').take(n + 1).collect();
-                        let derefs: String = iter::repeat('*').take(n).collect();
+                        let refs = "&".repeat(n + 1);
+                        let derefs = "*".repeat(n);
                         let explicit = format!("<{}{}>::clone({})", refs, ty, snip);
                         diag.span_suggestion(
                             expr.span,
diff --git a/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs b/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs
index ecec6da3aa0..f5b4b6bf8ea 100644
--- a/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/cloned_instead_of_copied.rs
@@ -41,5 +41,5 @@ pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span,
         "try",
         "copied".into(),
         Applicability::MachineApplicable,
-    )
+    );
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs b/src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs
index 12d560653ed..32d40d97bf4 100644
--- a/src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/flat_map_option.rs
@@ -30,5 +30,5 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, arg
         "try",
         "filter_map".into(),
         Applicability::MachineApplicable,
-    )
+    );
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs
index 28d0e8cd4ae..b4188d9ed30 100644
--- a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs
@@ -37,6 +37,10 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Exp
 }
 
 fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'tcx>) -> String {
+    fn strip_angle_brackets(s: &str) -> Option<&str> {
+        s.strip_prefix('<')?.strip_suffix('>')
+    }
+
     let call_site = expr.span.source_callsite();
     if_chain! {
         if let Ok(snippet) = cx.sess().source_map().span_to_snippet(call_site);
@@ -44,23 +48,32 @@ fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'tcx>) -
         if let Some((_, elements)) = snippet_split.split_last();
 
         then {
-            // is there a type specifier? (i.e.: like `<u32>` in `collections::BTreeSet::<u32>::`)
-            if let Some(type_specifier) = snippet_split.iter().find(|e| e.starts_with('<') && e.ends_with('>')) {
-                // remove the type specifier from the path elements
-                let without_ts = elements.iter().filter_map(|e| {
-                    if e == type_specifier { None } else { Some((*e).to_string()) }
-                }).collect::<Vec<_>>();
-                // join and add the type specifier at the end (i.e.: `collections::BTreeSet<u32>`)
-                format!("{}{}", without_ts.join("::"), type_specifier)
-            } else {
-                // type is not explicitly specified so wildcards are needed
-                // i.e.: 2 wildcards in `std::collections::BTreeMap<&i32, &char>`
-                let ty_str = ty.to_string();
-                let start = ty_str.find('<').unwrap_or(0);
-                let end = ty_str.find('>').unwrap_or_else(|| ty_str.len());
-                let nb_wildcard = ty_str[start..end].split(',').count();
-                let wildcards = format!("_{}", ", _".repeat(nb_wildcard - 1));
-                format!("{}<{}>", elements.join("::"), wildcards)
+            if_chain! {
+                if let [type_specifier, _] = snippet_split.as_slice();
+                if let Some(type_specifier) = strip_angle_brackets(type_specifier);
+                if let Some((type_specifier, ..)) = type_specifier.split_once(" as ");
+                then {
+                    type_specifier.to_string()
+                } else {
+                    // is there a type specifier? (i.e.: like `<u32>` in `collections::BTreeSet::<u32>::`)
+                    if let Some(type_specifier) = snippet_split.iter().find(|e| strip_angle_brackets(e).is_some()) {
+                        // remove the type specifier from the path elements
+                        let without_ts = elements.iter().filter_map(|e| {
+                            if e == type_specifier { None } else { Some((*e).to_string()) }
+                        }).collect::<Vec<_>>();
+                        // join and add the type specifier at the end (i.e.: `collections::BTreeSet<u32>`)
+                        format!("{}{}", without_ts.join("::"), type_specifier)
+                    } else {
+                        // type is not explicitly specified so wildcards are needed
+                        // i.e.: 2 wildcards in `std::collections::BTreeMap<&i32, &char>`
+                        let ty_str = ty.to_string();
+                        let start = ty_str.find('<').unwrap_or(0);
+                        let end = ty_str.find('>').unwrap_or_else(|| ty_str.len());
+                        let nb_wildcard = ty_str[start..end].split(',').count();
+                        let wildcards = format!("_{}", ", _".repeat(nb_wildcard - 1));
+                        format!("{}<{}>", elements.join("::"), wildcards)
+                    }
+                }
             }
         } else {
             ty.to_string()
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
index 52d7c15332e..68d906c3ea3 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
@@ -1,4 +1,4 @@
-use crate::consts::{constant, Constant};
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::is_trait_method;
 use clippy_utils::source::snippet_with_applicability;
diff --git a/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
index 06b12998b1a..64c09214a76 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
@@ -1,4 +1,4 @@
-use crate::consts::{constant, Constant};
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_trait_method;
 use rustc_hir as hir;
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs
new file mode 100644
index 00000000000..919e2628c52
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs
@@ -0,0 +1,99 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
+use clippy_utils::sugg::Sugg;
+use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item, match_type};
+use clippy_utils::{is_expr_path_def_path, paths};
+use if_chain::if_chain;
+use rustc_ast::LitKind;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind, LangItem};
+use rustc_lint::LateContext;
+use rustc_middle::ty::{self, Ty, TyS};
+use rustc_span::symbol::sym;
+use std::borrow::Cow;
+
+use super::MANUAL_STR_REPEAT;
+
+enum RepeatKind {
+    String,
+    Char(char),
+}
+
+fn get_ty_param(ty: Ty<'_>) -> Option<Ty<'_>> {
+    if let ty::Adt(_, subs) = ty.kind() {
+        subs.types().next()
+    } else {
+        None
+    }
+}
+
+fn parse_repeat_arg(cx: &LateContext<'_>, e: &Expr<'_>) -> Option<RepeatKind> {
+    if let ExprKind::Lit(lit) = &e.kind {
+        match lit.node {
+            LitKind::Str(..) => Some(RepeatKind::String),
+            LitKind::Char(c) => Some(RepeatKind::Char(c)),
+            _ => None,
+        }
+    } else {
+        let ty = cx.typeck_results().expr_ty(e);
+        if is_type_diagnostic_item(cx, ty, sym::string_type)
+            || (is_type_lang_item(cx, ty, LangItem::OwnedBox) && get_ty_param(ty).map_or(false, TyS::is_str))
+            || (match_type(cx, ty, &paths::COW) && get_ty_param(ty).map_or(false, TyS::is_str))
+        {
+            Some(RepeatKind::String)
+        } else {
+            let ty = ty.peel_refs();
+            (ty.is_str() || is_type_diagnostic_item(cx, ty, sym::string_type)).then(|| RepeatKind::String)
+        }
+    }
+}
+
+pub(super) fn check(
+    cx: &LateContext<'_>,
+    collect_expr: &Expr<'_>,
+    take_expr: &Expr<'_>,
+    take_self_arg: &Expr<'_>,
+    take_arg: &Expr<'_>,
+) {
+    if_chain! {
+        if let ExprKind::Call(repeat_fn, [repeat_arg]) = take_self_arg.kind;
+        if is_expr_path_def_path(cx, repeat_fn, &paths::ITER_REPEAT);
+        if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(collect_expr), sym::string_type);
+        if let Some(collect_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id);
+        if let Some(take_id) = cx.typeck_results().type_dependent_def_id(take_expr.hir_id);
+        if let Some(iter_trait_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
+        if cx.tcx.trait_of_item(collect_id) == Some(iter_trait_id);
+        if cx.tcx.trait_of_item(take_id) == Some(iter_trait_id);
+        if let Some(repeat_kind) = parse_repeat_arg(cx, repeat_arg);
+        let ctxt = collect_expr.span.ctxt();
+        if ctxt == take_expr.span.ctxt();
+        if ctxt == take_self_arg.span.ctxt();
+        then {
+            let mut app = Applicability::MachineApplicable;
+            let count_snip = snippet_with_context(cx, take_arg.span, ctxt, "..", &mut app).0;
+
+            let val_str = match repeat_kind {
+                RepeatKind::Char(_) if repeat_arg.span.ctxt() != ctxt => return,
+                RepeatKind::Char('\'') => r#""'""#.into(),
+                RepeatKind::Char('"') => r#""\"""#.into(),
+                RepeatKind::Char(_) =>
+                    match snippet_with_applicability(cx, repeat_arg.span, "..", &mut app) {
+                        Cow::Owned(s) => Cow::Owned(format!("\"{}\"", &s[1..s.len() - 1])),
+                        s @ Cow::Borrowed(_) => s,
+                    },
+                RepeatKind::String =>
+                    Sugg::hir_with_context(cx, repeat_arg, ctxt, "..", &mut app).maybe_par().to_string().into(),
+            };
+
+            span_lint_and_sugg(
+                cx,
+                MANUAL_STR_REPEAT,
+                collect_expr.span,
+                "manual implementation of `str::repeat` using iterators",
+                "try this",
+                format!("{}.repeat({})", val_str, count_snip),
+                app
+            )
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index e0d29682146..c8ae972f18c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -32,6 +32,7 @@ mod iter_nth_zero;
 mod iter_skip_next;
 mod iterator_step_by_zero;
 mod manual_saturating_arithmetic;
+mod manual_str_repeat;
 mod map_collect_result_unit;
 mod map_flatten;
 mod map_unwrap_or;
@@ -48,6 +49,7 @@ mod single_char_push_string;
 mod skip_while_next;
 mod string_extend_chars;
 mod suspicious_map;
+mod suspicious_splitn;
 mod uninit_assumed_init;
 mod unnecessary_filter_map;
 mod unnecessary_fold;
@@ -61,7 +63,7 @@ mod zst_offset;
 use bind_instead_of_map::BindInsteadOfMap;
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
 use clippy_utils::ty::{contains_adt_constructor, contains_ty, implements_trait, is_copy, is_type_diagnostic_item};
-use clippy_utils::{contains_return, get_trait_def_id, in_macro, iter_input_pats, paths, return_ty};
+use clippy_utils::{contains_return, get_trait_def_id, in_macro, iter_input_pats, meets_msrv, msrvs, paths, return_ty};
 use if_chain::if_chain;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
@@ -283,30 +285,6 @@ declare_clippy_lint! {
 }
 
 declare_clippy_lint! {
-    /// **What it does:** This is the same as
-    /// [`wrong_self_convention`](#wrong_self_convention), but for public items.
-    ///
-    /// **Why is this bad?** See [`wrong_self_convention`](#wrong_self_convention).
-    ///
-    /// **Known problems:** Actually *renaming* the function may break clients if
-    /// the function is part of the public interface. In that case, be mindful of
-    /// the stability guarantees you've given your users.
-    ///
-    /// **Example:**
-    /// ```rust
-    /// # struct X;
-    /// impl<'a> X {
-    ///     pub fn as_str(self) -> &'a str {
-    ///         "foo"
-    ///     }
-    /// }
-    /// ```
-    pub WRONG_PUB_SELF_CONVENTION,
-    restriction,
-    "defining a public method named with an established prefix (like \"into_\") that takes `self` with the wrong convention"
-}
-
-declare_clippy_lint! {
     /// **What it does:** Checks for usage of `ok().expect(..)`.
     ///
     /// **Why is this bad?** Because you usually call `expect()` on the `Result`
@@ -1657,14 +1635,69 @@ declare_clippy_lint! {
     "replace `.iter().count()` with `.len()`"
 }
 
+declare_clippy_lint! {
+    /// **What it does:** Checks for calls to [`splitn`]
+    /// (https://doc.rust-lang.org/std/primitive.str.html#method.splitn) and
+    /// related functions with either zero or one splits.
+    ///
+    /// **Why is this bad?** These calls don't actually split the value and are
+    /// likely to be intended as a different number.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust
+    /// // Bad
+    /// let s = "";
+    /// for x in s.splitn(1, ":") {
+    ///     // use x
+    /// }
+    ///
+    /// // Good
+    /// let s = "";
+    /// for x in s.splitn(2, ":") {
+    ///     // use x
+    /// }
+    /// ```
+    pub SUSPICIOUS_SPLITN,
+    correctness,
+    "checks for `.splitn(0, ..)` and `.splitn(1, ..)`"
+}
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for manual implementations of `str::repeat`
+    ///
+    /// **Why is this bad?** These are both harder to read, as well as less performant.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust
+    /// // Bad
+    /// let x: String = std::iter::repeat('x').take(10).collect();
+    ///
+    /// // Good
+    /// let x: String = "x".repeat(10);
+    /// ```
+    pub MANUAL_STR_REPEAT,
+    perf,
+    "manual implementation of `str::repeat`"
+}
+
 pub struct Methods {
+    avoid_breaking_exported_api: bool,
     msrv: Option<RustcVersion>,
 }
 
 impl Methods {
     #[must_use]
-    pub fn new(msrv: Option<RustcVersion>) -> Self {
-        Self { msrv }
+    pub fn new(avoid_breaking_exported_api: bool, msrv: Option<RustcVersion>) -> Self {
+        Self {
+            avoid_breaking_exported_api,
+            msrv,
+        }
     }
 }
 
@@ -1673,7 +1706,6 @@ impl_lint_pass!(Methods => [
     EXPECT_USED,
     SHOULD_IMPLEMENT_TRAIT,
     WRONG_SELF_CONVENTION,
-    WRONG_PUB_SELF_CONVENTION,
     OK_EXPECT,
     MAP_UNWRAP_OR,
     RESULT_MAP_OR_INTO_OPTION,
@@ -1726,7 +1758,9 @@ impl_lint_pass!(Methods => [
     MAP_COLLECT_RESULT_UNIT,
     FROM_ITER_INSTEAD_OF_COLLECT,
     INSPECT_FOR_EACH,
-    IMPLICIT_CLONE
+    IMPLICIT_CLONE,
+    SUSPICIOUS_SPLITN,
+    MANUAL_STR_REPEAT
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
@@ -1838,11 +1872,13 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
                     }
                 }
 
-                if sig.decl.implicit_self.has_implicit_self() {
+                if sig.decl.implicit_self.has_implicit_self()
+                    && !(self.avoid_breaking_exported_api
+                        && cx.access_levels.is_exported(impl_item.hir_id()))
+                {
                     wrong_self_convention::check(
                         cx,
                         &name,
-                        item.vis.node.is_pub(),
                         self_ty,
                         first_arg_ty,
                         first_arg.pat.span,
@@ -1915,7 +1951,6 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
                 wrong_self_convention::check(
                     cx,
                     &item.ident.name.as_str(),
-                    false,
                     self_ty,
                     first_arg_ty,
                     first_arg_span,
@@ -1951,7 +1986,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
     if let Some((name, [recv, args @ ..], span)) = method_call!(expr) {
         match (name, args) {
             ("add" | "offset" | "sub" | "wrapping_offset" | "wrapping_add" | "wrapping_sub", [recv, _]) => {
-                zst_offset::check(cx, expr, recv)
+                zst_offset::check(cx, expr, recv);
             },
             ("and_then", [arg]) => {
                 let biom_option_linted = bind_instead_of_map::OptionAndThenSome::check(cx, expr, recv, arg);
@@ -1969,6 +2004,11 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
                 Some(("map", [m_recv, m_arg], _)) => {
                     map_collect_result_unit::check(cx, expr, m_recv, m_arg, recv);
                 },
+                Some(("take", [take_self_arg, take_arg], _)) => {
+                    if meets_msrv(msrv, &msrvs::STR_REPEAT) {
+                        manual_str_repeat::check(cx, expr, recv, take_self_arg, take_arg);
+                    }
+                },
                 _ => {},
             },
             ("count", []) => match method_call!(recv) {
@@ -2012,7 +2052,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
                         ("as_mut", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, true, msrv),
                         ("as_ref", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, false, msrv),
                         ("filter", [f_arg]) => {
-                            filter_map::check(cx, expr, recv2, f_arg, span2, recv, m_arg, span, false)
+                            filter_map::check(cx, expr, recv2, f_arg, span2, recv, m_arg, span, false);
                         },
                         ("find", [f_arg]) => filter_map::check(cx, expr, recv2, f_arg, span2, recv, m_arg, span, true),
                         _ => {},
@@ -2044,6 +2084,9 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
                     unnecessary_lazy_eval::check(cx, expr, recv, arg, "or");
                 }
             },
+            ("splitn" | "splitn_mut" | "rsplitn" | "rsplitn_mut", [count_arg, _]) => {
+                suspicious_splitn::check(cx, name, expr, recv, count_arg);
+            },
             ("step_by", [arg]) => iterator_step_by_zero::check(cx, expr, arg),
             ("to_os_string" | "to_owned" | "to_path_buf" | "to_vec", []) => {
                 implicit_clone::check(cx, name, expr, recv, span);
@@ -2058,7 +2101,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
                     manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]);
                 },
                 Some(("map", [m_recv, m_arg], span)) => {
-                    option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span)
+                    option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span);
                 },
                 _ => {},
             },
@@ -2073,7 +2116,7 @@ fn check_methods<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, msrv: Optio
 
 fn check_is_some_is_none(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, is_some: bool) {
     if let Some((name @ ("find" | "position" | "rposition"), [f_recv, arg], span)) = method_call!(recv) {
-        search_is_some::check(cx, expr, name, is_some, f_recv, arg, recv, span)
+        search_is_some::check(cx, expr, name, is_some, f_recv, arg, recv, span);
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs
new file mode 100644
index 00000000000..a271df60572
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs
@@ -0,0 +1,56 @@
+use clippy_utils::consts::{constant, Constant};
+use clippy_utils::diagnostics::span_lint_and_note;
+use if_chain::if_chain;
+use rustc_ast::LitKind;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::LateContext;
+use rustc_span::source_map::Spanned;
+
+use super::SUSPICIOUS_SPLITN;
+
+pub(super) fn check(
+    cx: &LateContext<'_>,
+    method_name: &str,
+    expr: &Expr<'_>,
+    self_arg: &Expr<'_>,
+    count_arg: &Expr<'_>,
+) {
+    if_chain! {
+        if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg);
+        if count <= 1;
+        if let Some(call_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
+        if let Some(impl_id) = cx.tcx.impl_of_method(call_id);
+        let lang_items = cx.tcx.lang_items();
+        if lang_items.slice_impl() == Some(impl_id) || lang_items.str_impl() == Some(impl_id);
+        then {
+            // Ignore empty slice and string literals when used with a literal count.
+            if (matches!(self_arg.kind, ExprKind::Array([]))
+                || matches!(self_arg.kind, ExprKind::Lit(Spanned { node: LitKind::Str(s, _), .. }) if s.is_empty())
+            ) && matches!(count_arg.kind, ExprKind::Lit(_))
+            {
+                return;
+            }
+
+            let (msg, note_msg) = if count == 0 {
+                (format!("`{}` called with `0` splits", method_name),
+                "the resulting iterator will always return `None`")
+            } else {
+                (format!("`{}` called with `1` split", method_name),
+                if lang_items.slice_impl() == Some(impl_id) {
+                    "the resulting iterator will always return the entire slice followed by `None`"
+                } else {
+                    "the resulting iterator will always return the entire string followed by `None`"
+                })
+            };
+
+            span_lint_and_note(
+                cx,
+                SUSPICIOUS_SPLITN,
+                expr.span,
+                &msg,
+                None,
+                note_msg,
+            );
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
index 75517c48a21..4c4034437da 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
@@ -87,7 +87,7 @@ pub(super) fn check(
             ast::LitKind::Bool(true) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::And, "all", true),
             ast::LitKind::Int(0, _) => check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Add, "sum", false),
             ast::LitKind::Int(1, _) => {
-                check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Mul, "product", false)
+                check_fold_with_op(cx, expr, acc, fold_span, hir::BinOpKind::Mul, "product", false);
             },
             _ => (),
         }
diff --git a/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs b/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs
index 1773c26c251..a2e09e5ecec 100644
--- a/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs
@@ -6,7 +6,6 @@ use rustc_middle::ty::TyS;
 use rustc_span::source_map::Span;
 use std::fmt;
 
-use super::WRONG_PUB_SELF_CONVENTION;
 use super::WRONG_SELF_CONVENTION;
 
 #[rustfmt::skip]
@@ -21,9 +20,9 @@ const CONVENTIONS: [(&[Convention], &[SelfKind]); 9] = [
 
     // Conversion using `to_` can use borrowed (non-Copy types) or owned (Copy types).
     // Source: https://rust-lang.github.io/api-guidelines/naming.html#ad-hoc-conversions-follow-as_-to_-into_-conventions-c-conv
-    (&[Convention::StartsWith("to_"), Convention::NotEndsWith("_mut"), Convention::IsSelfTypeCopy(false), 
+    (&[Convention::StartsWith("to_"), Convention::NotEndsWith("_mut"), Convention::IsSelfTypeCopy(false),
     Convention::IsTraitItem(false), Convention::ImplementsTrait(false)], &[SelfKind::Ref]),
-    (&[Convention::StartsWith("to_"), Convention::NotEndsWith("_mut"), Convention::IsSelfTypeCopy(true), 
+    (&[Convention::StartsWith("to_"), Convention::NotEndsWith("_mut"), Convention::IsSelfTypeCopy(true),
     Convention::IsTraitItem(false), Convention::ImplementsTrait(false)], &[SelfKind::Value]),
 ];
 
@@ -85,18 +84,12 @@ impl fmt::Display for Convention {
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     item_name: &str,
-    is_pub: bool,
     self_ty: &'tcx TyS<'tcx>,
     first_arg_ty: &'tcx TyS<'tcx>,
     first_arg_span: Span,
     implements_trait: bool,
     is_trait_item: bool,
 ) {
-    let lint = if is_pub {
-        WRONG_PUB_SELF_CONVENTION
-    } else {
-        WRONG_SELF_CONVENTION
-    };
     if let Some((conventions, self_kinds)) = &CONVENTIONS.iter().find(|(convs, _)| {
         convs
             .iter()
@@ -142,7 +135,7 @@ pub(super) fn check<'tcx>(
 
             span_lint_and_help(
                 cx,
-                lint,
+                WRONG_SELF_CONVENTION,
                 first_arg_span,
                 &format!(
                     "{} usually take {}",
diff --git a/src/tools/clippy/clippy_lints/src/minmax.rs b/src/tools/clippy/clippy_lints/src/minmax.rs
index 45948f4d926..ff3473b744e 100644
--- a/src/tools/clippy/clippy_lints/src/minmax.rs
+++ b/src/tools/clippy/clippy_lints/src/minmax.rs
@@ -1,4 +1,4 @@
-use crate::consts::{constant_simple, Constant};
+use clippy_utils::consts::{constant_simple, Constant};
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::{match_def_path, match_trait_method, paths};
 use if_chain::if_chain;
diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs
index b5d2549242b..804c04fe1b8 100644
--- a/src/tools/clippy/clippy_lints/src/misc.rs
+++ b/src/tools/clippy/clippy_lints/src/misc.rs
@@ -17,7 +17,7 @@ use rustc_span::hygiene::DesugaringKind;
 use rustc_span::source_map::{ExpnKind, Span};
 use rustc_span::symbol::sym;
 
-use crate::consts::{constant, Constant};
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{
     expr_path_res, get_item_name, get_parent_expr, higher, in_constant, is_diag_trait_item, is_integer_const,
@@ -355,8 +355,10 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
             if binop.node == BinOpKind::And || binop.node == BinOpKind::Or;
             if let Some(sugg) = Sugg::hir_opt(cx, a);
             then {
-                span_lint_and_then(cx,
+                span_lint_hir_and_then(
+                    cx,
                     SHORT_CIRCUIT_STATEMENT,
+                    expr.hir_id,
                     stmt.span,
                     "boolean short circuit operator in statement may be clearer using an explicit test",
                     |diag| {
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
index dd38316fa25..050b6805b7c 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
@@ -310,7 +310,7 @@ impl EarlyLintPass for MiscEarlyLints {
         if in_external_macro(cx.sess(), expr.span) {
             return;
         }
-        double_neg::check(cx, expr)
+        double_neg::check(cx, expr);
     }
 }
 
@@ -334,15 +334,15 @@ impl MiscEarlyLints {
             };
             unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "integer");
             if lit_snip.starts_with("0x") {
-                mixed_case_hex_literals::check(cx, lit, suffix, &lit_snip)
+                mixed_case_hex_literals::check(cx, lit, suffix, &lit_snip);
             } else if lit_snip.starts_with("0b") || lit_snip.starts_with("0o") {
-                /* nothing to do */
+                // nothing to do
             } else if value != 0 && lit_snip.starts_with('0') {
-                zero_prefixed_literal::check(cx, lit, &lit_snip)
+                zero_prefixed_literal::check(cx, lit, &lit_snip);
             }
         } else if let LitKind::Float(_, LitFloatType::Suffixed(float_ty)) = lit.kind {
             let suffix = float_ty.name_str();
-            unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "float")
+            unseparated_literal_suffix::check(cx, lit, &lit_snip, suffix, "float");
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs
index dfab3e8a931..a46a7407df0 100644
--- a/src/tools/clippy/clippy_lints/src/missing_doc.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs
@@ -7,8 +7,7 @@
 
 use clippy_utils::attrs::is_doc_hidden;
 use clippy_utils::diagnostics::span_lint;
-use if_chain::if_chain;
-use rustc_ast::ast::{self, MetaItem, MetaItemKind};
+use rustc_ast::ast;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty;
@@ -56,20 +55,6 @@ impl MissingDoc {
         *self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
     }
 
-    fn has_include(meta: Option<MetaItem>) -> bool {
-        if_chain! {
-            if let Some(meta) = meta;
-            if let MetaItemKind::List(list) = meta.kind;
-            if let Some(meta) = list.get(0);
-            if let Some(name) = meta.ident();
-            then {
-                name.name == sym::include
-            } else {
-                false
-            }
-        }
-    }
-
     fn check_missing_docs_attrs(
         &self,
         cx: &LateContext<'_>,
@@ -93,9 +78,9 @@ impl MissingDoc {
             return;
         }
 
-        let has_doc = attrs.iter().any(|a| {
-            a.is_doc_comment() || a.doc_str().is_some() || a.value_str().is_some() || Self::has_include(a.meta())
-        });
+        let has_doc = attrs
+            .iter()
+            .any(|a| a.doc_str().is_some());
         if !has_doc {
             span_lint(
                 cx,
diff --git a/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs b/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs
index 64e9dc85466..1414fdc1b11 100644
--- a/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/modulo_arithmetic.rs
@@ -1,4 +1,4 @@
-use crate::consts::{constant, Constant};
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::sext;
 use if_chain::if_chain;
diff --git a/src/tools/clippy/clippy_lints/src/mut_reference.rs b/src/tools/clippy/clippy_lints/src/mut_reference.rs
index cea6fce1195..6efe8ffcde0 100644
--- a/src/tools/clippy/clippy_lints/src/mut_reference.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_reference.rs
@@ -48,7 +48,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryMutPassed {
                 let def_id = cx.typeck_results().type_dependent_def_id(e.hir_id).unwrap();
                 let substs = cx.typeck_results().node_substs(e.hir_id);
                 let method_type = cx.tcx.type_of(def_id).subst(cx.tcx, substs);
-                check_arguments(cx, arguments, method_type, &path.ident.as_str(), "method")
+                check_arguments(cx, arguments, method_type, &path.ident.as_str(), "method");
             },
             _ => (),
         }
diff --git a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
index 7dfe12cd4eb..25645a0e7a2 100644
--- a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
+++ b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
@@ -107,7 +107,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MutArgVisitor<'a, 'tcx> {
             _ if !self.found => self.expr_span = Some(expr.span),
             _ => return,
         }
-        walk_expr(self, expr)
+        walk_expr(self, expr);
     }
 
     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
diff --git a/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs b/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs
index 3e2b2782ed5..fe3c4455be5 100644
--- a/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs
@@ -121,7 +121,7 @@ impl EarlyLintPass for NeedlessArbitrarySelfType {
         match &p.ty.kind {
             TyKind::Path(None, path) => {
                 if let PatKind::Ident(BindingMode::ByValue(mutbl), _, _) = p.pat.kind {
-                    check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Value, mutbl)
+                    check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Value, mutbl);
                 }
             },
             TyKind::Rptr(lifetime, mut_ty) => {
@@ -129,7 +129,7 @@ impl EarlyLintPass for NeedlessArbitrarySelfType {
                 if let TyKind::Path(None, path) = &mut_ty.ty.kind;
                 if let PatKind::Ident(BindingMode::ByValue(Mutability::Not), _, _) = p.pat.kind;
                     then {
-                        check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl)
+                        check_param_inner(cx, path, p.span.to(p.ty.span), &Mode::Ref(*lifetime), mut_ty.mutbl);
                     }
                 }
             },
diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs
index dd458198637..3b3736fd3a1 100644
--- a/src/tools/clippy/clippy_lints/src/needless_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs
@@ -82,7 +82,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
                 }
 
                 if is_else_clause(cx.tcx, e) {
-                    snip = snip.blockify()
+                    snip = snip.blockify();
                 }
 
                 span_lint_and_sugg(
@@ -144,7 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for BoolComparison {
                         |h: Sugg<'_>| !h,
                         "equality checks against false can be replaced by a negation",
                     ));
-                    check_comparison(cx, e, true_case, false_case, true_case, false_case, ignore_no_literal)
+                    check_comparison(cx, e, true_case, false_case, true_case, false_case, ignore_no_literal);
                 },
                 BinOpKind::Ne => {
                     let true_case = Some((
@@ -152,7 +152,7 @@ impl<'tcx> LateLintPass<'tcx> for BoolComparison {
                         "inequality checks against true can be replaced by a negation",
                     ));
                     let false_case = Some((|h| h, "inequality checks against false are unnecessary"));
-                    check_comparison(cx, e, true_case, false_case, true_case, false_case, ignore_no_literal)
+                    check_comparison(cx, e, true_case, false_case, true_case, false_case, ignore_no_literal);
                 },
                 BinOpKind::Lt => check_comparison(
                     cx,
@@ -251,22 +251,22 @@ fn check_comparison<'a, 'tcx>(
                             snippet_with_applicability(cx, expression_info.right_span, "..", &mut applicability)
                         ),
                         applicability,
-                    )
+                    );
                 }
             }
 
             match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) {
                 (Bool(true), Other) => left_true.map_or((), |(h, m)| {
-                    suggest_bool_comparison(cx, e, right_side, applicability, m, h)
+                    suggest_bool_comparison(cx, e, right_side, applicability, m, h);
                 }),
                 (Other, Bool(true)) => right_true.map_or((), |(h, m)| {
-                    suggest_bool_comparison(cx, e, left_side, applicability, m, h)
+                    suggest_bool_comparison(cx, e, left_side, applicability, m, h);
                 }),
                 (Bool(false), Other) => left_false.map_or((), |(h, m)| {
-                    suggest_bool_comparison(cx, e, right_side, applicability, m, h)
+                    suggest_bool_comparison(cx, e, right_side, applicability, m, h);
                 }),
                 (Other, Bool(false)) => right_false.map_or((), |(h, m)| {
-                    suggest_bool_comparison(cx, e, left_side, applicability, m, h)
+                    suggest_bool_comparison(cx, e, left_side, applicability, m, h);
                 }),
                 (Other, Other) => no_literal.map_or((), |(h, m)| {
                     let left_side = Sugg::hir_with_applicability(cx, left_side, "..", &mut applicability);
@@ -279,7 +279,7 @@ fn check_comparison<'a, 'tcx>(
                         "try simplifying it as shown",
                         h(left_side, right_side).to_string(),
                         applicability,
-                    )
+                    );
                 }),
                 _ => (),
             }
diff --git a/src/tools/clippy/clippy_lints/src/needless_borrow.rs b/src/tools/clippy/clippy_lints/src/needless_borrow.rs
index eef3c16730b..dd1dfa2bdfb 100644
--- a/src/tools/clippy/clippy_lints/src/needless_borrow.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_borrow.rs
@@ -3,16 +3,18 @@
 //! This lint is **warn** by default
 
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::is_automatically_derived;
-use clippy_utils::source::snippet_opt;
+use clippy_utils::source::{snippet_opt, snippet_with_applicability, snippet_with_context};
+use clippy_utils::{get_parent_expr, in_macro, path_to_local};
 use if_chain::if_chain;
+use rustc_ast::util::parser::PREC_POSTFIX;
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::Applicability;
-use rustc_hir::{BindingAnnotation, BorrowKind, Expr, ExprKind, Item, Mutability, Pat, PatKind};
+use rustc_hir::{BindingAnnotation, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, Mutability, Pat, PatKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::def_id::LocalDefId;
+use rustc_span::Span;
 
 declare_clippy_lint! {
     /// **What it does:** Checks for address of operations (`&`) that are going to
@@ -32,20 +34,70 @@ declare_clippy_lint! {
     /// let x: &i32 = &5;
     /// ```
     pub NEEDLESS_BORROW,
-    nursery,
+    style,
     "taking a reference that is going to be automatically dereferenced"
 }
 
+declare_clippy_lint! {
+    /// **What it does:** Checks for `ref` bindings which create a reference to a reference.
+    ///
+    /// **Why is this bad?** The address-of operator at the use site is clearer about the need for a reference.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    /// ```rust
+    /// // Bad
+    /// let x = Some("");
+    /// if let Some(ref x) = x {
+    ///     // use `x` here
+    /// }
+    ///
+    /// // Good
+    /// let x = Some("");
+    /// if let Some(x) = x {
+    ///     // use `&x` here
+    /// }
+    /// ```
+    pub REF_BINDING_TO_REFERENCE,
+    pedantic,
+    "`ref` binding to a reference"
+}
+
+impl_lint_pass!(NeedlessBorrow => [NEEDLESS_BORROW, REF_BINDING_TO_REFERENCE]);
 #[derive(Default)]
 pub struct NeedlessBorrow {
-    derived_item: Option<LocalDefId>,
+    /// The body the first local was found in. Used to emit lints when the traversal of the body has
+    /// been finished. Note we can't lint at the end of every body as they can be nested within each
+    /// other.
+    current_body: Option<BodyId>,
+    /// The list of locals currently being checked by the lint.
+    /// If the value is `None`, then the binding has been seen as a ref pattern, but is not linted.
+    /// This is needed for or patterns where one of the branches can be linted, but another can not
+    /// be.
+    ///
+    /// e.g. `m!(x) | Foo::Bar(ref x)`
+    ref_locals: FxIndexMap<HirId, Option<RefPat>>,
 }
 
-impl_lint_pass!(NeedlessBorrow => [NEEDLESS_BORROW]);
+struct RefPat {
+    /// Whether every usage of the binding is dereferenced.
+    always_deref: bool,
+    /// The spans of all the ref bindings for this local.
+    spans: Vec<Span>,
+    /// The applicability of this suggestion.
+    app: Applicability,
+    /// All the replacements which need to be made.
+    replacements: Vec<(Span, String)>,
+}
 
 impl<'tcx> LateLintPass<'tcx> for NeedlessBorrow {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
-        if e.span.from_expansion() || self.derived_item.is_some() {
+        if let Some(local) = path_to_local(e) {
+            self.check_local_usage(cx, e, local);
+        }
+
+        if e.span.from_expansion() {
             return;
         }
         if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = e.kind {
@@ -85,50 +137,131 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrow {
             }
         }
     }
+
     fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
-        if pat.span.from_expansion() || self.derived_item.is_some() {
-            return;
+        if let PatKind::Binding(BindingAnnotation::Ref, id, name, _) = pat.kind {
+            if let Some(opt_prev_pat) = self.ref_locals.get_mut(&id) {
+                // This binding id has been seen before. Add this pattern to the list of changes.
+                if let Some(prev_pat) = opt_prev_pat {
+                    if in_macro(pat.span) {
+                        // Doesn't match the context of the previous pattern. Can't lint here.
+                        *opt_prev_pat = None;
+                    } else {
+                        prev_pat.spans.push(pat.span);
+                        prev_pat.replacements.push((
+                            pat.span,
+                            snippet_with_context(cx, name.span, pat.span.ctxt(), "..", &mut prev_pat.app)
+                                .0
+                                .into(),
+                        ));
+                    }
+                }
+                return;
+            }
+
+            if_chain! {
+                if !in_macro(pat.span);
+                if let ty::Ref(_, tam, _) = *cx.typeck_results().pat_ty(pat).kind();
+                // only lint immutable refs, because borrowed `&mut T` cannot be moved out
+                if let ty::Ref(_, _, Mutability::Not) = *tam.kind();
+                then {
+                    let mut app = Applicability::MachineApplicable;
+                    let snip = snippet_with_context(cx, name.span, pat.span.ctxt(), "..", &mut app).0;
+                    self.current_body = self.current_body.or(cx.enclosing_body);
+                    self.ref_locals.insert(
+                        id,
+                        Some(RefPat {
+                            always_deref: true,
+                            spans: vec![pat.span],
+                            app,
+                            replacements: vec![(pat.span, snip.into())],
+                        }),
+                    );
+                }
+            }
         }
-        if_chain! {
-            if let PatKind::Binding(BindingAnnotation::Ref, .., name, _) = pat.kind;
-            if let ty::Ref(_, tam, mutbl) = *cx.typeck_results().pat_ty(pat).kind();
-            if mutbl == Mutability::Not;
-            if let ty::Ref(_, _, mutbl) = *tam.kind();
-            // only lint immutable refs, because borrowed `&mut T` cannot be moved out
-            if mutbl == Mutability::Not;
-            then {
+    }
+
+    fn check_body_post(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) {
+        if Some(body.id()) == self.current_body {
+            for pat in self.ref_locals.drain(..).filter_map(|(_, x)| x) {
+                let replacements = pat.replacements;
+                let app = pat.app;
                 span_lint_and_then(
                     cx,
-                    NEEDLESS_BORROW,
-                    pat.span,
+                    if pat.always_deref {
+                        NEEDLESS_BORROW
+                    } else {
+                        REF_BINDING_TO_REFERENCE
+                    },
+                    pat.spans,
                     "this pattern creates a reference to a reference",
                     |diag| {
-                        if let Some(snippet) = snippet_opt(cx, name.span) {
-                            diag.span_suggestion(
-                                pat.span,
-                                "change this to",
-                                snippet,
-                                Applicability::MachineApplicable,
-                            );
-                        }
-                    }
-                )
+                        diag.multipart_suggestion("try this", replacements, app);
+                    },
+                );
             }
+            self.current_body = None;
         }
     }
-
-    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        let attrs = cx.tcx.hir().attrs(item.hir_id());
-        if is_automatically_derived(attrs) {
-            debug_assert!(self.derived_item.is_none());
-            self.derived_item = Some(item.def_id);
-        }
-    }
-
-    fn check_item_post(&mut self, _: &LateContext<'tcx>, item: &'tcx Item<'_>) {
-        if let Some(id) = self.derived_item {
-            if item.def_id == id {
-                self.derived_item = None;
+}
+impl NeedlessBorrow {
+    fn check_local_usage(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, local: HirId) {
+        if let Some(outer_pat) = self.ref_locals.get_mut(&local) {
+            if let Some(pat) = outer_pat {
+                // Check for auto-deref
+                if !matches!(
+                    cx.typeck_results().expr_adjustments(e),
+                    [
+                        Adjustment {
+                            kind: Adjust::Deref(_),
+                            ..
+                        },
+                        Adjustment {
+                            kind: Adjust::Deref(_),
+                            ..
+                        },
+                        ..
+                    ]
+                ) {
+                    match get_parent_expr(cx, e) {
+                        // Field accesses are the same no matter the number of references.
+                        Some(Expr {
+                            kind: ExprKind::Field(..),
+                            ..
+                        }) => (),
+                        Some(&Expr {
+                            span,
+                            kind: ExprKind::Unary(UnOp::Deref, _),
+                            ..
+                        }) if !in_macro(span) => {
+                            // Remove explicit deref.
+                            let snip = snippet_with_context(cx, e.span, span.ctxt(), "..", &mut pat.app).0;
+                            pat.replacements.push((span, snip.into()));
+                        },
+                        Some(parent) if !in_macro(parent.span) => {
+                            // Double reference might be needed at this point.
+                            if parent.precedence().order() == PREC_POSTFIX {
+                                // Parentheses would be needed here, don't lint.
+                                *outer_pat = None;
+                            } else {
+                                pat.always_deref = false;
+                                let snip = snippet_with_context(cx, e.span, parent.span.ctxt(), "..", &mut pat.app).0;
+                                pat.replacements.push((e.span, format!("&{}", snip)));
+                            }
+                        },
+                        _ if !in_macro(e.span) => {
+                            // Double reference might be needed at this point.
+                            pat.always_deref = false;
+                            let snip = snippet_with_applicability(cx, e.span, "..", &mut pat.app);
+                            pat.replacements.push((e.span, format!("&{}", snip)));
+                        },
+                        // Edge case for macros. The span of the identifier will usually match the context of the
+                        // binding, but not if the identifier was created in a macro. e.g. `concat_idents` and proc
+                        // macros
+                        _ => *outer_pat = None,
+                    }
+                }
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/needless_for_each.rs b/src/tools/clippy/clippy_lints/src/needless_for_each.rs
index 079b6642d58..a723a472a25 100644
--- a/src/tools/clippy/clippy_lints/src/needless_for_each.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_for_each.rs
@@ -142,10 +142,10 @@ impl<'tcx> Visitor<'tcx> for RetCollector {
         match expr.kind {
             ExprKind::Ret(..) => {
                 if self.loop_depth > 0 && !self.ret_in_loop {
-                    self.ret_in_loop = true
+                    self.ret_in_loop = true;
                 }
 
-                self.spans.push(expr.span)
+                self.spans.push(expr.span);
             },
 
             ExprKind::Loop(..) => {
diff --git a/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs
index 0704173a011..c824f6f54b5 100644
--- a/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs
+++ b/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs
@@ -84,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd {
                         types produces code that is hard to read and refactor, please \
                         consider using the `partial_cmp` method instead, to make it \
                         clear that the two values could be incomparable"
-                    )
+                    );
                 }
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/neg_multiply.rs b/src/tools/clippy/clippy_lints/src/neg_multiply.rs
index 34fd012572f..d5e1ea6d242 100644
--- a/src/tools/clippy/clippy_lints/src/neg_multiply.rs
+++ b/src/tools/clippy/clippy_lints/src/neg_multiply.rs
@@ -1,3 +1,4 @@
+use clippy_utils::consts::{self, Constant};
 use clippy_utils::diagnostics::span_lint;
 use if_chain::if_chain;
 use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
@@ -5,8 +6,6 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Span;
 
-use crate::consts::{self, Constant};
-
 declare_clippy_lint! {
     /// **What it does:** Checks for multiplication by -1 as a form of negation.
     ///
diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs
index cfcaf509471..b2206a82208 100644
--- a/src/tools/clippy/clippy_lints/src/no_effect.rs
+++ b/src/tools/clippy/clippy_lints/src/no_effect.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
+use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::has_drop;
 use rustc_errors::Applicability;
@@ -92,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect {
     fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
         if let StmtKind::Semi(expr) = stmt.kind {
             if has_no_effect(cx, expr) {
-                span_lint(cx, NO_EFFECT, stmt.span, "statement with no effect");
+                span_lint_hir(cx, NO_EFFECT, expr.hir_id, stmt.span, "statement with no effect");
             } else if let Some(reduced) = reduce_expression(cx, expr) {
                 let mut snippet = String::new();
                 for e in reduced {
@@ -106,14 +106,15 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect {
                         return;
                     }
                 }
-                span_lint_and_sugg(
+                span_lint_hir_and_then(
                     cx,
                     UNNECESSARY_OPERATION,
+                    expr.hir_id,
                     stmt.span,
                     "statement can be reduced",
-                    "replace it with",
-                    snippet,
-                    Applicability::MachineApplicable,
+                    |diag| {
+                        diag.span_suggestion(stmt.span, "replace it with", snippet, Applicability::MachineApplicable);
+                    },
                 );
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
index 4c8bceaf2cb..5292af5f076 100644
--- a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
+++ b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
@@ -126,6 +126,7 @@ const ALLOWED_TO_BE_SIMILAR: &[&[&str]] = &[
     &["args", "arms"],
     &["qpath", "path"],
     &["lit", "lint"],
+    &["wparam", "lparam"],
 ];
 
 struct SimilarNamesNameVisitor<'a, 'tcx, 'b>(&'b mut SimilarNamesLocalVisitor<'a, 'tcx>);
diff --git a/src/tools/clippy/clippy_lints/src/open_options.rs b/src/tools/clippy/clippy_lints/src/open_options.rs
index 9efe45336bf..fded48038e3 100644
--- a/src/tools/clippy/clippy_lints/src/open_options.rs
+++ b/src/tools/clippy/clippy_lints/src/open_options.rs
@@ -123,7 +123,7 @@ fn check_open_options(cx: &LateContext<'_>, options: &[(OpenOption, Argument)],
                         "the method `create` is called more than once",
                     );
                 } else {
-                    create = true
+                    create = true;
                 }
                 create_arg = create_arg || (arg == Argument::True);
             },
@@ -136,7 +136,7 @@ fn check_open_options(cx: &LateContext<'_>, options: &[(OpenOption, Argument)],
                         "the method `append` is called more than once",
                     );
                 } else {
-                    append = true
+                    append = true;
                 }
                 append_arg = append_arg || (arg == Argument::True);
             },
@@ -149,7 +149,7 @@ fn check_open_options(cx: &LateContext<'_>, options: &[(OpenOption, Argument)],
                         "the method `truncate` is called more than once",
                     );
                 } else {
-                    truncate = true
+                    truncate = true;
                 }
                 truncate_arg = truncate_arg || (arg == Argument::True);
             },
@@ -162,7 +162,7 @@ fn check_open_options(cx: &LateContext<'_>, options: &[(OpenOption, Argument)],
                         "the method `read` is called more than once",
                     );
                 } else {
-                    read = true
+                    read = true;
                 }
                 read_arg = read_arg || (arg == Argument::True);
             },
@@ -175,7 +175,7 @@ fn check_open_options(cx: &LateContext<'_>, options: &[(OpenOption, Argument)],
                         "the method `write` is called more than once",
                     );
                 } else {
-                    write = true
+                    write = true;
                 }
                 write_arg = write_arg || (arg == Argument::True);
             },
diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
index 6b64846c24d..f6a70478559 100644
--- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
+++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs
@@ -102,10 +102,16 @@ declare_clippy_lint! {
 pub struct PassByRefOrValue {
     ref_min_size: u64,
     value_max_size: u64,
+    avoid_breaking_exported_api: bool,
 }
 
 impl<'tcx> PassByRefOrValue {
-    pub fn new(ref_min_size: Option<u64>, value_max_size: u64, target: &Target) -> Self {
+    pub fn new(
+        ref_min_size: Option<u64>,
+        value_max_size: u64,
+        avoid_breaking_exported_api: bool,
+        target: &Target,
+    ) -> Self {
         let ref_min_size = ref_min_size.unwrap_or_else(|| {
             let bit_width = u64::from(target.pointer_width);
             // Cap the calculated bit width at 32-bits to reduce
@@ -120,10 +126,14 @@ impl<'tcx> PassByRefOrValue {
         Self {
             ref_min_size,
             value_max_size,
+            avoid_breaking_exported_api,
         }
     }
 
     fn check_poly_fn(&mut self, cx: &LateContext<'tcx>, hir_id: HirId, decl: &FnDecl<'_>, span: Option<Span>) {
+        if self.avoid_breaking_exported_api && cx.access_levels.is_exported(hir_id) {
+            return;
+        }
         let fn_def_id = cx.tcx.hir().local_def_id(hir_id);
 
         let fn_sig = cx.tcx.fn_sig(fn_def_id);
@@ -184,7 +194,6 @@ impl<'tcx> PassByRefOrValue {
                     }
 
                     if_chain! {
-                        if !cx.access_levels.is_exported(hir_id);
                         if is_copy(cx, ty);
                         if !is_self_ty(input);
                         if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes());
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index b0674f90678..12c44436874 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -211,7 +211,7 @@ fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
     ];
 
     if_chain! {
-        if let ExprKind::Call(ref fun, ref args) = expr.kind;
+        if let ExprKind::Call(fun, args) = expr.kind;
         if let ExprKind::Path(ref qpath) = fun.kind;
         if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
         let fun_def_path = cx.get_def_path(fun_def_id).into_iter().map(Symbol::to_ident_string).collect::<Vec<_>>();
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index 30bee213900..d66bac52243 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -88,7 +88,7 @@ impl QuestionMark {
                         "replace it with",
                         replacement_str,
                         applicability,
-                    )
+                    );
                 }
             }
         }
@@ -129,7 +129,7 @@ impl QuestionMark {
                     "replace it with",
                     replacement,
                     applicability,
-                )
+                );
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs
index 7169f96eaf1..ae5f0627fd6 100644
--- a/src/tools/clippy/clippy_lints/src/ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/ranges.rs
@@ -1,4 +1,4 @@
-use crate::consts::{constant, Constant};
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
 use clippy_utils::sugg::Sugg;
diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
index 92921bedf4d..8f56a21ac5b 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
@@ -57,7 +57,7 @@ impl<'ast> ast_visit::Visitor<'ast> for ReturnVisitor {
             self.found_return = true;
         }
 
-        ast_visit::walk_expr(self, ex)
+        ast_visit::walk_expr(self, ex);
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
index e091095de13..05f9e01acb4 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
@@ -59,7 +59,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
                                 Applicability::MachineApplicable,
                             );
                         },
-                    )
+                    );
                 }
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs
index 4b5306de58e..75151167454 100644
--- a/src/tools/clippy/clippy_lints/src/regex.rs
+++ b/src/tools/clippy/clippy_lints/src/regex.rs
@@ -1,4 +1,4 @@
-use crate::consts::{constant, Constant};
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
 use clippy_utils::{match_def_path, paths};
 use if_chain::if_chain;
diff --git a/src/tools/clippy/clippy_lints/src/repeat_once.rs b/src/tools/clippy/clippy_lints/src/repeat_once.rs
index 560a5e7c920..b479c40bca6 100644
--- a/src/tools/clippy/clippy_lints/src/repeat_once.rs
+++ b/src/tools/clippy/clippy_lints/src/repeat_once.rs
@@ -1,4 +1,4 @@
-use crate::consts::{constant_context, Constant};
+use clippy_utils::consts::{constant_context, Constant};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::in_macro;
 use clippy_utils::source::snippet;
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index b565c77aaec..251d527c265 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -139,7 +139,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
                 } else {
                     RetReplacement::Empty
                 };
-                check_final_expr(cx, &body.value, Some(body.value.span), replacement)
+                check_final_expr(cx, &body.value, Some(body.value.span), replacement);
             },
             FnKind::ItemFn(..) | FnKind::Method(..) => {
                 if let ExprKind::Block(block, _) = body.value.kind {
@@ -241,7 +241,7 @@ fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, inner_span: Option<Spa
                 if let Some(snippet) = snippet_opt(cx, inner_span) {
                     diag.span_suggestion(ret_span, "remove `return`", snippet, Applicability::MachineApplicable);
                 }
-            })
+            });
         },
         None => match replacement {
             RetReplacement::Empty => {
diff --git a/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs b/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs
index 553987a426b..16e4d73851f 100644
--- a/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs
+++ b/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs
@@ -8,11 +8,11 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
 declare_clippy_lint! {
-    /// **What it does:** Looks for blocks of expressions and fires if the last expression returns `()`
-    /// but is not followed by a semicolon.
+    /// **What it does:** Looks for blocks of expressions and fires if the last expression returns
+    /// `()` but is not followed by a semicolon.
     ///
-    /// **Why is this bad?** The semicolon might be optional but when
-    /// extending the block with new code, it doesn't require a change in previous last line.
+    /// **Why is this bad?** The semicolon might be optional but when extending the block with new
+    /// code, it doesn't require a change in previous last line.
     ///
     /// **Known problems:** None.
     ///
@@ -30,7 +30,7 @@ declare_clippy_lint! {
     /// }
     /// ```
     pub SEMICOLON_IF_NOTHING_RETURNED,
-    restriction,
+    pedantic,
     "add a semicolon if nothing is returned"
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs
index d6101bd5e36..ac3f7ebd14b 100644
--- a/src/tools/clippy/clippy_lints/src/shadow.rs
+++ b/src/tools/clippy/clippy_lints/src/shadow.rs
@@ -120,7 +120,7 @@ fn check_fn<'tcx>(cx: &LateContext<'tcx>, decl: &'tcx FnDecl<'_>, body: &'tcx Bo
     let mut bindings = Vec::with_capacity(decl.inputs.len());
     for arg in iter_input_pats(decl, body) {
         if let PatKind::Binding(.., ident, _) = arg.pat.kind {
-            bindings.push((ident.name, ident.span))
+            bindings.push((ident.name, ident.span));
         }
     }
     check_expr(cx, &body.value, &mut bindings);
@@ -156,7 +156,7 @@ fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: &
         ..
     } = *local;
     if let Some(t) = *ty {
-        check_ty(cx, t, bindings)
+        check_ty(cx, t, bindings);
     }
     if let Some(o) = *init {
         check_expr(cx, o, bindings);
@@ -324,14 +324,14 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut
     }
     match expr.kind {
         ExprKind::Unary(_, e) | ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) | ExprKind::Box(e) => {
-            check_expr(cx, e, bindings)
+            check_expr(cx, e, bindings);
         },
         ExprKind::Block(block, _) | ExprKind::Loop(block, ..) => check_block(cx, block, bindings),
         // ExprKind::Call
         // ExprKind::MethodCall
         ExprKind::Array(v) | ExprKind::Tup(v) => {
             for e in v {
-                check_expr(cx, e, bindings)
+                check_expr(cx, e, bindings);
             }
         },
         ExprKind::If(cond, then, ref otherwise) => {
@@ -374,7 +374,7 @@ fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<(
         TyKind::Ptr(MutTy { ty: mty, .. }) | TyKind::Rptr(_, MutTy { ty: mty, .. }) => check_ty(cx, mty, bindings),
         TyKind::Tup(tup) => {
             for t in tup {
-                check_ty(cx, t, bindings)
+                check_ty(cx, t, bindings);
             }
         },
         TyKind::Typeof(ref anon_const) => check_expr(cx, &cx.tcx.hir().body(anon_const.body).value, bindings),
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 a45bb102389..1eaad438237 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
@@ -70,7 +70,7 @@ fn check_mod(cx: &EarlyContext<'_>, items: &[P<Item>]) {
     for item in items {
         track_uses(
             cx,
-            &item,
+            item,
             &mut imports_reused_with_self,
             &mut single_use_usages,
             &mut macros,
@@ -117,7 +117,7 @@ fn track_uses(
 
     match &item.kind {
         ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) => {
-            check_mod(cx, &items);
+            check_mod(cx, items);
         },
         ItemKind::MacroDef(MacroDef { macro_rules: true, .. }) => {
             macros.push(item.ident.name);
diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
index a9ae2b77119..e5c58d70b60 100644
--- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
+++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
@@ -158,7 +158,7 @@ impl SlowVectorInit {
     ) {
         match initialization {
             InitializationType::Extend(e) | InitializationType::Resize(e) => {
-                Self::emit_lint(cx, e, vec_alloc, "slow zero-filling initialization")
+                Self::emit_lint(cx, e, vec_alloc, "slow zero-filling initialization");
             },
         };
     }
@@ -290,7 +290,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VectorInitializationVisitor<'a, 'tcx> {
     fn visit_block(&mut self, block: &'tcx Block<'_>) {
         if self.initialization_found {
             if let Some(s) = block.stmts.get(0) {
-                self.visit_stmt(s)
+                self.visit_stmt(s);
             }
 
             self.initialization_found = false;
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
index 4272935bc31..bb707f78fcc 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
@@ -59,7 +59,7 @@ declare_clippy_lint! {
     /// }
     /// ```
     pub SUSPICIOUS_OPERATION_GROUPINGS,
-    style,
+    nursery,
     "groupings of binary operations that look suspiciously like typos"
 }
 
@@ -266,7 +266,7 @@ fn emit_suggestion(cx: &EarlyContext<'_>, span: Span, sugg: String, applicabilit
         "did you mean",
         sugg,
         applicability,
-    )
+    );
 }
 
 fn ident_swap_sugg(
@@ -475,7 +475,7 @@ impl Add for IdentLocation {
 
 impl AddAssign for IdentLocation {
     fn add_assign(&mut self, other: Self) {
-        *self = *self + other
+        *self = *self + other;
     }
 }
 
@@ -506,7 +506,7 @@ impl Add for IdentDifference {
 
 impl AddAssign for IdentDifference {
     fn add_assign(&mut self, other: Self) {
-        *self = *self + other
+        *self = *self + other;
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
index b0589b0512e..74a94db1800 100644
--- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs
+++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
@@ -3,6 +3,7 @@ use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::{in_macro, SpanlessHash};
 use if_chain::if_chain;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::unhash::UnhashMap;
 use rustc_errors::Applicability;
 use rustc_hir::{def::Res, GenericBound, Generics, ParamName, Path, QPath, TyKind, WherePredicate};
 use rustc_lint::{LateContext, LateLintPass};
@@ -100,7 +101,7 @@ impl TraitBounds {
             hasher.hash_ty(ty);
             hasher.finish()
         };
-        let mut map = FxHashMap::default();
+        let mut map: UnhashMap<u64, Vec<&GenericBound<'_>>> = UnhashMap::default();
         let mut applicability = Applicability::MaybeIncorrect;
         for bound in gen.where_clause.predicates {
             if_chain! {
diff --git a/src/tools/clippy/clippy_lints/src/transmuting_null.rs b/src/tools/clippy/clippy_lints/src/transmuting_null.rs
index 888ecab1046..b57d158293d 100644
--- a/src/tools/clippy/clippy_lints/src/transmuting_null.rs
+++ b/src/tools/clippy/clippy_lints/src/transmuting_null.rs
@@ -1,4 +1,4 @@
-use crate::consts::{constant_context, Constant};
+use clippy_utils::consts::{constant_context, Constant};
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::{is_expr_path_def_path, paths};
 use if_chain::if_chain;
diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs
index d9b47a699dc..70b9e8adef8 100644
--- a/src/tools/clippy/clippy_lints/src/types/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/types/mod.rs
@@ -306,7 +306,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
     fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &TraitItem<'_>) {
         match item.kind {
             TraitItemKind::Const(ty, _) | TraitItemKind::Type(_, Some(ty)) => {
-                self.check_ty(cx, ty, CheckTyContext::default())
+                self.check_ty(cx, ty, CheckTyContext::default());
             },
             TraitItemKind::Fn(ref sig, _) => self.check_fn_decl(cx, sig.decl, CheckTyContext::default()),
             TraitItemKind::Type(..) => (),
@@ -433,7 +433,7 @@ impl Types {
             },
             TyKind::Slice(ty) | TyKind::Array(ty, _) | TyKind::Ptr(MutTy { ty, .. }) => {
                 context.is_nested_call = true;
-                self.check_ty(cx, ty, context)
+                self.check_ty(cx, ty, context);
             },
             TyKind::Tup(tys) => {
                 context.is_nested_call = true;
diff --git a/src/tools/clippy/clippy_lints/src/unicode.rs b/src/tools/clippy/clippy_lints/src/unicode.rs
index d81e31f5a21..45291a120ed 100644
--- a/src/tools/clippy/clippy_lints/src/unicode.rs
+++ b/src/tools/clippy/clippy_lints/src/unicode.rs
@@ -71,7 +71,7 @@ impl LateLintPass<'_> for Unicode {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ Expr<'_>) {
         if let ExprKind::Lit(ref lit) = expr.kind {
             if let LitKind::Str(_, _) = lit.node {
-                check_str(cx, lit.span, expr.hir_id)
+                check_str(cx, lit.span, expr.hir_id);
             }
         }
     }
@@ -82,7 +82,7 @@ fn escape<T: Iterator<Item = char>>(s: T) -> String {
     for c in s {
         if c as u32 > 0x7F {
             for d in c.escape_unicode() {
-                result.push(d)
+                result.push(d);
             }
         } else {
             result.push(c);
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
index f2f1410aed7..a85ffa6aa95 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
@@ -8,7 +8,7 @@ use rustc_hir::LangItem::{OptionSome, ResultOk};
 use rustc_hir::{Body, ExprKind, FnDecl, HirId, Impl, ItemKind, Node};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 
@@ -52,7 +52,19 @@ declare_clippy_lint! {
     "functions that only return `Ok` or `Some`"
 }
 
-declare_lint_pass!(UnnecessaryWraps => [UNNECESSARY_WRAPS]);
+pub struct UnnecessaryWraps {
+    avoid_breaking_exported_api: bool,
+}
+
+impl_lint_pass!(UnnecessaryWraps => [UNNECESSARY_WRAPS]);
+
+impl UnnecessaryWraps {
+    pub fn new(avoid_breaking_exported_api: bool) -> Self {
+        Self {
+            avoid_breaking_exported_api,
+        }
+    }
+}
 
 impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
     fn check_fn(
@@ -66,13 +78,12 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
     ) {
         // Abort if public function/method or closure.
         match fn_kind {
-            FnKind::ItemFn(.., visibility) | FnKind::Method(.., Some(visibility)) => {
-                if visibility.node.is_pub() {
+            FnKind::ItemFn(..) | FnKind::Method(..) => {
+                if self.avoid_breaking_exported_api && cx.access_levels.is_exported(hir_id) {
                     return;
                 }
             },
             FnKind::Closure => return,
-            FnKind::Method(..) => (),
         }
 
         // Abort if the method is implementing a trait or of it a trait method.
diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
index c27a6d4e347..ee082d30d93 100644
--- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
@@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount {
 
 fn check_map_error(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>) {
     let mut call = call;
-    while let hir::ExprKind::MethodCall(ref path, _, ref args, _) = call.kind {
+    while let hir::ExprKind::MethodCall(path, _, args, _) = call.kind {
         if matches!(&*path.ident.as_str(), "or" | "or_else" | "ok") {
             call = &args[0];
         } else {
diff --git a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
index 4ac2ec55b98..0b58c6c0917 100644
--- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
+++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
@@ -1,8 +1,8 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use itertools::Itertools;
-use rustc_ast::ast::{Item, ItemKind, VisibilityKind};
 use rustc_errors::Applicability;
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_hir::{Item, ItemKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::Ident;
@@ -38,12 +38,14 @@ declare_clippy_lint! {
 
 #[derive(Default)]
 pub struct UpperCaseAcronyms {
+    avoid_breaking_exported_api: bool,
     upper_case_acronyms_aggressive: bool,
 }
 
 impl UpperCaseAcronyms {
-    pub fn new(aggressive: bool) -> Self {
+    pub fn new(avoid_breaking_exported_api: bool, aggressive: bool) -> Self {
         Self {
+            avoid_breaking_exported_api,
             upper_case_acronyms_aggressive: aggressive,
         }
     }
@@ -72,7 +74,7 @@ fn correct_ident(ident: &str) -> String {
     ident
 }
 
-fn check_ident(cx: &EarlyContext<'_>, ident: &Ident, be_aggressive: bool) {
+fn check_ident(cx: &LateContext<'_>, ident: &Ident, be_aggressive: bool) {
     let span = ident.span;
     let ident = &ident.as_str();
     let corrected = correct_ident(ident);
@@ -92,27 +94,31 @@ fn check_ident(cx: &EarlyContext<'_>, ident: &Ident, be_aggressive: bool) {
             "consider making the acronym lowercase, except the initial letter",
             corrected,
             Applicability::MaybeIncorrect,
-        )
+        );
     }
 }
 
-impl EarlyLintPass for UpperCaseAcronyms {
-    fn check_item(&mut self, cx: &EarlyContext<'_>, it: &Item) {
+impl LateLintPass<'_> for UpperCaseAcronyms {
+    fn check_item(&mut self, cx: &LateContext<'_>, it: &Item<'_>) {
         // do not lint public items or in macros
-        if !in_external_macro(cx.sess(), it.span) && !matches!(it.vis.kind, VisibilityKind::Public) {
-            if matches!(
-                it.kind,
-                ItemKind::TyAlias(..) | ItemKind::Struct(..) | ItemKind::Trait(..)
-            ) {
+        if in_external_macro(cx.sess(), it.span)
+            || (self.avoid_breaking_exported_api && cx.access_levels.is_exported(it.hir_id()))
+        {
+            return;
+        }
+        match it.kind {
+            ItemKind::TyAlias(..) | ItemKind::Struct(..) | ItemKind::Trait(..) => {
                 check_ident(cx, &it.ident, self.upper_case_acronyms_aggressive);
-            } else if let ItemKind::Enum(ref enumdef, _) = it.kind {
+            },
+            ItemKind::Enum(ref enumdef, _) => {
                 // check enum variants seperately because again we only want to lint on private enums and
                 // the fn check_variant does not know about the vis of the enum of its variants
                 enumdef
                     .variants
                     .iter()
                     .for_each(|variant| check_ident(cx, &variant.ident, self.upper_case_acronyms_aggressive));
-            }
+            },
+            _ => {},
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs
index 2ad6fa77f48..254b104bdef 100644
--- a/src/tools/clippy/clippy_lints/src/use_self.rs
+++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -356,7 +356,7 @@ impl<'tcx> Visitor<'tcx> for SkipTyCollector {
     fn visit_ty(&mut self, hir_ty: &hir::Ty<'_>) {
         self.types_to_skip.push(hir_ty.hir_id);
 
-        walk_ty(self, hir_ty)
+        walk_ty(self, hir_ty);
     }
 
     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
@@ -385,7 +385,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LintTyCollector<'a, 'tcx> {
             }
         }
 
-        walk_ty(self, hir_ty)
+        walk_ty(self, hir_ty);
     }
 
     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index e70f8a09ebe..39ef170ae36 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -292,7 +292,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
                     LitKind::Str(ref text, _) => {
                         let str_pat = self.next("s");
                         println!("    if let LitKind::Str(ref {}, _) = {}.node;", str_pat, lit_pat);
-                        println!("    if {}.as_str() == {:?}", str_pat, &*text.as_str())
+                        println!("    if {}.as_str() == {:?}", str_pat, &*text.as_str());
                     },
                 }
             },
diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs
index fd2dddb3b96..0e33ae740d9 100644
--- a/src/tools/clippy/clippy_lints/src/utils/conf.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs
@@ -122,7 +122,9 @@ macro_rules! define_Conf {
 
 // N.B., this macro is parsed by util/lintlib.py
 define_Conf! {
-    /// Lint: CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE. The minimum rust version that the project supports
+    /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION. Suppress lints whenever the suggested change would cause breakage for other crates.
+    (avoid_breaking_exported_api: bool = true),
+    /// Lint: MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE. The minimum rust version that the project supports
     (msrv: Option<String> = None),
     /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about. NB: `bar` is not here since it has legitimate uses
     (blacklisted_names: Vec<String> = ["foo", "baz", "quux"].iter().map(ToString::to_string).collect()),
@@ -208,15 +210,13 @@ pub fn lookup_conf_file() -> io::Result<Option<PathBuf>> {
         .map_or_else(|| PathBuf::from("."), PathBuf::from);
     loop {
         for config_file_name in &CONFIG_FILE_NAMES {
-            let config_file = current.join(config_file_name);
-            match fs::metadata(&config_file) {
-                // Only return if it's a file to handle the unlikely situation of a directory named
-                // `clippy.toml`.
-                Ok(ref md) if !md.is_dir() => return Ok(Some(config_file)),
-                // Return the error if it's something other than `NotFound`; otherwise we didn't
-                // find the project file yet, and continue searching.
-                Err(e) if e.kind() != io::ErrorKind::NotFound => return Err(e),
-                _ => {},
+            if let Ok(config_file) = current.join(config_file_name).canonicalize() {
+                match fs::metadata(&config_file) {
+                    Err(e) if e.kind() == io::ErrorKind::NotFound => {},
+                    Err(e) => return Err(e),
+                    Ok(md) if md.is_dir() => {},
+                    Ok(_) => return Ok(Some(config_file)),
+                }
             }
         }
 
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
index ee7be24eae8..b1523e032af 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
@@ -1,4 +1,4 @@
-use crate::consts::{constant_simple, Constant};
+use clippy_utils::consts::{constant_simple, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::snippet;
 use clippy_utils::ty::match_type;
@@ -1100,7 +1100,7 @@ impl<'tcx> LateLintPass<'tcx> for IfChainStyle {
                 IF_CHAIN_STYLE,
                 if_chain_local_span(cx, local, if_chain_span),
                 "`let` expression should be inside `then { .. }`",
-            )
+            );
         }
     }
 
@@ -1141,7 +1141,7 @@ impl<'tcx> LateLintPass<'tcx> for IfChainStyle {
         if is_first_if_chain_expr(cx, expr.hir_id, if_chain_span)
             && is_if_chain_then(then_block.stmts, then_block.expr, if_chain_span)
         {
-            span_lint(cx, IF_CHAIN_STYLE, expr.span, "`if_chain!` only has one `if`")
+            span_lint(cx, IF_CHAIN_STYLE, expr.span, "`if_chain!` only has one `if`");
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
index e9fa043b20f..46af03663b8 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
@@ -379,7 +379,7 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector {
     /// }
     /// ```
     fn check_item(&mut self, cx: &LateContext<'hir>, item: &'hir Item<'_>) {
-        if let ItemKind::Static(ref ty, Mutability::Not, _) = item.kind {
+        if let ItemKind::Static(ty, Mutability::Not, _) = item.kind {
             // Normal lint
             if_chain! {
                 // item validation
@@ -489,7 +489,7 @@ fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> {
         .hir()
         .attrs(item.hir_id())
         .iter()
-        .filter_map(|ref x| x.doc_str().map(|sym| sym.as_str().to_string()))
+        .filter_map(|x| x.doc_str().map(|sym| sym.as_str().to_string()))
         .reduce(|mut acc, sym| {
             acc.push_str(&sym);
             acc.push('\n');
@@ -596,7 +596,7 @@ fn extract_emission_info<'hir>(
     let mut multi_part = false;
 
     for arg in args {
-        let (arg_ty, _) = walk_ptrs_ty_depth(cx.typeck_results().expr_ty(&arg));
+        let (arg_ty, _) = walk_ptrs_ty_depth(cx.typeck_results().expr_ty(arg));
 
         if match_type(cx, arg_ty, &paths::LINT) {
             // If we found the lint arg, extract the lint name
@@ -671,7 +671,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for LintResolver<'a, 'hir> {
             if let ExprKind::Path(qpath) = &expr.kind;
             if let QPath::Resolved(_, path) = qpath;
 
-            let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(&expr));
+            let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr));
             if match_type(self.cx, expr_ty, &paths::LINT);
             then {
                 if let hir::def::Res::Def(DefKind::Static, _) = path.res {
@@ -730,7 +730,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for ApplicabilityResolver<'a, 'hir> {
     }
 
     fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
-        let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(&expr));
+        let (expr_ty, _) = walk_ptrs_ty_depth(self.cx.typeck_results().expr_ty(expr));
 
         if_chain! {
             if match_type(self.cx, expr_ty, &paths::APPLICABILITY);
@@ -818,7 +818,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for IsMultiSpanScanner<'a, 'hir> {
                     .any(|func_path| match_function_call(self.cx, fn_expr, func_path).is_some());
                 if found_function {
                     // These functions are all multi part suggestions
-                    self.add_single_span_suggestion()
+                    self.add_single_span_suggestion();
                 }
             },
             ExprKind::MethodCall(path, _path_span, arg, _arg_span) => {
diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs
index febd4b6ff7b..1d5b7c98d31 100644
--- a/src/tools/clippy/clippy_lints/src/vec.rs
+++ b/src/tools/clippy/clippy_lints/src/vec.rs
@@ -1,5 +1,5 @@
-use crate::consts::{constant, Constant};
 use crate::rustc_target::abi::LayoutOf;
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::higher;
 use clippy_utils::source::snippet_with_applicability;
diff --git a/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs b/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs
index ec209b30951..3ab68df2b6d 100644
--- a/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs
+++ b/src/tools/clippy/clippy_lints/src/verbose_file_reads.rs
@@ -54,7 +54,7 @@ impl<'tcx> LateLintPass<'tcx> for VerboseFileReads {
                 "use of `File::read_to_string`",
                 None,
                 "consider using `fs::read_to_string` instead",
-            )
+            );
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs
index d0e79efa70d..5229a705865 100644
--- a/src/tools/clippy/clippy_lints/src/write.rs
+++ b/src/tools/clippy/clippy_lints/src/write.rs
@@ -300,7 +300,7 @@ impl EarlyLintPass for Write {
                                 Applicability::MachineApplicable,
                             );
                         },
-                    )
+                    );
                 }
             }
         } else if mac.path == sym!(writeln) {
diff --git a/src/tools/clippy/clippy_lints/src/zero_div_zero.rs b/src/tools/clippy/clippy_lints/src/zero_div_zero.rs
index 350b1cf25ff..a1ea743ba80 100644
--- a/src/tools/clippy/clippy_lints/src/zero_div_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/zero_div_zero.rs
@@ -1,4 +1,4 @@
-use crate::consts::{constant_simple, Constant};
+use clippy_utils::consts::{constant_simple, Constant};
 use clippy_utils::diagnostics::span_lint_and_help;
 use if_chain::if_chain;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs
index c0584e1e226..0318c483959 100644
--- a/src/tools/clippy/clippy_utils/src/attrs.rs
+++ b/src/tools/clippy/clippy_utils/src/attrs.rs
@@ -115,7 +115,7 @@ fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &'
     for attr in get_attr(sess, attrs, name) {
         if let Some(ref value) = attr.value_str() {
             if let Ok(value) = FromStr::from_str(&value.as_str()) {
-                f(value)
+                f(value);
             } else {
                 sess.span_err(attr.span, "not a number");
             }
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 2a305d8bcbe..0d7fdeeb920 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -229,25 +229,25 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
     pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant> {
         match e.kind {
             ExprKind::Path(ref qpath) => self.fetch_path(qpath, e.hir_id, self.typeck_results.expr_ty(e)),
-            ExprKind::Block(ref block, _) => self.block(block),
+            ExprKind::Block(block, _) => self.block(block),
             ExprKind::Lit(ref lit) => Some(lit_to_constant(&lit.node, self.typeck_results.expr_ty_opt(e))),
-            ExprKind::Array(ref vec) => self.multi(vec).map(Constant::Vec),
-            ExprKind::Tup(ref tup) => self.multi(tup).map(Constant::Tuple),
-            ExprKind::Repeat(ref value, _) => {
+            ExprKind::Array(vec) => self.multi(vec).map(Constant::Vec),
+            ExprKind::Tup(tup) => self.multi(tup).map(Constant::Tuple),
+            ExprKind::Repeat(value, _) => {
                 let n = match self.typeck_results.expr_ty(e).kind() {
                     ty::Array(_, n) => n.try_eval_usize(self.lcx.tcx, self.lcx.param_env)?,
                     _ => span_bug!(e.span, "typeck error"),
                 };
                 self.expr(value).map(|v| Constant::Repeat(Box::new(v), n))
             },
-            ExprKind::Unary(op, ref operand) => self.expr(operand).and_then(|o| match op {
+            ExprKind::Unary(op, operand) => self.expr(operand).and_then(|o| match op {
                 UnOp::Not => self.constant_not(&o, self.typeck_results.expr_ty(e)),
                 UnOp::Neg => self.constant_negate(&o, self.typeck_results.expr_ty(e)),
                 UnOp::Deref => Some(if let Constant::Ref(r) = o { *r } else { o }),
             }),
-            ExprKind::If(ref cond, ref then, ref otherwise) => self.ifthenelse(cond, then, *otherwise),
-            ExprKind::Binary(op, ref left, ref right) => self.binop(op, left, right),
-            ExprKind::Call(ref callee, ref args) => {
+            ExprKind::If(cond, then, ref otherwise) => self.ifthenelse(cond, then, *otherwise),
+            ExprKind::Binary(op, left, right) => self.binop(op, left, right),
+            ExprKind::Call(callee, args) => {
                 // We only handle a few const functions for now.
                 if_chain! {
                     if args.is_empty();
@@ -273,8 +273,8 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
                     }
                 }
             },
-            ExprKind::Index(ref arr, ref index) => self.index(arr, index),
-            ExprKind::AddrOf(_, _, ref inner) => self.expr(inner).map(|r| Constant::Ref(Box::new(r))),
+            ExprKind::Index(arr, index) => self.index(arr, index),
+            ExprKind::AddrOf(_, _, inner) => self.expr(inner).map(|r| Constant::Ref(Box::new(r))),
             // TODO: add other expressions.
             _ => None,
         }
@@ -349,7 +349,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
                     )
                     .ok()
                     .map(|val| rustc_middle::ty::Const::from_value(self.lcx.tcx, val, ty))?;
-                let result = miri_to_const(&result);
+                let result = miri_to_const(result);
                 if result.is_some() {
                     self.needed_resolution = true;
                 }
diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs
index a4efae54894..7c94474cb35 100644
--- a/src/tools/clippy/clippy_utils/src/diagnostics.rs
+++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs
@@ -167,7 +167,7 @@ pub fn span_lint_hir_and_then(
     cx: &LateContext<'_>,
     lint: &'static Lint,
     hir_id: HirId,
-    sp: Span,
+    sp: impl Into<MultiSpan>,
     msg: &str,
     f: impl FnOnce(&mut DiagnosticBuilder<'_>),
 ) {
@@ -223,7 +223,7 @@ pub fn multispan_sugg<I>(diag: &mut DiagnosticBuilder<'_>, help_msg: &str, sugg:
 where
     I: IntoIterator<Item = (Span, String)>,
 {
-    multispan_sugg_with_applicability(diag, help_msg, Applicability::Unspecified, sugg)
+    multispan_sugg_with_applicability(diag, help_msg, Applicability::Unspecified, sugg);
 }
 
 /// Create a suggestion made from several `span → replacement`.
diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs
index 0c0e4d3b4ce..8be36756b33 100644
--- a/src/tools/clippy/clippy_utils/src/higher.rs
+++ b/src/tools/clippy/clippy_utils/src/higher.rs
@@ -58,7 +58,7 @@ pub fn range<'a>(expr: &'a hir::Expr<'_>) -> Option<Range<'a>> {
     }
 
     match expr.kind {
-        hir::ExprKind::Call(ref path, ref args)
+        hir::ExprKind::Call(path, args)
             if matches!(
                 path.kind,
                 hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, _))
@@ -70,7 +70,7 @@ pub fn range<'a>(expr: &'a hir::Expr<'_>) -> Option<Range<'a>> {
                 limits: ast::RangeLimits::Closed,
             })
         },
-        hir::ExprKind::Struct(ref path, ref fields, None) => match path {
+        hir::ExprKind::Struct(path, fields, None) => match path {
             hir::QPath::LangItem(hir::LangItem::RangeFull, _) => Some(Range {
                 start: None,
                 end: None,
@@ -112,7 +112,7 @@ pub fn is_from_for_desugar(local: &hir::Local<'_>) -> bool {
     // }
     // ```
     if_chain! {
-        if let Some(ref expr) = local.init;
+        if let Some(expr) = local.init;
         if let hir::ExprKind::Match(_, _, hir::MatchSource::ForLoopDesugar) = expr.kind;
         then {
             return true;
@@ -140,14 +140,14 @@ pub fn for_loop<'tcx>(
     expr: &'tcx hir::Expr<'tcx>,
 ) -> Option<(&hir::Pat<'_>, &'tcx hir::Expr<'tcx>, &'tcx hir::Expr<'tcx>, Span)> {
     if_chain! {
-        if let hir::ExprKind::Match(ref iterexpr, ref arms, hir::MatchSource::ForLoopDesugar) = expr.kind;
-        if let hir::ExprKind::Call(_, ref iterargs) = iterexpr.kind;
+        if let hir::ExprKind::Match(iterexpr, arms, hir::MatchSource::ForLoopDesugar) = expr.kind;
+        if let hir::ExprKind::Call(_, iterargs) = iterexpr.kind;
         if iterargs.len() == 1 && arms.len() == 1 && arms[0].guard.is_none();
-        if let hir::ExprKind::Loop(ref block, ..) = arms[0].body.kind;
+        if let hir::ExprKind::Loop(block, ..) = arms[0].body.kind;
         if block.expr.is_none();
         if let [ _, _, ref let_stmt, ref body ] = *block.stmts;
-        if let hir::StmtKind::Local(ref local) = let_stmt.kind;
-        if let hir::StmtKind::Expr(ref expr) = body.kind;
+        if let hir::StmtKind::Local(local) = let_stmt.kind;
+        if let hir::StmtKind::Expr(expr) = body.kind;
         then {
             return Some((&*local.pat, &iterargs[0], expr, arms[0].span));
         }
@@ -182,7 +182,7 @@ pub enum VecArgs<'a> {
 /// from `vec!`.
 pub fn vec_macro<'e>(cx: &LateContext<'_>, expr: &'e hir::Expr<'_>) -> Option<VecArgs<'e>> {
     if_chain! {
-        if let hir::ExprKind::Call(ref fun, ref args) = expr.kind;
+        if let hir::ExprKind::Call(fun, args) = expr.kind;
         if let hir::ExprKind::Path(ref qpath) = fun.kind;
         if is_expn_of(fun.span, "vec").is_some();
         if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
@@ -194,8 +194,8 @@ pub fn vec_macro<'e>(cx: &LateContext<'_>, expr: &'e hir::Expr<'_>) -> Option<Ve
             else if match_def_path(cx, fun_def_id, &paths::SLICE_INTO_VEC) && args.len() == 1 {
                 // `vec![a, b, c]` case
                 if_chain! {
-                    if let hir::ExprKind::Box(ref boxed) = args[0].kind;
-                    if let hir::ExprKind::Array(ref args) = boxed.kind;
+                    if let hir::ExprKind::Box(boxed) = args[0].kind;
+                    if let hir::ExprKind::Array(args) = boxed.kind;
                     then {
                         return Some(VecArgs::Vec(&*args));
                     }
@@ -227,7 +227,7 @@ pub fn extract_assert_macro_args<'tcx>(e: &'tcx Expr<'tcx>) -> Option<Vec<&'tcx
     /// compared
     fn ast_matchblock(matchblock_expr: &'tcx Expr<'tcx>) -> Option<Vec<&Expr<'_>>> {
         if_chain! {
-            if let ExprKind::Match(ref headerexpr, _, _) = &matchblock_expr.kind;
+            if let ExprKind::Match(headerexpr, _, _) = &matchblock_expr.kind;
             if let ExprKind::Tup([lhs, rhs]) = &headerexpr.kind;
             if let ExprKind::AddrOf(BorrowKind::Ref, _, lhs) = lhs.kind;
             if let ExprKind::AddrOf(BorrowKind::Ref, _, rhs) = rhs.kind;
@@ -238,12 +238,12 @@ pub fn extract_assert_macro_args<'tcx>(e: &'tcx Expr<'tcx>) -> Option<Vec<&'tcx
         None
     }
 
-    if let ExprKind::Block(ref block, _) = e.kind {
+    if let ExprKind::Block(block, _) = e.kind {
         if block.stmts.len() == 1 {
-            if let StmtKind::Semi(ref matchexpr) = block.stmts.get(0)?.kind {
+            if let StmtKind::Semi(matchexpr) = block.stmts.get(0)?.kind {
                 // macros with unique arg: `{debug_}assert!` (e.g., `debug_assert!(some_condition)`)
                 if_chain! {
-                    if let ExprKind::If(ref clause, _, _)  = matchexpr.kind;
+                    if let ExprKind::If(clause, _, _)  = matchexpr.kind;
                     if let ExprKind::Unary(UnOp::Not, condition) = clause.kind;
                     then {
                         return Some(vec![condition]);
@@ -252,8 +252,8 @@ pub fn extract_assert_macro_args<'tcx>(e: &'tcx Expr<'tcx>) -> Option<Vec<&'tcx
 
                 // debug macros with two args: `debug_assert_{ne, eq}` (e.g., `assert_ne!(a, b)`)
                 if_chain! {
-                    if let ExprKind::Block(ref matchblock,_) = matchexpr.kind;
-                    if let Some(ref matchblock_expr) = matchblock.expr;
+                    if let ExprKind::Block(matchblock,_) = matchexpr.kind;
+                    if let Some(matchblock_expr) = matchblock.expr;
                     then {
                         return ast_matchblock(matchblock_expr);
                     }
@@ -261,7 +261,7 @@ pub fn extract_assert_macro_args<'tcx>(e: &'tcx Expr<'tcx>) -> Option<Vec<&'tcx
             }
         } else if let Some(matchblock_expr) = block.expr {
             // macros with two args: `assert_{ne, eq}` (e.g., `assert_ne!(a, b)`)
-            return ast_matchblock(&matchblock_expr);
+            return ast_matchblock(matchblock_expr);
         }
     }
     None
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 3b01158acd9..a21ad42c061 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -2,20 +2,19 @@ use crate::consts::{constant_context, constant_simple};
 use crate::differing_macro_contexts;
 use crate::source::snippet_opt;
 use rustc_ast::ast::InlineAsmTemplatePiece;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::fx::FxHasher;
 use rustc_hir::def::Res;
 use rustc_hir::HirIdMap;
 use rustc_hir::{
-    BinOpKind, Block, BlockCheckMode, BodyId, BorrowKind, CaptureBy, Expr, ExprField, ExprKind, FnRetTy, GenericArg,
-    GenericArgs, Guard, HirId, InlineAsmOperand, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path,
-    PathSegment, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding,
+    BinOpKind, Block, BodyId, Expr, ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, Guard, HirId,
+    InlineAsmOperand, Lifetime, LifetimeName, ParamName, Pat, PatField, PatKind, Path, PathSegment, QPath, Stmt,
+    StmtKind, Ty, TyKind, TypeBinding,
 };
 use rustc_lexer::{tokenize, TokenKind};
 use rustc_lint::LateContext;
-use rustc_middle::ich::StableHashingContextProvider;
 use rustc_middle::ty::TypeckResults;
 use rustc_span::Symbol;
-use std::hash::Hash;
+use std::hash::{Hash, Hasher};
 
 /// Type used to check whether two ast are the same. This is different from the
 /// operator
@@ -95,12 +94,12 @@ pub struct HirEqInterExpr<'a, 'b, 'tcx> {
 impl HirEqInterExpr<'_, '_, '_> {
     pub fn eq_stmt(&mut self, left: &Stmt<'_>, right: &Stmt<'_>) -> bool {
         match (&left.kind, &right.kind) {
-            (&StmtKind::Local(ref l), &StmtKind::Local(ref r)) => {
+            (&StmtKind::Local(l), &StmtKind::Local(r)) => {
                 // This additional check ensures that the type of the locals are equivalent even if the init
                 // expression or type have some inferred parts.
                 if let Some(typeck) = self.inner.maybe_typeck_results {
-                    let l_ty = typeck.pat_ty(&l.pat);
-                    let r_ty = typeck.pat_ty(&r.pat);
+                    let l_ty = typeck.pat_ty(l.pat);
+                    let r_ty = typeck.pat_ty(r.pat);
                     if !rustc_middle::ty::TyS::same_type(l_ty, r_ty) {
                         return false;
                     }
@@ -110,11 +109,9 @@ impl HirEqInterExpr<'_, '_, '_> {
                 // these only get added if the init and type is equal.
                 both(&l.init, &r.init, |l, r| self.eq_expr(l, r))
                     && both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r))
-                    && self.eq_pat(&l.pat, &r.pat)
-            },
-            (&StmtKind::Expr(ref l), &StmtKind::Expr(ref r)) | (&StmtKind::Semi(ref l), &StmtKind::Semi(ref r)) => {
-                self.eq_expr(l, r)
+                    && self.eq_pat(l.pat, r.pat)
             },
+            (&StmtKind::Expr(l), &StmtKind::Expr(r)) | (&StmtKind::Semi(l), &StmtKind::Semi(r)) => self.eq_expr(l, r),
             _ => false,
         }
     }
@@ -165,12 +162,18 @@ impl HirEqInterExpr<'_, '_, '_> {
                 left.eq(right)
             },
             _ => {
-                over(&left.stmts, &right.stmts, |l, r| self.eq_stmt(l, r))
+                over(left.stmts, right.stmts, |l, r| self.eq_stmt(l, r))
                     && both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r))
             },
         }
     }
 
+    pub fn eq_body(&mut self, left: BodyId, right: BodyId) -> bool {
+        let cx = self.inner.cx;
+        let eval_const = |body| constant_context(cx, cx.tcx.typeck_body(body)).expr(&cx.tcx.hir().body(body).value);
+        eval_const(left) == eval_const(right)
+    }
+
     #[allow(clippy::similar_names)]
     pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool {
         if !self.inner.allow_side_effects && differing_macro_contexts(left.span, right.span) {
@@ -192,20 +195,20 @@ impl HirEqInterExpr<'_, '_, '_> {
             &reduce_exprkind(self.inner.cx, &left.kind),
             &reduce_exprkind(self.inner.cx, &right.kind),
         ) {
-            (&ExprKind::AddrOf(lb, l_mut, ref le), &ExprKind::AddrOf(rb, r_mut, ref re)) => {
+            (&ExprKind::AddrOf(lb, l_mut, le), &ExprKind::AddrOf(rb, r_mut, re)) => {
                 lb == rb && l_mut == r_mut && self.eq_expr(le, re)
             },
             (&ExprKind::Continue(li), &ExprKind::Continue(ri)) => {
                 both(&li.label, &ri.label, |l, r| l.ident.name == r.ident.name)
             },
-            (&ExprKind::Assign(ref ll, ref lr, _), &ExprKind::Assign(ref rl, ref rr, _)) => {
+            (&ExprKind::Assign(ll, lr, _), &ExprKind::Assign(rl, rr, _)) => {
                 self.inner.allow_side_effects && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
             },
-            (&ExprKind::AssignOp(ref lo, ref ll, ref lr), &ExprKind::AssignOp(ref ro, ref rl, ref rr)) => {
+            (&ExprKind::AssignOp(ref lo, ll, lr), &ExprKind::AssignOp(ref ro, rl, rr)) => {
                 self.inner.allow_side_effects && lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
             },
-            (&ExprKind::Block(ref l, _), &ExprKind::Block(ref r, _)) => self.eq_block(l, r),
-            (&ExprKind::Binary(l_op, ref ll, ref lr), &ExprKind::Binary(r_op, ref rl, ref rr)) => {
+            (&ExprKind::Block(l, _), &ExprKind::Block(r, _)) => self.eq_block(l, r),
+            (&ExprKind::Binary(l_op, ll, lr), &ExprKind::Binary(r_op, rl, rr)) => {
                 l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
                     || swap_binop(l_op.node, ll, lr).map_or(false, |(l_op, ll, lr)| {
                         l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
@@ -215,58 +218,50 @@ impl HirEqInterExpr<'_, '_, '_> {
                 both(&li.label, &ri.label, |l, r| l.ident.name == r.ident.name)
                     && both(le, re, |l, r| self.eq_expr(l, r))
             },
-            (&ExprKind::Box(ref l), &ExprKind::Box(ref r)) => self.eq_expr(l, r),
+            (&ExprKind::Box(l), &ExprKind::Box(r)) => self.eq_expr(l, r),
             (&ExprKind::Call(l_fun, l_args), &ExprKind::Call(r_fun, r_args)) => {
                 self.inner.allow_side_effects && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args)
             },
-            (&ExprKind::Cast(ref lx, ref lt), &ExprKind::Cast(ref rx, ref rt))
-            | (&ExprKind::Type(ref lx, ref lt), &ExprKind::Type(ref rx, ref rt)) => {
+            (&ExprKind::Cast(lx, lt), &ExprKind::Cast(rx, rt)) | (&ExprKind::Type(lx, lt), &ExprKind::Type(rx, rt)) => {
                 self.eq_expr(lx, rx) && self.eq_ty(lt, rt)
             },
-            (&ExprKind::Field(ref l_f_exp, ref l_f_ident), &ExprKind::Field(ref r_f_exp, ref r_f_ident)) => {
+            (&ExprKind::Field(l_f_exp, ref l_f_ident), &ExprKind::Field(r_f_exp, ref r_f_ident)) => {
                 l_f_ident.name == r_f_ident.name && self.eq_expr(l_f_exp, r_f_exp)
             },
-            (&ExprKind::Index(ref la, ref li), &ExprKind::Index(ref ra, ref ri)) => {
-                self.eq_expr(la, ra) && self.eq_expr(li, ri)
-            },
-            (&ExprKind::If(ref lc, ref lt, ref le), &ExprKind::If(ref rc, ref rt, ref re)) => {
+            (&ExprKind::Index(la, li), &ExprKind::Index(ra, ri)) => self.eq_expr(la, ra) && self.eq_expr(li, ri),
+            (&ExprKind::If(lc, lt, ref le), &ExprKind::If(rc, rt, ref re)) => {
                 self.eq_expr(lc, rc) && self.eq_expr(&**lt, &**rt) && both(le, re, |l, r| self.eq_expr(l, r))
             },
             (&ExprKind::Lit(ref l), &ExprKind::Lit(ref r)) => l.node == r.node,
-            (&ExprKind::Loop(ref lb, ref ll, ref lls, _), &ExprKind::Loop(ref rb, ref rl, ref rls, _)) => {
+            (&ExprKind::Loop(lb, ref ll, ref lls, _), &ExprKind::Loop(rb, ref rl, ref rls, _)) => {
                 lls == rls && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.ident.name == r.ident.name)
             },
-            (&ExprKind::Match(ref le, ref la, ref ls), &ExprKind::Match(ref re, ref ra, ref rs)) => {
+            (&ExprKind::Match(le, la, ref ls), &ExprKind::Match(re, ra, ref rs)) => {
                 ls == rs
                     && self.eq_expr(le, re)
                     && over(la, ra, |l, r| {
-                        self.eq_pat(&l.pat, &r.pat)
+                        self.eq_pat(l.pat, r.pat)
                             && both(&l.guard, &r.guard, |l, r| self.eq_guard(l, r))
-                            && self.eq_expr(&l.body, &r.body)
+                            && self.eq_expr(l.body, r.body)
                     })
             },
             (&ExprKind::MethodCall(l_path, _, l_args, _), &ExprKind::MethodCall(r_path, _, r_args, _)) => {
                 self.inner.allow_side_effects && self.eq_path_segment(l_path, r_path) && self.eq_exprs(l_args, r_args)
             },
-            (&ExprKind::Repeat(ref le, ref ll_id), &ExprKind::Repeat(ref re, ref rl_id)) => {
-                let mut celcx = constant_context(self.inner.cx, self.inner.cx.tcx.typeck_body(ll_id.body));
-                let ll = celcx.expr(&self.inner.cx.tcx.hir().body(ll_id.body).value);
-                let mut celcx = constant_context(self.inner.cx, self.inner.cx.tcx.typeck_body(rl_id.body));
-                let rl = celcx.expr(&self.inner.cx.tcx.hir().body(rl_id.body).value);
-
-                self.eq_expr(le, re) && ll == rl
+            (&ExprKind::Repeat(le, ref ll_id), &ExprKind::Repeat(re, ref rl_id)) => {
+                self.eq_expr(le, re) && self.eq_body(ll_id.body, rl_id.body)
             },
             (&ExprKind::Ret(ref l), &ExprKind::Ret(ref r)) => both(l, r, |l, r| self.eq_expr(l, r)),
             (&ExprKind::Path(ref l), &ExprKind::Path(ref r)) => self.eq_qpath(l, r),
-            (&ExprKind::Struct(ref l_path, ref lf, ref lo), &ExprKind::Struct(ref r_path, ref rf, ref ro)) => {
+            (&ExprKind::Struct(l_path, lf, ref lo), &ExprKind::Struct(r_path, rf, ref ro)) => {
                 self.eq_qpath(l_path, r_path)
                     && both(lo, ro, |l, r| self.eq_expr(l, r))
                     && over(lf, rf, |l, r| self.eq_expr_field(l, r))
             },
             (&ExprKind::Tup(l_tup), &ExprKind::Tup(r_tup)) => self.eq_exprs(l_tup, r_tup),
-            (&ExprKind::Unary(l_op, ref le), &ExprKind::Unary(r_op, ref re)) => l_op == r_op && self.eq_expr(le, re),
+            (&ExprKind::Unary(l_op, le), &ExprKind::Unary(r_op, re)) => l_op == r_op && self.eq_expr(le, re),
             (&ExprKind::Array(l), &ExprKind::Array(r)) => self.eq_exprs(l, r),
-            (&ExprKind::DropTemps(ref le), &ExprKind::DropTemps(ref re)) => self.eq_expr(le, re),
+            (&ExprKind::DropTemps(le), &ExprKind::DropTemps(re)) => self.eq_expr(le, re),
             _ => false,
         };
         is_eq || self.inner.expr_fallback.as_mut().map_or(false, |f| f(left, right))
@@ -277,7 +272,7 @@ impl HirEqInterExpr<'_, '_, '_> {
     }
 
     fn eq_expr_field(&mut self, left: &ExprField<'_>, right: &ExprField<'_>) -> bool {
-        left.ident.name == right.ident.name && self.eq_expr(&left.expr, &right.expr)
+        left.ident.name == right.ident.name && self.eq_expr(left.expr, right.expr)
     }
 
     fn eq_guard(&mut self, left: &Guard<'_>, right: &Guard<'_>) -> bool {
@@ -290,6 +285,7 @@ impl HirEqInterExpr<'_, '_, '_> {
 
     fn eq_generic_arg(&mut self, left: &GenericArg<'_>, right: &GenericArg<'_>) -> bool {
         match (left, right) {
+            (GenericArg::Const(l), GenericArg::Const(r)) => self.eq_body(l.value.body, r.value.body),
             (GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => Self::eq_lifetime(l_lt, r_lt),
             (GenericArg::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty, r_ty),
             _ => false,
@@ -308,11 +304,11 @@ impl HirEqInterExpr<'_, '_, '_> {
     /// Checks whether two patterns are the same.
     fn eq_pat(&mut self, left: &Pat<'_>, right: &Pat<'_>) -> bool {
         match (&left.kind, &right.kind) {
-            (&PatKind::Box(ref l), &PatKind::Box(ref r)) => self.eq_pat(l, r),
-            (&PatKind::Struct(ref lp, ref la, ..), &PatKind::Struct(ref rp, ref ra, ..)) => {
+            (&PatKind::Box(l), &PatKind::Box(r)) => self.eq_pat(l, r),
+            (&PatKind::Struct(ref lp, la, ..), &PatKind::Struct(ref rp, ra, ..)) => {
                 self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat_field(l, r))
             },
-            (&PatKind::TupleStruct(ref lp, ref la, ls), &PatKind::TupleStruct(ref rp, ref ra, rs)) => {
+            (&PatKind::TupleStruct(ref lp, la, ls), &PatKind::TupleStruct(ref rp, ra, rs)) => {
                 self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat(l, r)) && ls == rs
             },
             (&PatKind::Binding(lb, li, _, ref lp), &PatKind::Binding(rb, ri, _, ref rp)) => {
@@ -323,15 +319,13 @@ impl HirEqInterExpr<'_, '_, '_> {
                 eq
             },
             (&PatKind::Path(ref l), &PatKind::Path(ref r)) => self.eq_qpath(l, r),
-            (&PatKind::Lit(ref l), &PatKind::Lit(ref r)) => self.eq_expr(l, r),
-            (&PatKind::Tuple(ref l, ls), &PatKind::Tuple(ref r, rs)) => {
-                ls == rs && over(l, r, |l, r| self.eq_pat(l, r))
-            },
+            (&PatKind::Lit(l), &PatKind::Lit(r)) => self.eq_expr(l, r),
+            (&PatKind::Tuple(l, ls), &PatKind::Tuple(r, rs)) => ls == rs && over(l, r, |l, r| self.eq_pat(l, r)),
             (&PatKind::Range(ref ls, ref le, li), &PatKind::Range(ref rs, ref re, ri)) => {
                 both(ls, rs, |a, b| self.eq_expr(a, b)) && both(le, re, |a, b| self.eq_expr(a, b)) && (li == ri)
             },
-            (&PatKind::Ref(ref le, ref lm), &PatKind::Ref(ref re, ref rm)) => lm == rm && self.eq_pat(le, re),
-            (&PatKind::Slice(ref ls, ref li, ref le), &PatKind::Slice(ref rs, ref ri, ref re)) => {
+            (&PatKind::Ref(le, ref lm), &PatKind::Ref(re, ref rm)) => lm == rm && self.eq_pat(le, re),
+            (&PatKind::Slice(ls, ref li, le), &PatKind::Slice(rs, ref ri, re)) => {
                 over(ls, rs, |l, r| self.eq_pat(l, r))
                     && over(le, re, |l, r| self.eq_pat(l, r))
                     && both(li, ri, |l, r| self.eq_pat(l, r))
@@ -344,10 +338,10 @@ impl HirEqInterExpr<'_, '_, '_> {
     #[allow(clippy::similar_names)]
     fn eq_qpath(&mut self, left: &QPath<'_>, right: &QPath<'_>) -> bool {
         match (left, right) {
-            (&QPath::Resolved(ref lty, ref lpath), &QPath::Resolved(ref rty, ref rpath)) => {
+            (&QPath::Resolved(ref lty, lpath), &QPath::Resolved(ref rty, rpath)) => {
                 both(lty, rty, |l, r| self.eq_ty(l, r)) && self.eq_path(lpath, rpath)
             },
-            (&QPath::TypeRelative(ref lty, ref lseg), &QPath::TypeRelative(ref rty, ref rseg)) => {
+            (&QPath::TypeRelative(lty, lseg), &QPath::TypeRelative(rty, rseg)) => {
                 self.eq_ty(lty, rty) && self.eq_path_segment(lseg, rseg)
             },
             (&QPath::LangItem(llang_item, _), &QPath::LangItem(rlang_item, _)) => llang_item == rlang_item,
@@ -359,14 +353,14 @@ impl HirEqInterExpr<'_, '_, '_> {
         match (left.res, right.res) {
             (Res::Local(l), Res::Local(r)) => l == r || self.locals.get(&l) == Some(&r),
             (Res::Local(_), _) | (_, Res::Local(_)) => false,
-            _ => over(&left.segments, &right.segments, |l, r| self.eq_path_segment(l, r)),
+            _ => over(left.segments, right.segments, |l, r| self.eq_path_segment(l, r)),
         }
     }
 
     fn eq_path_parameters(&mut self, left: &GenericArgs<'_>, right: &GenericArgs<'_>) -> bool {
         if !(left.parenthesized || right.parenthesized) {
-            over(&left.args, &right.args, |l, r| self.eq_generic_arg(l, r)) // FIXME(flip1995): may not work
-                && over(&left.bindings, &right.bindings, |l, r| self.eq_type_binding(l, r))
+            over(left.args, right.args, |l, r| self.eq_generic_arg(l, r)) // FIXME(flip1995): may not work
+                && over(left.bindings, right.bindings, |l, r| self.eq_type_binding(l, r))
         } else if left.parenthesized && right.parenthesized {
             over(left.inputs(), right.inputs(), |l, r| self.eq_ty(l, r))
                 && both(&Some(&left.bindings[0].ty()), &Some(&right.bindings[0].ty()), |l, r| {
@@ -390,12 +384,9 @@ impl HirEqInterExpr<'_, '_, '_> {
     #[allow(clippy::similar_names)]
     fn eq_ty(&mut self, left: &Ty<'_>, right: &Ty<'_>) -> bool {
         match (&left.kind, &right.kind) {
-            (&TyKind::Slice(ref l_vec), &TyKind::Slice(ref r_vec)) => self.eq_ty(l_vec, r_vec),
-            (&TyKind::Array(ref lt, ref ll_id), &TyKind::Array(ref rt, ref rl_id)) => {
-                let cx = self.inner.cx;
-                let eval_const =
-                    |body| constant_context(cx, cx.tcx.typeck_body(body)).expr(&cx.tcx.hir().body(body).value);
-                self.eq_ty(lt, rt) && eval_const(ll_id.body) == eval_const(rl_id.body)
+            (&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec),
+            (&TyKind::Array(lt, ref ll_id), &TyKind::Array(rt, ref rl_id)) => {
+                self.eq_ty(lt, rt) && self.eq_body(ll_id.body, rl_id.body)
             },
             (&TyKind::Ptr(ref l_mut), &TyKind::Ptr(ref r_mut)) => {
                 l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty)
@@ -404,14 +395,14 @@ impl HirEqInterExpr<'_, '_, '_> {
                 l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(&*l_rmut.ty, &*r_rmut.ty)
             },
             (&TyKind::Path(ref l), &TyKind::Path(ref r)) => self.eq_qpath(l, r),
-            (&TyKind::Tup(ref l), &TyKind::Tup(ref r)) => over(l, r, |l, r| self.eq_ty(l, r)),
+            (&TyKind::Tup(l), &TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)),
             (&TyKind::Infer, &TyKind::Infer) => true,
             _ => false,
         }
     }
 
     fn eq_type_binding(&mut self, left: &TypeBinding<'_>, right: &TypeBinding<'_>) -> bool {
-        left.ident.name == right.ident.name && self.eq_ty(&left.ty(), &right.ty())
+        left.ident.name == right.ident.name && self.eq_ty(left.ty(), right.ty())
     }
 }
 
@@ -519,7 +510,7 @@ pub struct SpanlessHash<'a, 'tcx> {
     /// Context used to evaluate constant expressions.
     cx: &'a LateContext<'tcx>,
     maybe_typeck_results: Option<&'tcx TypeckResults<'tcx>>,
-    s: StableHasher,
+    s: FxHasher,
 }
 
 impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
@@ -527,7 +518,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
         Self {
             cx,
             maybe_typeck_results: cx.maybe_typeck_results(),
-            s: StableHasher::new(),
+            s: FxHasher::default(),
         }
     }
 
@@ -540,17 +531,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
             self.hash_stmt(s);
         }
 
-        if let Some(ref e) = b.expr {
+        if let Some(e) = b.expr {
             self.hash_expr(e);
         }
 
-        match b.rules {
-            BlockCheckMode::DefaultBlock => 0,
-            BlockCheckMode::UnsafeBlock(_) => 1,
-            BlockCheckMode::PushUnsafeBlock(_) => 2,
-            BlockCheckMode::PopUnsafeBlock(_) => 3,
-        }
-        .hash(&mut self.s);
+        std::mem::discriminant(&b.rules).hash(&mut self.s);
     }
 
     #[allow(clippy::many_single_char_names, clippy::too_many_lines)]
@@ -561,21 +546,16 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
 
         // const hashing may result in the same hash as some unrelated node, so add a sort of
         // discriminant depending on which path we're choosing next
-        simple_const.is_some().hash(&mut self.s);
-
-        if let Some(e) = simple_const {
-            return e.hash(&mut self.s);
+        simple_const.hash(&mut self.s);
+        if simple_const.is_some() {
+            return;
         }
 
         std::mem::discriminant(&e.kind).hash(&mut self.s);
 
         match e.kind {
-            ExprKind::AddrOf(kind, m, ref e) => {
-                match kind {
-                    BorrowKind::Ref => 0,
-                    BorrowKind::Raw => 1,
-                }
-                .hash(&mut self.s);
+            ExprKind::AddrOf(kind, m, e) => {
+                std::mem::discriminant(&kind).hash(&mut self.s);
                 m.hash(&mut self.s);
                 self.hash_expr(e);
             },
@@ -584,22 +564,20 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     self.hash_name(i.ident.name);
                 }
             },
-            ExprKind::Assign(ref l, ref r, _) => {
+            ExprKind::Assign(l, r, _) => {
                 self.hash_expr(l);
                 self.hash_expr(r);
             },
-            ExprKind::AssignOp(ref o, ref l, ref r) => {
-                o.node
-                    .hash_stable(&mut self.cx.tcx.get_stable_hashing_context(), &mut self.s);
+            ExprKind::AssignOp(ref o, l, r) => {
+                std::mem::discriminant(&o.node).hash(&mut self.s);
                 self.hash_expr(l);
                 self.hash_expr(r);
             },
-            ExprKind::Block(ref b, _) => {
+            ExprKind::Block(b, _) => {
                 self.hash_block(b);
             },
-            ExprKind::Binary(op, ref l, ref r) => {
-                op.node
-                    .hash_stable(&mut self.cx.tcx.get_stable_hashing_context(), &mut self.s);
+            ExprKind::Binary(op, l, r) => {
+                std::mem::discriminant(&op.node).hash(&mut self.s);
                 self.hash_expr(l);
                 self.hash_expr(r);
             },
@@ -607,39 +585,35 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 if let Some(i) = i.label {
                     self.hash_name(i.ident.name);
                 }
-                if let Some(ref j) = *j {
+                if let Some(j) = *j {
                     self.hash_expr(&*j);
                 }
             },
-            ExprKind::Box(ref e) | ExprKind::DropTemps(ref e) | ExprKind::Yield(ref e, _) => {
+            ExprKind::Box(e) | ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => {
                 self.hash_expr(e);
             },
-            ExprKind::Call(ref fun, args) => {
+            ExprKind::Call(fun, args) => {
                 self.hash_expr(fun);
                 self.hash_exprs(args);
             },
-            ExprKind::Cast(ref e, ref ty) | ExprKind::Type(ref e, ref ty) => {
+            ExprKind::Cast(e, ty) | ExprKind::Type(e, ty) => {
                 self.hash_expr(e);
                 self.hash_ty(ty);
             },
             ExprKind::Closure(cap, _, eid, _, _) => {
-                match cap {
-                    CaptureBy::Value => 0,
-                    CaptureBy::Ref => 1,
-                }
-                .hash(&mut self.s);
+                std::mem::discriminant(&cap).hash(&mut self.s);
                 // closures inherit TypeckResults
                 self.hash_expr(&self.cx.tcx.hir().body(eid).value);
             },
-            ExprKind::Field(ref e, ref f) => {
+            ExprKind::Field(e, ref f) => {
                 self.hash_expr(e);
                 self.hash_name(f.name);
             },
-            ExprKind::Index(ref a, ref i) => {
+            ExprKind::Index(a, i) => {
                 self.hash_expr(a);
                 self.hash_expr(i);
             },
-            ExprKind::InlineAsm(ref asm) => {
+            ExprKind::InlineAsm(asm) => {
                 for piece in asm.template {
                     match piece {
                         InlineAsmTemplatePiece::String(s) => s.hash(&mut self.s),
@@ -694,22 +668,20 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
             ExprKind::Lit(ref l) => {
                 l.node.hash(&mut self.s);
             },
-            ExprKind::Loop(ref b, ref i, ..) => {
+            ExprKind::Loop(b, ref i, ..) => {
                 self.hash_block(b);
                 if let Some(i) = *i {
                     self.hash_name(i.ident.name);
                 }
             },
-            ExprKind::If(ref cond, ref then, ref else_opt) => {
-                let c: fn(_, _, _) -> _ = ExprKind::If;
-                c.hash(&mut self.s);
+            ExprKind::If(cond, then, ref else_opt) => {
                 self.hash_expr(cond);
-                self.hash_expr(&**then);
-                if let Some(ref e) = *else_opt {
+                self.hash_expr(then);
+                if let Some(e) = *else_opt {
                     self.hash_expr(e);
                 }
             },
-            ExprKind::Match(ref e, arms, ref s) => {
+            ExprKind::Match(e, arms, ref s) => {
                 self.hash_expr(e);
 
                 for arm in arms {
@@ -717,39 +689,39 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     if let Some(ref e) = arm.guard {
                         self.hash_guard(e);
                     }
-                    self.hash_expr(&arm.body);
+                    self.hash_expr(arm.body);
                 }
 
                 s.hash(&mut self.s);
             },
-            ExprKind::MethodCall(ref path, ref _tys, args, ref _fn_span) => {
+            ExprKind::MethodCall(path, ref _tys, args, ref _fn_span) => {
                 self.hash_name(path.ident.name);
                 self.hash_exprs(args);
             },
             ExprKind::ConstBlock(ref l_id) => {
                 self.hash_body(l_id.body);
             },
-            ExprKind::Repeat(ref e, ref l_id) => {
+            ExprKind::Repeat(e, ref l_id) => {
                 self.hash_expr(e);
                 self.hash_body(l_id.body);
             },
             ExprKind::Ret(ref e) => {
-                if let Some(ref e) = *e {
+                if let Some(e) = *e {
                     self.hash_expr(e);
                 }
             },
             ExprKind::Path(ref qpath) => {
                 self.hash_qpath(qpath);
             },
-            ExprKind::Struct(ref path, fields, ref expr) => {
+            ExprKind::Struct(path, fields, ref expr) => {
                 self.hash_qpath(path);
 
                 for f in fields {
                     self.hash_name(f.ident.name);
-                    self.hash_expr(&f.expr);
+                    self.hash_expr(f.expr);
                 }
 
-                if let Some(ref e) = *expr {
+                if let Some(e) = *expr {
                     self.hash_expr(e);
                 }
             },
@@ -759,8 +731,8 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
             ExprKind::Array(v) => {
                 self.hash_exprs(v);
             },
-            ExprKind::Unary(lop, ref le) => {
-                lop.hash_stable(&mut self.cx.tcx.get_stable_hashing_context(), &mut self.s);
+            ExprKind::Unary(lop, le) => {
+                std::mem::discriminant(&lop).hash(&mut self.s);
                 self.hash_expr(le);
             },
         }
@@ -773,19 +745,19 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
     }
 
     pub fn hash_name(&mut self, n: Symbol) {
-        n.as_str().hash(&mut self.s);
+        n.hash(&mut self.s);
     }
 
     pub fn hash_qpath(&mut self, p: &QPath<'_>) {
         match *p {
-            QPath::Resolved(_, ref path) => {
+            QPath::Resolved(_, path) => {
                 self.hash_path(path);
             },
-            QPath::TypeRelative(_, ref path) => {
+            QPath::TypeRelative(_, path) => {
                 self.hash_name(path.ident.name);
             },
             QPath::LangItem(lang_item, ..) => {
-                lang_item.hash_stable(&mut self.cx.tcx.get_stable_hashing_context(), &mut self.s);
+                std::mem::discriminant(&lang_item).hash(&mut self.s);
             },
         }
         // self.maybe_typeck_results.unwrap().qpath_res(p, id).hash(&mut self.s);
@@ -795,7 +767,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
         std::mem::discriminant(&pat.kind).hash(&mut self.s);
         match pat.kind {
             PatKind::Binding(ann, _, _, pat) => {
-                ann.hash_stable(&mut self.cx.tcx.get_stable_hashing_context(), &mut self.s);
+                std::mem::discriminant(&ann).hash(&mut self.s);
                 if let Some(pat) = pat {
                     self.hash_pat(pat);
                 }
@@ -815,11 +787,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 if let Some(e) = e {
                     self.hash_expr(e);
                 }
-                i.hash_stable(&mut self.cx.tcx.get_stable_hashing_context(), &mut self.s);
+                std::mem::discriminant(&i).hash(&mut self.s);
             },
-            PatKind::Ref(pat, m) => {
+            PatKind::Ref(pat, mu) => {
                 self.hash_pat(pat);
-                m.hash(&mut self.s);
+                std::mem::discriminant(&mu).hash(&mut self.s);
             },
             PatKind::Slice(l, m, r) => {
                 for pat in l {
@@ -838,7 +810,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     self.hash_name(f.ident.name);
                     self.hash_pat(f.pat);
                 }
-                e.hash(&mut self.s)
+                e.hash(&mut self.s);
             },
             PatKind::Tuple(pats, e) => {
                 for pat in pats {
@@ -864,6 +836,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
             _ => {
                 for seg in path.segments {
                     self.hash_name(seg.ident.name);
+                    self.hash_generic_args(seg.args().args);
                 }
             },
         }
@@ -875,7 +848,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
         match &b.kind {
             StmtKind::Local(local) => {
                 self.hash_pat(local.pat);
-                if let Some(ref init) = local.init {
+                if let Some(init) = local.init {
                     self.hash_expr(init);
                 }
             },
@@ -888,7 +861,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
 
     pub fn hash_guard(&mut self, g: &Guard<'_>) {
         match g {
-            Guard::If(ref expr) | Guard::IfLet(_, ref expr) => {
+            Guard::If(expr) | Guard::IfLet(_, expr) => {
                 self.hash_expr(expr);
             },
         }
@@ -921,25 +894,24 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 self.hash_body(anon_const.body);
             },
             TyKind::Ptr(ref mut_ty) => {
-                self.hash_ty(&mut_ty.ty);
+                self.hash_ty(mut_ty.ty);
                 mut_ty.mutbl.hash(&mut self.s);
             },
             TyKind::Rptr(lifetime, ref mut_ty) => {
                 self.hash_lifetime(lifetime);
-                self.hash_ty(&mut_ty.ty);
+                self.hash_ty(mut_ty.ty);
                 mut_ty.mutbl.hash(&mut self.s);
             },
             TyKind::BareFn(bfn) => {
                 bfn.unsafety.hash(&mut self.s);
                 bfn.abi.hash(&mut self.s);
                 for arg in bfn.decl.inputs {
-                    self.hash_ty(&arg);
+                    self.hash_ty(arg);
                 }
+                std::mem::discriminant(&bfn.decl.output).hash(&mut self.s);
                 match bfn.decl.output {
-                    FnRetTy::DefaultReturn(_) => {
-                        ().hash(&mut self.s);
-                    },
-                    FnRetTy::Return(ref ty) => {
+                    FnRetTy::DefaultReturn(_) => {},
+                    FnRetTy::Return(ty) => {
                         self.hash_ty(ty);
                     },
                 }
@@ -950,24 +922,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     self.hash_ty(ty);
                 }
             },
-            TyKind::Path(ref qpath) => match qpath {
-                QPath::Resolved(ref maybe_ty, ref path) => {
-                    if let Some(ref ty) = maybe_ty {
-                        self.hash_ty(ty);
-                    }
-                    for segment in path.segments {
-                        segment.ident.name.hash(&mut self.s);
-                        self.hash_generic_args(segment.args().args);
-                    }
-                },
-                QPath::TypeRelative(ref ty, ref segment) => {
-                    self.hash_ty(ty);
-                    segment.ident.name.hash(&mut self.s);
-                },
-                QPath::LangItem(lang_item, ..) => {
-                    lang_item.hash(&mut self.s);
-                },
-            },
+            TyKind::Path(ref qpath) => self.hash_qpath(qpath),
             TyKind::OpaqueDef(_, arg_list) => {
                 self.hash_generic_args(arg_list);
             },
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 82250151aab..769836aaf18 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -63,7 +63,7 @@ use std::hash::BuildHasherDefault;
 
 use if_chain::if_chain;
 use rustc_ast::ast::{self, Attribute, BorrowKind, LitKind};
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::unhash::UnhashMap;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
@@ -328,7 +328,7 @@ pub fn is_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, diag_item: Symbol)
 
 /// Checks if an expression references a variable of the given name.
 pub fn match_var(expr: &Expr<'_>, var: Symbol) -> bool {
-    if let ExprKind::Path(QPath::Resolved(None, ref path)) = expr.kind {
+    if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind {
         if let [p] = path.segments {
             return p.ident.name == var;
         }
@@ -338,8 +338,8 @@ pub fn match_var(expr: &Expr<'_>, var: Symbol) -> bool {
 
 pub fn last_path_segment<'tcx>(path: &QPath<'tcx>) -> &'tcx PathSegment<'tcx> {
     match *path {
-        QPath::Resolved(_, ref path) => path.segments.last().expect("A path must have at least one segment"),
-        QPath::TypeRelative(_, ref seg) => seg,
+        QPath::Resolved(_, path) => path.segments.last().expect("A path must have at least one segment"),
+        QPath::TypeRelative(_, seg) => seg,
         QPath::LangItem(..) => panic!("last_path_segment: lang item has no path segments"),
     }
 }
@@ -367,8 +367,8 @@ pub fn get_qpath_generic_tys(path: &QPath<'tcx>) -> impl Iterator<Item = &'tcx h
 
 pub fn single_segment_path<'tcx>(path: &QPath<'tcx>) -> Option<&'tcx PathSegment<'tcx>> {
     match *path {
-        QPath::Resolved(_, ref path) => path.segments.get(0),
-        QPath::TypeRelative(_, ref seg) => Some(seg),
+        QPath::Resolved(_, path) => path.segments.get(0),
+        QPath::TypeRelative(_, seg) => Some(seg),
         QPath::LangItem(..) => None,
     }
 }
@@ -388,8 +388,8 @@ pub fn single_segment_path<'tcx>(path: &QPath<'tcx>) -> Option<&'tcx PathSegment
 /// ```
 pub fn match_qpath(path: &QPath<'_>, segments: &[&str]) -> bool {
     match *path {
-        QPath::Resolved(_, ref path) => match_path(path, segments),
-        QPath::TypeRelative(ref ty, ref segment) => match ty.kind {
+        QPath::Resolved(_, path) => match_path(path, segments),
+        QPath::TypeRelative(ty, segment) => match ty.kind {
             TyKind::Path(ref inner_path) => {
                 if let [prefix @ .., end] = segments {
                     if match_qpath(inner_path, prefix) {
@@ -457,7 +457,7 @@ pub fn match_path(path: &Path<'_>, segments: &[&str]) -> bool {
 
 /// If the expression is a path to a local, returns the canonical `HirId` of the local.
 pub fn path_to_local(expr: &Expr<'_>) -> Option<HirId> {
-    if let ExprKind::Path(QPath::Resolved(None, ref path)) = expr.kind {
+    if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind {
         if let Res::Local(id) = path.res {
             return Some(id);
         }
@@ -661,13 +661,13 @@ pub fn method_chain_args<'a>(expr: &'a Expr<'_>, methods: &[&str]) -> Option<Vec
     let mut matched = Vec::with_capacity(methods.len());
     for method_name in methods.iter().rev() {
         // method chains are stored last -> first
-        if let ExprKind::MethodCall(ref path, _, ref args, _) = current.kind {
+        if let ExprKind::MethodCall(path, _, args, _) = current.kind {
             if path.ident.name.as_str() == *method_name {
                 if args.iter().any(|e| e.span.from_expansion()) {
                     return None;
                 }
-                matched.push(&**args); // build up `matched` backwards
-                current = &args[0] // go to parent expression
+                matched.push(args); // build up `matched` backwards
+                current = &args[0]; // go to parent expression
             } else {
                 return None;
             }
@@ -712,7 +712,7 @@ pub fn get_pat_name(pat: &Pat<'_>) -> Option<Symbol> {
     match pat.kind {
         PatKind::Binding(.., ref spname, _) => Some(spname.name),
         PatKind::Path(ref qpath) => single_segment_path(qpath).map(|ps| ps.ident.name),
-        PatKind::Box(ref p) | PatKind::Ref(ref p, _) => get_pat_name(&*p),
+        PatKind::Box(p) | PatKind::Ref(p, _) => get_pat_name(&*p),
         _ => None,
     }
 }
@@ -854,7 +854,7 @@ pub fn get_enclosing_block<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Optio
             kind: ImplItemKind::Fn(_, eid),
             ..
         }) => match cx.tcx.hir().body(eid).value.kind {
-            ExprKind::Block(ref block, _) => Some(block),
+            ExprKind::Block(block, _) => Some(block),
             _ => None,
         },
         _ => None,
@@ -1028,7 +1028,7 @@ pub fn return_ty<'tcx>(cx: &LateContext<'tcx>, fn_item: hir::HirId) -> Ty<'tcx>
 
 /// Checks if an expression is constructing a tuple-like enum variant or struct
 pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    if let ExprKind::Call(ref fun, _) = expr.kind {
+    if let ExprKind::Call(fun, _) = expr.kind {
         if let ExprKind::Path(ref qp) = fun.kind {
             let res = cx.qpath_res(qp, fun.hir_id);
             return match res {
@@ -1058,21 +1058,21 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
     match pat.kind {
         PatKind::Wild => false,
         PatKind::Binding(_, _, _, pat) => pat.map_or(false, |pat| is_refutable(cx, pat)),
-        PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => is_refutable(cx, pat),
+        PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat),
         PatKind::Lit(..) | PatKind::Range(..) => true,
         PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id),
-        PatKind::Or(ref pats) => {
+        PatKind::Or(pats) => {
             // TODO: should be the honest check, that pats is exhaustive set
             are_refutable(cx, pats.iter().map(|pat| &**pat))
         },
-        PatKind::Tuple(ref pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)),
-        PatKind::Struct(ref qpath, ref fields, _) => {
+        PatKind::Tuple(pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)),
+        PatKind::Struct(ref qpath, fields, _) => {
             is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| &*field.pat))
         },
-        PatKind::TupleStruct(ref qpath, ref pats, _) => {
+        PatKind::TupleStruct(ref qpath, pats, _) => {
             is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats.iter().map(|pat| &**pat))
         },
-        PatKind::Slice(ref head, ref middle, ref tail) => {
+        PatKind::Slice(head, ref middle, tail) => {
             match &cx.typeck_results().node_type(pat.hir_id).kind() {
                 rustc_ty::Slice(..) => {
                     // [..] is the only irrefutable slice pattern.
@@ -1094,9 +1094,9 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
 /// the function once on the given pattern.
 pub fn recurse_or_patterns<'tcx, F: FnMut(&'tcx Pat<'tcx>)>(pat: &'tcx Pat<'tcx>, mut f: F) {
     if let PatKind::Or(pats) = pat.kind {
-        pats.iter().copied().for_each(f)
+        pats.iter().copied().for_each(f);
     } else {
-        f(pat)
+        f(pat);
     }
 }
 
@@ -1111,7 +1111,7 @@ pub fn is_automatically_derived(attrs: &[ast::Attribute]) -> bool {
 /// Ie. `x`, `{ x }` and `{{{{ x }}}}` all give `x`. `{ x; y }` and `{}` return
 /// themselves.
 pub fn remove_blocks<'tcx>(mut expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> {
-    while let ExprKind::Block(ref block, ..) = expr.kind {
+    while let ExprKind::Block(block, ..) = expr.kind {
         match (block.stmts.is_empty(), block.expr.as_ref()) {
             (true, Some(e)) => expr = e,
             _ => break,
@@ -1130,7 +1130,7 @@ pub fn is_self(slf: &Param<'_>) -> bool {
 
 pub fn is_self_ty(slf: &hir::Ty<'_>) -> bool {
     if_chain! {
-        if let TyKind::Path(QPath::Resolved(None, ref path)) = slf.kind;
+        if let TyKind::Path(QPath::Resolved(None, path)) = slf.kind;
         if let Res::SelfTy(..) = path.res;
         then {
             return true
@@ -1148,7 +1148,7 @@ pub fn iter_input_pats<'tcx>(decl: &FnDecl<'_>, body: &'tcx Body<'_>) -> impl It
 pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
     fn is_ok(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
         if_chain! {
-            if let PatKind::TupleStruct(ref path, ref pat, None) = arm.pat.kind;
+            if let PatKind::TupleStruct(ref path, pat, None) = arm.pat.kind;
             if is_lang_ctor(cx, path, ResultOk);
             if let PatKind::Binding(_, hir_id, _, None) = pat[0].kind;
             if path_to_local_id(arm.body, hir_id);
@@ -1167,7 +1167,7 @@ pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tc
         }
     }
 
-    if let ExprKind::Match(_, ref arms, ref source) = expr.kind {
+    if let ExprKind::Match(_, arms, ref source) = expr.kind {
         // desugared from a `?` operator
         if let MatchSource::TryDesugar = *source {
             return Some(expr);
@@ -1254,12 +1254,12 @@ pub fn match_function_call<'tcx>(
     path: &[&str],
 ) -> Option<&'tcx [Expr<'tcx>]> {
     if_chain! {
-        if let ExprKind::Call(ref fun, ref args) = expr.kind;
+        if let ExprKind::Call(fun, args) = expr.kind;
         if let ExprKind::Path(ref qpath) = fun.kind;
         if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
         if match_def_path(cx, fun_def_id, path);
         then {
-            return Some(&args)
+            return Some(args)
         }
     };
     None
@@ -1316,15 +1316,15 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>,
     let mut conds = Vec::new();
     let mut blocks: Vec<&Block<'_>> = Vec::new();
 
-    while let ExprKind::If(ref cond, ref then_expr, ref else_expr) = expr.kind {
-        conds.push(&**cond);
-        if let ExprKind::Block(ref block, _) = then_expr.kind {
+    while let ExprKind::If(cond, then_expr, ref else_expr) = expr.kind {
+        conds.push(cond);
+        if let ExprKind::Block(block, _) = then_expr.kind {
             blocks.push(block);
         } else {
             panic!("ExprKind::If node is not an ExprKind::Block");
         }
 
-        if let Some(ref else_expr) = *else_expr {
+        if let Some(else_expr) = *else_expr {
             expr = else_expr;
         } else {
             break;
@@ -1333,8 +1333,8 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>,
 
     // final `else {..}`
     if !blocks.is_empty() {
-        if let ExprKind::Block(ref block, _) = expr.kind {
-            blocks.push(&**block);
+        if let ExprKind::Block(block, _) = expr.kind {
+            blocks.push(block);
         }
     }
 
@@ -1383,7 +1383,7 @@ pub fn must_use_attr(attrs: &[Attribute]) -> Option<&Attribute> {
 // check if expr is calling method or function with #[must_use] attribute
 pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     let did = match expr.kind {
-        ExprKind::Call(ref path, _) => if_chain! {
+        ExprKind::Call(path, _) => if_chain! {
             if let ExprKind::Path(ref qpath) = path.kind;
             if let def::Res::Def(_, did) = cx.qpath_res(qpath, path.hir_id);
             then {
@@ -1396,7 +1396,7 @@ pub fn is_must_use_func_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
         _ => None,
     };
 
-    did.map_or(false, |did| must_use_attr(&cx.tcx.get_attrs(did)).is_some())
+    did.map_or(false, |did| must_use_attr(cx.tcx.get_attrs(did)).is_some())
 }
 
 /// Gets the node where an expression is either used, or it's type is unified with another branch.
@@ -1572,14 +1572,16 @@ where
     Hash: Fn(&T) -> u64,
     Eq: Fn(&T, &T) -> bool,
 {
-    if exprs.len() == 2 && eq(&exprs[0], &exprs[1]) {
-        return vec![(&exprs[0], &exprs[1])];
+    match exprs {
+        [a, b] if eq(a, b) => return vec![(a, b)],
+        _ if exprs.len() <= 2 => return vec![],
+        _ => {},
     }
 
     let mut match_expr_list: Vec<(&T, &T)> = Vec::new();
 
-    let mut map: FxHashMap<_, Vec<&_>> =
-        FxHashMap::with_capacity_and_hasher(exprs.len(), BuildHasherDefault::default());
+    let mut map: UnhashMap<u64, Vec<&_>> =
+        UnhashMap::with_capacity_and_hasher(exprs.len(), BuildHasherDefault::default());
 
     for expr in exprs {
         match map.entry(hash(expr)) {
diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs
index 00df04c0144..4a9c4fd0276 100644
--- a/src/tools/clippy/clippy_utils/src/msrvs.rs
+++ b/src/tools/clippy/clippy_utils/src/msrvs.rs
@@ -26,4 +26,5 @@ msrv_aliases! {
     1,34,0 { TRY_FROM }
     1,30,0 { ITERATOR_FIND_MAP }
     1,17,0 { FIELD_INIT_SHORTHAND, STATIC_IN_CONST }
+    1,16,0 { STR_REPEAT }
 }
diff --git a/src/tools/clippy/clippy_utils/src/numeric_literal.rs b/src/tools/clippy/clippy_utils/src/numeric_literal.rs
index 268bc5b3205..546706d51d7 100644
--- a/src/tools/clippy/clippy_utils/src/numeric_literal.rs
+++ b/src/tools/clippy/clippy_utils/src/numeric_literal.rs
@@ -52,7 +52,7 @@ impl<'a> NumericLiteral<'a> {
 
     pub fn from_lit_kind(src: &'a str, lit_kind: &LitKind) -> Option<NumericLiteral<'a>> {
         if lit_kind.is_numeric() && src.chars().next().map_or(false, |c| c.is_digit(10)) {
-            let (unsuffixed, suffix) = split_suffix(&src, lit_kind);
+            let (unsuffixed, suffix) = split_suffix(src, lit_kind);
             let float = matches!(lit_kind, LitKind::Float(..));
             Some(NumericLiteral::new(unsuffixed, suffix, float))
         } else {
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index 8037d670500..b913d1ce8b1 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -116,8 +116,8 @@ pub const PERMISSIONS_FROM_MODE: [&str; 7] = ["std", "os", "imp", "unix", "fs",
 pub const POLL: [&str; 4] = ["core", "task", "poll", "Poll"];
 pub const POLL_PENDING: [&str; 5] = ["core", "task", "poll", "Poll", "Pending"];
 pub const POLL_READY: [&str; 5] = ["core", "task", "poll", "Poll", "Ready"];
-pub const PTR_COPY: [&str; 4] = ["core", "intrinsics", "", "copy"];
-pub const PTR_COPY_NONOVERLAPPING: [&str; 4] = ["core", "intrinsics", "", "copy_nonoverlapping"];
+pub const PTR_COPY: [&str; 3] = ["core", "intrinsics", "copy"];
+pub const PTR_COPY_NONOVERLAPPING: [&str; 3] = ["core", "intrinsics", "copy_nonoverlapping"];
 pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"];
 pub const PTR_NULL: [&str; 3] = ["core", "ptr", "null"];
 pub const PTR_NULL_MUT: [&str; 3] = ["core", "ptr", "null_mut"];
diff --git a/src/tools/clippy/clippy_utils/src/ptr.rs b/src/tools/clippy/clippy_utils/src/ptr.rs
index 5885cc83560..791688cd194 100644
--- a/src/tools/clippy/clippy_utils/src/ptr.rs
+++ b/src/tools/clippy/clippy_utils/src/ptr.rs
@@ -55,7 +55,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> {
         if self.abort {
             return;
         }
-        if let ExprKind::MethodCall(ref seg, _, ref args, _) = expr.kind {
+        if let ExprKind::MethodCall(seg, _, args, _) = expr.kind {
             if args.len() == 1 && match_var(&args[0], self.name) {
                 if seg.ident.name.as_str() == "capacity" {
                     self.abort = true;
@@ -79,5 +79,5 @@ impl<'a, 'tcx> Visitor<'tcx> for PtrCloneVisitor<'a, 'tcx> {
 }
 
 fn get_binding_name(arg: &Param<'_>) -> Option<Symbol> {
-    get_pat_name(&arg.pat)
+    get_pat_name(arg.pat)
 }
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index a08dcf19e5b..0e6ead675c2 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -255,7 +255,7 @@ fn check_place(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'t
         cursor = proj_base;
         match elem {
             ProjectionElem::Field(..) => {
-                let base_ty = Place::ty_from(place.local, &proj_base, body, tcx).ty;
+                let base_ty = Place::ty_from(place.local, proj_base, body, tcx).ty;
                 if let Some(def) = base_ty.ty_adt_def() {
                     // No union field accesses in `const fn`
                     if def.is_union() {
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 0c950661757..efc0ec50fdc 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -2,7 +2,7 @@
 #![deny(clippy::missing_docs_in_private_items)]
 
 use crate::higher;
-use crate::source::{snippet, snippet_opt, snippet_with_macro_callsite};
+use crate::source::{snippet, snippet_opt, snippet_with_context, snippet_with_macro_callsite};
 use rustc_ast::util::parser::AssocOp;
 use rustc_ast::{ast, token};
 use rustc_ast_pretty::pprust::token_kind_to_string;
@@ -10,7 +10,7 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::{EarlyContext, LateContext, LintContext};
 use rustc_span::source_map::{CharPos, Span};
-use rustc_span::{BytePos, Pos};
+use rustc_span::{BytePos, Pos, SyntaxContext};
 use std::borrow::Cow;
 use std::convert::TryInto;
 use std::fmt::Display;
@@ -90,6 +90,29 @@ impl<'a> Sugg<'a> {
         Self::hir_from_snippet(expr, snippet)
     }
 
+    /// Same as `hir`, but first walks the span up to the given context. This will result in the
+    /// macro call, rather then the expansion, if the span is from a child context. If the span is
+    /// not from a child context, it will be used directly instead.
+    ///
+    /// e.g. Given the expression `&vec![]`, getting a snippet from the span for `vec![]` as a HIR
+    /// node would result in `box []`. If given the context of the address of expression, this
+    /// function will correctly get a snippet of `vec![]`.
+    pub fn hir_with_context(
+        cx: &LateContext<'_>,
+        expr: &hir::Expr<'_>,
+        ctxt: SyntaxContext,
+        default: &'a str,
+        applicability: &mut Applicability,
+    ) -> Self {
+        let (snippet, in_macro) = snippet_with_context(cx, expr.span, ctxt, default, applicability);
+
+        if in_macro {
+            Sugg::NonParen(snippet)
+        } else {
+            Self::hir_from_snippet(expr, snippet)
+        }
+    }
+
     /// Generate a suggestion for an expression with the given snippet. This is used by the `hir_*`
     /// function variants of `Sugg`, since these use different snippet functions.
     fn hir_from_snippet(expr: &hir::Expr<'_>, snippet: Cow<'a, str>) -> Self {
@@ -684,7 +707,7 @@ impl<T: LintContext> DiagnosticBuilderExt<T> for rustc_errors::DiagnosticBuilder
 
             if let Some(non_whitespace_offset) = non_whitespace_offset {
                 remove_span = remove_span
-                    .with_hi(remove_span.hi() + BytePos(non_whitespace_offset.try_into().expect("offset too large")))
+                    .with_hi(remove_span.hi() + BytePos(non_whitespace_offset.try_into().expect("offset too large")));
             }
         }
 
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index c36e215f184..a92d3be5d3c 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -142,21 +142,18 @@ pub fn has_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
 // Returns whether the type has #[must_use] attribute
 pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
     match ty.kind() {
-        ty::Adt(ref adt, _) => must_use_attr(&cx.tcx.get_attrs(adt.did)).is_some(),
-        ty::Foreign(ref did) => must_use_attr(&cx.tcx.get_attrs(*did)).is_some(),
-        ty::Slice(ref ty)
-        | ty::Array(ref ty, _)
-        | ty::RawPtr(ty::TypeAndMut { ref ty, .. })
-        | ty::Ref(_, ref ty, _) => {
+        ty::Adt(adt, _) => must_use_attr(cx.tcx.get_attrs(adt.did)).is_some(),
+        ty::Foreign(ref did) => must_use_attr(cx.tcx.get_attrs(*did)).is_some(),
+        ty::Slice(ty) | ty::Array(ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _) => {
             // for the Array case we don't need to care for the len == 0 case
             // because we don't want to lint functions returning empty arrays
             is_must_use_ty(cx, *ty)
         },
-        ty::Tuple(ref substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)),
+        ty::Tuple(substs) => substs.types().any(|ty| is_must_use_ty(cx, ty)),
         ty::Opaque(ref def_id, _) => {
             for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) {
                 if let ty::PredicateKind::Trait(trait_predicate, _) = predicate.kind().skip_binder() {
-                    if must_use_attr(&cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some() {
+                    if must_use_attr(cx.tcx.get_attrs(trait_predicate.trait_ref.def_id)).is_some() {
                         return true;
                     }
                 }
@@ -166,7 +163,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
         ty::Dynamic(binder, _) => {
             for predicate in binder.iter() {
                 if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() {
-                    if must_use_attr(&cx.tcx.get_attrs(trait_ref.def_id)).is_some() {
+                    if must_use_attr(cx.tcx.get_attrs(trait_ref.def_id)).is_some() {
                         return true;
                     }
                 }
@@ -305,7 +302,7 @@ pub fn type_is_unsafe_function<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bo
 /// Returns the base type for HIR references and pointers.
 pub fn walk_ptrs_hir_ty<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
     match ty.kind {
-        TyKind::Ptr(ref mut_ty) | TyKind::Rptr(_, ref mut_ty) => walk_ptrs_hir_ty(&mut_ty.ty),
+        TyKind::Ptr(ref mut_ty) | TyKind::Rptr(_, ref mut_ty) => walk_ptrs_hir_ty(mut_ty.ty),
         _ => ty,
     }
 }
diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs
index 650b70c63af..2c55021ac88 100644
--- a/src/tools/clippy/clippy_utils/src/usage.rs
+++ b/src/tools/clippy/clippy_utils/src/usage.rs
@@ -59,7 +59,7 @@ impl<'tcx> MutVarsDelegate {
                 //FIXME: This causes false negatives. We can't get the `NodeId` from
                 //`Categorization::Upvar(_)`. So we search for any `Upvar`s in the
                 //`while`-body, not just the ones in the condition.
-                self.skip = true
+                self.skip = true;
             },
             _ => {},
         }
@@ -71,12 +71,12 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate {
 
     fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, bk: ty::BorrowKind) {
         if let ty::BorrowKind::MutBorrow = bk {
-            self.update(&cmt)
+            self.update(cmt);
         }
     }
 
     fn mutate(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId) {
-        self.update(&cmt)
+        self.update(cmt);
     }
 
     fn fake_read(&mut self, _: rustc_typeck::expr_use_visitor::Place<'tcx>, _: FakeReadCause, _: HirId) {}
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index ecdc666b5f6..ce00106dd4d 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -87,7 +87,7 @@ where
         }
 
         fn visit_stmt(&mut self, stmt: &'hir hir::Stmt<'_>) {
-            intravisit::walk_stmt(&mut *self.inside_stmt(true), stmt)
+            intravisit::walk_stmt(&mut *self.inside_stmt(true), stmt);
         }
 
         fn visit_expr(&mut self, expr: &'hir hir::Expr<'_>) {
@@ -189,34 +189,21 @@ impl<'v> Visitor<'v> for LocalUsedVisitor<'v> {
     }
 }
 
+/// A type which can be visited.
 pub trait Visitable<'tcx> {
-    fn visit<V: Visitor<'tcx>>(self, v: &mut V);
+    /// Calls the corresponding `visit_*` function on the visitor.
+    fn visit<V: Visitor<'tcx>>(self, visitor: &mut V);
 }
-impl Visitable<'tcx> for &'tcx Expr<'tcx> {
-    fn visit<V: Visitor<'tcx>>(self, v: &mut V) {
-        v.visit_expr(self)
-    }
-}
-impl Visitable<'tcx> for &'tcx Block<'tcx> {
-    fn visit<V: Visitor<'tcx>>(self, v: &mut V) {
-        v.visit_block(self)
-    }
-}
-impl<'tcx> Visitable<'tcx> for &'tcx Stmt<'tcx> {
-    fn visit<V: Visitor<'tcx>>(self, v: &mut V) {
-        v.visit_stmt(self)
-    }
-}
-impl<'tcx> Visitable<'tcx> for &'tcx Body<'tcx> {
-    fn visit<V: Visitor<'tcx>>(self, v: &mut V) {
-        v.visit_body(self)
-    }
-}
-impl<'tcx> Visitable<'tcx> for &'tcx Arm<'tcx> {
-    fn visit<V: Visitor<'tcx>>(self, v: &mut V) {
-        v.visit_arm(self)
-    }
+macro_rules! visitable_ref {
+    ($t:ident, $f:ident) => {
+        impl Visitable<'tcx> for &'tcx $t<'tcx> {
+            fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) {
+                visitor.$f(self);
+            }
+        }
+    };
 }
+visitable_ref!(Block, visit_block);
 
 /// Calls the given function for each break expression.
 pub fn visit_break_exprs<'tcx>(
@@ -232,7 +219,7 @@ pub fn visit_break_exprs<'tcx>(
 
         fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
             if let ExprKind::Break(dest, sub_expr) = e.kind {
-                self.0(e, dest, sub_expr)
+                self.0(e, dest, sub_expr);
             }
             walk_expr(self, e);
         }
@@ -264,7 +251,7 @@ pub fn is_res_used(cx: &LateContext<'_>, res: Res, body: BodyId) -> bool {
                     self.found = true;
                 }
             } else {
-                walk_expr(self, e)
+                walk_expr(self, e);
             }
         }
     }
diff --git a/src/tools/clippy/doc/release.md b/src/tools/clippy/doc/release.md
index eaa6a9af277..e0af9bf0625 100644
--- a/src/tools/clippy/doc/release.md
+++ b/src/tools/clippy/doc/release.md
@@ -94,7 +94,7 @@ After finding the Clippy commit, it can be tagged with the release number.
 # Assuming the current directory corresponds to the Clippy repository
 $ git checkout $SHA
 $ git tag rust-1.XX.0               # XX should be exchanged with the corresponding version
-$ git push upstream master --tags   # `upstream` is the `rust-lang/rust-clippy` remote
+$ git push upstream rust-1.XX.0     # `upstream` is the `rust-lang/rust-clippy` remote
 ```
 
 After this, the release should be available on the Clippy [release page].
diff --git a/src/tools/clippy/mini-macro/Cargo.toml b/src/tools/clippy/mini-macro/Cargo.toml
deleted file mode 100644
index 0d95c86aef0..00000000000
--- a/src/tools/clippy/mini-macro/Cargo.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-[package]
-name = "clippy-mini-macro-test"
-version = "0.2.0"
-authors = ["The Rust Clippy Developers"]
-license = "MIT OR Apache-2.0"
-description = "A macro to test clippy's procedural macro checks"
-repository = "https://github.com/rust-lang/rust-clippy"
-edition = "2018"
-
-[lib]
-name = "clippy_mini_macro_test"
-proc-macro = true
-
-[dependencies]
diff --git a/src/tools/clippy/mini-macro/src/lib.rs b/src/tools/clippy/mini-macro/src/lib.rs
deleted file mode 100644
index 2b793589049..00000000000
--- a/src/tools/clippy/mini-macro/src/lib.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-#![feature(proc_macro_quote)]
-#![deny(rust_2018_idioms)]
-// FIXME: Remove this attribute once the weird failure is gone.
-#![allow(unused_extern_crates)]
-extern crate proc_macro;
-
-use proc_macro::{quote, TokenStream};
-
-#[proc_macro_derive(ClippyMiniMacroTest)]
-/// # Panics
-///
-/// Panics if the macro derivation fails
-pub fn mini_macro(_: TokenStream) -> TokenStream {
-    quote!(
-        #[allow(unused)]
-        fn needless_take_by_value(s: String) {
-            println!("{}", s.len());
-        }
-        #[allow(unused)]
-        fn needless_loop(items: &[u8]) {
-            for i in 0..items.len() {
-                println!("{}", items[i]);
-            }
-        }
-        fn line_wrapper() {
-            println!("{}", line!());
-        }
-    )
-}
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index cb8cb0978f6..e3863c46288 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2021-05-20"
+channel = "nightly-2021-06-03"
 components = ["llvm-tools-preview", "rustc-dev", "rust-src"]
diff --git a/src/tools/clippy/rustc_tools_util/src/lib.rs b/src/tools/clippy/rustc_tools_util/src/lib.rs
index ff2a7de5725..5f289918a7c 100644
--- a/src/tools/clippy/rustc_tools_util/src/lib.rs
+++ b/src/tools/clippy/rustc_tools_util/src/lib.rs
@@ -100,9 +100,9 @@ pub fn get_commit_date() -> Option<String> {
 }
 
 #[must_use]
-pub fn get_channel() -> Option<String> {
+pub fn get_channel() -> String {
     match env::var("CFG_RELEASE_CHANNEL") {
-        Ok(channel) => Some(channel),
+        Ok(channel) => channel,
         Err(_) => {
             // if that failed, try to ask rustc -V, do some parsing and find out
             match std::process::Command::new("rustc")
@@ -113,16 +113,16 @@ pub fn get_channel() -> Option<String> {
             {
                 Some(rustc_output) => {
                     if rustc_output.contains("beta") {
-                        Some(String::from("beta"))
+                        String::from("beta")
                     } else if rustc_output.contains("stable") {
-                        Some(String::from("stable"))
+                        String::from("stable")
                     } else {
                         // default to nightly if we fail to parse
-                        Some(String::from("nightly"))
+                        String::from("nightly")
                     }
                 },
                 // default to nightly
-                None => Some(String::from("nightly")),
+                None => String::from("nightly"),
             }
         },
     }
diff --git a/src/tools/clippy/tests/clippy.toml b/src/tools/clippy/tests/clippy.toml
new file mode 100644
index 00000000000..5eb7ac03541
--- /dev/null
+++ b/src/tools/clippy/tests/clippy.toml
@@ -0,0 +1 @@
+# default config for tests, overrides clippy.toml at the project root
diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs
index e1110721f6e..7d266a36bb6 100644
--- a/src/tools/clippy/tests/compile-test.rs
+++ b/src/tools/clippy/tests/compile-test.rs
@@ -4,8 +4,8 @@
 use compiletest_rs as compiletest;
 use compiletest_rs::common::Mode as TestMode;
 
-use std::env::{self, set_var, var};
-use std::ffi::OsStr;
+use std::env::{self, remove_var, set_var, var_os};
+use std::ffi::{OsStr, OsString};
 use std::fs;
 use std::io;
 use std::path::{Path, PathBuf};
@@ -88,9 +88,11 @@ fn default_config() -> compiletest::Config {
     config
 }
 
-fn run_mode(cfg: &mut compiletest::Config) {
+fn run_ui(cfg: &mut compiletest::Config) {
     cfg.mode = TestMode::Ui;
     cfg.src_base = Path::new("tests").join("ui");
+    // use tests/clippy.toml
+    let _g = VarGuard::set("CARGO_MANIFEST_DIR", std::fs::canonicalize("tests").unwrap());
     compiletest::run_tests(cfg);
 }
 
@@ -114,7 +116,7 @@ fn run_ui_toml(config: &mut compiletest::Config) {
                 continue;
             }
             let dir_path = dir.path();
-            set_var("CARGO_MANIFEST_DIR", &dir_path);
+            let _g = VarGuard::set("CARGO_MANIFEST_DIR", &dir_path);
             for file in fs::read_dir(&dir_path)? {
                 let file = file?;
                 let file_path = file.path();
@@ -145,9 +147,7 @@ fn run_ui_toml(config: &mut compiletest::Config) {
 
     let tests = compiletest::make_tests(config);
 
-    let manifest_dir = var("CARGO_MANIFEST_DIR").unwrap_or_default();
     let res = run_tests(config, tests);
-    set_var("CARGO_MANIFEST_DIR", &manifest_dir);
     match res {
         Ok(true) => {},
         Ok(false) => panic!("Some tests failed"),
@@ -208,7 +208,7 @@ fn run_ui_cargo(config: &mut compiletest::Config) {
                         Some("main.rs") => {},
                         _ => continue,
                     }
-                    set_var("CLIPPY_CONF_DIR", case.path());
+                    let _g = VarGuard::set("CLIPPY_CONF_DIR", case.path());
                     let paths = compiletest::common::TestPaths {
                         file: file_path,
                         base: config.src_base.clone(),
@@ -236,10 +236,8 @@ fn run_ui_cargo(config: &mut compiletest::Config) {
     let tests = compiletest::make_tests(config);
 
     let current_dir = env::current_dir().unwrap();
-    let conf_dir = var("CLIPPY_CONF_DIR").unwrap_or_default();
     let res = run_tests(config, &config.filters, tests);
     env::set_current_dir(current_dir).unwrap();
-    set_var("CLIPPY_CONF_DIR", conf_dir);
 
     match res {
         Ok(true) => {},
@@ -260,8 +258,32 @@ fn prepare_env() {
 fn compile_test() {
     prepare_env();
     let mut config = default_config();
-    run_mode(&mut config);
+    run_ui(&mut config);
     run_ui_toml(&mut config);
     run_ui_cargo(&mut config);
     run_internal_tests(&mut config);
 }
+
+/// Restores an env var on drop
+#[must_use]
+struct VarGuard {
+    key: &'static str,
+    value: Option<OsString>,
+}
+
+impl VarGuard {
+    fn set(key: &'static str, val: impl AsRef<OsStr>) -> Self {
+        let value = var_os(key);
+        set_var(key, val);
+        Self { key, value }
+    }
+}
+
+impl Drop for VarGuard {
+    fn drop(&mut self) {
+        match self.value.as_deref() {
+            None => remove_var(self.key),
+            Some(value) => set_var(self.key, value),
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/dogfood.rs b/src/tools/clippy/tests/dogfood.rs
index 5d9f128753f..7de130c7dbe 100644
--- a/src/tools/clippy/tests/dogfood.rs
+++ b/src/tools/clippy/tests/dogfood.rs
@@ -179,8 +179,39 @@ fn dogfood_subprojects() {
 #[ignore]
 #[cfg(feature = "metadata-collector-lint")]
 fn run_metadata_collection_lint() {
+    use std::fs::File;
+    use std::time::SystemTime;
+
+    // Setup for validation
+    let metadata_output_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("util/gh-pages/metadata_collection.json");
+    let start_time = SystemTime::now();
+
+    // Run collection as is
     std::env::set_var("ENABLE_METADATA_COLLECTION", "1");
     run_clippy_for_project("clippy_lints");
+
+    // Check if cargo caching got in the way
+    if let Ok(file) = File::open(metadata_output_path) {
+        if let Ok(metadata) = file.metadata() {
+            if let Ok(last_modification) = metadata.modified() {
+                if last_modification > start_time {
+                    // The output file has been modified. Most likely by a hungry
+                    // metadata collection monster. So We'll return.
+                    return;
+                }
+            }
+        }
+    }
+
+    // Force cargo to invalidate the caches
+    filetime::set_file_mtime(
+        PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("clippy_lints/src/lib.rs"),
+        filetime::FileTime::now(),
+    )
+    .unwrap();
+
+    // Running the collection again
+    run_clippy_for_project("clippy_lints");
 }
 
 fn run_clippy_for_project(project: &str) {
diff --git a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
index d83080b69f5..a7be00426c4 100644
--- a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
+++ b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
@@ -1,4 +1,4 @@
-error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `msrv`, `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `unreadable-literal-lint-fractions`, `upper-case-acronyms-aggressive`, `cargo-ignore-publish`, `third-party` at line 5 column 1
+error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `avoid-breaking-exported-api`, `msrv`, `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `unreadable-literal-lint-fractions`, `upper-case-acronyms-aggressive`, `cargo-ignore-publish`, `third-party` at line 5 column 1
 
 error: aborting due to previous error
 
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
index aebeaf34679..4b7b7fec78f 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_derive.rs
@@ -53,3 +53,22 @@ pub fn derive_use_self(_input: TokenStream) -> proc_macro::TokenStream {
         }
     }
 }
+
+#[proc_macro_derive(ClippyMiniMacroTest)]
+pub fn mini_macro(_: TokenStream) -> TokenStream {
+    quote!(
+        #[allow(unused)]
+        fn needless_take_by_value(s: String) {
+            println!("{}", s.len());
+        }
+        #[allow(unused)]
+        fn needless_loop(items: &[u8]) {
+            for i in 0..items.len() {
+                println!("{}", items[i]);
+            }
+        }
+        fn line_wrapper() {
+            println!("{}", line!());
+        }
+    )
+}
diff --git a/src/tools/clippy/tests/ui/crashes/auxiliary/ice-7272-aux.rs b/src/tools/clippy/tests/ui/crashes/auxiliary/ice-7272-aux.rs
new file mode 100644
index 00000000000..780797e3c6a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/auxiliary/ice-7272-aux.rs
@@ -0,0 +1,14 @@
+pub fn warn<T>(_: T) {}
+
+macro_rules! define_macro {
+    ($d:tt $lower:ident $upper:ident) => {
+        #[macro_export]
+        macro_rules! $upper {
+            ($arg:tt) => {
+                $crate::$lower($arg)
+            };
+        }
+    };
+}
+
+define_macro! {$ warn  WARNING}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7272.rs b/src/tools/clippy/tests/ui/crashes/ice-7272.rs
new file mode 100644
index 00000000000..57ab6ca14f8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-7272.rs
@@ -0,0 +1,12 @@
+// aux-build:ice-7272-aux.rs
+
+#![allow(clippy::no_effect)]
+
+extern crate ice_7272_aux;
+
+use ice_7272_aux::*;
+
+pub fn main() {
+    || WARNING!("Style changed!");
+    || "}{";
+}
diff --git a/src/tools/clippy/tests/ui/crashes/procedural_macro.rs b/src/tools/clippy/tests/ui/crashes/procedural_macro.rs
deleted file mode 100644
index c7468493380..00000000000
--- a/src/tools/clippy/tests/ui/crashes/procedural_macro.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-#[macro_use]
-extern crate clippy_mini_macro_test;
-
-#[deny(warnings)]
-fn main() {
-    let x = Foo;
-    println!("{:?}", x);
-}
-
-#[derive(ClippyMiniMacroTest, Debug)]
-struct Foo;
diff --git a/src/tools/clippy/tests/ui/def_id_nocore.rs b/src/tools/clippy/tests/ui/def_id_nocore.rs
index 2a948d60b10..cba7666c2d8 100644
--- a/src/tools/clippy/tests/ui/def_id_nocore.rs
+++ b/src/tools/clippy/tests/ui/def_id_nocore.rs
@@ -20,7 +20,7 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize {
     0
 }
 
-pub struct A;
+struct A;
 
 impl A {
     pub fn as_ref(self) -> &'static str {
diff --git a/src/tools/clippy/tests/ui/deprecated.rs b/src/tools/clippy/tests/ui/deprecated.rs
index dbf0b03af76..4ba9f0c1fcf 100644
--- a/src/tools/clippy/tests/ui/deprecated.rs
+++ b/src/tools/clippy/tests/ui/deprecated.rs
@@ -12,5 +12,7 @@
 #[warn(clippy::unknown_clippy_lints)]
 #[warn(clippy::find_map)]
 #[warn(clippy::filter_map)]
+#[warn(clippy::pub_enum_variant_names)]
+#[warn(clippy::wrong_pub_self_convention)]
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/deprecated.stderr b/src/tools/clippy/tests/ui/deprecated.stderr
index e5de839dbc5..03c9f438891 100644
--- a/src/tools/clippy/tests/ui/deprecated.stderr
+++ b/src/tools/clippy/tests/ui/deprecated.stderr
@@ -84,5 +84,17 @@ error: lint `clippy::filter_map` has been removed: this lint has been replaced b
 LL | #[warn(clippy::filter_map)]
    |        ^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 14 previous errors
+error: lint `clippy::pub_enum_variant_names` has been removed: set the `avoid_breaking_exported_api` config option to `false` to enable the `enum_variant_names` lint for public items
+  --> $DIR/deprecated.rs:15:8
+   |
+LL | #[warn(clippy::pub_enum_variant_names)]
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: lint `clippy::wrong_pub_self_convention` has been removed: set the `avoid_breaking_exported_api` config option to `false` to enable the `wrong_self_convention` lint for public items
+  --> $DIR/deprecated.rs:16:8
+   |
+LL | #[warn(clippy::wrong_pub_self_convention)]
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 16 previous errors
 
diff --git a/src/tools/clippy/tests/ui/enum_variants.rs b/src/tools/clippy/tests/ui/enum_variants.rs
index 4fefc0b43f1..083f5143e6e 100644
--- a/src/tools/clippy/tests/ui/enum_variants.rs
+++ b/src/tools/clippy/tests/ui/enum_variants.rs
@@ -1,5 +1,4 @@
-#![feature(non_ascii_idents)]
-#![warn(clippy::enum_variant_names, clippy::pub_enum_variant_names)]
+#![warn(clippy::enum_variant_names)]
 #![allow(non_camel_case_types, clippy::upper_case_acronyms)]
 
 enum FakeCallType {
@@ -97,8 +96,8 @@ pub enum PubSeall {
     WithOut,
 }
 
-#[allow(clippy::pub_enum_variant_names)]
-mod allowed {
+#[allow(clippy::enum_variant_names)]
+pub mod allowed {
     pub enum PubAllowed {
         SomeThis,
         SomeThat,
diff --git a/src/tools/clippy/tests/ui/enum_variants.stderr b/src/tools/clippy/tests/ui/enum_variants.stderr
index ab7fff4507a..447fbb9e1bf 100644
--- a/src/tools/clippy/tests/ui/enum_variants.stderr
+++ b/src/tools/clippy/tests/ui/enum_variants.stderr
@@ -1,5 +1,5 @@
 error: variant name ends with the enum's name
-  --> $DIR/enum_variants.rs:16:5
+  --> $DIR/enum_variants.rs:15:5
    |
 LL |     cFoo,
    |     ^^^^
@@ -7,25 +7,25 @@ LL |     cFoo,
    = note: `-D clippy::enum-variant-names` implied by `-D warnings`
 
 error: variant name starts with the enum's name
-  --> $DIR/enum_variants.rs:27:5
+  --> $DIR/enum_variants.rs:26:5
    |
 LL |     FoodGood,
    |     ^^^^^^^^
 
 error: variant name starts with the enum's name
-  --> $DIR/enum_variants.rs:28:5
+  --> $DIR/enum_variants.rs:27:5
    |
 LL |     FoodMiddle,
    |     ^^^^^^^^^^
 
 error: variant name starts with the enum's name
-  --> $DIR/enum_variants.rs:29:5
+  --> $DIR/enum_variants.rs:28:5
    |
 LL |     FoodBad,
    |     ^^^^^^^
 
 error: all variants have the same prefix: `Food`
-  --> $DIR/enum_variants.rs:26:1
+  --> $DIR/enum_variants.rs:25:1
    |
 LL | / enum Food {
 LL | |     FoodGood,
@@ -37,7 +37,7 @@ LL | | }
    = help: remove the prefixes and use full paths to the variants instead of glob imports
 
 error: all variants have the same prefix: `CallType`
-  --> $DIR/enum_variants.rs:36:1
+  --> $DIR/enum_variants.rs:35:1
    |
 LL | / enum BadCallType {
 LL | |     CallTypeCall,
@@ -49,7 +49,7 @@ LL | | }
    = help: remove the prefixes and use full paths to the variants instead of glob imports
 
 error: all variants have the same prefix: `Constant`
-  --> $DIR/enum_variants.rs:48:1
+  --> $DIR/enum_variants.rs:47:1
    |
 LL | / enum Consts {
 LL | |     ConstantInt,
@@ -61,7 +61,7 @@ LL | | }
    = help: remove the prefixes and use full paths to the variants instead of glob imports
 
 error: all variants have the same prefix: `With`
-  --> $DIR/enum_variants.rs:82:1
+  --> $DIR/enum_variants.rs:81:1
    |
 LL | / enum Seallll {
 LL | |     WithOutCake,
@@ -73,7 +73,7 @@ LL | | }
    = help: remove the prefixes and use full paths to the variants instead of glob imports
 
 error: all variants have the same prefix: `Prefix`
-  --> $DIR/enum_variants.rs:88:1
+  --> $DIR/enum_variants.rs:87:1
    |
 LL | / enum NonCaps {
 LL | |     Prefix的,
@@ -84,21 +84,8 @@ LL | | }
    |
    = help: remove the prefixes and use full paths to the variants instead of glob imports
 
-error: all variants have the same prefix: `With`
-  --> $DIR/enum_variants.rs:94:1
-   |
-LL | / pub enum PubSeall {
-LL | |     WithOutCake,
-LL | |     WithOutTea,
-LL | |     WithOut,
-LL | | }
-   | |_^
-   |
-   = note: `-D clippy::pub-enum-variant-names` implied by `-D warnings`
-   = help: remove the prefixes and use full paths to the variants instead of glob imports
-
 error: all variants have the same postfix: `IData`
-  --> $DIR/enum_variants.rs:137:1
+  --> $DIR/enum_variants.rs:136:1
    |
 LL | / enum IDataRequest {
 LL | |     PutIData(String),
@@ -110,7 +97,7 @@ LL | | }
    = help: remove the postfixes and use full paths to the variants instead of glob imports
 
 error: all variants have the same postfix: `HIData`
-  --> $DIR/enum_variants.rs:143:1
+  --> $DIR/enum_variants.rs:142:1
    |
 LL | / enum HIDataRequest {
 LL | |     PutHIData(String),
@@ -121,5 +108,5 @@ LL | | }
    |
    = help: remove the postfixes and use full paths to the variants instead of glob imports
 
-error: aborting due to 12 previous errors
+error: aborting due to 11 previous errors
 
diff --git a/src/tools/clippy/tests/ui/eta.fixed b/src/tools/clippy/tests/ui/eta.fixed
index 2be2283e3fd..9e752311c67 100644
--- a/src/tools/clippy/tests/ui/eta.fixed
+++ b/src/tools/clippy/tests/ui/eta.fixed
@@ -48,6 +48,9 @@ fn main() {
     // See #515
     let a: Option<Box<dyn (::std::ops::Deref<Target = [i32]>)>> =
         Some(vec![1i32, 2]).map(|v| -> Box<dyn (::std::ops::Deref<Target = [i32]>)> { Box::new(v) });
+
+    // issue #7224
+    let _: Option<Vec<u32>> = Some(0).map(|_| vec![]);
 }
 
 trait TestTrait {
diff --git a/src/tools/clippy/tests/ui/eta.rs b/src/tools/clippy/tests/ui/eta.rs
index f0373f9ccf6..44be4628cbd 100644
--- a/src/tools/clippy/tests/ui/eta.rs
+++ b/src/tools/clippy/tests/ui/eta.rs
@@ -48,6 +48,9 @@ fn main() {
     // See #515
     let a: Option<Box<dyn (::std::ops::Deref<Target = [i32]>)>> =
         Some(vec![1i32, 2]).map(|v| -> Box<dyn (::std::ops::Deref<Target = [i32]>)> { Box::new(v) });
+
+    // issue #7224
+    let _: Option<Vec<u32>> = Some(0).map(|_| vec![]);
 }
 
 trait TestTrait {
diff --git a/src/tools/clippy/tests/ui/eta.stderr b/src/tools/clippy/tests/ui/eta.stderr
index 57ed6527966..8795d3b42c6 100644
--- a/src/tools/clippy/tests/ui/eta.stderr
+++ b/src/tools/clippy/tests/ui/eta.stderr
@@ -33,7 +33,7 @@ LL |     let e = Some(1u8).map(|a| generic(a));
    |                           ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `generic`
 
 error: redundant closure
-  --> $DIR/eta.rs:89:51
+  --> $DIR/eta.rs:92:51
    |
 LL |     let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo());
    |                                                   ^^^^^^^^^^^ help: replace the closure with the method itself: `TestStruct::foo`
@@ -41,43 +41,43 @@ LL |     let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo());
    = note: `-D clippy::redundant-closure-for-method-calls` implied by `-D warnings`
 
 error: redundant closure
-  --> $DIR/eta.rs:91:51
+  --> $DIR/eta.rs:94:51
    |
 LL |     let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo());
    |                                                   ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `TestTrait::trait_foo`
 
 error: redundant closure
-  --> $DIR/eta.rs:94:42
+  --> $DIR/eta.rs:97:42
    |
 LL |     let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear());
    |                                          ^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::vec::Vec::clear`
 
 error: redundant closure
-  --> $DIR/eta.rs:99:29
+  --> $DIR/eta.rs:102:29
    |
 LL |     let e = Some("str").map(|s| s.to_string());
    |                             ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::string::ToString::to_string`
 
 error: redundant closure
-  --> $DIR/eta.rs:101:27
+  --> $DIR/eta.rs:104:27
    |
 LL |     let e = Some('a').map(|s| s.to_uppercase());
    |                           ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_uppercase`
 
 error: redundant closure
-  --> $DIR/eta.rs:104:65
+  --> $DIR/eta.rs:107:65
    |
 LL |     let e: std::vec::Vec<char> = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect();
    |                                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_ascii_uppercase`
 
 error: redundant closure
-  --> $DIR/eta.rs:187:27
+  --> $DIR/eta.rs:190:27
    |
 LL |     let a = Some(1u8).map(|a| foo_ptr(a));
    |                           ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo_ptr`
 
 error: redundant closure
-  --> $DIR/eta.rs:192:27
+  --> $DIR/eta.rs:195:27
    |
 LL |     let a = Some(1u8).map(|a| closure(a));
    |                           ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `closure`
diff --git a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed
index b5f548810e6..12db43b5343 100644
--- a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed
+++ b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.fixed
@@ -6,6 +6,20 @@
 use std::collections::{BTreeMap, BTreeSet, HashMap, VecDeque};
 use std::iter::FromIterator;
 
+struct Foo(Vec<bool>);
+
+impl FromIterator<bool> for Foo {
+    fn from_iter<T: IntoIterator<Item = bool>>(_: T) -> Self {
+        todo!()
+    }
+}
+
+impl<'a> FromIterator<&'a bool> for Foo {
+    fn from_iter<T: IntoIterator<Item = &'a bool>>(iter: T) -> Self {
+        iter.into_iter().copied().collect::<Self>()
+    }
+}
+
 fn main() {
     let iter_expr = std::iter::repeat(5).take(5);
     let _ = iter_expr.collect::<Vec<_>>();
diff --git a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs
index b842b5451d1..f5ec190e0cd 100644
--- a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs
+++ b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.rs
@@ -6,6 +6,20 @@
 use std::collections::{BTreeMap, BTreeSet, HashMap, VecDeque};
 use std::iter::FromIterator;
 
+struct Foo(Vec<bool>);
+
+impl FromIterator<bool> for Foo {
+    fn from_iter<T: IntoIterator<Item = bool>>(_: T) -> Self {
+        todo!()
+    }
+}
+
+impl<'a> FromIterator<&'a bool> for Foo {
+    fn from_iter<T: IntoIterator<Item = &'a bool>>(iter: T) -> Self {
+        <Self as FromIterator<bool>>::from_iter(iter.into_iter().copied())
+    }
+}
+
 fn main() {
     let iter_expr = std::iter::repeat(5).take(5);
     let _ = Vec::from_iter(iter_expr);
diff --git a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.stderr b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.stderr
index 434734c9a21..8f08ac8c3ff 100644
--- a/src/tools/clippy/tests/ui/from_iter_instead_of_collect.stderr
+++ b/src/tools/clippy/tests/ui/from_iter_instead_of_collect.stderr
@@ -1,88 +1,94 @@
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:11:13
+  --> $DIR/from_iter_instead_of_collect.rs:19:9
    |
-LL |     let _ = Vec::from_iter(iter_expr);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter_expr.collect::<Vec<_>>()`
+LL |         <Self as FromIterator<bool>>::from_iter(iter.into_iter().copied())
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter.into_iter().copied().collect::<Self>()`
    |
    = note: `-D clippy::from-iter-instead-of-collect` implied by `-D warnings`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:13:13
+  --> $DIR/from_iter_instead_of_collect.rs:25:13
+   |
+LL |     let _ = Vec::from_iter(iter_expr);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `iter_expr.collect::<Vec<_>>()`
+
+error: usage of `FromIterator::from_iter`
+  --> $DIR/from_iter_instead_of_collect.rs:27:13
    |
 LL |     let _ = HashMap::<usize, &i8>::from_iter(vec![5, 5, 5, 5].iter().enumerate());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `vec![5, 5, 5, 5].iter().enumerate().collect::<HashMap<usize, &i8>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:18:19
+  --> $DIR/from_iter_instead_of_collect.rs:32:19
    |
 LL |     assert_eq!(a, Vec::from_iter(0..3));
    |                   ^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<Vec<_>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:19:19
+  --> $DIR/from_iter_instead_of_collect.rs:33:19
    |
 LL |     assert_eq!(a, Vec::<i32>::from_iter(0..3));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<Vec<i32>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:21:17
+  --> $DIR/from_iter_instead_of_collect.rs:35:17
    |
 LL |     let mut b = VecDeque::from_iter(0..3);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<VecDeque<_>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:24:17
+  --> $DIR/from_iter_instead_of_collect.rs:38:17
    |
 LL |     let mut b = VecDeque::<i32>::from_iter(0..3);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<VecDeque<i32>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:29:21
+  --> $DIR/from_iter_instead_of_collect.rs:43:21
    |
 LL |         let mut b = collections::VecDeque::<i32>::from_iter(0..3);
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<collections::VecDeque<i32>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:34:14
+  --> $DIR/from_iter_instead_of_collect.rs:48:14
    |
 LL |     let bm = BTreeMap::from_iter(values.iter().cloned());
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `values.iter().cloned().collect::<BTreeMap<_, _>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:35:19
+  --> $DIR/from_iter_instead_of_collect.rs:49:19
    |
 LL |     let mut bar = BTreeMap::from_iter(bm.range(0..2));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `bm.range(0..2).collect::<BTreeMap<_, _>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:38:19
+  --> $DIR/from_iter_instead_of_collect.rs:52:19
    |
 LL |     let mut bts = BTreeSet::from_iter(0..3);
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<BTreeSet<_>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:42:17
+  --> $DIR/from_iter_instead_of_collect.rs:56:17
    |
 LL |         let _ = collections::BTreeSet::from_iter(0..3);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<collections::BTreeSet<_>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:43:17
+  --> $DIR/from_iter_instead_of_collect.rs:57:17
    |
 LL |         let _ = collections::BTreeSet::<u32>::from_iter(0..3);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `(0..3).collect::<collections::BTreeSet<u32>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:46:15
+  --> $DIR/from_iter_instead_of_collect.rs:60:15
    |
 LL |     for _i in Vec::from_iter([1, 2, 3].iter()) {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `[1, 2, 3].iter().collect::<Vec<_>>()`
 
 error: usage of `FromIterator::from_iter`
-  --> $DIR/from_iter_instead_of_collect.rs:47:15
+  --> $DIR/from_iter_instead_of_collect.rs:61:15
    |
 LL |     for _i in Vec::<&i32>::from_iter([1, 2, 3].iter()) {}
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `.collect()` instead of `::from_iter()`: `[1, 2, 3].iter().collect::<Vec<&i32>>()`
 
-error: aborting due to 14 previous errors
+error: aborting due to 15 previous errors
 
diff --git a/src/tools/clippy/tests/ui/functions.stderr b/src/tools/clippy/tests/ui/functions.stderr
index 0a86568b18d..a2b8c2a384b 100644
--- a/src/tools/clippy/tests/ui/functions.stderr
+++ b/src/tools/clippy/tests/ui/functions.stderr
@@ -30,7 +30,7 @@ error: this function has too many arguments (8/7)
 LL |     fn bad_method(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool, _eight: ()) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: this public function dereferences a raw pointer but is not marked `unsafe`
+error: this public function might dereference a raw pointer but is not marked `unsafe`
   --> $DIR/functions.rs:63:34
    |
 LL |         println!("{}", unsafe { *p });
@@ -38,49 +38,49 @@ LL |         println!("{}", unsafe { *p });
    |
    = note: `-D clippy::not-unsafe-ptr-arg-deref` implied by `-D warnings`
 
-error: this public function dereferences a raw pointer but is not marked `unsafe`
+error: this public function might dereference a raw pointer but is not marked `unsafe`
   --> $DIR/functions.rs:64:35
    |
 LL |         println!("{:?}", unsafe { p.as_ref() });
    |                                   ^
 
-error: this public function dereferences a raw pointer but is not marked `unsafe`
+error: this public function might dereference a raw pointer but is not marked `unsafe`
   --> $DIR/functions.rs:65:33
    |
 LL |         unsafe { std::ptr::read(p) };
    |                                 ^
 
-error: this public function dereferences a raw pointer but is not marked `unsafe`
+error: this public function might dereference a raw pointer but is not marked `unsafe`
   --> $DIR/functions.rs:76:30
    |
 LL |     println!("{}", unsafe { *p });
    |                              ^
 
-error: this public function dereferences a raw pointer but is not marked `unsafe`
+error: this public function might dereference a raw pointer but is not marked `unsafe`
   --> $DIR/functions.rs:77:31
    |
 LL |     println!("{:?}", unsafe { p.as_ref() });
    |                               ^
 
-error: this public function dereferences a raw pointer but is not marked `unsafe`
+error: this public function might dereference a raw pointer but is not marked `unsafe`
   --> $DIR/functions.rs:78:29
    |
 LL |     unsafe { std::ptr::read(p) };
    |                             ^
 
-error: this public function dereferences a raw pointer but is not marked `unsafe`
+error: this public function might dereference a raw pointer but is not marked `unsafe`
   --> $DIR/functions.rs:87:34
    |
 LL |         println!("{}", unsafe { *p });
    |                                  ^
 
-error: this public function dereferences a raw pointer but is not marked `unsafe`
+error: this public function might dereference a raw pointer but is not marked `unsafe`
   --> $DIR/functions.rs:88:35
    |
 LL |         println!("{:?}", unsafe { p.as_ref() });
    |                                   ^
 
-error: this public function dereferences a raw pointer but is not marked `unsafe`
+error: this public function might dereference a raw pointer but is not marked `unsafe`
   --> $DIR/functions.rs:89:33
    |
 LL |         unsafe { std::ptr::read(p) };
diff --git a/src/tools/clippy/tests/ui/macro_use_imports.fixed b/src/tools/clippy/tests/ui/macro_use_imports.fixed
index 51c66a46368..70d49d9f2c4 100644
--- a/src/tools/clippy/tests/ui/macro_use_imports.fixed
+++ b/src/tools/clippy/tests/ui/macro_use_imports.fixed
@@ -1,6 +1,7 @@
 // compile-flags: --edition 2018
 // aux-build:macro_rules.rs
 // aux-build:macro_use_helper.rs
+// aux-build:proc_macro_derive.rs
 // run-rustfix
 // ignore-32bit
 
@@ -12,7 +13,7 @@
 extern crate macro_use_helper as mac;
 
 #[macro_use]
-extern crate clippy_mini_macro_test as mini_mac;
+extern crate proc_macro_derive as mini_mac;
 
 mod a {
     use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro};
diff --git a/src/tools/clippy/tests/ui/macro_use_imports.rs b/src/tools/clippy/tests/ui/macro_use_imports.rs
index 2011129bc94..68370023861 100644
--- a/src/tools/clippy/tests/ui/macro_use_imports.rs
+++ b/src/tools/clippy/tests/ui/macro_use_imports.rs
@@ -1,6 +1,7 @@
 // compile-flags: --edition 2018
 // aux-build:macro_rules.rs
 // aux-build:macro_use_helper.rs
+// aux-build:proc_macro_derive.rs
 // run-rustfix
 // ignore-32bit
 
@@ -12,7 +13,7 @@
 extern crate macro_use_helper as mac;
 
 #[macro_use]
-extern crate clippy_mini_macro_test as mini_mac;
+extern crate proc_macro_derive as mini_mac;
 
 mod a {
     #[macro_use]
diff --git a/src/tools/clippy/tests/ui/macro_use_imports.stderr b/src/tools/clippy/tests/ui/macro_use_imports.stderr
index f8c86c8d917..49314b7506d 100644
--- a/src/tools/clippy/tests/ui/macro_use_imports.stderr
+++ b/src/tools/clippy/tests/ui/macro_use_imports.stderr
@@ -1,5 +1,5 @@
 error: `macro_use` attributes are no longer needed in the Rust 2018 edition
-  --> $DIR/macro_use_imports.rs:18:5
+  --> $DIR/macro_use_imports.rs:19:5
    |
 LL |     #[macro_use]
    |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{pub_macro, inner_mod_macro, function_macro, ty_macro, pub_in_private_macro};`
@@ -7,22 +7,22 @@ LL |     #[macro_use]
    = note: `-D clippy::macro-use-imports` implied by `-D warnings`
 
 error: `macro_use` attributes are no longer needed in the Rust 2018 edition
-  --> $DIR/macro_use_imports.rs:20:5
+  --> $DIR/macro_use_imports.rs:25:5
    |
 LL |     #[macro_use]
-   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;`
+   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;`
 
 error: `macro_use` attributes are no longer needed in the Rust 2018 edition
-  --> $DIR/macro_use_imports.rs:22:5
+  --> $DIR/macro_use_imports.rs:21:5
    |
 LL |     #[macro_use]
-   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};`
+   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest;`
 
 error: `macro_use` attributes are no longer needed in the Rust 2018 edition
-  --> $DIR/macro_use_imports.rs:24:5
+  --> $DIR/macro_use_imports.rs:23:5
    |
 LL |     #[macro_use]
-   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::nested::string_add;`
+   |     ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::{inner::foofoo, inner::try_err};`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_str_repeat.fixed b/src/tools/clippy/tests/ui/manual_str_repeat.fixed
new file mode 100644
index 00000000000..dc140257f32
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_str_repeat.fixed
@@ -0,0 +1,66 @@
+// run-rustfix
+
+#![feature(custom_inner_attributes)]
+#![warn(clippy::manual_str_repeat)]
+
+use std::borrow::Cow;
+use std::iter::{repeat, FromIterator};
+
+fn main() {
+    let _: String = "test".repeat(10);
+    let _: String = "x".repeat(10);
+    let _: String = "'".repeat(10);
+    let _: String = "\"".repeat(10);
+
+    let x = "test";
+    let count = 10;
+    let _ = x.repeat(count + 2);
+
+    macro_rules! m {
+        ($e:expr) => {{ $e }};
+    }
+    // FIXME: macro args are fine
+    let _: String = repeat(m!("test")).take(m!(count)).collect();
+
+    let x = &x;
+    let _: String = (*x).repeat(count);
+
+    macro_rules! repeat_m {
+        ($e:expr) => {{ repeat($e) }};
+    }
+    // Don't lint, repeat is from a macro.
+    let _: String = repeat_m!("test").take(count).collect();
+
+    let x: Box<str> = Box::from("test");
+    let _: String = x.repeat(count);
+
+    #[derive(Clone)]
+    struct S;
+    impl FromIterator<Box<S>> for String {
+        fn from_iter<T: IntoIterator<Item = Box<S>>>(_: T) -> Self {
+            Self::new()
+        }
+    }
+    // Don't lint, wrong box type
+    let _: String = repeat(Box::new(S)).take(count).collect();
+
+    let _: String = Cow::Borrowed("test").repeat(count);
+
+    let x = "x".to_owned();
+    let _: String = x.repeat(count);
+
+    let x = 'x';
+    // Don't lint, not char literal
+    let _: String = repeat(x).take(count).collect();
+}
+
+fn _msrv_1_15() {
+    #![clippy::msrv = "1.15"]
+    // `str::repeat` was stabilized in 1.16. Do not lint this
+    let _: String = std::iter::repeat("test").take(10).collect();
+}
+
+fn _msrv_1_16() {
+    #![clippy::msrv = "1.16"]
+    let _: String = "test".repeat(10);
+}
diff --git a/src/tools/clippy/tests/ui/manual_str_repeat.rs b/src/tools/clippy/tests/ui/manual_str_repeat.rs
new file mode 100644
index 00000000000..0d69c989b2e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_str_repeat.rs
@@ -0,0 +1,66 @@
+// run-rustfix
+
+#![feature(custom_inner_attributes)]
+#![warn(clippy::manual_str_repeat)]
+
+use std::borrow::Cow;
+use std::iter::{repeat, FromIterator};
+
+fn main() {
+    let _: String = std::iter::repeat("test").take(10).collect();
+    let _: String = std::iter::repeat('x').take(10).collect();
+    let _: String = std::iter::repeat('\'').take(10).collect();
+    let _: String = std::iter::repeat('"').take(10).collect();
+
+    let x = "test";
+    let count = 10;
+    let _ = repeat(x).take(count + 2).collect::<String>();
+
+    macro_rules! m {
+        ($e:expr) => {{ $e }};
+    }
+    // FIXME: macro args are fine
+    let _: String = repeat(m!("test")).take(m!(count)).collect();
+
+    let x = &x;
+    let _: String = repeat(*x).take(count).collect();
+
+    macro_rules! repeat_m {
+        ($e:expr) => {{ repeat($e) }};
+    }
+    // Don't lint, repeat is from a macro.
+    let _: String = repeat_m!("test").take(count).collect();
+
+    let x: Box<str> = Box::from("test");
+    let _: String = repeat(x).take(count).collect();
+
+    #[derive(Clone)]
+    struct S;
+    impl FromIterator<Box<S>> for String {
+        fn from_iter<T: IntoIterator<Item = Box<S>>>(_: T) -> Self {
+            Self::new()
+        }
+    }
+    // Don't lint, wrong box type
+    let _: String = repeat(Box::new(S)).take(count).collect();
+
+    let _: String = repeat(Cow::Borrowed("test")).take(count).collect();
+
+    let x = "x".to_owned();
+    let _: String = repeat(x).take(count).collect();
+
+    let x = 'x';
+    // Don't lint, not char literal
+    let _: String = repeat(x).take(count).collect();
+}
+
+fn _msrv_1_15() {
+    #![clippy::msrv = "1.15"]
+    // `str::repeat` was stabilized in 1.16. Do not lint this
+    let _: String = std::iter::repeat("test").take(10).collect();
+}
+
+fn _msrv_1_16() {
+    #![clippy::msrv = "1.16"]
+    let _: String = std::iter::repeat("test").take(10).collect();
+}
diff --git a/src/tools/clippy/tests/ui/manual_str_repeat.stderr b/src/tools/clippy/tests/ui/manual_str_repeat.stderr
new file mode 100644
index 00000000000..c6511689716
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_str_repeat.stderr
@@ -0,0 +1,64 @@
+error: manual implementation of `str::repeat` using iterators
+  --> $DIR/manual_str_repeat.rs:10:21
+   |
+LL |     let _: String = std::iter::repeat("test").take(10).collect();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"test".repeat(10)`
+   |
+   = note: `-D clippy::manual-str-repeat` implied by `-D warnings`
+
+error: manual implementation of `str::repeat` using iterators
+  --> $DIR/manual_str_repeat.rs:11:21
+   |
+LL |     let _: String = std::iter::repeat('x').take(10).collect();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"x".repeat(10)`
+
+error: manual implementation of `str::repeat` using iterators
+  --> $DIR/manual_str_repeat.rs:12:21
+   |
+LL |     let _: String = std::iter::repeat('/'').take(10).collect();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"'".repeat(10)`
+
+error: manual implementation of `str::repeat` using iterators
+  --> $DIR/manual_str_repeat.rs:13:21
+   |
+LL |     let _: String = std::iter::repeat('"').take(10).collect();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"/"".repeat(10)`
+
+error: manual implementation of `str::repeat` using iterators
+  --> $DIR/manual_str_repeat.rs:17:13
+   |
+LL |     let _ = repeat(x).take(count + 2).collect::<String>();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `x.repeat(count + 2)`
+
+error: manual implementation of `str::repeat` using iterators
+  --> $DIR/manual_str_repeat.rs:26:21
+   |
+LL |     let _: String = repeat(*x).take(count).collect();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(*x).repeat(count)`
+
+error: manual implementation of `str::repeat` using iterators
+  --> $DIR/manual_str_repeat.rs:35:21
+   |
+LL |     let _: String = repeat(x).take(count).collect();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `x.repeat(count)`
+
+error: manual implementation of `str::repeat` using iterators
+  --> $DIR/manual_str_repeat.rs:47:21
+   |
+LL |     let _: String = repeat(Cow::Borrowed("test")).take(count).collect();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Cow::Borrowed("test").repeat(count)`
+
+error: manual implementation of `str::repeat` using iterators
+  --> $DIR/manual_str_repeat.rs:50:21
+   |
+LL |     let _: String = repeat(x).take(count).collect();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `x.repeat(count)`
+
+error: manual implementation of `str::repeat` using iterators
+  --> $DIR/manual_str_repeat.rs:65:21
+   |
+LL |     let _: String = std::iter::repeat("test").take(10).collect();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"test".repeat(10)`
+
+error: aborting due to 10 previous errors
+
diff --git a/src/tools/clippy/tests/ui/missing-doc-crate.rs b/src/tools/clippy/tests/ui/missing-doc-crate.rs
index 04711f86488..e00c7fbfed1 100644
--- a/src/tools/clippy/tests/ui/missing-doc-crate.rs
+++ b/src/tools/clippy/tests/ui/missing-doc-crate.rs
@@ -1,5 +1,4 @@
 #![warn(clippy::missing_docs_in_private_items)]
-#![feature(external_doc)]
-#![doc(include = "../../README.md")]
+#![doc = include_str!("../../README.md")]
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/missing-doc-impl.rs b/src/tools/clippy/tests/ui/missing-doc-impl.rs
index 57af84dcdf4..bfa9ef01b0e 100644
--- a/src/tools/clippy/tests/ui/missing-doc-impl.rs
+++ b/src/tools/clippy/tests/ui/missing-doc-impl.rs
@@ -67,7 +67,10 @@ impl PubFoo {
     pub fn foo() {}
     /// dox
     pub fn foo1() {}
-    fn foo2() {}
+    #[must_use = "yep"]
+    fn foo2() -> u32 {
+        1
+    }
     #[allow(clippy::missing_docs_in_private_items)]
     pub fn foo3() {}
 }
diff --git a/src/tools/clippy/tests/ui/missing-doc-impl.stderr b/src/tools/clippy/tests/ui/missing-doc-impl.stderr
index 7e10404ca00..d33d512475b 100644
--- a/src/tools/clippy/tests/ui/missing-doc-impl.stderr
+++ b/src/tools/clippy/tests/ui/missing-doc-impl.stderr
@@ -94,10 +94,12 @@ LL |     pub fn foo() {}
    |     ^^^^^^^^^^^^^^^
 
 error: missing documentation for an associated function
-  --> $DIR/missing-doc-impl.rs:70:5
+  --> $DIR/missing-doc-impl.rs:71:5
    |
-LL |     fn foo2() {}
-   |     ^^^^^^^^^^^^
+LL | /     fn foo2() -> u32 {
+LL | |         1
+LL | |     }
+   | |_____^
 
 error: aborting due to 15 previous errors
 
diff --git a/src/tools/clippy/tests/ui/module_name_repetitions.rs b/src/tools/clippy/tests/ui/module_name_repetitions.rs
index 669bf01a84c..f5908cb5701 100644
--- a/src/tools/clippy/tests/ui/module_name_repetitions.rs
+++ b/src/tools/clippy/tests/ui/module_name_repetitions.rs
@@ -15,12 +15,4 @@ mod foo {
     pub struct Foobar;
 }
 
-#[cfg(test)]
-mod test {
-    #[test]
-    fn it_works() {
-        assert_eq!(2 + 2, 4);
-    }
-}
-
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_borrow.fixed b/src/tools/clippy/tests/ui/needless_borrow.fixed
index 5ae4a0e79b9..a87171dc3f2 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.fixed
+++ b/src/tools/clippy/tests/ui/needless_borrow.fixed
@@ -18,7 +18,6 @@ fn main() {
     let vec = Vec::new();
     let vec_val = g(&vec); // should not error, because `&Vec<T>` derefs to `&[T]`
     h(&"foo"); // should not error, because the `&&str` is required, due to `&Trait`
-    if let Some(cake) = Some(&5) {}
     let garbl = match 42 {
         44 => &a,
         45 => {
@@ -43,19 +42,3 @@ trait Trait {}
 impl<'a> Trait for &'a str {}
 
 fn h(_: &dyn Trait) {}
-#[warn(clippy::needless_borrow)]
-#[allow(dead_code)]
-fn issue_1432() {
-    let mut v = Vec::<String>::new();
-    let _ = v.iter_mut().filter(|&ref a| a.is_empty());
-    let _ = v.iter().filter(|&a| a.is_empty());
-
-    let _ = v.iter().filter(|&a| a.is_empty());
-}
-
-#[allow(dead_code)]
-#[warn(clippy::needless_borrow)]
-#[derive(Debug)]
-enum Foo<'a> {
-    Str(&'a str),
-}
diff --git a/src/tools/clippy/tests/ui/needless_borrow.rs b/src/tools/clippy/tests/ui/needless_borrow.rs
index 1e281316c8a..059dc8ceac3 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.rs
+++ b/src/tools/clippy/tests/ui/needless_borrow.rs
@@ -18,7 +18,6 @@ fn main() {
     let vec = Vec::new();
     let vec_val = g(&vec); // should not error, because `&Vec<T>` derefs to `&[T]`
     h(&"foo"); // should not error, because the `&&str` is required, due to `&Trait`
-    if let Some(ref cake) = Some(&5) {}
     let garbl = match 42 {
         44 => &a,
         45 => {
@@ -43,19 +42,3 @@ trait Trait {}
 impl<'a> Trait for &'a str {}
 
 fn h(_: &dyn Trait) {}
-#[warn(clippy::needless_borrow)]
-#[allow(dead_code)]
-fn issue_1432() {
-    let mut v = Vec::<String>::new();
-    let _ = v.iter_mut().filter(|&ref a| a.is_empty());
-    let _ = v.iter().filter(|&ref a| a.is_empty());
-
-    let _ = v.iter().filter(|&a| a.is_empty());
-}
-
-#[allow(dead_code)]
-#[warn(clippy::needless_borrow)]
-#[derive(Debug)]
-enum Foo<'a> {
-    Str(&'a str),
-}
diff --git a/src/tools/clippy/tests/ui/needless_borrow.stderr b/src/tools/clippy/tests/ui/needless_borrow.stderr
index bea4b41b803..6eddf26db06 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.stderr
+++ b/src/tools/clippy/tests/ui/needless_borrow.stderr
@@ -6,23 +6,11 @@ LL |     let c = x(&&a);
    |
    = note: `-D clippy::needless-borrow` implied by `-D warnings`
 
-error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow.rs:21:17
-   |
-LL |     if let Some(ref cake) = Some(&5) {}
-   |                 ^^^^^^^^ help: change this to: `cake`
-
 error: this expression borrows a reference (`&i32`) that is immediately dereferenced by the compiler
-  --> $DIR/needless_borrow.rs:28:15
+  --> $DIR/needless_borrow.rs:27:15
    |
 LL |         46 => &&a,
    |               ^^^ help: change this to: `&a`
 
-error: this pattern creates a reference to a reference
-  --> $DIR/needless_borrow.rs:51:31
-   |
-LL |     let _ = v.iter().filter(|&ref a| a.is_empty());
-   |                               ^^^^^ help: change this to: `a`
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_borrow_pat.rs b/src/tools/clippy/tests/ui/needless_borrow_pat.rs
new file mode 100644
index 00000000000..f0926220755
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_borrow_pat.rs
@@ -0,0 +1,151 @@
+// edition:2018
+// FIXME: run-rustfix waiting on multi-span suggestions
+
+#![warn(clippy::needless_borrow)]
+#![allow(clippy::needless_borrowed_reference)]
+
+fn f1(_: &str) {}
+macro_rules! m1 {
+    ($e:expr) => {
+        f1($e);
+    };
+}
+macro_rules! m3 {
+    ($i:ident) => {
+        Some(ref $i)
+    };
+}
+macro_rules! if_chain {
+    (if $e:expr; $($rest:tt)*) => {
+        if $e {
+            if_chain!($($rest)*)
+        }
+    };
+
+    (if let $p:pat = $e:expr; $($rest:tt)*) => {
+        if let $p = $e {
+            if_chain!($($rest)*)
+        }
+    };
+
+    (then $b:block) => {
+        $b
+    };
+}
+
+#[allow(dead_code)]
+fn main() {
+    let x = String::new();
+
+    // Ok, reference to a String.
+    let _: &String = match Some(x.clone()) {
+        Some(ref x) => x,
+        None => return,
+    };
+
+    // Ok, reference to a &mut String
+    let _: &&mut String = match Some(&mut x.clone()) {
+        Some(ref x) => x,
+        None => return,
+    };
+
+    // Ok, the pattern is from a macro
+    let _: &String = match Some(&x) {
+        m3!(x) => x,
+        None => return,
+    };
+
+    // Err, reference to a &String
+    let _: &String = match Some(&x) {
+        Some(ref x) => x,
+        None => return,
+    };
+
+    // Err, reference to a &String.
+    let _: &String = match Some(&x) {
+        Some(ref x) => *x,
+        None => return,
+    };
+
+    // Err, reference to a &String
+    let _: &String = match Some(&x) {
+        Some(ref x) => {
+            f1(x);
+            f1(*x);
+            x
+        },
+        None => return,
+    };
+
+    // Err, reference to a &String
+    match Some(&x) {
+        Some(ref x) => m1!(x),
+        None => return,
+    };
+
+    // Err, reference to a &String
+    let _ = |&ref x: &&String| {
+        let _: &String = x;
+    };
+
+    // Err, reference to a &String
+    let (ref y,) = (&x,);
+    let _: &String = *y;
+
+    let y = &&x;
+    // Ok, different y
+    let _: &String = *y;
+
+    let x = (0, 0);
+    // Err, reference to a &u32. Don't suggest adding a reference to the field access.
+    let _: u32 = match Some(&x) {
+        Some(ref x) => x.0,
+        None => return,
+    };
+
+    enum E {
+        A(&'static u32),
+        B(&'static u32),
+    }
+    // Err, reference to &u32.
+    let _: &u32 = match E::A(&0) {
+        E::A(ref x) | E::B(ref x) => *x,
+    };
+
+    // Err, reference to &String.
+    if_chain! {
+        if true;
+        if let Some(ref x) = Some(&String::new());
+        then {
+            f1(x);
+        }
+    }
+}
+
+// Err, reference to a &String
+fn f2<'a>(&ref x: &&'a String) -> &'a String {
+    let _: &String = x;
+    *x
+}
+
+trait T1 {
+    // Err, reference to a &String
+    fn f(&ref x: &&String) {
+        let _: &String = x;
+    }
+}
+
+struct S;
+impl T1 for S {
+    // Err, reference to a &String
+    fn f(&ref x: &&String) {
+        let _: &String = *x;
+    }
+}
+
+// Ok - used to error due to rustc bug
+#[allow(dead_code)]
+#[derive(Debug)]
+enum Foo<'a> {
+    Str(&'a str),
+}
diff --git a/src/tools/clippy/tests/ui/needless_borrow_pat.stderr b/src/tools/clippy/tests/ui/needless_borrow_pat.stderr
new file mode 100644
index 00000000000..32913d59f7a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_borrow_pat.stderr
@@ -0,0 +1,112 @@
+error: this pattern creates a reference to a reference
+  --> $DIR/needless_borrow_pat.rs:60:14
+   |
+LL |         Some(ref x) => x,
+   |              ^^^^^ help: try this: `x`
+   |
+   = note: `-D clippy::needless-borrow` implied by `-D warnings`
+
+error: this pattern creates a reference to a reference
+  --> $DIR/needless_borrow_pat.rs:66:14
+   |
+LL |         Some(ref x) => *x,
+   |              ^^^^^
+   |
+help: try this
+   |
+LL |         Some(x) => x,
+   |              ^     ^
+
+error: this pattern creates a reference to a reference
+  --> $DIR/needless_borrow_pat.rs:72:14
+   |
+LL |         Some(ref x) => {
+   |              ^^^^^
+   |
+help: try this
+   |
+LL |         Some(x) => {
+LL |             f1(x);
+LL |             f1(x);
+   |
+
+error: this pattern creates a reference to a reference
+  --> $DIR/needless_borrow_pat.rs:82:14
+   |
+LL |         Some(ref x) => m1!(x),
+   |              ^^^^^ help: try this: `x`
+
+error: this pattern creates a reference to a reference
+  --> $DIR/needless_borrow_pat.rs:87:15
+   |
+LL |     let _ = |&ref x: &&String| {
+   |               ^^^^^ help: try this: `x`
+
+error: this pattern creates a reference to a reference
+  --> $DIR/needless_borrow_pat.rs:92:10
+   |
+LL |     let (ref y,) = (&x,);
+   |          ^^^^^
+   |
+help: try this
+   |
+LL |     let (y,) = (&x,);
+LL |     let _: &String = y;
+   |
+
+error: this pattern creates a reference to a reference
+  --> $DIR/needless_borrow_pat.rs:102:14
+   |
+LL |         Some(ref x) => x.0,
+   |              ^^^^^ help: try this: `x`
+
+error: this pattern creates a reference to a reference
+  --> $DIR/needless_borrow_pat.rs:112:14
+   |
+LL |         E::A(ref x) | E::B(ref x) => *x,
+   |              ^^^^^         ^^^^^
+   |
+help: try this
+   |
+LL |         E::A(x) | E::B(x) => x,
+   |              ^         ^     ^
+
+error: this pattern creates a reference to a reference
+  --> $DIR/needless_borrow_pat.rs:118:21
+   |
+LL |         if let Some(ref x) = Some(&String::new());
+   |                     ^^^^^ help: try this: `x`
+
+error: this pattern creates a reference to a reference
+  --> $DIR/needless_borrow_pat.rs:126:12
+   |
+LL | fn f2<'a>(&ref x: &&'a String) -> &'a String {
+   |            ^^^^^
+   |
+help: try this
+   |
+LL | fn f2<'a>(&x: &&'a String) -> &'a String {
+LL |     let _: &String = x;
+LL |     x
+   |
+
+error: this pattern creates a reference to a reference
+  --> $DIR/needless_borrow_pat.rs:133:11
+   |
+LL |     fn f(&ref x: &&String) {
+   |           ^^^^^ help: try this: `x`
+
+error: this pattern creates a reference to a reference
+  --> $DIR/needless_borrow_pat.rs:141:11
+   |
+LL |     fn f(&ref x: &&String) {
+   |           ^^^^^
+   |
+help: try this
+   |
+LL |     fn f(&x: &&String) {
+LL |         let _: &String = x;
+   |
+
+error: aborting due to 12 previous errors
+
diff --git a/src/tools/clippy/tests/ui/needless_collect_indirect.rs b/src/tools/clippy/tests/ui/needless_collect_indirect.rs
index 2458bf1e490..2c94235b8f5 100644
--- a/src/tools/clippy/tests/ui/needless_collect_indirect.rs
+++ b/src/tools/clippy/tests/ui/needless_collect_indirect.rs
@@ -1,4 +1,4 @@
-use std::collections::{BinaryHeap, HashMap, LinkedList, VecDeque};
+use std::collections::{BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
 
 fn main() {
     let sample = [1; 5];
@@ -75,3 +75,9 @@ mod issue7110 {
         buffer.len()
     }
 }
+
+fn allow_test() {
+    #[allow(clippy::needless_collect)]
+    let v = [1].iter().collect::<Vec<_>>();
+    v.into_iter().collect::<HashSet<_>>();
+}
diff --git a/src/tools/clippy/tests/ui/no_effect.rs b/src/tools/clippy/tests/ui/no_effect.rs
index 8fbfcb79860..7ec845adfaa 100644
--- a/src/tools/clippy/tests/ui/no_effect.rs
+++ b/src/tools/clippy/tests/ui/no_effect.rs
@@ -91,6 +91,9 @@ fn main() {
     let s: String = "foo".into();
     FooString { s: s };
 
+    #[allow(clippy::no_effect)]
+    0;
+
     // Do not warn
     get_number();
     unsafe { unsafe_fn() };
diff --git a/src/tools/clippy/tests/ui/ref_binding_to_reference.rs b/src/tools/clippy/tests/ui/ref_binding_to_reference.rs
new file mode 100644
index 00000000000..c7235e1c221
--- /dev/null
+++ b/src/tools/clippy/tests/ui/ref_binding_to_reference.rs
@@ -0,0 +1,76 @@
+// edition:2018
+// FIXME: run-rustfix waiting on multi-span suggestions
+
+#![warn(clippy::ref_binding_to_reference)]
+#![allow(clippy::needless_borrowed_reference)]
+
+fn f1(_: &str) {}
+macro_rules! m2 {
+    ($e:expr) => {
+        f1(*$e);
+    };
+}
+macro_rules! m3 {
+    ($i:ident) => {
+        Some(ref $i)
+    };
+}
+
+#[allow(dead_code)]
+fn main() {
+    let x = String::new();
+
+    // Ok, the pattern is from a macro
+    let _: &&String = match Some(&x) {
+        m3!(x) => x,
+        None => return,
+    };
+
+    // Err, reference to a &String
+    let _: &&String = match Some(&x) {
+        Some(ref x) => x,
+        None => return,
+    };
+
+    // Err, reference to a &String
+    let _: &&String = match Some(&x) {
+        Some(ref x) => {
+            f1(x);
+            f1(*x);
+            x
+        },
+        None => return,
+    };
+
+    // Err, reference to a &String
+    match Some(&x) {
+        Some(ref x) => m2!(x),
+        None => return,
+    }
+
+    // Err, reference to a &String
+    let _ = |&ref x: &&String| {
+        let _: &&String = x;
+    };
+}
+
+// Err, reference to a &String
+fn f2<'a>(&ref x: &&'a String) -> &'a String {
+    let _: &&String = x;
+    *x
+}
+
+trait T1 {
+    // Err, reference to a &String
+    fn f(&ref x: &&String) {
+        let _: &&String = x;
+    }
+}
+
+struct S;
+impl T1 for S {
+    // Err, reference to a &String
+    fn f(&ref x: &&String) {
+        let _: &&String = x;
+    }
+}
diff --git a/src/tools/clippy/tests/ui/ref_binding_to_reference.stderr b/src/tools/clippy/tests/ui/ref_binding_to_reference.stderr
new file mode 100644
index 00000000000..00aeff4fefa
--- /dev/null
+++ b/src/tools/clippy/tests/ui/ref_binding_to_reference.stderr
@@ -0,0 +1,88 @@
+error: this pattern creates a reference to a reference
+  --> $DIR/ref_binding_to_reference.rs:31:14
+   |
+LL |         Some(ref x) => x,
+   |              ^^^^^
+   |
+   = note: `-D clippy::ref-binding-to-reference` implied by `-D warnings`
+help: try this
+   |
+LL |         Some(x) => &x,
+   |              ^     ^^
+
+error: this pattern creates a reference to a reference
+  --> $DIR/ref_binding_to_reference.rs:37:14
+   |
+LL |         Some(ref x) => {
+   |              ^^^^^
+   |
+help: try this
+   |
+LL |         Some(x) => {
+LL |             f1(x);
+LL |             f1(x);
+LL |             &x
+   |
+
+error: this pattern creates a reference to a reference
+  --> $DIR/ref_binding_to_reference.rs:47:14
+   |
+LL |         Some(ref x) => m2!(x),
+   |              ^^^^^
+   |
+help: try this
+   |
+LL |         Some(x) => m2!(&x),
+   |              ^         ^^
+
+error: this pattern creates a reference to a reference
+  --> $DIR/ref_binding_to_reference.rs:52:15
+   |
+LL |     let _ = |&ref x: &&String| {
+   |               ^^^^^
+   |
+help: try this
+   |
+LL |     let _ = |&x: &&String| {
+LL |         let _: &&String = &x;
+   |
+
+error: this pattern creates a reference to a reference
+  --> $DIR/ref_binding_to_reference.rs:58:12
+   |
+LL | fn f2<'a>(&ref x: &&'a String) -> &'a String {
+   |            ^^^^^
+   |
+help: try this
+   |
+LL | fn f2<'a>(&x: &&'a String) -> &'a String {
+LL |     let _: &&String = &x;
+LL |     x
+   |
+
+error: this pattern creates a reference to a reference
+  --> $DIR/ref_binding_to_reference.rs:65:11
+   |
+LL |     fn f(&ref x: &&String) {
+   |           ^^^^^
+   |
+help: try this
+   |
+LL |     fn f(&x: &&String) {
+LL |         let _: &&String = &x;
+   |
+
+error: this pattern creates a reference to a reference
+  --> $DIR/ref_binding_to_reference.rs:73:11
+   |
+LL |     fn f(&ref x: &&String) {
+   |           ^^^^^
+   |
+help: try this
+   |
+LL |     fn f(&x: &&String) {
+LL |         let _: &&String = &x;
+   |
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui/similar_names.rs b/src/tools/clippy/tests/ui/similar_names.rs
index 5981980988b..2b1bc1f4859 100644
--- a/src/tools/clippy/tests/ui/similar_names.rs
+++ b/src/tools/clippy/tests/ui/similar_names.rs
@@ -72,6 +72,10 @@ fn main() {
     let rx1: i32;
     let tx_cake: i32;
     let rx_cake: i32;
+
+    // names often used in win32 code (for example WindowProc)
+    let wparam: i32;
+    let lparam: i32;
 }
 
 fn foo() {
diff --git a/src/tools/clippy/tests/ui/similar_names.stderr b/src/tools/clippy/tests/ui/similar_names.stderr
index 0256f126a94..a7eb2be0778 100644
--- a/src/tools/clippy/tests/ui/similar_names.stderr
+++ b/src/tools/clippy/tests/ui/similar_names.stderr
@@ -92,13 +92,13 @@ LL |     let parsee: i32;
    |         ^^^^^^
 
 error: binding's name is too similar to existing binding
-  --> $DIR/similar_names.rs:81:16
+  --> $DIR/similar_names.rs:85:16
    |
 LL |         bpple: sprang,
    |                ^^^^^^
    |
 note: existing binding defined here
-  --> $DIR/similar_names.rs:80:16
+  --> $DIR/similar_names.rs:84:16
    |
 LL |         apple: spring,
    |                ^^^^^^
diff --git a/src/tools/clippy/tests/ui/single_char_pattern.fixed b/src/tools/clippy/tests/ui/single_char_pattern.fixed
index fcbe9af9f56..1abd2b7883d 100644
--- a/src/tools/clippy/tests/ui/single_char_pattern.fixed
+++ b/src/tools/clippy/tests/ui/single_char_pattern.fixed
@@ -25,8 +25,8 @@ fn main() {
     x.rsplit('x');
     x.split_terminator('x');
     x.rsplit_terminator('x');
-    x.splitn(0, 'x');
-    x.rsplitn(0, 'x');
+    x.splitn(2, 'x');
+    x.rsplitn(2, 'x');
     x.matches('x');
     x.rmatches('x');
     x.match_indices('x');
diff --git a/src/tools/clippy/tests/ui/single_char_pattern.rs b/src/tools/clippy/tests/ui/single_char_pattern.rs
index b8bc20f4070..e662bf34be2 100644
--- a/src/tools/clippy/tests/ui/single_char_pattern.rs
+++ b/src/tools/clippy/tests/ui/single_char_pattern.rs
@@ -25,8 +25,8 @@ fn main() {
     x.rsplit("x");
     x.split_terminator("x");
     x.rsplit_terminator("x");
-    x.splitn(0, "x");
-    x.rsplitn(0, "x");
+    x.splitn(2, "x");
+    x.rsplitn(2, "x");
     x.matches("x");
     x.rmatches("x");
     x.match_indices("x");
diff --git a/src/tools/clippy/tests/ui/single_char_pattern.stderr b/src/tools/clippy/tests/ui/single_char_pattern.stderr
index 6d94d8a34e3..22d4b2d460f 100644
--- a/src/tools/clippy/tests/ui/single_char_pattern.stderr
+++ b/src/tools/clippy/tests/ui/single_char_pattern.stderr
@@ -75,13 +75,13 @@ LL |     x.rsplit_terminator("x");
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:28:17
    |
-LL |     x.splitn(0, "x");
+LL |     x.splitn(2, "x");
    |                 ^^^ help: try using a `char` instead: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:29:18
    |
-LL |     x.rsplitn(0, "x");
+LL |     x.rsplitn(2, "x");
    |                  ^^^ help: try using a `char` instead: `'x'`
 
 error: single-character string constant used as pattern
diff --git a/src/tools/clippy/tests/ui/suspicious_splitn.rs b/src/tools/clippy/tests/ui/suspicious_splitn.rs
new file mode 100644
index 00000000000..a21d94cf20b
--- /dev/null
+++ b/src/tools/clippy/tests/ui/suspicious_splitn.rs
@@ -0,0 +1,20 @@
+#![warn(clippy::suspicious_splitn)]
+
+fn main() {
+    let _ = "a,b,c".splitn(3, ',');
+    let _ = [0, 1, 2, 1, 3].splitn(3, |&x| x == 1);
+    let _ = "".splitn(0, ',');
+    let _ = [].splitn(0, |&x: &u32| x == 1);
+
+    let _ = "a,b".splitn(0, ',');
+    let _ = "a,b".rsplitn(0, ',');
+    let _ = "a,b".splitn(1, ',');
+    let _ = [0, 1, 2].splitn(0, |&x| x == 1);
+    let _ = [0, 1, 2].splitn_mut(0, |&x| x == 1);
+    let _ = [0, 1, 2].splitn(1, |&x| x == 1);
+    let _ = [0, 1, 2].rsplitn_mut(1, |&x| x == 1);
+
+    const X: usize = 0;
+    let _ = "a,b".splitn(X + 1, ',');
+    let _ = "a,b".splitn(X, ',');
+}
diff --git a/src/tools/clippy/tests/ui/suspicious_splitn.stderr b/src/tools/clippy/tests/ui/suspicious_splitn.stderr
new file mode 100644
index 00000000000..b6220ae2393
--- /dev/null
+++ b/src/tools/clippy/tests/ui/suspicious_splitn.stderr
@@ -0,0 +1,75 @@
+error: `splitn` called with `0` splits
+  --> $DIR/suspicious_splitn.rs:9:13
+   |
+LL |     let _ = "a,b".splitn(0, ',');
+   |             ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::suspicious-splitn` implied by `-D warnings`
+   = note: the resulting iterator will always return `None`
+
+error: `rsplitn` called with `0` splits
+  --> $DIR/suspicious_splitn.rs:10:13
+   |
+LL |     let _ = "a,b".rsplitn(0, ',');
+   |             ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the resulting iterator will always return `None`
+
+error: `splitn` called with `1` split
+  --> $DIR/suspicious_splitn.rs:11:13
+   |
+LL |     let _ = "a,b".splitn(1, ',');
+   |             ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the resulting iterator will always return the entire string followed by `None`
+
+error: `splitn` called with `0` splits
+  --> $DIR/suspicious_splitn.rs:12:13
+   |
+LL |     let _ = [0, 1, 2].splitn(0, |&x| x == 1);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the resulting iterator will always return `None`
+
+error: `splitn_mut` called with `0` splits
+  --> $DIR/suspicious_splitn.rs:13:13
+   |
+LL |     let _ = [0, 1, 2].splitn_mut(0, |&x| x == 1);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the resulting iterator will always return `None`
+
+error: `splitn` called with `1` split
+  --> $DIR/suspicious_splitn.rs:14:13
+   |
+LL |     let _ = [0, 1, 2].splitn(1, |&x| x == 1);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the resulting iterator will always return the entire slice followed by `None`
+
+error: `rsplitn_mut` called with `1` split
+  --> $DIR/suspicious_splitn.rs:15:13
+   |
+LL |     let _ = [0, 1, 2].rsplitn_mut(1, |&x| x == 1);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the resulting iterator will always return the entire slice followed by `None`
+
+error: `splitn` called with `1` split
+  --> $DIR/suspicious_splitn.rs:18:13
+   |
+LL |     let _ = "a,b".splitn(X + 1, ',');
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the resulting iterator will always return the entire string followed by `None`
+
+error: `splitn` called with `0` splits
+  --> $DIR/suspicious_splitn.rs:19:13
+   |
+LL |     let _ = "a,b".splitn(X, ',');
+   |             ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the resulting iterator will always return `None`
+
+error: aborting due to 9 previous errors
+
diff --git a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr
index ccc3cdb2b74..2b0005bbff1 100644
--- a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr
+++ b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr
@@ -89,12 +89,6 @@ LL |     fn trait_method(&self, _foo: &Foo);
    |                                  ^^^^ help: consider passing by value instead: `Foo`
 
 error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
-  --> $DIR/trivially_copy_pass_by_ref.rs:80:37
-   |
-LL |     fn trait_method2(&self, _color: &Color);
-   |                                     ^^^^^^ help: consider passing by value instead: `Color`
-
-error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
   --> $DIR/trivially_copy_pass_by_ref.rs:108:21
    |
 LL |     fn foo_never(x: &i32) {
@@ -106,5 +100,5 @@ error: this argument (N byte) is passed by reference, but would be more efficien
 LL |     fn foo(x: &i32) {
    |               ^^^^ help: consider passing by value instead: `i32`
 
-error: aborting due to 17 previous errors
+error: aborting due to 16 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_wraps.rs b/src/tools/clippy/tests/ui/unnecessary_wraps.rs
index 54f22e3ee6a..63648ef5826 100644
--- a/src/tools/clippy/tests/ui/unnecessary_wraps.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_wraps.rs
@@ -65,7 +65,7 @@ fn func10() -> Option<()> {
     unimplemented!()
 }
 
-struct A;
+pub struct A;
 
 impl A {
     // should not be linted
diff --git a/src/tools/clippy/tests/ui/unseparated_prefix_literals.fixed b/src/tools/clippy/tests/ui/unseparated_prefix_literals.fixed
index 3c422cc4fee..f0c2ba7ccdf 100644
--- a/src/tools/clippy/tests/ui/unseparated_prefix_literals.fixed
+++ b/src/tools/clippy/tests/ui/unseparated_prefix_literals.fixed
@@ -1,10 +1,11 @@
 // run-rustfix
+// aux-build:proc_macro_derive.rs
 
 #![warn(clippy::unseparated_literal_suffix)]
 #![allow(dead_code)]
 
 #[macro_use]
-extern crate clippy_mini_macro_test;
+extern crate proc_macro_derive;
 
 // Test for proc-macro attribute
 #[derive(ClippyMiniMacroTest)]
diff --git a/src/tools/clippy/tests/ui/unseparated_prefix_literals.rs b/src/tools/clippy/tests/ui/unseparated_prefix_literals.rs
index 09608661e0e..f44880b4147 100644
--- a/src/tools/clippy/tests/ui/unseparated_prefix_literals.rs
+++ b/src/tools/clippy/tests/ui/unseparated_prefix_literals.rs
@@ -1,10 +1,11 @@
 // run-rustfix
+// aux-build:proc_macro_derive.rs
 
 #![warn(clippy::unseparated_literal_suffix)]
 #![allow(dead_code)]
 
 #[macro_use]
-extern crate clippy_mini_macro_test;
+extern crate proc_macro_derive;
 
 // Test for proc-macro attribute
 #[derive(ClippyMiniMacroTest)]
diff --git a/src/tools/clippy/tests/ui/unseparated_prefix_literals.stderr b/src/tools/clippy/tests/ui/unseparated_prefix_literals.stderr
index a0c0be7a9d1..ab2f75e0c56 100644
--- a/src/tools/clippy/tests/ui/unseparated_prefix_literals.stderr
+++ b/src/tools/clippy/tests/ui/unseparated_prefix_literals.stderr
@@ -1,5 +1,5 @@
 error: integer type suffix should be separated by an underscore
-  --> $DIR/unseparated_prefix_literals.rs:23:18
+  --> $DIR/unseparated_prefix_literals.rs:24:18
    |
 LL |     let _fail1 = 1234i32;
    |                  ^^^^^^^ help: add an underscore: `1234_i32`
@@ -7,43 +7,43 @@ LL |     let _fail1 = 1234i32;
    = note: `-D clippy::unseparated-literal-suffix` implied by `-D warnings`
 
 error: integer type suffix should be separated by an underscore
-  --> $DIR/unseparated_prefix_literals.rs:24:18
+  --> $DIR/unseparated_prefix_literals.rs:25:18
    |
 LL |     let _fail2 = 1234u32;
    |                  ^^^^^^^ help: add an underscore: `1234_u32`
 
 error: integer type suffix should be separated by an underscore
-  --> $DIR/unseparated_prefix_literals.rs:25:18
+  --> $DIR/unseparated_prefix_literals.rs:26:18
    |
 LL |     let _fail3 = 1234isize;
    |                  ^^^^^^^^^ help: add an underscore: `1234_isize`
 
 error: integer type suffix should be separated by an underscore
-  --> $DIR/unseparated_prefix_literals.rs:26:18
+  --> $DIR/unseparated_prefix_literals.rs:27:18
    |
 LL |     let _fail4 = 1234usize;
    |                  ^^^^^^^^^ help: add an underscore: `1234_usize`
 
 error: integer type suffix should be separated by an underscore
-  --> $DIR/unseparated_prefix_literals.rs:27:18
+  --> $DIR/unseparated_prefix_literals.rs:28:18
    |
 LL |     let _fail5 = 0x123isize;
    |                  ^^^^^^^^^^ help: add an underscore: `0x123_isize`
 
 error: float type suffix should be separated by an underscore
-  --> $DIR/unseparated_prefix_literals.rs:31:19
+  --> $DIR/unseparated_prefix_literals.rs:32:19
    |
 LL |     let _failf1 = 1.5f32;
    |                   ^^^^^^ help: add an underscore: `1.5_f32`
 
 error: float type suffix should be separated by an underscore
-  --> $DIR/unseparated_prefix_literals.rs:32:19
+  --> $DIR/unseparated_prefix_literals.rs:33:19
    |
 LL |     let _failf2 = 1f32;
    |                   ^^^^ help: add an underscore: `1_f32`
 
 error: integer type suffix should be separated by an underscore
-  --> $DIR/unseparated_prefix_literals.rs:15:9
+  --> $DIR/unseparated_prefix_literals.rs:16:9
    |
 LL |         42usize
    |         ^^^^^^^ help: add an underscore: `42_usize`
@@ -54,7 +54,7 @@ LL |     let _ = lit_from_macro!();
    = note: this error originates in the macro `lit_from_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: integer type suffix should be separated by an underscore
-  --> $DIR/unseparated_prefix_literals.rs:40:16
+  --> $DIR/unseparated_prefix_literals.rs:41:16
    |
 LL |     assert_eq!(4897u32, 32223);
    |                ^^^^^^^ help: add an underscore: `4897_u32`
diff --git a/src/tools/clippy/tests/ui/wrong_self_convention.rs b/src/tools/clippy/tests/ui/wrong_self_convention.rs
index cdfbdb8b0db..151dd0c27d5 100644
--- a/src/tools/clippy/tests/ui/wrong_self_convention.rs
+++ b/src/tools/clippy/tests/ui/wrong_self_convention.rs
@@ -1,6 +1,5 @@
 // edition:2018
 #![warn(clippy::wrong_self_convention)]
-#![warn(clippy::wrong_pub_self_convention)]
 #![allow(dead_code)]
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/wrong_self_convention.stderr b/src/tools/clippy/tests/ui/wrong_self_convention.stderr
index 29f5ba82695..ce23317abf6 100644
--- a/src/tools/clippy/tests/ui/wrong_self_convention.stderr
+++ b/src/tools/clippy/tests/ui/wrong_self_convention.stderr
@@ -1,5 +1,5 @@
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:18:17
+  --> $DIR/wrong_self_convention.rs:17:17
    |
 LL |     fn from_i32(self) {}
    |                 ^^^^
@@ -8,7 +8,7 @@ LL |     fn from_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:24:21
+  --> $DIR/wrong_self_convention.rs:23:21
    |
 LL |     pub fn from_i64(self) {}
    |                     ^^^^
@@ -16,7 +16,7 @@ LL |     pub fn from_i64(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
-  --> $DIR/wrong_self_convention.rs:36:15
+  --> $DIR/wrong_self_convention.rs:35:15
    |
 LL |     fn as_i32(self) {}
    |               ^^^^
@@ -24,7 +24,7 @@ LL |     fn as_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `into_*` usually take `self` by value
-  --> $DIR/wrong_self_convention.rs:38:17
+  --> $DIR/wrong_self_convention.rs:37:17
    |
 LL |     fn into_i32(&self) {}
    |                 ^^^^^
@@ -32,7 +32,7 @@ LL |     fn into_i32(&self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `is_*` usually take `self` by reference or no `self`
-  --> $DIR/wrong_self_convention.rs:40:15
+  --> $DIR/wrong_self_convention.rs:39:15
    |
 LL |     fn is_i32(self) {}
    |               ^^^^
@@ -40,7 +40,7 @@ LL |     fn is_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
-  --> $DIR/wrong_self_convention.rs:42:15
+  --> $DIR/wrong_self_convention.rs:41:15
    |
 LL |     fn to_i32(self) {}
    |               ^^^^
@@ -48,7 +48,7 @@ LL |     fn to_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:44:17
+  --> $DIR/wrong_self_convention.rs:43:17
    |
 LL |     fn from_i32(self) {}
    |                 ^^^^
@@ -56,7 +56,7 @@ LL |     fn from_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
-  --> $DIR/wrong_self_convention.rs:46:19
+  --> $DIR/wrong_self_convention.rs:45:19
    |
 LL |     pub fn as_i64(self) {}
    |                   ^^^^
@@ -64,7 +64,7 @@ LL |     pub fn as_i64(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `into_*` usually take `self` by value
-  --> $DIR/wrong_self_convention.rs:47:21
+  --> $DIR/wrong_self_convention.rs:46:21
    |
 LL |     pub fn into_i64(&self) {}
    |                     ^^^^^
@@ -72,7 +72,7 @@ LL |     pub fn into_i64(&self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `is_*` usually take `self` by reference or no `self`
-  --> $DIR/wrong_self_convention.rs:48:19
+  --> $DIR/wrong_self_convention.rs:47:19
    |
 LL |     pub fn is_i64(self) {}
    |                   ^^^^
@@ -80,7 +80,7 @@ LL |     pub fn is_i64(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
-  --> $DIR/wrong_self_convention.rs:49:19
+  --> $DIR/wrong_self_convention.rs:48:19
    |
 LL |     pub fn to_i64(self) {}
    |                   ^^^^
@@ -88,7 +88,7 @@ LL |     pub fn to_i64(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:50:21
+  --> $DIR/wrong_self_convention.rs:49:21
    |
 LL |     pub fn from_i64(self) {}
    |                     ^^^^
@@ -96,7 +96,7 @@ LL |     pub fn from_i64(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
-  --> $DIR/wrong_self_convention.rs:95:19
+  --> $DIR/wrong_self_convention.rs:94:19
    |
 LL |         fn as_i32(self) {}
    |                   ^^^^
@@ -104,7 +104,7 @@ LL |         fn as_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `into_*` usually take `self` by value
-  --> $DIR/wrong_self_convention.rs:98:25
+  --> $DIR/wrong_self_convention.rs:97:25
    |
 LL |         fn into_i32_ref(&self) {}
    |                         ^^^^^
@@ -112,7 +112,7 @@ LL |         fn into_i32_ref(&self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `is_*` usually take `self` by reference or no `self`
-  --> $DIR/wrong_self_convention.rs:100:19
+  --> $DIR/wrong_self_convention.rs:99:19
    |
 LL |         fn is_i32(self) {}
    |                   ^^^^
@@ -120,7 +120,7 @@ LL |         fn is_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:104:21
+  --> $DIR/wrong_self_convention.rs:103:21
    |
 LL |         fn from_i32(self) {}
    |                     ^^^^
@@ -128,7 +128,7 @@ LL |         fn from_i32(self) {}
    = help: consider choosing a less ambiguous name
 
 error: methods called `as_*` usually take `self` by reference or `self` by mutable reference
-  --> $DIR/wrong_self_convention.rs:119:19
+  --> $DIR/wrong_self_convention.rs:118:19
    |
 LL |         fn as_i32(self);
    |                   ^^^^
@@ -136,7 +136,7 @@ LL |         fn as_i32(self);
    = help: consider choosing a less ambiguous name
 
 error: methods called `into_*` usually take `self` by value
-  --> $DIR/wrong_self_convention.rs:122:25
+  --> $DIR/wrong_self_convention.rs:121:25
    |
 LL |         fn into_i32_ref(&self);
    |                         ^^^^^
@@ -144,7 +144,7 @@ LL |         fn into_i32_ref(&self);
    = help: consider choosing a less ambiguous name
 
 error: methods called `is_*` usually take `self` by reference or no `self`
-  --> $DIR/wrong_self_convention.rs:124:19
+  --> $DIR/wrong_self_convention.rs:123:19
    |
 LL |         fn is_i32(self);
    |                   ^^^^
@@ -152,7 +152,7 @@ LL |         fn is_i32(self);
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:128:21
+  --> $DIR/wrong_self_convention.rs:127:21
    |
 LL |         fn from_i32(self);
    |                     ^^^^
@@ -160,7 +160,7 @@ LL |         fn from_i32(self);
    = help: consider choosing a less ambiguous name
 
 error: methods called `into_*` usually take `self` by value
-  --> $DIR/wrong_self_convention.rs:146:25
+  --> $DIR/wrong_self_convention.rs:145:25
    |
 LL |         fn into_i32_ref(&self);
    |                         ^^^^^
@@ -168,7 +168,7 @@ LL |         fn into_i32_ref(&self);
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention.rs:152:21
+  --> $DIR/wrong_self_convention.rs:151:21
    |
 LL |         fn from_i32(self);
    |                     ^^^^
@@ -176,7 +176,7 @@ LL |         fn from_i32(self);
    = help: consider choosing a less ambiguous name
 
 error: methods with the following characteristics: (`to_*` and `self` type is `Copy`) usually take `self` by value
-  --> $DIR/wrong_self_convention.rs:176:22
+  --> $DIR/wrong_self_convention.rs:175:22
    |
 LL |         fn to_u64_v2(&self) -> u64 {
    |                      ^^^^^
@@ -184,7 +184,7 @@ LL |         fn to_u64_v2(&self) -> u64 {
    = help: consider choosing a less ambiguous name
 
 error: methods with the following characteristics: (`to_*` and `self` type is not `Copy`) usually take `self` by reference
-  --> $DIR/wrong_self_convention.rs:185:19
+  --> $DIR/wrong_self_convention.rs:184:19
    |
 LL |         fn to_u64(self) -> u64 {
    |                   ^^^^
diff --git a/src/tools/clippy/tests/ui/wrong_self_convention2.rs b/src/tools/clippy/tests/ui/wrong_self_convention2.rs
index 3a72174d03d..501bc1e6a85 100644
--- a/src/tools/clippy/tests/ui/wrong_self_convention2.rs
+++ b/src/tools/clippy/tests/ui/wrong_self_convention2.rs
@@ -1,6 +1,5 @@
 // edition:2018
 #![warn(clippy::wrong_self_convention)]
-#![warn(clippy::wrong_pub_self_convention)]
 #![allow(dead_code)]
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/wrong_self_convention2.stderr b/src/tools/clippy/tests/ui/wrong_self_convention2.stderr
index d2d74ce099e..0e0d066d656 100644
--- a/src/tools/clippy/tests/ui/wrong_self_convention2.stderr
+++ b/src/tools/clippy/tests/ui/wrong_self_convention2.stderr
@@ -1,5 +1,5 @@
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention2.rs:56:29
+  --> $DIR/wrong_self_convention2.rs:55:29
    |
 LL |         pub fn from_be_self(self) -> Self {
    |                             ^^^^
@@ -8,7 +8,7 @@ LL |         pub fn from_be_self(self) -> Self {
    = help: consider choosing a less ambiguous name
 
 error: methods called `from_*` usually take no `self`
-  --> $DIR/wrong_self_convention2.rs:65:25
+  --> $DIR/wrong_self_convention2.rs:64:25
    |
 LL |         fn from_be_self(self) -> Self;
    |                         ^^^^
diff --git a/src/tools/clippy/util/cov.sh b/src/tools/clippy/util/cov.sh
deleted file mode 100755
index 3f9a6b06f72..00000000000
--- a/src/tools/clippy/util/cov.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/bash
-
-# This run `kcov` on Clippy. The coverage report will be at
-# `./target/cov/index.html`.
-# `compile-test` is special. `kcov` does not work directly on it so these files
-# are compiled manually.
-
-tests=$(find tests/ -maxdepth 1 -name '*.rs' ! -name compile-test.rs -exec basename {} .rs \;)
-tmpdir=$(mktemp -d)
-
-cargo test --no-run --verbose
-
-for t in $tests; do
-  kcov \
-    --verify \
-    --include-path="$(pwd)/src,$(pwd)/clippy_lints/src" \
-    "$tmpdir/$t" \
-    cargo test --test "$t"
-done
-
-for t in ./tests/compile-fail/*.rs; do
-  kcov \
-    --verify \
-    --include-path="$(pwd)/src,$(pwd)/clippy_lints/src" \
-    "$tmpdir/compile-fail-$(basename "$t")" \
-    cargo run -- -L target/debug -L target/debug/deps -Z no-trans "$t"
-done
-
-for t in ./tests/run-pass/*.rs; do
-  kcov \
-    --verify \
-    --include-path="$(pwd)/src,$(pwd)/clippy_lints/src" \
-    "$tmpdir/run-pass-$(basename "$t")" \
-    cargo run -- -L target/debug -L target/debug/deps -Z no-trans "$t"
-done
-
-kcov --verify --merge target/cov "$tmpdir"/*
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index d53e19f2908..08ee8fc984d 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -664,6 +664,10 @@ fn make_test(config: &Config, testpaths: &TestPaths, inputs: &Stamp) -> Vec<test
                     ignore,
                     should_panic,
                     allow_fail: false,
+                    #[cfg(not(bootstrap))]
+                    compile_fail: false,
+                    #[cfg(not(bootstrap))]
+                    no_run: false,
                     test_type: test::TestType::Unknown,
                 },
                 testfn: make_test_closure(config, testpaths, revision),
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 54b079a3e86..931c822ffe2 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1835,6 +1835,7 @@ impl<'test> TestCx<'test> {
             || self.config.target.contains("nvptx")
             || self.is_vxworks_pure_static()
             || self.config.target.contains("sgx")
+            || self.config.target.contains("bpf")
         {
             // We primarily compile all auxiliary libraries as dynamic libraries
             // to avoid code size bloat and large binaries as much as possible
@@ -2675,12 +2676,11 @@ impl<'test> TestCx<'test> {
 
         let mut tested = 0;
         for _ in res.stdout.split('\n').filter(|s| s.starts_with("test ")).inspect(|s| {
-            let tmp: Vec<&str> = s.split(" - ").collect();
-            if tmp.len() == 2 {
-                let path = tmp[0].rsplit("test ").next().unwrap();
+            if let Some((left, right)) = s.split_once(" - ") {
+                let path = left.rsplit("test ").next().unwrap();
                 if let Some(ref mut v) = files.get_mut(&path.replace('\\', "/")) {
                     tested += 1;
-                    let mut iter = tmp[1].split("(line ");
+                    let mut iter = right.split("(line ");
                     iter.next();
                     let line = iter
                         .next()
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index 7dbd70948b8..37164c4e575 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -48,6 +48,8 @@ const ARCH_TABLE: &[(&str, &str)] = &[
     ("armv7s", "arm"),
     ("asmjs", "asmjs"),
     ("avr", "avr"),
+    ("bpfeb", "bpf"),
+    ("bpfel", "bpf"),
     ("hexagon", "hexagon"),
     ("i386", "x86"),
     ("i586", "x86"),
diff --git a/src/tools/jsondocck/Cargo.toml b/src/tools/jsondocck/Cargo.toml
index a6efc4c9a6b..b5f1554dbe4 100644
--- a/src/tools/jsondocck/Cargo.toml
+++ b/src/tools/jsondocck/Cargo.toml
@@ -8,8 +8,7 @@ edition = "2018"
 jsonpath_lib = "0.2"
 getopts = "0.2"
 regex = "1.4"
-lazy_static = "1.4"
-shlex = "0.1"
-serde = "1.0"
+shlex = "1.0"
 serde_json = "1.0"
 fs-err = "2.5.0"
+once_cell = "1.0"
diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs
index 216890d59ad..b8ea10f3d22 100644
--- a/src/tools/jsondocck/src/main.rs
+++ b/src/tools/jsondocck/src/main.rs
@@ -1,5 +1,5 @@
 use jsonpath_lib::select;
-use lazy_static::lazy_static;
+use once_cell::sync::Lazy;
 use regex::{Regex, RegexBuilder};
 use serde_json::Value;
 use std::borrow::Cow;
@@ -94,19 +94,19 @@ impl fmt::Display for CommandKind {
     }
 }
 
-lazy_static! {
-    static ref LINE_PATTERN: Regex = RegexBuilder::new(
+static LINE_PATTERN: Lazy<Regex> = Lazy::new(|| {
+    RegexBuilder::new(
         r#"
         \s(?P<invalid>!?)@(?P<negated>!?)
         (?P<cmd>[A-Za-z]+(?:-[A-Za-z]+)*)
         (?P<args>.*)$
-    "#
+    "#,
     )
     .ignore_whitespace(true)
     .unicode(true)
     .build()
-    .unwrap();
-}
+    .unwrap()
+});
 
 fn print_err(msg: &str, lineno: usize) {
     eprintln!("Invalid command: {} on line {}", msg, lineno)
diff --git a/src/tools/linkchecker/linkcheck.sh b/src/tools/linkchecker/linkcheck.sh
index b68053c76be..9eeebf444a4 100755
--- a/src/tools/linkchecker/linkcheck.sh
+++ b/src/tools/linkchecker/linkcheck.sh
@@ -85,11 +85,11 @@ fi
 if [ ! -e "linkchecker/main.rs" ] || [ "$iterative" = "0" ]
 then
     echo "Downloading linkchecker source..."
+    nightly_hash=$(rustc +nightly -Vv | grep commit-hash | cut -f2 -d" ")
+    url="https://raw.githubusercontent.com/rust-lang/rust"
     mkdir linkchecker
-    curl -o linkchecker/Cargo.toml \
-        https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/Cargo.toml
-    curl -o linkchecker/main.rs \
-        https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/main.rs
+    curl -o linkchecker/Cargo.toml ${url}/${nightly_hash}/src/tools/linkchecker/Cargo.toml
+    curl -o linkchecker/main.rs ${url}/${nightly_hash}/src/tools/linkchecker/main.rs
 fi
 
 echo "Building book \"$book_name\"..."
@@ -106,7 +106,7 @@ else
     check_path="linkcheck/$book_name"
 fi
 echo "Running linkchecker on \"$check_path\"..."
-cargo run --manifest-path=linkchecker/Cargo.toml -- "$check_path"
+cargo run --release --manifest-path=linkchecker/Cargo.toml -- "$check_path"
 
 if [ "$iterative" = "0" ]
 then
diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs
index 076b3653583..47960c3f6cc 100644
--- a/src/tools/linkchecker/main.rs
+++ b/src/tools/linkchecker/main.rs
@@ -463,7 +463,7 @@ fn maybe_redirect(source: &str) -> Option<String> {
     const REDIRECT: &str = "<p>Redirecting to <a href=";
 
     let mut lines = source.lines();
-    let redirect_line = lines.nth(6)?;
+    let redirect_line = lines.nth(7)?;
 
     redirect_line.find(REDIRECT).map(|i| {
         let rest = &redirect_line[(i + REDIRECT.len() + 1)..];
diff --git a/src/tools/miri b/src/tools/miri
-Subproject 453affaaa1762a065d2857970b8333017211208
+Subproject c8713c2f9fc1e28c90876b9ec9557d8c5729757
diff --git a/src/tools/rls b/src/tools/rls
-Subproject 9ed6f96f2ff85753c5a6ac290ee88ecb2831ab2
+Subproject 517e9d62c095a04fa497d6b6d3c63b31696a88b
diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer
-Subproject f4383981249d3f2964f2c667f3349f8ff15b77c
+Subproject 13da28cc2bc1b59f7af817eca36927a71edb023
diff --git a/src/tools/rustdoc-gui/tester.js b/src/tools/rustdoc-gui/tester.js
index 298fc7519fa..c55e014e834 100644
--- a/src/tools/rustdoc-gui/tester.js
+++ b/src/tools/rustdoc-gui/tester.js
@@ -63,6 +63,13 @@ async function main(argv) {
         // This is more convenient that setting fields one by one.
         options.parseArguments([
             "--no-screenshot",
+            // This option shows what puppeteer "code" is run
+            // "--debug",
+            // This option disable the headless mode, allowing you to see what's going on.
+            // "--no-headless",
+            // The text isn't rendered by default because of a lot of small differences
+            // between hosts.
+            // "--show-text",
             "--variable", "DOC_PATH", opts["doc_folder"],
         ]);
     } catch (error) {
diff --git a/triagebot.toml b/triagebot.toml
index 8b6157cd4aa..c97f63f1cfd 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -79,7 +79,7 @@ trigger_labels = [
     "regression-from-stable-to-stable",
     "regression-from-stable-to-beta",
     "regression-from-stable-to-nightly",
-    "I-unsound 💥",
+    "I-unsound",
 ]
 exclude_labels = [
     "P-*",