about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml1
-rw-r--r--Cargo.lock180
-rw-r--r--RELEASES.md16
-rw-r--r--compiler/rustc_ast/src/ast.rs4
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs2
-rw-r--r--compiler/rustc_ast/src/lib.rs2
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs3
-rw-r--r--compiler/rustc_ast/src/token.rs7
-rw-r--r--compiler/rustc_ast/src/visit.rs3
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs13
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs5
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs29
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs86
-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_ast_pretty/src/pprust/state.rs16
-rw-r--r--compiler/rustc_borrowck/Cargo.toml (renamed from compiler/rustc_mir/Cargo.toml)19
-rw-r--r--compiler/rustc_borrowck/src/borrow_set.rs (renamed from compiler/rustc_mir/src/borrow_check/borrow_set.rs)10
-rw-r--r--compiler/rustc_borrowck/src/borrowck_errors.rs (renamed from compiler/rustc_mir/src/util/borrowck_errors.rs)2
-rw-r--r--compiler/rustc_borrowck/src/constraint_generation.rs (renamed from compiler/rustc_mir/src/borrow_check/constraint_generation.rs)2
-rw-r--r--compiler/rustc_borrowck/src/constraints/graph.rs (renamed from compiler/rustc_mir/src/borrow_check/constraints/graph.rs)2
-rw-r--r--compiler/rustc_borrowck/src/constraints/mod.rs (renamed from compiler/rustc_mir/src/borrow_check/constraints/mod.rs)2
-rw-r--r--compiler/rustc_borrowck/src/consumers.rs (renamed from compiler/rustc_mir/src/borrow_check/consumers.rs)6
-rw-r--r--compiler/rustc_borrowck/src/dataflow.rs (renamed from compiler/rustc_mir/src/dataflow/impls/borrows.rs)113
-rw-r--r--compiler/rustc_borrowck/src/def_use.rs (renamed from compiler/rustc_mir/src/borrow_check/def_use.rs)0
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs (renamed from compiler/rustc_mir/src/borrow_check/diagnostics/bound_region_errors.rs)4
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs (renamed from compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs)47
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs (renamed from compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs)16
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/find_use.rs (renamed from compiler/rustc_mir/src/borrow_check/diagnostics/find_use.rs)2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs (renamed from compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs)10
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs (renamed from compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs)12
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs (renamed from compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs)6
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs (renamed from compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs)8
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs (renamed from compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs)10
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs (renamed from compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs)2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/var_name.rs (renamed from compiler/rustc_mir/src/borrow_check/diagnostics/var_name.rs)4
-rw-r--r--compiler/rustc_borrowck/src/facts.rs (renamed from compiler/rustc_mir/src/borrow_check/facts.rs)11
-rw-r--r--compiler/rustc_borrowck/src/invalidation.rs (renamed from compiler/rustc_mir/src/borrow_check/invalidation.rs)8
-rw-r--r--compiler/rustc_borrowck/src/lib.rs (renamed from compiler/rustc_mir/src/borrow_check/mod.rs)68
-rw-r--r--compiler/rustc_borrowck/src/location.rs (renamed from compiler/rustc_mir/src/borrow_check/location.rs)0
-rw-r--r--compiler/rustc_borrowck/src/member_constraints.rs (renamed from compiler/rustc_mir/src/borrow_check/member_constraints.rs)0
-rw-r--r--compiler/rustc_borrowck/src/nll.rs (renamed from compiler/rustc_mir/src/borrow_check/nll.rs)32
-rw-r--r--compiler/rustc_borrowck/src/path_utils.rs (renamed from compiler/rustc_mir/src/borrow_check/path_utils.rs)10
-rw-r--r--compiler/rustc_borrowck/src/place_ext.rs (renamed from compiler/rustc_mir/src/borrow_check/place_ext.rs)2
-rw-r--r--compiler/rustc_borrowck/src/places_conflict.rs (renamed from compiler/rustc_mir/src/borrow_check/places_conflict.rs)6
-rw-r--r--compiler/rustc_borrowck/src/prefixes.rs (renamed from compiler/rustc_mir/src/borrow_check/prefixes.rs)0
-rw-r--r--compiler/rustc_borrowck/src/region_infer/dump_mir.rs (renamed from compiler/rustc_mir/src/borrow_check/region_infer/dump_mir.rs)2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/graphviz.rs (renamed from compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs)2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs (renamed from compiler/rustc_mir/src/borrow_check/region_infer/mod.rs)36
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs (renamed from compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs)4
-rw-r--r--compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs (renamed from compiler/rustc_mir/src/borrow_check/region_infer/reverse_sccs.rs)4
-rw-r--r--compiler/rustc_borrowck/src/region_infer/values.rs (renamed from compiler/rustc_mir/src/borrow_check/region_infer/values.rs)0
-rw-r--r--compiler/rustc_borrowck/src/renumber.rs (renamed from compiler/rustc_mir/src/borrow_check/renumber.rs)0
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs (renamed from compiler/rustc_mir/src/borrow_check/type_check/canonical.rs)16
-rw-r--r--compiler/rustc_borrowck/src/type_check/constraint_conversion.rs (renamed from compiler/rustc_mir/src/borrow_check/type_check/constraint_conversion.rs)2
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs (renamed from compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs)11
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs (renamed from compiler/rustc_mir/src/borrow_check/type_check/input_output.rs)9
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs (renamed from compiler/rustc_mir/src/borrow_check/type_check/liveness/local_use_map.rs)4
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/mod.rs (renamed from compiler/rustc_mir/src/borrow_check/type_check/liveness/mod.rs)8
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/polonius.rs (renamed from compiler/rustc_mir/src/borrow_check/type_check/liveness/polonius.rs)7
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs (renamed from compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs)9
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs (renamed from compiler/rustc_mir/src/borrow_check/type_check/mod.rs)25
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs (renamed from compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs)13
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs (renamed from compiler/rustc_mir/src/borrow_check/universal_regions.rs)2
-rw-r--r--compiler/rustc_borrowck/src/used_muts.rs (renamed from compiler/rustc_mir/src/borrow_check/used_muts.rs)5
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs14
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/debug.rs20
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs16
-rwxr-xr-xcompiler/rustc_codegen_cranelift/scripts/filter_profile.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs20
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs13
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/src/value_and_place.rs24
-rw-r--r--compiler/rustc_codegen_llvm/Cargo.toml1
-rw-r--r--compiler/rustc_codegen_llvm/src/abi.rs16
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs25
-rw-r--r--compiler/rustc_codegen_llvm/src/common.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs81
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/type_of.rs12
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/constant.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/intrinsic.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs16
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs40
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/builder.rs10
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/consts.rs2
-rw-r--r--compiler/rustc_const_eval/Cargo.toml27
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs (renamed from compiler/rustc_mir/src/const_eval/error.rs)0
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs (renamed from compiler/rustc_mir/src/const_eval/eval_queries.rs)2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/fn_queries.rs (renamed from compiler/rustc_mir/src/const_eval/fn_queries.rs)32
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs (renamed from compiler/rustc_mir/src/const_eval/machine.rs)0
-rw-r--r--compiler/rustc_const_eval/src/const_eval/mod.rs (renamed from compiler/rustc_mir/src/const_eval/mod.rs)0
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs (renamed from compiler/rustc_mir/src/interpret/cast.rs)0
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs (renamed from compiler/rustc_mir/src/interpret/eval_context.rs)2
-rw-r--r--compiler/rustc_const_eval/src/interpret/intern.rs (renamed from compiler/rustc_mir/src/interpret/intern.rs)2
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs (renamed from compiler/rustc_mir/src/interpret/intrinsics.rs)26
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs (renamed from compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs)0
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs (renamed from compiler/rustc_mir/src/interpret/intrinsics/type_name.rs)0
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs (renamed from compiler/rustc_mir/src/interpret/machine.rs)0
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs (renamed from compiler/rustc_mir/src/interpret/memory.rs)4
-rw-r--r--compiler/rustc_const_eval/src/interpret/mod.rs (renamed from compiler/rustc_mir/src/interpret/mod.rs)0
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs (renamed from compiler/rustc_mir/src/interpret/operand.rs)12
-rw-r--r--compiler/rustc_const_eval/src/interpret/operator.rs (renamed from compiler/rustc_mir/src/interpret/operator.rs)0
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs (renamed from compiler/rustc_mir/src/interpret/place.rs)6
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs (renamed from compiler/rustc_mir/src/interpret/step.rs)13
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs (renamed from compiler/rustc_mir/src/interpret/terminator.rs)11
-rw-r--r--compiler/rustc_const_eval/src/interpret/traits.rs (renamed from compiler/rustc_mir/src/interpret/traits.rs)0
-rw-r--r--compiler/rustc_const_eval/src/interpret/util.rs (renamed from compiler/rustc_mir/src/interpret/util.rs)0
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs (renamed from compiler/rustc_mir/src/interpret/validity.rs)32
-rw-r--r--compiler/rustc_const_eval/src/interpret/visitor.rs (renamed from compiler/rustc_mir/src/interpret/visitor.rs)0
-rw-r--r--compiler/rustc_const_eval/src/lib.rs (renamed from compiler/rustc_mir/src/lib.rs)34
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs (renamed from compiler/rustc_mir/src/transform/check_consts/check.rs)28
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/mod.rs (renamed from compiler/rustc_mir/src/transform/check_consts/mod.rs)0
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs (renamed from compiler/rustc_mir/src/transform/check_consts/ops.rs)13
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs (renamed from compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs)10
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs (renamed from compiler/rustc_mir/src/transform/check_consts/qualifs.rs)44
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/resolver.rs (renamed from compiler/rustc_mir/src/transform/check_consts/resolver.rs)5
-rw-r--r--compiler/rustc_const_eval/src/transform/mod.rs5
-rw-r--r--compiler/rustc_const_eval/src/transform/promote_consts.rs (renamed from compiler/rustc_mir/src/transform/promote_consts.rs)5
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs (renamed from compiler/rustc_mir/src/transform/validate.rs)7
-rw-r--r--compiler/rustc_const_eval/src/util/aggregate.rs (renamed from compiler/rustc_mir/src/util/aggregate.rs)0
-rw-r--r--compiler/rustc_const_eval/src/util/alignment.rs (renamed from compiler/rustc_mir/src/util/alignment.rs)0
-rw-r--r--compiler/rustc_const_eval/src/util/collect_writes.rs (renamed from compiler/rustc_mir/src/util/collect_writes.rs)2
-rw-r--r--compiler/rustc_const_eval/src/util/find_self_call.rs (renamed from compiler/rustc_mir/src/util/find_self_call.rs)0
-rw-r--r--compiler/rustc_const_eval/src/util/mod.rs8
-rw-r--r--compiler/rustc_data_structures/src/graph/iterate/mod.rs54
-rw-r--r--compiler/rustc_data_structures/src/graph/iterate/tests.rs16
-rw-r--r--compiler/rustc_data_structures/src/graph/mod.rs2
-rw-r--r--compiler/rustc_data_structures/src/lib.rs4
-rw-r--r--compiler/rustc_data_structures/src/stable_hasher.rs6
-rw-r--r--compiler/rustc_driver/Cargo.toml2
-rw-r--r--compiler/rustc_driver/src/pretty.rs2
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs27
-rw-r--r--compiler/rustc_errors/src/diagnostic_builder.rs14
-rw-r--r--compiler/rustc_errors/src/lib.rs1
-rw-r--r--compiler/rustc_expand/src/base.rs32
-rw-r--r--compiler/rustc_expand/src/expand.rs15
-rw-r--r--compiler/rustc_expand/src/lib.rs2
-rw-r--r--compiler/rustc_expand/src/mbe/quoted.rs2
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs8
-rw-r--r--compiler/rustc_feature/src/accepted.rs1
-rw-r--r--compiler/rustc_feature/src/active.rs4
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs3
-rw-r--r--compiler/rustc_feature/src/lib.rs1
-rw-r--r--compiler/rustc_feature/src/removed.rs4
-rw-r--r--compiler/rustc_hir/src/def.rs5
-rw-r--r--compiler/rustc_hir/src/definitions.rs24
-rw-r--r--compiler/rustc_hir/src/hir.rs8
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs21
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs8
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs88
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs18
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs21
-rw-r--r--compiler/rustc_infer/src/infer/nll_relate/mod.rs6
-rw-r--r--compiler/rustc_infer/src/traits/error_reporting/mod.rs12
-rw-r--r--compiler/rustc_infer/src/traits/mod.rs6
-rw-r--r--compiler/rustc_interface/Cargo.toml5
-rw-r--r--compiler/rustc_interface/src/callbacks.rs11
-rw-r--r--compiler/rustc_interface/src/passes.rs11
-rw-r--r--compiler/rustc_interface/src/tests.rs2
-rw-r--r--compiler/rustc_lint/src/traits.rs5
-rw-r--r--compiler/rustc_lint/src/types.rs15
-rw-r--r--compiler/rustc_lint/src/unused.rs120
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs54
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp56
-rw-r--r--compiler/rustc_macros/src/session_diagnostic.rs8
-rw-r--r--compiler/rustc_macros/src/symbols.rs2
-rw-r--r--compiler/rustc_metadata/src/dependency_format.rs32
-rw-r--r--compiler/rustc_metadata/src/locator.rs5
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs17
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs43
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs18
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs6
-rw-r--r--compiler/rustc_middle/Cargo.toml3
-rw-r--r--compiler/rustc_middle/src/hir/exports.rs13
-rw-r--r--compiler/rustc_middle/src/hir/map/collector.rs7
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs26
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs1
-rw-r--r--compiler/rustc_middle/src/ich/hcx.rs9
-rw-r--r--compiler/rustc_middle/src/lib.rs5
-rw-r--r--compiler/rustc_middle/src/mir/abstract_const.rs38
-rw-r--r--compiler/rustc_middle/src/mir/generic_graph.rs (renamed from compiler/rustc_mir/src/util/generic_graph.rs)0
-rw-r--r--compiler/rustc_middle/src/mir/generic_graphviz.rs (renamed from compiler/rustc_mir/src/util/generic_graphviz.rs)0
-rw-r--r--compiler/rustc_middle/src/mir/graphviz.rs (renamed from compiler/rustc_mir/src/util/graphviz.rs)0
-rw-r--r--compiler/rustc_middle/src/mir/interpret/pointer.rs14
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs41
-rw-r--r--compiler/rustc_middle/src/mir/patch.rs (renamed from compiler/rustc_mir/src/util/patch.rs)0
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs (renamed from compiler/rustc_mir/src/util/pretty.rs)4
-rw-r--r--compiler/rustc_middle/src/mir/query.rs18
-rw-r--r--compiler/rustc_middle/src/mir/spanview.rs (renamed from compiler/rustc_mir/src/util/spanview.rs)0
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs32
-rw-r--r--compiler/rustc_middle/src/thir.rs3
-rw-r--r--compiler/rustc_middle/src/thir/abstract_const.rs61
-rw-r--r--compiler/rustc_middle/src/thir/visit.rs (renamed from compiler/rustc_mir_build/src/thir/visit.rs)6
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs39
-rw-r--r--compiler/rustc_middle/src/traits/select.rs3
-rw-r--r--compiler/rustc_middle/src/traits/structural_impls.rs3
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs5
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs5
-rw-r--r--compiler/rustc_middle/src/ty/error.rs2
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs82
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs4
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs4
-rw-r--r--compiler/rustc_middle/src/ty/util.rs31
-rw-r--r--compiler/rustc_mir/src/dataflow/mod.rs49
-rw-r--r--compiler/rustc_mir/src/util/mod.rs21
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs5
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs5
-rw-r--r--compiler/rustc_mir_build/src/build/matches/simplify.rs13
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs6
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs4
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/mod.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs9
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs58
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/usefulness.rs154
-rw-r--r--compiler/rustc_mir_dataflow/Cargo.toml23
-rw-r--r--compiler/rustc_mir_dataflow/src/drop_flag_effects.rs (renamed from compiler/rustc_mir/src/dataflow/drop_flag_effects.rs)14
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs (renamed from compiler/rustc_mir/src/util/elaborate_drops.rs)2
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/cursor.rs (renamed from compiler/rustc_mir/src/dataflow/framework/cursor.rs)0
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/direction.rs (renamed from compiler/rustc_mir/src/dataflow/framework/direction.rs)0
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/engine.rs (renamed from compiler/rustc_mir/src/dataflow/framework/engine.rs)2
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/fmt.rs (renamed from compiler/rustc_mir/src/dataflow/framework/fmt.rs)8
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/graphviz.rs (renamed from compiler/rustc_mir/src/dataflow/framework/graphviz.rs)2
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/lattice.rs (renamed from compiler/rustc_mir/src/dataflow/framework/lattice.rs)0
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/mod.rs (renamed from compiler/rustc_mir/src/dataflow/framework/mod.rs)5
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/tests.rs (renamed from compiler/rustc_mir/src/dataflow/framework/tests.rs)0
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/visitor.rs (renamed from compiler/rustc_mir/src/dataflow/framework/visitor.rs)93
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs (renamed from compiler/rustc_mir/src/dataflow/impls/borrowed_locals.rs)4
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/init_locals.rs (renamed from compiler/rustc_mir/src/dataflow/impls/init_locals.rs)6
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/liveness.rs (renamed from compiler/rustc_mir/src/dataflow/impls/liveness.rs)2
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/mod.rs (renamed from compiler/rustc_mir/src/dataflow/impls/mod.rs)23
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs (renamed from compiler/rustc_mir/src/dataflow/impls/storage_liveness.rs)12
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs72
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs (renamed from compiler/rustc_mir/src/dataflow/move_paths/abs_domain.rs)0
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/builder.rs (renamed from compiler/rustc_mir/src/dataflow/move_paths/builder.rs)2
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/mod.rs (renamed from compiler/rustc_mir/src/dataflow/move_paths/mod.rs)14
-rw-r--r--compiler/rustc_mir_dataflow/src/rustc_peek.rs (renamed from compiler/rustc_mir/src/transform/rustc_peek.rs)14
-rw-r--r--compiler/rustc_mir_dataflow/src/storage.rs (renamed from compiler/rustc_mir/src/util/storage.rs)0
-rw-r--r--compiler/rustc_mir_transform/Cargo.toml29
-rw-r--r--compiler/rustc_mir_transform/src/abort_unwinding_calls.rs (renamed from compiler/rustc_mir/src/transform/abort_unwinding_calls.rs)12
-rw-r--r--compiler/rustc_mir_transform/src/add_call_guards.rs (renamed from compiler/rustc_mir/src/transform/add_call_guards.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs (renamed from compiler/rustc_mir/src/transform/add_moves_for_packed_drops.rs)4
-rw-r--r--compiler/rustc_mir_transform/src/add_retag.rs (renamed from compiler/rustc_mir/src/transform/add_retag.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/check_const_item_mutation.rs (renamed from compiler/rustc_mir/src/transform/check_const_item_mutation.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/check_packed_ref.rs (renamed from compiler/rustc_mir/src/transform/check_packed_ref.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs (renamed from compiler/rustc_mir/src/transform/check_unsafety.rs)0
-rw-r--r--compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs (renamed from compiler/rustc_mir/src/transform/cleanup_post_borrowck.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/const_debuginfo.rs (renamed from compiler/rustc_mir/src/transform/const_debuginfo.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/const_goto.rs (renamed from compiler/rustc_mir/src/transform/const_goto.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs (renamed from compiler/rustc_mir/src/transform/const_prop.rs)6
-rw-r--r--compiler/rustc_mir_transform/src/coverage/counters.rs (renamed from compiler/rustc_mir/src/transform/coverage/counters.rs)0
-rw-r--r--compiler/rustc_mir_transform/src/coverage/debug.rs (renamed from compiler/rustc_mir/src/transform/coverage/debug.rs)26
-rw-r--r--compiler/rustc_mir_transform/src/coverage/graph.rs (renamed from compiler/rustc_mir/src/transform/coverage/graph.rs)0
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mod.rs (renamed from compiler/rustc_mir/src/transform/coverage/mod.rs)8
-rw-r--r--compiler/rustc_mir_transform/src/coverage/query.rs (renamed from compiler/rustc_mir/src/transform/coverage/query.rs)0
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs (renamed from compiler/rustc_mir/src/transform/coverage/spans.rs)10
-rw-r--r--compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml (renamed from compiler/rustc_mir/src/transform/coverage/test_macros/Cargo.toml)0
-rw-r--r--compiler/rustc_mir_transform/src/coverage/test_macros/src/lib.rs (renamed from compiler/rustc_mir/src/transform/coverage/test_macros/src/lib.rs)0
-rw-r--r--compiler/rustc_mir_transform/src/coverage/tests.rs (renamed from compiler/rustc_mir/src/transform/coverage/tests.rs)0
-rw-r--r--compiler/rustc_mir_transform/src/deaggregator.rs (renamed from compiler/rustc_mir/src/transform/deaggregator.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/deduplicate_blocks.rs (renamed from compiler/rustc_mir/src/transform/deduplicate_blocks.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs (renamed from compiler/rustc_mir/src/transform/dest_prop.rs)10
-rw-r--r--compiler/rustc_mir_transform/src/dump_mir.rs (renamed from compiler/rustc_mir/src/transform/dump_mir.rs)17
-rw-r--r--compiler/rustc_mir_transform/src/early_otherwise_branch.rs (renamed from compiler/rustc_mir/src/transform/early_otherwise_branch.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs (renamed from compiler/rustc_mir/src/transform/elaborate_drops.rs)42
-rw-r--r--compiler/rustc_mir_transform/src/function_item_references.rs (renamed from compiler/rustc_mir/src/transform/function_item_references.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs (renamed from compiler/rustc_mir/src/transform/generator.rs)28
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs (renamed from compiler/rustc_mir/src/transform/inline.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/inline/cycle.rs (renamed from compiler/rustc_mir/src/transform/inline/cycle.rs)0
-rw-r--r--compiler/rustc_mir_transform/src/instcombine.rs (renamed from compiler/rustc_mir/src/transform/instcombine.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs (renamed from compiler/rustc_mir/src/transform/mod.rs)148
-rw-r--r--compiler/rustc_mir_transform/src/lower_intrinsics.rs (renamed from compiler/rustc_mir/src/transform/lower_intrinsics.rs)11
-rw-r--r--compiler/rustc_mir_transform/src/lower_slice_len.rs (renamed from compiler/rustc_mir/src/transform/lower_slice_len.rs)10
-rw-r--r--compiler/rustc_mir_transform/src/match_branches.rs (renamed from compiler/rustc_mir/src/transform/match_branches.rs)4
-rw-r--r--compiler/rustc_mir_transform/src/multiple_return_terminators.rs (renamed from compiler/rustc_mir/src/transform/multiple_return_terminators.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/nrvo.rs (renamed from compiler/rustc_mir/src/transform/nrvo.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs (renamed from compiler/rustc_mir/src/transform/remove_noop_landing_pads.rs)4
-rw-r--r--compiler/rustc_mir_transform/src/remove_storage_markers.rs (renamed from compiler/rustc_mir/src/transform/remove_storage_markers.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/remove_unneeded_drops.rs (renamed from compiler/rustc_mir/src/transform/remove_unneeded_drops.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/remove_zsts.rs (renamed from compiler/rustc_mir/src/transform/remove_zsts.rs)6
-rw-r--r--compiler/rustc_mir_transform/src/required_consts.rs (renamed from compiler/rustc_mir/src/transform/required_consts.rs)0
-rw-r--r--compiler/rustc_mir_transform/src/separate_const_switch.rs (renamed from compiler/rustc_mir/src/transform/separate_const_switch.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs (renamed from compiler/rustc_mir/src/shim.rs)10
-rw-r--r--compiler/rustc_mir_transform/src/simplify.rs (renamed from compiler/rustc_mir/src/transform/simplify.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/simplify_branches.rs (renamed from compiler/rustc_mir/src/transform/simplify_branches.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/simplify_comparison_integral.rs (renamed from compiler/rustc_mir/src/transform/simplify_comparison_integral.rs)0
-rw-r--r--compiler/rustc_mir_transform/src/simplify_try.rs (renamed from compiler/rustc_mir/src/transform/simplify_try.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs (renamed from compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs)2
-rw-r--r--compiler/rustc_mir_transform/src/unreachable_prop.rs (renamed from compiler/rustc_mir/src/transform/unreachable_prop.rs)4
-rw-r--r--compiler/rustc_monomorphize/Cargo.toml19
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs (renamed from compiler/rustc_mir/src/monomorphize/collector.rs)6
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs (renamed from compiler/rustc_mir/src/monomorphize/mod.rs)29
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/default.rs (renamed from compiler/rustc_mir/src/monomorphize/partitioning/default.rs)6
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/merging.rs (renamed from compiler/rustc_mir/src/monomorphize/partitioning/merging.rs)2
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/mod.rs (renamed from compiler/rustc_mir/src/monomorphize/partitioning/mod.rs)4
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs (renamed from compiler/rustc_mir/src/monomorphize/polymorphize.rs)0
-rw-r--r--compiler/rustc_monomorphize/src/util.rs (renamed from compiler/rustc_mir/src/monomorphize/util.rs)0
-rw-r--r--compiler/rustc_parse/src/lib.rs4
-rw-r--r--compiler/rustc_parse/src/parser/attr_wrapper.rs2
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs85
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs151
-rw-r--r--compiler/rustc_parse/src/parser/item.rs53
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs103
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs25
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs13
-rw-r--r--compiler/rustc_passes/src/dead.rs62
-rw-r--r--compiler/rustc_passes/src/liveness.rs4
-rw-r--r--compiler/rustc_passes/src/region.rs2
-rw-r--r--compiler/rustc_privacy/src/lib.rs2
-rw-r--r--compiler/rustc_query_impl/src/on_disk_cache.rs54
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs167
-rw-r--r--compiler/rustc_query_system/src/query/job.rs2
-rw-r--r--compiler/rustc_query_system/src/query/plumbing.rs469
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs4
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs8
-rw-r--r--compiler/rustc_resolve/src/imports.rs5
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs18
-rw-r--r--compiler/rustc_resolve/src/lib.rs28
-rw-r--r--compiler/rustc_resolve/src/macros.rs4
-rw-r--r--compiler/rustc_save_analysis/src/lib.rs1
-rw-r--r--compiler/rustc_serialize/src/serialize.rs12
-rw-r--r--compiler/rustc_session/src/config.rs15
-rw-r--r--compiler/rustc_session/src/options.rs20
-rw-r--r--compiler/rustc_session/src/session.rs7
-rw-r--r--compiler/rustc_span/src/hygiene.rs4
-rw-r--r--compiler/rustc_span/src/lib.rs93
-rw-r--r--compiler/rustc_span/src/source_map.rs2
-rw-r--r--compiler/rustc_span/src/span_encoding.rs30
-rw-r--r--compiler/rustc_span/src/symbol.rs9
-rw-r--r--compiler/rustc_target/src/abi/call/mips64.rs6
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs8
-rw-r--r--compiler/rustc_target/src/abi/call/riscv.rs4
-rw-r--r--compiler/rustc_target/src/abi/call/s390x.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/x86.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/x86_64.rs2
-rw-r--r--compiler/rustc_target/src/abi/mod.rs163
-rw-r--r--compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs43
-rw-r--r--compiler/rustc_target/src/spec/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs425
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs25
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs107
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs12
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs126
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs80
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs3
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs7
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs7
-rw-r--r--compiler/rustc_typeck/src/check/callee.rs11
-rw-r--r--compiler/rustc_typeck/src/check/check.rs2
-rw-r--r--compiler/rustc_typeck/src/check/coercion.rs14
-rw-r--r--compiler/rustc_typeck/src/check/compare_method.rs13
-rw-r--r--compiler/rustc_typeck/src/check/demand.rs109
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs51
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs12
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/checks.rs49
-rw-r--r--compiler/rustc_typeck/src/check/generator_interior.rs2
-rw-r--r--compiler/rustc_typeck/src/check/method/probe.rs2
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs2
-rw-r--r--compiler/rustc_typeck/src/check/mod.rs6
-rw-r--r--compiler/rustc_typeck/src/check/op.rs81
-rw-r--r--compiler/rustc_typeck/src/check/pat.rs74
-rw-r--r--compiler/rustc_typeck/src/check/regionck.rs14
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs28
-rw-r--r--compiler/rustc_typeck/src/collect.rs21
-rw-r--r--compiler/rustc_typeck/src/lib.rs2
-rw-r--r--library/alloc/src/lib.rs3
m---------library/backtrace0
-rw-r--r--library/core/primitive_docs/box_into_raw.md1
-rw-r--r--library/core/primitive_docs/fs_file.md1
-rw-r--r--library/core/primitive_docs/io_bufread.md1
-rw-r--r--library/core/primitive_docs/io_read.md1
-rw-r--r--library/core/primitive_docs/io_seek.md1
-rw-r--r--library/core/primitive_docs/io_write.md1
-rw-r--r--library/core/primitive_docs/net_tosocketaddrs.md1
-rw-r--r--library/core/primitive_docs/process_exit.md1
-rw-r--r--library/core/primitive_docs/string_string.md1
-rw-r--r--library/core/src/bool.rs6
-rw-r--r--library/core/src/cell.rs3
-rw-r--r--library/core/src/char/methods.rs14
-rw-r--r--library/core/src/clone.rs1
-rw-r--r--library/core/src/fmt/mod.rs26
-rw-r--r--library/core/src/hint.rs16
-rw-r--r--library/core/src/intrinsics.rs1
-rw-r--r--library/core/src/iter/traits/iterator.rs7
-rw-r--r--library/core/src/lib.rs6
-rw-r--r--library/core/src/macros/mod.rs11
-rw-r--r--library/core/src/marker.rs20
-rw-r--r--library/core/src/num/int_macros.rs2
-rw-r--r--library/core/src/num/uint_macros.rs5
-rw-r--r--library/core/src/num/wrapping.rs4
-rw-r--r--library/core/src/ops/bit.rs1
-rw-r--r--library/core/src/option.rs16
-rw-r--r--library/core/src/panicking.rs10
-rw-r--r--library/core/src/primitive_docs.rs1307
-rw-r--r--library/core/src/slice/mod.rs7
-rw-r--r--library/core/src/str/converts.rs1
-rw-r--r--library/core/src/str/mod.rs1
-rw-r--r--library/core/tests/fmt/builders.rs1
-rw-r--r--library/proc_macro/src/bridge/mod.rs2
-rw-r--r--library/proc_macro/src/lib.rs12
-rw-r--r--library/std/primitive_docs/box_into_raw.md1
-rw-r--r--library/std/primitive_docs/fs_file.md1
-rw-r--r--library/std/primitive_docs/io_bufread.md1
-rw-r--r--library/std/primitive_docs/io_read.md1
-rw-r--r--library/std/primitive_docs/io_seek.md1
-rw-r--r--library/std/primitive_docs/io_write.md1
-rw-r--r--library/std/primitive_docs/net_tosocketaddrs.md1
-rw-r--r--library/std/primitive_docs/process_exit.md1
-rw-r--r--library/std/primitive_docs/string_string.md1
-rw-r--r--library/std/src/collections/mod.rs2
-rw-r--r--library/std/src/ffi/c_str.rs3
-rw-r--r--library/std/src/io/buffered/tests.rs4
-rw-r--r--library/std/src/io/mod.rs2
-rw-r--r--library/std/src/keyword_docs.rs4
-rw-r--r--library/std/src/lib.rs3
-rw-r--r--library/std/src/net/ip.rs2
-rw-r--r--library/std/src/net/tcp.rs51
-rw-r--r--library/std/src/os/mod.rs209
-rw-r--r--library/std/src/panicking.rs2
-rw-r--r--library/std/src/primitive_docs.rs56
-rw-r--r--library/test/src/formatters/junit.rs2
-rw-r--r--library/test/src/term/terminfo/mod.rs1
-rw-r--r--src/bootstrap/doc.rs9
-rw-r--r--src/bootstrap/test.rs5
-rwxr-xr-xsrc/ci/docker/scripts/freebsd-toolchain.sh2
-rw-r--r--src/ci/github-actions/ci.yml3
-rwxr-xr-xsrc/ci/scripts/install-clang.sh6
-rwxr-xr-xsrc/ci/scripts/verify-backported-commits.sh8
m---------src/doc/embedded-book0
m---------src/doc/rust-by-example0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/doc/rustc/src/platform-support.md1
-rw-r--r--src/doc/rustdoc/src/unstable-features.md6
-rw-r--r--src/doc/unstable-book/src/compiler-flags/remap-cwd-prefix.md24
-rw-r--r--src/doc/unstable-book/src/library-features/asm.md8
-rw-r--r--src/librustdoc/clean/blanket_impl.rs13
-rw-r--r--src/librustdoc/clean/inline.rs17
-rw-r--r--src/librustdoc/clean/mod.rs41
-rw-r--r--src/librustdoc/clean/types.rs131
-rw-r--r--src/librustdoc/clean/utils.rs54
-rw-r--r--src/librustdoc/config.rs8
-rw-r--r--src/librustdoc/core.rs3
-rw-r--r--src/librustdoc/docfs.rs12
-rw-r--r--src/librustdoc/doctest.rs24
-rw-r--r--src/librustdoc/doctest/tests.rs7
-rw-r--r--src/librustdoc/formats/cache.rs26
-rw-r--r--src/librustdoc/html/format.rs10
-rw-r--r--src/librustdoc/html/highlight.rs8
-rw-r--r--src/librustdoc/html/markdown.rs72
-rw-r--r--src/librustdoc/html/markdown/tests.rs24
-rw-r--r--src/librustdoc/html/render/context.rs16
-rw-r--r--src/librustdoc/html/render/mod.rs48
-rw-r--r--src/librustdoc/html/render/print_item.rs123
-rw-r--r--src/librustdoc/html/render/span_map.rs18
-rw-r--r--src/librustdoc/html/render/write_shared.rs70
-rw-r--r--src/librustdoc/html/sources.rs2
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css5
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css2
-rw-r--r--src/librustdoc/json/conversions.rs4
-rw-r--r--src/librustdoc/lib.rs10
-rw-r--r--src/librustdoc/markdown.rs4
-rw-r--r--src/librustdoc/passes/bare_urls.rs4
-rw-r--r--src/librustdoc/passes/calculate_doc_coverage.rs40
-rw-r--r--src/librustdoc/passes/check_code_block_syntax.rs4
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs61
-rw-r--r--src/librustdoc/passes/doc_test_lints.rs21
-rw-r--r--src/librustdoc/passes/html_tags.rs4
-rw-r--r--src/librustdoc/visit_lib.rs2
m---------src/llvm-project0
-rw-r--r--src/stage0.json670
-rw-r--r--src/test/assembly/niche-prefer-zero.rs25
-rw-r--r--src/test/codegen/panic-in-drop-abort.rs54
-rw-r--r--src/test/debuginfo/basic-types.rs4
-rw-r--r--src/test/debuginfo/msvc-pretty-enums.rs4
-rw-r--r--src/test/debuginfo/mutex.rs2
-rw-r--r--src/test/debuginfo/pretty-std.rs4
-rw-r--r--src/test/incremental/change_symbol_export_status.rs14
-rw-r--r--src/test/incremental/hashes/call_expressions.rs70
-rw-r--r--src/test/incremental/hashes/closure_expressions.rs54
-rw-r--r--src/test/incremental/hashes/consts.rs2
-rw-r--r--src/test/incremental/hashes/enum_constructors.rs128
-rw-r--r--src/test/incremental/hashes/enum_defs.rs236
-rw-r--r--src/test/incremental/hashes/exported_vs_not.rs28
-rw-r--r--src/test/incremental/hashes/extern_mods.rs96
-rw-r--r--src/test/incremental/hashes/for_loops.rs87
-rw-r--r--src/test/incremental/hashes/function_interfaces.rs208
-rw-r--r--src/test/incremental/hashes/if_expressions.rs67
-rw-r--r--src/test/incremental/hashes/indexing_expressions.rs60
-rw-r--r--src/test/incremental/hashes/inherent_impls.rs500
-rw-r--r--src/test/incremental/hashes/inline_asm.rs50
-rw-r--r--src/test/incremental/hashes/let_expressions.rs137
-rw-r--r--src/test/incremental/hashes/loop_expressions.rs69
-rw-r--r--src/test/incremental/hashes/match_expressions.rs145
-rw-r--r--src/test/incremental/hashes/statics.rs84
-rw-r--r--src/test/incremental/hashes/struct_constructors.rs75
-rw-r--r--src/test/incremental/hashes/struct_defs.rs133
-rw-r--r--src/test/incremental/hashes/trait_defs.rs669
-rw-r--r--src/test/incremental/hashes/trait_impls.rs262
-rw-r--r--src/test/incremental/hashes/type_defs.rs2
-rw-r--r--src/test/incremental/hashes/unary_and_binary_exprs.rs190
-rw-r--r--src/test/incremental/hashes/while_let_loops.rs73
-rw-r--r--src/test/incremental/hashes/while_loops.rs75
-rw-r--r--src/test/incremental/spans_significant_w_debuginfo.rs13
-rw-r--r--src/test/incremental/spans_significant_w_panic.rs22
-rw-r--r--src/test/incremental/string_constant.rs18
-rw-r--r--src/test/incremental/thinlto/cgu_keeps_identical_fn.rs61
-rw-r--r--src/test/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff24
-rw-r--r--src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff162
-rw-r--r--src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir36
-rw-r--r--src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir26
-rw-r--r--src/test/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff26
-rw-r--r--src/test/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff32
-rw-r--r--src/test/mir-opt/lower_intrinsics.rs5
-rw-r--r--src/test/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff20
-rw-r--r--src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff2
-rw-r--r--src/test/pretty/anonymous-types.rs24
-rw-r--r--src/test/run-make-fulldeps/obtain-borrowck/driver.rs8
-rw-r--r--src/test/run-make-fulldeps/reproducible-build/Makefile65
-rw-r--r--src/test/run-make-fulldeps/sepcomp-cci-copies/Makefile2
-rw-r--r--src/test/rustdoc-gui/code-sidebar-toggle.goml1
-rw-r--r--src/test/rustdoc-gui/docblock-table-overflow.goml8
-rw-r--r--src/test/rustdoc-gui/jump-to-def-background.goml23
-rw-r--r--src/test/rustdoc-gui/src/lib2/lib.rs9
-rw-r--r--src/test/rustdoc-gui/src/link_to_definition/Cargo.lock7
-rw-r--r--src/test/rustdoc-gui/src/link_to_definition/Cargo.toml7
-rw-r--r--src/test/rustdoc-gui/src/link_to_definition/lib.rs6
-rw-r--r--src/test/rustdoc-js-std/multi-query.js7
-rw-r--r--src/test/rustdoc-ui/coverage/enum-tuple-documented.rs37
-rw-r--r--src/test/rustdoc-ui/coverage/enum-tuple-documented.stdout7
-rw-r--r--src/test/rustdoc-ui/coverage/enum-tuple.rs18
-rw-r--r--src/test/rustdoc-ui/coverage/enum-tuple.stdout7
-rw-r--r--src/test/rustdoc-ui/coverage/enums.stdout4
-rw-r--r--src/test/rustdoc-ui/display-output.rs9
-rw-r--r--src/test/rustdoc-ui/display-output.stdout24
-rw-r--r--src/test/rustdoc-ui/intra-doc/anchors.rs10
-rw-r--r--src/test/rustdoc-ui/intra-doc/anchors.stderr35
-rw-r--r--src/test/rustdoc-ui/invalid-syntax.stderr10
-rw-r--r--src/test/rustdoc-ui/lint-missing-doc-code-example.rs16
-rw-r--r--src/test/rustdoc/auxiliary/issue-15318.rs11
-rw-r--r--src/test/rustdoc/auxiliary/primitive-doc.rs3
-rw-r--r--src/test/rustdoc/check-source-code-urls-to-def-std.rs17
-rw-r--r--src/test/rustdoc/check-source-code-urls-to-def.rs8
-rw-r--r--src/test/rustdoc/cross-crate-primitive-doc.rs6
-rw-r--r--src/test/rustdoc/intra-doc/anchors.rs12
-rw-r--r--src/test/rustdoc/intra-doc/auxiliary/my-core.rs4
-rw-r--r--src/test/rustdoc/intra-doc/prim-methods-external-core.rs4
-rw-r--r--src/test/rustdoc/intra-doc/prim-methods-local.rs9
-rw-r--r--src/test/rustdoc/intra-link-prim-self.rs4
-rw-r--r--src/test/rustdoc/issue-15318-2.rs1
-rw-r--r--src/test/rustdoc/issue-88600.rs34
-rw-r--r--src/test/rustdoc/no_std-primitive.rs6
-rw-r--r--src/test/rustdoc/primitive/no_std.rs16
-rw-r--r--src/test/rustdoc/synthetic_auto/no-redundancy.rs2
-rw-r--r--src/test/rustdoc/table-in-docblock.rs16
-rw-r--r--src/test/rustdoc/type-layout.rs18
-rw-r--r--src/test/ui/anon-params/anon-params-denied-2018.stderr24
-rw-r--r--src/test/ui/array-slice-vec/slice_binary_search.rs1
-rw-r--r--src/test/ui/asm/parse-error.rs6
-rw-r--r--src/test/ui/asm/parse-error.stderr68
-rw-r--r--src/test/ui/associated-consts/associated-const-in-trait.stderr2
-rw-r--r--src/test/ui/associated-item/issue-48027.stderr2
-rw-r--r--src/test/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr24
-rw-r--r--src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr8
-rw-r--r--src/test/ui/associated-types/associated-types-bound-failure.stderr4
-rw-r--r--src/test/ui/associated-types/associated-types-path-1.stderr4
-rw-r--r--src/test/ui/associated-types/associated-types-path-2.rs2
-rw-r--r--src/test/ui/associated-types/associated-types-path-2.stderr32
-rw-r--r--src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr7
-rw-r--r--src/test/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.stderr14
-rw-r--r--src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr4
-rw-r--r--src/test/ui/associated-types/issue-36499.stderr10
-rw-r--r--src/test/ui/async-await/issue-72442.stderr4
-rw-r--r--src/test/ui/async-await/issues/issue-54752-async-block.stderr7
-rw-r--r--src/test/ui/borrowck/borrowck-unused-mut-locals.rs1
-rw-r--r--src/test/ui/borrowck/issue-82462.nll.stderr22
-rw-r--r--src/test/ui/borrowck/issue-82462.rs21
-rw-r--r--src/test/ui/borrowck/issue-82462.stderr22
-rw-r--r--src/test/ui/box/into-boxed-slice-fail.stderr8
-rw-r--r--src/test/ui/chalkify/type_inference.stderr4
-rw-r--r--src/test/ui/closure-expected.stderr4
-rw-r--r--src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.rs1
-rw-r--r--src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr14
-rw-r--r--src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs1
-rw-r--r--src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr6
-rw-r--r--src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs1
-rw-r--r--src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs2
-rw-r--r--src/test/ui/closures/closure-bounds-subtype.stderr4
-rw-r--r--src/test/ui/closures/coerce-unsafe-to-closure.stderr4
-rw-r--r--src/test/ui/coercion/issue-88097.rs31
-rw-r--r--src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr2
-rw-r--r--src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr4
-rw-r--r--src/test/ui/const-generics/broken-mir-2.rs3
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs11
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr10
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr2
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/closures.stderr2
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr8
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr2
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs35
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr10
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr12
-rw-r--r--src/test/ui/const-generics/issues/issue-67375.full.stderr6
-rw-r--r--src/test/ui/const-generics/issues/issue-67945-2.full.stderr3
-rw-r--r--src/test/ui/const-generics/issues/issue-86530.stderr4
-rw-r--r--src/test/ui/const-generics/type-dependent/type-mismatch.full.stderr2
-rw-r--r--src/test/ui/const-generics/type-dependent/type-mismatch.min.stderr2
-rw-r--r--src/test/ui/const-generics/unused_braces.stderr7
-rw-r--r--src/test/ui/consts/issue-88649.rs18
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn.stderr21
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr6
-rw-r--r--src/test/ui/derives/clone-debug-dead-code.rs45
-rw-r--r--src/test/ui/derives/clone-debug-dead-code.stderr38
-rw-r--r--src/test/ui/derives/deriving-copyclone.stderr27
-rw-r--r--src/test/ui/deriving/deriving-clone-generic-struct.rs2
-rw-r--r--src/test/ui/deriving/deriving-clone-struct.rs2
-rw-r--r--src/test/ui/deriving/deriving-clone-tuple-struct.rs2
-rw-r--r--src/test/ui/deriving/deriving-in-fn.rs3
-rw-r--r--src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr12
-rw-r--r--src/test/ui/discrim/discrim-ill-typed.stderr16
-rw-r--r--src/test/ui/enum-discriminant/niche-prefer-zero.rs14
-rw-r--r--src/test/ui/error-codes/E0038.stderr2
-rw-r--r--src/test/ui/error-codes/E0221.stderr13
-rw-r--r--src/test/ui/error-codes/E0277.stderr4
-rw-r--r--src/test/ui/error-should-say-copy-not-pod.stderr4
-rw-r--r--src/test/ui/expr/malformed_closure/missing_braces_around_block.fixed19
-rw-r--r--src/test/ui/expr/malformed_closure/missing_braces_around_block.rs19
-rw-r--r--src/test/ui/expr/malformed_closure/missing_braces_around_block.stderr38
-rw-r--r--src/test/ui/expr/malformed_closure/ruby_style_closure.rs16
-rw-r--r--src/test/ui/expr/malformed_closure/ruby_style_closure.stderr27
-rw-r--r--src/test/ui/extern/extern-wrong-value-type.stderr4
-rw-r--r--src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr4
-rw-r--r--src/test/ui/feature-gates/feature-gate-unnamed_fields.rs27
-rw-r--r--src/test/ui/feature-gates/feature-gate-unnamed_fields.stderr111
-rw-r--r--src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr4
-rw-r--r--src/test/ui/float-literal-inference-restrictions.stderr2
-rw-r--r--src/test/ui/fn/fn-trait-formatting.stderr4
-rw-r--r--src/test/ui/generator/static-not-unpin.stderr4
-rw-r--r--src/test/ui/generic-associated-types/gat-in-trait-path.stderr2
-rw-r--r--src/test/ui/generic-associated-types/impl_bounds.rs2
-rw-r--r--src/test/ui/generic-associated-types/impl_bounds.stderr20
-rw-r--r--src/test/ui/generic-associated-types/issue-67510-pass.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-76535.stderr4
-rw-r--r--src/test/ui/generic-associated-types/issue-78671.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-79422.stderr4
-rw-r--r--src/test/ui/generic-associated-types/issue-86787.stderr4
-rw-r--r--src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs13
-rw-r--r--src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr11
-rw-r--r--src/test/ui/generic-associated-types/trait-objects.stderr2
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr26
-rw-r--r--src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr4
-rw-r--r--src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr8
-rw-r--r--src/test/ui/hrtb/issue-88446.rs35
-rw-r--r--src/test/ui/indexing-requires-a-uint.stderr2
-rw-r--r--src/test/ui/inference/issue-71309.rs7
-rw-r--r--src/test/ui/inference/issue-71309.stderr15
-rw-r--r--src/test/ui/integer-literal-suffix-inference.stderr280
-rw-r--r--src/test/ui/issues/issue-13359.stderr4
-rw-r--r--src/test/ui/issues/issue-1362.stderr2
-rw-r--r--src/test/ui/issues/issue-1448-2.stderr2
-rw-r--r--src/test/ui/issues/issue-17651.rs1
-rw-r--r--src/test/ui/issues/issue-17651.stderr16
-rw-r--r--src/test/ui/issues/issue-18959.stderr2
-rw-r--r--src/test/ui/issues/issue-19358.rs3
-rw-r--r--src/test/ui/issues/issue-19538.stderr4
-rw-r--r--src/test/ui/issues/issue-20605.stderr7
-rw-r--r--src/test/ui/issues/issue-23966.stderr4
-rw-r--r--src/test/ui/issues/issue-25076.stderr4
-rw-r--r--src/test/ui/issues/issue-28098.stderr16
-rw-r--r--src/test/ui/issues/issue-30355.stderr4
-rw-r--r--src/test/ui/issues/issue-34255-1.rs2
-rw-r--r--src/test/ui/issues/issue-34255-1.stderr19
-rw-r--r--src/test/ui/issues/issue-3794.rs1
-rw-r--r--src/test/ui/issues/issue-47706-trait.stderr4
-rw-r--r--src/test/ui/issues/issue-47706.stderr8
-rw-r--r--src/test/ui/issues/issue-51632-try-desugar-incompatible-types.rs2
-rw-r--r--src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr3
-rw-r--r--src/test/ui/issues/issue-56031.stderr10
-rw-r--r--src/test/ui/issues/issue-59494.stderr4
-rw-r--r--src/test/ui/issues/issue-60218.stderr6
-rw-r--r--src/test/ui/issues/issue-60283.stderr13
-rw-r--r--src/test/ui/issues/issue-66353.stderr4
-rw-r--r--src/test/ui/issues/issue-86865.rs11
-rw-r--r--src/test/ui/issues/issue-86865.stderr18
-rw-r--r--src/test/ui/issues/issue-87199.stderr4
-rw-r--r--src/test/ui/issues/issue-8761.stderr4
-rw-r--r--src/test/ui/kindck/kindck-impl-type-params-2.stderr4
-rw-r--r--src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr4
-rw-r--r--src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr4
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/issue_74400.nll.stderr30
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/issue_74400.rs13
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/issue_74400.stderr11
-rw-r--r--src/test/ui/lint/lint-unnecessary-parens.stderr135
-rw-r--r--src/test/ui/lint/suggestions.stderr7
-rw-r--r--src/test/ui/lint/unused/issue-54538-unused-parens-lint.stderr191
-rw-r--r--src/test/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr46
-rw-r--r--src/test/ui/lint/unused_braces.stderr38
-rw-r--r--src/test/ui/lint/unused_braces_borrow.stderr7
-rw-r--r--src/test/ui/lint/unused_parens_json_suggestion.stderr9
-rw-r--r--src/test/ui/lint/unused_parens_remove_json_suggestion.stderr89
-rw-r--r--src/test/ui/meta/expected-error-correct-rev.a.stderr2
-rw-r--r--src/test/ui/meta/meta-expected-error-wrong-rev.a.stderr2
-rw-r--r--src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr2
-rw-r--r--src/test/ui/mir/remove-zsts-query-cycle.rs16
-rw-r--r--src/test/ui/mismatched_types/E0631.stderr8
-rw-r--r--src/test/ui/mismatched_types/closure-arg-count.stderr20
-rw-r--r--src/test/ui/mismatched_types/fn-variance-1.stderr8
-rw-r--r--src/test/ui/mismatched_types/issue-26480.stderr2
-rw-r--r--src/test/ui/mismatched_types/numeric-literal-cast.stderr6
-rw-r--r--src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs1
-rw-r--r--src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr4
-rw-r--r--src/test/ui/monomorphize-abi-alignment.rs1
-rw-r--r--src/test/ui/moves/move-1-unique.rs1
-rw-r--r--src/test/ui/moves/move-3-unique.rs1
-rw-r--r--src/test/ui/mutexguard-sync.stderr4
-rw-r--r--src/test/ui/namespace/namespace-mix.stderr176
-rw-r--r--src/test/ui/no_send-rc.stderr4
-rw-r--r--src/test/ui/no_send-struct.stderr4
-rw-r--r--src/test/ui/no_share-struct.stderr4
-rw-r--r--src/test/ui/numeric/const-scope.stderr8
-rw-r--r--src/test/ui/numeric/len.stderr2
-rw-r--r--src/test/ui/numeric/numeric-cast-2.stderr24
-rw-r--r--src/test/ui/numeric/numeric-cast-binop.stderr544
-rw-r--r--src/test/ui/numeric/numeric-cast-no-fix.stderr22
-rw-r--r--src/test/ui/numeric/numeric-cast.stderr434
-rw-r--r--src/test/ui/numeric/numeric-suffix.stderr284
-rw-r--r--src/test/ui/object-does-not-impl-trait.stderr4
-rw-r--r--src/test/ui/object-safety/object-safety-associated-consts.curr.stderr2
-rw-r--r--src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr2
-rw-r--r--src/test/ui/object-safety/object-safety-generics.curr.stderr4
-rw-r--r--src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr4
-rw-r--r--src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr4
-rw-r--r--src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr4
-rw-r--r--src/test/ui/on-unimplemented/enclosing-scope.stderr16
-rw-r--r--src/test/ui/on-unimplemented/multiple-impls.stderr12
-rw-r--r--src/test/ui/on-unimplemented/on-impl.stderr4
-rw-r--r--src/test/ui/overloaded/overloaded-autoderef-order.rs2
-rw-r--r--src/test/ui/parser/expr-as-stmt.fixed7
-rw-r--r--src/test/ui/parser/expr-as-stmt.rs7
-rw-r--r--src/test/ui/parser/expr-as-stmt.stderr30
-rw-r--r--src/test/ui/parser/inverted-parameters.stderr6
-rw-r--r--src/test/ui/parser/issue-44406.rs4
-rw-r--r--src/test/ui/parser/issue-44406.stderr20
-rw-r--r--src/test/ui/parser/issue-88276-unary-plus.fixed8
-rw-r--r--src/test/ui/parser/issue-88276-unary-plus.rs8
-rw-r--r--src/test/ui/parser/issue-88276-unary-plus.stderr50
-rw-r--r--src/test/ui/parser/issue-88583-union-as-ident.rs15
-rw-r--r--src/test/ui/parser/issue-88818.rs10
-rw-r--r--src/test/ui/parser/issue-88818.stderr18
-rw-r--r--src/test/ui/parser/lifetime-in-pattern.stderr8
-rw-r--r--src/test/ui/parser/macro-braces-dot-question.rs11
-rw-r--r--src/test/ui/parser/omitted-arg-in-item-fn.stderr6
-rw-r--r--src/test/ui/parser/pat-lt-bracket-2.stderr4
-rw-r--r--src/test/ui/parser/recover-from-bad-variant.rs2
-rw-r--r--src/test/ui/parser/recover-from-bad-variant.stderr19
-rw-r--r--src/test/ui/path-lookahead.stderr7
-rw-r--r--src/test/ui/phantom-auto-trait.stderr8
-rw-r--r--src/test/ui/pptypedef.stderr4
-rw-r--r--src/test/ui/proc-macro/span-preservation.stderr2
-rw-r--r--src/test/ui/repeat_count.stderr2
-rw-r--r--src/test/ui/repr/repr-transparent-issue-87496.rs12
-rw-r--r--src/test/ui/repr/repr-transparent-issue-87496.stderr16
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs23
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs10
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/reachable-patterns.rs160
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/reachable-patterns.stderr146
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/struct.stderr6
-rw-r--r--src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr6
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs13
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr4
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr68
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs54
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr68
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop.rs81
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs21
-rw-r--r--src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr24
-rw-r--r--src/test/ui/self/ufcs-explicit-self.rs1
-rw-r--r--src/test/ui/shift-various-bad-types.stderr2
-rw-r--r--src/test/ui/span/issue-34264.stderr14
-rw-r--r--src/test/ui/str/str-idx.stderr8
-rw-r--r--src/test/ui/str/str-mut-idx.stderr8
-rw-r--r--src/test/ui/structs-enums/class-cast-to-trait-multiple-types.rs1
-rw-r--r--src/test/ui/structs-enums/class-implement-traits.rs1
-rw-r--r--src/test/ui/structs-enums/functional-struct-upd.rs3
-rw-r--r--src/test/ui/structs-enums/tag-align-shape.rs1
-rw-r--r--src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr8
-rw-r--r--src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr8
-rw-r--r--src/test/ui/suggestions/imm-ref-trait-object-literal.stderr13
-rw-r--r--src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr24
-rw-r--r--src/test/ui/suggestions/issue-62843.stderr9
-rw-r--r--src/test/ui/suggestions/issue-64252-self-type.stderr8
-rw-r--r--src/test/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr8
-rw-r--r--src/test/ui/suggestions/issue-84973-2.stderr9
-rw-r--r--src/test/ui/suggestions/issue-84973-blacklist.rs1
-rw-r--r--src/test/ui/suggestions/issue-84973-blacklist.stderr30
-rw-r--r--src/test/ui/suggestions/issue-84973-negative.stderr13
-rw-r--r--src/test/ui/suggestions/issue-84973.stderr9
-rw-r--r--src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr4
-rw-r--r--src/test/ui/suggestions/object-unsafe-trait-references-self.stderr4
-rw-r--r--src/test/ui/suggestions/restrict-type-argument.stderr24
-rw-r--r--src/test/ui/suggestions/slice-issue-87994.rs16
-rw-r--r--src/test/ui/suggestions/slice-issue-87994.stderr71
-rw-r--r--src/test/ui/suggestions/suggest-change-mut.stderr4
-rw-r--r--src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr20
-rw-r--r--src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr30
-rw-r--r--src/test/ui/tail-typeck.stderr2
-rw-r--r--src/test/ui/traits/bound/same-crate-name.stderr16
-rw-r--r--src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr4
-rw-r--r--src/test/ui/traits/item-privacy.stderr6
-rw-r--r--src/test/ui/traits/multidispatch-bad.stderr2
-rw-r--r--src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr38
-rw-r--r--src/test/ui/traits/reservation-impl/no-use.stderr4
-rw-r--r--src/test/ui/traits/suggest-deferences/issue-39029.stderr9
-rw-r--r--src/test/ui/traits/suggest-deferences/issue-62530.stderr9
-rw-r--r--src/test/ui/traits/suggest-deferences/multiple-0.stderr9
-rw-r--r--src/test/ui/traits/suggest-deferences/multiple-1.stderr4
-rw-r--r--src/test/ui/traits/test-2.stderr8
-rw-r--r--src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr2
-rw-r--r--src/test/ui/trivial-bounds/trivial-bounds-leak.stderr8
-rw-r--r--src/test/ui/try-block/try-block-unused-delims.stderr38
-rw-r--r--src/test/ui/tutorial-suffix-inference-test.stderr14
-rw-r--r--src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.rs12
-rw-r--r--src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr13
-rw-r--r--src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr2
-rw-r--r--src/test/ui/typeck/issue-88803-call-expr-method.fixed9
-rw-r--r--src/test/ui/typeck/issue-88803-call-expr-method.rs9
-rw-r--r--src/test/ui/typeck/issue-88803-call-expr-method.stderr15
-rw-r--r--src/test/ui/typeck/typeck-unsafe-always-share.stderr12
-rw-r--r--src/test/ui/typeof/type_mismatch.stderr2
-rw-r--r--src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr4
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr4
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr2
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr12
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr12
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr12
-rw-r--r--src/test/ui/unnamed_fields/restrict_anonymous.rs52
-rw-r--r--src/test/ui/unnamed_fields/restrict_anonymous.stderr175
-rw-r--r--src/test/ui/unsized-locals/unsized-exprs.stderr6
-rw-r--r--src/test/ui/unsized/unsized3.rs4
-rw-r--r--src/test/ui/unsized/unsized3.stderr53
-rw-r--r--src/test/ui/vtable-res-trait-param.stderr4
-rw-r--r--src/test/ui/wf/issue-87495.stderr2
-rw-r--r--src/test/ui/wf/wf-object-safe.stderr2
-rw-r--r--src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr4
-rw-r--r--src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr4
-rw-r--r--src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr4
-rw-r--r--src/test/ui/wrong-ret-type.stderr2
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/.cargo/config3
-rw-r--r--src/tools/clippy/.github/ISSUE_TEMPLATE/blank_issue.md14
-rw-r--r--src/tools/clippy/.github/ISSUE_TEMPLATE/bug_report.md40
-rw-r--r--src/tools/clippy/.github/ISSUE_TEMPLATE/false_negative.md22
-rw-r--r--src/tools/clippy/.github/ISSUE_TEMPLATE/false_positive.md31
-rw-r--r--src/tools/clippy/.github/ISSUE_TEMPLATE/ice.md21
-rw-r--r--src/tools/clippy/.github/workflows/clippy_dev.yml3
-rw-r--r--src/tools/clippy/CHANGELOG.md12
-rw-r--r--src/tools/clippy/Cargo.toml31
-rw-r--r--src/tools/clippy/README.md8
-rw-r--r--src/tools/clippy/clippy_dev/Cargo.toml6
-rw-r--r--src/tools/clippy/clippy_dev/src/lib.rs1
-rw-r--r--src/tools/clippy/clippy_dev/src/main.rs9
-rw-r--r--src/tools/clippy/clippy_dev/src/stderr_length_check.rs51
-rw-r--r--src/tools/clippy/clippy_dummy/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml18
-rw-r--r--src/tools/clippy/clippy_lints/src/approx_const.rs124
-rw-r--r--src/tools/clippy/clippy_lints/src/assertions_on_constants.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs90
-rw-r--r--src/tools/clippy/clippy_lints/src/bytecount.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/cognitive_complexity.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/collapsible_match.rs39
-rw-r--r--src/tools/clippy/clippy_lints/src/copies.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/derivable_impls.rs108
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/doc.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/entry.rs31
-rw-r--r--src/tools/clippy/clippy_lints/src/eval_order_dependence.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/feature_name.rs164
-rw-r--r--src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs32
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/must_use.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/if_let_mutex.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/if_let_some_result.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_hasher.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/large_const_arrays.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/let_if_seq.rs21
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs43
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mod.rs27
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs98
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/needless_collect.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs33
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/macro_use.rs30
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_map.rs322
-rw-r--r--src/tools/clippy/clippy_lints/src/matches.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/mem_forget.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/mem_replace.rs85
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_next.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_split_once.rs213
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs42
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/utils.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/misc.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/module_style.rs178
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_mutex_lock.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_option_as_deref.rs66
-rw-r--r--src/tools/clippy/clippy_lints/src/no_effect.rs69
-rw-r--r--src/tools/clippy/clippy_lints/src/open_options.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/option_if_let_else.rs46
-rw-r--r--src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_clone.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_closure_call.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/regex.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/returns.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/strings.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/to_string_in_display.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/types/mod.rs81
-rw-r--r--src/tools/clippy/clippy_lints/src/types/rc_mutex.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_async.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_io_amount.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_self.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap.rs133
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/conf.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/inspector.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints.rs28
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/vec.rs2
-rw-r--r--src/tools/clippy/clippy_utils/Cargo.toml10
-rw-r--r--src/tools/clippy/clippy_utils/src/diagnostics.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/higher.rs165
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs363
-rw-r--r--src/tools/clippy/clippy_utils/src/msrvs.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/paths.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs8
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs9
-rw-r--r--src/tools/clippy/clippy_utils/src/usage.rs11
-rw-r--r--src/tools/clippy/clippy_utils/src/visitors.rs117
-rw-r--r--src/tools/clippy/doc/adding_lints.md9
-rw-r--r--src/tools/clippy/doc/common_tools_writing_lints.md27
-rw-r--r--src/tools/clippy/lintcheck/Cargo.toml17
-rw-r--r--src/tools/clippy/lintcheck/src/main.rs46
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/tests/compile-test.rs159
-rw-r--r--src/tools/clippy/tests/dogfood.rs2
-rw-r--r--src/tools/clippy/tests/fmt.rs3
-rw-r--r--src/tools/clippy/tests/integration.rs2
-rw-r--r--src/tools/clippy/tests/lint_message_convention.rs3
-rw-r--r--src/tools/clippy/tests/missing-test-files.rs2
-rw-r--r--src/tools/clippy/tests/ui-cargo/feature_name/fail/Cargo.toml21
-rw-r--r--src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.rs7
-rw-r--r--src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.stderr44
-rw-r--r--src/tools/clippy/tests/ui-cargo/feature_name/pass/Cargo.toml9
-rw-r--r--src/tools/clippy/tests/ui-cargo/feature_name/pass/src/main.rs7
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_mod/Cargo.toml8
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/bad/inner.rs1
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/bad/inner/stuff.rs3
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/bad/inner/stuff/most.rs1
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/bad/mod.rs3
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.rs9
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.stderr19
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/Cargo.toml8
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/bad/mod.rs1
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.rs7
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr11
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/pass_mod/Cargo.toml8
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/bad/mod.rs1
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/main.rs10
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/more/foo.rs1
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/more/inner/mod.rs1
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/more/mod.rs2
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/pass_no_mod/Cargo.toml8
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/pass_no_mod/src/good.rs1
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/pass_no_mod/src/main.rs7
-rw-r--r--src/tools/clippy/tests/ui/approx_const.rs4
-rw-r--r--src/tools/clippy/tests/ui/approx_const.stderr101
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/option_helpers.rs9
-rw-r--r--src/tools/clippy/tests/ui/bool_assert_comparison.rs63
-rw-r--r--src/tools/clippy/tests/ui/bool_assert_comparison.stderr62
-rw-r--r--src/tools/clippy/tests/ui/box_vec.rs28
-rw-r--r--src/tools/clippy/tests/ui/box_vec.stderr6
-rw-r--r--src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.stderr39
-rw-r--r--src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.stderr4
-rw-r--r--src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs4
-rw-r--r--src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr90
-rw-r--r--src/tools/clippy/tests/ui/default_trait_access.fixed2
-rw-r--r--src/tools/clippy/tests/ui/default_trait_access.rs2
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.rs170
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.stderr77
-rw-r--r--src/tools/clippy/tests/ui/entry.fixed15
-rw-r--r--src/tools/clippy/tests/ui/entry.rs9
-rw-r--r--src/tools/clippy/tests/ui/entry.stderr16
-rw-r--r--src/tools/clippy/tests/ui/entry_btree.fixed18
-rw-r--r--src/tools/clippy/tests/ui/entry_btree.rs18
-rw-r--r--src/tools/clippy/tests/ui/entry_btree.stderr20
-rw-r--r--src/tools/clippy/tests/ui/linkedlist.rs31
-rw-r--r--src/tools/clippy/tests/ui/linkedlist.stderr24
-rw-r--r--src/tools/clippy/tests/ui/manual_flatten.rs13
-rw-r--r--src/tools/clippy/tests/ui/manual_map_option_2.fixed50
-rw-r--r--src/tools/clippy/tests/ui/manual_map_option_2.rs56
-rw-r--r--src/tools/clippy/tests/ui/manual_map_option_2.stderr43
-rw-r--r--src/tools/clippy/tests/ui/manual_split_once.fixed50
-rw-r--r--src/tools/clippy/tests/ui/manual_split_once.rs50
-rw-r--r--src/tools/clippy/tests/ui/manual_split_once.stderr82
-rw-r--r--src/tools/clippy/tests/ui/mem_replace.fixed20
-rw-r--r--src/tools/clippy/tests/ui/mem_replace.rs20
-rw-r--r--src/tools/clippy/tests/ui/mem_replace.stderr20
-rw-r--r--src/tools/clippy/tests/ui/methods.rs5
-rw-r--r--src/tools/clippy/tests/ui/min_rust_version_attr.rs5
-rw-r--r--src/tools/clippy/tests/ui/min_rust_version_attr.stderr8
-rw-r--r--src/tools/clippy/tests/ui/missing-doc-crate.stderr0
-rw-r--r--src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.stderr0
-rw-r--r--src/tools/clippy/tests/ui/mut_range_bound.rs39
-rw-r--r--src/tools/clippy/tests/ui/mut_range_bound.stderr47
-rw-r--r--src/tools/clippy/tests/ui/needless_option_as_deref.fixed13
-rw-r--r--src/tools/clippy/tests/ui/needless_option_as_deref.rs13
-rw-r--r--src/tools/clippy/tests/ui/needless_option_as_deref.stderr16
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.fixed62
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.rs68
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.stderr72
-rw-r--r--src/tools/clippy/tests/ui/proc_macro.stderr3
-rw-r--r--src/tools/clippy/tests/ui/rc_buffer_redefined_string.stderr0
-rw-r--r--src/tools/clippy/tests/ui/rc_mutex.rs32
-rw-r--r--src/tools/clippy/tests/ui/rc_mutex.stderr33
-rw-r--r--src/tools/clippy/tests/ui/redundant_allocation.rs20
-rw-r--r--src/tools/clippy/tests/ui/redundant_allocation.stderr11
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_operation.fixed4
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_operation.stderr80
-rw-r--r--src/tools/clippy/tests/versioncheck.rs3
-rw-r--r--src/tools/linkchecker/main.rs26
m---------src/tools/miri16
-rwxr-xr-xsrc/tools/publish_toolstate.py8
-rw-r--r--src/tools/rustfmt/src/items.rs11
-rw-r--r--src/tools/rustfmt/src/lib.rs7
-rw-r--r--src/tools/rustfmt/src/macros.rs42
-rw-r--r--src/tools/rustfmt/src/modules.rs2
-rw-r--r--src/tools/rustfmt/src/types.rs59
-rw-r--r--src/tools/rustfmt/src/utils.rs4
-rw-r--r--src/tools/tidy/src/lib.rs1
-rw-r--r--src/tools/tidy/src/main.rs1
-rw-r--r--src/tools/tidy/src/primitive_docs.rs17
1071 files changed, 18270 insertions, 8392 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ff4fa1527e9..78ff874e755 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -404,6 +404,7 @@ jobs:
               RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=aarch64-pc-windows-msvc --enable-full-tools --enable-profiler"
               SCRIPT: python x.py dist
               DIST_REQUIRE_ALL_TOOLS: 0
+              WINDOWS_SDK_20348_HACK: 1
             os: windows-latest-xl
           - name: dist-i686-mingw
             env:
diff --git a/Cargo.lock b/Cargo.lock
index 5000b1e051f..f119f2050e9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -26,9 +26,9 @@ dependencies = [
 
 [[package]]
 name = "aho-corasick"
-version = "0.7.13"
+version = "0.7.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86"
+checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
 dependencies = [
  "memchr",
 ]
@@ -293,7 +293,7 @@ dependencies = [
  "humantime 2.0.1",
  "ignore",
  "im-rc",
- "itertools 0.10.0",
+ "itertools 0.10.1",
  "jobserver",
  "lazy_static",
  "lazycell",
@@ -388,7 +388,7 @@ dependencies = [
  "flate2",
  "git2",
  "glob",
- "itertools 0.10.0",
+ "itertools 0.10.1",
  "lazy_static",
  "remove_dir_all",
  "serde_json",
@@ -554,13 +554,16 @@ dependencies = [
 
 [[package]]
 name = "clippy"
-version = "0.1.56"
+version = "0.1.57"
 dependencies = [
  "cargo_metadata 0.12.0",
  "clippy_lints",
- "compiletest_rs 0.6.0",
+ "clippy_utils",
+ "compiletest_rs",
  "derive-new",
  "filetime",
+ "if_chain",
+ "itertools 0.10.1",
  "quote",
  "regex",
  "rustc-workspace-hack",
@@ -578,7 +581,7 @@ version = "0.0.1"
 dependencies = [
  "bytecount",
  "clap",
- "itertools 0.9.0",
+ "itertools 0.10.1",
  "opener",
  "regex",
  "shell-escape",
@@ -587,12 +590,12 @@ dependencies = [
 
 [[package]]
 name = "clippy_lints"
-version = "0.1.56"
+version = "0.1.57"
 dependencies = [
  "cargo_metadata 0.12.0",
  "clippy_utils",
  "if_chain",
- "itertools 0.9.0",
+ "itertools 0.10.1",
  "pulldown-cmark 0.8.0",
  "quine-mc_cluskey",
  "regex-syntax",
@@ -608,14 +611,10 @@ dependencies = [
 
 [[package]]
 name = "clippy_utils"
-version = "0.1.56"
+version = "0.1.57"
 dependencies = [
  "if_chain",
- "itertools 0.9.0",
- "regex-syntax",
  "rustc-semver",
- "serde",
- "unicode-normalization",
 ]
 
 [[package]]
@@ -690,29 +689,6 @@ dependencies = [
 
 [[package]]
 name = "compiletest_rs"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0086d6ad78cf409c3061618cd98e2789d5c9ce598fc9651611cf62eae0a599cb"
-dependencies = [
- "diff",
- "filetime",
- "getopts",
- "lazy_static",
- "libc",
- "log",
- "miow",
- "regex",
- "rustfix 0.5.1",
- "serde",
- "serde_derive",
- "serde_json",
- "tempfile",
- "tester",
- "winapi",
-]
-
-[[package]]
-name = "compiletest_rs"
 version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "64698e5e2435db061a85e6320af12c30c5fd88eb84b35d2c1e03ce4f143255ca"
@@ -1744,9 +1720,9 @@ dependencies = [
 
 [[package]]
 name = "itertools"
-version = "0.10.0"
+version = "0.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319"
+checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
 dependencies = [
  "either",
 ]
@@ -2273,7 +2249,7 @@ name = "miri"
 version = "0.1.0"
 dependencies = [
  "colored",
- "compiletest_rs 0.7.0",
+ "compiletest_rs",
  "env_logger 0.8.1",
  "getrandom 0.2.0",
  "hex 0.4.2",
@@ -3006,9 +2982,9 @@ dependencies = [
 
 [[package]]
 name = "regex"
-version = "1.4.6"
+version = "1.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759"
+checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -3622,6 +3598,33 @@ dependencies = [
 ]
 
 [[package]]
+name = "rustc_borrowck"
+version = "0.0.0"
+dependencies = [
+ "either",
+ "itertools 0.9.0",
+ "polonius-engine",
+ "rustc_const_eval",
+ "rustc_data_structures",
+ "rustc_errors",
+ "rustc_graphviz",
+ "rustc_hir",
+ "rustc_index",
+ "rustc_infer",
+ "rustc_lexer",
+ "rustc_middle",
+ "rustc_mir_dataflow",
+ "rustc_serialize",
+ "rustc_session",
+ "rustc_span",
+ "rustc_target",
+ "rustc_trait_selection",
+ "rustc_traits",
+ "smallvec",
+ "tracing",
+]
+
+[[package]]
 name = "rustc_builtin_macros"
 version = "0.0.0"
 dependencies = [
@@ -3651,6 +3654,7 @@ dependencies = [
  "libc",
  "measureme",
  "rustc-demangle",
+ "rustc_arena",
  "rustc_ast",
  "rustc_attr",
  "rustc_codegen_ssa",
@@ -3705,6 +3709,30 @@ dependencies = [
 ]
 
 [[package]]
+name = "rustc_const_eval"
+version = "0.0.0"
+dependencies = [
+ "either",
+ "gsgdt",
+ "rustc_apfloat",
+ "rustc_ast",
+ "rustc_attr",
+ "rustc_data_structures",
+ "rustc_errors",
+ "rustc_hir",
+ "rustc_index",
+ "rustc_infer",
+ "rustc_macros",
+ "rustc_middle",
+ "rustc_mir_dataflow",
+ "rustc_session",
+ "rustc_span",
+ "rustc_target",
+ "rustc_trait_selection",
+ "tracing",
+]
+
+[[package]]
 name = "rustc_data_structures"
 version = "0.0.0"
 dependencies = [
@@ -3742,6 +3770,7 @@ dependencies = [
  "rustc_ast",
  "rustc_ast_pretty",
  "rustc_codegen_ssa",
+ "rustc_const_eval",
  "rustc_data_structures",
  "rustc_error_codes",
  "rustc_errors",
@@ -3752,7 +3781,6 @@ dependencies = [
  "rustc_lint",
  "rustc_metadata",
  "rustc_middle",
- "rustc_mir",
  "rustc_parse",
  "rustc_plugin_impl",
  "rustc_save_analysis",
@@ -3911,9 +3939,11 @@ dependencies = [
  "rustc_ast_lowering",
  "rustc_ast_passes",
  "rustc_attr",
+ "rustc_borrowck",
  "rustc_builtin_macros",
  "rustc_codegen_llvm",
  "rustc_codegen_ssa",
+ "rustc_const_eval",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_expand",
@@ -3922,8 +3952,9 @@ dependencies = [
  "rustc_lint",
  "rustc_metadata",
  "rustc_middle",
- "rustc_mir",
  "rustc_mir_build",
+ "rustc_mir_transform",
+ "rustc_monomorphize",
  "rustc_parse",
  "rustc_passes",
  "rustc_plugin_impl",
@@ -4041,6 +4072,8 @@ version = "0.0.0"
 dependencies = [
  "bitflags",
  "chalk-ir",
+ "either",
+ "gsgdt",
  "polonius-engine",
  "rustc-rayon-core",
  "rustc_apfloat",
@@ -4050,6 +4083,7 @@ dependencies = [
  "rustc_data_structures",
  "rustc_errors",
  "rustc_feature",
+ "rustc_graphviz",
  "rustc_hir",
  "rustc_index",
  "rustc_macros",
@@ -4064,51 +4098,63 @@ dependencies = [
 ]
 
 [[package]]
-name = "rustc_mir"
+name = "rustc_mir_build"
 version = "0.0.0"
 dependencies = [
- "coverage_test_macros",
- "either",
- "gsgdt",
- "itertools 0.9.0",
- "polonius-engine",
- "regex",
  "rustc_apfloat",
+ "rustc_arena",
  "rustc_ast",
  "rustc_attr",
  "rustc_data_structures",
  "rustc_errors",
- "rustc_graphviz",
  "rustc_hir",
  "rustc_index",
  "rustc_infer",
- "rustc_lexer",
- "rustc_macros",
  "rustc_middle",
  "rustc_serialize",
  "rustc_session",
  "rustc_span",
  "rustc_target",
  "rustc_trait_selection",
- "rustc_traits",
  "smallvec",
  "tracing",
 ]
 
 [[package]]
-name = "rustc_mir_build"
+name = "rustc_mir_dataflow"
 version = "0.0.0"
 dependencies = [
- "rustc_apfloat",
- "rustc_arena",
+ "polonius-engine",
+ "regex",
+ "rustc_ast",
+ "rustc_data_structures",
+ "rustc_graphviz",
+ "rustc_hir",
+ "rustc_index",
+ "rustc_middle",
+ "rustc_serialize",
+ "rustc_session",
+ "rustc_span",
+ "rustc_target",
+ "smallvec",
+ "tracing",
+]
+
+[[package]]
+name = "rustc_mir_transform"
+version = "0.0.0"
+dependencies = [
+ "coverage_test_macros",
+ "itertools 0.9.0",
  "rustc_ast",
  "rustc_attr",
+ "rustc_const_eval",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_hir",
  "rustc_index",
- "rustc_infer",
  "rustc_middle",
+ "rustc_mir_dataflow",
  "rustc_serialize",
  "rustc_session",
  "rustc_span",
@@ -4119,6 +4165,22 @@ dependencies = [
 ]
 
 [[package]]
+name = "rustc_monomorphize"
+version = "0.0.0"
+dependencies = [
+ "rustc_data_structures",
+ "rustc_errors",
+ "rustc_hir",
+ "rustc_index",
+ "rustc_middle",
+ "rustc_session",
+ "rustc_span",
+ "rustc_target",
+ "smallvec",
+ "tracing",
+]
+
+[[package]]
 name = "rustc_parse"
 version = "0.0.0"
 dependencies = [
diff --git a/RELEASES.md b/RELEASES.md
index 2124195bcb2..c0851a1506e 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -10,8 +10,7 @@ Language
 
 Compiler
 --------
-- [Added tier 3\* support for `powerpc-unknown-freebsd`.][87370]
-- [Added tier 3 support for `powerpc64le-unknown-freebsd`.][83572]
+- [Added tier 3\* support for `powerpc64le-unknown-freebsd`.][83572]
 
 \* Refer to Rust's [platform support page][platform-support-doc] for more
    information on Rust's tiered platform support.
@@ -24,17 +23,6 @@ Libraries
   no longer reject certain valid floating point values, and reduce
   the produced code size for non-stripped artifacts.
 - [`string::Drain` now implements `AsRef<str>` and `AsRef<[u8]>`.][86858]
-- [`collections::{BinaryHeap, BTreeSet, HashSet, LinkedList, VecDeque}` now
-  implement `From<[T; N]>`.][84111]
-- [`collections::{BTreeMap, HashMap}` now implement `From<[(K, V); N]>`.][84111]
-  This allows you to write the following;
-  ```rust
-  let highscores = std::collections::HashMap::from([
-      ("Alice", 9000u32),
-      ("Bob", 7250),
-      ("Charlie", 5500),
-  ]);
-  ```
 
 Stabilised APIs
 ---------------
@@ -60,7 +48,6 @@ Stabilised APIs
 The following previously stable functions are now `const`.
 
 - [`str::from_utf8_unchecked`]
-- [`mem::transmute`]
 
 
 Cargo
@@ -131,7 +118,6 @@ Compatibility Notes
 [`MaybeUninit::assume_init_ref`]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.assume_init_ref
 [`MaybeUninit::write`]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.write
 [`Seek::rewind`]: https://doc.rust-lang.org/stable/std/io/trait.Seek.html#method.rewind
-[`mem::transmute`]: https://doc.rust-lang.org/stable/std/mem/fn.transmute.html
 [`ops::ControlFlow`]: https://doc.rust-lang.org/stable/std/ops/enum.ControlFlow.html
 [`str::from_utf8_unchecked`]: https://doc.rust-lang.org/stable/std/str/fn.from_utf8_unchecked.html
 [`x86::_bittest`]: https://doc.rust-lang.org/stable/core/arch/x86/fn._bittest.html
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index b92c5fa0727..c27ab810a4c 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1902,10 +1902,6 @@ pub enum TyKind {
     Never,
     /// A tuple (`(A, B, C, D,...)`).
     Tup(Vec<P<Ty>>),
-    /// An anonymous struct type i.e. `struct { foo: Type }`
-    AnonymousStruct(Vec<FieldDef>, bool),
-    /// An anonymous union type i.e. `union { bar: Type }`
-    AnonymousUnion(Vec<FieldDef>, bool),
     /// A path (`module::module::...::Type`), optionally
     /// "qualified", e.g., `<Vec<T> as SomeTrait>::SomeType`.
     ///
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 81195f7fb5c..5f17008bdc2 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -367,7 +367,7 @@ impl MetaItem {
             let is_first = i == 0;
             if !is_first {
                 let mod_sep_span =
-                    Span::new(last_pos, segment.ident.span.lo(), segment.ident.span.ctxt());
+                    Span::new(last_pos, segment.ident.span.lo(), segment.ident.span.ctxt(), None);
                 idents.push(TokenTree::token(token::ModSep, mod_sep_span).into());
             }
             idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident)).into());
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index ef3f6035085..a6167773003 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -9,14 +9,12 @@
     test(attr(deny(warnings)))
 )]
 #![feature(box_patterns)]
-#![cfg_attr(bootstrap, feature(const_fn_transmute))]
 #![feature(crate_visibility_modifier)]
 #![feature(if_let_guard)]
 #![feature(iter_zip)]
 #![feature(label_break_value)]
 #![feature(nll)]
 #![feature(min_specialization)]
-#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 2ec941cbb24..ba86036577a 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -484,9 +484,6 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
             visit_vec(bounds, |bound| vis.visit_param_bound(bound));
         }
         TyKind::MacCall(mac) => vis.visit_mac_call(mac),
-        TyKind::AnonymousStruct(fields, ..) | TyKind::AnonymousUnion(fields, ..) => {
-            fields.flat_map_in_place(|field| vis.flat_map_field_def(field));
-        }
     }
     vis.visit_span(span);
     visit_lazy_tts(tokens, vis);
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 710a592e258..3a65ffe41ae 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -586,6 +586,13 @@ impl Token {
         self.is_non_raw_ident_where(|id| id.name.is_bool_lit())
     }
 
+    pub fn is_numeric_lit(&self) -> bool {
+        matches!(
+            self.kind,
+            Literal(Lit { kind: LitKind::Integer, .. }) | Literal(Lit { kind: LitKind::Float, .. })
+        )
+    }
+
     /// Returns `true` if the token is a non-raw identifier for which `pred` holds.
     pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(Ident) -> bool) -> bool {
         match self.ident() {
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index c30f711b397..b38031042e0 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -407,9 +407,6 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
         TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
         TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {}
         TyKind::MacCall(ref mac) => visitor.visit_mac_call(mac),
-        TyKind::AnonymousStruct(ref fields, ..) | TyKind::AnonymousUnion(ref fields, ..) => {
-            walk_list!(visitor, visit_field_def, fields)
-        }
         TyKind::Never | TyKind::CVarArgs => {}
     }
 }
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 16cd7a0bcdd..ac7145bed78 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -422,7 +422,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let if_kind = hir::ExprKind::If(new_cond, self.arena.alloc(then), Some(else_expr));
         let if_expr = self.expr(span, if_kind, ThinVec::new());
         let block = self.block_expr(self.arena.alloc(if_expr));
-        hir::ExprKind::Loop(block, opt_label, hir::LoopSource::While, span.with_hi(cond.span.hi()))
+        let span = self.lower_span(span.with_hi(cond.span.hi()));
+        let opt_label = self.lower_label(opt_label);
+        hir::ExprKind::Loop(block, opt_label, hir::LoopSource::While, span)
     }
 
     /// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_output(<expr>) }`,
@@ -1450,8 +1452,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
             )
         };
 
+        // #82462: to correctly diagnose borrow errors, the block that contains
+        // the iter expr needs to have a span that covers the loop body.
+        let desugared_full_span =
+            self.mark_span_with_reason(DesugaringKind::ForLoop(ForLoopLoc::Head), e.span, None);
+
         let match_expr = self.arena.alloc(self.expr_match(
-            desugared_span,
+            desugared_full_span,
             into_iter_expr,
             arena_vec![self; iter_arm],
             hir::MatchSource::ForLoopDesugar,
@@ -1465,7 +1472,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // surrounding scope of the `match` since the `match` is not a terminating scope.
         //
         // Also, add the attributes to the outer returned expr node.
-        self.expr_drop_temps_mut(desugared_span, match_expr, attrs.into())
+        self.expr_drop_temps_mut(desugared_full_span, match_expr, attrs.into())
     }
 
     /// Desugar `ExprKind::Try` from: `<expr>?` into:
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index b7497c713f3..a77e3e1997f 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -748,10 +748,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         }
     }
 
-    pub(super) fn lower_field_def(
-        &mut self,
-        (index, f): (usize, &FieldDef),
-    ) -> hir::FieldDef<'hir> {
+    fn lower_field_def(&mut self, (index, f): (usize, &FieldDef)) -> hir::FieldDef<'hir> {
         let ty = if let TyKind::Path(ref qself, ref path) = f.ty.kind {
             let t = self.lower_path_ty(
                 &f.ty,
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index fa14764c42a..4cf54b07dbe 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -165,6 +165,8 @@ struct LoweringContext<'a, 'hir: 'a> {
 pub trait ResolverAstLowering {
     fn def_key(&mut self, id: DefId) -> DefKey;
 
+    fn def_span(&self, id: LocalDefId) -> Span;
+
     fn item_generics_num_lifetimes(&self, def: DefId) -> usize;
 
     fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option<Vec<usize>>;
@@ -216,6 +218,11 @@ impl<'a> rustc_span::HashStableContext for LoweringHasher<'a> {
     }
 
     #[inline]
+    fn def_span(&self, id: LocalDefId) -> Span {
+        self.resolver.def_span(id)
+    }
+
+    #[inline]
     fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
         self.resolver.def_path_hash(def_id)
     }
@@ -711,9 +718,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     }
 
     /// Intercept all spans entering HIR.
-    /// For now we are not doing anything with the intercepted spans.
+    /// Mark a span as relative to the current owning item.
     fn lower_span(&self, span: Span) -> Span {
-        span
+        if self.sess.opts.debugging_opts.incremental_relative_spans {
+            span.with_parent(Some(self.current_hir_id_owner.0))
+        } else {
+            // Do not make spans relative when not using incremental compilation.
+            span
+        }
     }
 
     fn lower_ident(&self, ident: Ident) -> Ident {
@@ -781,7 +793,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             node_id,
             DefPathData::LifetimeNs(str_name),
             ExpnId::root(),
-            span,
+            span.with_parent(None),
         );
 
         hir::GenericParam {
@@ -1289,15 +1301,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let kind = match t.kind {
             TyKind::Infer => hir::TyKind::Infer,
             TyKind::Err => hir::TyKind::Err,
-            // FIXME(unnamed_fields): IMPLEMENTATION IN PROGRESS
-            TyKind::AnonymousStruct(ref _fields, _recovered) => {
-                self.sess.struct_span_err(t.span, "anonymous structs are unimplemented").emit();
-                hir::TyKind::Err
-            }
-            TyKind::AnonymousUnion(ref _fields, _recovered) => {
-                self.sess.struct_span_err(t.span, "anonymous unions are unimplemented").emit();
-                hir::TyKind::Err
-            }
             TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)),
             TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)),
             TyKind::Rptr(ref region, ref mt) => {
@@ -1513,7 +1516,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         def_node_id,
                         DefPathData::LifetimeNs(name.ident().name),
                         ExpnId::root(),
-                        span,
+                        span.with_parent(None),
                     );
 
                     let (name, kind) = match name {
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index aca4503903c..24108f779c8 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -193,11 +193,6 @@ impl<'a> AstValidator<'a> {
                     }
                 }
             }
-            TyKind::AnonymousStruct(ref fields, ..) | TyKind::AnonymousUnion(ref fields, ..) => {
-                self.with_banned_assoc_ty_bound(|this| {
-                    walk_list!(this, visit_struct_field_def, fields)
-                });
-            }
             _ => visit::walk_ty(self, t),
         }
     }
@@ -205,7 +200,6 @@ impl<'a> AstValidator<'a> {
     fn visit_struct_field_def(&mut self, field: &'a FieldDef) {
         if let Some(ident) = field.ident {
             if ident.name == kw::Underscore {
-                self.check_anonymous_field(field);
                 self.visit_vis(&field.vis);
                 self.visit_ident(ident);
                 self.visit_ty_common(&field.ty);
@@ -251,66 +245,6 @@ impl<'a> AstValidator<'a> {
         err.emit();
     }
 
-    fn check_anonymous_field(&self, field: &FieldDef) {
-        let FieldDef { ty, .. } = field;
-        match &ty.kind {
-            TyKind::AnonymousStruct(..) | TyKind::AnonymousUnion(..) => {
-                // We already checked for `kw::Underscore` before calling this function,
-                // so skip the check
-            }
-            TyKind::Path(..) => {
-                // If the anonymous field contains a Path as type, we can't determine
-                // if the path is a valid struct or union, so skip the check
-            }
-            _ => {
-                let msg = "unnamed fields can only have struct or union types";
-                let label = "not a struct or union";
-                self.err_handler()
-                    .struct_span_err(field.span, msg)
-                    .span_label(ty.span, label)
-                    .emit();
-            }
-        }
-    }
-
-    fn deny_anonymous_struct(&self, ty: &Ty) {
-        match &ty.kind {
-            TyKind::AnonymousStruct(..) => {
-                self.err_handler()
-                    .struct_span_err(
-                        ty.span,
-                        "anonymous structs are not allowed outside of unnamed struct or union fields",
-                    )
-                    .span_label(ty.span, "anonymous struct declared here")
-                    .emit();
-            }
-            TyKind::AnonymousUnion(..) => {
-                self.err_handler()
-                    .struct_span_err(
-                        ty.span,
-                        "anonymous unions are not allowed outside of unnamed struct or union fields",
-                    )
-                    .span_label(ty.span, "anonymous union declared here")
-                    .emit();
-            }
-            _ => {}
-        }
-    }
-
-    fn deny_anonymous_field(&self, field: &FieldDef) {
-        if let Some(ident) = field.ident {
-            if ident.name == kw::Underscore {
-                self.err_handler()
-                    .struct_span_err(
-                        field.span,
-                        "anonymous fields are not allowed outside of structs or unions",
-                    )
-                    .span_label(ident.span, "anonymous field declared here")
-                    .emit()
-            }
-        }
-    }
-
     fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
         for Param { pat, .. } in &decl.inputs {
             match pat.kind {
@@ -422,11 +356,25 @@ impl<'a> AstValidator<'a> {
     }
 
     fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
+        self.check_decl_num_args(fn_decl);
         self.check_decl_cvaradic_pos(fn_decl);
         self.check_decl_attrs(fn_decl);
         self.check_decl_self_param(fn_decl, self_semantic);
     }
 
+    /// Emits fatal error if function declaration has more than `u16::MAX` arguments
+    /// Error is fatal to prevent errors during typechecking
+    fn check_decl_num_args(&self, fn_decl: &FnDecl) {
+        let max_num_args: usize = u16::MAX.into();
+        if fn_decl.inputs.len() > max_num_args {
+            let Param { span, .. } = fn_decl.inputs[0];
+            self.err_handler().span_fatal(
+                span,
+                &format!("function can not have more than {} arguments", max_num_args),
+            );
+        }
+    }
+
     fn check_decl_cvaradic_pos(&self, fn_decl: &FnDecl) {
         match &*fn_decl.inputs {
             [Param { ty, span, .. }] => {
@@ -1067,7 +1015,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
 
     fn visit_ty(&mut self, ty: &'a Ty) {
         self.visit_ty_common(ty);
-        self.deny_anonymous_struct(ty);
         self.walk_ty(ty)
     }
 
@@ -1082,7 +1029,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
     }
 
     fn visit_field_def(&mut self, s: &'a FieldDef) {
-        self.deny_anonymous_field(s);
         visit::walk_field_def(self, s)
     }
 
@@ -1655,7 +1601,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 walk_list!(self, visit_ty, ty);
             }
             AssocItemKind::Fn(box FnKind(_, ref sig, ref generics, ref body))
-                if self.in_const_trait_impl || ctxt == AssocCtxt::Trait =>
+                if self.in_const_trait_impl
+                    || ctxt == AssocCtxt::Trait
+                    || matches!(sig.header.constness, Const::Yes(_)) =>
             {
                 self.visit_vis(&item.vis);
                 self.visit_ident(item.ident);
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 1defb65ed87..30bc4edd7e6 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -668,7 +668,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
         // involved, so we only emit errors where there are no other parsing errors.
         gate_all!(destructuring_assignment, "destructuring assignments are unstable");
     }
-    gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented");
 
     // All uses of `gate_all!` below this point were added in #65742,
     // and subsequently disabled (with the non-early gating readded).
diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs
index 6cde7d2bbd2..47666670b2b 100644
--- a/compiler/rustc_ast_passes/src/lib.rs
+++ b/compiler/rustc_ast_passes/src/lib.rs
@@ -4,7 +4,6 @@
 //!
 //! The crate also contains other misc AST visitors, e.g. `node_count` and `show_span`.
 
-#![cfg_attr(bootstrap, feature(bindings_after_at))]
 #![feature(iter_is_partitioned)]
 #![feature(box_patterns)]
 #![recursion_limit = "256"]
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 3cf04be160c..c24882086e1 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -985,14 +985,6 @@ impl<'a> State<'a> {
                 }
                 self.pclose();
             }
-            ast::TyKind::AnonymousStruct(ref fields, ..) => {
-                self.head("struct");
-                self.print_record_struct_body(&fields, ty.span);
-            }
-            ast::TyKind::AnonymousUnion(ref fields, ..) => {
-                self.head("union");
-                self.print_record_struct_body(&fields, ty.span);
-            }
             ast::TyKind::Paren(ref typ) => {
                 self.popen();
                 self.print_type(typ);
@@ -1413,7 +1405,12 @@ impl<'a> State<'a> {
         }
     }
 
-    crate fn print_record_struct_body(&mut self, fields: &[ast::FieldDef], span: rustc_span::Span) {
+    crate fn print_record_struct_body(
+        &mut self,
+        fields: &Vec<ast::FieldDef>,
+        span: rustc_span::Span,
+    ) {
+        self.nbsp();
         self.bopen();
         self.hardbreak_if_not_bol();
 
@@ -1462,7 +1459,6 @@ impl<'a> State<'a> {
             }
             ast::VariantData::Struct(ref fields, ..) => {
                 self.print_where_clause(&generics.where_clause);
-                self.nbsp();
                 self.print_record_struct_body(fields, span);
             }
         }
diff --git a/compiler/rustc_mir/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml
index 3049fb3b383..c683c388ba9 100644
--- a/compiler/rustc_mir/Cargo.toml
+++ b/compiler/rustc_borrowck/Cargo.toml
@@ -1,5 +1,5 @@
 [package]
-name = "rustc_mir"
+name = "rustc_borrowck"
 version = "0.0.0"
 edition = "2018"
 
@@ -8,30 +8,23 @@ doctest = false
 
 [dependencies]
 either = "1.5.0"
-rustc_graphviz = { path = "../rustc_graphviz" }
-gsgdt = "0.1.2"
 itertools = "0.9"
 tracing = "0.1"
 polonius-engine = "0.13.0"
-regex = "1"
-rustc_middle = { path = "../rustc_middle" }
-rustc_attr = { path = "../rustc_attr" }
+smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
+rustc_graphviz = { path = "../rustc_graphviz" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
 rustc_infer = { path = "../rustc_infer" }
 rustc_lexer = { path = "../rustc_lexer" }
-rustc_macros = { path = "../rustc_macros" }
+rustc_middle = { path = "../rustc_middle" }
+rustc_const_eval = { path = "../rustc_const_eval" }
+rustc_mir_dataflow = { path = "../rustc_mir_dataflow" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
 rustc_traits = { path = "../rustc_traits" }
-rustc_ast = { path = "../rustc_ast" }
 rustc_span = { path = "../rustc_span" }
-rustc_apfloat = { path = "../rustc_apfloat" }
-smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
-
-[dev-dependencies]
-coverage_test_macros = { path = "src/transform/coverage/test_macros" }
diff --git a/compiler/rustc_mir/src/borrow_check/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs
index 288eda32e41..ee2ce1d3f74 100644
--- a/compiler/rustc_mir/src/borrow_check/borrow_set.rs
+++ b/compiler/rustc_borrowck/src/borrow_set.rs
@@ -1,14 +1,14 @@
-use crate::borrow_check::nll::ToRegionVid;
-use crate::borrow_check::path_utils::allow_two_phase_borrow;
-use crate::borrow_check::place_ext::PlaceExt;
-use crate::dataflow::indexes::BorrowIndex;
-use crate::dataflow::move_paths::MoveData;
+use crate::nll::ToRegionVid;
+use crate::path_utils::allow_two_phase_borrow;
+use crate::place_ext::PlaceExt;
+use crate::BorrowIndex;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::traversal;
 use rustc_middle::mir::visit::{MutatingUseContext, NonUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::{self, Body, Local, Location};
 use rustc_middle::ty::{RegionVid, TyCtxt};
+use rustc_mir_dataflow::move_paths::MoveData;
 use std::fmt;
 use std::ops::Index;
 
diff --git a/compiler/rustc_mir/src/util/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
index 56d8045813c..5702203d7c4 100644
--- a/compiler/rustc_mir/src/util/borrowck_errors.rs
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -2,7 +2,7 @@ use rustc_errors::{struct_span_err, DiagnosticBuilder, DiagnosticId};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::{MultiSpan, Span};
 
-impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> {
+impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
     crate fn cannot_move_when_borrowed(&self, span: Span, desc: &str) -> DiagnosticBuilder<'cx> {
         struct_span_err!(self, span, E0505, "cannot move out of {} because it is borrowed", desc,)
     }
diff --git a/compiler/rustc_mir/src/borrow_check/constraint_generation.rs b/compiler/rustc_borrowck/src/constraint_generation.rs
index c84928523d9..a40f148cdf8 100644
--- a/compiler/rustc_mir/src/borrow_check/constraint_generation.rs
+++ b/compiler/rustc_borrowck/src/constraint_generation.rs
@@ -9,7 +9,7 @@ use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, RegionVid, Ty};
 
-use crate::borrow_check::{
+use crate::{
     borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, nll::ToRegionVid,
     places_conflict, region_infer::values::LivenessValues,
 };
diff --git a/compiler/rustc_mir/src/borrow_check/constraints/graph.rs b/compiler/rustc_borrowck/src/constraints/graph.rs
index 9e4cfb2cc00..cb9e0234c49 100644
--- a/compiler/rustc_mir/src/borrow_check/constraints/graph.rs
+++ b/compiler/rustc_borrowck/src/constraints/graph.rs
@@ -4,7 +4,7 @@ use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::{RegionVid, VarianceDiagInfo};
 use rustc_span::DUMMY_SP;
 
-use crate::borrow_check::{
+use crate::{
     constraints::OutlivesConstraintIndex,
     constraints::{OutlivesConstraint, OutlivesConstraintSet},
     type_check::Locations,
diff --git a/compiler/rustc_mir/src/borrow_check/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs
index b944479ca45..98378a98684 100644
--- a/compiler/rustc_mir/src/borrow_check/constraints/mod.rs
+++ b/compiler/rustc_borrowck/src/constraints/mod.rs
@@ -5,7 +5,7 @@ use rustc_middle::ty::{RegionVid, VarianceDiagInfo};
 use std::fmt;
 use std::ops::Index;
 
-use crate::borrow_check::type_check::Locations;
+use crate::type_check::Locations;
 
 crate mod graph;
 
diff --git a/compiler/rustc_mir/src/borrow_check/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index f6e4e388841..4333038a6f9 100644
--- a/compiler/rustc_mir/src/borrow_check/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -14,7 +14,9 @@ pub use super::{
 };
 
 /// This function computes Polonius facts for the given body. It makes a copy of
-/// the body because it needs to regenerate the region identifiers.
+/// the body because it needs to regenerate the region identifiers. This function
+/// should never be invoked during a typical compilation session due to performance
+/// issues with Polonius.
 ///
 /// Note:
 /// *   This function will panic if the required body was already stolen. This
@@ -22,8 +24,6 @@ pub use super::{
 ///     because they are evaluated during typechecking. The panic can be avoided
 ///     by overriding the `mir_borrowck` query. You can find a complete example
 ///     that shows how to do this at `src/test/run-make/obtain-borrowck/`.
-/// *   This function will also panic if computation of Polonius facts
-///     (`-Zpolonius` flag) is not enabled.
 ///
 /// *   Polonius is highly unstable, so expect regular changes in its signature or other details.
 pub fn get_body_with_borrowck_facts<'tcx>(
diff --git a/compiler/rustc_mir/src/dataflow/impls/borrows.rs b/compiler/rustc_borrowck/src/dataflow.rs
index c92cff1433f..1e660ece908 100644
--- a/compiler/rustc_mir/src/dataflow/impls/borrows.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -1,17 +1,110 @@
-use rustc_middle::mir::{self, Body, Location, Place};
-use rustc_middle::ty::RegionVid;
-use rustc_middle::ty::TyCtxt;
-
 use rustc_data_structures::fx::FxHashMap;
 use rustc_index::bit_set::BitSet;
+use rustc_middle::mir::{self, BasicBlock, Body, Location, Place};
+use rustc_middle::ty::RegionVid;
+use rustc_middle::ty::TyCtxt;
+use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
+use rustc_mir_dataflow::ResultsVisitable;
+use rustc_mir_dataflow::{self, fmt::DebugWithContext, GenKill};
+use rustc_mir_dataflow::{Analysis, Direction, Results};
+use std::fmt;
+use std::iter;
 
-use crate::borrow_check::{
+use crate::{
     places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, ToRegionVid,
 };
-use crate::dataflow::{self, fmt::DebugWithContext, GenKill};
 
-use std::fmt;
-use std::iter;
+/// A tuple with named fields that can hold either the results or the transient state of the
+/// dataflow analyses used by the borrow checker.
+#[derive(Debug)]
+pub struct BorrowckAnalyses<B, U, E> {
+    pub borrows: B,
+    pub uninits: U,
+    pub ever_inits: E,
+}
+
+/// The results of the dataflow analyses used by the borrow checker.
+pub type BorrowckResults<'mir, 'tcx> = BorrowckAnalyses<
+    Results<'tcx, Borrows<'mir, 'tcx>>,
+    Results<'tcx, MaybeUninitializedPlaces<'mir, 'tcx>>,
+    Results<'tcx, EverInitializedPlaces<'mir, 'tcx>>,
+>;
+
+/// The transient state of the dataflow analyses used by the borrow checker.
+pub type BorrowckFlowState<'mir, 'tcx> =
+    <BorrowckResults<'mir, 'tcx> as ResultsVisitable<'tcx>>::FlowState;
+
+macro_rules! impl_visitable {
+    ( $(
+        $T:ident { $( $field:ident : $A:ident ),* $(,)? }
+    )* ) => { $(
+        impl<'tcx, $($A),*, D: Direction> ResultsVisitable<'tcx> for $T<$( Results<'tcx, $A> ),*>
+        where
+            $( $A: Analysis<'tcx, Direction = D>, )*
+        {
+            type Direction = D;
+            type FlowState = $T<$( $A::Domain ),*>;
+
+            fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
+                $T {
+                    $( $field: self.$field.analysis.bottom_value(body) ),*
+                }
+            }
+
+            fn reset_to_block_entry(
+                &self,
+                state: &mut Self::FlowState,
+                block: BasicBlock,
+            ) {
+                $( state.$field.clone_from(&self.$field.entry_set_for_block(block)); )*
+            }
+
+            fn reconstruct_before_statement_effect(
+                &self,
+                state: &mut Self::FlowState,
+                stmt: &mir::Statement<'tcx>,
+                loc: Location,
+            ) {
+                $( self.$field.analysis
+                    .apply_before_statement_effect(&mut state.$field, stmt, loc); )*
+            }
+
+            fn reconstruct_statement_effect(
+                &self,
+                state: &mut Self::FlowState,
+                stmt: &mir::Statement<'tcx>,
+                loc: Location,
+            ) {
+                $( self.$field.analysis
+                    .apply_statement_effect(&mut state.$field, stmt, loc); )*
+            }
+
+            fn reconstruct_before_terminator_effect(
+                &self,
+                state: &mut Self::FlowState,
+                term: &mir::Terminator<'tcx>,
+                loc: Location,
+            ) {
+                $( self.$field.analysis
+                    .apply_before_terminator_effect(&mut state.$field, term, loc); )*
+            }
+
+            fn reconstruct_terminator_effect(
+                &self,
+                state: &mut Self::FlowState,
+                term: &mir::Terminator<'tcx>,
+                loc: Location,
+            ) {
+                $( self.$field.analysis
+                    .apply_terminator_effect(&mut state.$field, term, loc); )*
+            }
+        }
+    )* }
+}
+
+impl_visitable! {
+    BorrowckAnalyses { borrows: B, uninits: U, ever_inits: E }
+}
 
 rustc_index::newtype_index! {
     pub struct BorrowIndex {
@@ -230,7 +323,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
     }
 }
 
-impl<'tcx> dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
+impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
     type Domain = BitSet<BorrowIndex>;
 
     const NAME: &'static str = "borrows";
@@ -246,7 +339,7 @@ impl<'tcx> dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
     }
 }
 
-impl<'tcx> dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
+impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
     type Idx = BorrowIndex;
 
     fn before_statement_effect(
diff --git a/compiler/rustc_mir/src/borrow_check/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs
index 689ec249a2f..689ec249a2f 100644
--- a/compiler/rustc_mir/src/borrow_check/def_use.rs
+++ b/compiler/rustc_borrowck/src/def_use.rs
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index ac30093ba82..76e779bfec6 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -14,8 +14,8 @@ use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_
 use std::fmt;
 use std::rc::Rc;
 
-use crate::borrow_check::region_infer::values::RegionElement;
-use crate::borrow_check::MirBorrowckCtxt;
+use crate::region_infer::values::RegionElement;
+use crate::MirBorrowckCtxt;
 
 #[derive(Clone)]
 crate struct UniverseInfo<'tcx>(UniverseInfoInner<'tcx>);
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 6561fe37c1c..f4cbbb60b05 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -10,16 +10,16 @@ use rustc_middle::mir::{
     ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
 };
 use rustc_middle::ty::{self, suggest_constraining_type_param, Ty};
+use rustc_mir_dataflow::drop_flag_effects;
+use rustc_mir_dataflow::move_paths::{MoveOutIndex, MovePathIndex};
 use rustc_span::source_map::DesugaringKind;
 use rustc_span::symbol::sym;
 use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP};
 use rustc_trait_selection::infer::InferCtxtExt;
 
-use crate::dataflow::drop_flag_effects;
-use crate::dataflow::indexes::{MoveOutIndex, MovePathIndex};
-use crate::util::borrowck_errors;
+use crate::borrowck_errors;
 
-use crate::borrow_check::{
+use crate::{
     borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
     InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind,
 };
@@ -49,7 +49,7 @@ enum StorageDeadOrDrop<'tcx> {
 }
 
 impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
-    pub(in crate::borrow_check) fn report_use_of_moved_or_uninitialized(
+    pub(crate) fn report_use_of_moved_or_uninitialized(
         &mut self,
         location: Location,
         desired_action: InitializationRequiringAction,
@@ -218,7 +218,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             );
                             if self.fn_self_span_reported.insert(fn_span) {
                                 err.span_note(
-                                    self_arg.span,
+                                    // Check whether the source is accessible
+                                    if self
+                                        .infcx
+                                        .tcx
+                                        .sess
+                                        .source_map()
+                                        .span_to_snippet(self_arg.span)
+                                        .is_ok()
+                                    {
+                                        self_arg.span
+                                    } else {
+                                        fn_call_span
+                                    },
                                     "calling this operator moves the left-hand side",
                                 );
                             }
@@ -429,7 +441,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     deref_target_ty
                 ));
 
-                err.span_note(deref_target, "deref defined here");
+                // Check first whether the source is accessible (issue #87060)
+                if self.infcx.tcx.sess.source_map().span_to_snippet(deref_target).is_ok() {
+                    err.span_note(deref_target, "deref defined here");
+                }
             }
 
             if let Some((_, mut old_err)) =
@@ -441,7 +456,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         }
     }
 
-    pub(in crate::borrow_check) fn report_move_out_while_borrowed(
+    pub(crate) fn report_move_out_while_borrowed(
         &mut self,
         location: Location,
         (place, span): (Place<'tcx>, Span),
@@ -489,7 +504,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         err.buffer(&mut self.errors_buffer);
     }
 
-    pub(in crate::borrow_check) fn report_use_while_mutably_borrowed(
+    pub(crate) fn report_use_while_mutably_borrowed(
         &mut self,
         location: Location,
         (place, _span): (Place<'tcx>, Span),
@@ -535,7 +550,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         err
     }
 
-    pub(in crate::borrow_check) fn report_conflicting_borrow(
+    pub(crate) fn report_conflicting_borrow(
         &mut self,
         location: Location,
         (place, span): (Place<'tcx>, Span),
@@ -798,7 +813,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// cannot borrow `a.u` (via `a.u.z.c`) as immutable because it is also borrowed as
     /// mutable (via `a.u.s.b`) [E0502]
     /// ```
-    pub(in crate::borrow_check) fn describe_place_for_conflicting_borrow(
+    pub(crate) fn describe_place_for_conflicting_borrow(
         &self,
         first_borrowed_place: Place<'tcx>,
         second_borrowed_place: Place<'tcx>,
@@ -875,7 +890,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// short a lifetime. (But sometimes it is more useful to report
     /// it as a more direct conflict between the execution of a
     /// `Drop::drop` with an aliasing borrow.)
-    pub(in crate::borrow_check) fn report_borrowed_value_does_not_live_long_enough(
+    pub(crate) fn report_borrowed_value_does_not_live_long_enough(
         &mut self,
         location: Location,
         borrow: &BorrowData<'tcx>,
@@ -1634,7 +1649,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         (result, reinits_reachable)
     }
 
-    pub(in crate::borrow_check) fn report_illegal_mutation_of_borrowed(
+    pub(crate) fn report_illegal_mutation_of_borrowed(
         &mut self,
         location: Location,
         (place, span): (Place<'tcx>, Span),
@@ -1695,7 +1710,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             Some((method_did, method_substs)),
         ) = (
             &self.body[loan.reserve_location.block].terminator,
-            crate::util::find_self_call(
+            rustc_const_eval::util::find_self_call(
                 tcx,
                 self.body,
                 loan.assigned_place.local,
@@ -1726,7 +1741,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// assigned; `err_place` is a place providing a reason why
     /// `place` is not mutable (e.g., the non-`mut` local `x` in an
     /// assignment to `x.f`).
-    pub(in crate::borrow_check) fn report_illegal_reassignment(
+    pub(crate) fn report_illegal_reassignment(
         &mut self,
         _location: Location,
         (place, span): (Place<'tcx>, Span),
@@ -2226,7 +2241,7 @@ enum AnnotatedBorrowFnSignature<'tcx> {
 impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
     /// Annotate the provided diagnostic with information about borrow from the fn signature that
     /// helps explain.
-    pub(in crate::borrow_check) fn emit(
+    pub(crate) fn emit(
         &self,
         cx: &mut MirBorrowckCtxt<'_, 'tcx>,
         diag: &mut DiagnosticBuilder<'_>,
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index f40a2db330a..2d12a682e7a 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -15,8 +15,8 @@ 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::{
+use crate::region_infer::BlameConstraint;
+use crate::{
     borrow_set::BorrowData, nll::ConstraintDescription, region_infer::Cause, MirBorrowckCtxt,
     WriteKind,
 };
@@ -24,7 +24,7 @@ use crate::borrow_check::{
 use super::{find_use, RegionName, UseSpans};
 
 #[derive(Debug)]
-pub(in crate::borrow_check) enum BorrowExplanation {
+pub(crate) enum BorrowExplanation {
     UsedLater(LaterUseKind, Span, Option<Span>),
     UsedLaterInLoop(LaterUseKind, Span, Option<Span>),
     UsedLaterWhenDropped {
@@ -43,7 +43,7 @@ pub(in crate::borrow_check) enum BorrowExplanation {
 }
 
 #[derive(Clone, Copy, Debug)]
-pub(in crate::borrow_check) enum LaterUseKind {
+pub(crate) enum LaterUseKind {
     TraitCapture,
     ClosureCapture,
     Call,
@@ -52,13 +52,13 @@ pub(in crate::borrow_check) enum LaterUseKind {
 }
 
 impl BorrowExplanation {
-    pub(in crate::borrow_check) fn is_explained(&self) -> bool {
+    pub(crate) fn is_explained(&self) -> bool {
         match self {
             BorrowExplanation::Unexplained => false,
             _ => true,
         }
     }
-    pub(in crate::borrow_check) fn add_explanation_to_diagnostic<'tcx>(
+    pub(crate) fn add_explanation_to_diagnostic<'tcx>(
         &self,
         tcx: TyCtxt<'tcx>,
         body: &Body<'tcx>,
@@ -267,7 +267,7 @@ impl BorrowExplanation {
             _ => {}
         }
     }
-    pub(in crate::borrow_check) fn add_lifetime_bound_suggestion_to_diagnostic(
+    pub(crate) fn add_lifetime_bound_suggestion_to_diagnostic(
         &self,
         err: &mut DiagnosticBuilder<'_>,
         category: &ConstraintCategory,
@@ -326,7 +326,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     ///   - second half is the place being accessed
     ///
     /// [d]: https://rust-lang.github.io/rfcs/2094-nll.html#leveraging-intuition-framing-errors-in-terms-of-points
-    pub(in crate::borrow_check) fn explain_why_borrow_contains_point(
+    pub(crate) fn explain_why_borrow_contains_point(
         &self,
         location: Location,
         borrow: &BorrowData<'tcx>,
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs
index 8d8cdfb5293..ab4536f00fc 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/find_use.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs
@@ -1,7 +1,7 @@
 use std::collections::VecDeque;
 use std::rc::Rc;
 
-use crate::borrow_check::{
+use crate::{
     def_use::{self, DefUse},
     nll::ToRegionVid,
     region_infer::{Cause, RegionInferenceContext},
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 55c6410ed32..50130dc2a27 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -12,6 +12,7 @@ use rustc_middle::mir::{
 };
 use rustc_middle::ty::print::Print;
 use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt};
+use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
 use rustc_span::{
     hygiene::{DesugaringKind, ForLoopLoc},
     symbol::sym,
@@ -21,7 +22,6 @@ use rustc_target::abi::VariantIdx;
 
 use super::borrow_set::BorrowData;
 use super::MirBorrowckCtxt;
-use crate::dataflow::move_paths::{InitLocation, LookupResult};
 
 mod find_use;
 mod outlives_suggestion;
@@ -900,8 +900,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         }) = &self.body[location.block].terminator
         {
             let (method_did, method_substs) = if let Some(info) =
-                crate::util::find_self_call(self.infcx.tcx, &self.body, target_temp, location.block)
-            {
+                rustc_const_eval::util::find_self_call(
+                    self.infcx.tcx,
+                    &self.body,
+                    target_temp,
+                    location.block,
+                ) {
                 info
             } else {
                 return normal_ret;
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 66e06325fa9..3c114084586 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -2,16 +2,16 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::mir::*;
 use rustc_middle::ty;
+use rustc_mir_dataflow::move_paths::{
+    IllegalMoveOrigin, IllegalMoveOriginKind, LookupResult, MoveError, MovePathIndex,
+};
 use rustc_span::source_map::DesugaringKind;
 use rustc_span::{sym, Span, DUMMY_SP};
 use rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions;
 
-use crate::borrow_check::diagnostics::UseSpans;
-use crate::borrow_check::prefixes::PrefixSet;
-use crate::borrow_check::MirBorrowckCtxt;
-use crate::dataflow::move_paths::{
-    IllegalMoveOrigin, IllegalMoveOriginKind, LookupResult, MoveError, MovePathIndex,
-};
+use crate::diagnostics::UseSpans;
+use crate::prefixes::PrefixSet;
+use crate::MirBorrowckCtxt;
 
 // Often when desugaring a pattern match we may have many individual moves in
 // MIR that are all part of one operation from the user's point-of-view. For
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 4e079ed865a..7ca72cbed8d 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -14,9 +14,9 @@ use rustc_span::source_map::DesugaringKind;
 use rustc_span::symbol::{kw, Symbol};
 use rustc_span::{BytePos, Span};
 
-use crate::borrow_check::diagnostics::BorrowedContentSource;
-use crate::borrow_check::MirBorrowckCtxt;
-use crate::util::collect_writes::FindAssignments;
+use crate::diagnostics::BorrowedContentSource;
+use crate::MirBorrowckCtxt;
+use rustc_const_eval::util::collect_writes::FindAssignments;
 use rustc_errors::{Applicability, DiagnosticBuilder};
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
index 7dc3434bf33..9de0c62f186 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/outlives_suggestion.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
@@ -1,16 +1,14 @@
 //! Contains utilities for generating suggestions for borrowck errors related to unsatisfied
 //! outlives constraints.
 
-use std::collections::BTreeMap;
-
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::DiagnosticBuilder;
 use rustc_middle::ty::RegionVid;
-use tracing::debug;
-
 use smallvec::SmallVec;
+use std::collections::BTreeMap;
+use tracing::debug;
 
-use crate::borrow_check::MirBorrowckCtxt;
+use crate::MirBorrowckCtxt;
 
 use super::{ErrorConstraintInfo, RegionName, RegionNameSource};
 
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index cbb8f064bb8..57d2a3c5ce9 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -11,10 +11,10 @@ use rustc_middle::ty::{self, RegionVid, Ty};
 use rustc_span::symbol::{kw, sym};
 use rustc_span::{BytePos, Span};
 
-use crate::util::borrowck_errors;
+use crate::borrowck_errors;
 
-use crate::borrow_check::region_infer::BlameConstraint;
-use crate::borrow_check::{
+use crate::region_infer::BlameConstraint;
+use crate::{
     nll::ConstraintDescription,
     region_infer::{values::RegionElement, TypeTest},
     universal_regions::DefiningTy,
@@ -152,7 +152,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     }
 
     /// Produces nice borrowck error diagnostics for all the errors collected in `nll_errors`.
-    pub(in crate::borrow_check) fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) {
+    pub(crate) fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) {
         // Iterate through all the errors, producing a diagnostic for each one. The diagnostics are
         // buffered in the `MirBorrowckCtxt`.
 
@@ -265,7 +265,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     /// ```
     ///
     /// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
-    pub(in crate::borrow_check) fn report_region_error(
+    pub(crate) fn report_region_error(
         &mut self,
         fr: RegionVid,
         fr_origin: NllRegionVariableOrigin,
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 1f168c612f1..5edb52b0b65 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -10,7 +10,7 @@ use rustc_middle::ty::{self, RegionVid, Ty};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 
-use crate::borrow_check::{nll::ToRegionVid, universal_regions::DefiningTy, MirBorrowckCtxt};
+use crate::{nll::ToRegionVid, universal_regions::DefiningTy, MirBorrowckCtxt};
 
 /// A name for a particular region used in emitting diagnostics. This name could be a generated
 /// name like `'1`, a name used by the user like `'a`, or a name like `'static`.
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs
index 4abc623fc5f..00f62806753 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/var_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs
@@ -1,5 +1,5 @@
-use crate::borrow_check::Upvar;
-use crate::borrow_check::{nll::ToRegionVid, region_infer::RegionInferenceContext};
+use crate::Upvar;
+use crate::{nll::ToRegionVid, region_infer::RegionInferenceContext};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::mir::{Body, Local};
 use rustc_middle::ty::{RegionVid, TyCtxt};
diff --git a/compiler/rustc_mir/src/borrow_check/facts.rs b/compiler/rustc_borrowck/src/facts.rs
index 215dead5bd1..86b719bdfa0 100644
--- a/compiler/rustc_mir/src/borrow_check/facts.rs
+++ b/compiler/rustc_borrowck/src/facts.rs
@@ -1,10 +1,11 @@
-use crate::borrow_check::location::{LocationIndex, LocationTable};
-use crate::dataflow::indexes::{BorrowIndex, MovePathIndex};
+use crate::location::{LocationIndex, LocationTable};
+use crate::BorrowIndex;
 use polonius_engine::AllFacts as PoloniusFacts;
 use polonius_engine::Atom;
 use rustc_index::vec::Idx;
 use rustc_middle::mir::Local;
 use rustc_middle::ty::{RegionVid, TyCtxt};
+use rustc_mir_dataflow::move_paths::MovePathIndex;
 use std::error::Error;
 use std::fmt::Debug;
 use std::fs::{self, File};
@@ -100,12 +101,6 @@ impl Atom for LocationIndex {
     }
 }
 
-impl Atom for MovePathIndex {
-    fn index(self) -> usize {
-        Idx::index(self)
-    }
-}
-
 struct FactWriter<'w> {
     location_table: &'w LocationTable,
     dir: &'w Path,
diff --git a/compiler/rustc_mir/src/borrow_check/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs
index b83a427f475..016fe0bb6de 100644
--- a/compiler/rustc_mir/src/borrow_check/invalidation.rs
+++ b/compiler/rustc_borrowck/src/invalidation.rs
@@ -7,12 +7,10 @@ use rustc_middle::mir::{Statement, StatementKind};
 use rustc_middle::ty::TyCtxt;
 use std::iter;
 
-use crate::dataflow::indexes::BorrowIndex;
-
-use crate::borrow_check::{
+use crate::{
     borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, path_utils::*, AccessDepth,
-    Activation, ArtificialField, Deep, JustWrite, LocalMutationIsAllowed, MutateMode, Read,
-    ReadKind, ReadOrWrite, Reservation, Shallow, Write, WriteAndRead, WriteKind,
+    Activation, ArtificialField, BorrowIndex, Deep, JustWrite, LocalMutationIsAllowed, MutateMode,
+    Read, ReadKind, ReadOrWrite, Reservation, Shallow, Write, WriteAndRead, WriteKind,
 };
 
 pub(super) fn generate_invalidates<'tcx>(
diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_borrowck/src/lib.rs
index 1dcb0676562..b3b7d7e02cc 100644
--- a/compiler/rustc_mir/src/borrow_check/mod.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -1,5 +1,23 @@
 //! This query borrow-checks the MIR to (further) ensure it is not broken.
 
+#![feature(bool_to_option)]
+#![feature(box_patterns)]
+#![feature(const_panic)]
+#![feature(crate_visibility_modifier)]
+#![feature(format_args_capture)]
+#![feature(in_band_lifetimes)]
+#![feature(iter_zip)]
+#![feature(min_specialization)]
+#![feature(stmt_expr_attributes)]
+#![feature(trusted_step)]
+#![feature(try_blocks)]
+#![recursion_limit = "256"]
+
+#[macro_use]
+extern crate rustc_middle;
+#[macro_use]
+extern crate tracing;
+
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorReported};
@@ -29,14 +47,13 @@ use std::iter;
 use std::mem;
 use std::rc::Rc;
 
-use crate::dataflow;
-use crate::dataflow::impls::{
-    Borrows, EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces,
+use rustc_mir_dataflow::impls::{
+    EverInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces,
 };
-use crate::dataflow::indexes::{BorrowIndex, InitIndex, MoveOutIndex, MovePathIndex};
-use crate::dataflow::move_paths::{InitLocation, LookupResult, MoveData, MoveError};
-use crate::dataflow::MoveDataParamEnv;
-use crate::dataflow::{Analysis, BorrowckFlowState as Flows, BorrowckResults};
+use rustc_mir_dataflow::move_paths::{InitIndex, MoveOutIndex, MovePathIndex};
+use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult, MoveData, MoveError};
+use rustc_mir_dataflow::Analysis;
+use rustc_mir_dataflow::MoveDataParamEnv;
 
 use self::diagnostics::{AccessKind, RegionName};
 use self::location::LocationTable;
@@ -47,9 +64,10 @@ use facts::AllFacts;
 use self::path_utils::*;
 
 mod borrow_set;
+mod borrowck_errors;
 mod constraint_generation;
 mod constraints;
-pub mod consumers;
+mod dataflow;
 mod def_use;
 mod diagnostics;
 mod facts;
@@ -67,15 +85,19 @@ mod type_check;
 mod universal_regions;
 mod used_muts;
 
-crate use borrow_set::{BorrowData, BorrowSet};
-crate use nll::{PoloniusOutput, ToRegionVid};
-crate use place_ext::PlaceExt;
-crate use places_conflict::{places_conflict, PlaceConflictBias};
-crate use region_infer::RegionInferenceContext;
+// A public API provided for the Rust compiler consumers.
+pub mod consumers;
+
+use borrow_set::{BorrowData, BorrowSet};
+use dataflow::{BorrowIndex, BorrowckFlowState as Flows, BorrowckResults, Borrows};
+use nll::{PoloniusOutput, ToRegionVid};
+use place_ext::PlaceExt;
+use places_conflict::{places_conflict, PlaceConflictBias};
+use region_infer::RegionInferenceContext;
 
 // FIXME(eddyb) perhaps move this somewhere more centrally.
 #[derive(Debug)]
-crate struct Upvar<'tcx> {
+struct Upvar<'tcx> {
     place: CapturedPlace<'tcx>,
 
     /// If true, the capture is behind a reference.
@@ -132,11 +154,6 @@ fn do_mir_borrowck<'a, 'tcx>(
 
     debug!("do_mir_borrowck(def = {:?})", def);
 
-    assert!(
-        !return_body_with_facts || infcx.tcx.sess.opts.debugging_opts.polonius,
-        "borrowck facts can be requested only when Polonius is enabled"
-    );
-
     let tcx = infcx.tcx;
     let param_env = tcx.param_env(def.did);
     let id = tcx.hir().local_def_id_to_hir_id(def.did);
@@ -213,6 +230,8 @@ fn do_mir_borrowck<'a, 'tcx>(
     let borrow_set =
         Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data));
 
+    let use_polonius = return_body_with_facts || infcx.tcx.sess.opts.debugging_opts.polonius;
+
     // Compute non-lexical lifetimes.
     let nll::NllOutput {
         regioncx,
@@ -232,6 +251,7 @@ fn do_mir_borrowck<'a, 'tcx>(
         &mdpe.move_data,
         &borrow_set,
         &upvars,
+        use_polonius,
     );
 
     // Dump MIR results into a file, if that is enabled. This let us
@@ -352,7 +372,7 @@ fn do_mir_borrowck<'a, 'tcx>(
 
     mbcx.report_move_errors(move_errors);
 
-    dataflow::visit_results(
+    rustc_mir_dataflow::visit_results(
         &body,
         traversal::reverse_postorder(&body).map(|(bb, _)| bb),
         &results,
@@ -495,8 +515,8 @@ pub struct BodyWithBorrowckFacts<'tcx> {
     pub location_table: LocationTable,
 }
 
-crate struct MirBorrowckCtxt<'cx, 'tcx> {
-    crate infcx: &'cx InferCtxt<'cx, 'tcx>,
+struct MirBorrowckCtxt<'cx, 'tcx> {
+    infcx: &'cx InferCtxt<'cx, 'tcx>,
     param_env: ParamEnv<'tcx>,
     body: &'cx Body<'tcx>,
     move_data: &'cx MoveData<'tcx>,
@@ -594,7 +614,7 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> {
 // 2. loans made in overlapping scopes do not conflict
 // 3. assignments do not affect things loaned out as immutable
 // 4. moves do not affect things loaned out in any way
-impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx> {
+impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx> {
     type FlowState = Flows<'cx, 'tcx>;
 
     fn visit_statement_before_primary_effect(
@@ -2344,7 +2364,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// then returns the index of the field being projected. Note that this closure will always
     /// be `self` in the current MIR, because that is the only time we directly access the fields
     /// of a closure type.
-    pub fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option<Field> {
+    fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option<Field> {
         path_utils::is_upvar_field_projection(self.infcx.tcx, &self.upvars, place_ref, self.body())
     }
 }
diff --git a/compiler/rustc_mir/src/borrow_check/location.rs b/compiler/rustc_borrowck/src/location.rs
index d378a2cbea3..d378a2cbea3 100644
--- a/compiler/rustc_mir/src/borrow_check/location.rs
+++ b/compiler/rustc_borrowck/src/location.rs
diff --git a/compiler/rustc_mir/src/borrow_check/member_constraints.rs b/compiler/rustc_borrowck/src/member_constraints.rs
index 2e2578df011..2e2578df011 100644
--- a/compiler/rustc_mir/src/borrow_check/member_constraints.rs
+++ b/compiler/rustc_borrowck/src/member_constraints.rs
diff --git a/compiler/rustc_mir/src/borrow_check/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 66ca94d3b41..477b049b075 100644
--- a/compiler/rustc_mir/src/borrow_check/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -4,6 +4,7 @@ use rustc_data_structures::vec_map::VecMap;
 use rustc_errors::Diagnostic;
 use rustc_index::vec::IndexVec;
 use rustc_infer::infer::InferCtxt;
+use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere};
 use rustc_middle::mir::{
     BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location,
     Promoted,
@@ -17,16 +18,13 @@ use std::path::PathBuf;
 use std::rc::Rc;
 use std::str::FromStr;
 
-use self::mir_util::PassWhere;
 use polonius_engine::{Algorithm, Output};
 
-use crate::dataflow::impls::MaybeInitializedPlaces;
-use crate::dataflow::move_paths::{InitKind, InitLocation, MoveData};
-use crate::dataflow::ResultsCursor;
-use crate::util as mir_util;
-use crate::util::pretty;
+use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
+use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData};
+use rustc_mir_dataflow::ResultsCursor;
 
-use crate::borrow_check::{
+use crate::{
     borrow_set::BorrowSet,
     constraint_generation,
     diagnostics::RegionErrors,
@@ -56,7 +54,7 @@ crate struct NllOutput<'tcx> {
 /// Rewrites the regions in the MIR to use NLL variables, also scraping out the set of universal
 /// regions (e.g., region parameters) declared on the function. That set will need to be given to
 /// `compute_regions`.
-pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>(
+pub(crate) fn replace_regions_in_mir<'cx, 'tcx>(
     infcx: &InferCtxt<'cx, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     body: &mut Body<'tcx>,
@@ -72,7 +70,7 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>(
     // Replace all remaining regions with fresh inference variables.
     renumber::renumber_mir(infcx, body, promoted);
 
-    mir_util::dump_mir(infcx.tcx, None, "renumber", &0, body, |_, _| Ok(()));
+    dump_mir(infcx.tcx, None, "renumber", &0, body, |_, _| Ok(()));
 
     universal_regions
 }
@@ -155,7 +153,7 @@ fn populate_polonius_move_facts(
 /// Computes the (non-lexical) regions from the input MIR.
 ///
 /// This may result in errors being reported.
-pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
+pub(crate) fn compute_regions<'cx, 'tcx>(
     infcx: &InferCtxt<'cx, 'tcx>,
     universal_regions: UniversalRegions<'tcx>,
     body: &Body<'tcx>,
@@ -166,8 +164,10 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
     move_data: &MoveData<'tcx>,
     borrow_set: &BorrowSet<'tcx>,
     upvars: &[Upvar<'tcx>],
+    use_polonius: bool,
 ) -> NllOutput<'tcx> {
-    let mut all_facts = AllFacts::enabled(infcx.tcx).then_some(AllFacts::default());
+    let mut all_facts =
+        (use_polonius || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default());
 
     let universal_regions = Rc::new(universal_regions);
 
@@ -283,7 +283,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>(
             all_facts.write_to_dir(dir_path, location_table).unwrap();
         }
 
-        if infcx.tcx.sess.opts.debugging_opts.polonius {
+        if use_polonius {
             let algorithm =
                 env::var("POLONIUS_ALGORITHM").unwrap_or_else(|_| String::from("Hybrid"));
             let algorithm = Algorithm::from_str(&algorithm).unwrap();
@@ -322,11 +322,11 @@ pub(super) fn dump_mir_results<'a, 'tcx>(
     regioncx: &RegionInferenceContext<'tcx>,
     closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
 ) {
-    if !mir_util::dump_enabled(infcx.tcx, "nll", body.source.def_id()) {
+    if !dump_enabled(infcx.tcx, "nll", body.source.def_id()) {
         return;
     }
 
-    mir_util::dump_mir(infcx.tcx, None, "nll", &0, body, |pass_where, out| {
+    dump_mir(infcx.tcx, None, "nll", &0, body, |pass_where, out| {
         match pass_where {
             // Before the CFG, dump out the values for each region variable.
             PassWhere::BeforeCFG => {
@@ -354,14 +354,14 @@ pub(super) fn dump_mir_results<'a, 'tcx>(
     // Also dump the inference graph constraints as a graphviz file.
     let _: io::Result<()> = try {
         let mut file =
-            pretty::create_dump_file(infcx.tcx, "regioncx.all.dot", None, "nll", &0, body.source)?;
+            create_dump_file(infcx.tcx, "regioncx.all.dot", None, "nll", &0, body.source)?;
         regioncx.dump_graphviz_raw_constraints(&mut file)?;
     };
 
     // Also dump the inference graph constraints as a graphviz file.
     let _: io::Result<()> = try {
         let mut file =
-            pretty::create_dump_file(infcx.tcx, "regioncx.scc.dot", None, "nll", &0, body.source)?;
+            create_dump_file(infcx.tcx, "regioncx.scc.dot", None, "nll", &0, body.source)?;
         regioncx.dump_graphviz_scc_constraints(&mut file)?;
     };
 }
diff --git a/compiler/rustc_mir/src/borrow_check/path_utils.rs b/compiler/rustc_borrowck/src/path_utils.rs
index 80de3b4e363..d5d00b467ee 100644
--- a/compiler/rustc_mir/src/borrow_check/path_utils.rs
+++ b/compiler/rustc_borrowck/src/path_utils.rs
@@ -1,8 +1,8 @@
-use crate::borrow_check::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation};
-use crate::borrow_check::places_conflict;
-use crate::borrow_check::AccessDepth;
-use crate::borrow_check::Upvar;
-use crate::dataflow::indexes::BorrowIndex;
+use crate::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation};
+use crate::places_conflict;
+use crate::AccessDepth;
+use crate::BorrowIndex;
+use crate::Upvar;
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_middle::mir::BorrowKind;
 use rustc_middle::mir::{BasicBlock, Body, Field, Location, Place, PlaceRef, ProjectionElem};
diff --git a/compiler/rustc_mir/src/borrow_check/place_ext.rs b/compiler/rustc_borrowck/src/place_ext.rs
index 52fac3e53ee..83ff1595b0b 100644
--- a/compiler/rustc_mir/src/borrow_check/place_ext.rs
+++ b/compiler/rustc_borrowck/src/place_ext.rs
@@ -1,4 +1,4 @@
-use crate::borrow_check::borrow_set::LocalsStateAtExit;
+use crate::borrow_set::LocalsStateAtExit;
 use rustc_hir as hir;
 use rustc_middle::mir::ProjectionElem;
 use rustc_middle::mir::{Body, Mutability, Place};
diff --git a/compiler/rustc_mir/src/borrow_check/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs
index d21550a8e1a..773e9e90b0c 100644
--- a/compiler/rustc_mir/src/borrow_check/places_conflict.rs
+++ b/compiler/rustc_borrowck/src/places_conflict.rs
@@ -1,6 +1,6 @@
-use crate::borrow_check::ArtificialField;
-use crate::borrow_check::Overlap;
-use crate::borrow_check::{AccessDepth, Deep, Shallow};
+use crate::ArtificialField;
+use crate::Overlap;
+use crate::{AccessDepth, Deep, Shallow};
 use rustc_hir as hir;
 use rustc_middle::mir::{Body, BorrowKind, Local, Place, PlaceElem, PlaceRef, ProjectionElem};
 use rustc_middle::ty::{self, TyCtxt};
diff --git a/compiler/rustc_mir/src/borrow_check/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs
index bdf2becb711..bdf2becb711 100644
--- a/compiler/rustc_mir/src/borrow_check/prefixes.rs
+++ b/compiler/rustc_borrowck/src/prefixes.rs
diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/dump_mir.rs b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
index 213ebff12ab..cfd3acb6bde 100644
--- a/compiler/rustc_mir/src/borrow_check/region_infer/dump_mir.rs
+++ b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
@@ -4,7 +4,7 @@
 //! context internal state.
 
 use super::{OutlivesConstraint, RegionInferenceContext};
-use crate::borrow_check::type_check::Locations;
+use crate::type_check::Locations;
 use rustc_infer::infer::NllRegionVariableOrigin;
 use rustc_middle::ty::TyCtxt;
 use std::io::{self, Write};
diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs
index b944d74e6f2..95048d50f11 100644
--- a/compiler/rustc_mir/src/borrow_check/region_infer/graphviz.rs
+++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs
@@ -6,7 +6,7 @@ use std::borrow::Cow;
 use std::io::{self, Write};
 
 use super::*;
-use crate::borrow_check::constraints::OutlivesConstraint;
+use crate::constraints::OutlivesConstraint;
 use rustc_graphviz as dot;
 
 impl<'tcx> RegionInferenceContext<'tcx> {
diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index a96cdbc13f3..128faab8d72 100644
--- a/compiler/rustc_mir/src/borrow_check/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -17,7 +17,7 @@ use rustc_middle::mir::{
 use rustc_middle::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable};
 use rustc_span::Span;
 
-use crate::borrow_check::{
+use crate::{
     constraints::{
         graph::NormalConstraintGraph, ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet,
     },
@@ -85,7 +85,7 @@ pub struct RegionInferenceContext<'tcx> {
         FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
 
     /// Map universe indexes to information on why we created it.
-    universe_causes: IndexVec<ty::UniverseIndex, UniverseInfo<'tcx>>,
+    universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
 
     /// Contains the minimum universe of any variable within the same
     /// SCC. We will ensure that no SCC contains values that are not
@@ -132,33 +132,33 @@ pub(crate) struct AppliedMemberConstraint {
     ///
     /// The vector if `AppliedMemberConstraint` elements is kept sorted
     /// by this field.
-    pub(in crate::borrow_check) member_region_scc: ConstraintSccIndex,
+    pub(crate) member_region_scc: ConstraintSccIndex,
 
     /// The "best option" that `apply_member_constraint` found -- this was
     /// added as an "ad-hoc" lower-bound to `member_region_scc`.
-    pub(in crate::borrow_check) min_choice: ty::RegionVid,
+    pub(crate) min_choice: ty::RegionVid,
 
     /// The "member constraint index" -- we can find out details about
     /// the constraint from
     /// `set.member_constraints[member_constraint_index]`.
-    pub(in crate::borrow_check) member_constraint_index: NllMemberConstraintIndex,
+    pub(crate) member_constraint_index: NllMemberConstraintIndex,
 }
 
 pub(crate) struct RegionDefinition<'tcx> {
     /// What kind of variable is this -- a free region? existential
     /// variable? etc. (See the `NllRegionVariableOrigin` for more
     /// info.)
-    pub(in crate::borrow_check) origin: NllRegionVariableOrigin,
+    pub(crate) origin: NllRegionVariableOrigin,
 
     /// Which universe is this region variable defined in? This is
     /// most often `ty::UniverseIndex::ROOT`, but when we encounter
     /// forall-quantifiers like `for<'a> { 'a = 'b }`, we would create
     /// the variable for `'a` in a fresh universe that extends ROOT.
-    pub(in crate::borrow_check) universe: ty::UniverseIndex,
+    pub(crate) universe: ty::UniverseIndex,
 
     /// If this is 'static or an early-bound region, then this is
     /// `Some(X)` where `X` is the name of the region.
-    pub(in crate::borrow_check) external_name: Option<ty::Region<'tcx>>,
+    pub(crate) external_name: Option<ty::Region<'tcx>>,
 }
 
 /// N.B., the variants in `Cause` are intentionally ordered. Lower
@@ -245,7 +245,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ///
     /// The `outlives_constraints` and `type_tests` are an initial set
     /// of constraints produced by the MIR type check.
-    pub(in crate::borrow_check) fn new(
+    pub(crate) fn new(
         var_infos: VarInfos,
         universal_regions: Rc<UniversalRegions<'tcx>>,
         placeholder_indices: Rc<PlaceholderIndices>,
@@ -256,7 +256,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             Location,
             FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
         >,
-        universe_causes: IndexVec<ty::UniverseIndex, UniverseInfo<'tcx>>,
+        universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
         type_tests: Vec<TypeTest<'tcx>>,
         liveness_constraints: LivenessValues<RegionVid>,
         elements: &Rc<RegionValueElements>,
@@ -534,7 +534,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// Once region solving has completed, this function will return
     /// the member constraints that were applied to the value of a given
     /// region `r`. See `AppliedMemberConstraint`.
-    pub(in crate::borrow_check) fn applied_member_constraints(
+    pub(crate) fn applied_member_constraints(
         &self,
         r: impl ToRegionVid,
     ) -> &[AppliedMemberConstraint] {
@@ -1088,7 +1088,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ///   include the CFG anyhow.
     /// - For each `end('x)` element in `'r`, compute the mutual LUB, yielding
     ///   a result `'y`.
-    pub(in crate::borrow_check) fn universal_upper_bound(&self, r: RegionVid) -> RegionVid {
+    pub(crate) fn universal_upper_bound(&self, r: RegionVid) -> RegionVid {
         debug!("universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
 
         // Find the smallest universal region that contains all other
@@ -1115,7 +1115,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// Therefore, this method should only be used in diagnostic code,
     /// where displaying *some* named universal region is better than
     /// falling back to 'static.
-    pub(in crate::borrow_check) fn approx_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
+    pub(crate) fn approx_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
         debug!("approx_universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
 
         // Find the smallest universal region that contains all other
@@ -1739,7 +1739,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     category: constraint.category,
                     from_closure: false,
                     span,
-                    variance_info: constraint.variance_info.clone(),
+                    variance_info: constraint.variance_info,
                 };
             }
             Locations::Single(loc) => loc,
@@ -1752,13 +1752,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 category,
                 from_closure: true,
                 span: span,
-                variance_info: constraint.variance_info.clone(),
+                variance_info: constraint.variance_info,
             })
             .unwrap_or(BlameConstraint {
                 category: constraint.category,
                 from_closure: false,
                 span: body.source_info(loc).span,
-                variance_info: constraint.variance_info.clone(),
+                variance_info: constraint.variance_info,
             })
     }
 
@@ -2001,7 +2001,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                         category: constraint.category,
                         from_closure: false,
                         span: constraint.locations.span(body),
-                        variance_info: constraint.variance_info.clone(),
+                        variance_info: constraint.variance_info,
                     }
                 }
             })
@@ -2149,7 +2149,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     }
 
     crate fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
-        self.universe_causes[universe].clone()
+        self.universe_causes[&universe].clone()
     }
 }
 
diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 12fceeff088..39b83e50431 100644
--- a/compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -47,7 +47,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// which has no `external_name` in which case we use `'empty` as the
     /// region to pass to `infer_opaque_definition_from_instantiation`.
     #[instrument(skip(self, infcx))]
-    pub(in crate::borrow_check) fn infer_opaque_types(
+    pub(crate) fn infer_opaque_types(
         &self,
         infcx: &InferCtxt<'_, 'tcx>,
         opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
@@ -105,7 +105,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// that the regions produced are in fact equal to the named region they are
     /// replaced with. This is fine because this function is only to improve the
     /// region names in error messages.
-    pub(in crate::borrow_check) fn name_regions<T>(&self, tcx: TyCtxt<'tcx>, ty: T) -> T
+    pub(crate) fn name_regions<T>(&self, tcx: TyCtxt<'tcx>, ty: T) -> T
     where
         T: TypeFoldable<'tcx>,
     {
diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/reverse_sccs.rs b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
index 5d345a6e63d..056907dcb16 100644
--- a/compiler/rustc_mir/src/borrow_check/region_infer/reverse_sccs.rs
+++ b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
@@ -1,5 +1,5 @@
-use crate::borrow_check::constraints::ConstraintSccIndex;
-use crate::borrow_check::RegionInferenceContext;
+use crate::constraints::ConstraintSccIndex;
+use crate::RegionInferenceContext;
 use itertools::Itertools;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::graph::vec_graph::VecGraph;
diff --git a/compiler/rustc_mir/src/borrow_check/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs
index 2864abde002..2864abde002 100644
--- a/compiler/rustc_mir/src/borrow_check/region_infer/values.rs
+++ b/compiler/rustc_borrowck/src/region_infer/values.rs
diff --git a/compiler/rustc_mir/src/borrow_check/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs
index 9377473befe..9377473befe 100644
--- a/compiler/rustc_mir/src/borrow_check/renumber.rs
+++ b/compiler/rustc_borrowck/src/renumber.rs
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index b501716a899..18070164e82 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -8,7 +8,7 @@ use rustc_span::Span;
 use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
 use rustc_trait_selection::traits::query::Fallible;
 
-use crate::borrow_check::diagnostics::{ToUniverseInfo, UniverseInfo};
+use crate::diagnostics::{ToUniverseInfo, UniverseInfo};
 
 use super::{Locations, NormalizeLocation, TypeChecker};
 
@@ -50,9 +50,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 None => UniverseInfo::other(),
             };
             for u in old_universe..universe {
-                let info_universe =
-                    self.borrowck_context.constraints.universe_causes.push(universe_info.clone());
-                assert_eq!(u.as_u32() + 1, info_universe.as_u32());
+                self.borrowck_context
+                    .constraints
+                    .universe_causes
+                    .insert(u + 1, universe_info.clone());
             }
         }
 
@@ -70,9 +71,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         let (instantiated, _) =
             self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
 
-        for _ in 0..canonical.max_universe.as_u32() {
+        for u in 0..canonical.max_universe.as_u32() {
             let info = UniverseInfo::other();
-            self.borrowck_context.constraints.universe_causes.push(info);
+            self.borrowck_context
+                .constraints
+                .universe_causes
+                .insert(ty::UniverseIndex::from_u32(u), info);
         }
 
         instantiated
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index 446a0f8e72f..b0207468485 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -9,7 +9,7 @@ use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::DUMMY_SP;
 
-use crate::borrow_check::{
+use crate::{
     constraints::OutlivesConstraint,
     nll::ToRegionVid,
     region_infer::TypeTest,
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index 6426098d843..70c74940d62 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -13,7 +13,7 @@ use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
 use std::rc::Rc;
 use type_op::TypeOpOutput;
 
-use crate::borrow_check::{
+use crate::{
     nll::ToRegionVid,
     type_check::constraint_conversion,
     type_check::{Locations, MirTypeckRegionConstraints},
@@ -55,7 +55,7 @@ type RegionBoundPairs<'tcx> = Vec<(ty::Region<'tcx>, GenericKind<'tcx>)>;
 type NormalizedInputsAndOutput<'tcx> = Vec<Ty<'tcx>>;
 
 crate struct CreateResult<'tcx> {
-    pub(in crate::borrow_check) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
+    crate universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
     crate region_bound_pairs: RegionBoundPairs<'tcx>,
     crate normalized_inputs_and_output: NormalizedInputsAndOutput<'tcx>,
 }
@@ -259,7 +259,7 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
                 // We add implied bounds from both the unnormalized and normalized ty
                 // See issue #87748
                 let constraints_implied_1 = self.add_implied_bounds(ty);
-                let TypeOpOutput { output: ty, constraints: constraints1, .. } = self
+                let TypeOpOutput { output: norm_ty, constraints: constraints1, .. } = self
                     .param_env
                     .and(type_op::normalize::Normalize::new(ty))
                     .fully_perform(self.infcx)
@@ -286,8 +286,9 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> {
                 // }
                 // ```
                 // Both &Self::Bar and &() are WF
-                let constraints_implied_2 = self.add_implied_bounds(ty);
-                normalized_inputs_and_output.push(ty);
+                let constraints_implied_2 =
+                    if ty != norm_ty { self.add_implied_bounds(norm_ty) } else { None };
+                normalized_inputs_and_output.push(norm_ty);
                 constraints1.into_iter().chain(constraints_implied_1).chain(constraints_implied_2)
             })
             .collect();
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index ba9b6926526..46d30a188ed 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -7,16 +7,15 @@
 //! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
 //! contain revealed `impl Trait` values).
 
+use rustc_index::vec::Idx;
 use rustc_infer::infer::LateBoundRegionConversionTime;
 use rustc_middle::mir::*;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{self, Ty};
-use rustc_trait_selection::traits::query::normalize::AtExt;
-
-use rustc_index::vec::Idx;
 use rustc_span::Span;
+use rustc_trait_selection::traits::query::normalize::AtExt;
 
-use crate::borrow_check::universal_regions::UniversalRegions;
+use crate::universal_regions::UniversalRegions;
 
 use super::{Locations, TypeChecker};
 
@@ -195,6 +194,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     b
                 }
             };
+            // Note: if we have to introduce new placeholders during normalization above, then we won't have
+            // added those universes to the universe info, which we would want in `relate_tys`.
             if let Err(terr) =
                 self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
             {
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/liveness/local_use_map.rs b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
index 7e8a33efe11..8b74abd94c0 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/liveness/local_use_map.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
@@ -3,8 +3,8 @@ use rustc_index::vec::IndexVec;
 use rustc_middle::mir::visit::{PlaceContext, Visitor};
 use rustc_middle::mir::{Body, Local, Location};
 
-use crate::borrow_check::def_use::{self, DefUse};
-use crate::borrow_check::region_infer::values::{PointIndex, RegionValueElements};
+use crate::def_use::{self, DefUse};
+use crate::region_infer::values::{PointIndex, RegionValueElements};
 
 /// A map that cross references each local with the locations where it
 /// is defined (assigned), used, or dropped. Used during liveness
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
index a34ae281b70..1e712354d6a 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/liveness/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
@@ -3,11 +3,11 @@ use rustc_middle::mir::{Body, Local};
 use rustc_middle::ty::{RegionVid, TyCtxt};
 use std::rc::Rc;
 
-use crate::dataflow::impls::MaybeInitializedPlaces;
-use crate::dataflow::move_paths::MoveData;
-use crate::dataflow::ResultsCursor;
+use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
+use rustc_mir_dataflow::move_paths::MoveData;
+use rustc_mir_dataflow::ResultsCursor;
 
-use crate::borrow_check::{
+use crate::{
     constraints::OutlivesConstraintSet,
     facts::{AllFacts, AllFactsExt},
     location::LocationTable,
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
index d285098c52a..79ab8b713f9 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/liveness/polonius.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
@@ -1,10 +1,9 @@
-use crate::borrow_check::def_use::{self, DefUse};
-use crate::borrow_check::location::{LocationIndex, LocationTable};
-use crate::dataflow::indexes::MovePathIndex;
-use crate::dataflow::move_paths::{LookupResult, MoveData};
+use crate::def_use::{self, DefUse};
+use crate::location::{LocationIndex, LocationTable};
 use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::{Body, Local, Location, Place};
 use rustc_middle::ty::subst::GenericArg;
+use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
 
 use super::TypeChecker;
 
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 566c11811e6..1671c7c627e 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -8,12 +8,11 @@ use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
 use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
 use std::rc::Rc;
 
-use crate::dataflow::impls::MaybeInitializedPlaces;
-use crate::dataflow::indexes::MovePathIndex;
-use crate::dataflow::move_paths::{HasMoveData, MoveData};
-use crate::dataflow::ResultsCursor;
+use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
+use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex};
+use rustc_mir_dataflow::ResultsCursor;
 
-use crate::borrow_check::{
+use crate::{
     region_infer::values::{self, PointIndex, RegionValueElements},
     type_check::liveness::local_use_map::LocalUseMap,
     type_check::liveness::polonius,
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 639bcb8fa94..41c004ea596 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -41,14 +41,14 @@ use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
 use rustc_trait_selection::traits::query::Fallible;
 use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligations};
 
-use crate::dataflow::impls::MaybeInitializedPlaces;
-use crate::dataflow::move_paths::MoveData;
-use crate::dataflow::ResultsCursor;
-use crate::transform::{
+use rustc_const_eval::transform::{
     check_consts::ConstCx, promote_consts::is_const_fn_in_array_repeat_expression,
 };
+use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
+use rustc_mir_dataflow::move_paths::MoveData;
+use rustc_mir_dataflow::ResultsCursor;
 
-use crate::borrow_check::{
+use crate::{
     borrow_set::BorrowSet,
     constraints::{OutlivesConstraint, OutlivesConstraintSet},
     diagnostics::UniverseInfo,
@@ -68,7 +68,7 @@ use crate::borrow_check::{
 
 macro_rules! span_mirbug {
     ($context:expr, $elem:expr, $($message:tt)*) => ({
-        $crate::borrow_check::type_check::mirbug(
+        $crate::type_check::mirbug(
             $context.tcx(),
             $context.last_span,
             &format!(
@@ -136,6 +136,8 @@ pub(crate) fn type_check<'mir, 'tcx>(
     upvars: &[Upvar<'tcx>],
 ) -> MirTypeckResults<'tcx> {
     let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
+    let mut universe_causes = FxHashMap::default();
+    universe_causes.insert(ty::UniverseIndex::from_u32(0), UniverseInfo::other());
     let mut constraints = MirTypeckRegionConstraints {
         placeholder_indices: PlaceholderIndices::default(),
         placeholder_index_to_region: IndexVec::default(),
@@ -144,7 +146,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
         member_constraints: MemberConstraintSet::default(),
         closure_bounds_mapping: Default::default(),
         type_tests: Vec::default(),
-        universe_causes: IndexVec::from_elem_n(UniverseInfo::other(), 1),
+        universe_causes,
     };
 
     let CreateResult {
@@ -159,9 +161,9 @@ pub(crate) fn type_check<'mir, 'tcx>(
         &mut constraints,
     );
 
-    for _ in ty::UniverseIndex::ROOT..infcx.universe() {
+    for u in ty::UniverseIndex::ROOT..infcx.universe() {
         let info = UniverseInfo::other();
-        constraints.universe_causes.push(info);
+        constraints.universe_causes.insert(u, info);
     }
 
     let mut borrowck_context = BorrowCheckContext {
@@ -887,7 +889,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 universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
     crate opaque_type_values: VecMap<OpaqueTypeKey<'tcx>, Ty<'tcx>>,
 }
 
@@ -924,7 +926,7 @@ crate struct MirTypeckRegionConstraints<'tcx> {
     crate closure_bounds_mapping:
         FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
 
-    crate universe_causes: IndexVec<ty::UniverseIndex, UniverseInfo<'tcx>>,
+    crate universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
 
     crate type_tests: Vec<TypeTest<'tcx>>,
 }
@@ -1996,7 +1998,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                                     &obligation,
                                     &traits::SelectionError::Unimplemented,
                                     false,
-                                    false,
                                 );
                             }
                         }
diff --git a/compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index 971c4daa6b3..de86d39cc37 100644
--- a/compiler/rustc_mir/src/borrow_check/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -5,9 +5,9 @@ use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::{self, Const, Ty};
 use rustc_trait_selection::traits::query::Fallible;
 
-use crate::borrow_check::constraints::OutlivesConstraint;
-use crate::borrow_check::diagnostics::UniverseInfo;
-use crate::borrow_check::type_check::{BorrowCheckContext, Locations};
+use crate::constraints::OutlivesConstraint;
+use crate::diagnostics::UniverseInfo;
+use crate::type_check::{BorrowCheckContext, Locations};
 
 /// Adds sufficient constraints to ensure that `a R b` where `R` depends on `v`:
 ///
@@ -80,10 +80,11 @@ impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> {
     }
 
     fn create_next_universe(&mut self) -> ty::UniverseIndex {
-        let info_universe =
-            self.borrowck_context.constraints.universe_causes.push(self.universe_info.clone());
         let universe = self.infcx.create_next_universe();
-        assert_eq!(info_universe, universe);
+        self.borrowck_context
+            .constraints
+            .universe_causes
+            .insert(universe, self.universe_info.clone());
         universe
     }
 
diff --git a/compiler/rustc_mir/src/borrow_check/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 3c9b4272b36..bebd1937029 100644
--- a/compiler/rustc_mir/src/borrow_check/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -26,7 +26,7 @@ use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
 use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt};
 use std::iter;
 
-use crate::borrow_check::nll::ToRegionVid;
+use crate::nll::ToRegionVid;
 
 #[derive(Debug)]
 pub struct UniversalRegions<'tcx> {
diff --git a/compiler/rustc_mir/src/borrow_check/used_muts.rs b/compiler/rustc_borrowck/src/used_muts.rs
index e027056842d..6022a980950 100644
--- a/compiler/rustc_mir/src/borrow_check/used_muts.rs
+++ b/compiler/rustc_borrowck/src/used_muts.rs
@@ -1,11 +1,10 @@
+use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::mir::visit::{PlaceContext, Visitor};
 use rustc_middle::mir::{
     Local, Location, Place, Statement, StatementKind, Terminator, TerminatorKind,
 };
 
-use rustc_data_structures::fx::FxHashSet;
-
-use crate::borrow_check::MirBorrowckCtxt;
+use crate::MirBorrowckCtxt;
 
 impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// Walks the MIR adding to the set of `used_mut` locals that will be ignored for the purposes
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index 652165fb9b6..c032364c008 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -117,6 +117,10 @@ fn parse_args<'a>(
         let mut explicit_reg = false;
         let op = if !is_global_asm && p.eat_keyword(kw::In) {
             let reg = parse_reg(&mut p, &mut explicit_reg)?;
+            if p.eat_keyword(kw::Underscore) {
+                let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands");
+                return Err(err);
+            }
             let expr = p.parse_expr()?;
             ast::InlineAsmOperand::In { reg, expr }
         } else if !is_global_asm && p.eat_keyword(sym::out) {
@@ -129,6 +133,10 @@ fn parse_args<'a>(
             ast::InlineAsmOperand::Out { reg, expr, late: true }
         } else if !is_global_asm && p.eat_keyword(sym::inout) {
             let reg = parse_reg(&mut p, &mut explicit_reg)?;
+            if p.eat_keyword(kw::Underscore) {
+                let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands");
+                return Err(err);
+            }
             let expr = p.parse_expr()?;
             if p.eat(&token::FatArrow) {
                 let out_expr =
@@ -139,6 +147,10 @@ fn parse_args<'a>(
             }
         } else if !is_global_asm && p.eat_keyword(sym::inlateout) {
             let reg = parse_reg(&mut p, &mut explicit_reg)?;
+            if p.eat_keyword(kw::Underscore) {
+                let err = ecx.struct_span_err(p.token.span, "_ cannot be used for input operands");
+                return Err(err);
+            }
             let expr = p.parse_expr()?;
             if p.eat(&token::FatArrow) {
                 let out_expr =
@@ -510,7 +522,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
             match expr_to_spanned_string(ecx, template_expr, msg) {
                 Ok(template_part) => template_part,
                 Err(err) => {
-                    if let Some(mut err) = err {
+                    if let Some((mut err, _)) = err {
                         err.emit();
                     }
                     return None;
diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs
index 14506f296bf..ecf70da6d96 100644
--- a/compiler/rustc_builtin_macros/src/deriving/debug.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs
@@ -65,15 +65,29 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
     // We want to make sure we have the ctxt set so that we can use unstable methods
     let span = cx.with_def_site_ctxt(span);
     let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked));
+    let fmt = substr.nonself_args[0].clone();
+
+    // Special fast path for unit variants. In the common case of an enum that is entirely unit
+    // variants (i.e. a C-like enum), this fast path allows LLVM to eliminate the entire switch in
+    // favor of a lookup table.
+    if let ast::VariantData::Unit(..) = vdata {
+        let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]);
+        let expr = cx.expr_call_global(span, fn_path_write_str, vec![fmt, name]);
+        let stmts = vec![cx.stmt_expr(expr)];
+        let block = cx.block(span, stmts);
+        return cx.expr_block(block);
+    }
+
     let builder = Ident::new(sym::debug_trait_builder, span);
     let builder_expr = cx.expr_ident(span, builder);
 
-    let fmt = substr.nonself_args[0].clone();
-
     let mut stmts = Vec::with_capacity(fields.len() + 2);
     let fn_path_finish;
     match vdata {
-        ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
+        ast::VariantData::Unit(..) => {
+            cx.span_bug(span, "unit variants should have been handled above");
+        }
+        ast::VariantData::Tuple(..) => {
             // tuple struct/"normal" variant
             let fn_path_debug_tuple = cx.std_path(&[sym::fmt, sym::Formatter, sym::debug_tuple]);
             let expr = cx.expr_call_global(span, fn_path_debug_tuple, vec![fmt, name]);
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 8508b3b7ae6..c7626dec4d7 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -964,17 +964,19 @@ pub fn expand_preparsed_format_args(
         }
         Ok(fmt) => fmt,
         Err(err) => {
-            if let Some(mut err) = err {
+            if let Some((mut err, suggested)) = err {
                 let sugg_fmt = match args.len() {
                     0 => "{}".to_string(),
                     _ => format!("{}{{}}", "{} ".repeat(args.len())),
                 };
-                err.span_suggestion(
-                    fmt_sp.shrink_to_lo(),
-                    "you might be missing a string literal to format with",
-                    format!("\"{}\", ", sugg_fmt),
-                    Applicability::MaybeIncorrect,
-                );
+                if !suggested {
+                    err.span_suggestion(
+                        fmt_sp.shrink_to_lo(),
+                        "you might be missing a string literal to format with",
+                        format!("\"{}\", ", sugg_fmt),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
                 err.emit();
             }
             return DummyResult::raw_expr(sp, true);
diff --git a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs
index c4801a0a87b..7a51293f5cd 100755
--- a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs
+++ b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs
@@ -42,7 +42,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
             continue;
         }
 
-        if stack.contains("rustc_mir::monomorphize::partitioning::collect_and_partition_mono_items")
+        if stack.contains("rustc_monomorphize::partitioning::collect_and_partition_mono_items")
             || stack.contains("rustc_incremental::assert_dep_graph::assert_dep_graph")
             || stack.contains("rustc_symbol_mangling::test::report_symbol_names")
         {
@@ -81,7 +81,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
         }
 
         const COLLECT_AND_PARTITION_MONO_ITEMS: &str =
-            "rustc_mir::monomorphize::partitioning::collect_and_partition_mono_items";
+            "rustc_monomorphize::partitioning::collect_and_partition_mono_items";
         if let Some(index) = stack.find(COLLECT_AND_PARTITION_MONO_ITEMS) {
             stack = &stack[..index + COLLECT_AND_PARTITION_MONO_ITEMS.len()];
         }
diff --git a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs
index 44eae706ea8..2144e7ed67a 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs
@@ -92,9 +92,9 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
     fn get_abi_param(&self, tcx: TyCtxt<'tcx>) -> SmallVec<[AbiParam; 2]> {
         match self.mode {
             PassMode::Ignore => smallvec![],
-            PassMode::Direct(attrs) => match &self.layout.abi {
+            PassMode::Direct(attrs) => match self.layout.abi {
                 Abi::Scalar(scalar) => smallvec![apply_arg_attrs_to_abi_param(
-                    AbiParam::new(scalar_to_clif_type(tcx, scalar.clone())),
+                    AbiParam::new(scalar_to_clif_type(tcx, scalar)),
                     attrs
                 )],
                 Abi::Vector { .. } => {
@@ -103,10 +103,10 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
                 }
                 _ => unreachable!("{:?}", self.layout.abi),
             },
-            PassMode::Pair(attrs_a, attrs_b) => match &self.layout.abi {
+            PassMode::Pair(attrs_a, attrs_b) => match self.layout.abi {
                 Abi::ScalarPair(a, b) => {
-                    let a = scalar_to_clif_type(tcx, a.clone());
-                    let b = scalar_to_clif_type(tcx, b.clone());
+                    let a = scalar_to_clif_type(tcx, a);
+                    let b = scalar_to_clif_type(tcx, b);
                     smallvec![
                         apply_arg_attrs_to_abi_param(AbiParam::new(a), attrs_a),
                         apply_arg_attrs_to_abi_param(AbiParam::new(b), attrs_b),
@@ -139,9 +139,9 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
     fn get_abi_return(&self, tcx: TyCtxt<'tcx>) -> (Option<AbiParam>, Vec<AbiParam>) {
         match self.mode {
             PassMode::Ignore => (None, vec![]),
-            PassMode::Direct(_) => match &self.layout.abi {
+            PassMode::Direct(_) => match self.layout.abi {
                 Abi::Scalar(scalar) => {
-                    (None, vec![AbiParam::new(scalar_to_clif_type(tcx, scalar.clone()))])
+                    (None, vec![AbiParam::new(scalar_to_clif_type(tcx, scalar))])
                 }
                 Abi::Vector { .. } => {
                     let vector_ty = crate::intrinsics::clif_vector_type(tcx, self.layout).unwrap();
@@ -149,10 +149,10 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
                 }
                 _ => unreachable!("{:?}", self.layout.abi),
             },
-            PassMode::Pair(_, _) => match &self.layout.abi {
+            PassMode::Pair(_, _) => match self.layout.abi {
                 Abi::ScalarPair(a, b) => {
-                    let a = scalar_to_clif_type(tcx, a.clone());
-                    let b = scalar_to_clif_type(tcx, b.clone());
+                    let a = scalar_to_clif_type(tcx, a);
+                    let b = scalar_to_clif_type(tcx, b);
                     (None, vec![AbiParam::new(a), AbiParam::new(b)])
                 }
                 _ => unreachable!("{:?}", self.layout.abi),
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index e99a227a3a6..d29558a4e1f 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -23,7 +23,7 @@ pub(crate) fn codegen_fn<'tcx>(
     let mir = tcx.instance_mir(instance.def);
     let _mir_guard = crate::PrintOnPanic(|| {
         let mut buf = Vec::new();
-        rustc_mir::util::write_mir_pretty(tcx, Some(instance.def_id()), &mut buf).unwrap();
+        rustc_middle::mir::write_mir_pretty(tcx, Some(instance.def_id()), &mut buf).unwrap();
         String::from_utf8_lossy(&buf).into_owned()
     });
 
@@ -726,15 +726,20 @@ fn codegen_stmt<'tcx>(
                     let ptr = fx.bcx.inst_results(call)[0];
                     lval.write_cvalue(fx, CValue::by_val(ptr, box_layout));
                 }
-                Rvalue::NullaryOp(NullOp::SizeOf, ty) => {
+                Rvalue::NullaryOp(null_op, ty) => {
                     assert!(
                         lval.layout()
                             .ty
                             .is_sized(fx.tcx.at(stmt.source_info.span), ParamEnv::reveal_all())
                     );
-                    let ty_size = fx.layout_of(fx.monomorphize(ty)).size.bytes();
+                    let layout = fx.layout_of(fx.monomorphize(ty));
+                    let val = match null_op {
+                        NullOp::SizeOf => layout.size.bytes(),
+                        NullOp::AlignOf => layout.align.abi.bytes(),
+                        NullOp::Box => unreachable!(),
+                    };
                     let val =
-                        CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), ty_size.into());
+                        CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), val.into());
                     lval.write_cvalue(fx, val);
                 }
                 Rvalue::Aggregate(ref kind, ref operands) => match kind.as_ref() {
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 12f61e0c564..48183b2d4f6 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -143,8 +143,8 @@ macro validate_simd_type($fx:ident, $intrinsic:ident, $span:ident, $ty:expr) {
 }
 
 pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>) -> Option<Type> {
-    let (element, count) = match &layout.abi {
-        Abi::Vector { element, count } => (element.clone(), *count),
+    let (element, count) = match layout.abi {
+        Abi::Vector { element, count } => (element, count),
         _ => unreachable!(),
     };
 
@@ -823,7 +823,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
             dest.write_cvalue(fx, val);
         };
 
-        pref_align_of | min_align_of | needs_drop | type_id | type_name | variant_count, () {
+        pref_align_of | needs_drop | type_id | type_name | variant_count, () {
             let const_val =
                 fx.tcx.const_eval_instance(ParamEnv::reveal_all(), instance, None).unwrap();
             let val = crate::constant::codegen_const_value(
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index 2e5e8f683cd..87193e3ef53 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -16,7 +16,6 @@ extern crate rustc_incremental;
 extern crate rustc_index;
 extern crate rustc_interface;
 extern crate rustc_metadata;
-extern crate rustc_mir;
 extern crate rustc_session;
 extern crate rustc_span;
 extern crate rustc_target;
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index 364b3da92b8..30d5340935f 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -49,11 +49,7 @@ fn codegen_field<'tcx>(
     }
 }
 
-fn scalar_pair_calculate_b_offset(
-    tcx: TyCtxt<'_>,
-    a_scalar: &Scalar,
-    b_scalar: &Scalar,
-) -> Offset32 {
+fn scalar_pair_calculate_b_offset(tcx: TyCtxt<'_>, a_scalar: Scalar, b_scalar: Scalar) -> Offset32 {
     let b_offset = a_scalar.value.size(&tcx).align_to(b_scalar.value.align(&tcx).abi);
     Offset32::new(b_offset.bytes().try_into().unwrap())
 }
@@ -124,12 +120,10 @@ impl<'tcx> CValue<'tcx> {
         match self.0 {
             CValueInner::ByRef(ptr, None) => {
                 let clif_ty = match layout.abi {
-                    Abi::Scalar(ref scalar) => scalar_to_clif_type(fx.tcx, scalar.clone()),
-                    Abi::Vector { ref element, count } => {
-                        scalar_to_clif_type(fx.tcx, element.clone())
-                            .by(u16::try_from(count).unwrap())
-                            .unwrap()
-                    }
+                    Abi::Scalar(scalar) => scalar_to_clif_type(fx.tcx, scalar),
+                    Abi::Vector { element, count } => scalar_to_clif_type(fx.tcx, element)
+                        .by(u16::try_from(count).unwrap())
+                        .unwrap(),
                     _ => unreachable!("{:?}", layout.ty),
                 };
                 let mut flags = MemFlags::new();
@@ -147,13 +141,13 @@ impl<'tcx> CValue<'tcx> {
         let layout = self.1;
         match self.0 {
             CValueInner::ByRef(ptr, None) => {
-                let (a_scalar, b_scalar) = match &layout.abi {
+                let (a_scalar, b_scalar) = match layout.abi {
                     Abi::ScalarPair(a, b) => (a, b),
                     _ => unreachable!("load_scalar_pair({:?})", self),
                 };
                 let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
-                let clif_ty1 = scalar_to_clif_type(fx.tcx, a_scalar.clone());
-                let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar.clone());
+                let clif_ty1 = scalar_to_clif_type(fx.tcx, a_scalar);
+                let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar);
                 let mut flags = MemFlags::new();
                 flags.set_notrap();
                 let val1 = ptr.load(fx, clif_ty1, flags);
@@ -564,7 +558,7 @@ impl<'tcx> CPlace<'tcx> {
                 to_ptr.store(fx, val, flags);
                 return;
             }
-            Abi::ScalarPair(ref a_scalar, ref b_scalar) => {
+            Abi::ScalarPair(a_scalar, b_scalar) => {
                 let (value, extra) = from.load_scalar_pair(fx);
                 let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
                 to_ptr.store(fx, value, flags);
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index 521ce344180..3c99febbd57 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -16,6 +16,7 @@ snap = "1"
 tracing = "0.1"
 rustc_middle = { path = "../rustc_middle" }
 rustc-demangle = "0.1.21"
+rustc_arena = { path = "../rustc_arena" }
 rustc_attr = { path = "../rustc_attr" }
 rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
 rustc_data_structures = { path = "../rustc_data_structures" }
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index cd55a61cbaf..1a0a3a0c340 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -511,7 +511,12 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> {
     }
 
     fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll Value) {
-        // FIXME(wesleywiser, eddyb): We should apply `nounwind` and `noreturn` as appropriate to this callsite.
+        if self.ret.layout.abi.is_uninhabited() {
+            llvm::Attribute::NoReturn.apply_callsite(llvm::AttributePlace::Function, callsite);
+        }
+        if !self.can_unwind {
+            llvm::Attribute::NoUnwind.apply_callsite(llvm::AttributePlace::Function, callsite);
+        }
 
         let mut i = 0;
         let mut apply = |cx: &CodegenCx<'_, '_>, attrs: &ArgAttributes| {
@@ -536,16 +541,13 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> {
             }
             _ => {}
         }
-        if let abi::Abi::Scalar(ref scalar) = self.ret.layout.abi {
+        if let abi::Abi::Scalar(scalar) = self.ret.layout.abi {
             // If the value is a boolean, the range is 0..2 and that ultimately
             // become 0..0 when the type becomes i1, which would be rejected
             // by the LLVM verifier.
             if let Int(..) = scalar.value {
-                if !scalar.is_bool() {
-                    let range = scalar.valid_range_exclusive(bx);
-                    if range.start != range.end {
-                        bx.range_metadata(callsite, range);
-                    }
+                if !scalar.is_bool() && !scalar.is_always_valid(bx) {
+                    bx.range_metadata(callsite, scalar.valid_range);
                 }
             }
         }
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index e0d312727a5..9690ad8b246 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -792,7 +792,7 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
 
 /// Helper function to get the LLVM type for a Scalar. Pointers are returned as
 /// the equivalent integer type.
-fn llvm_asm_scalar_type(cx: &CodegenCx<'ll, 'tcx>, scalar: &Scalar) -> &'ll Type {
+fn llvm_asm_scalar_type(cx: &CodegenCx<'ll, 'tcx>, scalar: Scalar) -> &'ll Type {
     match scalar.value {
         Primitive::Int(Integer::I8, _) => cx.type_i8(),
         Primitive::Int(Integer::I16, _) => cx.type_i16(),
@@ -812,7 +812,7 @@ fn llvm_fixup_input(
     reg: InlineAsmRegClass,
     layout: &TyAndLayout<'tcx>,
 ) -> &'ll Value {
-    match (reg, &layout.abi) {
+    match (reg, layout.abi) {
         (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
             if let Primitive::Int(Integer::I8, _) = s.value {
                 let vec_ty = bx.cx.type_vector(bx.cx.type_i8(), 8);
@@ -835,7 +835,7 @@ fn llvm_fixup_input(
             Abi::Vector { element, count },
         ) if layout.size.bytes() == 8 => {
             let elem_ty = llvm_asm_scalar_type(bx.cx, element);
-            let vec_ty = bx.cx.type_vector(elem_ty, *count);
+            let vec_ty = bx.cx.type_vector(elem_ty, count);
             let indices: Vec<_> = (0..count * 2).map(|x| bx.const_i32(x as i32)).collect();
             bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
         }
@@ -890,7 +890,7 @@ fn llvm_fixup_output(
     reg: InlineAsmRegClass,
     layout: &TyAndLayout<'tcx>,
 ) -> &'ll Value {
-    match (reg, &layout.abi) {
+    match (reg, layout.abi) {
         (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
             if let Primitive::Int(Integer::I8, _) = s.value {
                 bx.extract_element(value, bx.const_i32(0))
@@ -910,8 +910,8 @@ fn llvm_fixup_output(
             Abi::Vector { element, count },
         ) if layout.size.bytes() == 8 => {
             let elem_ty = llvm_asm_scalar_type(bx.cx, element);
-            let vec_ty = bx.cx.type_vector(elem_ty, *count * 2);
-            let indices: Vec<_> = (0..*count).map(|x| bx.const_i32(x as i32)).collect();
+            let vec_ty = bx.cx.type_vector(elem_ty, count * 2);
+            let indices: Vec<_> = (0..count).map(|x| bx.const_i32(x as i32)).collect();
             bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
         }
         (InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
@@ -965,7 +965,7 @@ fn llvm_fixup_output_type(
     reg: InlineAsmRegClass,
     layout: &TyAndLayout<'tcx>,
 ) -> &'ll Type {
-    match (reg, &layout.abi) {
+    match (reg, layout.abi) {
         (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
             if let Primitive::Int(Integer::I8, _) = s.value {
                 cx.type_vector(cx.type_i8(), 8)
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index da24fe08f0d..799f9a57e93 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -18,12 +18,12 @@ use rustc_hir::def_id::DefId;
 use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
-use rustc_target::abi::{self, Align, Size};
+use rustc_target::abi::{self, Align, Size, WrappingRange};
 use rustc_target::spec::{HasTargetSpec, Target};
 use std::borrow::Cow;
 use std::ffi::CStr;
 use std::iter;
-use std::ops::{Deref, Range};
+use std::ops::Deref;
 use std::ptr;
 use tracing::debug;
 
@@ -382,7 +382,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
             val
         }
     }
-    fn to_immediate_scalar(&mut self, val: Self::Value, scalar: &abi::Scalar) -> Self::Value {
+    fn to_immediate_scalar(&mut self, val: Self::Value, scalar: abi::Scalar) -> Self::Value {
         if scalar.is_bool() {
             return self.trunc(val, self.cx().type_i1());
         }
@@ -460,16 +460,15 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         fn scalar_load_metadata<'a, 'll, 'tcx>(
             bx: &mut Builder<'a, 'll, 'tcx>,
             load: &'ll Value,
-            scalar: &abi::Scalar,
+            scalar: abi::Scalar,
         ) {
             match scalar.value {
                 abi::Int(..) => {
-                    let range = scalar.valid_range_exclusive(bx);
-                    if range.start != range.end {
-                        bx.range_metadata(load, range);
+                    if !scalar.is_always_valid(bx) {
+                        bx.range_metadata(load, scalar.valid_range);
                     }
                 }
-                abi::Pointer if !scalar.valid_range.contains_zero() => {
+                abi::Pointer if !scalar.valid_range.contains(0) => {
                     bx.nonnull_metadata(load);
                 }
                 _ => {}
@@ -489,17 +488,17 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
             }
             let llval = const_llval.unwrap_or_else(|| {
                 let load = self.load(place.layout.llvm_type(self), place.llval, place.align);
-                if let abi::Abi::Scalar(ref scalar) = place.layout.abi {
+                if let abi::Abi::Scalar(scalar) = place.layout.abi {
                     scalar_load_metadata(self, load, scalar);
                 }
                 load
             });
             OperandValue::Immediate(self.to_immediate(llval, place.layout))
-        } else if let abi::Abi::ScalarPair(ref a, ref b) = place.layout.abi {
+        } else if let abi::Abi::ScalarPair(a, b) = place.layout.abi {
             let b_offset = a.value.size(self).align_to(b.value.align(self).abi);
             let pair_ty = place.layout.llvm_type(self);
 
-            let mut load = |i, scalar: &abi::Scalar, align| {
+            let mut load = |i, scalar: abi::Scalar, align| {
                 let llptr = self.struct_gep(pair_ty, place.llval, i as u64);
                 let llty = place.layout.scalar_pair_element_llvm_type(self, i, false);
                 let load = self.load(llty, llptr, align);
@@ -555,7 +554,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         next_bx
     }
 
-    fn range_metadata(&mut self, load: &'ll Value, range: Range<u128>) {
+    fn range_metadata(&mut self, load: &'ll Value, range: WrappingRange) {
         if self.sess().target.arch == "amdgpu" {
             // amdgpu/LLVM does something weird and thinks an i64 value is
             // split into a v2i32, halving the bitwidth LLVM expects,
@@ -568,7 +567,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
             let llty = self.cx.val_ty(load);
             let v = [
                 self.cx.const_uint_big(llty, range.start),
-                self.cx.const_uint_big(llty, range.end),
+                self.cx.const_uint_big(llty, range.end.wrapping_add(1)),
             ];
 
             llvm::LLVMSetMetadata(
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index cee582aec95..73a8d464431 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -228,7 +228,7 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         })
     }
 
-    fn scalar_to_backend(&self, cv: Scalar, layout: &abi::Scalar, llty: &'ll Type) -> &'ll Value {
+    fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: &'ll Type) -> &'ll Value {
         let bitsize = if layout.is_bool() { 1 } else { layout.value.size(self).bits() };
         match cv {
             Scalar::Int(ScalarInt::ZST) => {
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index e673b06f155..ef3a90fdeca 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -111,7 +111,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
                 Pointer::new(alloc_id, Size::from_bytes(ptr_offset)),
                 &cx.tcx,
             ),
-            &Scalar { value: Primitive::Pointer, valid_range: WrappingRange { start: 0, end: !0 } },
+            Scalar { value: Primitive::Pointer, valid_range: WrappingRange { start: 0, end: !0 } },
             cx.type_i8p_ext(address_space),
         ));
         next_offset = offset + pointer_size;
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 9a6391443dd..9272435a330 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -34,7 +34,7 @@ use rustc_middle::ty::Instance;
 use rustc_middle::ty::{self, AdtKind, GeneratorSubsts, ParamEnv, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_session::config::{self, DebugInfo};
-use rustc_span::symbol::{Interner, Symbol};
+use rustc_span::symbol::Symbol;
 use rustc_span::FileNameDisplayPreference;
 use rustc_span::{self, SourceFile, SourceFileHash, Span};
 use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, TagEncoding};
@@ -89,8 +89,54 @@ pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
 
 pub const NO_SCOPE_METADATA: Option<&DIScope> = None;
 
-#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
-pub struct UniqueTypeId(Symbol);
+mod unique_type_id {
+    use super::*;
+    use rustc_arena::DroplessArena;
+
+    #[derive(Copy, Hash, Eq, PartialEq, Clone)]
+    pub(super) struct UniqueTypeId(u32);
+
+    // The `&'static str`s in this type actually point into the arena.
+    //
+    // The `FxHashMap`+`Vec` pair could be replaced by `FxIndexSet`, but #75278
+    // found that to regress performance up to 2% in some cases. This might be
+    // revisited after further improvements to `indexmap`.
+    #[derive(Default)]
+    pub(super) struct TypeIdInterner {
+        arena: DroplessArena,
+        names: FxHashMap<&'static str, UniqueTypeId>,
+        strings: Vec<&'static str>,
+    }
+
+    impl TypeIdInterner {
+        #[inline]
+        pub(super) fn intern(&mut self, string: &str) -> UniqueTypeId {
+            if let Some(&name) = self.names.get(string) {
+                return name;
+            }
+
+            let name = UniqueTypeId(self.strings.len() as u32);
+
+            // `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be
+            // UTF-8.
+            let string: &str =
+                unsafe { std::str::from_utf8_unchecked(self.arena.alloc_slice(string.as_bytes())) };
+            // It is safe to extend the arena allocation to `'static` because we only access
+            // these while the arena is still alive.
+            let string: &'static str = unsafe { &*(string as *const str) };
+            self.strings.push(string);
+            self.names.insert(string, name);
+            name
+        }
+
+        // Get the symbol as a string. `Symbol::as_str()` should be used in
+        // preference to this function.
+        pub(super) fn get(&self, symbol: UniqueTypeId) -> &str {
+            self.strings[symbol.0 as usize]
+        }
+    }
+}
+use unique_type_id::*;
 
 /// The `TypeMap` is where the `CrateDebugContext` holds the type metadata nodes
 /// created so far. The metadata nodes are indexed by `UniqueTypeId`, and, for
@@ -99,7 +145,7 @@ pub struct UniqueTypeId(Symbol);
 #[derive(Default)]
 pub struct TypeMap<'ll, 'tcx> {
     /// The `UniqueTypeId`s created so far.
-    unique_id_interner: Interner,
+    unique_id_interner: TypeIdInterner,
     /// A map from `UniqueTypeId` to debuginfo metadata for that type. This is a 1:1 mapping.
     unique_id_to_metadata: FxHashMap<UniqueTypeId, &'ll DIType>,
     /// A map from types to debuginfo metadata. This is an N:1 mapping.
@@ -166,8 +212,7 @@ impl TypeMap<'ll, 'tcx> {
     /// Gets the string representation of a `UniqueTypeId`. This method will fail if
     /// the ID is unknown.
     fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> &str {
-        let UniqueTypeId(interner_key) = unique_type_id;
-        self.unique_id_interner.get(interner_key)
+        self.unique_id_interner.get(unique_type_id)
     }
 
     /// Gets the `UniqueTypeId` for the given type. If the `UniqueTypeId` for the given
@@ -197,9 +242,9 @@ impl TypeMap<'ll, 'tcx> {
         let unique_type_id = hasher.finish::<Fingerprint>().to_hex();
 
         let key = self.unique_id_interner.intern(&unique_type_id);
-        self.type_to_unique_id.insert(type_, UniqueTypeId(key));
+        self.type_to_unique_id.insert(type_, key);
 
-        UniqueTypeId(key)
+        key
     }
 
     /// Gets the `UniqueTypeId` for an enum variant. Enum variants are not really
@@ -215,7 +260,7 @@ impl TypeMap<'ll, 'tcx> {
         let enum_variant_type_id =
             format!("{}::{}", self.get_unique_type_id_as_string(enum_type_id), variant_name);
         let interner_key = self.unique_id_interner.intern(&enum_variant_type_id);
-        UniqueTypeId(interner_key)
+        interner_key
     }
 
     /// Gets the unique type ID string for an enum variant part.
@@ -1656,7 +1701,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
             Variants::Multiple {
                 tag_encoding:
                     TagEncoding::Niche { ref niche_variants, niche_start, dataful_variant },
-                ref tag,
+                tag,
                 ref variants,
                 tag_field,
             } => {
@@ -2082,10 +2127,8 @@ fn prepare_enum_metadata(
 
     let layout = cx.layout_of(enum_type);
 
-    if let (
-        &Abi::Scalar(_),
-        &Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. },
-    ) = (&layout.abi, &layout.variants)
+    if let (Abi::Scalar(_), Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, .. }) =
+        (layout.abi, &layout.variants)
     {
         return FinalMetadata(discriminant_type_metadata(tag.value));
     }
@@ -2093,8 +2136,8 @@ fn prepare_enum_metadata(
     if use_enum_fallback(cx) {
         let discriminant_type_metadata = match layout.variants {
             Variants::Single { .. } => None,
-            Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, ref tag, .. }
-            | Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. } => {
+            Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, .. }
+            | Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, .. } => {
                 Some(discriminant_type_metadata(tag.value))
             }
         };
@@ -2146,9 +2189,7 @@ fn prepare_enum_metadata(
         // A single-variant enum has no discriminant.
         Variants::Single { .. } => None,
 
-        Variants::Multiple {
-            tag_encoding: TagEncoding::Niche { .. }, ref tag, tag_field, ..
-        } => {
+        Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, tag_field, .. } => {
             // Find the integer type of the correct size.
             let size = tag.value.size(cx);
             let align = tag.value.align(cx);
@@ -2179,7 +2220,7 @@ fn prepare_enum_metadata(
             }
         }
 
-        Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, tag_field, .. } => {
+        Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, tag_field, .. } => {
             let discr_type = tag.value.to_ty(cx.tcx);
             let (size, align) = cx.size_and_align_of(discr_type);
 
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 1aa52d975e9..1060f911a9e 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -133,7 +133,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
             }
             sym::va_arg => {
                 match fn_abi.ret.layout.abi {
-                    abi::Abi::Scalar(ref scalar) => {
+                    abi::Abi::Scalar(scalar) => {
                         match scalar.value {
                             Primitive::Int(..) => {
                                 if self.cx().size_of(ret_ty).bytes() < 4 {
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index d615d230ea0..3e39bf3e995 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -23,7 +23,7 @@ fn uncached_llvm_type<'a, 'tcx>(
 ) -> &'a Type {
     match layout.abi {
         Abi::Scalar(_) => bug!("handled elsewhere"),
-        Abi::Vector { ref element, count } => {
+        Abi::Vector { element, count } => {
             let element = layout.scalar_llvm_type_at(cx, element, Size::ZERO);
             return cx.type_vector(element, count);
         }
@@ -177,7 +177,7 @@ pub trait LayoutLlvmExt<'tcx> {
     fn scalar_llvm_type_at<'a>(
         &self,
         cx: &CodegenCx<'a, 'tcx>,
-        scalar: &Scalar,
+        scalar: Scalar,
         offset: Size,
     ) -> &'a Type;
     fn scalar_pair_element_llvm_type<'a>(
@@ -218,7 +218,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
     /// of that field's type - this is useful for taking the address of
     /// that field and ensuring the struct has the right alignment.
     fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
-        if let Abi::Scalar(ref scalar) = self.abi {
+        if let Abi::Scalar(scalar) = self.abi {
             // Use a different cache for scalars because pointers to DSTs
             // can be either fat or thin (data pointers of fat pointers).
             if let Some(&llty) = cx.scalar_lltypes.borrow().get(&self.ty) {
@@ -286,7 +286,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
     }
 
     fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
-        if let Abi::Scalar(ref scalar) = self.abi {
+        if let Abi::Scalar(scalar) = self.abi {
             if scalar.is_bool() {
                 return cx.type_i1();
             }
@@ -297,7 +297,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
     fn scalar_llvm_type_at<'a>(
         &self,
         cx: &CodegenCx<'a, 'tcx>,
-        scalar: &Scalar,
+        scalar: Scalar,
         offset: Size,
     ) -> &'a Type {
         match scalar.value {
@@ -337,7 +337,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
         }
 
         let (a, b) = match self.abi {
-            Abi::ScalarPair(ref a, ref b) => (a, b),
+            Abi::ScalarPair(a, b) => (a, b),
             _ => bug!("TyAndLayout::scalar_pair_element_llty({:?}): not applicable", self),
         };
         let scalar = [a, b][index];
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index f0b32c96309..e842f5e9391 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -404,7 +404,7 @@ fn push_debuginfo_type_name<'tcx>(
 
             // calculate the range of values for the dataful variant
             let dataful_discriminant_range =
-                &dataful_variant_layout.largest_niche.as_ref().unwrap().scalar.valid_range;
+                dataful_variant_layout.largest_niche.unwrap().scalar.valid_range;
 
             let min = dataful_discriminant_range.start;
             let min = tag.value.size(&tcx).truncate(min);
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 2ca7e8fd7e8..cd0e9354c24 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -20,7 +20,7 @@ use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
 use rustc_span::source_map::Span;
 use rustc_span::{sym, Symbol};
 use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode};
-use rustc_target::abi::{self, HasDataLayout};
+use rustc_target::abi::{self, HasDataLayout, WrappingRange};
 use rustc_target::spec::abi::Abi;
 
 /// Used by `FunctionCx::codegen_terminator` for emitting common patterns
@@ -1102,9 +1102,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 // the load would just produce `OperandValue::Ref` instead
                 // of the `OperandValue::Immediate` we need for the call.
                 llval = bx.load(bx.backend_type(arg.layout), llval, align);
-                if let abi::Abi::Scalar(ref scalar) = arg.layout.abi {
+                if let abi::Abi::Scalar(scalar) = arg.layout.abi {
                     if scalar.is_bool() {
-                        bx.range_metadata(llval, 0..2);
+                        bx.range_metadata(llval, WrappingRange { start: 0, end: 1 });
                     }
                 }
                 // We store bools as `i8` so we need to truncate to `i1`.
@@ -1424,7 +1424,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let src = self.codegen_operand(bx, src);
 
         // Special-case transmutes between scalars as simple bitcasts.
-        match (&src.layout.abi, &dst.layout.abi) {
+        match (src.layout.abi, dst.layout.abi) {
             (abi::Abi::Scalar(src_scalar), abi::Abi::Scalar(dst_scalar)) => {
                 // HACK(eddyb) LLVM doesn't like `bitcast`s between pointers and non-pointers.
                 if (src_scalar.value == abi::Pointer) == (dst_scalar.value == abi::Pointer) {
diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs
index fa8a53e60b1..93b39dc8e9e 100644
--- a/compiler/rustc_codegen_ssa/src/mir/constant.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs
@@ -68,7 +68,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         if let Some(prim) = field.val.try_to_scalar() {
                             let layout = bx.layout_of(field_ty);
                             let scalar = match layout.abi {
-                                Abi::Scalar(ref x) => x,
+                                Abi::Scalar(x) => x,
                                 _ => bug!("from_const: invalid ByVal layout: {:#?}", layout),
                             };
                             bx.scalar_to_backend(prim, scalar, bx.immediate_backend_type(layout))
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index 75999225c03..f943157dc66 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -104,7 +104,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 }
             }
             sym::pref_align_of
-            | sym::min_align_of
             | sym::needs_drop
             | sym::type_id
             | sym::type_name
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 5cee25b5cca..ce6cec67ad4 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -79,7 +79,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
         let val = match val {
             ConstValue::Scalar(x) => {
                 let scalar = match layout.abi {
-                    Abi::Scalar(ref x) => x,
+                    Abi::Scalar(x) => x,
                     _ => bug!("from_const: invalid ByVal layout: {:#?}", layout),
                 };
                 let llval = bx.scalar_to_backend(x, scalar, bx.immediate_backend_type(layout));
@@ -87,7 +87,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
             }
             ConstValue::Slice { data, start, end } => {
                 let a_scalar = match layout.abi {
-                    Abi::ScalarPair(ref a, _) => a,
+                    Abi::ScalarPair(a, _) => a,
                     _ => bug!("from_const: invalid ScalarPair layout: {:#?}", layout),
                 };
                 let a = Scalar::from_pointer(
@@ -162,7 +162,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
         llval: V,
         layout: TyAndLayout<'tcx>,
     ) -> Self {
-        let val = if let Abi::ScalarPair(ref a, ref b) = layout.abi {
+        let val = if let Abi::ScalarPair(a, b) = layout.abi {
             debug!("Operand::from_immediate_or_packed_pair: unpacking {:?} @ {:?}", llval, layout);
 
             // Deconstruct the immediate aggregate.
@@ -185,7 +185,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
         let field = self.layout.field(bx.cx(), i);
         let offset = self.layout.fields.offset(i);
 
-        let mut val = match (self.val, &self.layout.abi) {
+        let mut val = match (self.val, self.layout.abi) {
             // If the field is ZST, it has no data.
             _ if field.is_zst() => {
                 return OperandRef::new_zst(bx, field);
@@ -200,7 +200,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
             }
 
             // Extract a scalar component from a pair.
-            (OperandValue::Pair(a_llval, b_llval), &Abi::ScalarPair(ref a, ref b)) => {
+            (OperandValue::Pair(a_llval, b_llval), Abi::ScalarPair(a, b)) => {
                 if offset.bytes() == 0 {
                     assert_eq!(field.size, a.value.size(bx.cx()));
                     OperandValue::Immediate(a_llval)
@@ -212,14 +212,14 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
             }
 
             // `#[repr(simd)]` types are also immediate.
-            (OperandValue::Immediate(llval), &Abi::Vector { .. }) => {
+            (OperandValue::Immediate(llval), Abi::Vector { .. }) => {
                 OperandValue::Immediate(bx.extract_element(llval, bx.cx().const_usize(i as u64)))
             }
 
             _ => bug!("OperandRef::extract_field({:?}): not applicable", self),
         };
 
-        match (&mut val, &field.abi) {
+        match (&mut val, field.abi) {
             (OperandValue::Immediate(llval), _) => {
                 // Bools in union fields needs to be truncated.
                 *llval = bx.to_immediate(*llval, field);
@@ -308,7 +308,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
             }
             OperandValue::Pair(a, b) => {
                 let (a_scalar, b_scalar) = match dest.layout.abi {
-                    Abi::ScalarPair(ref a, ref b) => (a, b),
+                    Abi::ScalarPair(a, b) => (a, b),
                     _ => bug!("store_with_flags: invalid ScalarPair layout: {:#?}", dest.layout),
                 };
                 let ty = bx.backend_type(dest.layout);
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index b48d6d42b43..4b07ed1a1e6 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -99,7 +99,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
                     // Also handles the first field of Scalar, ScalarPair, and Vector layouts.
                     self.llval
                 }
-                Abi::ScalarPair(ref a, ref b)
+                Abi::ScalarPair(a, b)
                     if offset == a.value.size(bx.cx()).align_to(b.value.align(bx.cx()).abi) =>
                 {
                     // Offset matches second field.
@@ -222,7 +222,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
                     .map_or(index.as_u32() as u128, |discr| discr.val);
                 return bx.cx().const_uint_big(cast_to, discr_val);
             }
-            Variants::Multiple { ref tag, ref tag_encoding, tag_field, .. } => {
+            Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => {
                 (tag, tag_encoding, tag_field)
             }
         };
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 3d8ea29160b..7403c21a906 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -300,7 +300,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         let llval = operand.immediate();
 
                         let mut signed = false;
-                        if let Abi::Scalar(ref scalar) = operand.layout.abi {
+                        if let Abi::Scalar(scalar) = operand.layout.abi {
                             if let Int(_, s) = scalar.value {
                                 // We use `i1` for bytes that are always `0` or `1`,
                                 // e.g., `#[repr(i8)] enum E { A, B }`, but we can't
@@ -308,8 +308,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                 // then `i1 1` (i.e., E::B) is effectively `i8 -1`.
                                 signed = !scalar.is_bool() && s;
 
-                                let er = scalar.valid_range_exclusive(bx.cx());
-                                if er.end != er.start
+                                if !scalar.is_always_valid(bx.cx())
                                     && scalar.valid_range.end >= scalar.valid_range.start
                                 {
                                     // We want `table[e as usize ± k]` to not
@@ -487,20 +486,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 )
             }
 
-            mir::Rvalue::NullaryOp(mir::NullOp::SizeOf, ty) => {
-                let ty = self.monomorphize(ty);
-                assert!(bx.cx().type_is_sized(ty));
-                let val = bx.cx().const_usize(bx.cx().layout_of(ty).size.bytes());
-                let tcx = self.cx.tcx();
-                (
-                    bx,
-                    OperandRef {
-                        val: OperandValue::Immediate(val),
-                        layout: self.cx.layout_of(tcx.types.usize),
-                    },
-                )
-            }
-
             mir::Rvalue::NullaryOp(mir::NullOp::Box, content_ty) => {
                 let content_ty = self.monomorphize(content_ty);
                 let content_layout = bx.cx().layout_of(content_ty);
@@ -525,6 +510,27 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 let operand = OperandRef { val: OperandValue::Immediate(val), layout: box_layout };
                 (bx, operand)
             }
+
+            mir::Rvalue::NullaryOp(null_op, ty) => {
+                let ty = self.monomorphize(ty);
+                assert!(bx.cx().type_is_sized(ty));
+                let layout = bx.cx().layout_of(ty);
+                let val = match null_op {
+                    mir::NullOp::SizeOf => layout.size.bytes(),
+                    mir::NullOp::AlignOf => layout.align.abi.bytes(),
+                    mir::NullOp::Box => unreachable!(),
+                };
+                let val = bx.cx().const_usize(val);
+                let tcx = self.cx.tcx();
+                (
+                    bx,
+                    OperandRef {
+                        val: OperandValue::Immediate(val),
+                        layout: self.cx.layout_of(tcx.types.usize),
+                    },
+                )
+            }
+
             mir::Rvalue::ThreadLocalRef(def_id) => {
                 assert!(bx.cx().tcx().is_static(def_id));
                 let static_ = bx.get_static(def_id);
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index afb8ee3c40d..e7da96f0ada 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -16,11 +16,9 @@ use crate::MemFlags;
 use rustc_middle::ty::layout::{HasParamEnv, TyAndLayout};
 use rustc_middle::ty::Ty;
 use rustc_span::Span;
-use rustc_target::abi::{Abi, Align, Scalar, Size};
+use rustc_target::abi::{Abi, Align, Scalar, Size, WrappingRange};
 use rustc_target::spec::HasTargetSpec;
 
-use std::ops::Range;
-
 #[derive(Copy, Clone)]
 pub enum OverflowOp {
     Add,
@@ -126,13 +124,13 @@ pub trait BuilderMethods<'a, 'tcx>:
 
     fn from_immediate(&mut self, val: Self::Value) -> Self::Value;
     fn to_immediate(&mut self, val: Self::Value, layout: TyAndLayout<'_>) -> Self::Value {
-        if let Abi::Scalar(ref scalar) = layout.abi {
+        if let Abi::Scalar(scalar) = layout.abi {
             self.to_immediate_scalar(val, scalar)
         } else {
             val
         }
     }
-    fn to_immediate_scalar(&mut self, val: Self::Value, scalar: &Scalar) -> Self::Value;
+    fn to_immediate_scalar(&mut self, val: Self::Value, scalar: Scalar) -> Self::Value;
 
     fn alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value;
     fn dynamic_alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value;
@@ -158,7 +156,7 @@ pub trait BuilderMethods<'a, 'tcx>:
         dest: PlaceRef<'tcx, Self::Value>,
     ) -> Self;
 
-    fn range_metadata(&mut self, load: Self::Value, range: Range<u128>);
+    fn range_metadata(&mut self, load: Self::Value, range: WrappingRange);
     fn nonnull_metadata(&mut self, load: Self::Value);
 
     fn store(&mut self, val: Self::Value, ptr: Self::Value, align: Align) -> Self::Value;
diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs
index 20f66187123..5260b7cc331 100644
--- a/compiler/rustc_codegen_ssa/src/traits/consts.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs
@@ -28,7 +28,7 @@ pub trait ConstMethods<'tcx>: BackendTypes {
 
     fn const_data_from_alloc(&self, alloc: &Allocation) -> Self::Value;
 
-    fn scalar_to_backend(&self, cv: Scalar, layout: &abi::Scalar, llty: Self::Type) -> Self::Value;
+    fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: Self::Type) -> Self::Value;
     fn from_const_alloc(
         &self,
         layout: TyAndLayout<'tcx>,
diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml
new file mode 100644
index 00000000000..1653d5cf6c5
--- /dev/null
+++ b/compiler/rustc_const_eval/Cargo.toml
@@ -0,0 +1,27 @@
+[package]
+name = "rustc_const_eval"
+version = "0.0.0"
+edition = "2018"
+
+[lib]
+doctest = false
+
+[dependencies]
+either = "1.5.0"
+gsgdt = "0.1.2"
+tracing = "0.1"
+rustc_apfloat = { path = "../rustc_apfloat" }
+rustc_ast = { path = "../rustc_ast" }
+rustc_attr = { path = "../rustc_attr" }
+rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_errors = { path = "../rustc_errors" }
+rustc_hir = { path = "../rustc_hir" }
+rustc_index = { path = "../rustc_index" }
+rustc_infer = { path = "../rustc_infer" }
+rustc_macros = { path = "../rustc_macros" }
+rustc_middle = { path = "../rustc_middle" }
+rustc_mir_dataflow = { path = "../rustc_mir_dataflow" }
+rustc_session = { path = "../rustc_session" }
+rustc_target = { path = "../rustc_target" }
+rustc_trait_selection = { path = "../rustc_trait_selection" }
+rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_mir/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index 5da16816625..5da16816625 100644
--- a/compiler/rustc_mir/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
diff --git a/compiler/rustc_mir/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index 3e8a93e08c2..171fc45ea46 100644
--- a/compiler/rustc_mir/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -5,12 +5,12 @@ use crate::interpret::{
     Immediate, InternKind, InterpCx, InterpResult, MPlaceTy, MemoryKind, OpTy, RefTracking, Scalar,
     ScalarMaybeUninit, StackPopCleanup,
 };
-use crate::util::pretty::display_allocation;
 
 use rustc_errors::ErrorReported;
 use rustc_hir::def::DefKind;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::ErrorHandled;
+use rustc_middle::mir::pretty::display_allocation;
 use rustc_middle::traits::Reveal;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::print::with_no_trimmed_paths;
diff --git a/compiler/rustc_mir/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
index 40419a4d201..10afd9560fa 100644
--- a/compiler/rustc_mir/src/const_eval/fn_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
@@ -1,5 +1,5 @@
 use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::DefId;
 use rustc_middle::hir::map::blocks::FnLikeNode;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
@@ -34,8 +34,14 @@ pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Symbol> {
 }
 
 pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
-    let parent_id = tcx.hir().get_parent_did(hir_id);
-    if !parent_id.is_top_level_module() { is_const_impl_raw(tcx, parent_id) } else { false }
+    let parent_id = tcx.hir().get_parent_node(hir_id);
+    matches!(
+        tcx.hir().get(parent_id),
+        hir::Node::Item(hir::Item {
+            kind: hir::ItemKind::Impl(hir::Impl { constness: hir::Constness::Const, .. }),
+            ..
+        })
+    )
 }
 
 /// Checks whether the function has a `const` modifier or, in case it is an intrinsic, whether
@@ -70,19 +76,6 @@ fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     }
 }
 
-/// Checks whether the given item is an `impl` that has a `const` modifier.
-fn is_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-    let node = tcx.hir().get(hir_id);
-    matches!(
-        node,
-        hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::Impl(hir::Impl { constness: hir::Constness::Const, .. }),
-            ..
-        })
-    )
-}
-
 fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     is_const_fn(tcx, def_id)
         && match tcx.lookup_const_stability(def_id) {
@@ -103,10 +96,5 @@ fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
 }
 
 pub fn provide(providers: &mut Providers) {
-    *providers = Providers {
-        is_const_fn_raw,
-        is_const_impl_raw: |tcx, def_id| is_const_impl_raw(tcx, def_id.expect_local()),
-        is_promotable_const_fn,
-        ..*providers
-    };
+    *providers = Providers { is_const_fn_raw, is_promotable_const_fn, ..*providers };
 }
diff --git a/compiler/rustc_mir/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 8a90686b900..8a90686b900 100644
--- a/compiler/rustc_mir/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
diff --git a/compiler/rustc_mir/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs
index a334165df4c..a334165df4c 100644
--- a/compiler/rustc_mir/src/const_eval/mod.rs
+++ b/compiler/rustc_const_eval/src/const_eval/mod.rs
diff --git a/compiler/rustc_mir/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index 4c4b0bd2d1f..4c4b0bd2d1f 100644
--- a/compiler/rustc_mir/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 05502d8b21f..0521443533b 100644
--- a/compiler/rustc_mir/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -12,6 +12,7 @@ use rustc_middle::ty::layout::{self, LayoutError, LayoutOf, LayoutOfHelpers, TyA
 use rustc_middle::ty::{
     self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
 };
+use rustc_mir_dataflow::storage::AlwaysLiveLocals;
 use rustc_session::Limit;
 use rustc_span::{Pos, Span};
 use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
@@ -22,7 +23,6 @@ use super::{
     ScalarMaybeUninit, StackPopJump,
 };
 use crate::transform::validate::equal_up_to_regions;
-use crate::util::storage::AlwaysLiveLocals;
 
 pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
     /// Stores the `Machine` instance.
diff --git a/compiler/rustc_mir/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs
index f2457d11d9e..84e79408397 100644
--- a/compiler/rustc_mir/src/interpret/intern.rs
+++ b/compiler/rustc_const_eval/src/interpret/intern.rs
@@ -420,7 +420,7 @@ impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>>
     /// A helper function that allocates memory for the layout given and gives you access to mutate
     /// it. Once your own mutation code is done, the backing `Allocation` is removed from the
     /// current `Memory` and returned.
-    pub(crate) fn intern_with_temp_alloc(
+    pub fn intern_with_temp_alloc(
         &mut self,
         layout: TyAndLayout<'tcx>,
         f: impl FnOnce(
diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 07e974b7266..698742fe98c 100644
--- a/compiler/rustc_mir/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -62,15 +62,10 @@ crate fn eval_nullary_intrinsic<'tcx>(
             ensure_monomorphic_enough(tcx, tp_ty)?;
             ConstValue::from_bool(tp_ty.needs_drop(tcx, param_env))
         }
-        sym::min_align_of | sym::pref_align_of => {
+        sym::pref_align_of => {
             // Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough.
             let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?;
-            let n = match name {
-                sym::pref_align_of => layout.align.pref.bytes(),
-                sym::min_align_of => layout.align.abi.bytes(),
-                _ => bug!(),
-            };
-            ConstValue::from_machine_usize(n, &tcx)
+            ConstValue::from_machine_usize(layout.align.pref.bytes(), &tcx)
         }
         sym::type_id => {
             ensure_monomorphic_enough(tcx, tp_ty)?;
@@ -160,17 +155,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 self.write_scalar(Scalar::from_machine_usize(result, self), dest)?;
             }
 
-            sym::min_align_of
-            | sym::pref_align_of
+            sym::pref_align_of
             | sym::needs_drop
             | sym::type_id
             | sym::type_name
             | sym::variant_count => {
                 let gid = GlobalId { instance, promoted: None };
                 let ty = match intrinsic_name {
-                    sym::min_align_of | sym::pref_align_of | sym::variant_count => {
-                        self.tcx.types.usize
-                    }
+                    sym::pref_align_of | sym::variant_count => self.tcx.types.usize,
                     sym::needs_drop => self.tcx.types.bool,
                     sym::type_id => self.tcx.types.u64,
                     sym::type_name => self.tcx.mk_static_str(),
@@ -194,7 +186,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let val = self.read_scalar(&args[0])?.check_init()?;
                 let bits = val.to_bits(layout_of.size)?;
                 let kind = match layout_of.abi {
-                    Abi::Scalar(ref scalar) => scalar.value,
+                    Abi::Scalar(scalar) => scalar.value,
                     _ => span_bug!(
                         self.cur_span(),
                         "{} called on invalid type {:?}",
@@ -234,7 +226,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     &r,
                 )?;
                 let val = if overflowed {
-                    let num_bits = l.layout.size.bits();
+                    let size = l.layout.size;
+                    let num_bits = size.bits();
                     if l.layout.abi.is_signed() {
                         // For signed ints the saturated value depends on the sign of the first
                         // term since the sign of the second term can be inferred from this and
@@ -259,10 +252,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         // unsigned
                         if is_add {
                             // max unsigned
-                            Scalar::from_uint(
-                                u128::MAX >> (128 - num_bits),
-                                Size::from_bits(num_bits),
-                            )
+                            Scalar::from_uint(size.unsigned_int_max(), Size::from_bits(num_bits))
                         } else {
                             // underflow to 0
                             Scalar::from_uint(0u128, Size::from_bits(num_bits))
diff --git a/compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
index d4cbba18029..d4cbba18029 100644
--- a/compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
diff --git a/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs
index a7012cd63f3..a7012cd63f3 100644
--- a/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs
diff --git a/compiler/rustc_mir/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 323e102b872..323e102b872 100644
--- a/compiler/rustc_mir/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
diff --git a/compiler/rustc_mir/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 4d13274a120..b8b6ff93753 100644
--- a/compiler/rustc_mir/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -15,6 +15,7 @@ use std::ptr;
 
 use rustc_ast::Mutability;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_middle::mir::display_allocation;
 use rustc_middle::ty::{Instance, ParamEnv, TyCtxt};
 use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
 
@@ -23,7 +24,6 @@ use super::{
     InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, Scalar,
     ScalarMaybeUninit,
 };
-use crate::util::pretty;
 
 #[derive(Debug, PartialEq, Copy, Clone)]
 pub enum MemoryKind<T> {
@@ -851,7 +851,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a,
             for alloc_id in alloc.relocations().values().map(|tag| tag.get_alloc_id()) {
                 allocs_to_print.push_back(alloc_id);
             }
-            write!(fmt, "{}", pretty::display_allocation(tcx, alloc))
+            write!(fmt, "{}", display_allocation(tcx, alloc))
         }
 
         let mut allocs_to_print: VecDeque<_> = self.allocs.iter().copied().collect();
diff --git a/compiler/rustc_mir/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs
index 2b9fe565997..2b9fe565997 100644
--- a/compiler/rustc_mir/src/interpret/mod.rs
+++ b/compiler/rustc_const_eval/src/interpret/mod.rs
diff --git a/compiler/rustc_mir/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index e67a6690836..de870bd5c6c 100644
--- a/compiler/rustc_mir/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -274,11 +274,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let scalar = alloc.read_scalar(alloc_range(Size::ZERO, mplace.layout.size))?;
                 Ok(Some(ImmTy { imm: scalar.into(), layout: mplace.layout }))
             }
-            Abi::ScalarPair(ref a, ref b) => {
+            Abi::ScalarPair(a, b) => {
                 // We checked `ptr_align` above, so all fields will have the alignment they need.
                 // We would anyway check against `ptr_align.restrict_for_offset(b_offset)`,
                 // which `ptr.offset(b_offset)` cannot possibly fail to satisfy.
-                let (a, b) = (&a.value, &b.value);
+                let (a, b) = (a.value, b.value);
                 let (a_size, b_size) = (a.size(self), b.size(self));
                 let b_offset = a_size.align_to(b.align(self).abi);
                 assert!(b_offset.bytes() > 0); // we later use the offset to tell apart the fields
@@ -296,7 +296,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// Note that for a given layout, this operation will either always fail or always
     /// succeed!  Whether it succeeds depends on whether the layout can be represented
     /// in an `Immediate`, not on which data is stored there currently.
-    pub(crate) fn try_read_immediate(
+    pub fn try_read_immediate(
         &self,
         src: &OpTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx, Result<ImmTy<'tcx, M::PointerTag>, MPlaceTy<'tcx, M::PointerTag>>> {
@@ -547,7 +547,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     // in patterns via the `const_eval` module
     /// The `val` and `layout` are assumed to already be in our interpreter
     /// "universe" (param_env).
-    crate fn const_to_op(
+    pub fn const_to_op(
         &self,
         val: &ty::Const<'tcx>,
         layout: Option<TyAndLayout<'tcx>>,
@@ -566,7 +566,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         }
     }
 
-    crate fn mir_const_to_op(
+    pub fn mir_const_to_op(
         &self,
         val: &mir::ConstantKind<'tcx>,
         layout: Option<TyAndLayout<'tcx>>,
@@ -648,7 +648,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 };
                 return Ok((discr, index));
             }
-            Variants::Multiple { ref tag, ref tag_encoding, tag_field, .. } => {
+            Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => {
                 (tag, tag_encoding, tag_field)
             }
         };
diff --git a/compiler/rustc_mir/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs
index ac000b1bb56..ac000b1bb56 100644
--- a/compiler/rustc_mir/src/interpret/operator.rs
+++ b/compiler/rustc_const_eval/src/interpret/operator.rs
diff --git a/compiler/rustc_mir/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 95a44e3fecf..0da6d8169bd 100644
--- a/compiler/rustc_mir/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -752,7 +752,7 @@ where
                 // We would anyway check against `ptr_align.restrict_for_offset(b_offset)`,
                 // which `ptr.offset(b_offset)` cannot possibly fail to satisfy.
                 let (a, b) = match dest.layout.abi {
-                    Abi::ScalarPair(ref a, ref b) => (&a.value, &b.value),
+                    Abi::ScalarPair(a, b) => (a.value, b.value),
                     _ => span_bug!(
                         self.cur_span(),
                         "write_immediate_to_mplace: invalid ScalarPair layout: {:#?}",
@@ -1000,7 +1000,7 @@ where
             }
             Variants::Multiple {
                 tag_encoding: TagEncoding::Direct,
-                tag: ref tag_layout,
+                tag: tag_layout,
                 tag_field,
                 ..
             } => {
@@ -1022,7 +1022,7 @@ where
             Variants::Multiple {
                 tag_encoding:
                     TagEncoding::Niche { dataful_variant, ref niche_variants, niche_start },
-                tag: ref tag_layout,
+                tag: tag_layout,
                 tag_field,
                 ..
             } => {
diff --git a/compiler/rustc_mir/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index 1e96581c392..6e35b33188c 100644
--- a/compiler/rustc_mir/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -76,7 +76,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
     /// Runs the interpretation logic for the given `mir::Statement` at the current frame and
     /// statement counter. This also moves the statement counter forward.
-    crate fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> {
+    pub fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> {
         info!("{:?}", stmt);
 
         use rustc_middle::mir::StatementKind::*;
@@ -270,18 +270,23 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 M::box_alloc(self, &dest)?;
             }
 
-            NullaryOp(mir::NullOp::SizeOf, ty) => {
+            NullaryOp(null_op, ty) => {
                 let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty);
                 let layout = self.layout_of(ty)?;
                 if layout.is_unsized() {
                     // FIXME: This should be a span_bug (#80742)
                     self.tcx.sess.delay_span_bug(
                         self.frame().current_span(),
-                        &format!("SizeOf nullary MIR operator called for unsized type {}", ty),
+                        &format!("Nullary MIR operator called for unsized type {}", ty),
                     );
                     throw_inval!(SizeOfUnsizedType(ty));
                 }
-                self.write_scalar(Scalar::from_machine_usize(layout.size.bytes(), self), &dest)?;
+                let val = match null_op {
+                    mir::NullOp::SizeOf => layout.size.bytes(),
+                    mir::NullOp::AlignOf => layout.align.abi.bytes(),
+                    mir::NullOp::Box => unreachable!(),
+                };
+                self.write_scalar(Scalar::from_machine_usize(val, self), &dest)?;
             }
 
             Cast(cast_kind, ref operand, cast_ty) => {
diff --git a/compiler/rustc_mir/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 1c8e5e9e23c..a06903aedf6 100644
--- a/compiler/rustc_mir/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -187,17 +187,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             return false;
         }
         // Compare layout
-        match (&caller.abi, &callee.abi) {
+        match (caller.abi, callee.abi) {
             // Different valid ranges are okay (once we enforce validity,
             // that will take care to make it UB to leave the range, just
             // like for transmute).
-            (abi::Abi::Scalar(ref caller), abi::Abi::Scalar(ref callee)) => {
-                caller.value == callee.value
+            (abi::Abi::Scalar(caller), abi::Abi::Scalar(callee)) => caller.value == callee.value,
+            (abi::Abi::ScalarPair(caller1, caller2), abi::Abi::ScalarPair(callee1, callee2)) => {
+                caller1.value == callee1.value && caller2.value == callee2.value
             }
-            (
-                abi::Abi::ScalarPair(ref caller1, ref caller2),
-                abi::Abi::ScalarPair(ref callee1, ref callee2),
-            ) => caller1.value == callee1.value && caller2.value == callee2.value,
             // Be conservative
             _ => false,
         }
diff --git a/compiler/rustc_mir/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs
index a6ba00ec695..a6ba00ec695 100644
--- a/compiler/rustc_mir/src/interpret/traits.rs
+++ b/compiler/rustc_const_eval/src/interpret/traits.rs
diff --git a/compiler/rustc_mir/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs
index eb0fdebb665..eb0fdebb665 100644
--- a/compiler/rustc_mir/src/interpret/util.rs
+++ b/compiler/rustc_const_eval/src/interpret/util.rs
diff --git a/compiler/rustc_mir/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 03e0a8e7901..a6375ad0e02 100644
--- a/compiler/rustc_mir/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -618,40 +618,38 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
     fn visit_scalar(
         &mut self,
         op: &OpTy<'tcx, M::PointerTag>,
-        scalar_layout: &ScalarAbi,
+        scalar_layout: ScalarAbi,
     ) -> InterpResult<'tcx> {
-        let value = self.read_scalar(op)?;
-        let valid_range = scalar_layout.valid_range.clone();
-        let WrappingRange { start: lo, end: hi } = valid_range;
-        // Determine the allowed range
-        // `max_hi` is as big as the size fits
-        let max_hi = u128::MAX >> (128 - op.layout.size.bits());
-        assert!(hi <= max_hi);
-        // We could also write `(hi + 1) % (max_hi + 1) == lo` but `max_hi + 1` overflows for `u128`
-        if (lo == 0 && hi == max_hi) || (hi + 1 == lo) {
+        if scalar_layout.valid_range.is_full_for(op.layout.size) {
             // Nothing to check
             return Ok(());
         }
-        // At least one value is excluded. Get the bits.
+        // At least one value is excluded.
+        let valid_range = scalar_layout.valid_range;
+        let WrappingRange { start, end } = valid_range;
+        let max_value = op.layout.size.unsigned_int_max();
+        assert!(end <= max_value);
+        // Determine the allowed range
+        let value = self.read_scalar(op)?;
         let value = try_validation!(
             value.check_init(),
             self.path,
             err_ub!(InvalidUninitBytes(None)) => { "{}", value }
-                expected { "something {}", wrapping_range_format(valid_range, max_hi) },
+                expected { "something {}", wrapping_range_format(valid_range, max_value) },
         );
         let bits = match value.try_to_int() {
             Err(_) => {
                 // So this is a pointer then, and casting to an int failed.
                 // Can only happen during CTFE.
                 let ptr = self.ecx.scalar_to_ptr(value);
-                if lo == 1 && hi == max_hi {
+                if start == 1 && end == max_value {
                     // Only null is the niche.  So make sure the ptr is NOT null.
                     if self.ecx.memory.ptr_may_be_null(ptr) {
                         throw_validation_failure!(self.path,
                             { "a potentially null pointer" }
                             expected {
                                 "something that cannot possibly fail to be {}",
-                                wrapping_range_format(valid_range, max_hi)
+                                wrapping_range_format(valid_range, max_value)
                             }
                         )
                     }
@@ -663,7 +661,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                         { "a pointer" }
                         expected {
                             "something that cannot possibly fail to be {}",
-                            wrapping_range_format(valid_range, max_hi)
+                            wrapping_range_format(valid_range, max_value)
                         }
                     )
                 }
@@ -676,7 +674,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
         } else {
             throw_validation_failure!(self.path,
                 { "{}", bits }
-                expected { "something {}", wrapping_range_format(valid_range, max_hi) }
+                expected { "something {}", wrapping_range_format(valid_range, max_value) }
             )
         }
     }
@@ -786,7 +784,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
                     { "a value of uninhabited type {:?}", op.layout.ty }
                 );
             }
-            Abi::Scalar(ref scalar_layout) => {
+            Abi::Scalar(scalar_layout) => {
                 self.visit_scalar(op, scalar_layout)?;
             }
             Abi::ScalarPair { .. } | Abi::Vector { .. } => {
diff --git a/compiler/rustc_mir/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs
index 679d30227f1..679d30227f1 100644
--- a/compiler/rustc_mir/src/interpret/visitor.rs
+++ b/compiler/rustc_const_eval/src/interpret/visitor.rs
diff --git a/compiler/rustc_mir/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index e439a247c7f..7ce40b319a1 100644
--- a/compiler/rustc_mir/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -4,32 +4,24 @@ Rust MIR: a lowered representation of Rust.
 
 */
 
-#![feature(nll)]
-#![feature(in_band_lifetimes)]
-#![feature(array_windows)]
 #![feature(assert_matches)]
-#![cfg_attr(bootstrap, feature(bindings_after_at))]
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
+#![feature(control_flow_enum)]
 #![feature(crate_visibility_modifier)]
 #![feature(decl_macro)]
 #![feature(exact_size_is_empty)]
-#![feature(format_args_capture)]
+#![feature(in_band_lifetimes)]
 #![feature(iter_zip)]
-#![feature(never_type)]
 #![feature(map_try_insert)]
 #![feature(min_specialization)]
 #![feature(slice_ptr_get)]
+#![feature(option_get_or_insert_default)]
+#![feature(never_type)]
+#![feature(trait_alias)]
 #![feature(trusted_len)]
+#![feature(trusted_step)]
 #![feature(try_blocks)]
-#![feature(associated_type_defaults)]
-#![feature(stmt_expr_attributes)]
-#![feature(trait_alias)]
-#![feature(option_get_or_insert_default)]
-#![feature(once_cell)]
-#![feature(control_flow_enum)]
-#![feature(try_reserve)]
-#![feature(try_reserve_kind)]
 #![recursion_limit = "256"]
 
 #[macro_use]
@@ -37,32 +29,18 @@ extern crate tracing;
 #[macro_use]
 extern crate rustc_middle;
 
-mod borrow_check;
 pub mod const_eval;
-pub mod dataflow;
 pub mod interpret;
-pub mod monomorphize;
-mod shim;
 pub mod transform;
 pub mod util;
 
-// A public API provided for the Rust compiler consumers.
-pub use self::borrow_check::consumers;
-
 use rustc_middle::ty::query::Providers;
 
 pub fn provide(providers: &mut Providers) {
-    borrow_check::provide(providers);
     const_eval::provide(providers);
-    shim::provide(providers);
-    transform::provide(providers);
-    monomorphize::partitioning::provide(providers);
-    monomorphize::polymorphize::provide(providers);
     providers.eval_to_const_value_raw = const_eval::eval_to_const_value_raw_provider;
     providers.eval_to_allocation_raw = const_eval::eval_to_allocation_raw_provider;
     providers.const_caller_location = const_eval::const_caller_location;
-    providers.mir_callgraph_reachable = transform::inline::cycle::mir_callgraph_reachable;
-    providers.mir_inliner_callees = transform::inline::cycle::mir_inliner_callees;
     providers.destructure_const = |tcx, param_env_and_value| {
         let (param_env, value) = param_env_and_value.into_parts();
         const_eval::destructure_const(tcx, param_env, value)
diff --git a/compiler/rustc_mir/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 0c381276823..d5682f702ba 100644
--- a/compiler/rustc_mir/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -12,6 +12,8 @@ use rustc_middle::ty::cast::CastTy;
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
 use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt};
 use rustc_middle::ty::{Binder, TraitPredicate, TraitRef};
+use rustc_mir_dataflow::impls::MaybeMutBorrowedLocals;
+use rustc_mir_dataflow::{self, Analysis};
 use rustc_span::{sym, Span, Symbol};
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
 use rustc_trait_selection::traits::{self, SelectionContext, TraitEngine};
@@ -20,26 +22,24 @@ use std::mem;
 use std::ops::Deref;
 
 use super::ops::{self, NonConstOp, Status};
-use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop};
+use super::qualifs::{self, CustomEq, HasMutInterior, NeedsNonConstDrop};
 use super::resolver::FlowSensitiveAnalysis;
 use super::{is_lang_panic_fn, ConstCx, Qualif};
 use crate::const_eval::is_unstable_const_fn;
-use crate::dataflow::impls::MaybeMutBorrowedLocals;
-use crate::dataflow::{self, Analysis};
 
 // We are using `MaybeMutBorrowedLocals` as a proxy for whether an item may have been mutated
 // through a pointer prior to the given point. This is okay even though `MaybeMutBorrowedLocals`
 // kills locals upon `StorageDead` because a local will never be used after a `StorageDead`.
 type IndirectlyMutableResults<'mir, 'tcx> =
-    dataflow::ResultsCursor<'mir, 'tcx, MaybeMutBorrowedLocals<'mir, 'tcx>>;
+    rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, MaybeMutBorrowedLocals<'mir, 'tcx>>;
 
 type QualifResults<'mir, 'tcx, Q> =
-    dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>;
+    rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>;
 
 #[derive(Default)]
 pub struct Qualifs<'mir, 'tcx> {
     has_mut_interior: Option<QualifResults<'mir, 'tcx, HasMutInterior>>,
-    needs_drop: Option<QualifResults<'mir, 'tcx, NeedsDrop>>,
+    needs_drop: Option<QualifResults<'mir, 'tcx, NeedsNonConstDrop>>,
     indirectly_mutable: Option<IndirectlyMutableResults<'mir, 'tcx>>,
 }
 
@@ -80,14 +80,14 @@ impl Qualifs<'mir, 'tcx> {
         location: Location,
     ) -> bool {
         let ty = ccx.body.local_decls[local].ty;
-        if !NeedsDrop::in_any_value_of_ty(ccx, ty) {
+        if !NeedsNonConstDrop::in_any_value_of_ty(ccx, ty) {
             return false;
         }
 
         let needs_drop = self.needs_drop.get_or_insert_with(|| {
             let ConstCx { tcx, body, .. } = *ccx;
 
-            FlowSensitiveAnalysis::new(NeedsDrop, ccx)
+            FlowSensitiveAnalysis::new(NeedsNonConstDrop, ccx)
                 .into_engine(tcx, &body)
                 .iterate_to_fixpoint()
                 .into_results_cursor(&body)
@@ -648,7 +648,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
                 }
             }
 
-            Rvalue::NullaryOp(NullOp::SizeOf, _) => {}
+            Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
             Rvalue::NullaryOp(NullOp::Box, _) => self.check_op(ops::HeapAllocation),
 
             Rvalue::UnaryOp(_, ref operand) => {
@@ -988,12 +988,12 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
 
                 let mut err_span = self.span;
 
-                // Check to see if the type of this place can ever have a drop impl. If not, this
-                // `Drop` terminator is frivolous.
-                let ty_needs_drop =
-                    dropped_place.ty(self.body, self.tcx).ty.needs_drop(self.tcx, self.param_env);
+                let ty_needs_non_const_drop = qualifs::NeedsNonConstDrop::in_any_value_of_ty(
+                    self.ccx,
+                    dropped_place.ty(self.body, self.tcx).ty,
+                );
 
-                if !ty_needs_drop {
+                if !ty_needs_non_const_drop {
                     return;
                 }
 
diff --git a/compiler/rustc_mir/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
index a5cb0f4e14b..a5cb0f4e14b 100644
--- a/compiler/rustc_mir/src/transform/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs
diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index 8923d989b29..2a296750838 100644
--- a/compiler/rustc_mir/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -599,12 +599,21 @@ pub mod ty {
         }
 
         fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
-            feature_err(
+            let mut builder = feature_err(
                 &ccx.tcx.sess.parse_sess,
                 sym::const_fn_trait_bound,
                 span,
                 "trait bounds other than `Sized` on const fn parameters are unstable",
-            )
+            );
+
+            match ccx.fn_sig() {
+                Some(fn_sig) if !fn_sig.span.contains(span) => {
+                    builder.span_label(fn_sig.span, "function declared as const here");
+                }
+                _ => {}
+            }
+
+            builder
         }
     }
 
diff --git a/compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
index b08ce219034..f2ba5a1ebb1 100644
--- a/compiler/rustc_mir/src/transform/check_consts/post_drop_elaboration.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
@@ -5,7 +5,7 @@ use rustc_span::Span;
 
 use super::check::Qualifs;
 use super::ops::{self, NonConstOp};
-use super::qualifs::{NeedsDrop, Qualif};
+use super::qualifs::{NeedsNonConstDrop, Qualif};
 use super::ConstCx;
 
 /// Returns `true` if we should use the more precise live drop checker that runs after drop
@@ -78,10 +78,10 @@ impl Visitor<'tcx> for CheckLiveDrops<'mir, 'tcx> {
         match &terminator.kind {
             mir::TerminatorKind::Drop { place: dropped_place, .. } => {
                 let dropped_ty = dropped_place.ty(self.body, self.tcx).ty;
-                if !NeedsDrop::in_any_value_of_ty(self.ccx, dropped_ty) {
-                    bug!(
-                        "Drop elaboration left behind a Drop for a type that does not need dropping"
-                    );
+                if !NeedsNonConstDrop::in_any_value_of_ty(self.ccx, dropped_ty) {
+                    // Instead of throwing a bug, we just return here. This is because we have to
+                    // run custom `const Drop` impls.
+                    return;
                 }
 
                 if dropped_place.is_indirect() {
diff --git a/compiler/rustc_mir/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index 413a9638eb3..dc3927ed85b 100644
--- a/compiler/rustc_mir/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -3,10 +3,14 @@
 //! See the `Qualif` trait for more info.
 
 use rustc_errors::ErrorReported;
+use rustc_hir as hir;
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
 use rustc_span::DUMMY_SP;
-use rustc_trait_selection::traits;
+use rustc_trait_selection::traits::{
+    self, ImplSource, Obligation, ObligationCause, SelectionContext,
+};
 
 use super::ConstCx;
 
@@ -17,7 +21,7 @@ pub fn in_any_value_of_ty(
 ) -> ConstQualifs {
     ConstQualifs {
         has_mut_interior: HasMutInterior::in_any_value_of_ty(cx, ty),
-        needs_drop: NeedsDrop::in_any_value_of_ty(cx, ty),
+        needs_drop: NeedsNonConstDrop::in_any_value_of_ty(cx, ty),
         custom_eq: CustomEq::in_any_value_of_ty(cx, ty),
         error_occured,
     }
@@ -97,10 +101,10 @@ impl Qualif for HasMutInterior {
 /// This must be ruled out (a) because we cannot run `Drop` during compile-time
 /// as that might not be a `const fn`, and (b) because implicit promotion would
 /// remove side-effects that occur as part of dropping that value.
-pub struct NeedsDrop;
+pub struct NeedsNonConstDrop;
 
-impl Qualif for NeedsDrop {
-    const ANALYSIS_NAME: &'static str = "flow_needs_drop";
+impl Qualif for NeedsNonConstDrop {
+    const ANALYSIS_NAME: &'static str = "flow_needs_nonconst_drop";
     const IS_CLEARED_ON_MOVE: bool = true;
 
     fn in_qualifs(qualifs: &ConstQualifs) -> bool {
@@ -108,11 +112,37 @@ impl Qualif for NeedsDrop {
     }
 
     fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
-        ty.needs_drop(cx.tcx, cx.param_env)
+        let drop_trait = if let Some(did) = cx.tcx.lang_items().drop_trait() {
+            did
+        } else {
+            // there is no way to define a type that needs non-const drop
+            // without having the lang item present.
+            return false;
+        };
+        let trait_ref =
+            ty::TraitRef { def_id: drop_trait, substs: cx.tcx.mk_substs_trait(ty, &[]) };
+        let obligation = Obligation::new(
+            ObligationCause::dummy(),
+            cx.param_env,
+            ty::Binder::dummy(ty::TraitPredicate {
+                trait_ref,
+                constness: ty::BoundConstness::ConstIfConst,
+            }),
+        );
+
+        let implsrc = cx.tcx.infer_ctxt().enter(|infcx| {
+            let mut selcx = SelectionContext::with_constness(&infcx, hir::Constness::Const);
+            selcx.select(&obligation)
+        });
+        match implsrc {
+            Ok(Some(ImplSource::ConstDrop(_)))
+            | Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => false,
+            _ => true,
+        }
     }
 
     fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &'tcx AdtDef, _: SubstsRef<'tcx>) -> bool {
-        adt.has_dtor(cx.tcx)
+        adt.has_non_const_dtor(cx.tcx)
     }
 }
 
diff --git a/compiler/rustc_mir/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs
index a00301952b3..8e1b69a1d74 100644
--- a/compiler/rustc_mir/src/transform/check_consts/resolver.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs
@@ -9,7 +9,6 @@ use rustc_middle::mir::{self, BasicBlock, Local, Location};
 use std::marker::PhantomData;
 
 use super::{qualifs, ConstCx, Qualif};
-use crate::dataflow;
 
 /// A `Visitor` that propagates qualifs between locals. This defines the transfer function of
 /// `FlowSensitiveAnalysis`.
@@ -165,7 +164,7 @@ where
     }
 }
 
-impl<Q> dataflow::AnalysisDomain<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q>
+impl<Q> rustc_mir_dataflow::AnalysisDomain<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q>
 where
     Q: Qualif,
 {
@@ -182,7 +181,7 @@ where
     }
 }
 
-impl<Q> dataflow::Analysis<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q>
+impl<Q> rustc_mir_dataflow::Analysis<'tcx> for FlowSensitiveAnalysis<'_, '_, 'tcx, Q>
 where
     Q: Qualif,
 {
diff --git a/compiler/rustc_const_eval/src/transform/mod.rs b/compiler/rustc_const_eval/src/transform/mod.rs
new file mode 100644
index 00000000000..38c28f34934
--- /dev/null
+++ b/compiler/rustc_const_eval/src/transform/mod.rs
@@ -0,0 +1,5 @@
+pub mod check_consts;
+pub mod promote_consts;
+pub mod validate;
+
+pub use rustc_middle::mir::MirPass;
diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs
index 1b43670ba3a..52d04cb4ff1 100644
--- a/compiler/rustc_mir/src/transform/promote_consts.rs
+++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs
@@ -231,7 +231,7 @@ impl<'tcx> Validator<'_, 'tcx> {
 
                         // We cannot promote things that need dropping, since the promoted value
                         // would not get dropped.
-                        if self.qualif_local::<qualifs::NeedsDrop>(place.local) {
+                        if self.qualif_local::<qualifs::NeedsNonConstDrop>(place.local) {
                             return Err(Unpromotable);
                         }
 
@@ -520,6 +520,7 @@ impl<'tcx> Validator<'_, 'tcx> {
             Rvalue::NullaryOp(op, _) => match op {
                 NullOp::Box => return Err(Unpromotable),
                 NullOp::SizeOf => {}
+                NullOp::AlignOf => {}
             },
 
             Rvalue::UnaryOp(op, operand) => {
@@ -1058,7 +1059,7 @@ pub fn promote_candidates<'tcx>(
 
 /// This function returns `true` if the function being called in the array
 /// repeat expression is a `const` function.
-crate fn is_const_fn_in_array_repeat_expression<'tcx>(
+pub fn is_const_fn_in_array_repeat_expression<'tcx>(
     ccx: &ConstCx<'_, 'tcx>,
     place: &Place<'tcx>,
     body: &Body<'tcx>,
diff --git a/compiler/rustc_mir/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 835789069bb..40a32a76c94 100644
--- a/compiler/rustc_mir/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -1,9 +1,5 @@
 //! Validates the MIR to ensure that invariants are upheld.
 
-use crate::dataflow::impls::MaybeStorageLive;
-use crate::dataflow::{Analysis, ResultsCursor};
-use crate::util::storage::AlwaysLiveLocals;
-
 use super::MirPass;
 use rustc_index::bit_set::BitSet;
 use rustc_infer::infer::TyCtxtInferExt;
@@ -17,6 +13,9 @@ use rustc_middle::mir::{
 };
 use rustc_middle::ty::fold::BottomUpFolder;
 use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeFoldable};
+use rustc_mir_dataflow::impls::MaybeStorageLive;
+use rustc_mir_dataflow::storage::AlwaysLiveLocals;
+use rustc_mir_dataflow::{Analysis, ResultsCursor};
 use rustc_target::abi::Size;
 
 #[derive(Copy, Clone, Debug)]
diff --git a/compiler/rustc_mir/src/util/aggregate.rs b/compiler/rustc_const_eval/src/util/aggregate.rs
index 4bc0357cab8..4bc0357cab8 100644
--- a/compiler/rustc_mir/src/util/aggregate.rs
+++ b/compiler/rustc_const_eval/src/util/aggregate.rs
diff --git a/compiler/rustc_mir/src/util/alignment.rs b/compiler/rustc_const_eval/src/util/alignment.rs
index 73adc60577b..73adc60577b 100644
--- a/compiler/rustc_mir/src/util/alignment.rs
+++ b/compiler/rustc_const_eval/src/util/alignment.rs
diff --git a/compiler/rustc_mir/src/util/collect_writes.rs b/compiler/rustc_const_eval/src/util/collect_writes.rs
index ecf3b08a96e..9c56fd722bd 100644
--- a/compiler/rustc_mir/src/util/collect_writes.rs
+++ b/compiler/rustc_const_eval/src/util/collect_writes.rs
@@ -2,7 +2,7 @@ use rustc_middle::mir::visit::PlaceContext;
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::{Body, Local, Location};
 
-crate trait FindAssignments {
+pub trait FindAssignments {
     // Finds all statements that assign directly to local (i.e., X = ...)
     // and returns their locations.
     fn find_assignments(&self, local: Local) -> Vec<Location>;
diff --git a/compiler/rustc_mir/src/util/find_self_call.rs b/compiler/rustc_const_eval/src/util/find_self_call.rs
index 33ad128eeeb..33ad128eeeb 100644
--- a/compiler/rustc_mir/src/util/find_self_call.rs
+++ b/compiler/rustc_const_eval/src/util/find_self_call.rs
diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs
new file mode 100644
index 00000000000..4a406f8bfd0
--- /dev/null
+++ b/compiler/rustc_const_eval/src/util/mod.rs
@@ -0,0 +1,8 @@
+pub mod aggregate;
+mod alignment;
+pub mod collect_writes;
+mod find_self_call;
+
+pub use self::aggregate::expand_aggregate;
+pub use self::alignment::is_disaligned;
+pub use self::find_self_call::find_self_call;
diff --git a/compiler/rustc_data_structures/src/graph/iterate/mod.rs b/compiler/rustc_data_structures/src/graph/iterate/mod.rs
index 09b91083a63..a9db3497b23 100644
--- a/compiler/rustc_data_structures/src/graph/iterate/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/iterate/mod.rs
@@ -83,8 +83,58 @@ impl<G> DepthFirstSearch<'graph, G>
 where
     G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors,
 {
-    pub fn new(graph: &'graph G, start_node: G::Node) -> Self {
-        Self { graph, stack: vec![start_node], visited: BitSet::new_empty(graph.num_nodes()) }
+    pub fn new(graph: &'graph G) -> Self {
+        Self { graph, stack: vec![], visited: BitSet::new_empty(graph.num_nodes()) }
+    }
+
+    /// Version of `push_start_node` that is convenient for chained
+    /// use.
+    pub fn with_start_node(mut self, start_node: G::Node) -> Self {
+        self.push_start_node(start_node);
+        self
+    }
+
+    /// Pushes another start node onto the stack. If the node
+    /// has not already been visited, then you will be able to
+    /// walk its successors (and so forth) after the current
+    /// contents of the stack are drained. If multiple start nodes
+    /// are added into the walk, then their mutual successors
+    /// will all be walked. You can use this method once the
+    /// iterator has been completely drained to add additional
+    /// start nodes.
+    pub fn push_start_node(&mut self, start_node: G::Node) {
+        if self.visited.insert(start_node) {
+            self.stack.push(start_node);
+        }
+    }
+
+    /// Searches all nodes reachable from the current start nodes.
+    /// This is equivalent to just invoke `next` repeatedly until
+    /// you get a `None` result.
+    pub fn complete_search(&mut self) {
+        while let Some(_) = self.next() {}
+    }
+
+    /// Returns true if node has been visited thus far.
+    /// A node is considered "visited" once it is pushed
+    /// onto the internal stack; it may not yet have been yielded
+    /// from the iterator. This method is best used after
+    /// the iterator is completely drained.
+    pub fn visited(&self, node: G::Node) -> bool {
+        self.visited.contains(node)
+    }
+}
+
+impl<G> std::fmt::Debug for DepthFirstSearch<'_, G>
+where
+    G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors,
+{
+    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let mut f = fmt.debug_set();
+        for n in self.visited.iter() {
+            f.entry(&n);
+        }
+        f.finish()
     }
 }
 
diff --git a/compiler/rustc_data_structures/src/graph/iterate/tests.rs b/compiler/rustc_data_structures/src/graph/iterate/tests.rs
index 0e038e88b22..c498c289337 100644
--- a/compiler/rustc_data_structures/src/graph/iterate/tests.rs
+++ b/compiler/rustc_data_structures/src/graph/iterate/tests.rs
@@ -20,3 +20,19 @@ fn is_cyclic() {
     assert!(!is_cyclic(&diamond_acyclic));
     assert!(is_cyclic(&diamond_cyclic));
 }
+
+#[test]
+fn dfs() {
+    let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3), (3, 0)]);
+
+    let result: Vec<usize> = DepthFirstSearch::new(&graph).with_start_node(0).collect();
+    assert_eq!(result, vec![0, 2, 3, 1]);
+}
+
+#[test]
+fn dfs_debug() {
+    let graph = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3), (3, 0)]);
+    let mut dfs = DepthFirstSearch::new(&graph).with_start_node(0);
+    dfs.complete_search();
+    assert_eq!(format!("{{0, 1, 2, 3}}"), format!("{:?}", dfs));
+}
diff --git a/compiler/rustc_data_structures/src/graph/mod.rs b/compiler/rustc_data_structures/src/graph/mod.rs
index dff22855629..3560df6e5e2 100644
--- a/compiler/rustc_data_structures/src/graph/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/mod.rs
@@ -32,7 +32,7 @@ where
     where
         Self: WithNumNodes,
     {
-        iterate::DepthFirstSearch::new(self, from)
+        iterate::DepthFirstSearch::new(self).with_start_node(from)
     }
 }
 
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 18bc2f896f2..dd6a17b92ae 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -21,8 +21,8 @@
 #![feature(iter_map_while)]
 #![feature(maybe_uninit_uninit_array)]
 #![feature(min_specialization)]
-#![cfg_attr(bootstrap, feature(min_type_alias_impl_trait))]
-#![cfg_attr(not(bootstrap), feature(type_alias_impl_trait))]
+#![feature(never_type)]
+#![feature(type_alias_impl_trait)]
 #![feature(new_uninit)]
 #![feature(nll)]
 #![feature(once_cell)]
diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs
index 18b352cf3b0..354f9dd93cc 100644
--- a/compiler/rustc_data_structures/src/stable_hasher.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher.rs
@@ -209,6 +209,12 @@ impl_stable_hash_via_hash!(i128);
 impl_stable_hash_via_hash!(char);
 impl_stable_hash_via_hash!(());
 
+impl<CTX> HashStable<CTX> for ! {
+    fn hash_stable(&self, _ctx: &mut CTX, _hasher: &mut StableHasher) {
+        unreachable!()
+    }
+}
+
 impl<CTX> HashStable<CTX> for ::std::num::NonZeroU32 {
     fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
         self.get().hash_stable(ctx, hasher)
diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml
index 57159962a9e..ba8616cc6ef 100644
--- a/compiler/rustc_driver/Cargo.toml
+++ b/compiler/rustc_driver/Cargo.toml
@@ -22,7 +22,7 @@ rustc_feature = { path = "../rustc_feature" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_hir_pretty = { path = "../rustc_hir_pretty" }
 rustc_metadata = { path = "../rustc_metadata" }
-rustc_mir = { path = "../rustc_mir" }
+rustc_const_eval = { path = "../rustc_const_eval" }
 rustc_parse = { path = "../rustc_parse" }
 rustc_plugin_impl = { path = "../rustc_plugin_impl" }
 rustc_save_analysis = { path = "../rustc_save_analysis" }
diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs
index 579ba43b6d8..a25cc000443 100644
--- a/compiler/rustc_driver/src/pretty.rs
+++ b/compiler/rustc_driver/src/pretty.rs
@@ -6,8 +6,8 @@ use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_hir_pretty as pprust_hir;
 use rustc_middle::hir::map as hir_map;
+use rustc_middle::mir::{write_mir_graphviz, write_mir_pretty};
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_mir::util::{write_mir_graphviz, write_mir_pretty};
 use rustc_session::config::{Input, PpAstTreeMode, PpHirMode, PpMode, PpSourceMode};
 use rustc_session::Session;
 use rustc_span::symbol::Ident;
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 550c1c43530..41a73268f46 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -74,6 +74,10 @@ impl DiagnosticStyledString {
     pub fn highlighted<S: Into<String>>(t: S) -> DiagnosticStyledString {
         DiagnosticStyledString(vec![StringPart::Highlighted(t.into())])
     }
+
+    pub fn content(&self) -> String {
+        self.0.iter().map(|x| x.content()).collect::<String>()
+    }
 }
 
 #[derive(Debug, PartialEq, Eq)]
@@ -82,6 +86,14 @@ pub enum StringPart {
     Highlighted(String),
 }
 
+impl StringPart {
+    pub fn content(&self) -> &str {
+        match self {
+            &StringPart::Normal(ref s) | &StringPart::Highlighted(ref s) => s,
+        }
+    }
+}
+
 impl Diagnostic {
     pub fn new(level: Level, message: &str) -> Self {
         Diagnostic::new_with_code(level, None, message)
@@ -304,6 +316,21 @@ impl Diagnostic {
         )
     }
 
+    /// Show a suggestion that has multiple parts to it, always as it's own subdiagnostic.
+    /// In other words, multiple changes need to be applied as part of this suggestion.
+    pub fn multipart_suggestion_verbose(
+        &mut self,
+        msg: &str,
+        suggestion: Vec<(Span, String)>,
+        applicability: Applicability,
+    ) -> &mut Self {
+        self.multipart_suggestion_with_style(
+            msg,
+            suggestion,
+            applicability,
+            SuggestionStyle::ShowAlways,
+        )
+    }
     /// [`Diagnostic::multipart_suggestion()`] but you can set the [`SuggestionStyle`].
     pub fn multipart_suggestion_with_style(
         &mut self,
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index c498ce7dbe4..6f84b0d400e 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -258,6 +258,20 @@ impl<'a> DiagnosticBuilder<'a> {
         self
     }
 
+    /// See [`Diagnostic::multipart_suggestion()`].
+    pub fn multipart_suggestion_verbose(
+        &mut self,
+        msg: &str,
+        suggestion: Vec<(Span, String)>,
+        applicability: Applicability,
+    ) -> &mut Self {
+        if !self.0.allow_suggestions {
+            return self;
+        }
+        self.0.diagnostic.multipart_suggestion_verbose(msg, suggestion, applicability);
+        self
+    }
+
     /// See [`Diagnostic::tool_only_multipart_suggestion()`].
     pub fn tool_only_multipart_suggestion(
         &mut self,
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 02b6179f895..b1526cf78d2 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -9,7 +9,6 @@
 #![feature(format_args_capture)]
 #![feature(iter_zip)]
 #![feature(nll)]
-#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard
 
 #[macro_use]
 extern crate rustc_macros;
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 35df8aae4ba..b630bc1f473 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -10,12 +10,12 @@ use rustc_ast::{self as ast, AstLike, Attribute, Item, NodeId, PatKind};
 use rustc_attr::{self as attr, Deprecation, Stability};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{self, Lrc};
-use rustc_errors::{DiagnosticBuilder, ErrorReported};
+use rustc_errors::{Applicability, DiagnosticBuilder, ErrorReported};
 use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
 use rustc_lint_defs::BuiltinLintDiagnostics;
 use rustc_parse::{self, nt_to_tokenstream, parser, MACRO_ARGUMENTS};
 use rustc_session::{parse::ParseSess, Limit, Session};
-use rustc_span::def_id::{CrateNum, DefId};
+use rustc_span::def_id::{CrateNum, DefId, LocalDefId};
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId};
 use rustc_span::source_map::SourceMap;
@@ -843,6 +843,7 @@ pub type DeriveResolutions = Vec<(ast::Path, Annotatable, Option<Lrc<SyntaxExten
 
 pub trait ResolverExpand {
     fn next_node_id(&mut self) -> NodeId;
+    fn invocation_parent(&self, id: LocalExpnId) -> LocalDefId;
 
     fn resolve_dollar_crates(&mut self);
     fn visit_ast_fragment_with_placeholders(
@@ -1136,13 +1137,15 @@ impl<'a> ExtCtxt<'a> {
 }
 
 /// Extracts a string literal from the macro expanded version of `expr`,
-/// emitting `err_msg` if `expr` is not a string literal. This does not stop
-/// compilation on error, merely emits a non-fatal error and returns `None`.
+/// returning a diagnostic error of `err_msg` if `expr` is not a string literal.
+/// The returned bool indicates whether an applicable suggestion has already been
+/// added to the diagnostic to avoid emitting multiple suggestions. `Err(None)`
+/// indicates that an ast error was encountered.
 pub fn expr_to_spanned_string<'a>(
     cx: &'a mut ExtCtxt<'_>,
     expr: P<ast::Expr>,
     err_msg: &str,
-) -> Result<(Symbol, ast::StrStyle, Span), Option<DiagnosticBuilder<'a>>> {
+) -> Result<(Symbol, ast::StrStyle, Span), Option<(DiagnosticBuilder<'a>, bool)>> {
     // Perform eager expansion on the expression.
     // We want to be able to handle e.g., `concat!("foo", "bar")`.
     let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr();
@@ -1150,14 +1153,27 @@ pub fn expr_to_spanned_string<'a>(
     Err(match expr.kind {
         ast::ExprKind::Lit(ref l) => match l.kind {
             ast::LitKind::Str(s, style) => return Ok((s, style, expr.span)),
+            ast::LitKind::ByteStr(_) => {
+                let mut err = cx.struct_span_err(l.span, err_msg);
+                err.span_suggestion(
+                    expr.span.shrink_to_lo(),
+                    "consider removing the leading `b`",
+                    String::new(),
+                    Applicability::MaybeIncorrect,
+                );
+                Some((err, true))
+            }
             ast::LitKind::Err(_) => None,
-            _ => Some(cx.struct_span_err(l.span, err_msg)),
+            _ => Some((cx.struct_span_err(l.span, err_msg), false)),
         },
         ast::ExprKind::Err => None,
-        _ => Some(cx.struct_span_err(expr.span, err_msg)),
+        _ => Some((cx.struct_span_err(expr.span, err_msg), false)),
     })
 }
 
+/// Extracts a string literal from the macro expanded version of `expr`,
+/// emitting `err_msg` if `expr` is not a string literal. This does not stop
+/// compilation on error, merely emits a non-fatal error and returns `None`.
 pub fn expr_to_string(
     cx: &mut ExtCtxt<'_>,
     expr: P<ast::Expr>,
@@ -1165,7 +1181,7 @@ pub fn expr_to_string(
 ) -> Option<(Symbol, ast::StrStyle)> {
     expr_to_spanned_string(cx, expr, err_msg)
         .map_err(|err| {
-            err.map(|mut err| {
+            err.map(|(mut err, _)| {
                 err.emit();
             })
         })
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 3ccf9f446a6..62066ca9657 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -588,7 +588,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         // Resolve `$crate`s in the fragment for pretty-printing.
         self.cx.resolver.resolve_dollar_crates();
 
-        let invocations = {
+        let mut invocations = {
             let mut collector = InvocationCollector {
                 // Non-derive macro invocations cannot see the results of cfg expansion - they
                 // will either be removed along with the item, or invoked before the cfg/cfg_attr
@@ -613,6 +613,19 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             self.cx
                 .resolver
                 .visit_ast_fragment_with_placeholders(self.cx.current_expansion.id, &fragment);
+
+            if self.cx.sess.opts.debugging_opts.incremental_relative_spans {
+                for (invoc, _) in invocations.iter_mut() {
+                    let expn_id = invoc.expansion_data.id;
+                    let parent_def = self.cx.resolver.invocation_parent(expn_id);
+                    let span = match &mut invoc.kind {
+                        InvocationKind::Bang { ref mut span, .. } => span,
+                        InvocationKind::Attr { attr, .. } => &mut attr.span,
+                        InvocationKind::Derive { path, .. } => &mut path.span,
+                    };
+                    *span = span.with_parent(Some(parent_def));
+                }
+            }
         }
 
         (fragment, invocations)
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs
index c6dc66e99fe..6dfeb047ec9 100644
--- a/compiler/rustc_expand/src/lib.rs
+++ b/compiler/rustc_expand/src/lib.rs
@@ -1,4 +1,3 @@
-#![cfg_attr(bootstrap, feature(bindings_after_at))]
 #![feature(crate_visibility_modifier)]
 #![feature(decl_macro)]
 #![feature(destructuring_assignment)]
@@ -9,7 +8,6 @@
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_span)]
 #![feature(try_blocks)]
-#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index fb7479eafc8..363cc72b52c 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -72,7 +72,7 @@ pub(super) fn parse(
                                             // this with just `span.edition()`. A
                                             // `SyntaxContext::root()` from the current crate will
                                             // have the edition of the current crate, and a
-                                            // `SyntaxxContext::root()` from a foreign crate will
+                                            // `SyntaxContext::root()` from a foreign crate will
                                             // have the edition of that crate (which we manually
                                             // retrieve via the `edition` parameter).
                                             if span.ctxt() == SyntaxContext::root() {
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 55700f7b0d4..52b60c3047e 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -745,7 +745,7 @@ impl server::Span for Rustc<'_> {
         self.sess.source_map().lookup_char_pos(span.lo()).file
     }
     fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
-        span.parent()
+        span.parent_callsite()
     }
     fn source(&mut self, span: Self::Span) -> Self::Span {
         span.source_callsite()
@@ -758,6 +758,12 @@ impl server::Span for Rustc<'_> {
         let loc = self.sess.source_map().lookup_char_pos(span.hi());
         LineColumn { line: loc.line, column: loc.col.to_usize() }
     }
+    fn before(&mut self, span: Self::Span) -> Self::Span {
+        span.shrink_to_lo()
+    }
+    fn after(&mut self, span: Self::Span) -> Self::Span {
+        span.shrink_to_hi()
+    }
     fn join(&mut self, first: Self::Span, second: Self::Span) -> Option<Self::Span> {
         let self_loc = self.sess.source_map().lookup_char_pos(first.lo());
         let other_loc = self.sess.source_map().lookup_char_pos(second.lo());
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 725f8b8763a..61e27d2e4cd 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -16,7 +16,6 @@ macro_rules! declare_features {
                     since: $ver,
                     issue: to_nonzero($issue),
                     edition: None,
-                    description: concat!($($doc,)*),
                 }
             ),+
         ];
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index a3807a2bb9f..efa93c18636 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -37,7 +37,6 @@ macro_rules! declare_features {
                     since: $ver,
                     issue: to_nonzero($issue),
                     edition: $edition,
-                    description: concat!($($doc,)*),
                 }
             ),+];
 
@@ -639,9 +638,6 @@ declare_features! (
     /// Allows specifying the as-needed link modifier
     (active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None),
 
-    /// Allows unnamed fields of struct and union type
-    (incomplete, unnamed_fields, "1.53.0", Some(49804), None),
-
     /// Allows qualified paths in struct expressions, struct patterns and tuple struct patterns.
     (active, more_qualified_paths, "1.54.0", Some(86935), None),
 
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index e2aa54a59b2..f74ea0e0c4d 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -453,6 +453,9 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
     // Enumerates "identity-like" conversion methods to suggest on type mismatch.
     rustc_attr!(rustc_conversion_suggestion, Normal, template!(Word), INTERNAL_UNSTABLE),
+    // Prevents field reads in the marked trait or method to be considered
+    // during dead code analysis.
+    rustc_attr!(rustc_trivial_field_reads, Normal, template!(Word), INTERNAL_UNSTABLE),
 
     // ==========================================================================
     // Internal attributes, Const related:
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index cf102aa16e0..b25aab21e49 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -51,7 +51,6 @@ pub struct Feature {
     pub since: &'static str,
     issue: Option<NonZeroU32>,
     pub edition: Option<Edition>,
-    description: &'static str,
 }
 
 #[derive(Copy, Clone, Debug)]
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 8e498a5446e..7b9b68268ea 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -16,7 +16,6 @@ macro_rules! declare_features {
                     since: $ver,
                     issue: to_nonzero($issue),
                     edition: None,
-                    description: concat!($($doc,)*),
                 }
             ),+
         ];
@@ -34,7 +33,6 @@ macro_rules! declare_features {
                     since: $ver,
                     issue: to_nonzero($issue),
                     edition: None,
-                    description: concat!($($doc,)*),
                 }
             ),+
         ];
@@ -104,7 +102,7 @@ declare_features! (
     (removed, quote, "1.33.0", Some(29601), None, None),
     /// Allows const generic types (e.g. `struct Foo<const N: usize>(...);`).
     (removed, const_generics, "1.34.0", Some(44580), None,
-     Some("removed in favor of `#![feature(adt_const_params]` and `#![feature(generic_const_exprs)]`")),
+     Some("removed in favor of `#![feature(adt_const_params)]` and `#![feature(generic_const_exprs)]`")),
     /// Allows `[x; N]` where `x` is a constant (RFC 2203).
     (removed, const_in_array_repeat_expressions,  "1.37.0", Some(49147), None,
      Some("removed due to causing promotable bugs")),
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 853415c4173..cb668eb35e0 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -598,6 +598,11 @@ impl<Id> Res<Id> {
         }
     }
 
+    #[track_caller]
+    pub fn expect_non_local<OtherId>(self) -> Res<OtherId> {
+        self.map_id(|_| panic!("unexpected `Res::Local`"))
+    }
+
     pub fn macro_kind(self) -> Option<MacroKind> {
         match self {
             Res::Def(DefKind::Macro(kind), _) => Some(kind),
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
index 30a367052cb..5f56f3a32ad 100644
--- a/compiler/rustc_hir/src/definitions.rs
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -14,6 +14,7 @@ use rustc_data_structures::unhash::UnhashMap;
 use rustc_index::vec::IndexVec;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_span::Span;
 
 use std::fmt::{self, Write};
 use std::hash::Hash;
@@ -107,6 +108,8 @@ pub struct Definitions {
 
     /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
     expansions_that_defined: FxHashMap<LocalDefId, ExpnId>,
+
+    def_id_to_span: IndexVec<LocalDefId, Span>,
 }
 
 /// A unique identifier that we can use to lookup a definition
@@ -324,7 +327,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(stable_crate_id: StableCrateId, crate_span: Span) -> Definitions {
         let key = DefKey {
             parent: None,
             disambiguated_data: DisambiguatedDefPathData {
@@ -341,11 +344,18 @@ impl Definitions {
         let root = LocalDefId { local_def_index: table.allocate(key, def_path_hash) };
         assert_eq!(root.local_def_index, CRATE_DEF_INDEX);
 
+        let mut def_id_to_span = IndexVec::new();
+        // A relative span's parent must be an absolute span.
+        debug_assert_eq!(crate_span.data_untracked().parent, None);
+        let _root = def_id_to_span.push(crate_span);
+        debug_assert_eq!(_root, root);
+
         Definitions {
             table,
             def_id_to_hir_id: Default::default(),
             hir_id_to_def_id: Default::default(),
             expansions_that_defined: Default::default(),
+            def_id_to_span,
         }
     }
 
@@ -361,6 +371,7 @@ impl Definitions {
         data: DefPathData,
         expn_id: ExpnId,
         mut next_disambiguator: impl FnMut(LocalDefId, DefPathData) -> u32,
+        span: Span,
     ) -> LocalDefId {
         debug!("create_def(parent={:?}, data={:?}, expn_id={:?})", parent, data, expn_id);
 
@@ -385,6 +396,11 @@ impl Definitions {
             self.expansions_that_defined.insert(def_id, expn_id);
         }
 
+        // A relative span's parent must be an absolute span.
+        debug_assert_eq!(span.data_untracked().parent, None);
+        let _id = self.def_id_to_span.push(span);
+        debug_assert_eq!(_id, def_id);
+
         def_id
     }
 
@@ -412,6 +428,12 @@ impl Definitions {
         self.expansions_that_defined.get(&id).copied().unwrap_or_else(ExpnId::root)
     }
 
+    /// Retrieves the span of the given `DefId` if `DefId` is in the local crate.
+    #[inline]
+    pub fn def_span(&self, def_id: LocalDefId) -> Span {
+        self.def_id_to_span[def_id]
+    }
+
     pub fn iter_local_def_id(&self) -> impl Iterator<Item = LocalDefId> + '_ {
         self.def_id_to_hir_id.iter_enumerated().map(|(k, _)| k)
     }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 84bc37170c6..5655c4c0e97 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -3234,12 +3234,7 @@ impl<'hir> Node<'hir> {
         }
     }
 
-    /// Returns `Constness::Const` when this node is a const fn/impl/item,
-    ///
-    /// HACK(fee1-dead): or an associated type in a trait. This works because
-    /// only typeck cares about const trait predicates, so although the predicates
-    /// query would return const predicates when it does not need to be const,
-    /// it wouldn't have any effect.
+    /// Returns `Constness::Const` when this node is a const fn/impl/item.
     pub fn constness_for_typeck(&self) -> Constness {
         match self {
             Node::Item(Item {
@@ -3258,7 +3253,6 @@ impl<'hir> Node<'hir> {
 
             Node::Item(Item { kind: ItemKind::Const(..), .. })
             | Node::TraitItem(TraitItem { kind: TraitItemKind::Const(..), .. })
-            | Node::TraitItem(TraitItem { kind: TraitItemKind::Type(..), .. })
             | Node::ImplItem(ImplItem { kind: ImplItemKind::Const(..), .. }) => Constness::Const,
 
             _ => Constness::NotConst,
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 36054c04847..67f92bc0a51 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1036,7 +1036,7 @@ impl<'a> State<'a> {
         self.maybe_print_comment(st.span.lo());
         match st.kind {
             hir::StmtKind::Local(ref loc) => {
-                self.print_local(loc.init.as_deref(), |this| this.print_local_decl(&loc));
+                self.print_local(loc.init, |this| this.print_local_decl(&loc));
             }
             hir::StmtKind::Item(item) => self.ann.nested(self, Nested::Item(item)),
             hir::StmtKind::Expr(ref expr) => {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 32150c7f4c6..b8089b2499b 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -1971,6 +1971,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         trace: TypeTrace<'tcx>,
         terr: &TypeError<'tcx>,
     ) -> DiagnosticBuilder<'tcx> {
+        use crate::traits::ObligationCauseCode::MatchExpressionArm;
+
         debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
 
         let span = trace.cause.span(self.tcx);
@@ -2013,6 +2015,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                         _ => {}
                     }
                 }
+                if let MatchExpressionArm(box MatchExpressionArmCause { source, .. }) =
+                    trace.cause.code
+                {
+                    if let hir::MatchSource::TryDesugar = source {
+                        if let Some((expected_ty, found_ty)) = self.values_str(trace.values) {
+                            err.note(&format!(
+                                "`?` operator cannot convert from `{}` to `{}`",
+                                found_ty.content(),
+                                expected_ty.content(),
+                            ));
+                        }
+                    }
+                }
                 err
             }
             FailureCode::Error0644(failure_str) => {
@@ -2345,7 +2360,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 );
                 err.span_suggestion(
                     generics.where_clause.tail_span_for_suggestion(),
-                    "consider adding a where clause".into(),
+                    "consider adding a where clause",
                     suggestion,
                     Applicability::MaybeIncorrect,
                 );
@@ -2585,9 +2600,7 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
             CompareImplTypeObligation { .. } => Error0308("type not compatible with trait"),
             MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => {
                 Error0308(match source {
-                    hir::MatchSource::TryDesugar => {
-                        "try expression alternatives have incompatible types"
-                    }
+                    hir::MatchSource::TryDesugar => "`?` operator has incompatible types",
                     _ => "`match` arms have incompatible types",
                 })
             }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
index c60a7149e40..593d06bad7b 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
@@ -29,7 +29,13 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             SubregionOrigin::Subtype(box TypeTrace { ref cause, .. }) => cause,
             _ => return None,
         };
-        let (parent, impl_def_id) = match &cause.code {
+        // If we added a "points at argument expression" obligation, we remove it here, we care
+        // about the original obligation only.
+        let code = match &cause.code {
+            ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } => &*parent_code,
+            _ => &cause.code,
+        };
+        let (parent, impl_def_id) = match code {
             ObligationCauseCode::MatchImpl(parent, impl_def_id) => (parent, impl_def_id),
             _ => return None,
         };
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
index 61c8113d052..43aa8a6efce 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs
@@ -2,7 +2,7 @@
 
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
-use crate::infer::{Subtype, ValuePairs};
+use crate::infer::{SubregionOrigin, Subtype, ValuePairs};
 use crate::traits::ObligationCauseCode::CompareImplMethodObligation;
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
@@ -11,44 +11,53 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::Visitor;
 use rustc_middle::ty::error::ExpectedFound;
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_span::{MultiSpan, Span};
+use rustc_span::{MultiSpan, Span, Symbol};
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`.
     pub(super) fn try_report_impl_not_conforming_to_trait(&self) -> Option<ErrorReported> {
-        if let Some(ref error) = self.error {
-            debug!("try_report_impl_not_conforming_to_trait {:?}", error);
-            if let RegionResolutionError::SubSupConflict(
-                _,
-                var_origin,
-                sub_origin,
-                _sub,
-                sup_origin,
-                _sup,
-            ) = error.clone()
-            {
-                if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) =
-                    (&sup_origin, &sub_origin)
+        let error = self.error.as_ref()?;
+        debug!("try_report_impl_not_conforming_to_trait {:?}", error);
+        if let RegionResolutionError::SubSupConflict(
+            _,
+            var_origin,
+            sub_origin,
+            _sub,
+            sup_origin,
+            _sup,
+        ) = error.clone()
+        {
+            if let (&Subtype(ref sup_trace), &Subtype(ref sub_trace)) = (&sup_origin, &sub_origin) {
+                if let (
+                    ValuePairs::Types(sub_expected_found),
+                    ValuePairs::Types(sup_expected_found),
+                    CompareImplMethodObligation { trait_item_def_id, .. },
+                ) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code)
                 {
-                    if let (
-                        ValuePairs::Types(sub_expected_found),
-                        ValuePairs::Types(sup_expected_found),
-                        CompareImplMethodObligation { trait_item_def_id, .. },
-                    ) = (&sub_trace.values, &sup_trace.values, &sub_trace.cause.code)
-                    {
-                        if sup_expected_found == sub_expected_found {
-                            self.emit_err(
-                                var_origin.span(),
-                                sub_expected_found.expected,
-                                sub_expected_found.found,
-                                *trait_item_def_id,
-                            );
-                            return Some(ErrorReported);
-                        }
+                    if sup_expected_found == sub_expected_found {
+                        self.emit_err(
+                            var_origin.span(),
+                            sub_expected_found.expected,
+                            sub_expected_found.found,
+                            *trait_item_def_id,
+                        );
+                        return Some(ErrorReported);
                     }
                 }
             }
         }
+        if let RegionResolutionError::ConcreteFailure(origin, _, _) = error.clone() {
+            if let SubregionOrigin::CompareImplTypeObligation {
+                span,
+                item_name,
+                impl_item_def_id,
+                trait_item_def_id,
+            } = origin
+            {
+                self.emit_associated_type_err(span, item_name, impl_item_def_id, trait_item_def_id);
+                return Some(ErrorReported);
+            }
+        }
         None
     }
 
@@ -107,6 +116,25 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         }
         err.emit();
     }
+
+    fn emit_associated_type_err(
+        &self,
+        span: Span,
+        item_name: Symbol,
+        impl_item_def_id: DefId,
+        trait_item_def_id: DefId,
+    ) {
+        let impl_sp = self.tcx().def_span(impl_item_def_id);
+        let trait_sp = self.tcx().def_span(trait_item_def_id);
+        let mut err = self
+            .tcx()
+            .sess
+            .struct_span_err(span, &format!("`impl` associated type signature for `{}` doesn't match `trait` associated type signature", item_name));
+        err.span_label(impl_sp, &format!("found"));
+        err.span_label(trait_sp, &format!("expected"));
+
+        err.emit();
+    }
 }
 
 struct TypeParamSpanVisitor<'tcx> {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index 4bc59a4baf5..5f99a23f86e 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -99,6 +99,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     "...so that the definition in impl matches the definition from the trait",
                 );
             }
+            infer::CompareImplTypeObligation { span, .. } => {
+                label_or_note(
+                    span,
+                    "...so that the definition in impl matches the definition from the trait",
+                );
+            }
         }
     }
 
@@ -356,6 +362,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 trait_item_def_id,
                 &format!("`{}: {}`", sup, sub),
             ),
+            infer::CompareImplTypeObligation {
+                span,
+                item_name,
+                impl_item_def_id,
+                trait_item_def_id,
+            } => self.report_extra_impl_obligation(
+                span,
+                item_name,
+                impl_item_def_id,
+                trait_item_def_id,
+                &format!("`{}: {}`", sup, sub),
+            ),
         }
     }
 
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index bc98a3aa3f9..354b8e26d53 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -427,6 +427,15 @@ pub enum SubregionOrigin<'tcx> {
         impl_item_def_id: DefId,
         trait_item_def_id: DefId,
     },
+
+    /// Comparing the signature and requirements of an impl associated type
+    /// against the containing trait
+    CompareImplTypeObligation {
+        span: Span,
+        item_name: Symbol,
+        impl_item_def_id: DefId,
+        trait_item_def_id: DefId,
+    },
 }
 
 // `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger.
@@ -1810,6 +1819,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
             ReferenceOutlivesReferent(_, a) => a,
             CallReturn(a) => a,
             CompareImplMethodObligation { span, .. } => span,
+            CompareImplTypeObligation { span, .. } => span,
         }
     }
 
@@ -1833,6 +1843,17 @@ impl<'tcx> SubregionOrigin<'tcx> {
                 trait_item_def_id,
             },
 
+            traits::ObligationCauseCode::CompareImplTypeObligation {
+                item_name,
+                impl_item_def_id,
+                trait_item_def_id,
+            } => SubregionOrigin::CompareImplTypeObligation {
+                span: cause.span,
+                item_name,
+                impl_item_def_id,
+                trait_item_def_id,
+            },
+
             _ => default(),
         }
     }
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index c211d8e94a6..e88c6608aca 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -519,7 +519,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);
+        self.ambient_variance_info = self.ambient_variance_info.xform(info);
 
         debug!("relate_with_variance: ambient_variance = {:?}", self.ambient_variance);
 
@@ -597,12 +597,12 @@ where
 
         if self.ambient_covariance() {
             // Covariance: a <= b. Hence, `b: a`.
-            self.push_outlives(v_b, v_a, self.ambient_variance_info.clone());
+            self.push_outlives(v_b, v_a, self.ambient_variance_info);
         }
 
         if self.ambient_contravariance() {
             // Contravariant: b <= a. Hence, `a: b`.
-            self.push_outlives(v_a, v_b, self.ambient_variance_info.clone());
+            self.push_outlives(v_a, v_b, self.ambient_variance_info);
         }
 
         Ok(a)
diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
index d0bd508bc25..9dbfa3a850b 100644
--- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
@@ -83,10 +83,6 @@ pub fn report_object_safety_error(
                     messages.push(msg.clone());
                 }
             }
-            if trait_span.is_some() {
-                // Only provide the help if its a local trait, otherwise it's not actionable.
-                violation.solution(&mut err);
-            }
         }
     }
     let has_multi_span = !multi_span.is_empty();
@@ -104,5 +100,13 @@ pub fn report_object_safety_error(
          to be resolvable dynamically; for more information visit \
          <https://doc.rust-lang.org/reference/items/traits.html#object-safety>",
     );
+    if trait_span.is_some() {
+        let mut reported_violations: Vec<_> = reported_violations.into_iter().collect();
+        reported_violations.sort();
+        for violation in reported_violations {
+            // Only provide the help if its a local trait, otherwise it's not actionable.
+            violation.solution(&mut err);
+        }
+    }
     err
 }
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index b450c398946..e1d6982f164 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -66,10 +66,6 @@ pub type Selection<'tcx> = ImplSource<'tcx, PredicateObligation<'tcx>>;
 pub struct FulfillmentError<'tcx> {
     pub obligation: PredicateObligation<'tcx>,
     pub code: FulfillmentErrorCode<'tcx>,
-    /// Diagnostics only: we opportunistically change the `code.span` when we encounter an
-    /// obligation error caused by a call argument. When this is the case, we also signal that in
-    /// this field to ensure accuracy of suggestions.
-    pub points_at_arg_span: bool,
     /// Diagnostics only: the 'root' obligation which resulted in
     /// the failure to process `obligation`. This is the obligation
     /// that was initially passed to `register_predicate_obligation`
@@ -128,7 +124,7 @@ impl<'tcx> FulfillmentError<'tcx> {
         code: FulfillmentErrorCode<'tcx>,
         root_obligation: PredicateObligation<'tcx>,
     ) -> FulfillmentError<'tcx> {
-        FulfillmentError { obligation, code, points_at_arg_span: false, root_obligation }
+        FulfillmentError { obligation, code, root_obligation }
     }
 }
 
diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml
index dad5b256e42..e76fa6d8a1b 100644
--- a/compiler/rustc_interface/Cargo.toml
+++ b/compiler/rustc_interface/Cargo.toml
@@ -14,6 +14,7 @@ rayon = { version = "0.3.1", package = "rustc-rayon" }
 smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
 rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
+rustc_borrowck = { path = "../rustc_borrowck" }
 rustc_builtin_macros = { path = "../rustc_builtin_macros" }
 rustc_expand = { path = "../rustc_expand" }
 rustc_parse = { path = "../rustc_parse" }
@@ -31,8 +32,10 @@ rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
 rustc_codegen_llvm = { path = "../rustc_codegen_llvm", optional = true }
 rustc_hir = { path = "../rustc_hir" }
 rustc_metadata = { path = "../rustc_metadata" }
-rustc_mir = { path = "../rustc_mir" }
+rustc_const_eval = { path = "../rustc_const_eval" }
 rustc_mir_build = { path = "../rustc_mir_build" }
+rustc_mir_transform = { path = "../rustc_mir_transform" }
+rustc_monomorphize = { path = "../rustc_monomorphize" }
 rustc_passes = { path = "../rustc_passes" }
 rustc_typeck = { path = "../rustc_typeck" }
 rustc_lint = { path = "../rustc_lint" }
diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs
index 3b852b8ccf9..95bd2993456 100644
--- a/compiler/rustc_interface/src/callbacks.rs
+++ b/compiler/rustc_interface/src/callbacks.rs
@@ -25,6 +25,16 @@ fn span_debug(span: rustc_span::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result
     })
 }
 
+fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) {
+    tls::with_opt(|tcx| {
+        if let Some(tcx) = tcx {
+            let _span = tcx.source_span(def_id);
+            // Sanity check: relative span's parent must be an absolute span.
+            debug_assert_eq!(_span.data_untracked().parent, None);
+        }
+    })
+}
+
 /// This is a callback from `rustc_ast` as it cannot access the implicit state
 /// in `rustc_middle` otherwise. It is used to when diagnostic messages are
 /// emitted and stores them in the current query, if there is one.
@@ -56,6 +66,7 @@ fn def_id_debug(def_id: rustc_hir::def_id::DefId, f: &mut fmt::Formatter<'_>) ->
 /// TyCtxt in.
 pub fn setup_callbacks() {
     rustc_span::SPAN_DEBUG.swap(&(span_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
+    rustc_span::SPAN_TRACK.swap(&(track_span_parent as fn(_)));
     rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
     TRACK_DIAGNOSTICS.swap(&(track_diagnostic as fn(&_)));
 }
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 1d542db9b69..1f3d6f70ff8 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -4,6 +4,7 @@ use crate::util;
 
 use rustc_ast::mut_visit::MutVisitor;
 use rustc_ast::{self as ast, visit};
+use rustc_borrowck as mir_borrowck;
 use rustc_codegen_ssa::back::link::emit_metadata;
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_data_structures::parallel;
@@ -21,7 +22,6 @@ use rustc_middle::middle;
 use rustc_middle::middle::cstore::{MetadataLoader, MetadataLoaderDyn};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt};
-use rustc_mir as mir;
 use rustc_mir_build as mir_build;
 use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str};
 use rustc_passes::{self, hir_stats, layout_test};
@@ -737,9 +737,12 @@ pub static DEFAULT_QUERY_PROVIDERS: SyncLazy<Providers> = SyncLazy::new(|| {
     let providers = &mut Providers::default();
     providers.analysis = analysis;
     proc_macro_decls::provide(providers);
+    rustc_const_eval::provide(providers);
     rustc_middle::hir::provide(providers);
-    mir::provide(providers);
+    mir_borrowck::provide(providers);
     mir_build::provide(providers);
+    rustc_mir_transform::provide(providers);
+    rustc_monomorphize::provide(providers);
     rustc_privacy::provide(providers);
     typeck::provide(providers);
     ty::provide(providers);
@@ -911,7 +914,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
         for def_id in tcx.body_owners() {
             tcx.ensure().thir_check_unsafety(def_id);
             if !tcx.sess.opts.debugging_opts.thir_unsafeck {
-                mir::transform::check_unsafety::check_unsafety(tcx, def_id);
+                rustc_mir_transform::check_unsafety::check_unsafety(tcx, def_id);
             }
 
             if tcx.hir().body_const_context(def_id).is_some() {
@@ -1059,7 +1062,7 @@ pub fn start_codegen<'tcx>(
     info!("Post-codegen\n{:?}", tcx.debug_stats());
 
     if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) {
-        if let Err(e) = mir::transform::dump_mir::emit_mir(tcx, outputs) {
+        if let Err(e) = rustc_mir_transform::dump_mir::emit_mir(tcx, outputs) {
             tcx.sess.err(&format!("could not emit MIR: {}", e));
             tcx.sess.abort_if_errors();
         }
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index afab919bc3c..cfe13b1fd4e 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -743,6 +743,7 @@ fn test_debugging_options_tracking_hash() {
     tracked!(no_profiler_runtime, true);
     tracked!(osx_rpath_install_name, true);
     tracked!(panic_abort_tests, true);
+    tracked!(panic_in_drop, PanicStrategy::Abort);
     tracked!(partially_uninit_const_threshold, Some(123));
     tracked!(plt, Some(true));
     tracked!(polonius, true);
@@ -753,6 +754,7 @@ fn test_debugging_options_tracking_hash() {
     tracked!(profiler_runtime, "abc".to_string());
     tracked!(relax_elf_relocations, Some(true));
     tracked!(relro_level, Some(RelroLevel::Full));
+    tracked!(remap_cwd_prefix, Some(PathBuf::from("abc")));
     tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc")));
     tracked!(report_delayed_bugs, true);
     tracked!(sanitizer, SanitizerSet::ADDRESS);
diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs
index edb158dd378..5435ff1396d 100644
--- a/compiler/rustc_lint/src/traits.rs
+++ b/compiler/rustc_lint/src/traits.rs
@@ -86,6 +86,7 @@ declare_lint_pass!(
 
 impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
+        use rustc_middle::ty;
         use rustc_middle::ty::PredicateKind::*;
 
         let predicates = cx.tcx.explicit_predicates_of(item.def_id);
@@ -94,6 +95,10 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
                 Trait(trait_predicate) => trait_predicate,
                 _ => continue,
             };
+            if trait_predicate.constness == ty::BoundConstness::ConstIfConst {
+                // `~const Drop` definitely have meanings so avoid linting here.
+                continue;
+            }
             let def_id = trait_predicate.trait_ref.def_id;
             if cx.tcx.lang_items().drop_trait() == Some(def_id) {
                 // Explicitly allow `impl Drop`, a drop-guards-as-Voldemort-type pattern.
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 480f7756db3..d35497c1b38 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -851,12 +851,18 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
         use FfiResult::*;
 
         if def.repr.transparent() {
-            // Can assume that only one field is not a ZST, so only check
+            // Can assume that at most one field is not a ZST, so only check
             // that field's type for FFI-safety.
             if let Some(field) = transparent_newtype_field(self.cx.tcx, variant) {
                 self.check_field_type_for_ffi(cache, field, substs)
             } else {
-                bug!("malformed transparent type");
+                // All fields are ZSTs; this means that the type should behave
+                // like (), which is FFI-unsafe
+                FfiUnsafe {
+                    ty,
+                    reason: "this struct contains only zero-sized fields".into(),
+                    help: None,
+                }
             }
         } else {
             // We can't completely trust repr(C) markings; make sure the fields are
@@ -1327,10 +1333,7 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {
             };
             let (variants, tag) = match layout.variants {
                 Variants::Multiple {
-                    tag_encoding: TagEncoding::Direct,
-                    ref tag,
-                    ref variants,
-                    ..
+                    tag_encoding: TagEncoding::Direct, tag, ref variants, ..
                 } => (variants, tag),
                 _ => return,
             };
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 7a42e8c1037..48b955e41ac 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -3,7 +3,6 @@ use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}
 use rustc_ast as ast;
 use rustc_ast::util::{classify, parser};
 use rustc_ast::{ExprKind, StmtKind};
-use rustc_ast_pretty::pprust;
 use rustc_errors::{pluralize, Applicability};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
@@ -12,7 +11,7 @@ use rustc_middle::ty::adjustment;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::Symbol;
 use rustc_span::symbol::{kw, sym};
-use rustc_span::{BytePos, Span, DUMMY_SP};
+use rustc_span::{BytePos, MultiSpan, Span, DUMMY_SP};
 
 declare_lint! {
     /// The `unused_must_use` lint detects unused result of a type flagged as
@@ -491,77 +490,60 @@ trait UnusedDelimLint {
         left_pos: Option<BytePos>,
         right_pos: Option<BytePos>,
     ) {
-        let expr_text = if let Ok(snippet) = cx.sess().source_map().span_to_snippet(value.span) {
-            snippet
-        } else {
-            pprust::expr_to_string(value)
+        let spans = match value.kind {
+            ast::ExprKind::Block(ref block, None) if block.stmts.len() > 0 => {
+                let start = block.stmts[0].span;
+                let end = block.stmts[block.stmts.len() - 1].span;
+                if value.span.from_expansion() || start.from_expansion() || end.from_expansion() {
+                    (
+                        value.span.with_hi(value.span.lo() + BytePos(1)),
+                        value.span.with_lo(value.span.hi() - BytePos(1)),
+                    )
+                } else {
+                    (value.span.with_hi(start.lo()), value.span.with_lo(end.hi()))
+                }
+            }
+            ast::ExprKind::Paren(ref expr) => {
+                if value.span.from_expansion() || expr.span.from_expansion() {
+                    (
+                        value.span.with_hi(value.span.lo() + BytePos(1)),
+                        value.span.with_lo(value.span.hi() - BytePos(1)),
+                    )
+                } else {
+                    (value.span.with_hi(expr.span.lo()), value.span.with_lo(expr.span.hi()))
+                }
+            }
+            _ => return,
         };
         let keep_space = (
             left_pos.map_or(false, |s| s >= value.span.lo()),
             right_pos.map_or(false, |s| s <= value.span.hi()),
         );
-        self.emit_unused_delims(cx, value.span, &expr_text, ctx.into(), keep_space);
+        self.emit_unused_delims(cx, spans, ctx.into(), keep_space);
     }
 
     fn emit_unused_delims(
         &self,
         cx: &EarlyContext<'_>,
-        span: Span,
-        pattern: &str,
+        spans: (Span, Span),
         msg: &str,
         keep_space: (bool, bool),
     ) {
         // FIXME(flip1995): Quick and dirty fix for #70814. This should be fixed in rustdoc
         // properly.
-        if span == DUMMY_SP {
+        if spans.0 == DUMMY_SP || spans.1 == DUMMY_SP {
             return;
         }
 
-        cx.struct_span_lint(self.lint(), span, |lint| {
+        cx.struct_span_lint(self.lint(), MultiSpan::from(vec![spans.0, spans.1]), |lint| {
             let span_msg = format!("unnecessary {} around {}", Self::DELIM_STR, msg);
             let mut err = lint.build(&span_msg);
-            let mut ate_left_paren = false;
-            let mut ate_right_paren = false;
-            let parens_removed = pattern
-                .trim_matches(|c| match c {
-                    '(' | '{' => {
-                        if ate_left_paren {
-                            false
-                        } else {
-                            ate_left_paren = true;
-                            true
-                        }
-                    }
-                    ')' | '}' => {
-                        if ate_right_paren {
-                            false
-                        } else {
-                            ate_right_paren = true;
-                            true
-                        }
-                    }
-                    _ => false,
-                })
-                .trim();
-
-            let replace = {
-                let mut replace = if keep_space.0 {
-                    let mut s = String::from(" ");
-                    s.push_str(parens_removed);
-                    s
-                } else {
-                    String::from(parens_removed)
-                };
-
-                if keep_space.1 {
-                    replace.push(' ');
-                }
-                replace
-            };
-
+            let replacement = vec![
+                (spans.0, if keep_space.0 { " ".into() } else { "".into() }),
+                (spans.1, if keep_space.1 { " ".into() } else { "".into() }),
+            ];
             let suggestion = format!("remove these {}", Self::DELIM_STR);
-
-            err.span_suggestion_short(span, &suggestion, replace, Applicability::MachineApplicable);
+            err.multipart_suggestion(&suggestion, replacement, Applicability::MachineApplicable);
             err.emit();
         });
     }
@@ -770,14 +752,15 @@ impl UnusedParens {
                 // Otherwise proceed with linting.
                 _ => {}
             }
-
-            let pattern_text =
-                if let Ok(snippet) = cx.sess().source_map().span_to_snippet(value.span) {
-                    snippet
-                } else {
-                    pprust::pat_to_string(value)
-                };
-            self.emit_unused_delims(cx, value.span, &pattern_text, "pattern", (false, false));
+            let spans = if value.span.from_expansion() || inner.span.from_expansion() {
+                (
+                    value.span.with_hi(value.span.lo() + BytePos(1)),
+                    value.span.with_lo(value.span.hi() - BytePos(1)),
+                )
+            } else {
+                (value.span.with_hi(inner.span.lo()), value.span.with_lo(inner.span.hi()))
+            };
+            self.emit_unused_delims(cx, spans, "pattern", (false, false));
         }
     }
 }
@@ -870,14 +853,15 @@ impl EarlyLintPass for UnusedParens {
                     );
                 }
                 _ => {
-                    let pattern_text =
-                        if let Ok(snippet) = cx.sess().source_map().span_to_snippet(ty.span) {
-                            snippet
-                        } else {
-                            pprust::ty_to_string(ty)
-                        };
-
-                    self.emit_unused_delims(cx, ty.span, &pattern_text, "type", (false, false));
+                    let spans = if ty.span.from_expansion() || r.span.from_expansion() {
+                        (
+                            ty.span.with_hi(ty.span.lo() + BytePos(1)),
+                            ty.span.with_lo(ty.span.hi() - BytePos(1)),
+                        )
+                    } else {
+                        (ty.span.with_hi(r.span.lo()), ty.span.with_lo(r.span.hi()))
+                    };
+                    self.emit_unused_delims(cx, spans, "type", (false, false));
                 }
             }
         }
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 8fb678e2d20..a00561e5213 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -3010,6 +3010,7 @@ declare_lint_pass! {
         UNSUPPORTED_CALLING_CONVENTIONS,
         BREAK_WITH_LABEL_AND_LOOP,
         UNUSED_ATTRIBUTES,
+        NON_EXHAUSTIVE_OMITTED_PATTERNS,
     ]
 }
 
@@ -3416,3 +3417,56 @@ declare_lint! {
     Warn,
     "`break` expression with label and unlabeled loop as value expression"
 }
+
+declare_lint! {
+    /// The `non_exhaustive_omitted_patterns` lint detects when a wildcard (`_` or `..`) in a
+    /// pattern for a `#[non_exhaustive]` struct or enum is reachable.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,ignore (needs separate crate)
+    /// // crate A
+    /// #[non_exhaustive]
+    /// pub enum Bar {
+    ///     A,
+    ///     B, // added variant in non breaking change
+    /// }
+    ///
+    /// // in crate B
+    /// match Bar::A {
+    ///     Bar::A => {},
+    ///     #[warn(non_exhaustive_omitted_patterns)]
+    ///     _ => {},
+    /// }
+    /// ```
+    ///
+    /// This will produce:
+    ///
+    /// ```text
+    /// warning: reachable patterns not covered of non exhaustive enum
+    ///    --> $DIR/reachable-patterns.rs:70:9
+    ///    |
+    /// LL |         _ => {}
+    ///    |         ^ pattern `B` not covered
+    ///    |
+    ///  note: the lint level is defined here
+    ///   --> $DIR/reachable-patterns.rs:69:16
+    ///    |
+    /// LL |         #[warn(non_exhaustive_omitted_patterns)]
+    ///    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    ///    = help: ensure that all possible cases are being handled by adding the suggested match arms
+    ///    = note: the matched value is of type `Bar` and the `non_exhaustive_omitted_patterns` attribute was found
+    /// ```
+    ///
+    /// ### Explanation
+    ///
+    /// Structs and enums tagged with `#[non_exhaustive]` force the user to add a
+    /// (potentially redundant) wildcard when pattern-matching, to allow for future
+    /// addition of fields or variants. The `non_exhaustive_omitted_patterns` lint
+    /// detects when such a wildcard happens to actually catch some fields/variants.
+    /// In other words, when the match without the wildcard would not be exhaustive.
+    /// This lets the user be informed if new fields/variants were added.
+    pub NON_EXHAUSTIVE_OMITTED_PATTERNS,
+    Allow,
+    "detect when patterns of types marked `non_exhaustive` are missed",
+}
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 4f07a0c67c1..9850f395a0f 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -203,56 +203,57 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
   report_fatal_error("bad AttributeKind");
 }
 
+template<typename T> static inline void AddAttribute(T *t, unsigned Index, Attribute Attr) {
+#if LLVM_VERSION_LT(14, 0)
+  t->addAttribute(Index, Attr);
+#else
+  t->addAttributeAtIndex(Index, Attr);
+#endif
+}
+
 extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned Index,
                                              LLVMRustAttribute RustAttr) {
   CallBase *Call = unwrap<CallBase>(Instr);
   Attribute Attr = Attribute::get(Call->getContext(), fromRust(RustAttr));
-  Call->addAttribute(Index, Attr);
+  AddAttribute(Call, Index, Attr);
 }
 
 extern "C" void LLVMRustAddCallSiteAttrString(LLVMValueRef Instr, unsigned Index,
                                               const char *Name) {
   CallBase *Call = unwrap<CallBase>(Instr);
   Attribute Attr = Attribute::get(Call->getContext(), Name);
-  Call->addAttribute(Index, Attr);
+  AddAttribute(Call, Index, Attr);
 }
 
-
 extern "C" void LLVMRustAddAlignmentCallSiteAttr(LLVMValueRef Instr,
                                                  unsigned Index,
                                                  uint32_t Bytes) {
   CallBase *Call = unwrap<CallBase>(Instr);
-  AttrBuilder B;
-  B.addAlignmentAttr(Bytes);
-  Call->setAttributes(Call->getAttributes().addAttributes(
-      Call->getContext(), Index, B));
+  Attribute Attr = Attribute::getWithAlignment(Call->getContext(), Align(Bytes));
+  AddAttribute(Call, Index, Attr);
 }
 
 extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr,
                                                        unsigned Index,
                                                        uint64_t Bytes) {
   CallBase *Call = unwrap<CallBase>(Instr);
-  AttrBuilder B;
-  B.addDereferenceableAttr(Bytes);
-  Call->setAttributes(Call->getAttributes().addAttributes(
-      Call->getContext(), Index, B));
+  Attribute Attr = Attribute::getWithDereferenceableBytes(Call->getContext(), Bytes);
+  AddAttribute(Call, Index, Attr);
 }
 
 extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr,
                                                              unsigned Index,
                                                              uint64_t Bytes) {
   CallBase *Call = unwrap<CallBase>(Instr);
-  AttrBuilder B;
-  B.addDereferenceableOrNullAttr(Bytes);
-  Call->setAttributes(Call->getAttributes().addAttributes(
-      Call->getContext(), Index, B));
+  Attribute Attr = Attribute::getWithDereferenceableOrNullBytes(Call->getContext(), Bytes);
+  AddAttribute(Call, Index, Attr);
 }
 
 extern "C" void LLVMRustAddByValCallSiteAttr(LLVMValueRef Instr, unsigned Index,
                                              LLVMTypeRef Ty) {
   CallBase *Call = unwrap<CallBase>(Instr);
   Attribute Attr = Attribute::getWithByValType(Call->getContext(), unwrap(Ty));
-  Call->addAttribute(Index, Attr);
+  AddAttribute(Call, Index, Attr);
 }
 
 extern "C" void LLVMRustAddStructRetCallSiteAttr(LLVMValueRef Instr, unsigned Index,
@@ -263,28 +264,28 @@ extern "C" void LLVMRustAddStructRetCallSiteAttr(LLVMValueRef Instr, unsigned In
 #else
   Attribute Attr = Attribute::get(Call->getContext(), Attribute::StructRet);
 #endif
-  Call->addAttribute(Index, Attr);
+  AddAttribute(Call, Index, Attr);
 }
 
 extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
                                              LLVMRustAttribute RustAttr) {
   Function *A = unwrap<Function>(Fn);
   Attribute Attr = Attribute::get(A->getContext(), fromRust(RustAttr));
-  A->addAttribute(Index, Attr);
+  AddAttribute(A, Index, Attr);
 }
 
 extern "C" void LLVMRustAddAlignmentAttr(LLVMValueRef Fn,
                                          unsigned Index,
                                          uint32_t Bytes) {
   Function *A = unwrap<Function>(Fn);
-  A->addAttribute(Index, Attribute::getWithAlignment(
+  AddAttribute(A, Index, Attribute::getWithAlignment(
       A->getContext(), llvm::Align(Bytes)));
 }
 
 extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn, unsigned Index,
                                                uint64_t Bytes) {
   Function *A = unwrap<Function>(Fn);
-  A->addAttribute(Index, Attribute::getWithDereferenceableBytes(A->getContext(),
+  AddAttribute(A, Index, Attribute::getWithDereferenceableBytes(A->getContext(),
                                                                 Bytes));
 }
 
@@ -292,7 +293,7 @@ extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn,
                                                      unsigned Index,
                                                      uint64_t Bytes) {
   Function *A = unwrap<Function>(Fn);
-  A->addAttribute(Index, Attribute::getWithDereferenceableOrNullBytes(
+  AddAttribute(A, Index, Attribute::getWithDereferenceableOrNullBytes(
       A->getContext(), Bytes));
 }
 
@@ -300,7 +301,7 @@ extern "C" void LLVMRustAddByValAttr(LLVMValueRef Fn, unsigned Index,
                                      LLVMTypeRef Ty) {
   Function *F = unwrap<Function>(Fn);
   Attribute Attr = Attribute::getWithByValType(F->getContext(), unwrap(Ty));
-  F->addAttribute(Index, Attr);
+  AddAttribute(F, Index, Attr);
 }
 
 extern "C" void LLVMRustAddStructRetAttr(LLVMValueRef Fn, unsigned Index,
@@ -311,7 +312,7 @@ extern "C" void LLVMRustAddStructRetAttr(LLVMValueRef Fn, unsigned Index,
 #else
   Attribute Attr = Attribute::get(F->getContext(), Attribute::StructRet);
 #endif
-  F->addAttribute(Index, Attr);
+  AddAttribute(F, Index, Attr);
 }
 
 extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
@@ -319,7 +320,7 @@ extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
                                                    const char *Name,
                                                    const char *Value) {
   Function *F = unwrap<Function>(Fn);
-  F->addAttribute(Index, Attribute::get(
+  AddAttribute(F, Index, Attribute::get(
       F->getContext(), StringRef(Name), StringRef(Value)));
 }
 
@@ -330,7 +331,12 @@ extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn,
   Attribute Attr = Attribute::get(F->getContext(), fromRust(RustAttr));
   AttrBuilder B(Attr);
   auto PAL = F->getAttributes();
-  auto PALNew = PAL.removeAttributes(F->getContext(), Index, B);
+  AttributeList PALNew;
+#if LLVM_VERSION_LT(14, 0)
+  PALNew = PAL.removeAttributes(F->getContext(), Index, B);
+#else
+  PALNew = PAL.removeAttributesAtIndex(F->getContext(), Index, B);
+#endif
   F->setAttributes(PALNew);
 }
 
diff --git a/compiler/rustc_macros/src/session_diagnostic.rs b/compiler/rustc_macros/src/session_diagnostic.rs
index 8a0fce209b7..80dcf99da62 100644
--- a/compiler/rustc_macros/src/session_diagnostic.rs
+++ b/compiler/rustc_macros/src/session_diagnostic.rs
@@ -448,7 +448,7 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
                                             span_idx = Some(syn::Index::from(idx));
                                         } else {
                                             throw_span_err!(
-                                                info.span.clone().unwrap(),
+                                                info.span.unwrap(),
                                                 "type of field annotated with `#[suggestion(...)]` contains more than one Span"
                                             );
                                         }
@@ -460,7 +460,7 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
                                             applicability_idx = Some(syn::Index::from(idx));
                                         } else {
                                             throw_span_err!(
-                                                info.span.clone().unwrap(),
+                                                info.span.unwrap(),
                                                 "type of field annotated with `#[suggestion(...)]` contains more than one Applicability"
                                             );
                                         }
@@ -479,7 +479,7 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
                                     return Ok((span, applicability));
                                 }
                                 throw_span_err!(
-                                    info.span.clone().unwrap(),
+                                    info.span.unwrap(),
                                     "wrong types for suggestion",
                                     |diag| {
                                         diag.help("#[suggestion(...)] on a tuple field must be applied to fields of type (Span, Applicability)")
@@ -487,7 +487,7 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
                                 );
                             }
                             _ => throw_span_err!(
-                                info.span.clone().unwrap(),
+                                info.span.unwrap(),
                                 "wrong field type for suggestion",
                                 |diag| {
                                     diag.help("#[suggestion(...)] should be applied to fields of type Span or (Span, Applicability)")
diff --git a/compiler/rustc_macros/src/symbols.rs b/compiler/rustc_macros/src/symbols.rs
index 85e990bde86..1b245f2a750 100644
--- a/compiler/rustc_macros/src/symbols.rs
+++ b/compiler/rustc_macros/src/symbols.rs
@@ -215,7 +215,7 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec<syn::Error>) {
         }
 
         impl Interner {
-            pub fn fresh() -> Self {
+            pub(crate) fn fresh() -> Self {
                 Interner::prefill(&[
                     #prefill_stream
                 ])
diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs
index 2d4deb1d8d5..b8d22560618 100644
--- a/compiler/rustc_metadata/src/dependency_format.rs
+++ b/compiler/rustc_metadata/src/dependency_format.rs
@@ -400,21 +400,35 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) {
                 continue;
             }
             let cnum = CrateNum::new(i + 1);
-            let found_strategy = tcx.panic_strategy(cnum);
-            let is_compiler_builtins = tcx.is_compiler_builtins(cnum);
-            if is_compiler_builtins || desired_strategy == found_strategy {
+            if tcx.is_compiler_builtins(cnum) {
                 continue;
             }
 
-            sess.err(&format!(
-                "the crate `{}` is compiled with the \
+            let found_strategy = tcx.panic_strategy(cnum);
+            if desired_strategy != found_strategy {
+                sess.err(&format!(
+                    "the crate `{}` is compiled with the \
                                panic strategy `{}` which is \
                                incompatible with this crate's \
                                strategy of `{}`",
-                tcx.crate_name(cnum),
-                found_strategy.desc(),
-                desired_strategy.desc()
-            ));
+                    tcx.crate_name(cnum),
+                    found_strategy.desc(),
+                    desired_strategy.desc()
+                ));
+            }
+
+            let found_drop_strategy = tcx.panic_in_drop_strategy(cnum);
+            if tcx.sess.opts.debugging_opts.panic_in_drop != found_drop_strategy {
+                sess.err(&format!(
+                    "the crate `{}` is compiled with the \
+                               panic-in-drop strategy `{}` which is \
+                               incompatible with this crate's \
+                               strategy of `{}`",
+                    tcx.crate_name(cnum),
+                    found_drop_strategy.desc(),
+                    tcx.sess.opts.debugging_opts.panic_in_drop.desc()
+                ));
+            }
         }
     }
 }
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index d3512b6cf57..b6922e0d72a 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -1095,6 +1095,11 @@ impl CrateError {
                         == Symbol::intern(&sess.opts.debugging_opts.profiler_runtime)
                     {
                         err.note(&"the compiler may have been built without the profiler runtime");
+                    } else if crate_name.as_str().starts_with("rustc_") {
+                        err.help(
+                            "maybe you need to install the missing components with: \
+                             `rustup component add rust-src rustc-dev llvm-tools-preview`",
+                        );
                     }
                     err.span_label(span, "can't find crate");
                     err
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index dd44e0cb1fa..2a0332a1124 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -26,6 +26,7 @@ use rustc_middle::middle::cstore::{ForeignModule, LinkagePreference, NativeLib};
 use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
 use rustc_middle::mir::{self, Body, Promoted};
+use rustc_middle::thir;
 use rustc_middle::ty::codec::TyDecoder;
 use rustc_middle::ty::{self, Ty, TyCtxt, Visibility};
 use rustc_serialize::{opaque, Decodable, Decoder};
@@ -536,11 +537,12 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
         let hi =
             (hi + source_file.translated_source_file.start_pos) - source_file.original_start_pos;
 
-        Ok(Span::new(lo, hi, ctxt))
+        // Do not try to decode parent for foreign spans.
+        Ok(Span::new(lo, hi, ctxt, None))
     }
 }
 
-impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [mir::abstract_const::Node<'tcx>] {
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [thir::abstract_const::Node<'tcx>] {
     fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Result<Self, String> {
         ty::codec::RefDecodable::decode(d)
     }
@@ -1019,10 +1021,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     /// Iterates over each child of the given item.
-    fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F, sess: &Session)
-    where
-        F: FnMut(Export<hir::HirId>),
-    {
+    fn each_child_of_item(&self, id: DefIndex, mut callback: impl FnMut(Export), sess: &Session) {
         if let Some(data) = &self.root.proc_macro_data {
             /* If we are loading as a proc macro, we want to return the view of this crate
              * as a proc macro crate.
@@ -1198,14 +1197,14 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .decode((self, tcx))
     }
 
-    fn get_mir_abstract_const(
+    fn get_thir_abstract_const(
         &self,
         tcx: TyCtxt<'tcx>,
         id: DefIndex,
-    ) -> Result<Option<&'tcx [mir::abstract_const::Node<'tcx>]>, ErrorReported> {
+    ) -> Result<Option<&'tcx [thir::abstract_const::Node<'tcx>]>, ErrorReported> {
         self.root
             .tables
-            .mir_abstract_consts
+            .thir_abstract_consts
             .get(self, id)
             .map_or(Ok(None), |v| Ok(Some(v.decode((self, tcx)))))
     }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 41839c58021..a01eaf68f01 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -5,7 +5,6 @@ use crate::rmeta::encoder;
 
 use rustc_ast as ast;
 use rustc_data_structures::stable_map::FxHashMap;
-use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
@@ -117,7 +116,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     optimized_mir => { tcx.arena.alloc(cdata.get_optimized_mir(tcx, def_id.index)) }
     mir_for_ctfe => { tcx.arena.alloc(cdata.get_mir_for_ctfe(tcx, def_id.index)) }
     promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) }
-    mir_abstract_const => { cdata.get_mir_abstract_const(tcx, def_id.index) }
+    thir_abstract_const => { cdata.get_thir_abstract_const(tcx, def_id.index) }
     unused_generic_params => { cdata.get_unused_generic_params(def_id.index) }
     const_param_default => { tcx.mk_const(cdata.get_const_param_default(tcx, def_id.index)) }
     mir_const_qualif => { cdata.mir_const_qualif(def_id.index) }
@@ -160,6 +159,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
     has_panic_handler => { cdata.root.has_panic_handler }
     is_profiler_runtime => { cdata.root.profiler_runtime }
     panic_strategy => { cdata.root.panic_strategy }
+    panic_in_drop_strategy => { cdata.root.panic_in_drop_strategy }
     extern_crate => {
         let r = *cdata.extern_crate.lock();
         r.map(|c| &*tcx.arena.alloc(c))
@@ -326,28 +326,27 @@ pub fn provide(providers: &mut Providers) {
             // (restrict scope of mutable-borrow of `visible_parent_map`)
             {
                 let visible_parent_map = &mut visible_parent_map;
-                let mut add_child =
-                    |bfs_queue: &mut VecDeque<_>, child: &Export<hir::HirId>, parent: DefId| {
-                        if child.vis != ty::Visibility::Public {
-                            return;
-                        }
+                let mut add_child = |bfs_queue: &mut VecDeque<_>, child: &Export, parent: DefId| {
+                    if child.vis != ty::Visibility::Public {
+                        return;
+                    }
 
-                        if let Some(child) = child.res.opt_def_id() {
-                            match visible_parent_map.entry(child) {
-                                Entry::Occupied(mut entry) => {
-                                    // If `child` is defined in crate `cnum`, ensure
-                                    // that it is mapped to a parent in `cnum`.
-                                    if child.is_local() && entry.get().is_local() {
-                                        entry.insert(parent);
-                                    }
-                                }
-                                Entry::Vacant(entry) => {
+                    if let Some(child) = child.res.opt_def_id() {
+                        match visible_parent_map.entry(child) {
+                            Entry::Occupied(mut entry) => {
+                                // If `child` is defined in crate `cnum`, ensure
+                                // that it is mapped to a parent in `cnum`.
+                                if child.is_local() && entry.get().is_local() {
                                     entry.insert(parent);
-                                    bfs_queue.push_back(child);
                                 }
                             }
+                            Entry::Vacant(entry) => {
+                                entry.insert(parent);
+                                bfs_queue.push_back(child);
+                            }
                         }
-                    };
+                    }
+                };
 
                 while let Some(def) = bfs_queue.pop_front() {
                     for child in tcx.item_children(def).iter() {
@@ -393,11 +392,7 @@ impl CStore {
         self.get_crate_data(def.krate).get_visibility(def.index)
     }
 
-    pub fn item_children_untracked(
-        &self,
-        def_id: DefId,
-        sess: &Session,
-    ) -> Vec<Export<hir::HirId>> {
+    pub fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec<Export> {
         let mut result = vec![];
         self.get_crate_data(def_id.krate).each_child_of_item(
             def_id.index,
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index d8b9a479976..b0d22037f21 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -23,6 +23,7 @@ use rustc_middle::middle::exported_symbols::{
     metadata_symbol_name, ExportedSymbol, SymbolExportLevel,
 };
 use rustc_middle::mir::interpret;
+use rustc_middle::thir;
 use rustc_middle::traits::specialization_graph;
 use rustc_middle::ty::codec::TyEncoder;
 use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
@@ -344,7 +345,7 @@ impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for &'tcx [mir::abstract_const::Node<'tcx>] {
+impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for &'tcx [thir::abstract_const::Node<'tcx>] {
     fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
         (**self).encode(s)
     }
@@ -691,6 +692,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             hash: tcx.crate_hash(LOCAL_CRATE),
             stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
             panic_strategy: tcx.sess.panic_strategy(),
+            panic_in_drop_strategy: tcx.sess.opts.debugging_opts.panic_in_drop,
             edition: tcx.sess.edition(),
             has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE),
             has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
@@ -1065,14 +1067,7 @@ impl EncodeContext<'a, 'tcx> {
         // items - we encode information about proc-macros later on.
         let reexports = if !self.is_proc_macro {
             match tcx.module_exports(local_def_id) {
-                Some(exports) => {
-                    let hir = self.tcx.hir();
-                    self.lazy(
-                        exports
-                            .iter()
-                            .map(|export| export.map_id(|id| hir.local_def_id_to_hir_id(id))),
-                    )
-                }
+                Some(exports) => self.lazy(exports),
                 _ => Lazy::empty(),
             }
         } else {
@@ -1304,9 +1299,10 @@ impl EncodeContext<'a, 'tcx> {
             if encode_const {
                 record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- self.tcx.mir_for_ctfe(def_id));
 
-                let abstract_const = self.tcx.mir_abstract_const(def_id);
+                // FIXME(generic_const_exprs): this feels wrong to have in `encode_mir`
+                let abstract_const = self.tcx.thir_abstract_const(def_id);
                 if let Ok(Some(abstract_const)) = abstract_const {
-                    record!(self.tables.mir_abstract_consts[def_id.to_def_id()] <- abstract_const);
+                    record!(self.tables.thir_abstract_consts[def_id.to_def_id()] <- abstract_const);
                 }
             }
             record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(def_id));
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index a487753f462..1f307f3fdee 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -15,6 +15,7 @@ use rustc_middle::hir::exports::Export;
 use rustc_middle::middle::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib};
 use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use rustc_middle::mir;
+use rustc_middle::thir;
 use rustc_middle::ty::{self, ReprOptions, Ty};
 use rustc_serialize::opaque::Encoder;
 use rustc_session::config::SymbolManglingVersion;
@@ -204,6 +205,7 @@ crate struct CrateRoot<'tcx> {
     hash: Svh,
     stable_crate_id: StableCrateId,
     panic_strategy: PanicStrategy,
+    panic_in_drop_strategy: PanicStrategy,
     edition: Edition,
     has_global_allocator: bool,
     has_panic_handler: bool,
@@ -305,7 +307,7 @@ define_tables! {
     mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
     mir_for_ctfe: Table<DefIndex, Lazy!(mir::Body<'tcx>)>,
     promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
-    mir_abstract_consts: Table<DefIndex, Lazy!(&'tcx [mir::abstract_const::Node<'tcx>])>,
+    thir_abstract_consts: Table<DefIndex, Lazy!(&'tcx [thir::abstract_const::Node<'tcx>])>,
     const_defaults: Table<DefIndex, Lazy<rustc_middle::ty::Const<'tcx>>>,
     unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>,
     // `def_keys` and `def_path_hashes` represent a lazy version of a
@@ -359,7 +361,7 @@ struct RenderedConst(String);
 
 #[derive(MetadataEncodable, MetadataDecodable)]
 struct ModData {
-    reexports: Lazy<[Export<hir::HirId>]>,
+    reexports: Lazy<[Export]>,
     expansion: ExpnId,
 }
 
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index 2403ce2d24f..68b83fccc85 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -9,6 +9,8 @@ doctest = false
 [dependencies]
 rustc_arena = { path = "../rustc_arena" }
 bitflags = "1.2.1"
+either = "1.5.0"
+gsgdt = "0.1.2"
 tracing = "0.1"
 rustc-rayon-core = "0.3.1"
 polonius-engine = "0.13.0"
@@ -21,6 +23,7 @@ rustc_macros = { path = "../rustc_macros" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_query_system = { path = "../rustc_query_system" }
 rustc_errors = { path = "../rustc_errors" }
+rustc_graphviz = { path = "../rustc_graphviz" }
 rustc_index = { path = "../rustc_index" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_ast = { path = "../rustc_ast" }
diff --git a/compiler/rustc_middle/src/hir/exports.rs b/compiler/rustc_middle/src/hir/exports.rs
index be9e38aca65..f37b976fba6 100644
--- a/compiler/rustc_middle/src/hir/exports.rs
+++ b/compiler/rustc_middle/src/hir/exports.rs
@@ -11,23 +11,18 @@ use std::fmt::Debug;
 
 /// This is the replacement export map. It maps a module to all of the exports
 /// within.
-pub type ExportMap<Id> = FxHashMap<LocalDefId, Vec<Export<Id>>>;
+pub type ExportMap = FxHashMap<LocalDefId, Vec<Export>>;
 
 #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
-pub struct Export<Id> {
+pub struct Export {
     /// The name of the target.
     pub ident: Ident,
     /// The resolution of the target.
-    pub res: Res<Id>,
+    /// Local variables cannot be exported, so this `Res` doesn't need the ID parameter.
+    pub res: Res<!>,
     /// The span of the target.
     pub span: Span,
     /// The visibility of the export.
     /// We include non-`pub` exports for hygienic macros that get used from extern crates.
     pub vis: ty::Visibility,
 }
-
-impl<Id> Export<Id> {
-    pub fn map_id<R>(self, map: impl FnMut(Id) -> R) -> Export<R> {
-        Export { ident: self.ident, res: self.res.map_id(map), span: self.span, vis: self.vis }
-    }
-}
diff --git a/compiler/rustc_middle/src/hir/map/collector.rs b/compiler/rustc_middle/src/hir/map/collector.rs
index 1351b4950f1..082948eba41 100644
--- a/compiler/rustc_middle/src/hir/map/collector.rs
+++ b/compiler/rustc_middle/src/hir/map/collector.rs
@@ -62,13 +62,6 @@ fn hash_body(
     stable_hasher.finish()
 }
 
-/// Represents an entry and its parent `HirId`.
-#[derive(Copy, Clone, Debug)]
-pub struct Entry<'hir> {
-    parent: HirId,
-    node: Node<'hir>,
-}
-
 impl<'a, 'hir> NodeCollector<'a, 'hir> {
     pub(super) fn root(
         sess: &'a Session,
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index e0b6039fe34..10714a4b706 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -969,22 +969,12 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
         .iter_enumerated()
         .filter_map(|(def_id, hod)| {
             let def_path_hash = tcx.untracked_resolutions.definitions.def_path_hash(def_id);
-            let mut hasher = StableHasher::new();
-            hod.as_ref()?.hash_stable(&mut hcx, &mut hasher);
-            AttributeMap { map: &tcx.untracked_crate.attrs, prefix: def_id }
-                .hash_stable(&mut hcx, &mut hasher);
-            Some((def_path_hash, hasher.finish()))
+            let hash = hod.as_ref()?.hash;
+            Some((def_path_hash, hash, def_id))
         })
         .collect();
     hir_body_nodes.sort_unstable_by_key(|bn| bn.0);
 
-    let node_hashes = hir_body_nodes.iter().fold(
-        Fingerprint::ZERO,
-        |combined_fingerprint, &(def_path_hash, fingerprint)| {
-            combined_fingerprint.combine(def_path_hash.0.combine(fingerprint))
-        },
-    );
-
     let upstream_crates = upstream_crates(tcx);
 
     // We hash the final, remapped names of all local source files so we
@@ -1004,7 +994,17 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
     source_file_names.sort_unstable();
 
     let mut stable_hasher = StableHasher::new();
-    node_hashes.hash_stable(&mut hcx, &mut stable_hasher);
+    for (def_path_hash, fingerprint, def_id) in hir_body_nodes.iter() {
+        def_path_hash.0.hash_stable(&mut hcx, &mut stable_hasher);
+        fingerprint.hash_stable(&mut hcx, &mut stable_hasher);
+        AttributeMap { map: &tcx.untracked_crate.attrs, prefix: *def_id }
+            .hash_stable(&mut hcx, &mut stable_hasher);
+        if tcx.sess.opts.debugging_opts.incremental_relative_spans {
+            let span = tcx.untracked_resolutions.definitions.def_span(*def_id);
+            debug_assert_eq!(span.parent(), None);
+            span.hash_stable(&mut hcx, &mut stable_hasher);
+        }
+    }
     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);
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 34aee4f1b3b..c8ea7454f0b 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -153,6 +153,7 @@ pub fn provide(providers: &mut Providers) {
         index.parenting.get(&id).copied().unwrap_or(CRATE_HIR_ID)
     };
     providers.hir_attrs = |tcx, id| AttributeMap { map: &tcx.untracked_crate.attrs, prefix: id };
+    providers.source_span = |tcx, def_id| tcx.resolutions(()).definitions.def_span(def_id);
     providers.def_span = |tcx, def_id| tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP);
     providers.fn_arg_names = |tcx, id| {
         let hir = tcx.hir();
diff --git a/compiler/rustc_middle/src/ich/hcx.rs b/compiler/rustc_middle/src/ich/hcx.rs
index 32ccdafaeb4..c7f58ce5b13 100644
--- a/compiler/rustc_middle/src/ich/hcx.rs
+++ b/compiler/rustc_middle/src/ich/hcx.rs
@@ -12,7 +12,7 @@ use rustc_hir::definitions::{DefPathHash, Definitions};
 use rustc_session::Session;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::Symbol;
-use rustc_span::{BytePos, CachingSourceMapView, SourceFile, SpanData};
+use rustc_span::{BytePos, CachingSourceMapView, SourceFile, Span, SpanData};
 
 use smallvec::SmallVec;
 use std::cmp::Ord;
@@ -28,7 +28,6 @@ fn compute_ignored_attr_names() -> FxHashSet<Symbol> {
 /// things (e.g., each `DefId`/`DefPath` is only hashed once).
 #[derive(Clone)]
 pub struct StableHashingContext<'a> {
-    sess: &'a Session,
     definitions: &'a Definitions,
     cstore: &'a dyn CrateStore,
     pub(super) body_resolver: BodyResolver<'a>,
@@ -78,7 +77,6 @@ impl<'a> StableHashingContext<'a> {
             !always_ignore_spans && !sess.opts.debugging_opts.incremental_ignore_spans;
 
         StableHashingContext {
-            sess,
             body_resolver: BodyResolver(krate),
             definitions,
             cstore,
@@ -229,6 +227,11 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
         self.def_path_hash(def_id)
     }
 
+    #[inline]
+    fn def_span(&self, def_id: LocalDefId) -> Span {
+        self.definitions.def_span(def_id)
+    }
+
     fn span_data_to_lines_and_cols(
         &mut self,
         span: &SpanData,
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 6868be50f1d..94267ec64c7 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -8,7 +8,7 @@
 //! - **MIR.** The "mid-level (M) intermediate representation (IR)" is
 //!   defined in the `mir` module. This module contains only the
 //!   *definition* of the MIR; the passes that transform and operate
-//!   on MIR are found in `rustc_mir` crate.
+//!   on MIR are found in `rustc_const_eval` crate.
 //! - **Types.** The internal representation of types used in rustc is
 //!   defined in the `ty` module. This includes the **type context**
 //!   (or `tcx`), which is the central context during most of
@@ -51,10 +51,11 @@
 #![feature(associated_type_defaults)]
 #![feature(iter_zip)]
 #![feature(thread_local_const_init)]
+#![feature(trusted_step)]
+#![feature(try_blocks)]
 #![feature(try_reserve)]
 #![feature(try_reserve_kind)]
 #![feature(nonzero_ops)]
-#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard
 #![recursion_limit = "512"]
 
 #[macro_use]
diff --git a/compiler/rustc_middle/src/mir/abstract_const.rs b/compiler/rustc_middle/src/mir/abstract_const.rs
deleted file mode 100644
index 1ef10241143..00000000000
--- a/compiler/rustc_middle/src/mir/abstract_const.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-//! A subset of a mir body used for const evaluatability checking.
-use crate::mir::{self, CastKind};
-use crate::ty::{self, Ty};
-
-rustc_index::newtype_index! {
-    /// An index into an `AbstractConst`.
-    pub struct NodeId {
-        derive [HashStable]
-        DEBUG_FORMAT = "n{}",
-    }
-}
-
-/// A node of an `AbstractConst`.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
-pub enum Node<'tcx> {
-    Leaf(&'tcx ty::Const<'tcx>),
-    Binop(mir::BinOp, NodeId, NodeId),
-    UnaryOp(mir::UnOp, NodeId),
-    FunctionCall(NodeId, &'tcx [NodeId]),
-    Cast(CastKind, NodeId, Ty<'tcx>),
-}
-
-#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
-pub enum NotConstEvaluatable {
-    Error(rustc_errors::ErrorReported),
-    MentionsInfer,
-    MentionsParam,
-}
-
-impl From<rustc_errors::ErrorReported> for NotConstEvaluatable {
-    fn from(e: rustc_errors::ErrorReported) -> NotConstEvaluatable {
-        NotConstEvaluatable::Error(e)
-    }
-}
-
-TrivialTypeFoldableAndLiftImpls! {
-    NotConstEvaluatable,
-}
diff --git a/compiler/rustc_mir/src/util/generic_graph.rs b/compiler/rustc_middle/src/mir/generic_graph.rs
index 770b52a4d4b..770b52a4d4b 100644
--- a/compiler/rustc_mir/src/util/generic_graph.rs
+++ b/compiler/rustc_middle/src/mir/generic_graph.rs
diff --git a/compiler/rustc_mir/src/util/generic_graphviz.rs b/compiler/rustc_middle/src/mir/generic_graphviz.rs
index 21c18b28e25..21c18b28e25 100644
--- a/compiler/rustc_mir/src/util/generic_graphviz.rs
+++ b/compiler/rustc_middle/src/mir/generic_graphviz.rs
diff --git a/compiler/rustc_mir/src/util/graphviz.rs b/compiler/rustc_middle/src/mir/graphviz.rs
index 92c7a358c0a..92c7a358c0a 100644
--- a/compiler/rustc_mir/src/util/graphviz.rs
+++ b/compiler/rustc_middle/src/mir/graphviz.rs
diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs
index 3eee45a9230..c9dc5a0f3b5 100644
--- a/compiler/rustc_middle/src/mir/interpret/pointer.rs
+++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs
@@ -3,7 +3,7 @@ use super::{AllocId, InterpResult};
 use rustc_macros::HashStable;
 use rustc_target::abi::{HasDataLayout, Size};
 
-use std::convert::TryFrom;
+use std::convert::{TryFrom, TryInto};
 use std::fmt;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -20,29 +20,27 @@ pub trait PointerArithmetic: HasDataLayout {
 
     #[inline]
     fn machine_usize_max(&self) -> u64 {
-        let max_usize_plus_1 = 1u128 << self.pointer_size().bits();
-        u64::try_from(max_usize_plus_1 - 1).unwrap()
+        self.pointer_size().unsigned_int_max().try_into().unwrap()
     }
 
     #[inline]
     fn machine_isize_min(&self) -> i64 {
-        let max_isize_plus_1 = 1i128 << (self.pointer_size().bits() - 1);
-        i64::try_from(-max_isize_plus_1).unwrap()
+        self.pointer_size().signed_int_min().try_into().unwrap()
     }
 
     #[inline]
     fn machine_isize_max(&self) -> i64 {
-        let max_isize_plus_1 = 1u128 << (self.pointer_size().bits() - 1);
-        i64::try_from(max_isize_plus_1 - 1).unwrap()
+        self.pointer_size().signed_int_max().try_into().unwrap()
     }
 
     #[inline]
     fn machine_usize_to_isize(&self, val: u64) -> i64 {
         let val = val as i64;
-        // Now clamp into the machine_isize range.
+        // Now wrap-around into the machine_isize range.
         if val > self.machine_isize_max() {
             // This can only happen the the ptr size is < 64, so we know max_usize_plus_1 fits into
             // i64.
+            debug_assert!(self.pointer_size().bits() < 64);
             let max_usize_plus_1 = 1u128 << self.pointer_size().bits();
             val - i64::try_from(max_usize_plus_1).unwrap()
         } else {
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 83f6e79d5fc..e8d30034dc4 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -40,13 +40,18 @@ use self::graph_cyclic_cache::GraphIsCyclicCache;
 use self::predecessors::{PredecessorCache, Predecessors};
 pub use self::query::*;
 
-pub mod abstract_const;
 pub mod coverage;
+mod generic_graph;
+pub mod generic_graphviz;
 mod graph_cyclic_cache;
+pub mod graphviz;
 pub mod interpret;
 pub mod mono;
+pub mod patch;
 mod predecessors;
+pub mod pretty;
 mod query;
+pub mod spanview;
 pub mod tcx;
 pub mod terminator;
 pub use terminator::*;
@@ -54,6 +59,12 @@ pub mod traversal;
 mod type_foldable;
 pub mod visit;
 
+pub use self::generic_graph::graphviz_safe_def_name;
+pub use self::graphviz::write_mir_graphviz;
+pub use self::pretty::{
+    create_dump_file, display_allocation, dump_enabled, dump_mir, write_mir_pretty, PassWhere,
+};
+
 /// Types for locals
 pub type LocalDecls<'tcx> = IndexVec<Local, LocalDecl<'tcx>>;
 
@@ -75,6 +86,22 @@ impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> {
     }
 }
 
+/// A streamlined trait that you can implement to create a pass; the
+/// pass will be named after the type, and it will consist of a main
+/// loop that goes over each available MIR and applies `run_pass`.
+pub trait MirPass<'tcx> {
+    fn name(&self) -> Cow<'_, str> {
+        let name = std::any::type_name::<Self>();
+        if let Some(tail) = name.rfind(':') {
+            Cow::from(&name[tail + 1..])
+        } else {
+            Cow::from(name)
+        }
+    }
+
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>);
+}
+
 /// The various "big phases" that MIR goes through.
 ///
 /// These phases all describe dialects of MIR. Since all MIR uses the same datastructures, the
@@ -1142,7 +1169,7 @@ rustc_index::newtype_index! {
     /// [CFG]: https://rustc-dev-guide.rust-lang.org/appendix/background.html#cfg
     /// [data-flow analyses]:
     ///     https://rustc-dev-guide.rust-lang.org/appendix/background.html#what-is-a-dataflow-analysis
-    /// [`CriticalCallEdges`]: ../../rustc_mir/transform/add_call_guards/enum.AddCallGuards.html#variant.CriticalCallEdges
+    /// [`CriticalCallEdges`]: ../../rustc_const_eval/transform/add_call_guards/enum.AddCallGuards.html#variant.CriticalCallEdges
     /// [guide-mir]: https://rustc-dev-guide.rust-lang.org/mir/
     pub struct BasicBlock {
         derive [HashStable]
@@ -1708,7 +1735,7 @@ pub struct Place<'tcx> {
     pub projection: &'tcx List<PlaceElem<'tcx>>,
 }
 
-#[cfg(target_arch = "x86_64")]
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 static_assert_size!(Place<'_>, 16);
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -2034,7 +2061,7 @@ pub enum Operand<'tcx> {
     Constant(Box<Constant<'tcx>>),
 }
 
-#[cfg(target_arch = "x86_64")]
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 static_assert_size!(Operand<'_>, 24);
 
 impl<'tcx> Debug for Operand<'tcx> {
@@ -2172,7 +2199,7 @@ pub enum Rvalue<'tcx> {
     Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>),
 }
 
-#[cfg(target_arch = "x86_64")]
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 static_assert_size!(Rvalue<'_>, 40);
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
@@ -2198,7 +2225,7 @@ pub enum AggregateKind<'tcx> {
     Generator(DefId, SubstsRef<'tcx>, hir::Movability),
 }
 
-#[cfg(target_arch = "x86_64")]
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 static_assert_size!(AggregateKind<'_>, 48);
 
 #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
@@ -2250,6 +2277,8 @@ impl BinOp {
 pub enum NullOp {
     /// Returns the size of a value of that type
     SizeOf,
+    /// Returns the minimum alignment of a type
+    AlignOf,
     /// Creates a new uninitialized box for a value of that type
     Box,
 }
diff --git a/compiler/rustc_mir/src/util/patch.rs b/compiler/rustc_middle/src/mir/patch.rs
index 1f571a36441..1f571a36441 100644
--- a/compiler/rustc_mir/src/util/patch.rs
+++ b/compiler/rustc_middle/src/mir/patch.rs
diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 92591db668c..db98cb76343 100644
--- a/compiler/rustc_mir/src/util/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -7,7 +7,6 @@ use std::path::{Path, PathBuf};
 
 use super::graphviz::write_mir_fn_graphviz;
 use super::spanview::write_mir_fn_spanview;
-use crate::transform::MirSource;
 use either::Either;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::DefId;
@@ -16,6 +15,7 @@ use rustc_middle::mir::interpret::{
     read_target_uint, AllocId, Allocation, ConstValue, GlobalAlloc, Pointer, Provenance,
 };
 use rustc_middle::mir::visit::Visitor;
+use rustc_middle::mir::MirSource;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, TyCtxt, TyS, TypeFoldable, TypeVisitor};
 use rustc_target::abi::Size;
@@ -250,7 +250,7 @@ fn create_dump_file_with_basename(
 /// bit of MIR-related data. Used by `mir-dump`, but also by other
 /// bits of code (e.g., NLL inference) that dump graphviz data or
 /// other things, and hence takes the extension as an argument.
-pub(crate) fn create_dump_file(
+pub fn create_dump_file(
     tcx: TyCtxt<'_>,
     extension: &str,
     pass_num: Option<&dyn Display>,
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 4fb737f463a..567f65e83d9 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -1,6 +1,6 @@
 //! Values computed by queries that use MIR.
 
-use crate::mir::{abstract_const, Body, Promoted};
+use crate::mir::{Body, Promoted};
 use crate::ty::{self, Ty, TyCtxt};
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::vec_map::VecMap;
@@ -219,7 +219,7 @@ pub struct BorrowCheckResult<'tcx> {
 /// The result of the `mir_const_qualif` query.
 ///
 /// Each field (except `error_occured`) corresponds to an implementer of the `Qualif` trait in
-/// `rustc_mir/src/transform/check_consts/qualifs.rs`. See that file for more information on each
+/// `rustc_const_eval/src/transform/check_consts/qualifs.rs`. See that file for more information on each
 /// `Qualif`.
 #[derive(Clone, Copy, Debug, Default, TyEncodable, TyDecodable, HashStable)]
 pub struct ConstQualifs {
@@ -313,7 +313,7 @@ pub struct ClosureOutlivesRequirement<'tcx> {
 /// are interesting (for error reporting). Order of variants indicates sort
 /// order of the category, thereby influencing diagnostic output.
 ///
-/// See also `rustc_mir::borrow_check::constraints`.
+/// See also `rustc_const_eval::borrow_check::constraints`.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
 #[derive(TyEncodable, TyDecodable, HashStable)]
 pub enum ConstraintCategory {
@@ -431,16 +431,4 @@ impl<'tcx> TyCtxt<'tcx> {
             self.mir_for_ctfe(def.did)
         }
     }
-
-    #[inline]
-    pub fn mir_abstract_const_opt_const_arg(
-        self,
-        def: ty::WithOptConstParam<DefId>,
-    ) -> Result<Option<&'tcx [abstract_const::Node<'tcx>]>, ErrorReported> {
-        if let Some((did, param_did)) = def.as_const_arg() {
-            self.mir_abstract_const_of_const_arg((did, param_did))
-        } else {
-            self.mir_abstract_const(def.did)
-        }
-    }
 }
diff --git a/compiler/rustc_mir/src/util/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs
index 42683dac426..42683dac426 100644
--- a/compiler/rustc_mir/src/util/spanview.rs
+++ b/compiler/rustc_middle/src/mir/spanview.rs
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 74d303cee5d..b48e8a868ef 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -196,7 +196,7 @@ impl<'tcx> Rvalue<'tcx> {
             Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx),
             Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx),
             Rvalue::NullaryOp(NullOp::Box, t) => tcx.mk_box(t),
-            Rvalue::NullaryOp(NullOp::SizeOf, _) => tcx.types.usize,
+            Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => tcx.types.usize,
             Rvalue::Aggregate(ref ak, ref ops) => match **ak {
                 AggregateKind::Array(ty) => tcx.mk_array(ty, ops.len() as u64),
                 AggregateKind::Tuple => tcx.mk_tup(ops.iter().map(|op| op.ty(local_decls, tcx))),
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index c93996162e3..4296acce1ff 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -20,6 +20,14 @@ rustc_queries! {
         desc { "get the resolver outputs" }
     }
 
+    /// Return the span for a definition.
+    /// Contrary to `def_span` below, this query returns the full absolute span of the definition.
+    /// This span is meant for dep-tracking rather than diagnostics. It should not be used outside
+    /// of rustc_middle::hir::source_map.
+    query source_span(key: LocalDefId) -> Span {
+        desc { "get the source span" }
+    }
+
     /// Represents crate as a whole (as distinct from the top-level crate module).
     /// If you call `hir_crate` (e.g., indirectly by calling `tcx.hir().krate()`),
     /// we will have to assume that any change means that you need to be recompiled.
@@ -295,17 +303,17 @@ rustc_queries! {
     }
 
     /// Try to build an abstract representation of the given constant.
-    query mir_abstract_const(
+    query thir_abstract_const(
         key: DefId
-    ) -> Result<Option<&'tcx [mir::abstract_const::Node<'tcx>]>, ErrorReported> {
+    ) -> Result<Option<&'tcx [thir::abstract_const::Node<'tcx>]>, ErrorReported> {
         desc {
             |tcx| "building an abstract representation for {}", tcx.def_path_str(key),
         }
     }
     /// Try to build an abstract representation of the given constant.
-    query mir_abstract_const_of_const_arg(
+    query thir_abstract_const_of_const_arg(
         key: (LocalDefId, DefId)
-    ) -> Result<Option<&'tcx [mir::abstract_const::Node<'tcx>]>, ErrorReported> {
+    ) -> Result<Option<&'tcx [thir::abstract_const::Node<'tcx>]>, ErrorReported> {
         desc {
             |tcx|
             "building an abstract representation for the const argument {}",
@@ -544,14 +552,6 @@ rustc_queries! {
         desc { |tcx| "checking if item is const fn: `{}`", tcx.def_path_str(key) }
     }
 
-    /// Returns `true` if this is a const `impl`. **Do not call this function manually.**
-    ///
-    /// This query caches the base data for the `is_const_impl` helper function, which also
-    /// takes into account stability attributes (e.g., `#[rustc_const_unstable]`).
-    query is_const_impl_raw(key: DefId) -> bool {
-        desc { |tcx| "checking if item is const impl: `{}`", tcx.def_path_str(key) }
-    }
-
     query asyncness(key: DefId) -> hir::IsAsync {
         desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) }
     }
@@ -1159,6 +1159,10 @@ rustc_queries! {
         fatal_cycle
         desc { "query a crate's configured panic strategy" }
     }
+    query panic_in_drop_strategy(_: CrateNum) -> PanicStrategy {
+        fatal_cycle
+        desc { "query a crate's configured panic-in-drop strategy" }
+    }
     query is_no_builtins(_: CrateNum) -> bool {
         fatal_cycle
         desc { "test whether a crate has `#![no_builtins]`" }
@@ -1181,7 +1185,7 @@ rustc_queries! {
         desc { "traits in scope at a block" }
     }
 
-    query module_exports(def_id: LocalDefId) -> Option<&'tcx [Export<LocalDefId>]> {
+    query module_exports(def_id: LocalDefId) -> Option<&'tcx [Export]> {
         desc { |tcx| "looking up items exported by `{}`", tcx.def_path_str(def_id.to_def_id()) }
     }
 
@@ -1393,7 +1397,7 @@ rustc_queries! {
         eval_always
         desc { "fetching what a crate is named" }
     }
-    query item_children(def_id: DefId) -> &'tcx [Export<hir::HirId>] {
+    query item_children(def_id: DefId) -> &'tcx [Export] {
         desc { |tcx| "collecting child items of `{}`", tcx.def_path_str(def_id) }
     }
     query extern_mod_stmt_cnum(def_id: LocalDefId) -> Option<CrateNum> {
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 91a64e163e7..8d6fd1e729d 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -33,6 +33,9 @@ use rustc_target::asm::InlineAsmRegOrRegClass;
 use std::fmt;
 use std::ops::Index;
 
+pub mod abstract_const;
+pub mod visit;
+
 newtype_index! {
     /// An index to an [`Arm`] stored in [`Thir::arms`]
     #[derive(HashStable)]
diff --git a/compiler/rustc_middle/src/thir/abstract_const.rs b/compiler/rustc_middle/src/thir/abstract_const.rs
new file mode 100644
index 00000000000..f80beadd6e5
--- /dev/null
+++ b/compiler/rustc_middle/src/thir/abstract_const.rs
@@ -0,0 +1,61 @@
+//! A subset of a mir body used for const evaluatability checking.
+use crate::mir;
+use crate::ty::{self, Ty, TyCtxt};
+use rustc_errors::ErrorReported;
+
+rustc_index::newtype_index! {
+    /// An index into an `AbstractConst`.
+    pub struct NodeId {
+        derive [HashStable]
+        DEBUG_FORMAT = "n{}",
+    }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+pub enum CastKind {
+    /// thir::ExprKind::As
+    As,
+    /// thir::ExprKind::Use
+    Use,
+}
+
+/// A node of an `AbstractConst`.
+#[derive(Debug, Clone, Copy, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+pub enum Node<'tcx> {
+    Leaf(&'tcx ty::Const<'tcx>),
+    Binop(mir::BinOp, NodeId, NodeId),
+    UnaryOp(mir::UnOp, NodeId),
+    FunctionCall(NodeId, &'tcx [NodeId]),
+    Cast(CastKind, NodeId, Ty<'tcx>),
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
+pub enum NotConstEvaluatable {
+    Error(ErrorReported),
+    MentionsInfer,
+    MentionsParam,
+}
+
+impl From<ErrorReported> for NotConstEvaluatable {
+    fn from(e: ErrorReported) -> NotConstEvaluatable {
+        NotConstEvaluatable::Error(e)
+    }
+}
+
+TrivialTypeFoldableAndLiftImpls! {
+    NotConstEvaluatable,
+}
+
+impl<'tcx> TyCtxt<'tcx> {
+    #[inline]
+    pub fn thir_abstract_const_opt_const_arg(
+        self,
+        def: ty::WithOptConstParam<rustc_hir::def_id::DefId>,
+    ) -> Result<Option<&'tcx [Node<'tcx>]>, ErrorReported> {
+        if let Some((did, param_did)) = def.as_const_arg() {
+            self.thir_abstract_const_of_const_arg((did, param_did))
+        } else {
+            self.thir_abstract_const(def.did)
+        }
+    }
+}
diff --git a/compiler/rustc_mir_build/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs
index 51c371b8720..7fc15e02fcd 100644
--- a/compiler/rustc_mir_build/src/thir/visit.rs
+++ b/compiler/rustc_middle/src/thir/visit.rs
@@ -1,4 +1,6 @@
-use rustc_middle::thir::{self, *};
+use super::{
+    Arm, Block, Expr, ExprKind, Guard, InlineAsmOperand, Pat, PatKind, Stmt, StmtKind, Thir,
+};
 use rustc_middle::ty::Const;
 
 pub trait Visitor<'a, 'tcx: 'a>: Sized {
@@ -101,7 +103,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
                 visitor.visit_expr(&visitor.thir()[field]);
             }
         }
-        Adt(box thir::Adt {
+        Adt(box crate::thir::Adt {
             ref fields,
             ref base,
             adt_def: _,
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 74edb17fe32..b4ae56adf32 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -9,7 +9,7 @@ pub mod specialization_graph;
 mod structural_impls;
 
 use crate::infer::canonical::Canonical;
-use crate::mir::abstract_const::NotConstEvaluatable;
+use crate::thir::abstract_const::NotConstEvaluatable;
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, AdtKind, Ty, TyCtxt};
 
@@ -253,6 +253,15 @@ pub enum ObligationCauseCode<'tcx> {
 
     DerivedObligation(DerivedObligationCause<'tcx>),
 
+    FunctionArgumentObligation {
+        /// The node of the relevant argument in the function call.
+        arg_hir_id: hir::HirId,
+        /// The node of the function call.
+        call_hir_id: hir::HirId,
+        /// The obligation introduced by this argument.
+        parent_code: Lrc<ObligationCauseCode<'tcx>>,
+    },
+
     /// Error derived when matching traits/impls; see ObligationCause for more details
     CompareImplConstObligation,
 
@@ -368,11 +377,12 @@ impl ObligationCauseCode<'_> {
     // Return the base obligation, ignoring derived obligations.
     pub fn peel_derives(&self) -> &Self {
         let mut base_cause = self;
-        while let BuiltinDerivedObligation(cause)
-        | ImplDerivedObligation(cause)
-        | DerivedObligation(cause) = base_cause
+        while let BuiltinDerivedObligation(DerivedObligationCause { parent_code, .. })
+        | ImplDerivedObligation(DerivedObligationCause { parent_code, .. })
+        | DerivedObligation(DerivedObligationCause { parent_code, .. })
+        | FunctionArgumentObligation { parent_code, .. } = base_cause
         {
-            base_cause = &cause.parent_code;
+            base_cause = &parent_code;
         }
         base_cause
     }
@@ -529,6 +539,9 @@ pub enum ImplSource<'tcx, N> {
 
     /// ImplSource for a trait alias.
     TraitAlias(ImplSourceTraitAliasData<'tcx, N>),
+
+    /// ImplSource for a `const Drop` implementation.
+    ConstDrop(ImplSourceConstDropData),
 }
 
 impl<'tcx, N> ImplSource<'tcx, N> {
@@ -543,7 +556,8 @@ impl<'tcx, N> ImplSource<'tcx, N> {
             ImplSource::Object(d) => d.nested,
             ImplSource::FnPointer(d) => d.nested,
             ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
-            | ImplSource::Pointee(ImplSourcePointeeData) => Vec::new(),
+            | ImplSource::Pointee(ImplSourcePointeeData)
+            | ImplSource::ConstDrop(ImplSourceConstDropData) => Vec::new(),
             ImplSource::TraitAlias(d) => d.nested,
             ImplSource::TraitUpcasting(d) => d.nested,
         }
@@ -560,7 +574,8 @@ impl<'tcx, N> ImplSource<'tcx, N> {
             ImplSource::Object(d) => &d.nested[..],
             ImplSource::FnPointer(d) => &d.nested[..],
             ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
-            | ImplSource::Pointee(ImplSourcePointeeData) => &[],
+            | ImplSource::Pointee(ImplSourcePointeeData)
+            | ImplSource::ConstDrop(ImplSourceConstDropData) => &[],
             ImplSource::TraitAlias(d) => &d.nested[..],
             ImplSource::TraitUpcasting(d) => &d.nested[..],
         }
@@ -621,6 +636,9 @@ impl<'tcx, N> ImplSource<'tcx, N> {
                     nested: d.nested.into_iter().map(f).collect(),
                 })
             }
+            ImplSource::ConstDrop(ImplSourceConstDropData) => {
+                ImplSource::ConstDrop(ImplSourceConstDropData)
+            }
         }
     }
 }
@@ -712,6 +730,9 @@ pub struct ImplSourceDiscriminantKindData;
 #[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
 pub struct ImplSourcePointeeData;
 
+#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
+pub struct ImplSourceConstDropData;
+
 #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
 pub struct ImplSourceTraitAliasData<'tcx, N> {
     pub alias_def_id: DefId,
@@ -719,7 +740,7 @@ pub struct ImplSourceTraitAliasData<'tcx, N> {
     pub nested: Vec<N>,
 }
 
-#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
 pub enum ObjectSafetyViolation {
     /// `Self: Sized` declared on the trait.
     SizedSelf(SmallVec<[Span; 1]>),
@@ -868,7 +889,7 @@ impl ObjectSafetyViolation {
 }
 
 /// Reasons a method might not be object-safe.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)]
 pub enum MethodViolationCode {
     /// e.g., `fn foo()`
     StaticMethod(Option<(&'static str, Span)>, Span, bool /* has args */),
diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs
index 62996bf4cbe..3c0fedb3608 100644
--- a/compiler/rustc_middle/src/traits/select.rs
+++ b/compiler/rustc_middle/src/traits/select.rs
@@ -143,6 +143,9 @@ pub enum SelectionCandidate<'tcx> {
     BuiltinObjectCandidate,
 
     BuiltinUnsizeCandidate,
+
+    /// Implementation of `const Drop`.
+    ConstDropCandidate,
 }
 
 /// The result of trait evaluation. The order is important
diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs
index aa16e14fedc..6032004e607 100644
--- a/compiler/rustc_middle/src/traits/structural_impls.rs
+++ b/compiler/rustc_middle/src/traits/structural_impls.rs
@@ -32,6 +32,8 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> {
             super::ImplSource::TraitAlias(ref d) => write!(f, "{:?}", d),
 
             super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d),
+
+            super::ImplSource::ConstDrop(ref d) => write!(f, "{:?}", d),
         }
     }
 }
@@ -125,4 +127,5 @@ TrivialTypeFoldableAndLiftImpls! {
     super::IfExpressionCause,
     super::ImplSourceDiscriminantKindData,
     super::ImplSourcePointeeData,
+    super::ImplSourceConstDropData,
 }
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 27927bcca72..c32f0ea9ca5 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -7,6 +7,7 @@ use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_errors::ErrorReported;
+use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_index::vec::{Idx, IndexVec};
@@ -288,6 +289,10 @@ impl<'tcx> AdtDef {
         self.destructor(tcx).is_some()
     }
 
+    pub fn has_non_const_dtor(&self, tcx: TyCtxt<'tcx>) -> bool {
+        matches!(self.destructor(tcx), Some(Destructor { constness: hir::Constness::NotConst, .. }))
+    }
+
     /// Asserts this is a struct or union and returns its unique variant.
     pub fn non_enum_variant(&self) -> &VariantDef {
         assert!(self.is_struct() || self.is_union());
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 4edb6a327b0..8b70692960d 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -12,6 +12,7 @@ use crate::mir::{
     self,
     interpret::{AllocId, Allocation},
 };
+use crate::thir;
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, List, Ty, TyCtxt};
 use rustc_data_structures::fx::FxHashMap;
@@ -362,7 +363,7 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [(ty::Predicate<'tcx>,
     }
 }
 
-impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::Node<'tcx>] {
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [thir::abstract_const::Node<'tcx>] {
     fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
         Ok(decoder.tcx().arena.alloc_from_iter(
             (0..decoder.read_usize()?)
@@ -372,7 +373,7 @@ impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::N
     }
 }
 
-impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [mir::abstract_const::NodeId] {
+impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [thir::abstract_const::NodeId] {
     fn decode(decoder: &mut D) -> Result<&'tcx Self, D::Error> {
         Ok(decoder.tcx().arena.alloc_from_iter(
             (0..decoder.read_usize()?)
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 796ca650bdd..08b4d3aecda 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -964,7 +964,7 @@ fn foo(&self) -> Self::T { String::new() }
         {
             let (span, sugg) = if has_params {
                 let pos = span.hi() - BytePos(1);
-                let span = Span::new(pos, pos, span.ctxt());
+                let span = Span::new(pos, pos, span.ctxt(), span.parent());
                 (span, format!(", {} = {}", assoc.ident, ty))
             } else {
                 let item_args = self.format_generic_args(assoc_substs);
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index f7ab9dd82ac..1bea1cbc3b9 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -290,9 +290,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
 
         // HACK(nox): We iter on `b` and then `a` because `max_by_key`
         // returns the last maximum.
-        let largest_niche = Niche::from_scalar(dl, b_offset, b.clone())
+        let largest_niche = Niche::from_scalar(dl, b_offset, b)
             .into_iter()
-            .chain(Niche::from_scalar(dl, Size::ZERO, a.clone()))
+            .chain(Niche::from_scalar(dl, Size::ZERO, a))
             .max_by_key(|niche| niche.available(dl));
 
         Layout {
@@ -401,7 +401,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
             offsets[i as usize] = offset;
 
             if !repr.hide_niche() {
-                if let Some(mut niche) = field.largest_niche.clone() {
+                if let Some(mut niche) = field.largest_niche {
                     let available = niche.available(dl);
                     if available > largest_niche_available {
                         largest_niche_available = available;
@@ -449,12 +449,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                             // For plain scalars, or vectors of them, we can't unpack
                             // newtypes for `#[repr(C)]`, as that affects C ABIs.
                             Abi::Scalar(_) | Abi::Vector { .. } if optimize => {
-                                abi = field.abi.clone();
+                                abi = field.abi;
                             }
                             // But scalar pairs are Rust-specific and get
                             // treated as aggregates by C ABIs anyway.
                             Abi::ScalarPair(..) => {
-                                abi = field.abi.clone();
+                                abi = field.abi;
                             }
                             _ => {}
                         }
@@ -463,14 +463,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
 
                 // Two non-ZST fields, and they're both scalars.
                 (
-                    Some((i, &TyAndLayout { layout: &Layout { abi: Abi::Scalar(ref a), .. }, .. })),
-                    Some((j, &TyAndLayout { layout: &Layout { abi: Abi::Scalar(ref b), .. }, .. })),
+                    Some((i, &TyAndLayout { layout: &Layout { abi: Abi::Scalar(a), .. }, .. })),
+                    Some((j, &TyAndLayout { layout: &Layout { abi: Abi::Scalar(b), .. }, .. })),
                     None,
                 ) => {
                     // Order by the memory placement, not source order.
                     let ((i, a), (j, b)) =
                         if offsets[i] < offsets[j] { ((i, a), (j, b)) } else { ((j, b), (i, a)) };
-                    let pair = self.scalar_pair(a.clone(), b.clone());
+                    let pair = self.scalar_pair(a, b);
                     let pair_offsets = match pair.fields {
                         FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
                             assert_eq!(memory_index, &[0, 1]);
@@ -512,9 +512,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
         let param_env = self.param_env;
         let dl = self.data_layout();
         let scalar_unit = |value: Primitive| {
-            let bits = value.size(dl).bits();
-            assert!(bits <= 128);
-            Scalar { value, valid_range: WrappingRange { start: 0, end: (!0 >> (128 - bits)) } }
+            let size = value.size(dl);
+            assert!(size.bits() <= 128);
+            Scalar { value, valid_range: WrappingRange { start: 0, end: size.unsigned_int_max() } }
         };
         let scalar = |value: Primitive| tcx.intern_layout(Layout::scalar(self, scalar_unit(value)));
 
@@ -609,7 +609,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                         Abi::Aggregate { sized: true }
                     };
 
-                let largest_niche = if count != 0 { element.largest_niche.clone() } else { None };
+                let largest_niche = if count != 0 { element.largest_niche } else { None };
 
                 tcx.intern_layout(Layout {
                     variants: Variants::Single { index: VariantIdx::new(0) },
@@ -768,8 +768,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
 
                 // Compute the ABI of the element type:
                 let e_ly = self.layout_of(e_ty)?;
-                let e_abi = if let Abi::Scalar(ref scalar) = e_ly.abi {
-                    scalar.clone()
+                let e_abi = if let Abi::Scalar(scalar) = e_ly.abi {
+                    scalar
                 } else {
                     // This error isn't caught in typeck, e.g., if
                     // the element type of the vector is generic.
@@ -796,7 +796,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                     variants: Variants::Single { index: VariantIdx::new(0) },
                     fields,
                     abi: Abi::Vector { element: e_abi, count: e_len },
-                    largest_niche: e_ly.largest_niche.clone(),
+                    largest_niche: e_ly.largest_niche,
                     size,
                     align,
                 })
@@ -843,13 +843,13 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                         // If all non-ZST fields have the same ABI, forward this ABI
                         if optimize && !field.is_zst() {
                             // Normalize scalar_unit to the maximal valid range
-                            let field_abi = match &field.abi {
+                            let field_abi = match field.abi {
                                 Abi::Scalar(x) => Abi::Scalar(scalar_unit(x.value)),
                                 Abi::ScalarPair(x, y) => {
                                     Abi::ScalarPair(scalar_unit(x.value), scalar_unit(y.value))
                                 }
                                 Abi::Vector { element: x, count } => {
-                                    Abi::Vector { element: scalar_unit(x.value), count: *count }
+                                    Abi::Vector { element: scalar_unit(x.value), count }
                                 }
                                 Abi::Uninhabited | Abi::Aggregate { .. } => {
                                     Abi::Aggregate { sized: true }
@@ -970,7 +970,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                                 Niche::from_scalar(dl, Size::ZERO, scalar.clone())
                             };
                             if let Some(niche) = niche {
-                                match &st.largest_niche {
+                                match st.largest_niche {
                                     Some(largest_niche) => {
                                         // Replace the existing niche even if they're equal,
                                         // because this one is at a lower offset.
@@ -1045,7 +1045,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                         let niche_candidate = variants[i]
                             .iter()
                             .enumerate()
-                            .filter_map(|(j, &field)| Some((j, field.largest_niche.as_ref()?)))
+                            .filter_map(|(j, field)| Some((j, field.largest_niche?)))
                             .max_by_key(|(_, niche)| niche.available(dl));
 
                         if let Some((field_index, niche, (niche_start, niche_scalar))) =
@@ -1078,31 +1078,24 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                                 Abi::Uninhabited
                             } else {
                                 match st[i].abi {
-                                    Abi::Scalar(_) => Abi::Scalar(niche_scalar.clone()),
-                                    Abi::ScalarPair(ref first, ref second) => {
+                                    Abi::Scalar(_) => Abi::Scalar(niche_scalar),
+                                    Abi::ScalarPair(first, second) => {
                                         // We need to use scalar_unit to reset the
                                         // valid range to the maximal one for that
                                         // primitive, because only the niche is
                                         // guaranteed to be initialised, not the
                                         // other primitive.
                                         if offset.bytes() == 0 {
-                                            Abi::ScalarPair(
-                                                niche_scalar.clone(),
-                                                scalar_unit(second.value),
-                                            )
+                                            Abi::ScalarPair(niche_scalar, scalar_unit(second.value))
                                         } else {
-                                            Abi::ScalarPair(
-                                                scalar_unit(first.value),
-                                                niche_scalar.clone(),
-                                            )
+                                            Abi::ScalarPair(scalar_unit(first.value), niche_scalar)
                                         }
                                     }
                                     _ => Abi::Aggregate { sized: true },
                                 }
                             };
 
-                            let largest_niche =
-                                Niche::from_scalar(dl, offset, niche_scalar.clone());
+                            let largest_niche = Niche::from_scalar(dl, offset, niche_scalar);
 
                             niche_filling_layout = Some(Layout {
                                 variants: Variants::Multiple {
@@ -1273,7 +1266,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                     }
                 }
 
-                let tag_mask = !0u128 >> (128 - ity.size().bits());
+                let tag_mask = ity.size().unsigned_int_max();
                 let tag = Scalar {
                     value: Int(ity, signed),
                     valid_range: WrappingRange {
@@ -1283,7 +1276,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                 };
                 let mut abi = Abi::Aggregate { sized: true };
                 if tag.value.size(dl) == size {
-                    abi = Abi::Scalar(tag.clone());
+                    abi = Abi::Scalar(tag);
                 } else {
                     // Try to use a ScalarPair for all tagged enums.
                     let mut common_prim = None;
@@ -1303,7 +1296,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                             }
                         };
                         let prim = match field.abi {
-                            Abi::Scalar(ref scalar) => scalar.value,
+                            Abi::Scalar(scalar) => scalar.value,
                             _ => {
                                 common_prim = None;
                                 break;
@@ -1323,7 +1316,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                         }
                     }
                     if let Some((prim, offset)) = common_prim {
-                        let pair = self.scalar_pair(tag.clone(), scalar_unit(prim));
+                        let pair = self.scalar_pair(tag, scalar_unit(prim));
                         let pair_offsets = match pair.fields {
                             FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
                                 assert_eq!(memory_index, &[0, 1]);
@@ -1347,7 +1340,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                     abi = Abi::Uninhabited;
                 }
 
-                let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag.clone());
+                let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag);
 
                 let tagged_layout = Layout {
                     variants: Variants::Multiple {
@@ -1372,8 +1365,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                         // pick the layout with the larger niche; otherwise,
                         // pick tagged as it has simpler codegen.
                         cmp::min_by_key(tagged_layout, niche_filling_layout, |layout| {
-                            let niche_size =
-                                layout.largest_niche.as_ref().map_or(0, |n| n.available(dl));
+                            let niche_size = layout.largest_niche.map_or(0, |n| n.available(dl));
                             (layout.size, cmp::Reverse(niche_size))
                         })
                     }
@@ -1560,7 +1552,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
             value: Primitive::Int(discr_int, false),
             valid_range: WrappingRange { start: 0, end: max_discr },
         };
-        let tag_layout = self.tcx.intern_layout(Layout::scalar(self, tag.clone()));
+        let tag_layout = self.tcx.intern_layout(Layout::scalar(self, tag));
         let tag_layout = TyAndLayout { ty: discr_int_ty, layout: tag_layout };
 
         let promoted_layouts = ineligible_locals
@@ -1832,7 +1824,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                 }
             }
 
-            Variants::Multiple { ref tag, ref tag_encoding, .. } => {
+            Variants::Multiple { tag, ref tag_encoding, .. } => {
                 debug!(
                     "print-type-size `{:#?}` adt general variants def {}",
                     layout.ty,
@@ -2240,7 +2232,7 @@ where
             i: usize,
         ) -> TyMaybeWithLayout<'tcx> {
             let tcx = cx.tcx();
-            let tag_layout = |tag: &Scalar| -> TyAndLayout<'tcx> {
+            let tag_layout = |tag: Scalar| -> TyAndLayout<'tcx> {
                 let layout = Layout::scalar(cx, tag.clone());
                 TyAndLayout { layout: tcx.intern_layout(layout), ty: tag.value.to_ty(tcx) }
             };
@@ -2329,7 +2321,7 @@ where
                             .nth(i)
                             .unwrap(),
                     ),
-                    Variants::Multiple { ref tag, tag_field, .. } => {
+                    Variants::Multiple { tag, tag_field, .. } => {
                         if i == tag_field {
                             return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
                         }
@@ -2347,7 +2339,7 @@ where
                         }
 
                         // Discriminant field for enums (where applicable).
-                        Variants::Multiple { ref tag, .. } => {
+                        Variants::Multiple { tag, .. } => {
                             assert_eq!(i, 0);
                             return TyMaybeWithLayout::TyAndLayout(tag_layout(tag));
                         }
@@ -2906,7 +2898,7 @@ where
 
         // Handle safe Rust thin and fat pointers.
         let adjust_for_rust_scalar = |attrs: &mut ArgAttributes,
-                                      scalar: &Scalar,
+                                      scalar: Scalar,
                                       layout: TyAndLayout<'tcx>,
                                       offset: Size,
                                       is_return: bool| {
@@ -2921,7 +2913,7 @@ where
                 return;
             }
 
-            if !scalar.valid_range.contains_zero() {
+            if !scalar.valid_range.contains(0) {
                 attrs.set(ArgAttribute::NonNull);
             }
 
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index fddfd6e435c..777c6035be8 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -127,7 +127,7 @@ pub struct ResolverOutputs {
     pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
     pub maybe_unused_trait_imports: FxHashSet<LocalDefId>,
     pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
-    pub export_map: ExportMap<LocalDefId>,
+    pub export_map: ExportMap,
     pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
     /// Extern prelude entries. The value is `true` if the entry was introduced
     /// via `extern crate` item and not `--extern` option or compiler built-in.
@@ -1377,6 +1377,8 @@ where
 pub struct Destructor {
     /// The `DefId` of the destructor method
     pub did: DefId,
+    /// The constness of the destructor method
+    pub constness: hir::Constness,
 }
 
 bitflags! {
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 65dd61b6329..0fbaf81c21e 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -643,7 +643,7 @@ impl<'tcx> GeneratorSubsts<'tcx> {
     }
 
     /// This returns the types of the MIR locals which had to be stored across suspension points.
-    /// It is calculated in rustc_mir::transform::generator::StateTransform.
+    /// It is calculated in rustc_const_eval::transform::generator::StateTransform.
     /// All the types here must be in the tuple in GeneratorInterior.
     ///
     /// The locals are grouped by their variant number. Note that some locals may
@@ -1268,7 +1268,7 @@ pub type Region<'tcx> = &'tcx RegionKind;
 /// Representation of regions. Note that the NLL checker uses a distinct
 /// representation of regions. For this reason, it internally replaces all the
 /// regions with inference variables -- the index of the variable is then used
-/// to index into internal NLL data structures. See `rustc_mir::borrow_check`
+/// to index into internal NLL data structures. See `rustc_const_eval::borrow_check`
 /// module for more information.
 ///
 /// ## The Region lattice within a given function
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 1b8e94260b9..2ec06d472fe 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -45,18 +45,6 @@ impl<'tcx> fmt::Display for Discr<'tcx> {
     }
 }
 
-fn signed_min(size: Size) -> i128 {
-    size.sign_extend(1_u128 << (size.bits() - 1)) as i128
-}
-
-fn signed_max(size: Size) -> i128 {
-    i128::MAX >> (128 - size.bits())
-}
-
-fn unsigned_max(size: Size) -> u128 {
-    u128::MAX >> (128 - size.bits())
-}
-
 fn int_size_and_signed<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (Size, bool) {
     let (int, signed) = match *ty.kind() {
         Int(ity) => (Integer::from_int_ty(&tcx, ity), true),
@@ -74,8 +62,8 @@ impl<'tcx> Discr<'tcx> {
     pub fn checked_add(self, tcx: TyCtxt<'tcx>, n: u128) -> (Self, bool) {
         let (size, signed) = int_size_and_signed(tcx, self.ty);
         let (val, oflo) = if signed {
-            let min = signed_min(size);
-            let max = signed_max(size);
+            let min = size.signed_int_min();
+            let max = size.signed_int_max();
             let val = size.sign_extend(self.val) as i128;
             assert!(n < (i128::MAX as u128));
             let n = n as i128;
@@ -86,7 +74,7 @@ impl<'tcx> Discr<'tcx> {
             let val = size.truncate(val);
             (val, oflo)
         } else {
-            let max = unsigned_max(size);
+            let max = size.unsigned_int_max();
             let val = self.val;
             let oflo = val > max - n;
             let val = if oflo { n - (max - val) - 1 } else { val + n };
@@ -336,16 +324,16 @@ impl<'tcx> TyCtxt<'tcx> {
         self.ensure().coherent_trait(drop_trait);
 
         let ty = self.type_of(adt_did);
-        let dtor_did = self.find_map_relevant_impl(drop_trait, ty, |impl_did| {
+        let (did, constness) = self.find_map_relevant_impl(drop_trait, ty, |impl_did| {
             if let Some(item) = self.associated_items(impl_did).in_definition_order().next() {
                 if validate(self, impl_did).is_ok() {
-                    return Some(item.def_id);
+                    return Some((item.def_id, self.impl_constness(impl_did)));
                 }
             }
             None
-        });
+        })?;
 
-        Some(ty::Destructor { did: dtor_did? })
+        Some(ty::Destructor { did, constness })
     }
 
     /// Returns the set of types that are required to be alive in
@@ -621,7 +609,8 @@ impl<'tcx> ty::TyS<'tcx> {
         let val = match self.kind() {
             ty::Int(_) | ty::Uint(_) => {
                 let (size, signed) = int_size_and_signed(tcx, self);
-                let val = if signed { signed_max(size) as u128 } else { unsigned_max(size) };
+                let val =
+                    if signed { size.signed_int_max() as u128 } else { size.unsigned_int_max() };
                 Some(val)
             }
             ty::Char => Some(std::char::MAX as u128),
@@ -640,7 +629,7 @@ impl<'tcx> ty::TyS<'tcx> {
         let val = match self.kind() {
             ty::Int(_) | ty::Uint(_) => {
                 let (size, signed) = int_size_and_signed(tcx, self);
-                let val = if signed { size.truncate(signed_min(size) as u128) } else { 0 };
+                let val = if signed { size.truncate(size.signed_int_min() as u128) } else { 0 };
                 Some(val)
             }
             ty::Char => Some(0),
diff --git a/compiler/rustc_mir/src/dataflow/mod.rs b/compiler/rustc_mir/src/dataflow/mod.rs
deleted file mode 100644
index 8a426cc1015..00000000000
--- a/compiler/rustc_mir/src/dataflow/mod.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-use rustc_ast::{self as ast, MetaItem};
-use rustc_middle::ty;
-use rustc_session::Session;
-use rustc_span::symbol::{sym, Symbol};
-
-pub(crate) use self::drop_flag_effects::*;
-pub use self::framework::{
-    fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, BorrowckFlowState,
-    BorrowckResults, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results,
-    ResultsCursor, ResultsRefCursor, ResultsVisitor, SwitchIntEdgeEffects,
-};
-
-use self::move_paths::MoveData;
-
-pub mod drop_flag_effects;
-mod framework;
-pub mod impls;
-pub mod move_paths;
-
-pub(crate) mod indexes {
-    pub(crate) use super::{
-        impls::borrows::BorrowIndex,
-        move_paths::{InitIndex, MoveOutIndex, MovePathIndex},
-    };
-}
-
-pub struct MoveDataParamEnv<'tcx> {
-    pub(crate) move_data: MoveData<'tcx>,
-    pub(crate) param_env: ty::ParamEnv<'tcx>,
-}
-
-pub(crate) fn has_rustc_mir_with(
-    _sess: &Session,
-    attrs: &[ast::Attribute],
-    name: Symbol,
-) -> Option<MetaItem> {
-    for attr in attrs {
-        if attr.has_name(sym::rustc_mir) {
-            let items = attr.meta_item_list();
-            for item in items.iter().flat_map(|l| l.iter()) {
-                match item.meta_item() {
-                    Some(mi) if mi.has_name(name) => return Some(mi.clone()),
-                    _ => continue,
-                }
-            }
-        }
-    }
-    None
-}
diff --git a/compiler/rustc_mir/src/util/mod.rs b/compiler/rustc_mir/src/util/mod.rs
deleted file mode 100644
index 3e466b5060f..00000000000
--- a/compiler/rustc_mir/src/util/mod.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-pub mod aggregate;
-pub mod borrowck_errors;
-pub mod elaborate_drops;
-pub mod patch;
-pub mod storage;
-
-mod alignment;
-pub mod collect_writes;
-mod find_self_call;
-mod generic_graph;
-pub(crate) mod generic_graphviz;
-mod graphviz;
-pub(crate) mod pretty;
-pub(crate) mod spanview;
-
-pub use self::aggregate::expand_aggregate;
-pub use self::alignment::is_disaligned;
-pub use self::find_self_call::find_self_call;
-pub use self::generic_graph::graphviz_safe_def_name;
-pub use self::graphviz::write_mir_graphviz;
-pub use self::pretty::{dump_enabled, dump_mir, write_mir_fn, write_mir_pretty, PassWhere};
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 68de1af613d..be0d5d2f1b2 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -494,9 +494,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     // Helper to get a `-1` value of the appropriate type
     fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
         let param_ty = ty::ParamEnv::empty().and(ty);
-        let bits = self.tcx.layout_of(param_ty).unwrap().size.bits();
-        let n = (!0u128) >> (128 - bits);
-        let literal = ty::Const::from_bits(self.tcx, n, param_ty);
+        let size = self.tcx.layout_of(param_ty).unwrap().size;
+        let literal = ty::Const::from_bits(self.tcx, size.unsigned_int_max(), param_ty);
 
         self.literal_operand(span, literal)
     }
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index ba94e15444a..4df073c40e2 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -900,10 +900,7 @@ fn traverse_candidate<'pat, 'tcx: 'pat, C, T, I>(
 struct Binding<'tcx> {
     span: Span,
     source: Place<'tcx>,
-    name: Symbol,
     var_id: HirId,
-    var_ty: Ty<'tcx>,
-    mutability: Mutability,
     binding_mode: BindingMode,
 }
 
@@ -2063,7 +2060,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 source_info.span, ascription.source, ascription.user_ty,
             );
 
-            let user_ty = ascription.user_ty.clone().user_ty(
+            let user_ty = ascription.user_ty.user_ty(
                 &mut self.canonical_user_type_annotations,
                 ascription.source.ty(&self.local_decls, self.tcx).ty,
                 source_info.span,
diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs
index 1feb8b0d7a0..4ce26cc8dff 100644
--- a/compiler/rustc_mir_build/src/build/matches/simplify.rs
+++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs
@@ -176,17 +176,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 Ok(())
             }
 
-            PatKind::Binding { name, mutability, mode, var, ty, ref subpattern, is_primary: _ } => {
+            PatKind::Binding {
+                name: _,
+                mutability: _,
+                mode,
+                var,
+                ty: _,
+                ref subpattern,
+                is_primary: _,
+            } => {
                 if let Ok(place_resolved) =
                     match_pair.place.clone().try_upvars_resolved(self.tcx, self.typeck_results)
                 {
                     candidate.bindings.push(Binding {
-                        name,
-                        mutability,
                         span: match_pair.pattern.span,
                         source: place_resolved.into_place(self.tcx, self.typeck_results),
                         var_id: var,
-                        var_ty: ty,
                         binding_mode: mode,
                     });
                 }
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 0a760a740dc..0ee740a6463 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -47,10 +47,12 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
     // Ensure unsafeck is ran before we steal the THIR.
     match def {
         ty::WithOptConstParam { did, const_param_did: Some(const_param_did) } => {
-            tcx.ensure().thir_check_unsafety_for_const_arg((did, const_param_did))
+            tcx.ensure().thir_check_unsafety_for_const_arg((did, const_param_did));
+            tcx.ensure().thir_abstract_const_of_const_arg((did, const_param_did));
         }
         ty::WithOptConstParam { did, const_param_did: None } => {
-            tcx.ensure().thir_check_unsafety(did)
+            tcx.ensure().thir_check_unsafety(did);
+            tcx.ensure().thir_abstract_const(did);
         }
     }
 
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index bd8d14fcd01..b74208edafe 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -118,9 +118,6 @@ struct Scope {
     /// the region span of this scope within source code.
     region_scope: region::Scope,
 
-    /// the span of that region_scope
-    region_scope_span: Span,
-
     /// set of places to drop when exiting this scope. This starts
     /// out empty but grows as variables are declared during the
     /// building process. This is a stack, so we always drop from the
@@ -420,7 +417,6 @@ impl<'tcx> Scopes<'tcx> {
         self.scopes.push(Scope {
             source_scope: vis_scope,
             region_scope: region_scope.0,
-            region_scope_span: region_scope.1.span,
             drops: vec![],
             moved_locals: vec![],
             cached_unwind_block: None,
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 05a5fcef16a..0e82b187201 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -1,5 +1,5 @@
 use crate::build::ExprCategory;
-use crate::thir::visit::{self, Visitor};
+use rustc_middle::thir::visit::{self, Visitor};
 
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
diff --git a/compiler/rustc_mir_build/src/thir/mod.rs b/compiler/rustc_mir_build/src/thir/mod.rs
index e5123d8ef0c..ddbe1b0b69c 100644
--- a/compiler/rustc_mir_build/src/thir/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/mod.rs
@@ -11,4 +11,3 @@ crate mod cx;
 crate mod pattern;
 
 mod util;
-pub mod visit;
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index b34c1e07be7..4c51b9207bb 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -14,8 +14,9 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_hir::{HirId, Pat};
 use rustc_middle::thir::PatKind;
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_session::lint::builtin::BINDINGS_WITH_VARIANT_NAME;
-use rustc_session::lint::builtin::{IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS};
+use rustc_session::lint::builtin::{
+    BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS,
+};
 use rustc_session::Session;
 use rustc_span::{DesugaringKind, ExpnKind, Span};
 use std::slice;
@@ -559,7 +560,7 @@ fn non_exhaustive_match<'p, 'tcx>(
     err.emit();
 }
 
-fn joined_uncovered_patterns(witnesses: &[super::Pat<'_>]) -> String {
+crate fn joined_uncovered_patterns(witnesses: &[super::Pat<'_>]) -> String {
     const LIMIT: usize = 3;
     match witnesses {
         [] => bug!(),
@@ -576,7 +577,7 @@ fn joined_uncovered_patterns(witnesses: &[super::Pat<'_>]) -> String {
     }
 }
 
-fn pattern_not_covered_label(witnesses: &[super::Pat<'_>], joined_patterns: &str) -> String {
+crate fn pattern_not_covered_label(witnesses: &[super::Pat<'_>], joined_patterns: &str) -> String {
     format!("pattern{} {} not covered", rustc_errors::pluralize!(witnesses.len()), joined_patterns)
 }
 
diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
index ace13ea4462..cee2a4db0a8 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -606,8 +606,9 @@ pub(super) enum Constructor<'tcx> {
     /// for those types for which we cannot list constructors explicitly, like `f64` and `str`.
     NonExhaustive,
     /// Stands for constructors that are not seen in the matrix, as explained in the documentation
-    /// for [`SplitWildcard`].
-    Missing,
+    /// for [`SplitWildcard`]. The carried `bool` is used for the `non_exhaustive_omitted_patterns`
+    /// lint.
+    Missing { nonexhaustive_enum_missing_real_variants: bool },
     /// Wildcard pattern.
     Wildcard,
 }
@@ -617,6 +618,10 @@ impl<'tcx> Constructor<'tcx> {
         matches!(self, Wildcard)
     }
 
+    pub(super) fn is_non_exhaustive(&self) -> bool {
+        matches!(self, NonExhaustive)
+    }
+
     fn as_int_range(&self) -> Option<&IntRange> {
         match self {
             IntRange(range) => Some(range),
@@ -756,7 +761,7 @@ impl<'tcx> Constructor<'tcx> {
             // Wildcards cover anything
             (_, Wildcard) => true,
             // The missing ctors are not covered by anything in the matrix except wildcards.
-            (Missing | Wildcard, _) => false,
+            (Missing { .. } | Wildcard, _) => false,
 
             (Single, Single) => true,
             (Variant(self_id), Variant(other_id)) => self_id == other_id,
@@ -829,7 +834,7 @@ impl<'tcx> Constructor<'tcx> {
                 .any(|other| slice.is_covered_by(other)),
             // This constructor is never covered by anything else
             NonExhaustive => false,
-            Str(..) | FloatRange(..) | Opaque | Missing | Wildcard => {
+            Str(..) | FloatRange(..) | Opaque | Missing { .. } | Wildcard => {
                 span_bug!(pcx.span, "found unexpected ctor in all_ctors: {:?}", self)
             }
         }
@@ -919,8 +924,14 @@ impl<'tcx> SplitWildcard<'tcx> {
                     && !cx.tcx.features().exhaustive_patterns
                     && !pcx.is_top_level;
 
-                if is_secretly_empty || is_declared_nonexhaustive {
+                if is_secretly_empty {
                     smallvec![NonExhaustive]
+                } else if is_declared_nonexhaustive {
+                    def.variants
+                        .indices()
+                        .map(|idx| Variant(idx))
+                        .chain(Some(NonExhaustive))
+                        .collect()
                 } else if cx.tcx.features().exhaustive_patterns {
                     // If `exhaustive_patterns` is enabled, we exclude variants known to be
                     // uninhabited.
@@ -975,6 +986,7 @@ impl<'tcx> SplitWildcard<'tcx> {
             // This type is one for which we cannot list constructors, like `str` or `f64`.
             _ => smallvec![NonExhaustive],
         };
+
         SplitWildcard { matrix_ctors: Vec::new(), all_ctors }
     }
 
@@ -1039,7 +1051,17 @@ impl<'tcx> SplitWildcard<'tcx> {
             // sometimes prefer reporting the list of constructors instead of just `_`.
             let report_when_all_missing = pcx.is_top_level && !IntRange::is_integral(pcx.ty);
             let ctor = if !self.matrix_ctors.is_empty() || report_when_all_missing {
-                Missing
+                if pcx.is_non_exhaustive {
+                    Missing {
+                        nonexhaustive_enum_missing_real_variants: self
+                            .iter_missing(pcx)
+                            .filter(|c| !c.is_non_exhaustive())
+                            .next()
+                            .is_some(),
+                    }
+                } else {
+                    Missing { nonexhaustive_enum_missing_real_variants: false }
+                }
             } else {
                 Wildcard
             };
@@ -1176,7 +1198,12 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
                 }
                 _ => bug!("bad slice pattern {:?} {:?}", constructor, ty),
             },
-            Str(..) | FloatRange(..) | IntRange(..) | NonExhaustive | Opaque | Missing
+            Str(..)
+            | FloatRange(..)
+            | IntRange(..)
+            | NonExhaustive
+            | Opaque
+            | Missing { .. }
             | Wildcard => Fields::Slice(&[]),
         };
         debug!("Fields::wildcards({:?}, {:?}) = {:#?}", constructor, ty, ret);
@@ -1189,15 +1216,18 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
     /// This is roughly the inverse of `specialize_constructor`.
     ///
     /// Examples:
-    /// `ctor`: `Constructor::Single`
-    /// `ty`: `Foo(u32, u32, u32)`
-    /// `self`: `[10, 20, _]`
+    ///
+    /// ```text
+    /// ctor: `Constructor::Single`
+    /// ty: `Foo(u32, u32, u32)`
+    /// self: `[10, 20, _]`
     /// returns `Foo(10, 20, _)`
     ///
-    /// `ctor`: `Constructor::Variant(Option::Some)`
-    /// `ty`: `Option<bool>`
-    /// `self`: `[false]`
+    /// ctor: `Constructor::Variant(Option::Some)`
+    /// ty: `Option<bool>`
+    /// self: `[false]`
     /// returns `Some(false)`
+    /// ```
     pub(super) fn apply(self, pcx: PatCtxt<'_, 'p, 'tcx>, ctor: &Constructor<'tcx>) -> Pat<'tcx> {
         let subpatterns_and_indices = self.patterns_and_indices();
         let mut subpatterns = subpatterns_and_indices.iter().map(|&(_, p)| p).cloned();
@@ -1265,7 +1295,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
             NonExhaustive => PatKind::Wild,
             Wildcard => return Pat::wildcard_from_ty(pcx.ty),
             Opaque => bug!("we should not try to apply an opaque constructor"),
-            Missing => bug!(
+            Missing { .. } => bug!(
                 "trying to apply the `Missing` constructor; this should have been done in `apply_constructors`"
             ),
         };
diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
index 344006e9fb4..f4255713e2a 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
@@ -280,20 +280,23 @@
 //! The details are not necessary to understand this file, so we explain them in
 //! [`super::deconstruct_pat`]. Splitting is done by the [`Constructor::split`] function.
 
+use self::ArmType::*;
 use self::Usefulness::*;
-use self::WitnessPreference::*;
 
+use super::check_match::{joined_uncovered_patterns, pattern_not_covered_label};
 use super::deconstruct_pat::{Constructor, Fields, SplitWildcard};
 use super::{PatternFoldable, PatternFolder};
 
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashMap;
 
+use hir::def_id::DefId;
+use hir::HirId;
 use rustc_arena::TypedArena;
-use rustc_hir::def_id::DefId;
-use rustc_hir::HirId;
+use rustc_hir as hir;
 use rustc_middle::thir::{Pat, PatKind};
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
 use rustc_span::Span;
 
 use smallvec::{smallvec, SmallVec};
@@ -343,6 +346,8 @@ pub(super) struct PatCtxt<'a, 'p, 'tcx> {
     /// Whether the current pattern is the whole pattern as found in a match arm, or if it's a
     /// subpattern.
     pub(super) is_top_level: bool,
+    /// Wether the current pattern is from a `non_exhaustive` enum.
+    pub(super) is_non_exhaustive: bool,
 }
 
 impl<'a, 'p, 'tcx> fmt::Debug for PatCtxt<'a, 'p, 'tcx> {
@@ -862,7 +867,7 @@ impl<'p, 'tcx> SubPatSet<'p, 'tcx> {
 /// of potential unreachable sub-patterns (in the presence of or-patterns). When checking
 /// exhaustiveness of a whole match, we use the `WithWitnesses` variant, which carries a list of
 /// witnesses of non-exhaustiveness when there are any.
-/// Which variant to use is dictated by `WitnessPreference`.
+/// Which variant to use is dictated by `ArmType`.
 #[derive(Clone, Debug)]
 enum Usefulness<'p, 'tcx> {
     /// Carries a set of subpatterns that have been found to be reachable. If empty, this indicates
@@ -877,16 +882,24 @@ enum Usefulness<'p, 'tcx> {
 }
 
 impl<'p, 'tcx> Usefulness<'p, 'tcx> {
-    fn new_useful(preference: WitnessPreference) -> Self {
+    fn new_useful(preference: ArmType) -> Self {
         match preference {
-            ConstructWitness => WithWitnesses(vec![Witness(vec![])]),
-            LeaveOutWitness => NoWitnesses(SubPatSet::full()),
+            FakeExtraWildcard => WithWitnesses(vec![Witness(vec![])]),
+            RealArm => NoWitnesses(SubPatSet::full()),
         }
     }
-    fn new_not_useful(preference: WitnessPreference) -> Self {
+
+    fn new_not_useful(preference: ArmType) -> Self {
         match preference {
-            ConstructWitness => WithWitnesses(vec![]),
-            LeaveOutWitness => NoWitnesses(SubPatSet::empty()),
+            FakeExtraWildcard => WithWitnesses(vec![]),
+            RealArm => NoWitnesses(SubPatSet::empty()),
+        }
+    }
+
+    fn is_useful(&self) -> bool {
+        match self {
+            Usefulness::NoWitnesses(set) => !set.is_empty(),
+            Usefulness::WithWitnesses(witnesses) => !witnesses.is_empty(),
         }
     }
 
@@ -903,7 +916,7 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> {
 
     /// When trying several branches and each returns a `Usefulness`, we need to combine the
     /// results together.
-    fn merge(pref: WitnessPreference, usefulnesses: impl Iterator<Item = Self>) -> Self {
+    fn merge(pref: ArmType, usefulnesses: impl Iterator<Item = Self>) -> Self {
         let mut ret = Self::new_not_useful(pref);
         for u in usefulnesses {
             ret.extend(u);
@@ -926,7 +939,7 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> {
         }
     }
 
-    /// After calculating usefulness after a specialization, call this to recontruct a usefulness
+    /// After calculating usefulness after a specialization, call this to reconstruct a usefulness
     /// that makes sense for the matrix pre-specialization. This new usefulness can then be merged
     /// with the results of specializing with the other constructors.
     fn apply_constructor(
@@ -939,19 +952,31 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> {
         match self {
             WithWitnesses(witnesses) if witnesses.is_empty() => WithWitnesses(witnesses),
             WithWitnesses(witnesses) => {
-                let new_witnesses = if matches!(ctor, Constructor::Missing) {
-                    let mut split_wildcard = SplitWildcard::new(pcx);
-                    split_wildcard.split(pcx, matrix.head_ctors(pcx.cx));
-                    // Construct for each missing constructor a "wild" version of this
-                    // constructor, that matches everything that can be built with
-                    // it. For example, if `ctor` is a `Constructor::Variant` for
-                    // `Option::Some`, we get the pattern `Some(_)`.
-                    let new_patterns: Vec<_> = split_wildcard
-                        .iter_missing(pcx)
-                        .map(|missing_ctor| {
-                            Fields::wildcards(pcx, missing_ctor).apply(pcx, missing_ctor)
-                        })
-                        .collect();
+                let new_witnesses = if let Constructor::Missing { .. } = ctor {
+                    // We got the special `Missing` constructor, so each of the missing constructors
+                    // gives a new pattern that is not caught by the match. We list those patterns.
+                    let new_patterns = if pcx.is_non_exhaustive {
+                        // Here we don't want the user to try to list all variants, we want them to add
+                        // a wildcard, so we only suggest that.
+                        vec![
+                            Fields::wildcards(pcx, &Constructor::NonExhaustive)
+                                .apply(pcx, &Constructor::NonExhaustive),
+                        ]
+                    } else {
+                        let mut split_wildcard = SplitWildcard::new(pcx);
+                        split_wildcard.split(pcx, matrix.head_ctors(pcx.cx));
+                        // Construct for each missing constructor a "wild" version of this
+                        // constructor, that matches everything that can be built with
+                        // it. For example, if `ctor` is a `Constructor::Variant` for
+                        // `Option::Some`, we get the pattern `Some(_)`.
+                        split_wildcard
+                            .iter_missing(pcx)
+                            .map(|missing_ctor| {
+                                Fields::wildcards(pcx, missing_ctor).apply(pcx, missing_ctor)
+                            })
+                            .collect()
+                    };
+
                     witnesses
                         .into_iter()
                         .flat_map(|witness| {
@@ -976,9 +1001,9 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> {
 }
 
 #[derive(Copy, Clone, Debug)]
-enum WitnessPreference {
-    ConstructWitness,
-    LeaveOutWitness,
+enum ArmType {
+    FakeExtraWildcard,
+    RealArm,
 }
 
 /// A witness of non-exhaustiveness for error reporting, represented
@@ -1056,6 +1081,32 @@ impl<'tcx> Witness<'tcx> {
     }
 }
 
+/// Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
+/// is not exhaustive enough.
+///
+/// NB: The partner lint for structs lives in `compiler/rustc_typeck/src/check/pat.rs`.
+fn lint_non_exhaustive_omitted_patterns<'p, 'tcx>(
+    cx: &MatchCheckCtxt<'p, 'tcx>,
+    scrut_ty: Ty<'tcx>,
+    sp: Span,
+    hir_id: HirId,
+    witnesses: Vec<Pat<'tcx>>,
+) {
+    let joined_patterns = joined_uncovered_patterns(&witnesses);
+    cx.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, hir_id, sp, |build| {
+        let mut lint = build.build("some variants are not matched explicitly");
+        lint.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns));
+        lint.help(
+            "ensure that all variants are matched explicitly by adding the suggested match arms",
+        );
+        lint.note(&format!(
+            "the matched value is of type `{}` and the `non_exhaustive_omitted_patterns` attribute was found",
+            scrut_ty,
+        ));
+        lint.emit();
+    });
+}
+
 /// Algorithm from <http://moscova.inria.fr/~maranget/papers/warn/index.html>.
 /// The algorithm from the paper has been modified to correctly handle empty
 /// types. The changes are:
@@ -1086,7 +1137,7 @@ fn is_useful<'p, 'tcx>(
     cx: &MatchCheckCtxt<'p, 'tcx>,
     matrix: &Matrix<'p, 'tcx>,
     v: &PatStack<'p, 'tcx>,
-    witness_preference: WitnessPreference,
+    witness_preference: ArmType,
     hir_id: HirId,
     is_under_guard: bool,
     is_top_level: bool,
@@ -1113,7 +1164,8 @@ fn is_useful<'p, 'tcx>(
 
     // FIXME(Nadrieril): Hack to work around type normalization issues (see #72476).
     let ty = matrix.heads().next().map_or(v.head().ty, |r| r.ty);
-    let pcx = PatCtxt { cx, ty, span: v.head().span, is_top_level };
+    let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty);
+    let pcx = PatCtxt { cx, ty, span: v.head().span, is_top_level, is_non_exhaustive };
 
     // If the first pattern is an or-pattern, expand it.
     let ret = if is_or_pat(v.head()) {
@@ -1148,6 +1200,7 @@ fn is_useful<'p, 'tcx>(
         }
         // We split the head constructor of `v`.
         let split_ctors = v_ctor.split(pcx, matrix.head_ctors(cx));
+        let is_non_exhaustive_and_wild = is_non_exhaustive && v_ctor.is_wildcard();
         // For each constructor, we compute whether there's a value that starts with it that would
         // witness the usefulness of `v`.
         let start_matrix = &matrix;
@@ -1160,10 +1213,46 @@ fn is_useful<'p, 'tcx>(
             let v = v.pop_head_constructor(&ctor_wild_subpatterns);
             let usefulness =
                 is_useful(cx, &spec_matrix, &v, witness_preference, hir_id, is_under_guard, false);
+
+            // When all the conditions are met we have a match with a `non_exhaustive` enum
+            // that has the potential to trigger the `non_exhaustive_omitted_patterns` lint.
+            // To understand the workings checkout `Constructor::split` and `SplitWildcard::new/into_ctors`
+            if is_non_exhaustive_and_wild
+                // We check that the match has a wildcard pattern and that that wildcard is useful,
+                // meaning there are variants that are covered by the wildcard. Without the check
+                // for `witness_preference` the lint would trigger on `if let NonExhaustiveEnum::A = foo {}`
+                && usefulness.is_useful() && matches!(witness_preference, RealArm)
+                && matches!(
+                    &ctor,
+                    Constructor::Missing { nonexhaustive_enum_missing_real_variants: true }
+                )
+            {
+                let patterns = {
+                    let mut split_wildcard = SplitWildcard::new(pcx);
+                    split_wildcard.split(pcx, matrix.head_ctors(pcx.cx));
+                    // Construct for each missing constructor a "wild" version of this
+                    // constructor, that matches everything that can be built with
+                    // it. For example, if `ctor` is a `Constructor::Variant` for
+                    // `Option::Some`, we get the pattern `Some(_)`.
+                    split_wildcard
+                        .iter_missing(pcx)
+                        // Filter out the `Constructor::NonExhaustive` variant it's meaningless
+                        // to our lint
+                        .filter(|c| !c.is_non_exhaustive())
+                        .map(|missing_ctor| {
+                            Fields::wildcards(pcx, missing_ctor).apply(pcx, missing_ctor)
+                        })
+                        .collect::<Vec<_>>()
+                };
+
+                lint_non_exhaustive_omitted_patterns(pcx.cx, pcx.ty, pcx.span, hir_id, patterns);
+            }
+
             usefulness.apply_constructor(pcx, start_matrix, &ctor, &ctor_wild_subpatterns)
         });
         Usefulness::merge(witness_preference, usefulnesses)
     };
+
     debug!(?ret);
     ret
 }
@@ -1214,8 +1303,7 @@ crate fn compute_match_usefulness<'p, 'tcx>(
         .copied()
         .map(|arm| {
             let v = PatStack::from_pattern(arm.pat);
-            let usefulness =
-                is_useful(cx, &matrix, &v, LeaveOutWitness, arm.hir_id, arm.has_guard, true);
+            let usefulness = is_useful(cx, &matrix, &v, RealArm, arm.hir_id, arm.has_guard, true);
             if !arm.has_guard {
                 matrix.push(v);
             }
@@ -1232,7 +1320,7 @@ crate fn compute_match_usefulness<'p, 'tcx>(
 
     let wild_pattern = cx.pattern_arena.alloc(Pat::wildcard_from_ty(scrut_ty));
     let v = PatStack::from_pattern(wild_pattern);
-    let usefulness = is_useful(cx, &matrix, &v, ConstructWitness, scrut_hir_id, false, true);
+    let usefulness = is_useful(cx, &matrix, &v, FakeExtraWildcard, scrut_hir_id, false, true);
     let non_exhaustiveness_witnesses = match usefulness {
         WithWitnesses(pats) => pats.into_iter().map(|w| w.single_pattern()).collect(),
         NoWitnesses(_) => bug!(),
diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml
new file mode 100644
index 00000000000..3cd4892402e
--- /dev/null
+++ b/compiler/rustc_mir_dataflow/Cargo.toml
@@ -0,0 +1,23 @@
+[package]
+name = "rustc_mir_dataflow"
+version = "0.0.0"
+edition = "2018"
+
+[lib]
+doctest = false
+
+[dependencies]
+polonius-engine = "0.13.0"
+regex = "1"
+smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+tracing = "0.1"
+rustc_ast = { path = "../rustc_ast" }
+rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_graphviz = { path = "../rustc_graphviz" }
+rustc_hir = { path = "../rustc_hir" }
+rustc_index = { path = "../rustc_index" }
+rustc_middle = { path = "../rustc_middle" }
+rustc_serialize = { path = "../rustc_serialize" }
+rustc_session = { path = "../rustc_session" }
+rustc_target = { path = "../rustc_target" }
+rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_mir/src/dataflow/drop_flag_effects.rs b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
index d16366fded9..e2269562b3d 100644
--- a/compiler/rustc_mir/src/dataflow/drop_flag_effects.rs
+++ b/compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
@@ -1,4 +1,4 @@
-use crate::util::elaborate_drops::DropFlagState;
+use crate::elaborate_drops::DropFlagState;
 use rustc_middle::mir::{self, Body, Location};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_target::abi::VariantIdx;
@@ -79,7 +79,7 @@ fn place_contents_drop_state_cannot_differ<'tcx>(
     }
 }
 
-pub(crate) fn on_lookup_result_bits<'tcx, F>(
+pub fn on_lookup_result_bits<'tcx, F>(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
     move_data: &MoveData<'tcx>,
@@ -96,7 +96,7 @@ pub(crate) fn on_lookup_result_bits<'tcx, F>(
     }
 }
 
-pub(crate) fn on_all_children_bits<'tcx, F>(
+pub fn on_all_children_bits<'tcx, F>(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
     move_data: &MoveData<'tcx>,
@@ -138,7 +138,7 @@ pub(crate) fn on_all_children_bits<'tcx, F>(
     on_all_children_bits(tcx, body, move_data, move_path_index, &mut each_child);
 }
 
-pub(crate) fn on_all_drop_children_bits<'tcx, F>(
+pub fn on_all_drop_children_bits<'tcx, F>(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
     ctxt: &MoveDataParamEnv<'tcx>,
@@ -161,7 +161,7 @@ pub(crate) fn on_all_drop_children_bits<'tcx, F>(
     })
 }
 
-pub(crate) fn drop_flag_effects_for_function_entry<'tcx, F>(
+pub fn drop_flag_effects_for_function_entry<'tcx, F>(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
     ctxt: &MoveDataParamEnv<'tcx>,
@@ -179,7 +179,7 @@ pub(crate) fn drop_flag_effects_for_function_entry<'tcx, F>(
     }
 }
 
-pub(crate) fn drop_flag_effects_for_location<'tcx, F>(
+pub fn drop_flag_effects_for_location<'tcx, F>(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
     ctxt: &MoveDataParamEnv<'tcx>,
@@ -204,7 +204,7 @@ pub(crate) fn drop_flag_effects_for_location<'tcx, F>(
     for_location_inits(tcx, body, move_data, loc, |mpi| callback(mpi, DropFlagState::Present));
 }
 
-pub(crate) fn for_location_inits<'tcx, F>(
+pub fn for_location_inits<'tcx, F>(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
     move_data: &MoveData<'tcx>,
diff --git a/compiler/rustc_mir/src/util/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 50756fc15fb..7607ccc3aba 100644
--- a/compiler/rustc_mir/src/util/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -1,7 +1,7 @@
-use crate::util::patch::MirPatch;
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::vec::Idx;
+use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
 use rustc_middle::traits::Reveal;
 use rustc_middle::ty::subst::SubstsRef;
diff --git a/compiler/rustc_mir/src/dataflow/framework/cursor.rs b/compiler/rustc_mir_dataflow/src/framework/cursor.rs
index c000e49c14b..c000e49c14b 100644
--- a/compiler/rustc_mir/src/dataflow/framework/cursor.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/cursor.rs
diff --git a/compiler/rustc_mir/src/dataflow/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index 8a9ced91eb3..8a9ced91eb3 100644
--- a/compiler/rustc_mir/src/dataflow/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
diff --git a/compiler/rustc_mir/src/dataflow/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs
index 7ff7c860591..804abc3b42b 100644
--- a/compiler/rustc_mir/src/dataflow/framework/engine.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs
@@ -11,6 +11,7 @@ use rustc_hir::def_id::DefId;
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::mir::{self, traversal, BasicBlock};
+use rustc_middle::mir::{create_dump_file, dump_enabled};
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::{sym, Symbol};
 
@@ -20,7 +21,6 @@ use super::{
     visit_results, Analysis, Direction, GenKill, GenKillAnalysis, GenKillSet, JoinSemiLattice,
     ResultsCursor, ResultsVisitor,
 };
-use crate::util::pretty::{create_dump_file, dump_enabled};
 
 /// A dataflow analysis that has converged to fixpoint.
 pub struct Results<'tcx, A>
diff --git a/compiler/rustc_mir/src/dataflow/framework/fmt.rs b/compiler/rustc_mir_dataflow/src/framework/fmt.rs
index 35115ca9db7..1d1553bbbd9 100644
--- a/compiler/rustc_mir/src/dataflow/framework/fmt.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/fmt.rs
@@ -147,18 +147,18 @@ where
 }
 
 impl<C> DebugWithContext<C> for rustc_middle::mir::Local {}
-impl<C> DebugWithContext<C> for crate::dataflow::move_paths::InitIndex {}
+impl<C> DebugWithContext<C> for crate::move_paths::InitIndex {}
 
-impl<'tcx, C> DebugWithContext<C> for crate::dataflow::move_paths::MovePathIndex
+impl<'tcx, C> DebugWithContext<C> for crate::move_paths::MovePathIndex
 where
-    C: crate::dataflow::move_paths::HasMoveData<'tcx>,
+    C: crate::move_paths::HasMoveData<'tcx>,
 {
     fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{}", ctxt.move_data().move_paths[*self])
     }
 }
 
-impl<T, C> DebugWithContext<C> for crate::dataflow::lattice::Dual<T>
+impl<T, C> DebugWithContext<C> for crate::lattice::Dual<T>
 where
     T: DebugWithContext<C>,
 {
diff --git a/compiler/rustc_mir/src/dataflow/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index 4e54257a1cb..a370f8e40f9 100644
--- a/compiler/rustc_mir/src/dataflow/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -6,11 +6,11 @@ use std::{io, ops, str};
 
 use regex::Regex;
 use rustc_graphviz as dot;
+use rustc_middle::mir::graphviz_safe_def_name;
 use rustc_middle::mir::{self, BasicBlock, Body, Location};
 
 use super::fmt::{DebugDiffWithAdapter, DebugWithAdapter, DebugWithContext};
 use super::{Analysis, Direction, Results, ResultsRefCursor, ResultsVisitor};
-use crate::util::graphviz_safe_def_name;
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub enum OutputStyle {
diff --git a/compiler/rustc_mir/src/dataflow/framework/lattice.rs b/compiler/rustc_mir_dataflow/src/framework/lattice.rs
index f937b31f4cf..f937b31f4cf 100644
--- a/compiler/rustc_mir/src/dataflow/framework/lattice.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/lattice.rs
diff --git a/compiler/rustc_mir/src/dataflow/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs
index a5badc07d10..f0c9ac4c504 100644
--- a/compiler/rustc_mir/src/dataflow/framework/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs
@@ -11,7 +11,7 @@
 //! `visit_results`. The following example uses the `ResultsCursor` approach.
 //!
 //! ```ignore (cross-crate-imports)
-//! use rustc_mir::dataflow::Analysis; // Makes `into_engine` available.
+//! use rustc_const_eval::dataflow::Analysis; // Makes `into_engine` available.
 //!
 //! fn do_my_analysis(tcx: TyCtxt<'tcx>, body: &mir::Body<'tcx>) {
 //!     let analysis = MyAnalysis::new()
@@ -50,8 +50,7 @@ pub use self::cursor::{ResultsCursor, ResultsRefCursor};
 pub use self::direction::{Backward, Direction, Forward};
 pub use self::engine::{Engine, Results};
 pub use self::lattice::{JoinSemiLattice, MeetSemiLattice};
-pub use self::visitor::{visit_results, ResultsVisitor};
-pub use self::visitor::{BorrowckFlowState, BorrowckResults};
+pub use self::visitor::{visit_results, ResultsVisitable, ResultsVisitor};
 
 /// Define the domain of a dataflow problem.
 ///
diff --git a/compiler/rustc_mir/src/dataflow/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs
index a5989121679..a5989121679 100644
--- a/compiler/rustc_mir/src/dataflow/framework/tests.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs
diff --git a/compiler/rustc_mir/src/dataflow/framework/visitor.rs b/compiler/rustc_mir_dataflow/src/framework/visitor.rs
index 82eb734ed06..84136c4d78c 100644
--- a/compiler/rustc_mir/src/dataflow/framework/visitor.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/visitor.rs
@@ -1,7 +1,6 @@
 use rustc_middle::mir::{self, BasicBlock, Location};
 
 use super::{Analysis, Direction, Results};
-use crate::dataflow::impls::{borrows::Borrows, EverInitializedPlaces, MaybeUninitializedPlaces};
 
 /// Calls the corresponding method in `ResultsVisitor` for every location in a `mir::Body` with the
 /// dataflow state at that location.
@@ -186,95 +185,3 @@ where
         self.analysis.apply_terminator_effect(state, term, loc);
     }
 }
-
-/// A tuple with named fields that can hold either the results or the transient state of the
-/// dataflow analyses used by the borrow checker.
-#[derive(Debug)]
-pub struct BorrowckAnalyses<B, U, E> {
-    pub borrows: B,
-    pub uninits: U,
-    pub ever_inits: E,
-}
-
-/// The results of the dataflow analyses used by the borrow checker.
-pub type BorrowckResults<'mir, 'tcx> = BorrowckAnalyses<
-    Results<'tcx, Borrows<'mir, 'tcx>>,
-    Results<'tcx, MaybeUninitializedPlaces<'mir, 'tcx>>,
-    Results<'tcx, EverInitializedPlaces<'mir, 'tcx>>,
->;
-
-/// The transient state of the dataflow analyses used by the borrow checker.
-pub type BorrowckFlowState<'mir, 'tcx> =
-    <BorrowckResults<'mir, 'tcx> as ResultsVisitable<'tcx>>::FlowState;
-
-macro_rules! impl_visitable {
-    ( $(
-        $T:ident { $( $field:ident : $A:ident ),* $(,)? }
-    )* ) => { $(
-        impl<'tcx, $($A),*, D: Direction> ResultsVisitable<'tcx> for $T<$( Results<'tcx, $A> ),*>
-        where
-            $( $A: Analysis<'tcx, Direction = D>, )*
-        {
-            type Direction = D;
-            type FlowState = $T<$( $A::Domain ),*>;
-
-            fn new_flow_state(&self, body: &mir::Body<'tcx>) -> Self::FlowState {
-                $T {
-                    $( $field: self.$field.analysis.bottom_value(body) ),*
-                }
-            }
-
-            fn reset_to_block_entry(
-                &self,
-                state: &mut Self::FlowState,
-                block: BasicBlock,
-            ) {
-                $( state.$field.clone_from(&self.$field.entry_set_for_block(block)); )*
-            }
-
-            fn reconstruct_before_statement_effect(
-                &self,
-                state: &mut Self::FlowState,
-                stmt: &mir::Statement<'tcx>,
-                loc: Location,
-            ) {
-                $( self.$field.analysis
-                    .apply_before_statement_effect(&mut state.$field, stmt, loc); )*
-            }
-
-            fn reconstruct_statement_effect(
-                &self,
-                state: &mut Self::FlowState,
-                stmt: &mir::Statement<'tcx>,
-                loc: Location,
-            ) {
-                $( self.$field.analysis
-                    .apply_statement_effect(&mut state.$field, stmt, loc); )*
-            }
-
-            fn reconstruct_before_terminator_effect(
-                &self,
-                state: &mut Self::FlowState,
-                term: &mir::Terminator<'tcx>,
-                loc: Location,
-            ) {
-                $( self.$field.analysis
-                    .apply_before_terminator_effect(&mut state.$field, term, loc); )*
-            }
-
-            fn reconstruct_terminator_effect(
-                &self,
-                state: &mut Self::FlowState,
-                term: &mir::Terminator<'tcx>,
-                loc: Location,
-            ) {
-                $( self.$field.analysis
-                    .apply_terminator_effect(&mut state.$field, term, loc); )*
-            }
-        }
-    )* }
-}
-
-impl_visitable! {
-    BorrowckAnalyses { borrows: B, uninits: U, ever_inits: E }
-}
diff --git a/compiler/rustc_mir/src/dataflow/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
index 65e04ed6831..81d84f80ad4 100644
--- a/compiler/rustc_mir/src/dataflow/impls/borrowed_locals.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
@@ -1,6 +1,6 @@
-pub use super::*;
+use super::*;
 
-use crate::dataflow::{AnalysisDomain, GenKill, GenKillAnalysis};
+use crate::{AnalysisDomain, GenKill, GenKillAnalysis};
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{ParamEnv, TyCtxt};
diff --git a/compiler/rustc_mir/src/dataflow/impls/init_locals.rs b/compiler/rustc_mir_dataflow/src/impls/init_locals.rs
index bb7292cd033..07570e764f5 100644
--- a/compiler/rustc_mir/src/dataflow/impls/init_locals.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/init_locals.rs
@@ -2,7 +2,7 @@
 //!
 //! A local will be maybe initialized if *any* projections of that local might be initialized.
 
-use crate::dataflow::{self, GenKill};
+use crate::GenKill;
 
 use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::visit::{PlaceContext, Visitor};
@@ -10,7 +10,7 @@ use rustc_middle::mir::{self, BasicBlock, Local, Location};
 
 pub struct MaybeInitializedLocals;
 
-impl dataflow::AnalysisDomain<'tcx> for MaybeInitializedLocals {
+impl crate::AnalysisDomain<'tcx> for MaybeInitializedLocals {
     type Domain = BitSet<Local>;
 
     const NAME: &'static str = "maybe_init_locals";
@@ -28,7 +28,7 @@ impl dataflow::AnalysisDomain<'tcx> for MaybeInitializedLocals {
     }
 }
 
-impl dataflow::GenKillAnalysis<'tcx> for MaybeInitializedLocals {
+impl crate::GenKillAnalysis<'tcx> for MaybeInitializedLocals {
     type Idx = Local;
 
     fn statement_effect(
diff --git a/compiler/rustc_mir/src/dataflow/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
index 2d20f0d9547..0039d3188d5 100644
--- a/compiler/rustc_mir/src/dataflow/impls/liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
@@ -2,7 +2,7 @@ use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::{self, Local, Location};
 
-use crate::dataflow::{AnalysisDomain, Backward, GenKill, GenKillAnalysis};
+use crate::{AnalysisDomain, Backward, GenKill, GenKillAnalysis};
 
 /// A [live-variable dataflow analysis][liveness].
 ///
diff --git a/compiler/rustc_mir/src/dataflow/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs
index 185f0edfeb6..771ad90af28 100644
--- a/compiler/rustc_mir/src/dataflow/impls/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs
@@ -7,27 +7,22 @@ use rustc_index::vec::Idx;
 use rustc_middle::mir::{self, Body, Location};
 use rustc_middle::ty::{self, TyCtxt};
 
-use super::MoveDataParamEnv;
-
-use crate::util::elaborate_drops::DropFlagState;
-
-use super::move_paths::{HasMoveData, InitIndex, InitKind, MoveData, MovePathIndex};
-use super::{lattice, AnalysisDomain, GenKill, GenKillAnalysis};
-
-use super::drop_flag_effects_for_function_entry;
-use super::drop_flag_effects_for_location;
-use super::on_lookup_result_bits;
-use crate::dataflow::drop_flag_effects;
-use crate::dataflow::framework::SwitchIntEdgeEffects;
+use crate::drop_flag_effects;
+use crate::drop_flag_effects_for_function_entry;
+use crate::drop_flag_effects_for_location;
+use crate::elaborate_drops::DropFlagState;
+use crate::framework::SwitchIntEdgeEffects;
+use crate::move_paths::{HasMoveData, InitIndex, InitKind, MoveData, MovePathIndex};
+use crate::on_lookup_result_bits;
+use crate::MoveDataParamEnv;
+use crate::{lattice, AnalysisDomain, GenKill, GenKillAnalysis};
 
 mod borrowed_locals;
-pub(super) mod borrows;
 mod init_locals;
 mod liveness;
 mod storage_liveness;
 
 pub use self::borrowed_locals::{MaybeBorrowedLocals, MaybeMutBorrowedLocals};
-pub use self::borrows::Borrows;
 pub use self::init_locals::MaybeInitializedLocals;
 pub use self::liveness::MaybeLiveLocals;
 pub use self::storage_liveness::{MaybeRequiresStorage, MaybeStorageLive};
diff --git a/compiler/rustc_mir/src/dataflow/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
index 792664597fd..b468e50b391 100644
--- a/compiler/rustc_mir/src/dataflow/impls/storage_liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
@@ -1,7 +1,7 @@
 pub use super::*;
 
-use crate::dataflow::{self, GenKill, Results, ResultsRefCursor};
-use crate::util::storage::AlwaysLiveLocals;
+use crate::storage::AlwaysLiveLocals;
+use crate::{GenKill, Results, ResultsRefCursor};
 use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use std::cell::RefCell;
@@ -17,7 +17,7 @@ impl MaybeStorageLive {
     }
 }
 
-impl dataflow::AnalysisDomain<'tcx> for MaybeStorageLive {
+impl crate::AnalysisDomain<'tcx> for MaybeStorageLive {
     type Domain = BitSet<Local>;
 
     const NAME: &'static str = "maybe_storage_live";
@@ -39,7 +39,7 @@ impl dataflow::AnalysisDomain<'tcx> for MaybeStorageLive {
     }
 }
 
-impl dataflow::GenKillAnalysis<'tcx> for MaybeStorageLive {
+impl crate::GenKillAnalysis<'tcx> for MaybeStorageLive {
     type Idx = Local;
 
     fn statement_effect(
@@ -97,7 +97,7 @@ impl<'mir, 'tcx> MaybeRequiresStorage<'mir, 'tcx> {
     }
 }
 
-impl<'mir, 'tcx> dataflow::AnalysisDomain<'tcx> for MaybeRequiresStorage<'mir, 'tcx> {
+impl<'mir, 'tcx> crate::AnalysisDomain<'tcx> for MaybeRequiresStorage<'mir, 'tcx> {
     type Domain = BitSet<Local>;
 
     const NAME: &'static str = "requires_storage";
@@ -116,7 +116,7 @@ impl<'mir, 'tcx> dataflow::AnalysisDomain<'tcx> for MaybeRequiresStorage<'mir, '
     }
 }
 
-impl<'mir, 'tcx> dataflow::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tcx> {
+impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tcx> {
     type Idx = Local;
 
     fn before_statement_effect(
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
new file mode 100644
index 00000000000..72c4e27cbea
--- /dev/null
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -0,0 +1,72 @@
+#![feature(associated_type_defaults)]
+#![feature(bool_to_option)]
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+#![feature(const_panic)]
+#![feature(exact_size_is_empty)]
+#![feature(in_band_lifetimes)]
+#![feature(iter_zip)]
+#![feature(min_specialization)]
+#![feature(once_cell)]
+#![feature(stmt_expr_attributes)]
+#![feature(trusted_step)]
+#![recursion_limit = "256"]
+
+#[macro_use]
+extern crate tracing;
+#[macro_use]
+extern crate rustc_middle;
+
+use rustc_ast::{self as ast, MetaItem};
+use rustc_middle::ty;
+use rustc_session::Session;
+use rustc_span::symbol::{sym, Symbol};
+
+pub use self::drop_flag_effects::{
+    drop_flag_effects_for_function_entry, drop_flag_effects_for_location,
+    move_path_children_matching, on_all_children_bits, on_all_drop_children_bits,
+    on_lookup_result_bits,
+};
+pub use self::framework::{
+    fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, Direction, Engine,
+    Forward, GenKill, GenKillAnalysis, JoinSemiLattice, Results, ResultsCursor, ResultsRefCursor,
+    ResultsVisitable, ResultsVisitor,
+};
+
+use self::move_paths::MoveData;
+
+pub mod drop_flag_effects;
+pub mod elaborate_drops;
+mod framework;
+pub mod impls;
+pub mod move_paths;
+pub mod rustc_peek;
+pub mod storage;
+
+pub(crate) mod indexes {
+    pub(crate) use super::move_paths::MovePathIndex;
+}
+
+pub struct MoveDataParamEnv<'tcx> {
+    pub move_data: MoveData<'tcx>,
+    pub param_env: ty::ParamEnv<'tcx>,
+}
+
+pub fn has_rustc_mir_with(
+    _sess: &Session,
+    attrs: &[ast::Attribute],
+    name: Symbol,
+) -> Option<MetaItem> {
+    for attr in attrs {
+        if attr.has_name(sym::rustc_mir) {
+            let items = attr.meta_item_list();
+            for item in items.iter().flat_map(|l| l.iter()) {
+                match item.meta_item() {
+                    Some(mi) if mi.has_name(name) => return Some(mi.clone()),
+                    _ => continue,
+                }
+            }
+        }
+    }
+    None
+}
diff --git a/compiler/rustc_mir/src/dataflow/move_paths/abs_domain.rs b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
index 28936274baa..28936274baa 100644
--- a/compiler/rustc_mir/src/dataflow/move_paths/abs_domain.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
diff --git a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index cea465ea1ed..407ba739463 100644
--- a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -342,7 +342,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
             | Rvalue::AddressOf(..)
             | Rvalue::Discriminant(..)
             | Rvalue::Len(..)
-            | Rvalue::NullaryOp(NullOp::SizeOf, _)
+            | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _)
             | Rvalue::NullaryOp(NullOp::Box, _) => {
                 // This returns an rvalue with uninitialized contents. We can't
                 // move out of it here because it is an rvalue - assignments always
diff --git a/compiler/rustc_mir/src/dataflow/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
index 7c630259186..699ec4bbff8 100644
--- a/compiler/rustc_mir/src/dataflow/move_paths/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
@@ -19,6 +19,12 @@ rustc_index::newtype_index! {
     }
 }
 
+impl polonius_engine::Atom for MovePathIndex {
+    fn index(self) -> usize {
+        rustc_index::vec::Idx::index(self)
+    }
+}
+
 rustc_index::newtype_index! {
     pub struct MoveOutIndex {
         DEBUG_FORMAT = "mo{}"
@@ -276,7 +282,7 @@ impl fmt::Debug for Init {
 }
 
 impl Init {
-    crate fn span<'tcx>(&self, body: &Body<'tcx>) -> Span {
+    pub fn span<'tcx>(&self, body: &Body<'tcx>) -> Span {
         match self.location {
             InitLocation::Argument(local) => body.local_decls[local].source_info.span,
             InitLocation::Statement(location) => body.source_info(location).span,
@@ -338,12 +344,12 @@ impl MovePathLookup {
 
 #[derive(Debug)]
 pub struct IllegalMoveOrigin<'tcx> {
-    pub(crate) location: Location,
-    pub(crate) kind: IllegalMoveOriginKind<'tcx>,
+    pub location: Location,
+    pub kind: IllegalMoveOriginKind<'tcx>,
 }
 
 #[derive(Debug)]
-pub(crate) enum IllegalMoveOriginKind<'tcx> {
+pub enum IllegalMoveOriginKind<'tcx> {
     /// Illegal move due to attempt to move from behind a reference.
     BorrowedContent {
         /// The place the reference refers to: if erroneous code was trying to
diff --git a/compiler/rustc_mir/src/transform/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
index f4a1b0ddba5..29ffed99344 100644
--- a/compiler/rustc_mir/src/transform/rustc_peek.rs
+++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs
@@ -5,25 +5,25 @@ use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 
-use crate::transform::MirPass;
 use rustc_index::bit_set::BitSet;
+use rustc_middle::mir::MirPass;
 use rustc_middle::mir::{self, Body, Local, Location};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
-use crate::dataflow::impls::{
+use crate::impls::{
     DefinitelyInitializedPlaces, MaybeInitializedPlaces, MaybeLiveLocals, MaybeMutBorrowedLocals,
     MaybeUninitializedPlaces,
 };
-use crate::dataflow::move_paths::{HasMoveData, MoveData};
-use crate::dataflow::move_paths::{LookupResult, MovePathIndex};
-use crate::dataflow::MoveDataParamEnv;
-use crate::dataflow::{Analysis, JoinSemiLattice, Results, ResultsCursor};
+use crate::move_paths::{HasMoveData, MoveData};
+use crate::move_paths::{LookupResult, MovePathIndex};
+use crate::MoveDataParamEnv;
+use crate::{Analysis, JoinSemiLattice, Results, ResultsCursor};
 
 pub struct SanityCheck;
 
 impl<'tcx> MirPass<'tcx> for SanityCheck {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        use crate::dataflow::has_rustc_mir_with;
+        use crate::has_rustc_mir_with;
         let def_id = body.source.def_id();
         if !tcx.has_attr(def_id, sym::rustc_mir) {
             debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id));
diff --git a/compiler/rustc_mir/src/util/storage.rs b/compiler/rustc_mir_dataflow/src/storage.rs
index 18b8ef557d6..18b8ef557d6 100644
--- a/compiler/rustc_mir/src/util/storage.rs
+++ b/compiler/rustc_mir_dataflow/src/storage.rs
diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml
new file mode 100644
index 00000000000..5e1a587b0ec
--- /dev/null
+++ b/compiler/rustc_mir_transform/Cargo.toml
@@ -0,0 +1,29 @@
+[package]
+name = "rustc_mir_transform"
+version = "0.0.0"
+edition = "2018"
+
+[lib]
+doctest = false
+
+[dependencies]
+itertools = "0.9"
+smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+tracing = "0.1"
+rustc_ast = { path = "../rustc_ast" }
+rustc_attr = { path = "../rustc_attr" }
+rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_errors = { path = "../rustc_errors" }
+rustc_hir = { path = "../rustc_hir" }
+rustc_index = { path = "../rustc_index" }
+rustc_middle = { path = "../rustc_middle" }
+rustc_const_eval = { path = "../rustc_const_eval" }
+rustc_mir_dataflow = { path = "../rustc_mir_dataflow" }
+rustc_serialize = { path = "../rustc_serialize" }
+rustc_session = { path = "../rustc_session" }
+rustc_target = { path = "../rustc_target" }
+rustc_trait_selection = { path = "../rustc_trait_selection" }
+rustc_span = { path = "../rustc_span" }
+
+[dev-dependencies]
+coverage_test_macros = { path = "src/coverage/test_macros" }
diff --git a/compiler/rustc_mir/src/transform/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
index aecb2373eaf..1abb64219f6 100644
--- a/compiler/rustc_mir/src/transform/abort_unwinding_calls.rs
+++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
@@ -1,10 +1,11 @@
-use crate::transform::MirPass;
+use crate::MirPass;
 use rustc_hir::def::DefKind;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::*;
 use rustc_middle::ty::layout;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_target::spec::abi::Abi;
+use rustc_target::spec::PanicStrategy;
 
 /// A pass that runs which is targeted at ensuring that codegen guarantees about
 /// unwinding are upheld for compilations of panic=abort programs.
@@ -82,10 +83,11 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
                     };
                     layout::fn_can_unwind(tcx, flags, sig.abi())
                 }
-                TerminatorKind::Drop { .. }
-                | TerminatorKind::DropAndReplace { .. }
-                | TerminatorKind::Assert { .. }
-                | TerminatorKind::FalseUnwind { .. } => {
+                TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => {
+                    tcx.sess.opts.debugging_opts.panic_in_drop == PanicStrategy::Unwind
+                        && layout::fn_can_unwind(tcx, CodegenFnAttrFlags::empty(), Abi::Rust)
+                }
+                TerminatorKind::Assert { .. } | TerminatorKind::FalseUnwind { .. } => {
                     layout::fn_can_unwind(tcx, CodegenFnAttrFlags::empty(), Abi::Rust)
                 }
                 _ => continue,
diff --git a/compiler/rustc_mir/src/transform/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs
index 12ee6bb4c67..cd6b671a0db 100644
--- a/compiler/rustc_mir/src/transform/add_call_guards.rs
+++ b/compiler/rustc_mir_transform/src/add_call_guards.rs
@@ -1,4 +1,4 @@
-use crate::transform::MirPass;
+use crate::MirPass;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
diff --git a/compiler/rustc_mir/src/transform/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
index 417e0a51aec..9eaf2b6a211 100644
--- a/compiler/rustc_mir/src/transform/add_moves_for_packed_drops.rs
+++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
@@ -1,9 +1,9 @@
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
-use crate::transform::MirPass;
 use crate::util;
-use crate::util::patch::MirPatch;
+use crate::MirPass;
+use rustc_middle::mir::patch::MirPatch;
 
 // This pass moves values being dropped that are within a packed
 // struct to a separate local before dropping them, to ensure that
diff --git a/compiler/rustc_mir/src/transform/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs
index cb608819ea8..7a8dee09c29 100644
--- a/compiler/rustc_mir/src/transform/add_retag.rs
+++ b/compiler/rustc_mir_transform/src/add_retag.rs
@@ -4,7 +4,7 @@
 //! of MIR building, and only after this pass we think of the program has having the
 //! normal MIR semantics.
 
-use crate::transform::MirPass;
+use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
diff --git a/compiler/rustc_mir/src/transform/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
index e2d50ba034a..27fe80a456f 100644
--- a/compiler/rustc_mir/src/transform/check_const_item_mutation.rs
+++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
@@ -6,7 +6,7 @@ use rustc_middle::ty::TyCtxt;
 use rustc_session::lint::builtin::CONST_ITEM_MUTATION;
 use rustc_span::def_id::DefId;
 
-use crate::transform::MirPass;
+use crate::MirPass;
 
 pub struct CheckConstItemMutation;
 
diff --git a/compiler/rustc_mir/src/transform/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs
index 13b7221046b..49be34c7a28 100644
--- a/compiler/rustc_mir/src/transform/check_packed_ref.rs
+++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs
@@ -6,8 +6,8 @@ use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint::builtin::UNALIGNED_REFERENCES;
 use rustc_span::symbol::sym;
 
-use crate::transform::MirPass;
 use crate::util;
+use crate::MirPass;
 
 pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers { unsafe_derive_on_repr_packed, ..*providers };
diff --git a/compiler/rustc_mir/src/transform/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index 1ff9bd15721..1ff9bd15721 100644
--- a/compiler/rustc_mir/src/transform/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
diff --git a/compiler/rustc_mir/src/transform/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
index 8ff0fae7686..611d29a4ee2 100644
--- a/compiler/rustc_mir/src/transform/cleanup_post_borrowck.rs
+++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
@@ -18,7 +18,7 @@
 //! [`ForMatchGuard`]: rustc_middle::mir::FakeReadCause::ForMatchGuard
 //! [`Nop`]: rustc_middle::mir::StatementKind::Nop
 
-use crate::transform::MirPass;
+use crate::MirPass;
 use rustc_middle::mir::visit::MutVisitor;
 use rustc_middle::mir::{Body, BorrowKind, Location, Rvalue};
 use rustc_middle::mir::{Statement, StatementKind};
diff --git a/compiler/rustc_mir/src/transform/const_debuginfo.rs b/compiler/rustc_mir_transform/src/const_debuginfo.rs
index 3cdaf4c7dcd..b613634560f 100644
--- a/compiler/rustc_mir/src/transform/const_debuginfo.rs
+++ b/compiler/rustc_mir_transform/src/const_debuginfo.rs
@@ -9,7 +9,7 @@ use rustc_middle::{
     ty::TyCtxt,
 };
 
-use crate::transform::MirPass;
+use crate::MirPass;
 use rustc_index::{bit_set::BitSet, vec::IndexVec};
 
 pub struct ConstDebugInfo;
diff --git a/compiler/rustc_mir/src/transform/const_goto.rs b/compiler/rustc_mir_transform/src/const_goto.rs
index ba10b54c5ae..d319fdcaa6b 100644
--- a/compiler/rustc_mir/src/transform/const_goto.rs
+++ b/compiler/rustc_mir_transform/src/const_goto.rs
@@ -17,7 +17,7 @@
 //! }
 //! ```
 
-use crate::transform::MirPass;
+use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 use rustc_middle::{mir::visit::Visitor, ty::ParamEnv};
diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index 71c07be4c6d..71b3a555587 100644
--- a/compiler/rustc_mir/src/transform/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -28,13 +28,13 @@ use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout};
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits;
 
-use crate::const_eval::ConstEvalErr;
-use crate::interpret::{
+use crate::MirPass;
+use rustc_const_eval::const_eval::ConstEvalErr;
+use rustc_const_eval::interpret::{
     self, compile_time_machine, AllocId, Allocation, ConstValue, CtfeValidationMode, Frame, ImmTy,
     Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemPlace, MemoryKind, OpTy,
     Operand as InterpOperand, PlaceTy, Scalar, ScalarMaybeUninit, StackPopCleanup, StackPopUnwind,
 };
-use crate::transform::MirPass;
 
 /// The maximum number of bytes that we'll allocate space for a local or the return value.
 /// Needed for #66397, because otherwise we eval into large places and that can cause OOM or just
diff --git a/compiler/rustc_mir/src/transform/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs
index 6726b669ff2..6726b669ff2 100644
--- a/compiler/rustc_mir/src/transform/coverage/counters.rs
+++ b/compiler/rustc_mir_transform/src/coverage/counters.rs
diff --git a/compiler/rustc_mir/src/transform/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs
index 464079656f9..513a85b5913 100644
--- a/compiler/rustc_mir/src/transform/coverage/debug.rs
+++ b/compiler/rustc_mir_transform/src/coverage/debug.rs
@@ -44,7 +44,7 @@
 //! points, which can be enabled via environment variable:
 //!
 //! ```shell
-//! RUSTC_LOG=rustc_mir::transform::coverage=debug
+//! RUSTC_LOG=rustc_mir_transform::transform::coverage=debug
 //! ```
 //!
 //! Other module paths with coverage-related debug logs may also be of interest, particularly for
@@ -52,7 +52,7 @@
 //! code generation pass). For example:
 //!
 //! ```shell
-//! RUSTC_LOG=rustc_mir::transform::coverage,rustc_codegen_ssa::coverageinfo,rustc_codegen_llvm::coverageinfo=debug
+//! RUSTC_LOG=rustc_mir_transform::transform::coverage,rustc_codegen_ssa::coverageinfo,rustc_codegen_llvm::coverageinfo=debug
 //! ```
 //!
 //! Coverage Debug Options
@@ -111,9 +111,9 @@
 use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph};
 use super::spans::CoverageSpan;
 
-use crate::util::generic_graphviz::GraphvizWriter;
-use crate::util::pretty;
-use crate::util::spanview::{self, SpanViewable};
+use rustc_middle::mir::create_dump_file;
+use rustc_middle::mir::generic_graphviz::GraphvizWriter;
+use rustc_middle::mir::spanview::{self, SpanViewable};
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::mir::coverage::*;
@@ -181,13 +181,11 @@ impl DebugOptions {
                             }
                         };
                     }
-                    _ => {
-                        bug!(
-                            "Unsupported setting `{}` in environment variable {}",
-                            option,
-                            RUSTC_COVERAGE_DEBUG_OPTIONS
-                        )
-                    }
+                    _ => bug!(
+                        "Unsupported setting `{}` in environment variable {}",
+                        option,
+                        RUSTC_COVERAGE_DEBUG_OPTIONS
+                    ),
                 };
             }
         }
@@ -643,7 +641,7 @@ pub(super) fn dump_coverage_spanview(
     let def_id = mir_source.def_id();
 
     let span_viewables = span_viewables(tcx, mir_body, basic_coverage_blocks, &coverage_spans);
-    let mut file = pretty::create_dump_file(tcx, "html", None, pass_name, &0, mir_source)
+    let mut file = create_dump_file(tcx, "html", None, pass_name, &0, mir_source)
         .expect("Unexpected error creating MIR spanview HTML file");
     let crate_name = tcx.crate_name(def_id.krate);
     let item_name = tcx.def_path(def_id).to_filename_friendly_no_crate();
@@ -745,7 +743,7 @@ pub(super) fn dump_coverage_graphviz(
                 .join("\n  ")
         ));
     }
-    let mut file = pretty::create_dump_file(tcx, "dot", None, pass_name, &0, mir_source)
+    let mut file = create_dump_file(tcx, "dot", None, pass_name, &0, mir_source)
         .expect("Unexpected error creating BasicCoverageBlock graphviz DOT file");
     graphviz_writer
         .write_graphviz(tcx, &mut file)
diff --git a/compiler/rustc_mir/src/transform/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs
index d78ad6ce97f..d78ad6ce97f 100644
--- a/compiler/rustc_mir/src/transform/coverage/graph.rs
+++ b/compiler/rustc_mir_transform/src/coverage/graph.rs
diff --git a/compiler/rustc_mir/src/transform/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index f7fbea6ad53..b9e3c058ad7 100644
--- a/compiler/rustc_mir/src/transform/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -12,8 +12,7 @@ use counters::CoverageCounters;
 use graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph};
 use spans::{CoverageSpan, CoverageSpans};
 
-use crate::transform::MirPass;
-use crate::util::pretty;
+use crate::MirPass;
 
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::graph::WithNumNodes;
@@ -25,6 +24,7 @@ use rustc_middle::hir::map::blocks::FnLikeNode;
 use rustc_middle::ich::StableHashingContext;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::coverage::*;
+use rustc_middle::mir::dump_enabled;
 use rustc_middle::mir::{
     self, BasicBlock, BasicBlockData, Coverage, SourceInfo, Statement, StatementKind, Terminator,
     TerminatorKind,
@@ -159,7 +159,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
         let mut graphviz_data = debug::GraphvizData::new();
         let mut debug_used_expressions = debug::UsedExpressions::new();
 
-        let dump_mir = pretty::dump_enabled(tcx, self.pass_name, def_id);
+        let dump_mir = dump_enabled(tcx, self.pass_name, def_id);
         let dump_graphviz = dump_mir && tcx.sess.opts.debugging_opts.dump_mir_graphviz;
         let dump_spanview = dump_mir && tcx.sess.opts.debugging_opts.dump_mir_spanview.is_some();
 
@@ -263,7 +263,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
         }
 
         if let Err(e) = result {
-            bug!("Error processing: {:?}: {:?}", self.mir_body.source.def_id(), e)
+            bug!("Error processing: {:?}: {:?}", self.mir_body.source.def_id(), e.message)
         };
 
         // Depending on current `debug_options()`, `alert_on_unused_expressions()` could panic, so
diff --git a/compiler/rustc_mir/src/transform/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs
index 760f16eae6b..760f16eae6b 100644
--- a/compiler/rustc_mir/src/transform/coverage/query.rs
+++ b/compiler/rustc_mir_transform/src/coverage/query.rs
diff --git a/compiler/rustc_mir/src/transform/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index 08cc87ccc34..cc525a4d6b9 100644
--- a/compiler/rustc_mir/src/transform/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -1,15 +1,13 @@
 use super::debug::term_type;
 use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB};
 
-use crate::util::spanview::source_range_no_file;
-
 use rustc_data_structures::graph::WithNumNodes;
+use rustc_middle::mir::spanview::source_range_no_file;
 use rustc_middle::mir::{
     self, AggregateKind, BasicBlock, FakeReadCause, Rvalue, Statement, StatementKind, Terminator,
     TerminatorKind,
 };
 use rustc_middle::ty::TyCtxt;
-
 use rustc_span::source_map::original_sp;
 use rustc_span::{BytePos, ExpnKind, MacroKind, Span, Symbol};
 
@@ -198,7 +196,11 @@ impl CoverageSpan {
     /// body_span), returns the macro name symbol.
     pub fn visible_macro(&self, body_span: Span) -> Option<Symbol> {
         if let Some(current_macro) = self.current_macro() {
-            if self.expn_span.parent().unwrap_or_else(|| bug!("macro must have a parent")).ctxt()
+            if self
+                .expn_span
+                .parent_callsite()
+                .unwrap_or_else(|| bug!("macro must have a parent"))
+                .ctxt()
                 == body_span.ctxt()
             {
                 return Some(current_macro);
diff --git a/compiler/rustc_mir/src/transform/coverage/test_macros/Cargo.toml b/compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml
index cc93fd482b5..cc93fd482b5 100644
--- a/compiler/rustc_mir/src/transform/coverage/test_macros/Cargo.toml
+++ b/compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml
diff --git a/compiler/rustc_mir/src/transform/coverage/test_macros/src/lib.rs b/compiler/rustc_mir_transform/src/coverage/test_macros/src/lib.rs
index 3d6095d2738..3d6095d2738 100644
--- a/compiler/rustc_mir/src/transform/coverage/test_macros/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/coverage/test_macros/src/lib.rs
diff --git a/compiler/rustc_mir/src/transform/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs
index 14dd0a8b924..14dd0a8b924 100644
--- a/compiler/rustc_mir/src/transform/coverage/tests.rs
+++ b/compiler/rustc_mir_transform/src/coverage/tests.rs
diff --git a/compiler/rustc_mir/src/transform/deaggregator.rs b/compiler/rustc_mir_transform/src/deaggregator.rs
index 5bd7256c666..a5491f0ef4e 100644
--- a/compiler/rustc_mir/src/transform/deaggregator.rs
+++ b/compiler/rustc_mir_transform/src/deaggregator.rs
@@ -1,5 +1,5 @@
-use crate::transform::MirPass;
 use crate::util::expand_aggregate;
+use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
diff --git a/compiler/rustc_mir/src/transform/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs
index 912505c6598..8d2413433a9 100644
--- a/compiler/rustc_mir/src/transform/deduplicate_blocks.rs
+++ b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs
@@ -3,7 +3,7 @@
 
 use std::{collections::hash_map::Entry, hash::Hash, hash::Hasher, iter};
 
-use crate::transform::MirPass;
+use crate::MirPass;
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::mir::visit::MutVisitor;
diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 4f5a467a6ee..dd95f001423 100644
--- a/compiler/rustc_mir/src/transform/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -96,12 +96,7 @@
 //! [previous attempt]: https://github.com/rust-lang/rust/pull/47954
 //! [subsequent approach]: https://github.com/rust-lang/rust/pull/71003
 
-use crate::dataflow::impls::{MaybeInitializedLocals, MaybeLiveLocals};
-use crate::dataflow::Analysis;
-use crate::{
-    transform::MirPass,
-    util::{dump_mir, PassWhere},
-};
+use crate::MirPass;
 use itertools::Itertools;
 use rustc_data_structures::unify::{InPlaceUnificationTable, UnifyKey};
 use rustc_index::{
@@ -110,11 +105,14 @@ use rustc_index::{
 };
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
+use rustc_middle::mir::{dump_mir, PassWhere};
 use rustc_middle::mir::{
     traversal, Body, InlineAsmOperand, Local, LocalKind, Location, Operand, Place, PlaceElem,
     Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
 };
 use rustc_middle::ty::TyCtxt;
+use rustc_mir_dataflow::impls::{MaybeInitializedLocals, MaybeLiveLocals};
+use rustc_mir_dataflow::Analysis;
 
 // Empirical measurements have resulted in some observations:
 // - Running on a body with a single block and 500 locals takes barely any time
diff --git a/compiler/rustc_mir/src/transform/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs
index 5b6edf17d06..2a24e1ea8d7 100644
--- a/compiler/rustc_mir/src/transform/dump_mir.rs
+++ b/compiler/rustc_mir_transform/src/dump_mir.rs
@@ -5,9 +5,9 @@ use std::fmt;
 use std::fs::File;
 use std::io;
 
-use crate::transform::MirPass;
-use crate::util as mir_util;
+use crate::MirPass;
 use rustc_middle::mir::Body;
+use rustc_middle::mir::{dump_enabled, dump_mir, write_mir_pretty};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{OutputFilenames, OutputType};
 
@@ -39,21 +39,14 @@ pub fn on_mir_pass<'tcx>(
     body: &Body<'tcx>,
     is_after: bool,
 ) {
-    if mir_util::dump_enabled(tcx, pass_name, body.source.def_id()) {
-        mir_util::dump_mir(
-            tcx,
-            Some(pass_num),
-            pass_name,
-            &Disambiguator { is_after },
-            body,
-            |_, _| Ok(()),
-        );
+    if dump_enabled(tcx, pass_name, body.source.def_id()) {
+        dump_mir(tcx, Some(pass_num), pass_name, &Disambiguator { is_after }, body, |_, _| Ok(()));
     }
 }
 
 pub fn emit_mir(tcx: TyCtxt<'_>, outputs: &OutputFilenames) -> io::Result<()> {
     let path = outputs.path(OutputType::Mir);
     let mut f = io::BufWriter::new(File::create(&path)?);
-    mir_util::write_mir_pretty(tcx, None, &mut f)?;
+    write_mir_pretty(tcx, None, &mut f)?;
     Ok(())
 }
diff --git a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
index e507bcb0f81..d7f1ad7f696 100644
--- a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs
+++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
@@ -1,4 +1,4 @@
-use crate::{transform::MirPass, util::patch::MirPatch};
+use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{Ty, TyCtxt};
 use std::fmt::Debug;
diff --git a/compiler/rustc_mir/src/transform/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index 9b44af06b7d..b9a48197a35 100644
--- a/compiler/rustc_mir/src/transform/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -1,18 +1,17 @@
-use crate::dataflow;
-use crate::dataflow::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
-use crate::dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
-use crate::dataflow::on_lookup_result_bits;
-use crate::dataflow::MoveDataParamEnv;
-use crate::dataflow::{on_all_children_bits, on_all_drop_children_bits};
-use crate::dataflow::{Analysis, ResultsCursor};
-use crate::transform::MirPass;
-use crate::util::elaborate_drops::{elaborate_drop, DropFlagState, Unwind};
-use crate::util::elaborate_drops::{DropElaborator, DropFlagMode, DropStyle};
-use crate::util::patch::MirPatch;
+use crate::MirPass;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_index::bit_set::BitSet;
+use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_mir_dataflow::elaborate_drops::{elaborate_drop, DropFlagState, Unwind};
+use rustc_mir_dataflow::elaborate_drops::{DropElaborator, DropFlagMode, DropStyle};
+use rustc_mir_dataflow::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces};
+use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
+use rustc_mir_dataflow::on_lookup_result_bits;
+use rustc_mir_dataflow::MoveDataParamEnv;
+use rustc_mir_dataflow::{on_all_children_bits, on_all_drop_children_bits};
+use rustc_mir_dataflow::{Analysis, ResultsCursor};
 use rustc_span::Span;
 use rustc_target::abi::VariantIdx;
 use std::fmt;
@@ -214,14 +213,14 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> {
     }
 
     fn field_subpath(&self, path: Self::Path, field: Field) -> Option<Self::Path> {
-        dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e {
+        rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e {
             ProjectionElem::Field(idx, _) => idx == field,
             _ => false,
         })
     }
 
     fn array_subpath(&self, path: Self::Path, index: u64, size: u64) -> Option<Self::Path> {
-        dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e {
+        rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e {
             ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
                 debug_assert!(size == min_length, "min_length should be exact for arrays");
                 assert!(!from_end, "from_end should not be used for array element ConstantIndex");
@@ -232,13 +231,13 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> {
     }
 
     fn deref_subpath(&self, path: Self::Path) -> Option<Self::Path> {
-        dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| {
+        rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| {
             e == ProjectionElem::Deref
         })
     }
 
     fn downcast_subpath(&self, path: Self::Path, variant: VariantIdx) -> Option<Self::Path> {
-        dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e {
+        rustc_mir_dataflow::move_path_children_matching(self.ctxt.move_data(), path, |e| match e {
             ProjectionElem::Downcast(_, idx) => idx == variant,
             _ => false,
         })
@@ -513,9 +512,14 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
 
     fn drop_flags_for_args(&mut self) {
         let loc = Location::START;
-        dataflow::drop_flag_effects_for_function_entry(self.tcx, self.body, self.env, |path, ds| {
-            self.set_drop_flag(loc, path, ds);
-        })
+        rustc_mir_dataflow::drop_flag_effects_for_function_entry(
+            self.tcx,
+            self.body,
+            self.env,
+            |path, ds| {
+                self.set_drop_flag(loc, path, ds);
+            },
+        )
     }
 
     fn drop_flags_for_locs(&mut self) {
@@ -556,7 +560,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                     }
                 }
                 let loc = Location { block: bb, statement_index: i };
-                dataflow::drop_flag_effects_for_location(
+                rustc_mir_dataflow::drop_flag_effects_for_location(
                     self.tcx,
                     self.body,
                     self.env,
diff --git a/compiler/rustc_mir/src/transform/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index ba2c91a9347..d96a067fdda 100644
--- a/compiler/rustc_mir/src/transform/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -11,7 +11,7 @@ use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES;
 use rustc_span::{symbol::sym, Span};
 use rustc_target::spec::abi::Abi;
 
-use crate::transform::MirPass;
+use crate::MirPass;
 
 pub struct FunctionItemReferences;
 
diff --git a/compiler/rustc_mir/src/transform/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index acdaa5b4568..06366b6fc31 100644
--- a/compiler/rustc_mir/src/transform/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -49,25 +49,25 @@
 //! For generators with state 1 (returned) and state 2 (poisoned) it does nothing.
 //! Otherwise it drops all the values in scope at the last suspension point.
 
-use crate::dataflow::impls::{
-    MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive,
-};
-use crate::dataflow::{self, Analysis};
-use crate::transform::simplify;
-use crate::transform::MirPass;
-use crate::util::dump_mir;
+use crate::simplify;
 use crate::util::expand_aggregate;
-use crate::util::storage;
+use crate::MirPass;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::bit_set::{BitMatrix, BitSet};
 use rustc_index::vec::{Idx, IndexVec};
+use rustc_middle::mir::dump_mir;
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::subst::{Subst, SubstsRef};
 use rustc_middle::ty::GeneratorSubsts;
 use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
+use rustc_mir_dataflow::impls::{
+    MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive,
+};
+use rustc_mir_dataflow::storage;
+use rustc_mir_dataflow::{self, Analysis};
 use rustc_target::abi::VariantIdx;
 use rustc_target::spec::PanicStrategy;
 use std::{iter, ops};
@@ -468,7 +468,7 @@ fn locals_live_across_suspend_points(
         .iterate_to_fixpoint();
 
     let mut borrowed_locals_cursor =
-        dataflow::ResultsCursor::new(body_ref, &borrowed_locals_results);
+        rustc_mir_dataflow::ResultsCursor::new(body_ref, &borrowed_locals_results);
 
     // Calculate the MIR locals that we actually need to keep storage around
     // for.
@@ -476,7 +476,7 @@ fn locals_live_across_suspend_points(
         .into_engine(tcx, body_ref)
         .iterate_to_fixpoint();
     let mut requires_storage_cursor =
-        dataflow::ResultsCursor::new(body_ref, &requires_storage_results);
+        rustc_mir_dataflow::ResultsCursor::new(body_ref, &requires_storage_results);
 
     // Calculate the liveness of MIR locals ignoring borrows.
     let mut liveness = MaybeLiveLocals
@@ -616,7 +616,7 @@ fn compute_storage_conflicts(
     body: &'mir Body<'tcx>,
     saved_locals: &GeneratorSavedLocals,
     always_live_locals: storage::AlwaysLiveLocals,
-    requires_storage: dataflow::Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>,
+    requires_storage: rustc_mir_dataflow::Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>,
 ) -> BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal> {
     assert_eq!(body.local_decls.len(), saved_locals.domain_size());
 
@@ -671,7 +671,7 @@ struct StorageConflictVisitor<'mir, 'tcx, 's> {
     local_conflicts: BitMatrix<Local, Local>,
 }
 
-impl dataflow::ResultsVisitor<'mir, 'tcx> for StorageConflictVisitor<'mir, 'tcx, '_> {
+impl rustc_mir_dataflow::ResultsVisitor<'mir, 'tcx> for StorageConflictVisitor<'mir, 'tcx, '_> {
     type FlowState = BitSet<Local>;
 
     fn visit_statement_before_primary_effect(
@@ -865,8 +865,8 @@ fn insert_switch<'tcx>(
 
 fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     use crate::shim::DropShimElaborator;
-    use crate::util::elaborate_drops::{elaborate_drop, Unwind};
-    use crate::util::patch::MirPatch;
+    use rustc_middle::mir::patch::MirPatch;
+    use rustc_mir_dataflow::elaborate_drops::{elaborate_drop, Unwind};
 
     // Note that `elaborate_drops` only drops the upvars of a generator, and
     // this is ok because `open_drop` can only be reached within that own
diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 8e9da31eba1..d43528a1cf0 100644
--- a/compiler/rustc_mir/src/transform/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -13,7 +13,7 @@ use rustc_span::{hygiene::ExpnKind, ExpnData, Span};
 use rustc_target::spec::abi::Abi;
 
 use super::simplify::{remove_dead_blocks, CfgSimplifier};
-use crate::transform::MirPass;
+use crate::MirPass;
 use std::iter;
 use std::ops::{Range, RangeFrom};
 
diff --git a/compiler/rustc_mir/src/transform/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs
index 385394ba67d..385394ba67d 100644
--- a/compiler/rustc_mir/src/transform/inline/cycle.rs
+++ b/compiler/rustc_mir_transform/src/inline/cycle.rs
diff --git a/compiler/rustc_mir/src/transform/instcombine.rs b/compiler/rustc_mir_transform/src/instcombine.rs
index 805f546104c..e15a69c95ae 100644
--- a/compiler/rustc_mir/src/transform/instcombine.rs
+++ b/compiler/rustc_mir_transform/src/instcombine.rs
@@ -1,6 +1,6 @@
 //! Performs various peephole optimizations.
 
-use crate::transform::MirPass;
+use crate::MirPass;
 use rustc_hir::Mutability;
 use rustc_middle::mir::{
     BinOp, Body, Constant, LocalDecls, Operand, Place, ProjectionElem, Rvalue, SourceInfo,
diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir_transform/src/lib.rs
index d4c2456e9a4..bfd0de85438 100644
--- a/compiler/rustc_mir/src/transform/mod.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -1,5 +1,25 @@
-use crate::{shim, util};
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+#![feature(crate_visibility_modifier)]
+#![feature(const_panic)]
+#![feature(in_band_lifetimes)]
+#![feature(iter_zip)]
+#![feature(map_try_insert)]
+#![feature(min_specialization)]
+#![feature(option_get_or_insert_default)]
+#![feature(once_cell)]
+#![feature(never_type)]
+#![feature(trusted_step)]
+#![feature(try_blocks)]
+#![recursion_limit = "256"]
+
+#[macro_use]
+extern crate tracing;
+#[macro_use]
+extern crate rustc_middle;
+
 use required_consts::RequiredConstsVisitor;
+use rustc_const_eval::util;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::steal::Steal;
 use rustc_hir as hir;
@@ -11,57 +31,59 @@ use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPhase, Promoted};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
 use rustc_span::{Span, Symbol};
-use std::borrow::Cow;
-
-pub mod abort_unwinding_calls;
-pub mod add_call_guards;
-pub mod add_moves_for_packed_drops;
-pub mod add_retag;
-pub mod check_const_item_mutation;
-pub mod check_consts;
-pub mod check_packed_ref;
+
+mod abort_unwinding_calls;
+mod add_call_guards;
+mod add_moves_for_packed_drops;
+mod add_retag;
+mod check_const_item_mutation;
+mod check_packed_ref;
 pub mod check_unsafety;
-pub mod cleanup_post_borrowck;
-pub mod const_debuginfo;
-pub mod const_goto;
-pub mod const_prop;
-pub mod coverage;
-pub mod deaggregator;
-pub mod deduplicate_blocks;
-pub mod dest_prop;
+mod cleanup_post_borrowck;
+mod const_debuginfo;
+mod const_goto;
+mod const_prop;
+mod coverage;
+mod deaggregator;
+mod deduplicate_blocks;
+mod dest_prop;
 pub mod dump_mir;
-pub mod early_otherwise_branch;
-pub mod elaborate_drops;
-pub mod function_item_references;
-pub mod generator;
-pub mod inline;
-pub mod instcombine;
-pub mod lower_intrinsics;
-pub mod lower_slice_len;
-pub mod match_branches;
-pub mod multiple_return_terminators;
-pub mod nrvo;
-pub mod promote_consts;
-pub mod remove_noop_landing_pads;
-pub mod remove_storage_markers;
-pub mod remove_unneeded_drops;
-pub mod remove_zsts;
-pub mod required_consts;
-pub mod rustc_peek;
-pub mod separate_const_switch;
-pub mod simplify;
-pub mod simplify_branches;
-pub mod simplify_comparison_integral;
-pub mod simplify_try;
-pub mod uninhabited_enum_branching;
-pub mod unreachable_prop;
-pub mod validate;
-
-pub use rustc_middle::mir::MirSource;
-
-pub(crate) fn provide(providers: &mut Providers) {
-    self::check_unsafety::provide(providers);
-    self::check_packed_ref::provide(providers);
+mod early_otherwise_branch;
+mod elaborate_drops;
+mod function_item_references;
+mod generator;
+mod inline;
+mod instcombine;
+mod lower_intrinsics;
+mod lower_slice_len;
+mod match_branches;
+mod multiple_return_terminators;
+mod nrvo;
+mod remove_noop_landing_pads;
+mod remove_storage_markers;
+mod remove_unneeded_drops;
+mod remove_zsts;
+mod required_consts;
+mod separate_const_switch;
+mod shim;
+mod simplify;
+mod simplify_branches;
+mod simplify_comparison_integral;
+mod simplify_try;
+mod uninhabited_enum_branching;
+mod unreachable_prop;
+
+use rustc_const_eval::transform::check_consts;
+use rustc_const_eval::transform::promote_consts;
+use rustc_const_eval::transform::validate;
+pub use rustc_const_eval::transform::MirPass;
+use rustc_mir_dataflow::rustc_peek;
+
+pub fn provide(providers: &mut Providers) {
+    check_unsafety::provide(providers);
+    check_packed_ref::provide(providers);
+    coverage::query::provide(providers);
+    shim::provide(providers);
     *providers = Providers {
         mir_keys,
         mir_const,
@@ -83,6 +105,8 @@ pub(crate) fn provide(providers: &mut Providers) {
         optimized_mir,
         is_mir_available,
         is_ctfe_mir_available: |tcx, did| is_mir_available(tcx, did),
+        mir_callgraph_reachable: inline::cycle::mir_callgraph_reachable,
+        mir_inliner_callees: inline::cycle::mir_inliner_callees,
         promoted_mir: |tcx, def_id| {
             let def_id = def_id.expect_local();
             if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
@@ -96,7 +120,6 @@ pub(crate) fn provide(providers: &mut Providers) {
         },
         ..*providers
     };
-    coverage::query::provide(providers);
 }
 
 fn is_mir_available(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
@@ -144,25 +167,7 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxHashSet<LocalDefId> {
     set
 }
 
-/// Generates a default name for the pass based on the name of the
-/// type `T`.
-pub fn default_name<T: ?Sized>() -> Cow<'static, str> {
-    let name = std::any::type_name::<T>();
-    if let Some(tail) = name.rfind(':') { Cow::from(&name[tail + 1..]) } else { Cow::from(name) }
-}
-
-/// A streamlined trait that you can implement to create a pass; the
-/// pass will be named after the type, and it will consist of a main
-/// loop that goes over each available MIR and applies `run_pass`.
-pub trait MirPass<'tcx> {
-    fn name(&self) -> Cow<'_, str> {
-        default_name::<Self>()
-    }
-
-    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>);
-}
-
-pub fn run_passes(
+fn run_passes(
     tcx: TyCtxt<'tcx>,
     body: &mut Body<'tcx>,
     mir_phase: MirPhase,
@@ -269,7 +274,7 @@ fn mir_const<'tcx>(
 
     let mut body = tcx.mir_built(def).steal();
 
-    util::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(()));
+    rustc_middle::mir::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(()));
 
     run_passes(
         tcx,
@@ -301,7 +306,6 @@ fn mir_promoted(
     // this point, before we steal the mir-const result.
     // Also this means promotion can rely on all const checks having been done.
     let _ = tcx.mir_const_qualif_opt_const_arg(def);
-    let _ = tcx.mir_abstract_const_opt_const_arg(def.to_global());
     let mut body = tcx.mir_const(def).steal();
 
     let mut required_consts = Vec::new();
diff --git a/compiler/rustc_mir/src/transform/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index e9f1d4f2ce8..5848163af72 100644
--- a/compiler/rustc_mir/src/transform/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -1,6 +1,6 @@
 //! Lowers intrinsic calls
 
-use crate::transform::MirPass;
+use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -92,14 +92,19 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                         // since their semantics depend on the value of overflow-checks flag used
                         // during codegen. Issue #35310.
                     }
-                    sym::size_of => {
+                    sym::size_of | sym::min_align_of => {
                         if let Some((destination, target)) = *destination {
                             let tp_ty = substs.type_at(0);
+                            let null_op = match intrinsic_name {
+                                sym::size_of => NullOp::SizeOf,
+                                sym::min_align_of => NullOp::AlignOf,
+                                _ => bug!("unexpected intrinsic"),
+                            };
                             block.statements.push(Statement {
                                 source_info: terminator.source_info,
                                 kind: StatementKind::Assign(Box::new((
                                     destination,
-                                    Rvalue::NullaryOp(NullOp::SizeOf, tp_ty),
+                                    Rvalue::NullaryOp(null_op, tp_ty),
                                 ))),
                             });
                             terminator.kind = TerminatorKind::Goto { target };
diff --git a/compiler/rustc_mir/src/transform/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs
index c3eb2d9f921..a2cce9f1eda 100644
--- a/compiler/rustc_mir/src/transform/lower_slice_len.rs
+++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs
@@ -1,7 +1,7 @@
 //! This pass lowers calls to core::slice::len to just Len op.
 //! It should run before inlining!
 
-use crate::transform::MirPass;
+use crate::MirPass;
 use rustc_hir::def_id::DefId;
 use rustc_index::vec::IndexVec;
 use rustc_middle::mir::*;
@@ -75,13 +75,11 @@ fn lower_slice_len_call<'tcx>(
                     let deref_arg = tcx.mk_place_deref(arg);
                     let r_value = Rvalue::Len(deref_arg);
                     let len_statement_kind = StatementKind::Assign(Box::new((*dest, r_value)));
-                    let add_statement = Statement {
-                        kind: len_statement_kind,
-                        source_info: terminator.source_info.clone(),
-                    };
+                    let add_statement =
+                        Statement { kind: len_statement_kind, source_info: terminator.source_info };
 
                     // modify terminator into simple Goto
-                    let new_terminator_kind = TerminatorKind::Goto { target: bb.clone() };
+                    let new_terminator_kind = TerminatorKind::Goto { target: *bb };
 
                     let patch = SliceLenPatchInformation { add_statement, new_terminator_kind };
 
diff --git a/compiler/rustc_mir/src/transform/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs
index 37a3fa50a52..c618abe9d05 100644
--- a/compiler/rustc_mir/src/transform/match_branches.rs
+++ b/compiler/rustc_mir_transform/src/match_branches.rs
@@ -1,4 +1,4 @@
-use crate::transform::MirPass;
+use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 use std::iter;
@@ -134,7 +134,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
                             let const_cmp = Operand::const_from_scalar(
                                 tcx,
                                 switch_ty,
-                                crate::interpret::Scalar::from_uint(val, size),
+                                rustc_const_eval::interpret::Scalar::from_uint(val, size),
                                 rustc_span::DUMMY_SP,
                             );
                             let op = if f_b { BinOp::Eq } else { BinOp::Ne };
diff --git a/compiler/rustc_mir/src/transform/multiple_return_terminators.rs b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs
index cd2db180552..b614917a883 100644
--- a/compiler/rustc_mir/src/transform/multiple_return_terminators.rs
+++ b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs
@@ -1,7 +1,7 @@
 //! This pass removes jumps to basic blocks containing only a return, and replaces them with a
 //! return instead.
 
-use crate::transform::{simplify, MirPass};
+use crate::{simplify, MirPass};
 use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
diff --git a/compiler/rustc_mir/src/transform/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs
index 445dc12909c..3ac4e77cf9a 100644
--- a/compiler/rustc_mir/src/transform/nrvo.rs
+++ b/compiler/rustc_mir_transform/src/nrvo.rs
@@ -6,7 +6,7 @@ use rustc_middle::mir::visit::{MutVisitor, NonUseContext, PlaceContext, Visitor}
 use rustc_middle::mir::{self, BasicBlock, Local, Location};
 use rustc_middle::ty::TyCtxt;
 
-use crate::transform::MirPass;
+use crate::MirPass;
 
 /// This pass looks for MIR that always copies the same local into the return place and eliminates
 /// the copy by renaming all uses of that local to `_0`.
diff --git a/compiler/rustc_mir/src/transform/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
index 5347846a4b3..298bcd9dc24 100644
--- a/compiler/rustc_mir/src/transform/remove_noop_landing_pads.rs
+++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
@@ -1,6 +1,6 @@
-use crate::transform::MirPass;
-use crate::util::patch::MirPatch;
+use crate::MirPass;
 use rustc_index::bit_set::BitSet;
+use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 use rustc_target::spec::PanicStrategy;
diff --git a/compiler/rustc_mir/src/transform/remove_storage_markers.rs b/compiler/rustc_mir_transform/src/remove_storage_markers.rs
index 2d529feb072..0c7323cbac5 100644
--- a/compiler/rustc_mir/src/transform/remove_storage_markers.rs
+++ b/compiler/rustc_mir_transform/src/remove_storage_markers.rs
@@ -1,6 +1,6 @@
 //! This pass removes storage markers if they won't be emitted during codegen.
 
-use crate::transform::MirPass;
+use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
diff --git a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
index 02e45021a0a..5c9d04a08bf 100644
--- a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
@@ -1,6 +1,6 @@
 //! This pass replaces a drop of a type that does not need dropping, with a goto
 
-use crate::transform::MirPass;
+use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
diff --git a/compiler/rustc_mir/src/transform/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs
index 03277b1b2e0..d93ffa38c69 100644
--- a/compiler/rustc_mir/src/transform/remove_zsts.rs
+++ b/compiler/rustc_mir_transform/src/remove_zsts.rs
@@ -1,6 +1,6 @@
 //! Removes assignments to ZST places.
 
-use crate::transform::MirPass;
+use crate::MirPass;
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::{Body, LocalDecls, Place, StatementKind};
 use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -9,6 +9,10 @@ pub struct RemoveZsts;
 
 impl<'tcx> MirPass<'tcx> for RemoveZsts {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        // Avoid query cycles (generators require optimized MIR for layout).
+        if tcx.type_of(body.source.def_id()).is_generator() {
+            return;
+        }
         let param_env = tcx.param_env(body.source.def_id());
         let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
         for block in basic_blocks.iter_mut() {
diff --git a/compiler/rustc_mir/src/transform/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs
index 8b64ad65ab3..8b64ad65ab3 100644
--- a/compiler/rustc_mir/src/transform/required_consts.rs
+++ b/compiler/rustc_mir_transform/src/required_consts.rs
diff --git a/compiler/rustc_mir/src/transform/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs
index 87cd27984a0..1945e551485 100644
--- a/compiler/rustc_mir/src/transform/separate_const_switch.rs
+++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs
@@ -37,7 +37,7 @@
 //! simplicity rather than completeness (it notably
 //! sometimes duplicates abusively).
 
-use crate::transform::MirPass;
+use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 use smallvec::SmallVec;
diff --git a/compiler/rustc_mir/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 8083ec95447..4d350fc87cb 100644
--- a/compiler/rustc_mir/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -15,13 +15,13 @@ use rustc_target::spec::abi::Abi;
 use std::fmt;
 use std::iter;
 
-use crate::transform::{
+use crate::util::expand_aggregate;
+use crate::{
     abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, remove_noop_landing_pads,
     run_passes, simplify,
 };
-use crate::util::elaborate_drops::{self, DropElaborator, DropFlagMode, DropStyle};
-use crate::util::expand_aggregate;
-use crate::util::patch::MirPatch;
+use rustc_middle::mir::patch::MirPatch;
+use rustc_mir_dataflow::elaborate_drops::{self, DropElaborator, DropFlagMode, DropStyle};
 
 pub fn provide(providers: &mut Providers) {
     providers.mir_shims = make_shim;
@@ -940,7 +940,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
         span,
     );
 
-    crate::util::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(()));
+    rustc_middle::mir::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(()));
 
     body
 }
diff --git a/compiler/rustc_mir/src/transform/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index 3ecb5133e3b..e3cfd1d0afc 100644
--- a/compiler/rustc_mir/src/transform/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -27,7 +27,7 @@
 //! naively generate still contains the `_a = ()` write in the unreachable block "after" the
 //! return.
 
-use crate::transform::MirPass;
+use crate::MirPass;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::mir::coverage::*;
 use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
diff --git a/compiler/rustc_mir/src/transform/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs
index a9a45e61a38..df90cfa318d 100644
--- a/compiler/rustc_mir/src/transform/simplify_branches.rs
+++ b/compiler/rustc_mir_transform/src/simplify_branches.rs
@@ -1,6 +1,6 @@
 //! A pass that simplifies branches when their condition is known.
 
-use crate::transform::MirPass;
+use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
diff --git a/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
index 948fcd9f455..948fcd9f455 100644
--- a/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs
+++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
diff --git a/compiler/rustc_mir/src/transform/simplify_try.rs b/compiler/rustc_mir_transform/src/simplify_try.rs
index 7c35dab694f..fd36671b36f 100644
--- a/compiler/rustc_mir/src/transform/simplify_try.rs
+++ b/compiler/rustc_mir_transform/src/simplify_try.rs
@@ -9,7 +9,7 @@
 //!
 //! into just `x`.
 
-use crate::transform::{simplify, MirPass};
+use crate::{simplify, MirPass};
 use itertools::Itertools as _;
 use rustc_index::{bit_set::BitSet, vec::IndexVec};
 use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
diff --git a/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
index 5c6c158d46e..5cef64d7786 100644
--- a/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs
+++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
@@ -1,6 +1,6 @@
 //! A pass that eliminates branches on uninhabited enum variants.
 
-use crate::transform::MirPass;
+use crate::MirPass;
 use rustc_data_structures::stable_set::FxHashSet;
 use rustc_middle::mir::{
     BasicBlock, BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, SwitchTargets,
diff --git a/compiler/rustc_mir/src/transform/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs
index e7fb6b4f6b4..baf381081dd 100644
--- a/compiler/rustc_mir/src/transform/unreachable_prop.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs
@@ -2,8 +2,8 @@
 //! when all of their successors are unreachable. This is achieved through a
 //! post-order traversal of the blocks.
 
-use crate::transform::simplify;
-use crate::transform::MirPass;
+use crate::simplify;
+use crate::MirPass;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml
new file mode 100644
index 00000000000..350ae088777
--- /dev/null
+++ b/compiler/rustc_monomorphize/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+name = "rustc_monomorphize"
+version = "0.0.0"
+edition = "2018"
+
+[lib]
+doctest = false
+
+[dependencies]
+smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+tracing = "0.1"
+rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_errors = { path = "../rustc_errors" }
+rustc_hir = { path = "../rustc_hir" }
+rustc_index = { path = "../rustc_index" }
+rustc_middle = { path = "../rustc_middle" }
+rustc_session = { path = "../rustc_session" }
+rustc_span = { path = "../rustc_span" }
+rustc_target = { path = "../rustc_target" }
diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 4cb362238c1..1e39b1bd5e8 100644
--- a/compiler/rustc_mir/src/monomorphize/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -178,8 +178,6 @@
 //! this is not implemented however: a mono item will be produced
 //! regardless of whether it is actually needed or not.
 
-use crate::monomorphize;
-
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
 use rustc_errors::{ErrorReported, FatalError};
@@ -1052,7 +1050,7 @@ fn find_vtable_types_for_unsizing<'tcx>(
             assert_eq!(source_adt_def, target_adt_def);
 
             let CustomCoerceUnsized::Struct(coerce_index) =
-                monomorphize::custom_coerce_unsize_info(tcx, source_ty, target_ty);
+                crate::custom_coerce_unsize_info(tcx, source_ty, target_ty);
 
             let source_fields = &source_adt_def.non_enum_variant().fields;
             let target_fields = &target_adt_def.non_enum_variant().fields;
@@ -1085,7 +1083,7 @@ fn create_fn_mono_item<'tcx>(
     let def_id = instance.def_id();
     if tcx.sess.opts.debugging_opts.profile_closures && def_id.is_local() && tcx.is_closure(def_id)
     {
-        monomorphize::util::dump_closure_profile(tcx, instance);
+        crate::util::dump_closure_profile(tcx, instance);
     }
 
     respan(source, MonoItem::Fn(instance.polymorphize(tcx)))
diff --git a/compiler/rustc_mir/src/monomorphize/mod.rs b/compiler/rustc_monomorphize/src/lib.rs
index 57d2723cf9c..08b1d7b7fab 100644
--- a/compiler/rustc_mir/src/monomorphize/mod.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -1,13 +1,25 @@
+#![feature(array_windows)]
+#![feature(bool_to_option)]
+#![feature(crate_visibility_modifier)]
+#![feature(control_flow_enum)]
+#![feature(in_band_lifetimes)]
+#![recursion_limit = "256"]
+
+#[macro_use]
+extern crate tracing;
+#[macro_use]
+extern crate rustc_middle;
+
+use rustc_hir::lang_items::LangItem;
 use rustc_middle::traits;
 use rustc_middle::ty::adjustment::CustomCoerceUnsized;
+use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
-use rustc_hir::lang_items::LangItem;
-
-pub mod collector;
-pub mod partitioning;
-pub mod polymorphize;
-pub mod util;
+mod collector;
+mod partitioning;
+mod polymorphize;
+mod util;
 
 fn custom_coerce_unsize_info<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -31,3 +43,8 @@ fn custom_coerce_unsize_info<'tcx>(
         }
     }
 }
+
+pub fn provide(providers: &mut Providers) {
+    partitioning::provide(providers);
+    polymorphize::provide(providers);
+}
diff --git a/compiler/rustc_mir/src/monomorphize/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs
index a559a6ce415..429ed53d379 100644
--- a/compiler/rustc_mir/src/monomorphize/partitioning/default.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/default.rs
@@ -13,9 +13,9 @@ use rustc_middle::ty::{self, DefIdTree, InstanceDef, TyCtxt};
 use rustc_span::symbol::Symbol;
 
 use super::PartitioningCx;
-use crate::monomorphize::collector::InliningMap;
-use crate::monomorphize::partitioning::merging;
-use crate::monomorphize::partitioning::{
+use crate::collector::InliningMap;
+use crate::partitioning::merging;
+use crate::partitioning::{
     MonoItemPlacement, Partitioner, PostInliningPartitioning, PreInliningPartitioning,
 };
 
diff --git a/compiler/rustc_mir/src/monomorphize/partitioning/merging.rs b/compiler/rustc_monomorphize/src/partitioning/merging.rs
index cbe36665790..229468b47ff 100644
--- a/compiler/rustc_mir/src/monomorphize/partitioning/merging.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/merging.rs
@@ -6,7 +6,7 @@ use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder};
 use rustc_span::symbol::{Symbol, SymbolStr};
 
 use super::PartitioningCx;
-use crate::monomorphize::partitioning::PreInliningPartitioning;
+use crate::partitioning::PreInliningPartitioning;
 
 pub fn merge_codegen_units<'tcx>(
     cx: &PartitioningCx<'_, 'tcx>,
diff --git a/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs
index 6ed0ab8be41..7a7a56a034e 100644
--- a/compiler/rustc_mir/src/monomorphize/partitioning/mod.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs
@@ -105,8 +105,8 @@ use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::Symbol;
 
-use crate::monomorphize::collector::InliningMap;
-use crate::monomorphize::collector::{self, MonoItemCollectionMode};
+use crate::collector::InliningMap;
+use crate::collector::{self, MonoItemCollectionMode};
 
 pub struct PartitioningCx<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_mir/src/monomorphize/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index 3c55a4b0a8f..3c55a4b0a8f 100644
--- a/compiler/rustc_mir/src/monomorphize/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
diff --git a/compiler/rustc_mir/src/monomorphize/util.rs b/compiler/rustc_monomorphize/src/util.rs
index 799b4e18c24..799b4e18c24 100644
--- a/compiler/rustc_mir/src/monomorphize/util.rs
+++ b/compiler/rustc_monomorphize/src/util.rs
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index bf76dedd252..af41a99ada4 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -3,9 +3,7 @@
 #![feature(array_windows)]
 #![feature(crate_visibility_modifier)]
 #![feature(if_let_guard)]
-#![cfg_attr(bootstrap, feature(bindings_after_at))]
 #![feature(box_patterns)]
-#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard
 #![recursion_limit = "256"]
 
 use rustc_ast as ast;
@@ -133,7 +131,7 @@ fn maybe_source_file_to_parser(
     let mut parser = stream_to_parser(sess, stream, None);
     parser.unclosed_delims = unclosed_delims;
     if parser.token == token::Eof {
-        parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt());
+        parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt(), None);
     }
 
     Ok(parser)
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index 9f06bdcc135..568682cc3e4 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -34,7 +34,7 @@ pub struct AttrWrapper {
 
 // This struct is passed around very frequently,
 // so make sure it doesn't accidentally get larger
-#[cfg(target_arch = "x86_64")]
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 rustc_data_structures::static_assert_size!(AttrWrapper, 16);
 
 impl AttrWrapper {
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 94ca70d3f95..4fccfc287fd 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -1633,50 +1633,57 @@ impl<'a> Parser<'a> {
         {
             let rfc_note = "anonymous parameters are removed in the 2018 edition (see RFC 1685)";
 
-            let (ident, self_sugg, param_sugg, type_sugg) = match pat.kind {
-                PatKind::Ident(_, ident, _) => (
-                    ident,
-                    format!("self: {}", ident),
-                    format!("{}: TypeName", ident),
-                    format!("_: {}", ident),
-                ),
-                // Also catches `fn foo(&a)`.
-                PatKind::Ref(ref pat, mutab)
-                    if matches!(pat.clone().into_inner().kind, PatKind::Ident(..)) =>
-                {
-                    match pat.clone().into_inner().kind {
-                        PatKind::Ident(_, ident, _) => {
-                            let mutab = mutab.prefix_str();
-                            (
-                                ident,
-                                format!("self: &{}{}", mutab, ident),
-                                format!("{}: &{}TypeName", ident, mutab),
-                                format!("_: &{}{}", mutab, ident),
-                            )
+            let (ident, self_sugg, param_sugg, type_sugg, self_span, param_span, type_span) =
+                match pat.kind {
+                    PatKind::Ident(_, ident, _) => (
+                        ident,
+                        "self: ".to_string(),
+                        ": TypeName".to_string(),
+                        "_: ".to_string(),
+                        pat.span.shrink_to_lo(),
+                        pat.span.shrink_to_hi(),
+                        pat.span.shrink_to_lo(),
+                    ),
+                    // Also catches `fn foo(&a)`.
+                    PatKind::Ref(ref inner_pat, mutab)
+                        if matches!(inner_pat.clone().into_inner().kind, PatKind::Ident(..)) =>
+                    {
+                        match inner_pat.clone().into_inner().kind {
+                            PatKind::Ident(_, ident, _) => {
+                                let mutab = mutab.prefix_str();
+                                (
+                                    ident,
+                                    "self: ".to_string(),
+                                    format!("{}: &{}TypeName", ident, mutab),
+                                    "_: ".to_string(),
+                                    pat.span.shrink_to_lo(),
+                                    pat.span,
+                                    pat.span.shrink_to_lo(),
+                                )
+                            }
+                            _ => unreachable!(),
                         }
-                        _ => unreachable!(),
-                    }
-                }
-                _ => {
-                    // Otherwise, try to get a type and emit a suggestion.
-                    if let Some(ty) = pat.to_ty() {
-                        err.span_suggestion_verbose(
-                            pat.span,
-                            "explicitly ignore the parameter name",
-                            format!("_: {}", pprust::ty_to_string(&ty)),
-                            Applicability::MachineApplicable,
-                        );
-                        err.note(rfc_note);
                     }
+                    _ => {
+                        // Otherwise, try to get a type and emit a suggestion.
+                        if let Some(ty) = pat.to_ty() {
+                            err.span_suggestion_verbose(
+                                pat.span,
+                                "explicitly ignore the parameter name",
+                                format!("_: {}", pprust::ty_to_string(&ty)),
+                                Applicability::MachineApplicable,
+                            );
+                            err.note(rfc_note);
+                        }
 
-                    return None;
-                }
-            };
+                        return None;
+                    }
+                };
 
             // `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}`
             if first_param {
                 err.span_suggestion(
-                    pat.span,
+                    self_span,
                     "if this is a `self` type, give it a parameter name",
                     self_sugg,
                     Applicability::MaybeIncorrect,
@@ -1686,14 +1693,14 @@ impl<'a> Parser<'a> {
             // `fn foo(HashMap: TypeName<u32>)`.
             if self.token != token::Lt {
                 err.span_suggestion(
-                    pat.span,
+                    param_span,
                     "if this is a parameter name, give it a type",
                     param_sugg,
                     Applicability::HasPlaceholders,
                 );
             }
             err.span_suggestion(
-                pat.span,
+                type_span,
                 "if this is a type, explicitly ignore the parameter name",
                 type_sugg,
                 Applicability::MachineApplicable,
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index a1d3e9adba0..737f1d9cbb1 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1,9 +1,12 @@
 use super::pat::{RecoverColon, RecoverComma, PARAM_EXPECTED};
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
-use super::{AttrWrapper, BlockMode, ForceCollect, Parser, PathStyle, Restrictions, TokenType};
+use super::{
+    AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions, TokenType,
+};
 use super::{SemiColonMode, SeqSep, TokenExpectType, TrailingToken};
 use crate::maybe_recover_from_interpolated_ty_qpath;
 
+use ast::token::DelimToken;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Token, TokenKind};
 use rustc_ast::tokenstream::Spacing;
@@ -91,6 +94,8 @@ impl<'a> Parser<'a> {
     /// Parses an expression.
     #[inline]
     pub fn parse_expr(&mut self) -> PResult<'a, P<Expr>> {
+        self.current_closure.take();
+
         self.parse_expr_res(Restrictions::empty(), None)
     }
 
@@ -516,6 +521,26 @@ impl<'a> Parser<'a> {
             token::BinOp(token::And) | token::AndAnd => {
                 make_it!(this, attrs, |this, _| this.parse_borrow_expr(lo))
             }
+            token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => {
+                let mut err = this.struct_span_err(lo, "leading `+` is not supported");
+                err.span_label(lo, "unexpected `+`");
+
+                // a block on the LHS might have been intended to be an expression instead
+                if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) {
+                    this.sess.expr_parentheses_needed(&mut err, *sp);
+                } else {
+                    err.span_suggestion_verbose(
+                        lo,
+                        "try removing the `+`",
+                        "".to_string(),
+                        Applicability::MachineApplicable,
+                    );
+                }
+                err.emit();
+
+                this.bump();
+                this.parse_prefix_expr(None)
+            } // `+expr`
             token::Ident(..) if this.token.is_keyword(kw::Box) => {
                 make_it!(this, attrs, |this, _| this.parse_box_expr(lo))
             }
@@ -882,6 +907,12 @@ impl<'a> Parser<'a> {
         }
     }
 
+    fn look_ahead_type_ascription_as_field(&mut self) -> bool {
+        self.look_ahead(1, |t| t.is_ident())
+            && self.look_ahead(2, |t| t == &token::Colon)
+            && self.look_ahead(3, |t| t.can_begin_expr())
+    }
+
     fn parse_dot_suffix_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
         match self.token.uninterpolate().kind {
             token::Ident(..) => self.parse_dot_suffix(base, lo),
@@ -1031,12 +1062,76 @@ impl<'a> Parser<'a> {
 
     /// Parse a function call expression, `expr(...)`.
     fn parse_fn_call_expr(&mut self, lo: Span, fun: P<Expr>) -> P<Expr> {
-        let seq = self.parse_paren_expr_seq().map(|args| {
+        let snapshot = if self.token.kind == token::OpenDelim(token::Paren)
+            && self.look_ahead_type_ascription_as_field()
+        {
+            Some((self.clone(), fun.kind.clone()))
+        } else {
+            None
+        };
+        let open_paren = self.token.span;
+
+        let mut seq = self.parse_paren_expr_seq().map(|args| {
             self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args), AttrVec::new())
         });
+        if let Some(expr) =
+            self.maybe_recover_struct_lit_bad_delims(lo, open_paren, &mut seq, snapshot)
+        {
+            return expr;
+        }
         self.recover_seq_parse_error(token::Paren, lo, seq)
     }
 
+    /// If we encounter a parser state that looks like the user has written a `struct` literal with
+    /// parentheses instead of braces, recover the parser state and provide suggestions.
+    fn maybe_recover_struct_lit_bad_delims(
+        &mut self,
+        lo: Span,
+        open_paren: Span,
+        seq: &mut PResult<'a, P<Expr>>,
+        snapshot: Option<(Self, ExprKind)>,
+    ) -> Option<P<Expr>> {
+        match (seq.as_mut(), snapshot) {
+            (Err(ref mut err), Some((mut snapshot, ExprKind::Path(None, path)))) => {
+                let name = pprust::path_to_string(&path);
+                snapshot.bump(); // `(`
+                match snapshot.parse_struct_fields(path.clone(), false, token::Paren) {
+                    Ok((fields, ..)) if snapshot.eat(&token::CloseDelim(token::Paren)) => {
+                        // We have are certain we have `Enum::Foo(a: 3, b: 4)`, suggest
+                        // `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`.
+                        *self = snapshot;
+                        let close_paren = self.prev_token.span;
+                        let span = lo.to(self.prev_token.span);
+                        err.cancel();
+                        self.struct_span_err(
+                            span,
+                            "invalid `struct` delimiters or `fn` call arguments",
+                        )
+                        .multipart_suggestion(
+                            &format!("if `{}` is a struct, use braces as delimiters", name),
+                            vec![(open_paren, " { ".to_string()), (close_paren, " }".to_string())],
+                            Applicability::MaybeIncorrect,
+                        )
+                        .multipart_suggestion(
+                            &format!("if `{}` is a function, use the arguments directly", name),
+                            fields
+                                .into_iter()
+                                .map(|field| (field.span.until(field.expr.span), String::new()))
+                                .collect(),
+                            Applicability::MaybeIncorrect,
+                        )
+                        .emit();
+                        return Some(self.mk_expr_err(span));
+                    }
+                    Ok(_) => {}
+                    Err(mut err) => err.emit(),
+                }
+            }
+            _ => {}
+        }
+        None
+    }
+
     /// Parse an indexing expression `expr[...]`.
     fn parse_index_expr(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
         self.bump(); // `[`
@@ -1716,7 +1811,7 @@ impl<'a> Parser<'a> {
         let capture_clause = self.parse_capture_clause()?;
         let decl = self.parse_fn_block_decl()?;
         let decl_hi = self.prev_token.span;
-        let body = match decl.output {
+        let mut body = match decl.output {
             FnRetTy::Default(_) => {
                 let restrictions = self.restrictions - Restrictions::STMT_EXPR;
                 self.parse_expr_res(restrictions, None)?
@@ -1733,11 +1828,28 @@ impl<'a> Parser<'a> {
             self.sess.gated_spans.gate(sym::async_closure, span);
         }
 
-        Ok(self.mk_expr(
+        if self.token.kind == TokenKind::Semi && self.token_cursor.frame.delim == DelimToken::Paren
+        {
+            // It is likely that the closure body is a block but where the
+            // braces have been removed. We will recover and eat the next
+            // statements later in the parsing process.
+            body = self.mk_expr_err(body.span);
+        }
+
+        let body_span = body.span;
+
+        let closure = self.mk_expr(
             lo.to(body.span),
             ExprKind::Closure(capture_clause, asyncness, movability, decl, body, lo.to(decl_hi)),
             attrs,
-        ))
+        );
+
+        // Disable recovery for closure body
+        let spans =
+            ClosureSpans { whole_closure: closure.span, closing_pipe: decl_hi, body: body_span };
+        self.current_closure = Some(spans);
+
+        Ok(closure)
     }
 
     /// Parses an optional `move` prefix to a closure-like construct.
@@ -2332,14 +2444,12 @@ impl<'a> Parser<'a> {
             .emit();
     }
 
-    /// Precondition: already parsed the '{'.
-    pub(super) fn parse_struct_expr(
+    pub(super) fn parse_struct_fields(
         &mut self,
-        qself: Option<ast::QSelf>,
         pth: ast::Path,
-        attrs: AttrVec,
         recover: bool,
-    ) -> PResult<'a, P<Expr>> {
+        close_delim: token::DelimToken,
+    ) -> PResult<'a, (Vec<ExprField>, ast::StructRest, bool)> {
         let mut fields = Vec::new();
         let mut base = ast::StructRest::None;
         let mut recover_async = false;
@@ -2351,11 +2461,11 @@ impl<'a> Parser<'a> {
             e.note("for more on editions, read https://doc.rust-lang.org/edition-guide");
         };
 
-        while self.token != token::CloseDelim(token::Brace) {
+        while self.token != token::CloseDelim(close_delim) {
             if self.eat(&token::DotDot) {
                 let exp_span = self.prev_token.span;
                 // We permit `.. }` on the left-hand side of a destructuring assignment.
-                if self.check(&token::CloseDelim(token::Brace)) {
+                if self.check(&token::CloseDelim(close_delim)) {
                     self.sess.gated_spans.gate(sym::destructuring_assignment, self.prev_token.span);
                     base = ast::StructRest::Rest(self.prev_token.span.shrink_to_hi());
                     break;
@@ -2396,7 +2506,7 @@ impl<'a> Parser<'a> {
                 }
             };
 
-            match self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)]) {
+            match self.expect_one_of(&[token::Comma], &[token::CloseDelim(close_delim)]) {
                 Ok(_) => {
                     if let Some(f) = parsed_field.or(recovery_field) {
                         // Only include the field if there's no parse error for the field name.
@@ -2427,8 +2537,21 @@ impl<'a> Parser<'a> {
                 }
             }
         }
+        Ok((fields, base, recover_async))
+    }
 
-        let span = pth.span.to(self.token.span);
+    /// Precondition: already parsed the '{'.
+    pub(super) fn parse_struct_expr(
+        &mut self,
+        qself: Option<ast::QSelf>,
+        pth: ast::Path,
+        attrs: AttrVec,
+        recover: bool,
+    ) -> PResult<'a, P<Expr>> {
+        let lo = pth.span;
+        let (fields, base, recover_async) =
+            self.parse_struct_fields(pth.clone(), recover, token::Brace)?;
+        let span = lo.to(self.token.span);
         self.expect(&token::CloseDelim(token::Brace))?;
         let expr = if recover_async {
             ExprKind::Err
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 10c73fd64bc..0e2222bf840 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -493,7 +493,20 @@ impl<'a> Parser<'a> {
         let ty_first = if self.token.is_keyword(kw::For) && self.look_ahead(1, |t| t != &token::Lt)
         {
             let span = self.prev_token.span.between(self.token.span);
-            self.struct_span_err(span, "missing trait in a trait impl").emit();
+            self.struct_span_err(span, "missing trait in a trait impl")
+                .span_suggestion(
+                    span,
+                    "add a trait here",
+                    " Trait ".into(),
+                    Applicability::HasPlaceholders,
+                )
+                .span_suggestion(
+                    span.to(self.token.span),
+                    "for an inherent impl, drop this `for`",
+                    "".into(),
+                    Applicability::MaybeIncorrect,
+                )
+                .emit();
             P(Ty {
                 kind: TyKind::Path(None, err_path(span)),
                 span,
@@ -1234,7 +1247,7 @@ impl<'a> Parser<'a> {
         Ok((class_name, ItemKind::Union(vdata, generics)))
     }
 
-    pub(super) fn parse_record_struct_body(
+    fn parse_record_struct_body(
         &mut self,
         adt_ty: &str,
     ) -> PResult<'a, (Vec<FieldDef>, /* recovered */ bool)> {
@@ -1468,28 +1481,22 @@ impl<'a> Parser<'a> {
     fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
         let (ident, is_raw) = self.ident_or_err()?;
         if !is_raw && ident.is_reserved() {
-            if ident.name == kw::Underscore {
-                self.sess.gated_spans.gate(sym::unnamed_fields, lo);
+            let err = if self.check_fn_front_matter(false) {
+                // We use `parse_fn` to get a span for the function
+                if let Err(mut db) = self.parse_fn(&mut Vec::new(), |_| true, lo) {
+                    db.delay_as_bug();
+                }
+                let mut err = self.struct_span_err(
+                    lo.to(self.prev_token.span),
+                    &format!("functions are not allowed in {} definitions", adt_ty),
+                );
+                err.help("unlike in C++, Java, and C#, functions are declared in `impl` blocks");
+                err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
+                err
             } else {
-                let err = if self.check_fn_front_matter(false) {
-                    // We use `parse_fn` to get a span for the function
-                    if let Err(mut db) = self.parse_fn(&mut Vec::new(), |_| true, lo) {
-                        db.delay_as_bug();
-                    }
-                    let mut err = self.struct_span_err(
-                        lo.to(self.prev_token.span),
-                        &format!("functions are not allowed in {} definitions", adt_ty),
-                    );
-                    err.help(
-                        "unlike in C++, Java, and C#, functions are declared in `impl` blocks",
-                    );
-                    err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
-                    err
-                } else {
-                    self.expected_ident_found()
-                };
-                return Err(err);
-            }
+                self.expected_ident_found()
+            };
+            return Err(err);
         }
         self.bump();
         Ok(ident)
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index c4419e995ed..5c701fefd17 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -142,6 +142,17 @@ pub struct Parser<'a> {
     /// If present, this `Parser` is not parsing Rust code but rather a macro call.
     subparser_name: Option<&'static str>,
     capture_state: CaptureState,
+    /// This allows us to recover when the user forget to add braces around
+    /// multiple statements in the closure body.
+    pub current_closure: Option<ClosureSpans>,
+}
+
+/// Stores span informations about a closure.
+#[derive(Clone)]
+pub struct ClosureSpans {
+    pub whole_closure: Span,
+    pub closing_pipe: Span,
+    pub body: Span,
 }
 
 /// Indicates a range of tokens that should be replaced by
@@ -440,6 +451,7 @@ impl<'a> Parser<'a> {
                 replace_ranges: Vec::new(),
                 inner_attr_ranges: Default::default(),
             },
+            current_closure: None,
         };
 
         // Make parser point to the first token.
@@ -761,8 +773,11 @@ impl<'a> Parser<'a> {
                     first = false;
                 } else {
                     match self.expect(t) {
-                        Ok(false) => {}
+                        Ok(false) => {
+                            self.current_closure.take();
+                        }
                         Ok(true) => {
+                            self.current_closure.take();
                             recovered = true;
                             break;
                         }
@@ -770,10 +785,29 @@ impl<'a> Parser<'a> {
                             let sp = self.prev_token.span.shrink_to_hi();
                             let token_str = pprust::token_kind_to_string(t);
 
-                            // Attempt to keep parsing if it was a similar separator.
-                            if let Some(ref tokens) = t.similar_tokens() {
-                                if tokens.contains(&self.token.kind) && !unclosed_delims {
-                                    self.bump();
+                            match self.current_closure.take() {
+                                Some(closure_spans) if self.token.kind == TokenKind::Semi => {
+                                    // Finding a semicolon instead of a comma
+                                    // after a closure body indicates that the
+                                    // closure body may be a block but the user
+                                    // forgot to put braces around its
+                                    // statements.
+
+                                    self.recover_missing_braces_around_closure_body(
+                                        closure_spans,
+                                        expect_err,
+                                    )?;
+
+                                    continue;
+                                }
+
+                                _ => {
+                                    // Attempt to keep parsing if it was a similar separator.
+                                    if let Some(ref tokens) = t.similar_tokens() {
+                                        if tokens.contains(&self.token.kind) && !unclosed_delims {
+                                            self.bump();
+                                        }
+                                    }
                                 }
                             }
 
@@ -839,6 +873,65 @@ impl<'a> Parser<'a> {
         Ok((v, trailing, recovered))
     }
 
+    fn recover_missing_braces_around_closure_body(
+        &mut self,
+        closure_spans: ClosureSpans,
+        mut expect_err: DiagnosticBuilder<'_>,
+    ) -> PResult<'a, ()> {
+        let initial_semicolon = self.token.span;
+
+        while self.eat(&TokenKind::Semi) {
+            let _ = self.parse_stmt(ForceCollect::Yes)?;
+        }
+
+        expect_err.set_primary_message(
+            "closure bodies that contain statements must be surrounded by braces",
+        );
+
+        let preceding_pipe_span = closure_spans.closing_pipe;
+        let following_token_span = self.token.span;
+
+        let mut first_note = MultiSpan::from(vec![initial_semicolon]);
+        first_note.push_span_label(
+            initial_semicolon,
+            "this `;` turns the preceding closure into a statement".to_string(),
+        );
+        first_note.push_span_label(
+            closure_spans.body,
+            "this expression is a statement because of the trailing semicolon".to_string(),
+        );
+        expect_err.span_note(first_note, "statement found outside of a block");
+
+        let mut second_note = MultiSpan::from(vec![closure_spans.whole_closure]);
+        second_note.push_span_label(
+            closure_spans.whole_closure,
+            "this is the parsed closure...".to_string(),
+        );
+        second_note.push_span_label(
+            following_token_span,
+            "...but likely you meant the closure to end here".to_string(),
+        );
+        expect_err.span_note(second_note, "the closure body may be incorrectly delimited");
+
+        expect_err.set_span(vec![preceding_pipe_span, following_token_span]);
+
+        let opening_suggestion_str = " {".to_string();
+        let closing_suggestion_str = "}".to_string();
+
+        expect_err.multipart_suggestion(
+            "try adding braces",
+            vec![
+                (preceding_pipe_span.shrink_to_hi(), opening_suggestion_str),
+                (following_token_span.shrink_to_lo(), closing_suggestion_str),
+            ],
+            Applicability::MaybeIncorrect,
+        );
+
+        expect_err.emit();
+
+        Ok(())
+    }
+
     /// Parses a sequence, not including the closing delimiter. The function
     /// `f` must consume tokens until reaching the next separator or
     /// closing bracket.
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 25dcb4a112d..9ec6effeb4e 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -155,17 +155,20 @@ impl<'a> Parser<'a> {
 
         let mac = MacCall { path, args, prior_type_ascription: self.last_type_ascription };
 
-        let kind = if delim == token::Brace || self.token == token::Semi || self.token == token::Eof
-        {
-            StmtKind::MacCall(P(MacCallStmt { mac, style, attrs, tokens: None }))
-        } else {
-            // Since none of the above applied, this is an expression statement macro.
-            let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac), AttrVec::new());
-            let e = self.maybe_recover_from_bad_qpath(e, true)?;
-            let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
-            let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
-            StmtKind::Expr(e)
-        };
+        let kind =
+            if (delim == token::Brace && self.token != token::Dot && self.token != token::Question)
+                || self.token == token::Semi
+                || self.token == token::Eof
+            {
+                StmtKind::MacCall(P(MacCallStmt { mac, style, attrs, tokens: None }))
+            } else {
+                // Since none of the above applied, this is an expression statement macro.
+                let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac), AttrVec::new());
+                let e = self.maybe_recover_from_bad_qpath(e, true)?;
+                let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
+                let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
+                StmtKind::Expr(e)
+            };
         Ok(self.mk_stmt(lo.to(hi), kind))
     }
 
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 299fc916ac9..98400372c36 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -226,19 +226,6 @@ impl<'a> Parser<'a> {
             }
         } else if self.eat_keyword(kw::Impl) {
             self.parse_impl_ty(&mut impl_dyn_multi)?
-        } else if self.token.is_keyword(kw::Union)
-            && self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace))
-        {
-            self.bump();
-            let (fields, recovered) = self.parse_record_struct_body("union")?;
-            let span = lo.to(self.prev_token.span);
-            self.sess.gated_spans.gate(sym::unnamed_fields, span);
-            TyKind::AnonymousUnion(fields, recovered)
-        } else if self.eat_keyword(kw::Struct) {
-            let (fields, recovered) = self.parse_record_struct_body("struct")?;
-            let span = lo.to(self.prev_token.span);
-            self.sess.gated_spans.gate(sym::unnamed_fields, span);
-            TyKind::AnonymousStruct(fields, recovered)
         } else if self.is_explicit_dyn_type() {
             self.parse_dyn_ty(&mut impl_dyn_multi)?
         } else if self.eat_lt() {
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 25ad00aaf1f..0a309375716 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -239,7 +239,69 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
         }
     }
 
+    /// Automatically generated items marked with `rustc_trivial_field_reads`
+    /// will be ignored for the purposes of dead code analysis (see PR #85200
+    /// for discussion).
+    fn should_ignore_item(&self, def_id: DefId) -> bool {
+        if !self.tcx.has_attr(def_id, sym::automatically_derived)
+            && !self
+                .tcx
+                .impl_of_method(def_id)
+                .map_or(false, |impl_id| self.tcx.has_attr(impl_id, sym::automatically_derived))
+        {
+            return false;
+        }
+
+        let has_attr = |def_id| self.tcx.has_attr(def_id, sym::rustc_trivial_field_reads);
+
+        if has_attr(def_id) {
+            return true;
+        }
+
+        if let Some(impl_of) = self.tcx.impl_of_method(def_id) {
+            if has_attr(impl_of) {
+                return true;
+            }
+
+            if let Some(trait_of) = self.tcx.trait_id_of_impl(impl_of) {
+                if has_attr(trait_of) {
+                    return true;
+                }
+
+                if let Some(method_ident) = self.tcx.opt_item_name(def_id) {
+                    if let Some(trait_method) = self
+                        .tcx
+                        .associated_items(trait_of)
+                        .find_by_name_and_kind(self.tcx, method_ident, ty::AssocKind::Fn, trait_of)
+                    {
+                        if has_attr(trait_method.def_id) {
+                            return true;
+                        }
+                    }
+                }
+            }
+        } else if let Some(trait_of) = self.tcx.trait_of_item(def_id) {
+            if has_attr(trait_of) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     fn visit_node(&mut self, node: Node<'tcx>) {
+        if let Some(item_def_id) = match node {
+            Node::Item(hir::Item { def_id, .. })
+            | Node::ForeignItem(hir::ForeignItem { def_id, .. })
+            | Node::TraitItem(hir::TraitItem { def_id, .. })
+            | Node::ImplItem(hir::ImplItem { def_id, .. }) => Some(def_id.to_def_id()),
+            _ => None,
+        } {
+            if self.should_ignore_item(item_def_id) {
+                return;
+            }
+        }
+
         let had_repr_c = self.repr_has_repr_c;
         let had_inherited_pub_visibility = self.inherited_pub_visibility;
         let had_pub_visibility = self.pub_visibility;
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index ab9bfea9694..0d7abeba1a7 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -775,7 +775,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         if blk.targeted_by_break {
             self.break_ln.insert(blk.hir_id, succ);
         }
-        let succ = self.propagate_through_opt_expr(blk.expr.as_deref(), succ);
+        let succ = self.propagate_through_opt_expr(blk.expr, succ);
         blk.stmts.iter().rev().fold(succ, |succ, stmt| self.propagate_through_stmt(stmt, succ))
     }
 
@@ -796,7 +796,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                 // initialization, which is mildly more complex than checking
                 // once at the func header but otherwise equivalent.
 
-                let succ = self.propagate_through_opt_expr(local.init.as_deref(), succ);
+                let succ = self.propagate_through_opt_expr(local.init, succ);
                 self.define_bindings_in_pat(&local.pat, succ)
             }
             hir::StmtKind::Item(..) => succ,
diff --git a/compiler/rustc_passes/src/region.rs b/compiler/rustc_passes/src/region.rs
index 08702cad41c..5fc8e230d72 100644
--- a/compiler/rustc_passes/src/region.rs
+++ b/compiler/rustc_passes/src/region.rs
@@ -812,7 +812,7 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> {
         resolve_expr(self, ex);
     }
     fn visit_local(&mut self, l: &'tcx Local<'tcx>) {
-        resolve_local(self, Some(&l.pat), l.init.as_deref());
+        resolve_local(self, Some(&l.pat), l.init);
     }
 }
 
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 35e25e52dc5..391e4305423 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -19,8 +19,8 @@ use rustc_hir::{AssocItemKind, HirIdSet, Node, PatKind};
 use rustc_middle::bug;
 use rustc_middle::hir::map::Map;
 use rustc_middle::middle::privacy::{AccessLevel, AccessLevels};
-use rustc_middle::mir::abstract_const::Node as ACNode;
 use rustc_middle::span_bug;
+use rustc_middle::thir::abstract_const::Node as ACNode;
 use rustc_middle::ty::fold::TypeVisitor;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index 5c2803c67e7..bfd36bfb2db 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -9,6 +9,7 @@ use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex};
 use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
 use rustc_middle::mir::{self, interpret};
+use rustc_middle::thir;
 use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_query_system::dep_graph::DepContext;
@@ -23,7 +24,7 @@ use rustc_span::hygiene::{
 };
 use rustc_span::source_map::{SourceMap, StableSourceFileId};
 use rustc_span::CachingSourceMapView;
-use rustc_span::{BytePos, ExpnData, ExpnHash, SourceFile, Span, DUMMY_SP};
+use rustc_span::{BytePos, ExpnData, ExpnHash, Pos, SourceFile, Span};
 use std::collections::hash_map::Entry;
 use std::mem;
 
@@ -33,6 +34,7 @@ const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
 const TAG_FULL_SPAN: u8 = 0;
 // A partial span with no location information, encoded only with a `SyntaxContext`
 const TAG_PARTIAL_SPAN: u8 = 1;
+const TAG_RELATIVE_SPAN: u8 = 2;
 
 const TAG_SYNTAX_CONTEXT: u8 = 0;
 const TAG_EXPN_DATA: u8 = 1;
@@ -829,11 +831,26 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for ExpnId {
 
 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
     fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
+        let ctxt = SyntaxContext::decode(decoder)?;
+        let parent = Option::<LocalDefId>::decode(decoder)?;
         let tag: u8 = Decodable::decode(decoder)?;
 
         if tag == TAG_PARTIAL_SPAN {
-            let ctxt = SyntaxContext::decode(decoder)?;
-            return Ok(DUMMY_SP.with_ctxt(ctxt));
+            return Ok(Span::new(BytePos(0), BytePos(0), ctxt, parent));
+        } else if tag == TAG_RELATIVE_SPAN {
+            let dlo = u32::decode(decoder)?;
+            let dto = u32::decode(decoder)?;
+
+            let enclosing =
+                decoder.tcx.definitions_untracked().def_span(parent.unwrap()).data_untracked();
+            let span = Span::new(
+                enclosing.lo + BytePos::from_u32(dlo),
+                enclosing.lo + BytePos::from_u32(dto),
+                ctxt,
+                parent,
+            );
+
+            return Ok(span);
         } else {
             debug_assert_eq!(tag, TAG_FULL_SPAN);
         }
@@ -842,13 +859,12 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
         let line_lo = usize::decode(decoder)?;
         let col_lo = BytePos::decode(decoder)?;
         let len = BytePos::decode(decoder)?;
-        let ctxt = SyntaxContext::decode(decoder)?;
 
         let file_lo = decoder.file_index_to_file(file_lo_index);
         let lo = file_lo.lines[line_lo - 1] + col_lo;
         let hi = lo + len;
 
-        Ok(Span::new(lo, hi, ctxt))
+        Ok(Span::new(lo, hi, ctxt, parent))
     }
 }
 
@@ -906,7 +922,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
     }
 }
 
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [mir::abstract_const::Node<'tcx>] {
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [thir::abstract_const::Node<'tcx>] {
     fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
         RefDecodable::decode(d)
     }
@@ -1008,10 +1024,22 @@ where
     E: 'a + OpaqueEncoder,
 {
     fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) -> Result<(), E::Error> {
-        let span_data = self.data();
-        if self.is_dummy() {
-            TAG_PARTIAL_SPAN.encode(s)?;
-            return span_data.ctxt.encode(s);
+        let span_data = self.data_untracked();
+        span_data.ctxt.encode(s)?;
+        span_data.parent.encode(s)?;
+
+        if span_data.is_dummy() {
+            return TAG_PARTIAL_SPAN.encode(s);
+        }
+
+        if let Some(parent) = span_data.parent {
+            let enclosing = s.tcx.definitions_untracked().def_span(parent).data_untracked();
+            if enclosing.contains(span_data) {
+                TAG_RELATIVE_SPAN.encode(s)?;
+                (span_data.lo - enclosing.lo).to_u32().encode(s)?;
+                (span_data.hi - enclosing.lo).to_u32().encode(s)?;
+                return Ok(());
+            }
         }
 
         let pos = s.source_map.byte_pos_to_line_and_col(span_data.lo);
@@ -1021,8 +1049,7 @@ where
         };
 
         if partial_span {
-            TAG_PARTIAL_SPAN.encode(s)?;
-            return span_data.ctxt.encode(s);
+            return TAG_PARTIAL_SPAN.encode(s);
         }
 
         let (file_lo, line_lo, col_lo) = pos.unwrap();
@@ -1035,8 +1062,7 @@ where
         source_file_index.encode(s)?;
         line_lo.encode(s)?;
         col_lo.encode(s)?;
-        len.encode(s)?;
-        span_data.ctxt.encode(s)
+        len.encode(s)
     }
 }
 
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 9c3dad8bd63..e589d16992f 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -11,6 +11,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
 use parking_lot::Mutex;
 use smallvec::{smallvec, SmallVec};
 use std::collections::hash_map::Entry;
+use std::fmt::Debug;
 use std::hash::Hash;
 use std::marker::PhantomData;
 use std::sync::atomic::Ordering::Relaxed;
@@ -208,89 +209,99 @@ impl<K: DepKind> DepGraph<K> {
     ///   `arg` parameter.
     ///
     /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/incremental-compilation.html
-    pub fn with_task<Ctxt: HasDepContext<DepKind = K>, A, R>(
+    pub fn with_task<Ctxt: HasDepContext<DepKind = K>, A: Debug, R>(
         &self,
         key: DepNode<K>,
         cx: Ctxt,
         arg: A,
         task: fn(Ctxt, A) -> R,
-        hash_result: impl FnOnce(&mut Ctxt::StableHashingContext, &R) -> Option<Fingerprint>,
+        hash_result: fn(&mut Ctxt::StableHashingContext, &R) -> Option<Fingerprint>,
     ) -> (R, DepNodeIndex) {
-        self.with_task_impl(
-            key,
-            cx,
-            arg,
-            task,
-            |_key| {
-                Some(TaskDeps {
-                    #[cfg(debug_assertions)]
-                    node: Some(_key),
-                    reads: SmallVec::new(),
-                    read_set: Default::default(),
-                    phantom_data: PhantomData,
-                })
-            },
-            hash_result,
-        )
+        if self.is_fully_enabled() {
+            self.with_task_impl(key, cx, arg, task, hash_result)
+        } else {
+            // Incremental compilation is turned off. We just execute the task
+            // without tracking. We still provide a dep-node index that uniquely
+            // identifies the task so that we have a cheap way of referring to
+            // the query for self-profiling.
+            (task(cx, arg), self.next_virtual_depnode_index())
+        }
     }
 
-    fn with_task_impl<Ctxt: HasDepContext<DepKind = K>, A, R>(
+    fn with_task_impl<Ctxt: HasDepContext<DepKind = K>, A: Debug, R>(
         &self,
         key: DepNode<K>,
         cx: Ctxt,
         arg: A,
         task: fn(Ctxt, A) -> R,
-        create_task: fn(DepNode<K>) -> Option<TaskDeps<K>>,
-        hash_result: impl FnOnce(&mut Ctxt::StableHashingContext, &R) -> Option<Fingerprint>,
+        hash_result: fn(&mut Ctxt::StableHashingContext, &R) -> Option<Fingerprint>,
     ) -> (R, DepNodeIndex) {
-        if let Some(ref data) = self.data {
-            let dcx = cx.dep_context();
-            let task_deps = create_task(key).map(Lock::new);
-            let result = K::with_deps(task_deps.as_ref(), || task(cx, arg));
-            let edges = task_deps.map_or_else(|| smallvec![], |lock| lock.into_inner().reads);
-
-            let mut hcx = dcx.create_stable_hashing_context();
-            let hashing_timer = dcx.profiler().incr_result_hashing();
-            let current_fingerprint = hash_result(&mut hcx, &result);
-
-            let print_status = cfg!(debug_assertions) && dcx.sess().opts.debugging_opts.dep_tasks;
-
-            // Get timer for profiling `DepNode` interning
-            let node_intern_timer = self
-                .node_intern_event_id
-                .map(|eid| dcx.profiler().generic_activity_with_event_id(eid));
-            // Intern the new `DepNode`.
-            let (dep_node_index, prev_and_color) = data.current.intern_node(
-                dcx.profiler(),
-                &data.previous,
-                key,
-                edges,
-                current_fingerprint,
-                print_status,
-            );
-            drop(node_intern_timer);
+        // This function is only called when the graph is enabled.
+        let data = self.data.as_ref().unwrap();
 
-            hashing_timer.finish_with_query_invocation_id(dep_node_index.into());
+        // If the following assertion triggers, it can have two reasons:
+        // 1. Something is wrong with DepNode creation, either here or
+        //    in `DepGraph::try_mark_green()`.
+        // 2. Two distinct query keys get mapped to the same `DepNode`
+        //    (see for example #48923).
+        assert!(
+            !self.dep_node_exists(&key),
+            "forcing query with already existing `DepNode`\n\
+                 - query-key: {:?}\n\
+                 - dep-node: {:?}",
+            arg,
+            key
+        );
 
-            if let Some((prev_index, color)) = prev_and_color {
-                debug_assert!(
-                    data.colors.get(prev_index).is_none(),
-                    "DepGraph::with_task() - Duplicate DepNodeColor \
-                            insertion for {:?}",
-                    key
-                );
+        let task_deps = if key.kind.is_eval_always() {
+            None
+        } else {
+            Some(Lock::new(TaskDeps {
+                #[cfg(debug_assertions)]
+                node: Some(key),
+                reads: SmallVec::new(),
+                read_set: Default::default(),
+                phantom_data: PhantomData,
+            }))
+        };
+        let result = K::with_deps(task_deps.as_ref(), || task(cx, arg));
+        let edges = task_deps.map_or_else(|| smallvec![], |lock| lock.into_inner().reads);
+
+        let dcx = cx.dep_context();
+        let mut hcx = dcx.create_stable_hashing_context();
+        let hashing_timer = dcx.profiler().incr_result_hashing();
+        let current_fingerprint = hash_result(&mut hcx, &result);
+
+        let print_status = cfg!(debug_assertions) && dcx.sess().opts.debugging_opts.dep_tasks;
+
+        // Get timer for profiling `DepNode` interning
+        let node_intern_timer =
+            self.node_intern_event_id.map(|eid| dcx.profiler().generic_activity_with_event_id(eid));
+        // Intern the new `DepNode`.
+        let (dep_node_index, prev_and_color) = data.current.intern_node(
+            dcx.profiler(),
+            &data.previous,
+            key,
+            edges,
+            current_fingerprint,
+            print_status,
+        );
+        drop(node_intern_timer);
 
-                data.colors.insert(prev_index, color);
-            }
+        hashing_timer.finish_with_query_invocation_id(dep_node_index.into());
 
-            (result, dep_node_index)
-        } else {
-            // Incremental compilation is turned off. We just execute the task
-            // without tracking. We still provide a dep-node index that uniquely
-            // identifies the task so that we have a cheap way of referring to
-            // the query for self-profiling.
-            (task(cx, arg), self.next_virtual_depnode_index())
+        if let Some((prev_index, color)) = prev_and_color {
+            debug_assert!(
+                data.colors.get(prev_index).is_none(),
+                "DepGraph::with_task() - Duplicate DepNodeColor \
+                            insertion for {:?}",
+                key
+            );
+
+            data.colors.insert(prev_index, color);
         }
+
+        (result, dep_node_index)
     }
 
     /// Executes something within an "anonymous" task, that is, a task the
@@ -357,19 +368,6 @@ impl<K: DepKind> DepGraph<K> {
         }
     }
 
-    /// Executes something within an "eval-always" task which is a task
-    /// that runs whenever anything changes.
-    pub fn with_eval_always_task<Ctxt: HasDepContext<DepKind = K>, A, R>(
-        &self,
-        key: DepNode<K>,
-        cx: Ctxt,
-        arg: A,
-        task: fn(Ctxt, A) -> R,
-        hash_result: impl FnOnce(&mut Ctxt::StableHashingContext, &R) -> Option<Fingerprint>,
-    ) -> (R, DepNodeIndex) {
-        self.with_task_impl(key, cx, arg, task, |_| None, hash_result)
-    }
-
     #[inline]
     pub fn read_index(&self, dep_node_index: DepNodeIndex) {
         if let Some(ref data) = self.data {
@@ -484,22 +482,11 @@ impl<K: DepKind> DepGraph<K> {
         None
     }
 
-    /// Try to read a node index for the node dep_node.
+    /// Try to mark a node index for the node dep_node.
+    ///
     /// A node will have an index, when it's already been marked green, or when we can mark it
     /// green. This function will mark the current task as a reader of the specified node, when
     /// a node index can be found for that node.
-    pub fn try_mark_green_and_read<Ctxt: QueryContext<DepKind = K>>(
-        &self,
-        tcx: Ctxt,
-        dep_node: &DepNode<K>,
-    ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> {
-        self.try_mark_green(tcx, dep_node).map(|(prev_index, dep_node_index)| {
-            debug_assert!(self.is_green(&dep_node));
-            self.read_index(dep_node_index);
-            (prev_index, dep_node_index)
-        })
-    }
-
     pub fn try_mark_green<Ctxt: QueryContext<DepKind = K>>(
         &self,
         tcx: Ctxt,
diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs
index c3fdf4fc228..98b2a450b19 100644
--- a/compiler/rustc_query_system/src/query/job.rs
+++ b/compiler/rustc_query_system/src/query/job.rs
@@ -143,6 +143,8 @@ impl<D> QueryJobId<D>
 where
     D: Copy + Clone + Eq + Hash,
 {
+    #[cold]
+    #[inline(never)]
     pub(super) fn find_cycle_in_stack(
         &self,
         query_map: QueryMap<D>,
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 3f22de6fba4..3534c324295 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -2,8 +2,7 @@
 //! generate the actual methods on tcx which find and execute the provider,
 //! manage the caches, and so forth.
 
-use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeParams};
-use crate::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
+use crate::dep_graph::{DepContext, DepKind, DepNode, DepNodeIndex, DepNodeParams};
 use crate::query::caches::QueryCache;
 use crate::query::config::{QueryDescription, QueryVtable, QueryVtableExt};
 use crate::query::job::{
@@ -13,12 +12,12 @@ use crate::query::{QueryContext, QueryMap, QuerySideEffects, QueryStackFrame};
 
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHasher};
+#[cfg(parallel_compiler)]
+use rustc_data_structures::profiling::TimingGuard;
 use rustc_data_structures::sharded::{get_shard_index_by_hash, Sharded};
 use rustc_data_structures::sync::{Lock, LockGuard};
 use rustc_data_structures::thin_vec::ThinVec;
-#[cfg(not(parallel_compiler))]
-use rustc_errors::DiagnosticBuilder;
-use rustc_errors::{Diagnostic, FatalError};
+use rustc_errors::{DiagnosticBuilder, FatalError};
 use rustc_span::{Span, DUMMY_SP};
 use std::cell::Cell;
 use std::collections::hash_map::Entry;
@@ -148,24 +147,21 @@ impl<D, K> Default for QueryState<D, K> {
 
 /// A type representing the responsibility to execute the job in the `job` field.
 /// This will poison the relevant query if dropped.
-struct JobOwner<'tcx, D, C>
+struct JobOwner<'tcx, D, K>
 where
     D: Copy + Clone + Eq + Hash,
-    C: QueryCache,
+    K: Eq + Hash + Clone,
 {
-    state: &'tcx QueryState<D, C::Key>,
-    cache: &'tcx QueryCacheStore<C>,
-    key: C::Key,
+    state: &'tcx QueryState<D, K>,
+    key: K,
     id: QueryJobId<D>,
 }
 
 #[cold]
 #[inline(never)]
-#[cfg(not(parallel_compiler))]
 fn mk_cycle<CTX, V, R>(
     tcx: CTX,
-    root: QueryJobId<CTX::DepKind>,
-    span: Span,
+    error: CycleError,
     handle_cycle_error: fn(CTX, DiagnosticBuilder<'_>) -> V,
     cache: &dyn crate::query::QueryStorage<Value = V, Stored = R>,
 ) -> R
@@ -174,20 +170,15 @@ where
     V: std::fmt::Debug,
     R: Clone,
 {
-    let error: CycleError = root.find_cycle_in_stack(
-        tcx.try_collect_active_jobs().unwrap(),
-        &tcx.current_query_job(),
-        span,
-    );
     let error = report_cycle(tcx.dep_context().sess(), error);
     let value = handle_cycle_error(tcx, error);
     cache.store_nocache(value)
 }
 
-impl<'tcx, D, C> JobOwner<'tcx, D, C>
+impl<'tcx, D, K> JobOwner<'tcx, D, K>
 where
     D: Copy + Clone + Eq + Hash,
-    C: QueryCache,
+    K: Eq + Hash + Clone,
 {
     /// Either gets a `JobOwner` corresponding the query, allowing us to
     /// start executing the query, or returns with the result of the query.
@@ -199,14 +190,13 @@ where
     /// for some compile-time benchmarks.
     #[inline(always)]
     fn try_start<'b, CTX>(
-        tcx: CTX,
-        state: &'b QueryState<CTX::DepKind, C::Key>,
-        cache: &'b QueryCacheStore<C>,
+        tcx: &'b CTX,
+        state: &'b QueryState<CTX::DepKind, K>,
         span: Span,
-        key: C::Key,
+        key: K,
         lookup: QueryLookup,
-        query: &QueryVtable<CTX, C::Key, C::Value>,
-    ) -> TryGetJob<'b, CTX::DepKind, C>
+        dep_kind: CTX::DepKind,
+    ) -> TryGetJob<'b, CTX::DepKind, K>
     where
         CTX: QueryContext,
     {
@@ -227,26 +217,24 @@ where
                 let key = entry.key().clone();
                 entry.insert(QueryResult::Started(job));
 
-                let global_id = QueryJobId::new(id, shard, query.dep_kind);
-                let owner = JobOwner { state, cache, id: global_id, key };
+                let global_id = QueryJobId::new(id, shard, dep_kind);
+                let owner = JobOwner { state, id: global_id, key };
                 return TryGetJob::NotYetStarted(owner);
             }
             Entry::Occupied(mut entry) => {
                 match entry.get_mut() {
                     #[cfg(not(parallel_compiler))]
                     QueryResult::Started(job) => {
-                        let id = QueryJobId::new(job.id, shard, query.dep_kind);
+                        let id = QueryJobId::new(job.id, shard, dep_kind);
 
                         drop(state_lock);
 
                         // If we are single-threaded we know that we have cycle error,
                         // so we just return the error.
-                        return TryGetJob::Cycle(mk_cycle(
-                            tcx,
-                            id,
+                        return TryGetJob::Cycle(id.find_cycle_in_stack(
+                            tcx.try_collect_active_jobs().unwrap(),
+                            &tcx.current_query_job(),
                             span,
-                            query.handle_cycle_error,
-                            &cache.cache,
                         ));
                     }
                     #[cfg(parallel_compiler)]
@@ -258,7 +246,6 @@ where
 
                         // Get the latch out
                         let latch = job.latch();
-                        let key = entry.key().clone();
 
                         drop(state_lock);
 
@@ -266,30 +253,10 @@ where
                         // thread.
                         let result = latch.wait_on(tcx.current_query_job(), span);
 
-                        if let Err(cycle) = result {
-                            let cycle = report_cycle(tcx.dep_context().sess(), cycle);
-                            let value = (query.handle_cycle_error)(tcx, cycle);
-                            let value = cache.cache.store_nocache(value);
-                            return TryGetJob::Cycle(value);
+                        match result {
+                            Ok(()) => TryGetJob::JobCompleted(query_blocked_prof_timer),
+                            Err(cycle) => TryGetJob::Cycle(cycle),
                         }
-
-                        let cached = cache
-                            .cache
-                            .lookup(cache, &key, |value, index| {
-                                if unlikely!(tcx.dep_context().profiler().enabled()) {
-                                    tcx.dep_context().profiler().query_cache_hit(index.into());
-                                }
-                                #[cfg(debug_assertions)]
-                                {
-                                    cache.cache_hits.fetch_add(1, Ordering::Relaxed);
-                                }
-                                (value.clone(), index)
-                            })
-                            .unwrap_or_else(|_| panic!("value must be in cache after waiting"));
-
-                        query_blocked_prof_timer.finish_with_query_invocation_id(cached.1.into());
-
-                        return TryGetJob::JobCompleted(cached);
                     }
                     QueryResult::Poisoned => FatalError.raise(),
                 }
@@ -299,11 +266,18 @@ where
 
     /// Completes the query by updating the query cache with the `result`,
     /// signals the waiter and forgets the JobOwner, so it won't poison the query
-    fn complete(self, result: C::Value, dep_node_index: DepNodeIndex) -> C::Stored {
+    fn complete<C>(
+        self,
+        cache: &QueryCacheStore<C>,
+        result: C::Value,
+        dep_node_index: DepNodeIndex,
+    ) -> C::Stored
+    where
+        C: QueryCache<Key = K>,
+    {
         // We can move out of `self` here because we `mem::forget` it below
         let key = unsafe { ptr::read(&self.key) };
         let state = self.state;
-        let cache = self.cache;
 
         // Forget ourself so our destructor won't poison the query
         mem::forget(self);
@@ -330,19 +304,10 @@ where
     }
 }
 
-fn with_diagnostics<F, R>(f: F) -> (R, ThinVec<Diagnostic>)
-where
-    F: FnOnce(Option<&Lock<ThinVec<Diagnostic>>>) -> R,
-{
-    let diagnostics = Lock::new(ThinVec::new());
-    let result = f(Some(&diagnostics));
-    (result, diagnostics.into_inner())
-}
-
-impl<'tcx, D, C> Drop for JobOwner<'tcx, D, C>
+impl<'tcx, D, K> Drop for JobOwner<'tcx, D, K>
 where
     D: Copy + Clone + Eq + Hash,
-    C: QueryCache,
+    K: Eq + Hash + Clone,
 {
     #[inline(never)]
     #[cold]
@@ -373,22 +338,22 @@ pub(crate) struct CycleError {
 }
 
 /// The result of `try_start`.
-enum TryGetJob<'tcx, D, C>
+enum TryGetJob<'tcx, D, K>
 where
     D: Copy + Clone + Eq + Hash,
-    C: QueryCache,
+    K: Eq + Hash + Clone,
 {
     /// The query is not yet started. Contains a guard to the cache eventually used to start it.
-    NotYetStarted(JobOwner<'tcx, D, C>),
+    NotYetStarted(JobOwner<'tcx, D, K>),
 
     /// The query was already completed.
     /// Returns the result of the query and its dep-node index
     /// if it succeeded or a cycle error if it failed.
     #[cfg(parallel_compiler)]
-    JobCompleted((C::Stored, DepNodeIndex)),
+    JobCompleted(TimingGuard<'tcx>),
 
     /// Trying to execute the query resulted in a cycle.
-    Cycle(C::Stored),
+    Cycle(CycleError),
 }
 
 /// Checks if the query is already computed and in the cache.
@@ -428,119 +393,146 @@ fn try_execute_query<CTX, C>(
     span: Span,
     key: C::Key,
     lookup: QueryLookup,
+    dep_node: Option<DepNode<CTX::DepKind>>,
     query: &QueryVtable<CTX, C::Key, C::Value>,
     compute: fn(CTX::DepContext, C::Key) -> C::Value,
-) -> C::Stored
+) -> (C::Stored, Option<DepNodeIndex>)
 where
     C: QueryCache,
-    C::Key: DepNodeParams<CTX::DepContext>,
+    C::Key: Clone + DepNodeParams<CTX::DepContext>,
     CTX: QueryContext,
 {
-    let job = match JobOwner::<'_, CTX::DepKind, C>::try_start(
-        tcx,
+    match JobOwner::<'_, CTX::DepKind, C::Key>::try_start(
+        &tcx,
         state,
-        cache,
         span,
         key.clone(),
         lookup,
-        query,
+        query.dep_kind,
     ) {
-        TryGetJob::NotYetStarted(job) => job,
-        TryGetJob::Cycle(result) => return result,
+        TryGetJob::NotYetStarted(job) => {
+            let (result, dep_node_index) = execute_job(tcx, key, dep_node, query, job.id, compute);
+            let result = job.complete(cache, result, dep_node_index);
+            (result, Some(dep_node_index))
+        }
+        TryGetJob::Cycle(error) => {
+            let result = mk_cycle(tcx, error, query.handle_cycle_error, &cache.cache);
+            (result, None)
+        }
         #[cfg(parallel_compiler)]
-        TryGetJob::JobCompleted((v, index)) => {
-            tcx.dep_context().dep_graph().read_index(index);
-            return v;
+        TryGetJob::JobCompleted(query_blocked_prof_timer) => {
+            let (v, index) = cache
+                .cache
+                .lookup(cache, &key, |value, index| (value.clone(), index))
+                .unwrap_or_else(|_| panic!("value must be in cache after waiting"));
+
+            if unlikely!(tcx.dep_context().profiler().enabled()) {
+                tcx.dep_context().profiler().query_cache_hit(index.into());
+            }
+            #[cfg(debug_assertions)]
+            {
+                cache.cache_hits.fetch_add(1, Ordering::Relaxed);
+            }
+            query_blocked_prof_timer.finish_with_query_invocation_id(index.into());
+
+            (v, Some(index))
         }
-    };
+    }
+}
 
+fn execute_job<CTX, K, V>(
+    tcx: CTX,
+    key: K,
+    mut dep_node_opt: Option<DepNode<CTX::DepKind>>,
+    query: &QueryVtable<CTX, K, V>,
+    job_id: QueryJobId<CTX::DepKind>,
+    compute: fn(CTX::DepContext, K) -> V,
+) -> (V, DepNodeIndex)
+where
+    K: Clone + DepNodeParams<CTX::DepContext>,
+    V: Debug,
+    CTX: QueryContext,
+{
     let dep_graph = tcx.dep_context().dep_graph();
 
     // Fast path for when incr. comp. is off.
     if !dep_graph.is_fully_enabled() {
         let prof_timer = tcx.dep_context().profiler().query_provider();
-        let result = tcx.start_query(job.id, None, || compute(*tcx.dep_context(), key));
+        let result = tcx.start_query(job_id, None, || compute(*tcx.dep_context(), key));
         let dep_node_index = dep_graph.next_virtual_depnode_index();
         prof_timer.finish_with_query_invocation_id(dep_node_index.into());
-        return job.complete(result, dep_node_index);
+        return (result, dep_node_index);
     }
 
-    if query.anon {
-        let prof_timer = tcx.dep_context().profiler().query_provider();
+    if !query.anon && !query.eval_always {
+        // `to_dep_node` is expensive for some `DepKind`s.
+        let dep_node =
+            dep_node_opt.get_or_insert_with(|| query.to_dep_node(*tcx.dep_context(), &key));
 
-        let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
-            tcx.start_query(job.id, diagnostics, || {
-                dep_graph.with_anon_task(*tcx.dep_context(), query.dep_kind, || {
-                    compute(*tcx.dep_context(), key)
-                })
-            })
-        });
+        // The diagnostics for this query will be promoted to the current session during
+        // `try_mark_green()`, so we can ignore them here.
+        if let Some(ret) = tcx.start_query(job_id, None, || {
+            try_load_from_disk_and_cache_in_memory(tcx, &key, &dep_node, query, compute)
+        }) {
+            return ret;
+        }
+    }
 
-        prof_timer.finish_with_query_invocation_id(dep_node_index.into());
+    let prof_timer = tcx.dep_context().profiler().query_provider();
+    let diagnostics = Lock::new(ThinVec::new());
 
-        dep_graph.read_index(dep_node_index);
+    let (result, dep_node_index) = tcx.start_query(job_id, Some(&diagnostics), || {
+        if query.anon {
+            return dep_graph.with_anon_task(*tcx.dep_context(), query.dep_kind, || {
+                compute(*tcx.dep_context(), key)
+            });
+        }
 
-        let side_effects = QuerySideEffects { diagnostics };
+        // `to_dep_node` is expensive for some `DepKind`s.
+        let dep_node = dep_node_opt.unwrap_or_else(|| query.to_dep_node(*tcx.dep_context(), &key));
 
-        if unlikely!(!side_effects.is_empty()) {
-            tcx.store_side_effects_for_anon_node(dep_node_index, side_effects);
-        }
+        dep_graph.with_task(dep_node, *tcx.dep_context(), key, compute, query.hash_result)
+    });
 
-        return job.complete(result, dep_node_index);
-    }
+    prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
-    let dep_node = query.to_dep_node(*tcx.dep_context(), &key);
+    let diagnostics = diagnostics.into_inner();
+    let side_effects = QuerySideEffects { diagnostics };
 
-    if !query.eval_always {
-        // The diagnostics for this query will be
-        // promoted to the current session during
-        // `try_mark_green()`, so we can ignore them here.
-        let loaded = tcx.start_query(job.id, None, || {
-            let marked = dep_graph.try_mark_green_and_read(tcx, &dep_node);
-            marked.map(|(prev_dep_node_index, dep_node_index)| {
-                (
-                    load_from_disk_and_cache_in_memory(
-                        tcx,
-                        key.clone(),
-                        prev_dep_node_index,
-                        dep_node_index,
-                        &dep_node,
-                        query,
-                        compute,
-                    ),
-                    dep_node_index,
-                )
-            })
-        });
-        if let Some((result, dep_node_index)) = loaded {
-            return job.complete(result, dep_node_index);
+    if unlikely!(!side_effects.is_empty()) {
+        if query.anon {
+            tcx.store_side_effects_for_anon_node(dep_node_index, side_effects);
+        } else {
+            tcx.store_side_effects(dep_node_index, side_effects);
         }
     }
 
-    let (result, dep_node_index) = force_query_with_job(tcx, key, job, dep_node, query, compute);
-    dep_graph.read_index(dep_node_index);
-    result
+    (result, dep_node_index)
 }
 
-fn load_from_disk_and_cache_in_memory<CTX, K, V: Debug>(
+fn try_load_from_disk_and_cache_in_memory<CTX, K, V>(
     tcx: CTX,
-    key: K,
-    prev_dep_node_index: SerializedDepNodeIndex,
-    dep_node_index: DepNodeIndex,
+    key: &K,
     dep_node: &DepNode<CTX::DepKind>,
     query: &QueryVtable<CTX, K, V>,
     compute: fn(CTX::DepContext, K) -> V,
-) -> V
+) -> Option<(V, DepNodeIndex)>
 where
+    K: Clone,
     CTX: QueryContext,
+    V: Debug,
 {
     // Note this function can be called concurrently from the same query
     // We must ensure that this is handled correctly.
 
-    debug_assert!(tcx.dep_context().dep_graph().is_green(dep_node));
+    let dep_graph = tcx.dep_context().dep_graph();
+    let (prev_dep_node_index, dep_node_index) = dep_graph.try_mark_green(tcx, &dep_node)?;
+
+    debug_assert!(dep_graph.is_green(dep_node));
 
     // First we try to load the result from the on-disk cache.
-    let result = if query.cache_on_disk(tcx, &key, None) {
+    // Some things are never cached on disk.
+    if query.cache_on_disk(tcx, key, None) {
         let prof_timer = tcx.dep_context().profiler().incr_cache_loading();
         let result = query.try_load_from_disk(tcx, prev_dep_node_index);
         prof_timer.finish_with_query_invocation_id(dep_node_index.into());
@@ -552,43 +544,39 @@ where
             "missing on-disk cache entry for {:?}",
             dep_node
         );
-        result
-    } else {
-        // Some things are never cached on disk.
-        None
-    };
 
-    if let Some(result) = result {
-        // If `-Zincremental-verify-ich` is specified, re-hash results from
-        // the cache and make sure that they have the expected fingerprint.
-        if unlikely!(tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich) {
-            incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query);
+        if let Some(result) = result {
+            // If `-Zincremental-verify-ich` is specified, re-hash results from
+            // the cache and make sure that they have the expected fingerprint.
+            if unlikely!(tcx.dep_context().sess().opts.debugging_opts.incremental_verify_ich) {
+                incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query);
+            }
+
+            return Some((result, dep_node_index));
         }
+    }
 
-        result
-    } else {
-        // We could not load a result from the on-disk cache, so
-        // recompute.
-        let prof_timer = tcx.dep_context().profiler().query_provider();
+    // We could not load a result from the on-disk cache, so
+    // recompute.
+    let prof_timer = tcx.dep_context().profiler().query_provider();
 
-        // The dep-graph for this computation is already in-place.
-        let result = tcx.dep_context().dep_graph().with_ignore(|| compute(*tcx.dep_context(), key));
+    // The dep-graph for this computation is already in-place.
+    let result = dep_graph.with_ignore(|| compute(*tcx.dep_context(), key.clone()));
 
-        prof_timer.finish_with_query_invocation_id(dep_node_index.into());
-
-        // Verify that re-running the query produced a result with the expected hash
-        // This catches bugs in query implementations, turning them into ICEs.
-        // For example, a query might sort its result by `DefId` - since `DefId`s are
-        // not stable across compilation sessions, the result could get up getting sorted
-        // in a different order when the query is re-run, even though all of the inputs
-        // (e.g. `DefPathHash` values) were green.
-        //
-        // See issue #82920 for an example of a miscompilation that would get turned into
-        // an ICE by this check
-        incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query);
+    prof_timer.finish_with_query_invocation_id(dep_node_index.into());
 
-        result
-    }
+    // Verify that re-running the query produced a result with the expected hash
+    // This catches bugs in query implementations, turning them into ICEs.
+    // For example, a query might sort its result by `DefId` - since `DefId`s are
+    // not stable across compilation sessions, the result could get up getting sorted
+    // in a different order when the query is re-run, even though all of the inputs
+    // (e.g. `DefPathHash` values) were green.
+    //
+    // See issue #82920 for an example of a miscompilation that would get turned into
+    // an ICE by this check
+    incremental_verify_ich(*tcx.dep_context(), &result, dep_node, query);
+
+    Some((result, dep_node_index))
 }
 
 fn incremental_verify_ich<CTX, K, V: Debug>(
@@ -648,88 +636,6 @@ fn incremental_verify_ich<CTX, K, V: Debug>(
     }
 }
 
-fn force_query_with_job<C, CTX>(
-    tcx: CTX,
-    key: C::Key,
-    job: JobOwner<'_, CTX::DepKind, C>,
-    dep_node: DepNode<CTX::DepKind>,
-    query: &QueryVtable<CTX, C::Key, C::Value>,
-    compute: fn(CTX::DepContext, C::Key) -> C::Value,
-) -> (C::Stored, DepNodeIndex)
-where
-    C: QueryCache,
-    CTX: QueryContext,
-{
-    // If the following assertion triggers, it can have two reasons:
-    // 1. Something is wrong with DepNode creation, either here or
-    //    in `DepGraph::try_mark_green()`.
-    // 2. Two distinct query keys get mapped to the same `DepNode`
-    //    (see for example #48923).
-    assert!(
-        !tcx.dep_context().dep_graph().dep_node_exists(&dep_node),
-        "forcing query with already existing `DepNode`\n\
-                 - query-key: {:?}\n\
-                 - dep-node: {:?}",
-        key,
-        dep_node
-    );
-
-    let prof_timer = tcx.dep_context().profiler().query_provider();
-
-    let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
-        tcx.start_query(job.id, diagnostics, || {
-            if query.eval_always {
-                tcx.dep_context().dep_graph().with_eval_always_task(
-                    dep_node,
-                    *tcx.dep_context(),
-                    key,
-                    compute,
-                    query.hash_result,
-                )
-            } else {
-                tcx.dep_context().dep_graph().with_task(
-                    dep_node,
-                    *tcx.dep_context(),
-                    key,
-                    compute,
-                    query.hash_result,
-                )
-            }
-        })
-    });
-
-    prof_timer.finish_with_query_invocation_id(dep_node_index.into());
-
-    let side_effects = QuerySideEffects { diagnostics };
-
-    if unlikely!(!side_effects.is_empty()) && dep_node.kind != DepKind::NULL {
-        tcx.store_side_effects(dep_node_index, side_effects);
-    }
-
-    let result = job.complete(result, dep_node_index);
-
-    (result, dep_node_index)
-}
-
-#[inline(never)]
-fn get_query_impl<CTX, C>(
-    tcx: CTX,
-    state: &QueryState<CTX::DepKind, C::Key>,
-    cache: &QueryCacheStore<C>,
-    span: Span,
-    key: C::Key,
-    lookup: QueryLookup,
-    query: &QueryVtable<CTX, C::Key, C::Value>,
-    compute: fn(CTX::DepContext, C::Key) -> C::Value,
-) -> C::Stored
-where
-    CTX: QueryContext,
-    C: QueryCache,
-    C::Key: DepNodeParams<CTX::DepContext>,
-{
-    try_execute_query(tcx, state, cache, span, key, lookup, query, compute)
-}
-
 /// Ensure that either this query has all green inputs or been executed.
 /// Executing `query::ensure(D)` is considered a read of the dep-node `D`.
 /// Returns true if the query should still run.
@@ -739,13 +645,17 @@ where
 ///
 /// Note: The optimization is only available during incr. comp.
 #[inline(never)]
-fn ensure_must_run<CTX, K, V>(tcx: CTX, key: &K, query: &QueryVtable<CTX, K, V>) -> bool
+fn ensure_must_run<CTX, K, V>(
+    tcx: CTX,
+    key: &K,
+    query: &QueryVtable<CTX, K, V>,
+) -> (bool, Option<DepNode<CTX::DepKind>>)
 where
     K: crate::dep_graph::DepNodeParams<CTX::DepContext>,
     CTX: QueryContext,
 {
     if query.eval_always {
-        return true;
+        return (true, None);
     }
 
     // Ensuring an anonymous query makes no sense
@@ -753,19 +663,21 @@ where
 
     let dep_node = query.to_dep_node(*tcx.dep_context(), key);
 
-    match tcx.dep_context().dep_graph().try_mark_green_and_read(tcx, &dep_node) {
+    let dep_graph = tcx.dep_context().dep_graph();
+    match dep_graph.try_mark_green(tcx, &dep_node) {
         None => {
-            // A None return from `try_mark_green_and_read` means that this is either
+            // A None return from `try_mark_green` means that this is either
             // a new dep node or that the dep node has already been marked red.
             // Either way, we can't call `dep_graph.read()` as we don't have the
             // DepNodeIndex. We must invoke the query itself. The performance cost
             // this introduces should be negligible as we'll immediately hit the
             // in-memory cache, or another query down the line will.
-            true
+            (true, Some(dep_node))
         }
         Some((_, dep_node_index)) => {
+            dep_graph.read_index(dep_node_index);
             tcx.dep_context().profiler().query_cache_hit(dep_node_index.into());
-            false
+            (false, None)
         }
     }
 }
@@ -804,23 +716,8 @@ where
         Err(lookup) => lookup,
     };
 
-    let job = match JobOwner::<'_, CTX::DepKind, C>::try_start(
-        tcx,
-        state,
-        cache,
-        DUMMY_SP,
-        key.clone(),
-        lookup,
-        query,
-    ) {
-        TryGetJob::NotYetStarted(job) => job,
-        TryGetJob::Cycle(_) => return true,
-        #[cfg(parallel_compiler)]
-        TryGetJob::JobCompleted(_) => return true,
-    };
-
-    force_query_with_job(tcx, key, job, dep_node, query, compute);
-
+    let _ =
+        try_execute_query(tcx, state, cache, DUMMY_SP, key, lookup, Some(dep_node), query, compute);
     true
 }
 
@@ -842,25 +739,33 @@ where
     CTX: QueryContext,
 {
     let query = &Q::VTABLE;
-    if let QueryMode::Ensure = mode {
-        if !ensure_must_run(tcx, &key, query) {
+    let dep_node = if let QueryMode::Ensure = mode {
+        let (must_run, dep_node) = ensure_must_run(tcx, &key, query);
+        if !must_run {
             return None;
         }
-    }
+        dep_node
+    } else {
+        None
+    };
 
     debug!("ty::query::get_query<{}>(key={:?}, span={:?})", Q::NAME, key, span);
     let compute = Q::compute_fn(tcx, &key);
-    let value = get_query_impl(
+    let (result, dep_node_index) = try_execute_query(
         tcx,
         Q::query_state(tcx),
         Q::query_cache(tcx),
         span,
         key,
         lookup,
+        dep_node,
         query,
         compute,
     );
-    Some(value)
+    if let Some(dep_node_index) = dep_node_index {
+        tcx.dep_context().dep_graph().read_index(dep_node_index)
+    }
+    Some(result)
 }
 
 pub fn force_query<Q, CTX>(tcx: CTX, dep_node: &DepNode<CTX::DepKind>) -> bool
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 2ee483d850e..55f2b04c4f1 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -228,7 +228,6 @@ impl<'a> Resolver<'a> {
     crate fn build_reduced_graph_external(&mut self, module: Module<'a>) {
         let def_id = module.def_id().expect("unpopulated module without a def-id");
         for child in self.cstore().item_children_untracked(def_id, self.session) {
-            let child = child.map_id(|_| panic!("unexpected id"));
             let parent_scope = ParentScope::module(module, self);
             BuildReducedGraphVisitor { r: self, parent_scope }
                 .build_reduced_graph_for_external_crate_res(child);
@@ -946,9 +945,10 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
     }
 
     /// Builds the reduced graph for a single item in an external crate.
-    fn build_reduced_graph_for_external_crate_res(&mut self, child: Export<NodeId>) {
+    fn build_reduced_graph_for_external_crate_res(&mut self, child: Export) {
         let parent = self.parent_scope.module;
         let Export { ident, res, vis, span } = child;
+        let res = res.expect_non_local();
         let expansion = self.parent_scope.expansion;
         // Record primary definitions.
         match res {
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 6f4f1bdaea1..5879cb1daa5 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -32,7 +32,13 @@ impl<'a, 'b> DefCollector<'a, 'b> {
     fn create_def(&mut self, node_id: NodeId, data: DefPathData, span: Span) -> LocalDefId {
         let parent_def = self.parent_def;
         debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
-        self.resolver.create_def(parent_def, node_id, data, self.expansion.to_expn_id(), span)
+        self.resolver.create_def(
+            parent_def,
+            node_id,
+            data,
+            self.expansion.to_expn_id(),
+            span.with_parent(None),
+        )
     }
 
     fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: LocalDefId, f: F) {
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index dfb6d89a0d1..d4782edbc13 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -11,7 +11,6 @@ use crate::{NameBinding, NameBindingKind, PathResult, PrivacyError, ToNameBindin
 
 use rustc_ast::unwrap_or;
 use rustc_ast::NodeId;
-use rustc_ast_lowering::ResolverAstLowering;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::ptr_key::PtrKey;
 use rustc_errors::{pluralize, struct_span_err, Applicability};
@@ -1387,13 +1386,13 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
 
         let mut reexports = Vec::new();
 
-        module.for_each_child(self.r, |this, ident, _, binding| {
+        module.for_each_child(self.r, |_, ident, _, binding| {
             // Filter away ambiguous imports and anything that has def-site hygiene.
             // FIXME: Implement actual cross-crate hygiene.
             let is_good_import =
                 binding.is_import() && !binding.is_ambiguity() && !ident.span.from_expansion();
             if is_good_import || binding.is_macro_def() {
-                let res = binding.res().map_id(|id| this.local_def_id(id));
+                let res = binding.res().expect_non_local();
                 if res != def::Res::Err {
                     reexports.push(Export { ident, res, span: binding.span, vis: binding.vis });
                 }
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index b2c0c787465..19136c6ceeb 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -12,7 +12,7 @@ use rustc_ast::{
 };
 use rustc_ast_pretty::pprust::path_segment_to_string;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, SuggestionStyle};
+use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
@@ -768,6 +768,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                                             args[1].span.lo(),
                                             args.last().unwrap().span.hi(),
                                             call_span.ctxt(),
+                                            None,
                                         ))
                                     } else {
                                         None
@@ -1959,11 +1960,10 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                             introduce_suggestion.push((*span, formatter(&lt_name)));
                         }
                     }
-                    err.multipart_suggestion_with_style(
+                    err.multipart_suggestion_verbose(
                         &msg,
                         introduce_suggestion,
                         Applicability::MaybeIncorrect,
-                        SuggestionStyle::ShowAlways,
                     );
                 }
 
@@ -1975,14 +1975,13 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                     })
                     .map(|(formatter, span)| (*span, formatter(name)))
                     .collect();
-                err.multipart_suggestion_with_style(
+                err.multipart_suggestion_verbose(
                     &format!(
                         "consider using the `{}` lifetime",
                         lifetime_names.iter().next().unwrap()
                     ),
                     spans_suggs,
                     Applicability::MaybeIncorrect,
-                    SuggestionStyle::ShowAlways,
                 );
             };
         let suggest_new = |err: &mut DiagnosticBuilder<'_>, suggs: Vec<Option<String>>| {
@@ -2073,11 +2072,10 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                             };
                             spans_suggs.push((span, sugg.to_string()));
                         }
-                        err.multipart_suggestion_with_style(
+                        err.multipart_suggestion_verbose(
                             "consider using the `'static` lifetime",
                             spans_suggs,
                             Applicability::MaybeIncorrect,
-                            SuggestionStyle::ShowAlways,
                         );
                         continue;
                     }
@@ -2162,11 +2160,10 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                         .unwrap_or((span, sugg));
                     introduce_suggestion.push((span, sugg.to_string()));
                 }
-                err.multipart_suggestion_with_style(
+                err.multipart_suggestion_verbose(
                     &msg,
                     introduce_suggestion,
                     Applicability::MaybeIncorrect,
-                    SuggestionStyle::ShowAlways,
                 );
                 if should_break {
                     break;
@@ -2242,11 +2239,10 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
                 if spans_suggs.len() > 0 {
                     // This happens when we have `Foo<T>` where we point at the space before `T`,
                     // but this can be confusing so we give a suggestion with placeholders.
-                    err.multipart_suggestion_with_style(
+                    err.multipart_suggestion_verbose(
                         "consider using one of the available lifetimes here",
                         spans_suggs,
                         Applicability::HasPlaceholders,
-                        SuggestionStyle::ShowAlways,
                     );
                 }
             }
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 6d2961db9e3..d76ba80e42e 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -14,6 +14,7 @@
 #![feature(crate_visibility_modifier)]
 #![feature(format_args_capture)]
 #![feature(iter_zip)]
+#![feature(never_type)]
 #![feature(nll)]
 #![recursion_limit = "256"]
 #![allow(rustdoc::private_intra_doc_links)]
@@ -911,7 +912,7 @@ pub struct Resolver<'a> {
 
     /// `CrateNum` resolutions of `extern crate` items.
     extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
-    export_map: ExportMap<LocalDefId>,
+    export_map: ExportMap,
     trait_map: Option<NodeMap<Vec<TraitCandidate>>>,
 
     /// A map from nodes to anonymous modules.
@@ -1012,8 +1013,6 @@ pub struct Resolver<'a> {
 
     next_node_id: NodeId,
 
-    def_id_to_span: IndexVec<LocalDefId, Span>,
-
     node_id_to_def_id: FxHashMap<ast::NodeId, LocalDefId>,
     def_id_to_node_id: IndexVec<LocalDefId, ast::NodeId>,
 
@@ -1116,6 +1115,11 @@ impl ResolverAstLowering for Resolver<'_> {
         }
     }
 
+    #[inline]
+    fn def_span(&self, id: LocalDefId) -> Span {
+        self.definitions.def_span(id)
+    }
+
     fn item_generics_num_lifetimes(&self, def_id: DefId) -> usize {
         if let Some(def_id) = def_id.as_local() {
             self.item_generics_num_lifetimes[&def_id]
@@ -1197,9 +1201,7 @@ impl ResolverAstLowering for Resolver<'_> {
             disambiguator
         };
 
-        let def_id = self.definitions.create_def(parent, data, expn_id, next_disambiguator);
-
-        assert_eq!(self.def_id_to_span.push(span), def_id);
+        let def_id = self.definitions.create_def(parent, data, expn_id, next_disambiguator, span);
 
         // Some things for which we allocate `LocalDefId`s don't correspond to
         // anything in the AST, so they don't have a `NodeId`. For these cases
@@ -1226,6 +1228,11 @@ impl<'a, 'b> rustc_span::HashStableContext for ExpandHasher<'a, 'b> {
     }
 
     #[inline]
+    fn def_span(&self, id: LocalDefId) -> Span {
+        self.resolver.def_span(id)
+    }
+
+    #[inline]
     fn def_path_hash(&self, def_id: DefId) -> DefPathHash {
         self.resolver.def_path_hash(def_id)
     }
@@ -1269,14 +1276,12 @@ 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(session.local_stable_crate_id(), krate.span);
         let root = definitions.get_root_def();
 
         let mut visibilities = FxHashMap::default();
         visibilities.insert(root_local_def_id, ty::Visibility::Public);
 
-        let mut def_id_to_span = IndexVec::default();
-        assert_eq!(def_id_to_span.push(rustc_span::DUMMY_SP), root);
         let mut def_id_to_node_id = IndexVec::default();
         assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), root);
         let mut node_id_to_def_id = FxHashMap::default();
@@ -1393,7 +1398,6 @@ impl<'a> Resolver<'a> {
                 .collect(),
             lint_buffer: LintBuffer::default(),
             next_node_id: NodeId::from_u32(1),
-            def_id_to_span,
             node_id_to_def_id,
             def_id_to_node_id,
             placeholder_field_indices: Default::default(),
@@ -1487,7 +1491,7 @@ impl<'a> Resolver<'a> {
                 .iter()
                 .map(|(ident, entry)| (ident.name, entry.introduced_by_item))
                 .collect(),
-            main_def: self.main_def.clone(),
+            main_def: self.main_def,
             trait_impls: self.trait_impls.clone(),
             proc_macros,
             confused_type_with_std_module: self.confused_type_with_std_module.clone(),
@@ -3360,7 +3364,7 @@ impl<'a> Resolver<'a> {
     /// Retrieves the span of the given `DefId` if `DefId` is in the local crate.
     #[inline]
     pub fn opt_span(&self, def_id: DefId) -> Option<Span> {
-        if let Some(def_id) = def_id.as_local() { Some(self.def_id_to_span[def_id]) } else { None }
+        def_id.as_local().map(|def_id| self.definitions.def_span(def_id))
     }
 
     /// Checks if an expression refers to a function marked with
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 6dc3aa0888a..4dbac47c3cc 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -180,6 +180,10 @@ impl<'a> ResolverExpand for Resolver<'a> {
         self.next_node_id()
     }
 
+    fn invocation_parent(&self, id: LocalExpnId) -> LocalDefId {
+        self.invocation_parents[&id].0
+    }
+
     fn resolve_dollar_crates(&mut self) {
         hygiene::update_dollar_crate_names(|ctxt| {
             let ident = Ident::new(kw::DollarCrate, DUMMY_SP.with_ctxt(ctxt));
diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs
index 41d174cde0a..0f9257809fe 100644
--- a/compiler/rustc_save_analysis/src/lib.rs
+++ b/compiler/rustc_save_analysis/src/lib.rs
@@ -1,7 +1,6 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![feature(if_let_guard)]
 #![feature(nll)]
-#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard
 #![recursion_limit = "256"]
 
 mod dump_visitor;
diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs
index ecc8dae0480..e32e4493726 100644
--- a/compiler/rustc_serialize/src/serialize.rs
+++ b/compiler/rustc_serialize/src/serialize.rs
@@ -366,6 +366,18 @@ direct_serialize_impls! {
     char emit_char read_char
 }
 
+impl<S: Encoder> Encodable<S> for ! {
+    fn encode(&self, _s: &mut S) -> Result<(), S::Error> {
+        unreachable!()
+    }
+}
+
+impl<D: Decoder> Decodable<D> for ! {
+    fn decode(_d: &mut D) -> Result<!, D::Error> {
+        unreachable!()
+    }
+}
+
 impl<S: Encoder> Encodable<S> for ::std::num::NonZeroU32 {
     fn encode(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_u32(self.get())
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index fdedb7e6a4a..32aa035e1cd 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1920,9 +1920,10 @@ fn parse_extern_dep_specs(
 
 fn parse_remap_path_prefix(
     matches: &getopts::Matches,
+    debugging_opts: &DebuggingOptions,
     error_format: ErrorOutputType,
 ) -> Vec<(PathBuf, PathBuf)> {
-    matches
+    let mut mapping: Vec<(PathBuf, PathBuf)> = matches
         .opt_strs("remap-path-prefix")
         .into_iter()
         .map(|remap| match remap.rsplit_once('=') {
@@ -1932,7 +1933,15 @@ fn parse_remap_path_prefix(
             ),
             Some((from, to)) => (PathBuf::from(from), PathBuf::from(to)),
         })
-        .collect()
+        .collect();
+    match &debugging_opts.remap_cwd_prefix {
+        Some(to) => match std::env::current_dir() {
+            Ok(cwd) => mapping.push((cwd, to.clone())),
+            Err(_) => (),
+        },
+        None => (),
+    };
+    mapping
 }
 
 pub fn build_session_options(matches: &getopts::Matches) -> Options {
@@ -2077,7 +2086,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
 
     let crate_name = matches.opt_str("crate-name");
 
-    let remap_path_prefix = parse_remap_path_prefix(matches, error_format);
+    let remap_path_prefix = parse_remap_path_prefix(matches, &debugging_opts, error_format);
 
     let pretty = parse_pretty(&debugging_opts, error_format);
 
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 9a1be40558c..8110afe75fa 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -349,6 +349,7 @@ mod desc {
     pub const parse_threads: &str = parse_number;
     pub const parse_passes: &str = "a space-separated list of passes, or `all`";
     pub const parse_panic_strategy: &str = "either `unwind` or `abort`";
+    pub const parse_opt_panic_strategy: &str = parse_panic_strategy;
     pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
     pub const parse_sanitizers: &str =
         "comma separated list of sanitizers: `address`, `hwaddress`, `leak`, `memory` or `thread`";
@@ -549,7 +550,7 @@ mod parse {
         }
     }
 
-    crate fn parse_panic_strategy(slot: &mut Option<PanicStrategy>, v: Option<&str>) -> bool {
+    crate fn parse_opt_panic_strategy(slot: &mut Option<PanicStrategy>, v: Option<&str>) -> bool {
         match v {
             Some("unwind") => *slot = Some(PanicStrategy::Unwind),
             Some("abort") => *slot = Some(PanicStrategy::Abort),
@@ -558,6 +559,15 @@ mod parse {
         true
     }
 
+    crate fn parse_panic_strategy(slot: &mut PanicStrategy, v: Option<&str>) -> bool {
+        match v {
+            Some("unwind") => *slot = PanicStrategy::Unwind,
+            Some("abort") => *slot = PanicStrategy::Abort,
+            _ => return false,
+        }
+        true
+    }
+
     crate fn parse_relro_level(slot: &mut Option<RelroLevel>, v: Option<&str>) -> bool {
         match v {
             Some(s) => match s.parse::<RelroLevel>() {
@@ -958,7 +968,7 @@ options! {
         "optimization level (0-3, s, or z; default: 0)"),
     overflow_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "use overflow checks for integer arithmetic"),
-    panic: Option<PanicStrategy> = (None, parse_panic_strategy, [TRACKED],
+    panic: Option<PanicStrategy> = (None, parse_opt_panic_strategy, [TRACKED],
         "panic strategy to compile crate with"),
     passes: Vec<String> = (Vec::new(), parse_list, [TRACKED],
         "a list of extra LLVM passes to run (space separated)"),
@@ -1106,6 +1116,8 @@ options! {
     incremental_info: bool = (false, parse_bool, [UNTRACKED],
         "print high-level information about incremental reuse (or the lack thereof) \
         (default: no)"),
+    incremental_relative_spans: bool = (false, parse_bool, [TRACKED],
+        "hash spans relative to their parent item for incr. comp. (default: no)"),
     incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED],
         "verify incr. comp. hashes of green query instances (default: no)"),
     inline_mir: Option<bool> = (None, parse_opt_bool, [TRACKED],
@@ -1184,6 +1196,8 @@ options! {
         "pass `-install_name @rpath/...` to the macOS linker (default: no)"),
     panic_abort_tests: bool = (false, parse_bool, [TRACKED],
         "support compiling tests with panic=abort (default: no)"),
+    panic_in_drop: PanicStrategy = (PanicStrategy::Unwind, parse_panic_strategy, [TRACKED],
+        "panic strategy for panics in drops"),
     parse_only: bool = (false, parse_bool, [UNTRACKED],
         "parse only; do not compile, assemble, or link (default: no)"),
     partially_uninit_const_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
@@ -1236,6 +1250,8 @@ options! {
         "whether ELF relocations can be relaxed"),
     relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
         "choose which RELRO level to use"),
+    remap_cwd_prefix: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
+        "remap paths under the current working directory to this path prefix"),
     simulate_remapped_rust_src_base: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
         "simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \
         to rust's source base directory. only meant for testing purposes"),
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 58ea29c080f..d6f4a3ae4f1 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -169,6 +169,9 @@ pub struct Session {
     /// Data about code being compiled, gathered during compilation.
     pub code_stats: CodeStats,
 
+    /// If `-zfuel=crate=n` is specified, `Some(crate)`.
+    optimization_fuel_crate: Option<String>,
+
     /// Tracks fuel info if `-zfuel=crate=n` is specified.
     optimization_fuel: Lock<OptimizationFuel>,
 
@@ -893,7 +896,7 @@ impl Session {
     /// This expends fuel if applicable, and records fuel if applicable.
     pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
         let mut ret = true;
-        if let Some(c) = self.opts.debugging_opts.fuel.as_ref().map(|i| &i.0) {
+        if let Some(ref c) = self.optimization_fuel_crate {
             if c == crate_name {
                 assert_eq!(self.threads(), 1);
                 let mut fuel = self.optimization_fuel.lock();
@@ -1266,6 +1269,7 @@ pub fn build_session(
     let local_crate_source_file =
         local_crate_source_file.map(|path| file_path_mapping.map_prefix(path).0);
 
+    let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone());
     let optimization_fuel = Lock::new(OptimizationFuel {
         remaining: sopts.debugging_opts.fuel.as_ref().map_or(0, |i| i.1),
         out_of_fuel: false,
@@ -1317,6 +1321,7 @@ pub fn build_session(
             normalize_projection_ty: AtomicUsize::new(0),
         },
         code_stats: Default::default(),
+        optimization_fuel_crate,
         optimization_fuel,
         print_fuel,
         jobserver: jobserver::client(),
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index c22093c5a42..ef60608a27c 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -1357,9 +1357,7 @@ fn for_all_expns_in<E>(
     mut f: impl FnMut(ExpnId, &ExpnData, ExpnHash) -> Result<(), E>,
 ) -> Result<(), E> {
     let all_data: Vec<_> = HygieneData::with(|data| {
-        expns
-            .map(|expn| (expn, data.expn_data(expn).clone(), data.expn_hash(expn).clone()))
-            .collect()
+        expns.map(|expn| (expn, data.expn_data(expn).clone(), data.expn_hash(expn))).collect()
     });
     for (expn, data, hash) in all_data.into_iter() {
         f(expn, &data, hash)?;
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index b4cc8b2b4a3..eb496140553 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -21,7 +21,6 @@
 #![feature(nll)]
 #![feature(min_specialization)]
 #![feature(thread_local_const_init)]
-#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard
 
 #[macro_use]
 extern crate rustc_macros;
@@ -42,7 +41,7 @@ use hygiene::Transparency;
 pub use hygiene::{DesugaringKind, ExpnKind, ForLoopLoc, MacroKind};
 pub use hygiene::{ExpnData, ExpnHash, ExpnId, LocalExpnId, SyntaxContext};
 pub mod def_id;
-use def_id::{CrateNum, DefId, DefPathHash, LOCAL_CRATE};
+use def_id::{CrateNum, DefId, DefPathHash, LocalDefId, LOCAL_CRATE};
 pub mod lev_distance;
 mod span_encoding;
 pub use span_encoding::{Span, DUMMY_SP};
@@ -435,24 +434,38 @@ pub struct SpanData {
     /// Information about where the macro came from, if this piece of
     /// code was created by a macro expansion.
     pub ctxt: SyntaxContext,
+    pub parent: Option<LocalDefId>,
 }
 
 impl SpanData {
     #[inline]
     pub fn span(&self) -> Span {
-        Span::new(self.lo, self.hi, self.ctxt)
+        Span::new(self.lo, self.hi, self.ctxt, self.parent)
     }
     #[inline]
     pub fn with_lo(&self, lo: BytePos) -> Span {
-        Span::new(lo, self.hi, self.ctxt)
+        Span::new(lo, self.hi, self.ctxt, self.parent)
     }
     #[inline]
     pub fn with_hi(&self, hi: BytePos) -> Span {
-        Span::new(self.lo, hi, self.ctxt)
+        Span::new(self.lo, hi, self.ctxt, self.parent)
     }
     #[inline]
     pub fn with_ctxt(&self, ctxt: SyntaxContext) -> Span {
-        Span::new(self.lo, self.hi, ctxt)
+        Span::new(self.lo, self.hi, ctxt, self.parent)
+    }
+    #[inline]
+    pub fn with_parent(&self, parent: Option<LocalDefId>) -> Span {
+        Span::new(self.lo, self.hi, self.ctxt, parent)
+    }
+    /// Returns `true` if this is a dummy span with any hygienic context.
+    #[inline]
+    pub fn is_dummy(self) -> bool {
+        self.lo.0 == 0 && self.hi.0 == 0
+    }
+    /// Returns `true` if `self` fully encloses `other`.
+    pub fn contains(self, other: Self) -> bool {
+        self.lo <= other.lo && other.hi <= self.hi
     }
 }
 
@@ -508,18 +521,25 @@ impl Span {
     }
     #[inline]
     pub fn ctxt(self) -> SyntaxContext {
-        self.data().ctxt
+        self.data_untracked().ctxt
     }
     #[inline]
     pub fn with_ctxt(self, ctxt: SyntaxContext) -> Span {
-        self.data().with_ctxt(ctxt)
+        self.data_untracked().with_ctxt(ctxt)
+    }
+    #[inline]
+    pub fn parent(self) -> Option<LocalDefId> {
+        self.data().parent
+    }
+    #[inline]
+    pub fn with_parent(self, ctxt: Option<LocalDefId>) -> Span {
+        self.data().with_parent(ctxt)
     }
 
     /// Returns `true` if this is a dummy span with any hygienic context.
     #[inline]
     pub fn is_dummy(self) -> bool {
-        let span = self.data();
-        span.lo.0 == 0 && span.hi.0 == 0
+        self.data_untracked().is_dummy()
     }
 
     /// Returns `true` if this span comes from a macro or desugaring.
@@ -535,26 +555,26 @@ impl Span {
 
     #[inline]
     pub fn with_root_ctxt(lo: BytePos, hi: BytePos) -> Span {
-        Span::new(lo, hi, SyntaxContext::root())
+        Span::new(lo, hi, SyntaxContext::root(), None)
     }
 
     /// Returns a new span representing an empty span at the beginning of this span.
     #[inline]
     pub fn shrink_to_lo(self) -> Span {
-        let span = self.data();
+        let span = self.data_untracked();
         span.with_hi(span.lo)
     }
     /// Returns a new span representing an empty span at the end of this span.
     #[inline]
     pub fn shrink_to_hi(self) -> Span {
-        let span = self.data();
+        let span = self.data_untracked();
         span.with_lo(span.hi)
     }
 
     #[inline]
     /// Returns `true` if `hi == lo`.
     pub fn is_empty(&self) -> bool {
-        let span = self.data();
+        let span = self.data_untracked();
         span.hi == span.lo
     }
 
@@ -567,7 +587,7 @@ impl Span {
     pub fn contains(self, other: Span) -> bool {
         let span = self.data();
         let other = other.data();
-        span.lo <= other.lo && other.hi <= span.hi
+        span.contains(other)
     }
 
     /// Returns `true` if `self` touches `other`.
@@ -603,7 +623,7 @@ impl Span {
 
     /// The `Span` for the tokens in the previous macro expansion from which `self` was generated,
     /// if any.
-    pub fn parent(self) -> Option<Span> {
+    pub fn parent_callsite(self) -> Option<Span> {
         let expn_data = self.ctxt().outer_expn_data();
         if !expn_data.is_root() { Some(expn_data.call_site) } else { None }
     }
@@ -611,7 +631,7 @@ impl Span {
     /// Walk down the expansion ancestors to find a span that's contained within `outer`.
     pub fn find_ancestor_inside(mut self, outer: Span) -> Option<Span> {
         while !outer.contains(self) {
-            self = self.parent()?;
+            self = self.parent_callsite()?;
         }
         Some(self)
     }
@@ -732,6 +752,7 @@ impl Span {
             cmp::min(span_data.lo, end_data.lo),
             cmp::max(span_data.hi, end_data.hi),
             if span_data.ctxt == SyntaxContext::root() { end_data.ctxt } else { span_data.ctxt },
+            if span_data.parent == end_data.parent { span_data.parent } else { None },
         )
     }
 
@@ -749,6 +770,7 @@ impl Span {
             span.hi,
             end.lo,
             if end.ctxt == SyntaxContext::root() { end.ctxt } else { span.ctxt },
+            if span.parent == end.parent { span.parent } else { None },
         )
     }
 
@@ -766,6 +788,7 @@ impl Span {
             span.lo,
             end.lo,
             if end.ctxt == SyntaxContext::root() { end.ctxt } else { span.ctxt },
+            if span.parent == end.parent { span.parent } else { None },
         )
     }
 
@@ -775,6 +798,7 @@ impl Span {
             span.lo + BytePos::from_usize(inner.start),
             span.lo + BytePos::from_usize(inner.end),
             span.ctxt,
+            span.parent,
         )
     }
 
@@ -813,7 +837,7 @@ impl Span {
     pub fn remove_mark(&mut self) -> ExpnId {
         let mut span = self.data();
         let mark = span.ctxt.remove_mark();
-        *self = Span::new(span.lo, span.hi, span.ctxt);
+        *self = Span::new(span.lo, span.hi, span.ctxt, span.parent);
         mark
     }
 
@@ -821,7 +845,7 @@ impl Span {
     pub fn adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
         let mut span = self.data();
         let mark = span.ctxt.adjust(expn_id);
-        *self = Span::new(span.lo, span.hi, span.ctxt);
+        *self = Span::new(span.lo, span.hi, span.ctxt, span.parent);
         mark
     }
 
@@ -829,7 +853,7 @@ impl Span {
     pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
         let mut span = self.data();
         let mark = span.ctxt.normalize_to_macros_2_0_and_adjust(expn_id);
-        *self = Span::new(span.lo, span.hi, span.ctxt);
+        *self = Span::new(span.lo, span.hi, span.ctxt, span.parent);
         mark
     }
 
@@ -837,7 +861,7 @@ impl Span {
     pub fn glob_adjust(&mut self, expn_id: ExpnId, glob_span: Span) -> Option<Option<ExpnId>> {
         let mut span = self.data();
         let mark = span.ctxt.glob_adjust(expn_id, glob_span);
-        *self = Span::new(span.lo, span.hi, span.ctxt);
+        *self = Span::new(span.lo, span.hi, span.ctxt, span.parent);
         mark
     }
 
@@ -849,7 +873,7 @@ impl Span {
     ) -> Option<Option<ExpnId>> {
         let mut span = self.data();
         let mark = span.ctxt.reverse_glob_adjust(expn_id, glob_span);
-        *self = Span::new(span.lo, span.hi, span.ctxt);
+        *self = Span::new(span.lo, span.hi, span.ctxt, span.parent);
         mark
     }
 
@@ -901,7 +925,7 @@ impl<D: Decoder> Decodable<D> for Span {
             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()))
+            Ok(Span::new(lo, hi, SyntaxContext::root(), None))
         })
     }
 }
@@ -962,7 +986,7 @@ impl fmt::Debug for Span {
 
 impl fmt::Debug for SpanData {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        (*SPAN_DEBUG)(Span::new(self.lo, self.hi, self.ctxt), f)
+        (*SPAN_DEBUG)(Span::new(self.lo, self.hi, self.ctxt, self.parent), f)
     }
 }
 
@@ -1923,6 +1947,7 @@ pub struct FileLines {
 
 pub static SPAN_DEBUG: AtomicRef<fn(Span, &mut fmt::Formatter<'_>) -> fmt::Result> =
     AtomicRef::new(&(default_span_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
+pub static SPAN_TRACK: AtomicRef<fn(LocalDefId)> = AtomicRef::new(&((|_| {}) as fn(_)));
 
 // _____________________________________________________________________________
 // SpanLinesError, SpanSnippetError, DistinctSources, MalformedSourceMapPositions
@@ -1977,6 +2002,7 @@ impl InnerSpan {
 pub trait HashStableContext {
     fn def_path_hash(&self, def_id: DefId) -> DefPathHash;
     fn hash_spans(&self) -> bool;
+    fn def_span(&self, def_id: LocalDefId) -> Span;
     fn span_data_to_lines_and_cols(
         &mut self,
         span: &SpanData,
@@ -2000,22 +2026,35 @@ where
     fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
         const TAG_VALID_SPAN: u8 = 0;
         const TAG_INVALID_SPAN: u8 = 1;
+        const TAG_RELATIVE_SPAN: u8 = 2;
 
         if !ctx.hash_spans() {
             return;
         }
 
-        self.ctxt().hash_stable(ctx, hasher);
+        let span = self.data_untracked();
+        span.ctxt.hash_stable(ctx, hasher);
+        span.parent.hash_stable(ctx, hasher);
 
-        if self.is_dummy() {
+        if span.is_dummy() {
             Hash::hash(&TAG_INVALID_SPAN, hasher);
             return;
         }
 
+        if let Some(parent) = span.parent {
+            let def_span = ctx.def_span(parent).data_untracked();
+            if def_span.contains(span) {
+                // This span is enclosed in a definition: only hash the relative position.
+                Hash::hash(&TAG_RELATIVE_SPAN, hasher);
+                (span.lo - def_span.lo).to_u32().hash_stable(ctx, hasher);
+                (span.hi - def_span.lo).to_u32().hash_stable(ctx, hasher);
+                return;
+            }
+        }
+
         // If this is not an empty or invalid span, we want to hash the last
         // position that belongs to it, as opposed to hashing the first
         // position past it.
-        let span = self.data();
         let (file, line_lo, col_lo, line_hi, col_hi) = match ctx.span_data_to_lines_and_cols(&span)
         {
             Some(pos) => pos,
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 9b8c8594ee8..9e403eb3f67 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -794,7 +794,7 @@ impl SourceMap {
             start_of_next_point.checked_add(width - 1).unwrap_or(start_of_next_point);
 
         let end_of_next_point = BytePos(cmp::max(sp.lo().0 + 1, end_of_next_point));
-        Span::new(BytePos(start_of_next_point), end_of_next_point, sp.ctxt())
+        Span::new(BytePos(start_of_next_point), end_of_next_point, sp.ctxt(), None)
     }
 
     /// Finds the width of the character, either before or after the end of provided span,
diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs
index cb017709c6c..e9120b98aab 100644
--- a/compiler/rustc_span/src/span_encoding.rs
+++ b/compiler/rustc_span/src/span_encoding.rs
@@ -4,7 +4,9 @@
 // The encoding format for inline spans were obtained by optimizing over crates in rustc/libstd.
 // See https://internals.rust-lang.org/t/rfc-compiler-refactoring-spans/1357/28
 
+use crate::def_id::LocalDefId;
 use crate::hygiene::SyntaxContext;
+use crate::SPAN_TRACK;
 use crate::{BytePos, SpanData};
 
 use rustc_data_structures::fx::FxIndexSet;
@@ -54,6 +56,10 @@ use rustc_data_structures::fx::FxIndexSet;
 ///   the code. No crates in `rustc-perf` need more than 15 bits for `ctxt`,
 ///   but larger crates might need more than 16 bits.
 ///
+/// In order to reliably use parented spans in incremental compilation,
+/// the dependency to the parent definition's span. This is performed
+/// using the callback `SPAN_TRACK` to access the query engine.
+///
 #[derive(Clone, Copy, Eq, PartialEq, Hash)]
 pub struct Span {
     base_or_index: u32,
@@ -70,25 +76,42 @@ pub const DUMMY_SP: Span = Span { base_or_index: 0, len_or_tag: 0, ctxt_or_zero:
 
 impl Span {
     #[inline]
-    pub fn new(mut lo: BytePos, mut hi: BytePos, ctxt: SyntaxContext) -> Self {
+    pub fn new(
+        mut lo: BytePos,
+        mut hi: BytePos,
+        ctxt: SyntaxContext,
+        parent: Option<LocalDefId>,
+    ) -> Self {
         if lo > hi {
             std::mem::swap(&mut lo, &mut hi);
         }
 
         let (base, len, ctxt2) = (lo.0, hi.0 - lo.0, ctxt.as_u32());
 
-        if len <= MAX_LEN && ctxt2 <= MAX_CTXT {
+        if len <= MAX_LEN && ctxt2 <= MAX_CTXT && parent.is_none() {
             // Inline format.
             Span { base_or_index: base, len_or_tag: len as u16, ctxt_or_zero: ctxt2 as u16 }
         } else {
             // Interned format.
-            let index = with_span_interner(|interner| interner.intern(&SpanData { lo, hi, ctxt }));
+            let index =
+                with_span_interner(|interner| interner.intern(&SpanData { lo, hi, ctxt, parent }));
             Span { base_or_index: index, len_or_tag: LEN_TAG, ctxt_or_zero: 0 }
         }
     }
 
     #[inline]
     pub fn data(self) -> SpanData {
+        let data = self.data_untracked();
+        if let Some(parent) = data.parent {
+            (*SPAN_TRACK)(parent);
+        }
+        data
+    }
+
+    /// Internal function to translate between an encoded span and the expanded representation.
+    /// This function must not be used outside the incremental engine.
+    #[inline]
+    pub fn data_untracked(self) -> SpanData {
         if self.len_or_tag != LEN_TAG {
             // Inline format.
             debug_assert!(self.len_or_tag as u32 <= MAX_LEN);
@@ -96,6 +119,7 @@ impl Span {
                 lo: BytePos(self.base_or_index),
                 hi: BytePos(self.base_or_index + self.len_or_tag as u32),
                 ctxt: SyntaxContext::from_u32(self.ctxt_or_zero as u32),
+                parent: None,
             }
         } else {
             // Interned format.
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 24023163cc3..760357644a5 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -934,7 +934,6 @@ symbols! {
         panic_unwind,
         panicking,
         param_attrs,
-        parent_trait,
         partial_cmp,
         partial_ord,
         passes,
@@ -1134,6 +1133,7 @@ symbols! {
         rustc_synthetic,
         rustc_test_marker,
         rustc_then_this_would_need,
+        rustc_trivial_field_reads,
         rustc_unsafe_specialization_marker,
         rustc_variance,
         rustdoc,
@@ -1358,7 +1358,6 @@ symbols! {
         unix,
         unlikely,
         unmarked_api,
-        unnamed_fields,
         unpin,
         unreachable,
         unreachable_code,
@@ -1418,6 +1417,7 @@ symbols! {
         wrapping_sub,
         wreg,
         write_bytes,
+        write_str,
         x87_reg,
         xer,
         xmm_reg,
@@ -1700,8 +1700,11 @@ impl<CTX> ToStableHashKey<CTX> for Symbol {
 // The `FxHashMap`+`Vec` pair could be replaced by `FxIndexSet`, but #75278
 // found that to regress performance up to 2% in some cases. This might be
 // revisited after further improvements to `indexmap`.
+//
+// This type is private to prevent accidentally constructing more than one `Interner` on the same
+// thread, which makes it easy to mixup `Symbol`s between `Interner`s.
 #[derive(Default)]
-pub struct Interner {
+pub(crate) struct Interner {
     arena: DroplessArena,
     names: FxHashMap<&'static str, Symbol>,
     strings: Vec<&'static str>,
diff --git a/compiler/rustc_target/src/abi/call/mips64.rs b/compiler/rustc_target/src/abi/call/mips64.rs
index 28ca93c4692..2e00ffc7e14 100644
--- a/compiler/rustc_target/src/abi/call/mips64.rs
+++ b/compiler/rustc_target/src/abi/call/mips64.rs
@@ -3,7 +3,7 @@ use crate::abi::{self, HasDataLayout, Size, TyAbiInterface};
 
 fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) {
     // Always sign extend u32 values on 64-bit mips
-    if let abi::Abi::Scalar(ref scalar) = arg.layout.abi {
+    if let abi::Abi::Scalar(scalar) = arg.layout.abi {
         if let abi::Int(i, signed) = scalar.value {
             if !signed && i.size().bits() == 32 {
                 if let PassMode::Direct(ref mut attrs) = arg.mode {
@@ -23,7 +23,7 @@ where
     C: HasDataLayout,
 {
     match ret.layout.field(cx, i).abi {
-        abi::Abi::Scalar(ref scalar) => match scalar.value {
+        abi::Abi::Scalar(scalar) => match scalar.value {
             abi::F32 => Some(Reg::f32()),
             abi::F64 => Some(Reg::f64()),
             _ => None,
@@ -107,7 +107,7 @@ where
                 let offset = arg.layout.fields.offset(i);
 
                 // We only care about aligned doubles
-                if let abi::Abi::Scalar(ref scalar) = field.abi {
+                if let abi::Abi::Scalar(scalar) = field.abi {
                     if let abi::F64 = scalar.value {
                         if offset.is_aligned(dl.f64_align.abi) {
                             // Insert enough integers to cover [last_offset, offset)
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 6d3c7318091..927bebd8157 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -322,7 +322,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
             Abi::Uninhabited => Err(Heterogeneous),
 
             // The primitive for this algorithm.
-            Abi::Scalar(ref scalar) => {
+            Abi::Scalar(scalar) => {
                 let kind = match scalar.value {
                     abi::Int(..) | abi::Pointer => RegKind::Integer,
                     abi::F32 | abi::F64 => RegKind::Float,
@@ -450,9 +450,9 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
     pub fn new(
         cx: &impl HasDataLayout,
         layout: TyAndLayout<'a, Ty>,
-        scalar_attrs: impl Fn(&TyAndLayout<'a, Ty>, &abi::Scalar, Size) -> ArgAttributes,
+        scalar_attrs: impl Fn(&TyAndLayout<'a, Ty>, abi::Scalar, Size) -> ArgAttributes,
     ) -> Self {
-        let mode = match &layout.abi {
+        let mode = match layout.abi {
             Abi::Uninhabited => PassMode::Ignore,
             Abi::Scalar(scalar) => PassMode::Direct(scalar_attrs(&layout, scalar, Size::ZERO)),
             Abi::ScalarPair(a, b) => PassMode::Pair(
@@ -504,7 +504,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
 
     pub fn extend_integer_width_to(&mut self, bits: u64) {
         // Only integers have signedness
-        if let Abi::Scalar(ref scalar) = self.layout.abi {
+        if let Abi::Scalar(scalar) = self.layout.abi {
             if let abi::Int(i, signed) = scalar.value {
                 if i.size().bits() < bits {
                     if let PassMode::Direct(ref mut attrs) = self.mode {
diff --git a/compiler/rustc_target/src/abi/call/riscv.rs b/compiler/rustc_target/src/abi/call/riscv.rs
index 8c2ef8c7a01..bbefc73a076 100644
--- a/compiler/rustc_target/src/abi/call/riscv.rs
+++ b/compiler/rustc_target/src/abi/call/riscv.rs
@@ -44,7 +44,7 @@ where
     Ty: TyAbiInterface<'a, C> + Copy,
 {
     match arg_layout.abi {
-        Abi::Scalar(ref scalar) => match scalar.value {
+        Abi::Scalar(scalar) => match scalar.value {
             abi::Int(..) | abi::Pointer => {
                 if arg_layout.size.bits() > xlen {
                     return Err(CannotUseFpConv);
@@ -297,7 +297,7 @@ fn classify_arg<'a, Ty, C>(
 }
 
 fn extend_integer_width<'a, Ty>(arg: &mut ArgAbi<'a, Ty>, xlen: u64) {
-    if let Abi::Scalar(ref scalar) = arg.layout.abi {
+    if let Abi::Scalar(scalar) = arg.layout.abi {
         if let abi::Int(i, _) = scalar.value {
             // 32-bit integers are always sign-extended
             if i.size().bits() == 32 && xlen > 32 {
diff --git a/compiler/rustc_target/src/abi/call/s390x.rs b/compiler/rustc_target/src/abi/call/s390x.rs
index 594108925de..38aaee64a4d 100644
--- a/compiler/rustc_target/src/abi/call/s390x.rs
+++ b/compiler/rustc_target/src/abi/call/s390x.rs
@@ -18,7 +18,7 @@ where
     C: HasDataLayout,
 {
     match layout.abi {
-        abi::Abi::Scalar(ref scalar) => scalar.value.is_float(),
+        abi::Abi::Scalar(scalar) => scalar.value.is_float(),
         abi::Abi::Aggregate { .. } => {
             if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
                 is_single_fp_element(cx, layout.field(cx, 0))
diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs
index 3fc197b5d75..28064d85bf1 100644
--- a/compiler/rustc_target/src/abi/call/x86.rs
+++ b/compiler/rustc_target/src/abi/call/x86.rs
@@ -14,7 +14,7 @@ where
     C: HasDataLayout,
 {
     match layout.abi {
-        abi::Abi::Scalar(ref scalar) => scalar.value.is_float(),
+        abi::Abi::Scalar(scalar) => scalar.value.is_float(),
         abi::Abi::Aggregate { .. } => {
             if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
                 is_single_fp_element(cx, layout.field(cx, 0))
diff --git a/compiler/rustc_target/src/abi/call/x86_64.rs b/compiler/rustc_target/src/abi/call/x86_64.rs
index 08f0aaba59a..fae3c3af61b 100644
--- a/compiler/rustc_target/src/abi/call/x86_64.rs
+++ b/compiler/rustc_target/src/abi/call/x86_64.rs
@@ -49,7 +49,7 @@ where
         let mut c = match layout.abi {
             Abi::Uninhabited => return Ok(()),
 
-            Abi::Scalar(ref scalar) => match scalar.value {
+            Abi::Scalar(scalar) => match scalar.value {
                 abi::Int(..) | abi::Pointer => Class::Int,
                 abi::F32 | abi::F64 => Class::Sse,
             },
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index b0ecd117dd2..61607159208 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -7,7 +7,7 @@ use std::convert::{TryFrom, TryInto};
 use std::fmt;
 use std::iter::Step;
 use std::num::NonZeroUsize;
-use std::ops::{Add, AddAssign, Deref, Mul, Range, RangeInclusive, Sub};
+use std::ops::{Add, AddAssign, Deref, Mul, RangeInclusive, Sub};
 use std::str::FromStr;
 
 use rustc_index::vec::{Idx, IndexVec};
@@ -392,6 +392,21 @@ impl Size {
         // Truncate (shift left to drop out leftover values, shift right to fill with zeroes).
         (value << shift) >> shift
     }
+
+    #[inline]
+    pub fn signed_int_min(&self) -> i128 {
+        self.sign_extend(1_u128 << (self.bits() - 1)) as i128
+    }
+
+    #[inline]
+    pub fn signed_int_max(&self) -> i128 {
+        i128::MAX >> (128 - self.bits())
+    }
+
+    #[inline]
+    pub fn unsigned_int_max(&self) -> u128 {
+        u128::MAX >> (128 - self.bits())
+    }
 }
 
 // Panicking addition, subtraction and multiplication for convenience.
@@ -739,9 +754,8 @@ impl Primitive {
 ///
 ///    254 (-2), 255 (-1), 0, 1, 2
 ///
-/// This is intended specifically to mirror LLVM’s `!range` metadata,
-/// semantics.
-#[derive(Clone, PartialEq, Eq, Hash)]
+/// This is intended specifically to mirror LLVM’s `!range` metadata semantics.
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
 #[derive(HashStable_Generic)]
 pub struct WrappingRange {
     pub start: u128,
@@ -759,13 +773,6 @@ impl WrappingRange {
         }
     }
 
-    /// Returns `true` if zero is contained in the range.
-    /// Equal to `range.contains(0)` but should be faster.
-    #[inline(always)]
-    pub fn contains_zero(&self) -> bool {
-        self.start > self.end || self.start == 0
-    }
-
     /// Returns `self` with replaced `start`
     #[inline(always)]
     pub fn with_start(mut self, start: u128) -> Self {
@@ -779,17 +786,29 @@ impl WrappingRange {
         self.end = end;
         self
     }
+
+    /// Returns `true` if `size` completely fills the range.
+    #[inline]
+    pub fn is_full_for(&self, size: Size) -> bool {
+        let max_value = size.unsigned_int_max();
+        debug_assert!(self.start <= max_value && self.end <= max_value);
+        self.start == (self.end.wrapping_add(1) & max_value)
+    }
 }
 
 impl fmt::Debug for WrappingRange {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(fmt, "{}..={}", self.start, self.end)?;
+        if self.start > self.end {
+            write!(fmt, "(..={}) | ({}..)", self.end, self.start)?;
+        } else {
+            write!(fmt, "{}..={}", self.start, self.end)?;
+        }
         Ok(())
     }
 }
 
 /// Information about one scalar component of a Rust type.
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
 #[derive(HashStable_Generic)]
 pub struct Scalar {
     pub value: Primitive,
@@ -803,25 +822,16 @@ pub struct Scalar {
 impl Scalar {
     #[inline]
     pub fn is_bool(&self) -> bool {
-        matches!(self.value, Int(I8, false))
-            && matches!(self.valid_range, WrappingRange { start: 0, end: 1 })
+        matches!(
+            self,
+            Scalar { value: Int(I8, false), valid_range: WrappingRange { start: 0, end: 1 } }
+        )
     }
 
-    /// Returns the valid range as a `x..y` range.
-    ///
-    /// If `x` and `y` are equal, the range is full, not empty.
-    pub fn valid_range_exclusive<C: HasDataLayout>(&self, cx: &C) -> Range<u128> {
-        // For a (max) value of -1, max will be `-1 as usize`, which overflows.
-        // However, that is fine here (it would still represent the full range),
-        // i.e., if the range is everything.
-        let bits = self.value.size(cx).bits();
-        assert!(bits <= 128);
-        let mask = !0u128 >> (128 - bits);
-        let start = self.valid_range.start;
-        let end = self.valid_range.end;
-        assert_eq!(start, start & mask);
-        assert_eq!(end, end & mask);
-        start..(end.wrapping_add(1) & mask)
+    /// Returns `true` if all possible numbers are valid, i.e `valid_range` covers the whole layout
+    #[inline]
+    pub fn is_always_valid<C: HasDataLayout>(&self, cx: &C) -> bool {
+        self.valid_range.is_full_for(self.value.size(cx))
     }
 }
 
@@ -960,7 +970,7 @@ impl AddressSpace {
 
 /// Describes how values of the type are passed by target ABIs,
 /// in terms of categories of C types there are ABI rules for.
-#[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub enum Abi {
     Uninhabited,
     Scalar(Scalar),
@@ -988,8 +998,8 @@ impl Abi {
     /// Returns `true` if this is a single signed integer scalar
     #[inline]
     pub fn is_signed(&self) -> bool {
-        match *self {
-            Abi::Scalar(ref scal) => match scal.value {
+        match self {
+            Abi::Scalar(scal) => match scal.value {
                 Primitive::Int(_, signed) => signed,
                 _ => false,
             },
@@ -1058,7 +1068,7 @@ pub enum TagEncoding {
     },
 }
 
-#[derive(Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
 pub struct Niche {
     pub offset: Size,
     pub scalar: Scalar,
@@ -1071,10 +1081,10 @@ impl Niche {
     }
 
     pub fn available<C: HasDataLayout>(&self, cx: &C) -> u128 {
-        let Scalar { value, valid_range: ref v } = self.scalar;
-        let bits = value.size(cx).bits();
-        assert!(bits <= 128);
-        let max_value = !0u128 >> (128 - bits);
+        let Scalar { value, valid_range: v } = self.scalar;
+        let size = value.size(cx);
+        assert!(size.bits() <= 128);
+        let max_value = size.unsigned_int_max();
 
         // Find out how many values are outside the valid range.
         let niche = v.end.wrapping_add(1)..v.start;
@@ -1084,24 +1094,58 @@ impl Niche {
     pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> {
         assert!(count > 0);
 
-        let Scalar { value, valid_range: v } = self.scalar.clone();
-        let bits = value.size(cx).bits();
-        assert!(bits <= 128);
-        let max_value = !0u128 >> (128 - bits);
+        let Scalar { value, valid_range: v } = self.scalar;
+        let size = value.size(cx);
+        assert!(size.bits() <= 128);
+        let max_value = size.unsigned_int_max();
 
-        if count > max_value {
+        let niche = v.end.wrapping_add(1)..v.start;
+        let available = niche.end.wrapping_sub(niche.start) & max_value;
+        if count > available {
             return None;
         }
 
-        // Compute the range of invalid values being reserved.
-        let start = v.end.wrapping_add(1) & max_value;
-        let end = v.end.wrapping_add(count) & max_value;
-
-        if v.contains(end) {
-            return None;
+        // Extend the range of valid values being reserved by moving either `v.start` or `v.end` bound.
+        // Given an eventual `Option<T>`, we try to maximize the chance for `None` to occupy the niche of zero.
+        // This is accomplished by prefering enums with 2 variants(`count==1`) and always taking the shortest path to niche zero.
+        // Having `None` in niche zero can enable some special optimizations.
+        //
+        // Bound selection criteria:
+        // 1. Select closest to zero given wrapping semantics.
+        // 2. Avoid moving past zero if possible.
+        //
+        // In practice this means that enums with `count > 1` are unlikely to claim niche zero, since they have to fit perfectly.
+        // If niche zero is already reserved, the selection of bounds are of little interest.
+        let move_start = |v: WrappingRange| {
+            let start = v.start.wrapping_sub(1) & max_value;
+            Some((start, Scalar { value, valid_range: v.with_start(start) }))
+        };
+        let move_end = |v: WrappingRange| {
+            let start = v.end.wrapping_add(1) & max_value;
+            let end = v.end.wrapping_add(count) & max_value;
+            Some((start, Scalar { value, valid_range: v.with_end(end) }))
+        };
+        let distance_end_zero = max_value - v.end;
+        if v.start > v.end {
+            // zero is unavailable because wrapping occurs
+            move_end(v)
+        } else if v.start <= distance_end_zero {
+            if count <= v.start {
+                move_start(v)
+            } else {
+                // moved past zero, use other bound
+                move_end(v)
+            }
+        } else {
+            let end = v.end.wrapping_add(count) & max_value;
+            let overshot_zero = (1..=v.end).contains(&end);
+            if overshot_zero {
+                // moved past zero, use other bound
+                move_start(v)
+            } else {
+                move_end(v)
+            }
         }
-
-        Some((start, Scalar { value, valid_range: v.with_end(end) }))
     }
 }
 
@@ -1138,7 +1182,7 @@ pub struct Layout {
 
 impl Layout {
     pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
-        let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar.clone());
+        let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar);
         let size = scalar.value.size(cx);
         let align = scalar.value.align(cx);
         Layout {
@@ -1264,25 +1308,22 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
         Ty: TyAbiInterface<'a, C>,
         C: HasDataLayout,
     {
-        let scalar_allows_raw_init = move |s: &Scalar| -> bool {
+        let scalar_allows_raw_init = move |s: Scalar| -> bool {
             if zero {
                 // The range must contain 0.
-                s.valid_range.contains_zero()
+                s.valid_range.contains(0)
             } else {
-                // The range must include all values. `valid_range_exclusive` handles
-                // the wrap-around using target arithmetic; with wrap-around then the full
-                // range is one where `start == end`.
-                let range = s.valid_range_exclusive(cx);
-                range.start == range.end
+                // The range must include all values.
+                s.is_always_valid(cx)
             }
         };
 
         // Check the ABI.
-        let valid = match &self.abi {
+        let valid = match self.abi {
             Abi::Uninhabited => false, // definitely UB
             Abi::Scalar(s) => scalar_allows_raw_init(s),
             Abi::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2),
-            Abi::Vector { element: s, count } => *count == 0 || scalar_allows_raw_init(s),
+            Abi::Vector { element: s, count } => count == 0 || scalar_allows_raw_init(s),
             Abi::Aggregate { .. } => true, // Fields are checked below.
         };
         if !valid {
diff --git a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
new file mode 100644
index 00000000000..01f5c197d20
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
@@ -0,0 +1,43 @@
+use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
+
+/// A base target for Nintendo 3DS devices using the devkitARM toolchain.
+///
+/// Requires the devkitARM toolchain for 3DS targets on the host system.
+
+pub fn target() -> Target {
+    let mut pre_link_args = LinkArgs::new();
+    pre_link_args.insert(
+        LinkerFlavor::Gcc,
+        vec![
+            "-specs=3dsx.specs".to_string(),
+            "-mtune=mpcore".to_string(),
+            "-mfloat-abi=hard".to_string(),
+            "-mtp=soft".to_string(),
+        ],
+    );
+
+    Target {
+        llvm_target: "armv6k-none-eabihf".to_string(),
+        pointer_width: 32,
+        data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".to_string(),
+        arch: "arm".to_string(),
+
+        options: TargetOptions {
+            os: "horizon".to_string(),
+            env: "newlib".to_string(),
+            vendor: "nintendo".to_string(),
+            abi: "eabihf".to_string(),
+            linker_flavor: LinkerFlavor::Gcc,
+            cpu: "mpcore".to_string(),
+            executables: true,
+            families: vec!["unix".to_string()],
+            linker: Some("arm-none-eabi-gcc".to_string()),
+            relocation_model: RelocModel::Static,
+            features: "+vfp2".to_string(),
+            pre_link_args,
+            exe_suffix: ".elf".to_string(),
+            panic_strategy: PanicStrategy::Abort,
+            ..Default::default()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 273221360b8..920a929544a 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -941,6 +941,8 @@ supported_targets! {
 
     ("bpfeb-unknown-none", bpfeb_unknown_none),
     ("bpfel-unknown-none", bpfel_unknown_none),
+
+    ("armv6k-nintendo-3ds", armv6k_nintendo_3ds),
 }
 
 /// Warnings encountered when parsing the target `json`.
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index c90649353e8..42cbed600d5 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -2,6 +2,7 @@ use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use crate::traits::query::outlives_bounds::InferCtxtExt as _;
 use crate::traits::{self, TraitEngine, TraitEngineExt};
 
+use rustc_data_structures::stable_set::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
@@ -184,7 +185,7 @@ pub trait OutlivesEnvironmentExt<'tcx> {
     fn add_implied_bounds(
         &mut self,
         infcx: &InferCtxt<'a, 'tcx>,
-        fn_sig_tys: &[Ty<'tcx>],
+        fn_sig_tys: FxHashSet<Ty<'tcx>>,
         body_id: hir::HirId,
         span: Span,
     );
@@ -210,13 +211,13 @@ impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> {
     fn add_implied_bounds(
         &mut self,
         infcx: &InferCtxt<'a, 'tcx>,
-        fn_sig_tys: &[Ty<'tcx>],
+        fn_sig_tys: FxHashSet<Ty<'tcx>>,
         body_id: hir::HirId,
         span: Span,
     ) {
         debug!("add_implied_bounds()");
 
-        for &ty in fn_sig_tys {
+        for ty in fn_sig_tys {
             let ty = infcx.resolve_vars_if_possible(ty);
             debug!("add_implied_bounds: ty = {}", ty);
             let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span);
diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
index 7a690af0cc6..9c962d30ce0 100644
--- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
@@ -57,7 +57,6 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
                 .map(|obligation| FulfillmentError {
                     obligation: obligation.clone(),
                     code: FulfillmentErrorCode::CodeAmbiguity,
-                    points_at_arg_span: false,
                     // FIXME - does Chalk have a notation of 'root obligation'?
                     // This is just for diagnostics, so it's okay if this is wrong
                     root_obligation: obligation.clone(),
@@ -112,7 +111,6 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
                                     code: FulfillmentErrorCode::CodeSelectionError(
                                         SelectionError::Unimplemented,
                                     ),
-                                    points_at_arg_span: false,
                                     // FIXME - does Chalk have a notation of 'root obligation'?
                                     // This is just for diagnostics, so it's okay if this is wrong
                                     root_obligation: obligation,
@@ -129,7 +127,6 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> {
                         code: FulfillmentErrorCode::CodeSelectionError(
                             SelectionError::Unimplemented,
                         ),
-                        points_at_arg_span: false,
                         // FIXME - does Chalk have a notation of 'root obligation'?
                         // This is just for diagnostics, so it's okay if this is wrong
                         root_obligation: obligation,
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index ddabe5967d7..24fa5007f1e 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -6,16 +6,16 @@
 //! this is not as easy.
 //!
 //! In this case we try to build an abstract representation of this constant using
-//! `mir_abstract_const` which can then be checked for structural equality with other
+//! `thir_abstract_const` which can then be checked for structural equality with other
 //! generic constants mentioned in the `caller_bounds` of the current environment.
 use rustc_errors::ErrorReported;
 use rustc_hir::def::DefKind;
-use rustc_index::bit_set::BitSet;
 use rustc_index::vec::IndexVec;
 use rustc_infer::infer::InferCtxt;
-use rustc_middle::mir::abstract_const::{Node, NodeId, NotConstEvaluatable};
+use rustc_middle::mir;
 use rustc_middle::mir::interpret::ErrorHandled;
-use rustc_middle::mir::{self, Rvalue, StatementKind, TerminatorKind};
+use rustc_middle::thir;
+use rustc_middle::thir::abstract_const::{self, Node, NodeId, NotConstEvaluatable};
 use rustc_middle::ty::subst::{Subst, SubstsRef};
 use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
 use rustc_session::lint;
@@ -196,7 +196,7 @@ impl<'tcx> AbstractConst<'tcx> {
         tcx: TyCtxt<'tcx>,
         uv: ty::Unevaluated<'tcx, ()>,
     ) -> Result<Option<AbstractConst<'tcx>>, ErrorReported> {
-        let inner = tcx.mir_abstract_const_opt_const_arg(uv.def)?;
+        let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?;
         debug!("AbstractConst::new({:?}) = {:?}", uv, inner);
         Ok(inner.map(|inner| AbstractConst { inner, substs: uv.substs(tcx) }))
     }
@@ -223,35 +223,24 @@ impl<'tcx> AbstractConst<'tcx> {
     }
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-struct WorkNode<'tcx> {
-    node: Node<'tcx>,
-    span: Span,
-    used: bool,
-}
-
 struct AbstractConstBuilder<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    body: &'a mir::Body<'tcx>,
+    body_id: thir::ExprId,
+    body: &'a thir::Thir<'tcx>,
     /// The current WIP node tree.
-    ///
-    /// We require all nodes to be used in the final abstract const,
-    /// so we store this here. Note that we also consider nodes as used
-    /// if they are mentioned in an assert, so some used nodes are never
-    /// actually reachable by walking the [`AbstractConst`].
-    nodes: IndexVec<NodeId, WorkNode<'tcx>>,
-    locals: IndexVec<mir::Local, NodeId>,
-    /// We only allow field accesses if they access
-    /// the result of a checked operation.
-    checked_op_locals: BitSet<mir::Local>,
+    nodes: IndexVec<NodeId, Node<'tcx>>,
 }
 
 impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
+    fn root_span(&self) -> Span {
+        self.body.exprs[self.body_id].span
+    }
+
     fn error(&mut self, span: Option<Span>, msg: &str) -> Result<!, ErrorReported> {
         self.tcx
             .sess
-            .struct_span_err(self.body.span, "overly complex generic constant")
-            .span_label(span.unwrap_or(self.body.span), msg)
+            .struct_span_err(self.root_span(), "overly complex generic constant")
+            .span_label(span.unwrap_or(self.root_span()), msg)
             .help("consider moving this anonymous constant into a `const` function")
             .emit();
 
@@ -260,98 +249,49 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
 
     fn new(
         tcx: TyCtxt<'tcx>,
-        body: &'a mir::Body<'tcx>,
+        (body, body_id): (&'a thir::Thir<'tcx>, thir::ExprId),
     ) -> Result<Option<AbstractConstBuilder<'a, 'tcx>>, ErrorReported> {
-        let mut builder = AbstractConstBuilder {
-            tcx,
-            body,
-            nodes: IndexVec::new(),
-            locals: IndexVec::from_elem(NodeId::MAX, &body.local_decls),
-            checked_op_locals: BitSet::new_empty(body.local_decls.len()),
-        };
-
-        // We don't have to look at concrete constants, as we
-        // can just evaluate them.
-        if !body.is_polymorphic {
-            return Ok(None);
-        }
+        let builder = AbstractConstBuilder { tcx, body_id, body, nodes: IndexVec::new() };
 
-        // We only allow consts without control flow, so
-        // we check for cycles here which simplifies the
-        // rest of this implementation.
-        if body.is_cfg_cyclic() {
-            builder.error(None, "cyclic anonymous constants are forbidden")?;
+        struct IsThirPolymorphic<'a, 'tcx> {
+            is_poly: bool,
+            thir: &'a thir::Thir<'tcx>,
+            tcx: TyCtxt<'tcx>,
         }
 
-        Ok(Some(builder))
-    }
-
-    fn add_node(&mut self, node: Node<'tcx>, span: Span) -> NodeId {
-        // Mark used nodes.
-        match node {
-            Node::Leaf(_) => (),
-            Node::Binop(_, lhs, rhs) => {
-                self.nodes[lhs].used = true;
-                self.nodes[rhs].used = true;
-            }
-            Node::UnaryOp(_, input) => {
-                self.nodes[input].used = true;
-            }
-            Node::FunctionCall(func, nodes) => {
-                self.nodes[func].used = true;
-                nodes.iter().for_each(|&n| self.nodes[n].used = true);
+        use thir::visit;
+        impl<'a, 'tcx: 'a> visit::Visitor<'a, 'tcx> for IsThirPolymorphic<'a, 'tcx> {
+            fn thir(&self) -> &'a thir::Thir<'tcx> {
+                &self.thir
             }
-            Node::Cast(_, operand, _) => {
-                self.nodes[operand].used = true;
+
+            fn visit_expr(&mut self, expr: &thir::Expr<'tcx>) {
+                self.is_poly |= expr.ty.definitely_has_param_types_or_consts(self.tcx);
+                if self.is_poly == false {
+                    visit::walk_expr(self, expr)
+                }
             }
-        }
 
-        // Nodes start as unused.
-        self.nodes.push(WorkNode { node, span, used: false })
-    }
+            fn visit_pat(&mut self, pat: &thir::Pat<'tcx>) {
+                self.is_poly |= pat.ty.definitely_has_param_types_or_consts(self.tcx);
+                if self.is_poly == false {
+                    visit::walk_pat(self, pat);
+                }
+            }
 
-    fn place_to_local(
-        &mut self,
-        span: Span,
-        p: &mir::Place<'tcx>,
-    ) -> Result<mir::Local, ErrorReported> {
-        const ZERO_FIELD: mir::Field = mir::Field::from_usize(0);
-        // Do not allow any projections.
-        //
-        // One exception are field accesses on the result of checked operations,
-        // which are required to support things like `1 + 2`.
-        if let Some(p) = p.as_local() {
-            debug_assert!(!self.checked_op_locals.contains(p));
-            Ok(p)
-        } else if let &[mir::ProjectionElem::Field(ZERO_FIELD, _)] = p.projection.as_ref() {
-            // Only allow field accesses if the given local
-            // contains the result of a checked operation.
-            if self.checked_op_locals.contains(p.local) {
-                Ok(p.local)
-            } else {
-                self.error(Some(span), "unsupported projection")?;
+            fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) {
+                self.is_poly |= ct.definitely_has_param_types_or_consts(self.tcx);
             }
-        } else {
-            self.error(Some(span), "unsupported projection")?;
         }
-    }
 
-    fn operand_to_node(
-        &mut self,
-        span: Span,
-        op: &mir::Operand<'tcx>,
-    ) -> Result<NodeId, ErrorReported> {
-        debug!("operand_to_node: op={:?}", op);
-        match op {
-            mir::Operand::Copy(p) | mir::Operand::Move(p) => {
-                let local = self.place_to_local(span, p)?;
-                Ok(self.locals[local])
-            }
-            mir::Operand::Constant(ct) => match ct.literal {
-                mir::ConstantKind::Ty(ct) => Ok(self.add_node(Node::Leaf(ct), span)),
-                mir::ConstantKind::Val(..) => self.error(Some(span), "unsupported constant")?,
-            },
+        let mut is_poly_vis = IsThirPolymorphic { is_poly: false, thir: body, tcx };
+        visit::walk_expr(&mut is_poly_vis, &body[body_id]);
+        debug!("AbstractConstBuilder: is_poly={}", is_poly_vis.is_poly);
+        if is_poly_vis.is_poly == false {
+            return Ok(None);
         }
+
+        Ok(Some(builder))
     }
 
     /// We do not allow all binary operations in abstract consts, so filter disallowed ones.
@@ -373,170 +313,126 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
         }
     }
 
-    fn build_statement(&mut self, stmt: &mir::Statement<'tcx>) -> Result<(), ErrorReported> {
-        debug!("AbstractConstBuilder: stmt={:?}", stmt);
-        let span = stmt.source_info.span;
-        match stmt.kind {
-            StatementKind::Assign(box (ref place, ref rvalue)) => {
-                let local = self.place_to_local(span, place)?;
-                match *rvalue {
-                    Rvalue::Use(ref operand) => {
-                        self.locals[local] = self.operand_to_node(span, operand)?;
-                        Ok(())
-                    }
-                    Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) if Self::check_binop(op) => {
-                        let lhs = self.operand_to_node(span, lhs)?;
-                        let rhs = self.operand_to_node(span, rhs)?;
-                        self.locals[local] = self.add_node(Node::Binop(op, lhs, rhs), span);
-                        if op.is_checkable() {
-                            bug!("unexpected unchecked checkable binary operation");
-                        } else {
-                            Ok(())
-                        }
-                    }
-                    Rvalue::CheckedBinaryOp(op, box (ref lhs, ref rhs))
-                        if Self::check_binop(op) =>
-                    {
-                        let lhs = self.operand_to_node(span, lhs)?;
-                        let rhs = self.operand_to_node(span, rhs)?;
-                        self.locals[local] = self.add_node(Node::Binop(op, lhs, rhs), span);
-                        self.checked_op_locals.insert(local);
-                        Ok(())
-                    }
-                    Rvalue::UnaryOp(op, ref operand) if Self::check_unop(op) => {
-                        let operand = self.operand_to_node(span, operand)?;
-                        self.locals[local] = self.add_node(Node::UnaryOp(op, operand), span);
-                        Ok(())
-                    }
-                    Rvalue::Cast(cast_kind, ref operand, ty) => {
-                        let operand = self.operand_to_node(span, operand)?;
-                        self.locals[local] =
-                            self.add_node(Node::Cast(cast_kind, operand, ty), span);
-                        Ok(())
-                    }
-                    _ => self.error(Some(span), "unsupported rvalue")?,
-                }
-            }
-            // These are not actually relevant for us here, so we can ignore them.
-            StatementKind::AscribeUserType(..)
-            | StatementKind::StorageLive(_)
-            | StatementKind::StorageDead(_) => Ok(()),
-            _ => self.error(Some(stmt.source_info.span), "unsupported statement")?,
-        }
-    }
-
-    /// Possible return values:
-    ///
-    /// - `None`: unsupported terminator, stop building
-    /// - `Some(None)`: supported terminator, finish building
-    /// - `Some(Some(block))`: support terminator, build `block` next
-    fn build_terminator(
-        &mut self,
-        terminator: &mir::Terminator<'tcx>,
-    ) -> Result<Option<mir::BasicBlock>, ErrorReported> {
-        debug!("AbstractConstBuilder: terminator={:?}", terminator);
-        match terminator.kind {
-            TerminatorKind::Goto { target } => Ok(Some(target)),
-            TerminatorKind::Return => Ok(None),
-            TerminatorKind::Call {
-                ref func,
-                ref args,
-                destination: Some((ref place, target)),
-                // We do not care about `cleanup` here. Any branch which
-                // uses `cleanup` will fail const-eval and they therefore
-                // do not matter when checking for const evaluatability.
-                //
-                // Do note that even if `panic::catch_unwind` is made const,
-                // we still do not have to care about this, as we do not look
-                // into functions.
-                cleanup: _,
-                // Do not allow overloaded operators for now,
-                // we probably do want to allow this in the future.
-                //
-                // This is currently fairly irrelevant as it requires `const Trait`s.
-                from_hir_call: true,
-                fn_span,
-            } => {
-                let local = self.place_to_local(fn_span, place)?;
-                let func = self.operand_to_node(fn_span, func)?;
-                let args = self.tcx.arena.alloc_from_iter(
-                    args.iter()
-                        .map(|arg| self.operand_to_node(terminator.source_info.span, arg))
-                        .collect::<Result<Vec<NodeId>, _>>()?,
-                );
-                self.locals[local] = self.add_node(Node::FunctionCall(func, args), fn_span);
-                Ok(Some(target))
-            }
-            TerminatorKind::Assert { ref cond, expected: false, target, .. } => {
-                let p = match cond {
-                    mir::Operand::Copy(p) | mir::Operand::Move(p) => p,
-                    mir::Operand::Constant(_) => bug!("unexpected assert"),
-                };
-
-                const ONE_FIELD: mir::Field = mir::Field::from_usize(1);
-                debug!("proj: {:?}", p.projection);
-                if let Some(p) = p.as_local() {
-                    debug_assert!(!self.checked_op_locals.contains(p));
-                    // Mark locals directly used in asserts as used.
-                    //
-                    // This is needed because division does not use `CheckedBinop` but instead
-                    // adds an explicit assert for `divisor != 0`.
-                    self.nodes[self.locals[p]].used = true;
-                    return Ok(Some(target));
-                } else if let &[mir::ProjectionElem::Field(ONE_FIELD, _)] = p.projection.as_ref() {
-                    // Only allow asserts checking the result of a checked operation.
-                    if self.checked_op_locals.contains(p.local) {
-                        return Ok(Some(target));
-                    }
-                }
-
-                self.error(Some(terminator.source_info.span), "unsupported assertion")?;
-            }
-            _ => self.error(Some(terminator.source_info.span), "unsupported terminator")?,
-        }
-    }
-
-    /// Builds the abstract const by walking the mir from start to finish
-    /// and bailing out when encountering an unsupported operation.
+    /// Builds the abstract const by walking the thir and bailing out when
+    /// encountering an unspported operation.
     fn build(mut self) -> Result<&'tcx [Node<'tcx>], ErrorReported> {
-        let mut block = &self.body.basic_blocks()[mir::START_BLOCK];
-        // We checked for a cyclic cfg above, so this should terminate.
-        loop {
-            debug!("AbstractConstBuilder: block={:?}", block);
-            for stmt in block.statements.iter() {
-                self.build_statement(stmt)?;
-            }
+        debug!("Abstractconstbuilder::build: body={:?}", &*self.body);
+        self.recurse_build(self.body_id)?;
 
-            if let Some(next) = self.build_terminator(block.terminator())? {
-                block = &self.body.basic_blocks()[next];
-            } else {
-                break;
-            }
-        }
-
-        assert_eq!(self.locals[mir::RETURN_PLACE], self.nodes.last().unwrap());
         for n in self.nodes.iter() {
-            if let Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(ct), ty: _ }) = n.node {
+            if let Node::Leaf(ty::Const { val: ty::ConstKind::Unevaluated(ct), ty: _ }) = n {
                 // `AbstractConst`s should not contain any promoteds as they require references which
                 // are not allowed.
                 assert_eq!(ct.promoted, None);
             }
         }
 
-        self.nodes[self.locals[mir::RETURN_PLACE]].used = true;
-        if let Some(&unused) = self.nodes.iter().find(|n| !n.used) {
-            self.error(Some(unused.span), "dead code")?;
-        }
+        Ok(self.tcx.arena.alloc_from_iter(self.nodes.into_iter()))
+    }
 
-        Ok(self.tcx.arena.alloc_from_iter(self.nodes.into_iter().map(|n| n.node)))
+    fn recurse_build(&mut self, node: thir::ExprId) -> Result<NodeId, ErrorReported> {
+        use thir::ExprKind;
+        let node = &self.body.exprs[node];
+        debug!("recurse_build: node={:?}", node);
+        Ok(match &node.kind {
+            // I dont know if handling of these 3 is correct
+            &ExprKind::Scope { value, .. } => self.recurse_build(value)?,
+            &ExprKind::PlaceTypeAscription { source, .. } |
+            &ExprKind::ValueTypeAscription { source, .. } => self.recurse_build(source)?,
+
+            // subtle: associated consts are literals this arm handles
+            // `<T as Trait>::ASSOC` as well as `12`
+            &ExprKind::Literal { literal, .. } => self.nodes.push(Node::Leaf(literal)),
+
+            ExprKind::Call { fun, args,  .. } => {
+                let fun = self.recurse_build(*fun)?;
+
+                let mut new_args = Vec::<NodeId>::with_capacity(args.len());
+                for &id in args.iter() {
+                    new_args.push(self.recurse_build(id)?);
+                }
+                let new_args = self.tcx.arena.alloc_slice(&new_args);
+                self.nodes.push(Node::FunctionCall(fun, new_args))
+            },
+            &ExprKind::Binary { op, lhs, rhs } if Self::check_binop(op) => {
+                let lhs = self.recurse_build(lhs)?;
+                let rhs = self.recurse_build(rhs)?;
+                self.nodes.push(Node::Binop(op, lhs, rhs))
+            }
+            &ExprKind::Unary { op, arg } if Self::check_unop(op) => {
+                let arg = self.recurse_build(arg)?;
+                self.nodes.push(Node::UnaryOp(op, arg))
+            },
+            // This is necessary so that the following compiles:
+            //
+            // ```
+            // fn foo<const N: usize>(a: [(); N + 1]) {
+            //     bar::<{ N + 1 }>();
+            // }
+            // ```
+            ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. }} => self.recurse_build(*e)?,
+            // `ExprKind::Use` happens when a `hir::ExprKind::Cast` is a
+            // "coercion cast" i.e. using a coercion or is a no-op.
+            // This is important so that `N as usize as usize` doesnt unify with `N as usize`. (untested)
+            &ExprKind::Use { source } => {
+                let arg = self.recurse_build(source)?;
+                self.nodes.push(Node::Cast(abstract_const::CastKind::Use, arg, node.ty))
+            },
+            &ExprKind::Cast { source } => {
+                let arg = self.recurse_build(source)?;
+                self.nodes.push(Node::Cast(abstract_const::CastKind::As, arg, node.ty))
+            },
+
+            // FIXME(generic_const_exprs): We may want to support these.
+            ExprKind::AddressOf { .. }
+            | ExprKind::Borrow { .. }
+            | ExprKind::Deref { .. }
+            | ExprKind::Repeat { .. }
+            | ExprKind::Array { .. }
+            | ExprKind::Block { .. }
+            | ExprKind::NeverToAny { .. }
+            | ExprKind::Tuple { .. }
+            | ExprKind::Index { .. }
+            | ExprKind::Field { .. }
+            | ExprKind::ConstBlock { .. }
+            | ExprKind::Adt(_) => self.error(
+                    Some(node.span),
+                    "unsupported operation in generic constant, this may be supported in the future",
+                )?,
+
+            ExprKind::Match { .. }
+            // we dont permit let stmts so `VarRef` and `UpvarRef` cant happen
+            | ExprKind::VarRef { .. }
+            | ExprKind::UpvarRef { .. }
+            | ExprKind::Closure { .. }
+            | ExprKind::Let { .. } // let expressions imply control flow
+            | ExprKind::Loop { .. }
+            | ExprKind::Assign { .. }
+            | ExprKind::StaticRef { .. }
+            | ExprKind::LogicalOp { .. }
+            // we handle valid unary/binary ops above
+            | ExprKind::Unary { .. }
+            | ExprKind::Binary { .. }
+            | ExprKind::Break { .. }
+            | ExprKind::Continue { .. }
+            | ExprKind::If { .. }
+            | ExprKind::Pointer { .. } // dont know if this is correct
+            | ExprKind::ThreadLocalRef(_)
+            | ExprKind::LlvmInlineAsm { .. }
+            | ExprKind::Return { .. }
+            | ExprKind::Box { .. } // allocations not allowed in constants
+            | ExprKind::AssignOp { .. }
+            | ExprKind::InlineAsm { .. }
+            | ExprKind::Yield { .. } => self.error(Some(node.span), "unsupported operation in generic constant")?,
+        })
     }
 }
 
 /// Builds an abstract const, do not use this directly, but use `AbstractConst::new` instead.
-pub(super) fn mir_abstract_const<'tcx>(
+pub(super) fn thir_abstract_const<'tcx>(
     tcx: TyCtxt<'tcx>,
     def: ty::WithOptConstParam<LocalDefId>,
-) -> Result<Option<&'tcx [mir::abstract_const::Node<'tcx>]>, ErrorReported> {
+) -> Result<Option<&'tcx [thir::abstract_const::Node<'tcx>]>, ErrorReported> {
     if tcx.features().generic_const_exprs {
         match tcx.def_kind(def.did) {
             // FIXME(generic_const_exprs): We currently only do this for anonymous constants,
@@ -547,8 +443,16 @@ pub(super) fn mir_abstract_const<'tcx>(
             DefKind::AnonConst => (),
             _ => return Ok(None),
         }
-        let body = tcx.mir_const(def).borrow();
-        AbstractConstBuilder::new(tcx, &body)?.map(AbstractConstBuilder::build).transpose()
+
+        let body = tcx.thir_body(def);
+        if body.0.borrow().exprs.is_empty() {
+            // type error in constant, there is no thir
+            return Err(ErrorReported);
+        }
+
+        AbstractConstBuilder::new(tcx, (&*body.0.borrow(), body.1))?
+            .map(AbstractConstBuilder::build)
+            .transpose()
     } else {
         Ok(None)
     }
@@ -682,11 +586,16 @@ pub(super) fn try_unify<'tcx>(
                 && iter::zip(a_args, b_args)
                     .all(|(&an, &bn)| try_unify(tcx, a.subtree(an), b.subtree(bn)))
         }
-        (Node::Cast(a_cast_kind, a_operand, a_ty), Node::Cast(b_cast_kind, b_operand, b_ty))
-            if (a_ty == b_ty) && (a_cast_kind == b_cast_kind) =>
+        (Node::Cast(a_kind, a_operand, a_ty), Node::Cast(b_kind, b_operand, b_ty))
+            if (a_ty == b_ty) && (a_kind == b_kind) =>
         {
             try_unify(tcx, a.subtree(a_operand), b.subtree(b_operand))
         }
-        _ => false,
+        // use this over `_ => false` to make adding variants to `Node` less error prone
+        (Node::Cast(..), _)
+        | (Node::FunctionCall(..), _)
+        | (Node::UnaryOp(..), _)
+        | (Node::Binop(..), _)
+        | (Node::Leaf(..), _) => false,
     }
 }
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 9ce6c58a0f1..8c9acd3ba73 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -19,7 +19,7 @@ use rustc_hir::intravisit::Visitor;
 use rustc_hir::GenericParam;
 use rustc_hir::Item;
 use rustc_hir::Node;
-use rustc_middle::mir::abstract_const::NotConstEvaluatable;
+use rustc_middle::thir::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::ExpectedFound;
 use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::{
@@ -66,7 +66,6 @@ pub trait InferCtxtExt<'tcx> {
         root_obligation: &PredicateObligation<'tcx>,
         error: &SelectionError<'tcx>,
         fallback_has_occurred: bool,
-        points_at_arg: bool,
     );
 
     /// Given some node representing a fn-like thing in the HIR map,
@@ -237,7 +236,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         root_obligation: &PredicateObligation<'tcx>,
         error: &SelectionError<'tcx>,
         fallback_has_occurred: bool,
-        points_at_arg: bool,
     ) {
         let tcx = self.tcx;
         let mut span = obligation.cause.span;
@@ -249,10 +247,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 if let ObligationCauseCode::WellFormed(Some(wf_loc)) =
                     root_obligation.cause.code.peel_derives()
                 {
-                    if let Some(cause) = self.tcx.diagnostic_hir_wf_check((
-                        tcx.erase_regions(obligation.predicate),
-                        wf_loc.clone(),
-                    )) {
+                    if let Some(cause) = self
+                        .tcx
+                        .diagnostic_hir_wf_check((tcx.erase_regions(obligation.predicate), *wf_loc))
+                    {
                         obligation.cause = cause;
                         span = obligation.cause.span;
                     }
@@ -387,7 +385,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                             &obligation,
                             &mut err,
                             &trait_ref,
-                            points_at_arg,
                             have_alt_message,
                         ) {
                             self.note_obligation_cause(&mut err, &obligation);
@@ -430,8 +427,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                             err.span_label(enclosing_scope_span, s.as_str());
                         }
 
-                        self.suggest_dereferences(&obligation, &mut err, trait_ref, points_at_arg);
-                        self.suggest_fn_call(&obligation, &mut err, trait_ref, points_at_arg);
+                        self.suggest_dereferences(&obligation, &mut err, trait_ref);
+                        self.suggest_fn_call(&obligation, &mut err, trait_ref);
                         self.suggest_remove_reference(&obligation, &mut err, trait_ref);
                         self.suggest_semicolon_removal(&obligation, &mut err, span, trait_ref);
                         self.note_version_mismatch(&mut err, &trait_ref);
@@ -500,12 +497,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         // Changing mutability doesn't make a difference to whether we have
                         // an `Unsize` impl (Fixes ICE in #71036)
                         if !is_unsize {
-                            self.suggest_change_mut(
-                                &obligation,
-                                &mut err,
-                                trait_ref,
-                                points_at_arg,
-                            );
+                            self.suggest_change_mut(&obligation, &mut err, trait_ref);
                         }
 
                         // If this error is due to `!: Trait` not implemented but `(): Trait` is
@@ -1214,7 +1206,6 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
                     &error.root_obligation,
                     selection_error,
                     fallback_has_occurred,
-                    error.points_at_arg_span,
                 );
             }
             FulfillmentErrorCode::CodeProjectionError(ref e) => {
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 3a32f1cb903..6128c119b6b 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -154,9 +154,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 flags.push((sym::from_method, Some(method.to_string())));
             }
         }
-        if let Some((t, _)) = self.get_parent_trait_ref(&obligation.cause.code) {
-            flags.push((sym::parent_trait, Some(t)));
-        }
 
         if let Some(k) = obligation.cause.span.desugaring_kind() {
             flags.push((sym::from_desugaring, None));
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 0d3fd748645..f006bede409 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -9,6 +9,7 @@ use crate::traits::normalize_projection_type;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::stack::ensure_sufficient_stack;
+use rustc_data_structures::sync::Lrc;
 use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Style};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
@@ -23,7 +24,7 @@ use rustc_middle::ty::{
 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_span::{BytePos, DesugaringKind, ExpnKind, ForLoopLoc, MultiSpan, Span, DUMMY_SP};
 use rustc_target::spec::abi;
 use std::fmt;
 
@@ -54,7 +55,6 @@ pub trait InferCtxtExt<'tcx> {
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'tcx>,
         trait_ref: ty::PolyTraitRef<'tcx>,
-        points_at_arg: bool,
     );
 
     fn get_closure_name(
@@ -69,7 +69,6 @@ pub trait InferCtxtExt<'tcx> {
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'_>,
         trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
     );
 
     fn suggest_add_reference_to_arg(
@@ -77,7 +76,6 @@ pub trait InferCtxtExt<'tcx> {
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'_>,
         trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
         has_custom_message: bool,
     ) -> bool;
 
@@ -93,7 +91,6 @@ pub trait InferCtxtExt<'tcx> {
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'_>,
         trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
     );
 
     fn suggest_semicolon_removal(
@@ -490,16 +487,19 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'tcx>,
         trait_ref: ty::PolyTraitRef<'tcx>,
-        points_at_arg: bool,
     ) {
         // It only make sense when suggesting dereferences for arguments
-        if !points_at_arg {
+        let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } =
+            &obligation.cause.code
+        {
+            parent_code.clone()
+        } else {
             return;
-        }
+        };
         let param_env = obligation.param_env;
         let body_id = obligation.cause.body_id;
         let span = obligation.cause.span;
-        let real_trait_ref = match &obligation.cause.code {
+        let real_trait_ref = match &*code {
             ObligationCauseCode::ImplDerivedObligation(cause)
             | ObligationCauseCode::DerivedObligation(cause)
             | ObligationCauseCode::BuiltinDerivedObligation(cause) => cause.parent_trait_ref,
@@ -584,7 +584,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'_>,
         trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
     ) {
         let self_ty = match trait_ref.self_ty().no_bound_vars() {
             None => return,
@@ -656,11 +655,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             }
             _ => return,
         };
-        if points_at_arg {
+        if matches!(obligation.cause.code, ObligationCauseCode::FunctionArgumentObligation { .. }) {
             // When the obligation error has been ensured to have been caused by
             // an argument, the `obligation.cause.span` points at the expression
-            // of the argument, so we can provide a suggestion. This is signaled
-            // by `points_at_arg`. Otherwise, we give a more general note.
+            // of the argument, so we can provide a suggestion. Otherwise, we give
+            // a more general note.
             err.span_suggestion_verbose(
                 obligation.cause.span.shrink_to_hi(),
                 &msg,
@@ -677,12 +676,21 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'_>,
         trait_ref: &ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
         has_custom_message: bool,
     ) -> bool {
-        if !points_at_arg {
+        let span = obligation.cause.span;
+
+        let code = if let ObligationCauseCode::FunctionArgumentObligation { parent_code, .. } =
+            &obligation.cause.code
+        {
+            parent_code.clone()
+        } else if let ExpnKind::Desugaring(DesugaringKind::ForLoop(ForLoopLoc::IntoIter)) =
+            span.ctxt().outer_expn_data().kind
+        {
+            Lrc::new(obligation.cause.code.clone())
+        } else {
             return false;
-        }
+        };
 
         // List of traits for which it would be nonsensical to suggest borrowing.
         // For instance, immutable references are always Copy, so suggesting to
@@ -695,7 +703,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
 
         never_suggest_borrow.push(self.tcx.get_diagnostic_item(sym::send_trait).unwrap());
 
-        let span = obligation.cause.span;
         let param_env = obligation.param_env;
         let trait_ref = trait_ref.skip_binder();
 
@@ -754,7 +761,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     );
 
                     // This if is to prevent a special edge-case
-                    if !span.from_expansion() {
+                    if matches!(
+                        span.ctxt().outer_expn_data().kind,
+                        ExpnKind::Root
+                            | ExpnKind::Desugaring(DesugaringKind::ForLoop(ForLoopLoc::IntoIter))
+                    ) {
                         // We don't want a borrowing suggestion on the fields in structs,
                         // ```
                         // struct Foo {
@@ -778,7 +789,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             return false;
         };
 
-        if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code {
+        if let ObligationCauseCode::ImplDerivedObligation(obligation) = &*code {
             let expected_trait_ref = obligation.parent_trait_ref.skip_binder();
             let new_imm_trait_ref =
                 ty::TraitRef::new(obligation.parent_trait_ref.def_id(), imm_substs);
@@ -790,7 +801,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 return try_borrowing(new_mut_trait_ref, expected_trait_ref, true, &[]);
             }
         } else if let ObligationCauseCode::BindingObligation(_, _)
-        | ObligationCauseCode::ItemObligation(_) = &obligation.cause.code
+        | ObligationCauseCode::ItemObligation(_) = &*code
         {
             if try_borrowing(
                 ty::TraitRef::new(trait_ref.def_id, imm_substs),
@@ -882,8 +893,12 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         obligation: &PredicateObligation<'tcx>,
         err: &mut DiagnosticBuilder<'_>,
         trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>,
-        points_at_arg: bool,
     ) {
+        let points_at_arg = matches!(
+            obligation.cause.code,
+            ObligationCauseCode::FunctionArgumentObligation { .. },
+        );
+
         let span = obligation.cause.span;
         if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
             let refs_number =
@@ -2280,6 +2295,56 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     )
                 });
             }
+            ObligationCauseCode::FunctionArgumentObligation {
+                arg_hir_id,
+                call_hir_id,
+                ref parent_code,
+            } => {
+                let hir = self.tcx.hir();
+                if let Some(Node::Expr(expr @ hir::Expr { kind: hir::ExprKind::Block(..), .. })) =
+                    hir.find(arg_hir_id)
+                {
+                    let in_progress_typeck_results =
+                        self.in_progress_typeck_results.map(|t| t.borrow());
+                    let parent_id = hir.local_def_id(hir.get_parent_item(arg_hir_id));
+                    let typeck_results: &TypeckResults<'tcx> = match &in_progress_typeck_results {
+                        Some(t) if t.hir_owner == parent_id => t,
+                        _ => self.tcx.typeck(parent_id),
+                    };
+                    let ty = typeck_results.expr_ty_adjusted(expr);
+                    let span = expr.peel_blocks().span;
+                    if Some(span) != err.span.primary_span() {
+                        err.span_label(
+                            span,
+                            &if ty.references_error() {
+                                String::new()
+                            } else {
+                                format!("this tail expression is of type `{:?}`", ty)
+                            },
+                        );
+                    }
+                }
+                if let Some(Node::Expr(hir::Expr {
+                    kind:
+                        hir::ExprKind::Call(hir::Expr { span, .. }, _)
+                        | hir::ExprKind::MethodCall(_, span, ..),
+                    ..
+                })) = hir.find(call_hir_id)
+                {
+                    if Some(*span) != err.span.primary_span() {
+                        err.span_label(*span, "required by a bound introduced by this call");
+                    }
+                }
+                ensure_sufficient_stack(|| {
+                    self.note_obligation_cause_code(
+                        err,
+                        predicate,
+                        &parent_code,
+                        obligated_types,
+                        seen_requirements,
+                    )
+                });
+            }
             ObligationCauseCode::CompareImplMethodObligation {
                 item_name,
                 trait_item_def_id,
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 18abcc72bce..b376f429292 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -5,8 +5,8 @@ use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProce
 use rustc_errors::ErrorReported;
 use rustc_hir as hir;
 use rustc_infer::traits::{SelectionError, TraitEngine, TraitEngineExt as _, TraitObligation};
-use rustc_middle::mir::abstract_const::NotConstEvaluatable;
 use rustc_middle::mir::interpret::ErrorHandled;
+use rustc_middle::thir::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::ToPredicate;
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 44c67524383..ef208c44471 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -827,16 +827,16 @@ pub fn provide(providers: &mut ty::query::Providers) {
         vtable_entries,
         vtable_trait_upcasting_coercion_new_vptr_slot,
         subst_and_check_impossible_predicates,
-        mir_abstract_const: |tcx, def_id| {
+        thir_abstract_const: |tcx, def_id| {
             let def_id = def_id.expect_local();
             if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
-                tcx.mir_abstract_const_of_const_arg(def)
+                tcx.thir_abstract_const_of_const_arg(def)
             } else {
-                const_evaluatable::mir_abstract_const(tcx, ty::WithOptConstParam::unknown(def_id))
+                const_evaluatable::thir_abstract_const(tcx, ty::WithOptConstParam::unknown(def_id))
             }
         },
-        mir_abstract_const_of_const_arg: |tcx, (did, param_did)| {
-            const_evaluatable::mir_abstract_const(
+        thir_abstract_const_of_const_arg: |tcx, (did, param_did)| {
+            const_evaluatable::thir_abstract_const(
                 tcx,
                 ty::WithOptConstParam { did, const_param_did: Some(param_did) },
             )
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 57b8a84300f..4922cf45a4a 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -465,9 +465,9 @@ fn virtual_call_violation_for_method<'tcx>(
 
             let param_env = tcx.param_env(method.def_id);
 
-            let abi_of_ty = |ty: Ty<'tcx>| -> Option<&Abi> {
+            let abi_of_ty = |ty: Ty<'tcx>| -> Option<Abi> {
                 match tcx.layout_of(param_env.and(ty)) {
-                    Ok(layout) => Some(&layout.abi),
+                    Ok(layout) => Some(layout.abi),
                     Err(err) => {
                         // #78372
                         tcx.sess.delay_span_bug(
@@ -836,7 +836,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeFoldable<'tcx>>(
             //
             // This shouldn't really matter though as we can't really use any
             // constants which are not considered const evaluatable.
-            use rustc_middle::mir::abstract_const::Node;
+            use rustc_middle::thir::abstract_const::Node;
             if let Ok(Some(ct)) = AbstractConst::new(self.tcx, uv.shrink()) {
                 const_evaluatable::walk_abstract_const(self.tcx, ct, |node| match node.root() {
                     Node::Leaf(leaf) => {
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 7038f16a2c9..4f22543950c 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -595,7 +595,7 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
             ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => {
                 let universe = self.universe_for(debruijn);
                 let p = ty::PlaceholderRegion { universe, name: br.kind };
-                self.mapped_regions.insert(p.clone(), br);
+                self.mapped_regions.insert(p, br);
                 self.infcx.tcx.mk_region(ty::RePlaceholder(p))
             }
             _ => r,
@@ -613,7 +613,7 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
             ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
                 let universe = self.universe_for(debruijn);
                 let p = ty::PlaceholderType { universe, name: bound_ty.var };
-                self.mapped_types.insert(p.clone(), bound_ty);
+                self.mapped_types.insert(p, bound_ty);
                 self.infcx.tcx.mk_ty(ty::Placeholder(p))
             }
             _ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self),
@@ -637,7 +637,7 @@ impl TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
                     universe,
                     name: ty::BoundConst { var: bound_const, ty },
                 };
-                self.mapped_consts.insert(p.clone(), bound_const);
+                self.mapped_consts.insert(p, bound_const);
                 self.infcx.tcx.mk_const(ty::Const { val: ty::ConstKind::Placeholder(p), ty })
             }
             _ if ct.has_vars_bound_at_or_above(self.current_index) => ct.super_fold_with(self),
@@ -1477,7 +1477,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
             }
             super::ImplSource::AutoImpl(..)
             | super::ImplSource::Builtin(..)
-            | super::ImplSource::TraitUpcasting(_) => {
+            | super::ImplSource::TraitUpcasting(_)
+            | super::ImplSource::ConstDrop(_) => {
                 // These traits have no associated types.
                 selcx.tcx().sess.delay_span_bug(
                     obligation.cause.span,
@@ -1549,7 +1550,8 @@ fn confirm_select_candidate<'cx, 'tcx>(
         | super::ImplSource::Param(..)
         | super::ImplSource::Builtin(..)
         | super::ImplSource::TraitUpcasting(_)
-        | super::ImplSource::TraitAlias(..) => {
+        | super::ImplSource::TraitAlias(..)
+        | super::ImplSource::ConstDrop(_) => {
             // we don't create Select candidates with this kind of resolution
             span_bug!(
                 obligation.cause.span,
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index e18828fec3f..6d64dc8254b 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -8,7 +8,7 @@
 use rustc_hir as hir;
 use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, TypeFoldable};
+use rustc_middle::ty::{self, Ty, TypeFoldable};
 use rustc_target::spec::abi::Abi;
 
 use crate::traits::coherence::Conflict;
@@ -277,6 +277,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates);
         } else if lang_items.unsize_trait() == Some(def_id) {
             self.assemble_candidates_for_unsizing(obligation, &mut candidates);
+        } else if lang_items.drop_trait() == Some(def_id)
+            && obligation.predicate.skip_binder().constness == ty::BoundConstness::ConstIfConst
+        {
+            if self.is_in_const_context {
+                self.assemble_const_drop_candidates(obligation, &mut candidates)?;
+            } else {
+                debug!("passing ~const Drop bound; in non-const context");
+                // `~const Drop` when we are not in a const context has no effect.
+                candidates.vec.push(ConstDropCandidate)
+            }
         } else {
             if lang_items.clone_trait() == Some(def_id) {
                 // Same builtin conditions as `Copy`, i.e., every type which has builtin support
@@ -803,4 +813,118 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
         }
     }
+
+    fn assemble_const_drop_candidates(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) -> Result<(), SelectionError<'tcx>> {
+        let mut stack: Vec<(Ty<'tcx>, usize)> = vec![(obligation.self_ty().skip_binder(), 0)];
+
+        while let Some((ty, depth)) = stack.pop() {
+            let mut noreturn = false;
+
+            self.check_recursion_depth(depth, obligation)?;
+            let mut copy_candidates = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
+            let mut copy_obligation =
+                obligation.with(obligation.predicate.rebind(ty::TraitPredicate {
+                    trait_ref: ty::TraitRef {
+                        def_id: self.tcx().require_lang_item(hir::LangItem::Copy, None),
+                        substs: self.tcx().mk_substs_trait(ty, &[]),
+                    },
+                    constness: ty::BoundConstness::NotConst,
+                }));
+            copy_obligation.recursion_depth = depth + 1;
+            self.assemble_candidates_from_impls(&copy_obligation, &mut copy_candidates);
+            let copy_conditions = self.copy_clone_conditions(&copy_obligation);
+            self.assemble_builtin_bound_candidates(copy_conditions, &mut copy_candidates);
+            if !copy_candidates.vec.is_empty() {
+                noreturn = true;
+            }
+            debug!(?copy_candidates.vec, "assemble_const_drop_candidates - copy");
+
+            match ty.kind() {
+                ty::Int(_)
+                | ty::Uint(_)
+                | ty::Float(_)
+                | ty::Infer(ty::IntVar(_))
+                | ty::Infer(ty::FloatVar(_))
+                | ty::FnPtr(_)
+                | ty::Never
+                | ty::Ref(..)
+                | ty::FnDef(..)
+                | ty::RawPtr(_)
+                | ty::Bool
+                | ty::Char
+                | ty::Str
+                | ty::Foreign(_) => {} // Do nothing. These types satisfy `const Drop`.
+
+                ty::Adt(def, subst) => {
+                    let mut set = SelectionCandidateSet { vec: Vec::new(), ambiguous: false };
+                    self.assemble_candidates_from_impls(
+                        &obligation.with(obligation.predicate.map_bound(|mut pred| {
+                            pred.trait_ref.substs = self.tcx().mk_substs_trait(ty, &[]);
+                            pred
+                        })),
+                        &mut set,
+                    );
+                    stack.extend(def.all_fields().map(|f| (f.ty(self.tcx(), subst), depth + 1)));
+
+                    debug!(?set.vec, "assemble_const_drop_candidates - ty::Adt");
+                    if set.vec.into_iter().any(|candidate| {
+                        if let SelectionCandidate::ImplCandidate(did) = candidate {
+                            matches!(self.tcx().impl_constness(did), hir::Constness::NotConst)
+                        } else {
+                            false
+                        }
+                    }) {
+                        if !noreturn {
+                            // has non-const Drop
+                            return Ok(());
+                        }
+                        debug!("not returning");
+                    }
+                }
+
+                ty::Array(ty, _) => stack.push((ty, depth + 1)),
+
+                ty::Tuple(_) => stack.extend(ty.tuple_fields().map(|t| (t, depth + 1))),
+
+                ty::Closure(_, substs) => {
+                    stack.extend(substs.as_closure().upvar_tys().map(|t| (t, depth + 1)))
+                }
+
+                ty::Generator(_, substs, _) => {
+                    let substs = substs.as_generator();
+                    stack.extend(substs.upvar_tys().map(|t| (t, depth + 1)));
+                    stack.push((substs.witness(), depth + 1));
+                }
+
+                ty::GeneratorWitness(tys) => stack.extend(
+                    self.tcx().erase_late_bound_regions(*tys).iter().map(|t| (t, depth + 1)),
+                ),
+
+                ty::Slice(ty) => stack.push((ty, depth + 1)),
+
+                ty::Opaque(..)
+                | ty::Dynamic(..)
+                | ty::Error(_)
+                | ty::Bound(..)
+                | ty::Infer(_)
+                | ty::Placeholder(_)
+                | ty::Projection(..)
+                | ty::Param(..) => {
+                    if !noreturn {
+                        return Ok(());
+                    }
+                    debug!("not returning");
+                }
+            }
+            debug!(?stack, "assemble_const_drop_candidates - in loop");
+        }
+        // all types have passed.
+        candidates.vec.push(ConstDropCandidate);
+
+        Ok(())
+    }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 6fae8173985..3b6555de912 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -28,7 +28,7 @@ use crate::traits::TraitNotObjectSafe;
 use crate::traits::VtblSegment;
 use crate::traits::{BuiltinDerivedObligation, ImplDerivedObligation};
 use crate::traits::{
-    ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData,
+    ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData, ImplSourceConstDropData,
     ImplSourceDiscriminantKindData, ImplSourceFnPointerData, ImplSourceGeneratorData,
     ImplSourceObjectData, ImplSourcePointeeData, ImplSourceTraitAliasData,
     ImplSourceTraitUpcastingData, ImplSourceUserDefinedData,
@@ -124,6 +124,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 let data = self.confirm_trait_upcasting_unsize_candidate(obligation, idx)?;
                 Ok(ImplSource::TraitUpcasting(data))
             }
+
+            ConstDropCandidate => Ok(ImplSource::ConstDrop(ImplSourceConstDropData)),
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 22013fb79cf..7b948a0939f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -34,8 +34,8 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::LateBoundRegionConversionTime;
 use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
-use rustc_middle::mir::abstract_const::NotConstEvaluatable;
 use rustc_middle::mir::interpret::ErrorHandled;
+use rustc_middle::thir::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::fast_reject;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::relate::TypeRelation;
@@ -1038,19 +1038,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         it.for_each(|o| o.recursion_depth = cmp::max(min_depth, o.recursion_depth) + 1);
     }
 
-    /// Checks that the recursion limit has not been exceeded.
-    ///
-    /// The weird return type of this function allows it to be used with the `try` (`?`)
-    /// operator within certain functions.
-    fn check_recursion_limit<T: Display + TypeFoldable<'tcx>, V: Display + TypeFoldable<'tcx>>(
+    fn check_recursion_depth<T: Display + TypeFoldable<'tcx>>(
         &self,
-        obligation: &Obligation<'tcx, T>,
-        error_obligation: &Obligation<'tcx, V>,
+        depth: usize,
+        error_obligation: &Obligation<'tcx, T>,
     ) -> Result<(), OverflowError> {
-        if !self.infcx.tcx.recursion_limit().value_within_limit(obligation.recursion_depth) {
+        if !self.infcx.tcx.recursion_limit().value_within_limit(depth) {
             match self.query_mode {
                 TraitQueryMode::Standard => {
-                    self.infcx().report_overflow_error(error_obligation, true);
+                    self.infcx.report_overflow_error(error_obligation, true);
                 }
                 TraitQueryMode::Canonical => {
                     return Err(OverflowError);
@@ -1060,6 +1056,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         Ok(())
     }
 
+    /// Checks that the recursion limit has not been exceeded.
+    ///
+    /// The weird return type of this function allows it to be used with the `try` (`?`)
+    /// operator within certain functions.
+    fn check_recursion_limit<T: Display + TypeFoldable<'tcx>, V: Display + TypeFoldable<'tcx>>(
+        &self,
+        obligation: &Obligation<'tcx, T>,
+        error_obligation: &Obligation<'tcx, V>,
+    ) -> Result<(), OverflowError> {
+        self.check_recursion_depth(obligation.recursion_depth, error_obligation)
+    }
+
     fn in_task<OP, R>(&mut self, op: OP) -> (R, DepNodeIndex)
     where
         OP: FnOnce(&mut Self) -> R,
@@ -1079,28 +1087,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let tcx = self.tcx();
         // Respect const trait obligations
         if self.is_trait_predicate_const(obligation.predicate.skip_binder()) {
-            if Some(obligation.predicate.skip_binder().trait_ref.def_id)
-                != tcx.lang_items().sized_trait()
-            // const Sized bounds are skipped
-            {
-                match candidate {
-                    // const impl
-                    ImplCandidate(def_id)
-                        if tcx.impl_constness(def_id) == hir::Constness::Const => {}
-                    // const param
-                    ParamCandidate(ty::ConstnessAnd {
-                        constness: ty::BoundConstness::ConstIfConst,
-                        ..
-                    }) => {}
-                    // auto trait impl
-                    AutoImplCandidate(..) => {}
-                    // generator, this will raise error in other places
-                    // or ignore error with const_async_blocks feature
-                    GeneratorCandidate => {}
-                    _ => {
-                        // reject all other types of candidates
-                        return Err(Unimplemented);
-                    }
+            match candidate {
+                // const impl
+                ImplCandidate(def_id) if tcx.impl_constness(def_id) == hir::Constness::Const => {}
+                // const param
+                ParamCandidate(ty::ConstnessAnd {
+                    constness: ty::BoundConstness::ConstIfConst,
+                    ..
+                }) => {}
+                // auto trait impl
+                AutoImplCandidate(..) => {}
+                // generator, this will raise error in other places
+                // or ignore error with const_async_blocks feature
+                GeneratorCandidate => {}
+                ConstDropCandidate => {}
+                _ => {
+                    // reject all other types of candidates
+                    return Err(Unimplemented);
                 }
             }
         }
@@ -1476,21 +1479,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             (
                 BuiltinCandidate { has_nested: false }
                 | DiscriminantKindCandidate
-                | PointeeCandidate,
+                | PointeeCandidate
+                | ConstDropCandidate,
                 _,
             ) => true,
             (
                 _,
                 BuiltinCandidate { has_nested: false }
                 | DiscriminantKindCandidate
-                | PointeeCandidate,
+                | PointeeCandidate
+                | ConstDropCandidate,
             ) => false,
 
             (ParamCandidate(other), ParamCandidate(victim)) => {
-                let value_same_except_bound_vars = other.value.skip_binder()
+                let same_except_bound_vars = other.value.skip_binder()
                     == victim.value.skip_binder()
+                    && other.constness == victim.constness
                     && !other.value.skip_binder().has_escaping_bound_vars();
-                if value_same_except_bound_vars {
+                if same_except_bound_vars {
                     // See issue #84398. In short, we can generate multiple ParamCandidates which are
                     // the same except for unused bound vars. Just pick the one with the fewest bound vars
                     // or the current one if tied (they should both evaluate to the same answer). This is
@@ -2445,7 +2451,7 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> {
             "get_provisional = {:#?}",
             self.map.borrow().get(&fresh_trait_ref),
         );
-        Some(self.map.borrow().get(&fresh_trait_ref)?.clone())
+        Some(*self.map.borrow().get(&fresh_trait_ref)?)
     }
 
     /// Insert a provisional result into the cache. The result came
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index b00d2ab3561..87b729faa54 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -386,7 +386,8 @@ fn resolve_associated_item<'tcx>(
         | traits::ImplSource::TraitAlias(..)
         | traits::ImplSource::DiscriminantKind(..)
         | traits::ImplSource::Pointee(..)
-        | traits::ImplSource::TraitUpcasting(_) => None,
+        | traits::ImplSource::TraitUpcasting(_)
+        | traits::ImplSource::ConstDrop(_) => None,
     })
 }
 
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index d837af85d58..32d271d94c8 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -11,12 +11,15 @@ use rustc_span::{sym, DUMMY_SP};
 type NeedsDropResult<T> = Result<T, AlwaysRequiresDrop>;
 
 fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
-    let adt_fields =
+    let adt_components =
         move |adt_def: &ty::AdtDef| tcx.adt_drop_tys(adt_def.did).map(|tys| tys.iter());
+
     // If we don't know a type doesn't need drop, for example if it's a type
     // parameter without a `Copy` bound, then we conservatively return that it
     // needs drop.
-    let res = NeedsDropTypes::new(tcx, query.param_env, query.value, adt_fields).next().is_some();
+    let res =
+        NeedsDropTypes::new(tcx, query.param_env, query.value, adt_components).next().is_some();
+
     debug!("needs_drop_raw({:?}) = {:?}", query, res);
     res
 }
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 51bb09e4c54..2f2223ee822 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -1687,14 +1687,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             constraint=constraint,
                         ));
                     } else {
-                        err.span_suggestion(
-                            span,
+                        err.span_suggestion_verbose(
+                            span.with_hi(assoc_name.span.lo()),
                             "use fully qualified syntax to disambiguate",
                             format!(
-                                "<{} as {}>::{}",
+                                "<{} as {}>::",
                                 ty_param_name(),
                                 bound.print_only_trait_path(),
-                                assoc_name,
                             ),
                             Applicability::MaybeIncorrect,
                         );
diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_typeck/src/check/callee.rs
index d1015510859..1cc06b8c2e5 100644
--- a/compiler/rustc_typeck/src/check/callee.rs
+++ b/compiler/rustc_typeck/src/check/callee.rs
@@ -72,7 +72,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         arg_exprs: &'tcx [hir::Expr<'tcx>],
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
-        let original_callee_ty = self.check_expr(callee_expr);
+        let original_callee_ty = match &callee_expr.kind {
+            hir::ExprKind::Path(hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)) => self
+                .check_expr_with_expectation_and_args(
+                    callee_expr,
+                    Expectation::NoExpectation,
+                    arg_exprs,
+                ),
+            _ => self.check_expr(callee_expr),
+        };
+
         let expr_ty = self.structurally_resolved_type(call_expr.span, original_callee_ty);
 
         let mut autoderef = self.autoderef(callee_expr.span, expr_ty);
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 3c9d5b4def4..1fd1253e527 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -688,7 +688,7 @@ fn check_opaque_meets_bounds<'tcx>(
         // Finally, resolve all regions. This catches wily misuses of
         // lifetime parameters.
         let fcx = FnCtxt::new(&inh, param_env, hir_id);
-        fcx.regionck_item(hir_id, span, &[]);
+        fcx.regionck_item(hir_id, span, FxHashSet::default());
     });
 }
 
diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_typeck/src/check/coercion.rs
index 3bfab9d513f..013aecae586 100644
--- a/compiler/rustc_typeck/src/check/coercion.rs
+++ b/compiler/rustc_typeck/src/check/coercion.rs
@@ -707,13 +707,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
 
                 // Object safety violations or miscellaneous.
                 Err(err) => {
-                    self.report_selection_error(
-                        obligation.clone(),
-                        &obligation,
-                        &err,
-                        false,
-                        false,
-                    );
+                    self.report_selection_error(obligation.clone(), &obligation, &err, false);
                     // Treat this like an obligation and follow through
                     // with the unsizing - the lack of a coercion should
                     // be silent, as it causes a type mismatch later.
@@ -1003,6 +997,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             exprs.len()
         );
 
+        // The following check fixes #88097, where the compiler erroneously
+        // attempted to coerce a closure type to itself via a function pointer.
+        if prev_ty == new_ty {
+            return Ok(prev_ty);
+        }
+
         // Special-case that coercion alone cannot handle:
         // Function items or non-capturing closures of differing IDs or InternalSubsts.
         let (a_sig, b_sig) = {
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index d59291b8fd4..d5b631df058 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -1,4 +1,5 @@
 use crate::errors::LifetimesOrBoundsMismatchOnTrait;
+use rustc_data_structures::stable_set::FxHashSet;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorReported};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
@@ -250,7 +251,7 @@ fn compare_predicate_entailment<'tcx>(
         // Compute placeholder form of impl and trait method tys.
         let tcx = infcx.tcx;
 
-        let mut wf_tys = vec![];
+        let mut wf_tys = FxHashSet::default();
 
         let (impl_sig, _) = infcx.replace_bound_vars_with_fresh_vars(
             impl_m_span,
@@ -398,7 +399,7 @@ fn compare_predicate_entailment<'tcx>(
         // Finally, resolve all regions. This catches wily misuses of
         // lifetime parameters.
         let fcx = FnCtxt::new(&inh, param_env, impl_m_hir_id);
-        fcx.regionck_item(impl_m_hir_id, impl_m_span, &wf_tys);
+        fcx.regionck_item(impl_m_hir_id, impl_m_span, wf_tys);
 
         Ok(())
     })
@@ -1098,7 +1099,7 @@ crate fn compare_const_impl<'tcx>(
         }
 
         let fcx = FnCtxt::new(&inh, param_env, impl_c_hir_id);
-        fcx.regionck_item(impl_c_hir_id, impl_c_span, &[]);
+        fcx.regionck_item(impl_c_hir_id, impl_c_span, FxHashSet::default());
     });
 }
 
@@ -1216,7 +1217,7 @@ fn compare_type_predicate_entailment<'tcx>(
         // Finally, resolve all regions. This catches wily misuses of
         // lifetime parameters.
         let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id);
-        fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &[]);
+        fcx.regionck_item(impl_ty_hir_id, impl_ty_span, FxHashSet::default());
 
         Ok(())
     })
@@ -1436,10 +1437,10 @@ pub fn check_type_bounds<'tcx>(
         // lifetime parameters.
         let fcx = FnCtxt::new(&inh, param_env, impl_ty_hir_id);
         let implied_bounds = match impl_ty.container {
-            ty::TraitContainer(_) => vec![],
+            ty::TraitContainer(_) => FxHashSet::default(),
             ty::ImplContainer(def_id) => fcx.impl_implied_bounds(def_id, impl_ty_span),
         };
-        fcx.regionck_item(impl_ty_hir_id, impl_ty_span, &implied_bounds);
+        fcx.regionck_item(impl_ty_hir_id, impl_ty_span, implied_bounds);
 
         Ok(())
     })
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_typeck/src/check/demand.rs
index 808685d7fa9..a86db2d31b3 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_typeck/src/check/demand.rs
@@ -17,7 +17,6 @@ use rustc_span::{BytePos, Span};
 
 use super::method::probe;
 
-use std::fmt;
 use std::iter;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -589,7 +588,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // 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))
+                        iter::successors(Some(expr.span), |s| s.parent_callsite())
+                            .find(|&s| sp.contains(s))
                     {
                         if sm.span_to_snippet(call_span).is_ok() {
                             return Some((
@@ -771,9 +771,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // For now, don't suggest casting with `as`.
         let can_cast = false;
 
-        let prefix = if let Some(hir::Node::Expr(hir::Expr {
-            kind: hir::ExprKind::Struct(_, fields, _),
-            ..
+        let mut sugg = vec![];
+
+        if let Some(hir::Node::Expr(hir::Expr {
+            kind: hir::ExprKind::Struct(_, fields, _), ..
         })) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id))
         {
             // `expr` is a literal field for a struct, only suggest if appropriate
@@ -782,12 +783,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .find(|field| field.expr.hir_id == expr.hir_id && field.is_shorthand)
             {
                 // This is a field literal
-                Some(field) => format!("{}: ", field.ident),
+                Some(field) => {
+                    sugg.push((field.ident.span.shrink_to_lo(), format!("{}: ", field.ident)));
+                }
                 // Likely a field was meant, but this field wasn't found. Do not suggest anything.
                 None => return false,
             }
-        } else {
-            String::new()
         };
 
         if let hir::ExprKind::Call(path, args) = &expr.kind {
@@ -842,28 +843,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             checked_ty, expected_ty,
         );
 
-        let with_opt_paren: fn(&dyn fmt::Display) -> String =
-            if expr.precedence().order() < PREC_POSTFIX {
-                |s| format!("({})", s)
-            } else {
-                |s| s.to_string()
-            };
+        let close_paren = if expr.precedence().order() < PREC_POSTFIX {
+            sugg.push((expr.span.shrink_to_lo(), "(".to_string()));
+            ")"
+        } else {
+            ""
+        };
 
-        let cast_suggestion = format!("{}{} as {}", prefix, with_opt_paren(&src), expected_ty);
-        let into_suggestion = format!("{}{}.into()", prefix, with_opt_paren(&src));
-        let suffix_suggestion = with_opt_paren(&format_args!(
-            "{}{}",
+        let mut cast_suggestion = sugg.clone();
+        cast_suggestion
+            .push((expr.span.shrink_to_hi(), format!("{} as {}", close_paren, expected_ty)));
+        let mut into_suggestion = sugg.clone();
+        into_suggestion.push((expr.span.shrink_to_hi(), format!("{}.into()", close_paren)));
+        let mut suffix_suggestion = sugg.clone();
+        suffix_suggestion.push((
             if matches!(
                 (&expected_ty.kind(), &checked_ty.kind()),
                 (ty::Int(_) | ty::Uint(_), ty::Float(_))
             ) {
                 // Remove fractional part from literal, for example `42.0f32` into `42`
                 let src = src.trim_end_matches(&checked_ty.to_string());
-                src.split('.').next().unwrap()
+                let len = src.split('.').next().unwrap().len();
+                expr.span.with_lo(expr.span.lo() + BytePos(len as u32))
             } else {
-                src.trim_end_matches(&checked_ty.to_string())
+                let len = src.trim_end_matches(&checked_ty.to_string()).len();
+                expr.span.with_lo(expr.span.lo() + BytePos(len as u32))
+            },
+            if expr.precedence().order() < PREC_POSTFIX {
+                // Readd `)`
+                format!("{})", expected_ty)
+            } else {
+                expected_ty.to_string()
             },
-            expected_ty,
         ));
         let literal_is_ty_suffixed = |expr: &hir::Expr<'_>| {
             if let hir::ExprKind::Lit(lit) = &expr.kind { lit.node.is_suffixed() } else { false }
@@ -890,22 +901,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         .ok()
                         .map(|src| (expr, src))
                 });
-                let (span, msg, suggestion) = if let (Some((lhs_expr, lhs_src)), false) =
+                let (msg, suggestion) = if let (Some((lhs_expr, lhs_src)), false) =
                     (lhs_expr_and_src, exp_to_found_is_fallible)
                 {
                     let msg = format!(
                         "you can convert `{}` from `{}` to `{}`, matching the type of `{}`",
                         lhs_src, expected_ty, checked_ty, src
                     );
-                    let suggestion = format!("{}::from({})", checked_ty, lhs_src);
-                    (lhs_expr.span, msg, suggestion)
+                    let suggestion = vec![
+                        (lhs_expr.span.shrink_to_lo(), format!("{}::from(", checked_ty)),
+                        (lhs_expr.span.shrink_to_hi(), ")".to_string()),
+                    ];
+                    (msg, suggestion)
                 } else {
                     let msg = format!("{} and panic if the converted value doesn't fit", msg);
-                    let suggestion =
-                        format!("{}{}.try_into().unwrap()", prefix, with_opt_paren(&src));
-                    (expr.span, msg, suggestion)
+                    let mut suggestion = sugg.clone();
+                    suggestion.push((
+                        expr.span.shrink_to_hi(),
+                        format!("{}.try_into().unwrap()", close_paren),
+                    ));
+                    (msg, suggestion)
                 };
-                err.span_suggestion(span, &msg, suggestion, Applicability::MachineApplicable);
+                err.multipart_suggestion_verbose(
+                    &msg,
+                    suggestion,
+                    Applicability::MachineApplicable,
+                );
             };
 
         let suggest_to_change_suffix_or_into =
@@ -943,7 +964,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 } else {
                     into_suggestion.clone()
                 };
-                err.span_suggestion(expr.span, msg, suggestion, Applicability::MachineApplicable);
+                err.multipart_suggestion_verbose(msg, suggestion, Applicability::MachineApplicable);
             };
 
         match (&expected_ty.kind(), &checked_ty.kind()) {
@@ -997,16 +1018,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 if found.bit_width() < exp.bit_width() {
                     suggest_to_change_suffix_or_into(err, false, true);
                 } else if literal_is_ty_suffixed(expr) {
-                    err.span_suggestion(
-                        expr.span,
+                    err.multipart_suggestion_verbose(
                         &lit_msg,
                         suffix_suggestion,
                         Applicability::MachineApplicable,
                     );
                 } else if can_cast {
                     // Missing try_into implementation for `f64` to `f32`
-                    err.span_suggestion(
-                        expr.span,
+                    err.multipart_suggestion_verbose(
                         &format!("{}, producing the closest possible value", cast_msg),
                         cast_suggestion,
                         Applicability::MaybeIncorrect, // lossy conversion
@@ -1016,16 +1035,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             (&ty::Uint(_) | &ty::Int(_), &ty::Float(_)) => {
                 if literal_is_ty_suffixed(expr) {
-                    err.span_suggestion(
-                        expr.span,
+                    err.multipart_suggestion_verbose(
                         &lit_msg,
                         suffix_suggestion,
                         Applicability::MachineApplicable,
                     );
                 } else if can_cast {
                     // Missing try_into implementation for `{float}` to `{integer}`
-                    err.span_suggestion(
-                        expr.span,
+                    err.multipart_suggestion_verbose(
                         &format!("{}, rounding the float towards zero", msg),
                         cast_suggestion,
                         Applicability::MaybeIncorrect, // lossy conversion
@@ -1036,8 +1053,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             (&ty::Float(ref exp), &ty::Uint(ref found)) => {
                 // if `found` is `None` (meaning found is `usize`), don't suggest `.into()`
                 if exp.bit_width() > found.bit_width().unwrap_or(256) {
-                    err.span_suggestion(
-                        expr.span,
+                    err.multipart_suggestion_verbose(
                         &format!(
                             "{}, producing the floating point representation of the integer",
                             msg,
@@ -1046,16 +1062,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         Applicability::MachineApplicable,
                     );
                 } else if literal_is_ty_suffixed(expr) {
-                    err.span_suggestion(
-                        expr.span,
+                    err.multipart_suggestion_verbose(
                         &lit_msg,
                         suffix_suggestion,
                         Applicability::MachineApplicable,
                     );
                 } else {
                     // Missing try_into implementation for `{integer}` to `{float}`
-                    err.span_suggestion(
-                        expr.span,
+                    err.multipart_suggestion_verbose(
                         &format!(
                             "{}, producing the floating point representation of the integer,
                                  rounded if necessary",
@@ -1070,8 +1084,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             (&ty::Float(ref exp), &ty::Int(ref found)) => {
                 // if `found` is `None` (meaning found is `isize`), don't suggest `.into()`
                 if exp.bit_width() > found.bit_width().unwrap_or(256) {
-                    err.span_suggestion(
-                        expr.span,
+                    err.multipart_suggestion_verbose(
                         &format!(
                             "{}, producing the floating point representation of the integer",
                             &msg,
@@ -1080,16 +1093,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         Applicability::MachineApplicable,
                     );
                 } else if literal_is_ty_suffixed(expr) {
-                    err.span_suggestion(
-                        expr.span,
+                    err.multipart_suggestion_verbose(
                         &lit_msg,
                         suffix_suggestion,
                         Applicability::MachineApplicable,
                     );
                 } else {
                     // Missing try_into implementation for `{integer}` to `{float}`
-                    err.span_suggestion(
-                        expr.span,
+                    err.multipart_suggestion_verbose(
                         &format!(
                             "{}, producing the floating point representation of the integer, \
                                 rounded if necessary",
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index d578fac4cdb..917adf0e2b9 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -162,6 +162,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &'tcx hir::Expr<'tcx>,
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
+        self.check_expr_with_expectation_and_args(expr, expected, &[])
+    }
+
+    /// Same as `check_expr_with_expectation`, but allows us to pass in the arguments of a
+    /// `ExprKind::Call` when evaluating its callee when it is an `ExprKind::Path`.
+    pub(super) fn check_expr_with_expectation_and_args(
+        &self,
+        expr: &'tcx hir::Expr<'tcx>,
+        expected: Expectation<'tcx>,
+        args: &'tcx [hir::Expr<'tcx>],
+    ) -> Ty<'tcx> {
         if self.tcx().sess.verbose() {
             // make this code only run with -Zverbose because it is probably slow
             if let Ok(lint_str) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
@@ -198,7 +209,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let old_diverges = self.diverges.replace(Diverges::Maybe);
         let old_has_errors = self.has_errors.replace(false);
 
-        let ty = ensure_sufficient_stack(|| self.check_expr_kind(expr, expected));
+        let ty = ensure_sufficient_stack(|| match &expr.kind {
+            hir::ExprKind::Path(
+                qpath @ hir::QPath::Resolved(..) | qpath @ hir::QPath::TypeRelative(..),
+            ) => self.check_expr_path(qpath, expr, args),
+            _ => self.check_expr_kind(expr, expected),
+        });
 
         // Warn for non-block expressions with diverging children.
         match expr.kind {
@@ -261,7 +277,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ExprKind::Path(QPath::LangItem(lang_item, _)) => {
                 self.check_lang_item_path(lang_item, expr)
             }
-            ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr),
+            ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[]),
             ExprKind::InlineAsm(asm) => self.check_expr_asm(asm),
             ExprKind::LlvmInlineAsm(asm) => {
                 for expr in asm.outputs_exprs.iter().chain(asm.inputs_exprs.iter()) {
@@ -481,10 +497,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.resolve_lang_item_path(lang_item, expr.span, expr.hir_id).1
     }
 
-    fn check_expr_path(
+    pub(crate) fn check_expr_path(
         &self,
         qpath: &'tcx hir::QPath<'tcx>,
         expr: &'tcx hir::Expr<'tcx>,
+        args: &'tcx [hir::Expr<'tcx>],
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
         let (res, opt_ty, segs) =
@@ -517,16 +534,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // We just want to check sizedness, so instead of introducing
                     // placeholder lifetimes with probing, we just replace higher lifetimes
                     // with fresh vars.
+                    let span = args.get(i).map(|a| a.span).unwrap_or(expr.span);
                     let input = self
                         .replace_bound_vars_with_fresh_vars(
-                            expr.span,
+                            span,
                             infer::LateBoundRegionConversionTime::FnCall,
                             fn_sig.input(i),
                         )
                         .0;
                     self.require_type_is_sized_deferred(
                         input,
-                        expr.span,
+                        span,
                         traits::SizedArgumentType(None),
                     );
                 }
@@ -1842,7 +1860,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             expr_t
         );
         err.span_label(field.span, "method, not a field");
-        if !self.expr_in_place(expr.hir_id) {
+        let expr_is_call =
+            if let hir::Node::Expr(hir::Expr { kind: ExprKind::Call(callee, _args), .. }) =
+                self.tcx.hir().get(self.tcx.hir().get_parent_node(expr.hir_id))
+            {
+                expr.hir_id == callee.hir_id
+            } else {
+                false
+            };
+        let expr_snippet =
+            self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap_or(String::new());
+        if expr_is_call && expr_snippet.starts_with("(") && expr_snippet.ends_with(")") {
+            let after_open = expr.span.lo() + rustc_span::BytePos(1);
+            let before_close = expr.span.hi() - rustc_span::BytePos(1);
+            err.multipart_suggestion(
+                "remove wrapping parentheses to call the method",
+                vec![
+                    (expr.span.with_hi(after_open), String::new()),
+                    (expr.span.with_lo(before_close), String::new()),
+                ],
+                Applicability::MachineApplicable,
+            );
+        } else if !self.expr_in_place(expr.hir_id) {
             self.suggest_method_call(
                 &mut err,
                 "use parentheses to call the method",
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index 9748c0835bf..ed01dae59f6 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -83,7 +83,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// version (resolve_vars_if_possible), this version will
     /// also select obligations if it seems useful, in an effort
     /// to get more type information.
-    pub(in super::super) fn resolve_vars_with_obligations(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
+    pub(in super::super) fn resolve_vars_with_obligations(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        self.resolve_vars_with_obligations_and_mutate_fulfillment(ty, |_| {})
+    }
+
+    pub(in super::super) fn resolve_vars_with_obligations_and_mutate_fulfillment(
+        &self,
+        mut ty: Ty<'tcx>,
+        mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
+    ) -> Ty<'tcx> {
         debug!("resolve_vars_with_obligations(ty={:?})", ty);
 
         // No Infer()? Nothing needs doing.
@@ -103,7 +111,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // possible. This can help substantially when there are
         // indirect dependencies that don't seem worth tracking
         // precisely.
-        self.select_obligations_where_possible(false, |_| {});
+        self.select_obligations_where_possible(false, mutate_fulfillment_errors);
         ty = self.resolve_vars_if_possible(ty);
 
         debug!("resolve_vars_with_obligations: ty={:?}", ty);
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index 9efb52a08b7..9cf00bad10b 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -9,6 +9,7 @@ use crate::check::{
 };
 
 use rustc_ast as ast;
+use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
@@ -324,6 +325,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     self.point_at_arg_instead_of_call_if_possible(
                         errors,
                         &final_arg_types[..],
+                        expr,
                         sp,
                         &args,
                     );
@@ -354,8 +356,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     continue;
                 }
 
-                debug!("checking the argument");
                 let formal_ty = formal_tys[i];
+                debug!("checking argument {}: {:?} = {:?}", i, arg, formal_ty);
 
                 // The special-cased logic below has three functions:
                 // 1. Provide as good of an expected type as possible.
@@ -367,6 +369,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 //    to, which is `expected_ty` if `rvalue_hint` returns an
                 //    `ExpectHasType(expected_ty)`, or the `formal_ty` otherwise.
                 let coerce_ty = expected.only_has_type(self).unwrap_or(formal_ty);
+
+                // Cause selection errors caused by resolving a single argument to point at the
+                // argument and not the call. This is otherwise redundant with the `demand_coerce`
+                // call immediately after, but it lets us customize the span pointed to in the
+                // fulfillment error to be more accurate.
+                let _ = self.resolve_vars_with_obligations_and_mutate_fulfillment(
+                    coerce_ty,
+                    |errors| {
+                        // This is not coming from a macro or a `derive`.
+                        if sp.desugaring_kind().is_none()
+                        && !arg.span.from_expansion()
+                        // Do not change the spans of `async fn`s.
+                        && !matches!(
+                            expr.kind,
+                            hir::ExprKind::Call(
+                                hir::Expr {
+                                    kind: hir::ExprKind::Path(hir::QPath::LangItem(_, _)),
+                                    ..
+                                },
+                                _
+                            )
+                        ) {
+                            for error in errors {
+                                error.obligation.cause.make_mut().span = arg.span;
+                                let code = error.obligation.cause.code.clone();
+                                error.obligation.cause.make_mut().code =
+                                    ObligationCauseCode::FunctionArgumentObligation {
+                                        arg_hir_id: arg.hir_id,
+                                        call_hir_id: expr.hir_id,
+                                        parent_code: Lrc::new(code),
+                                    };
+                            }
+                        }
+                    },
+                );
+
                 // We're processing function arguments so we definitely want to use
                 // two-phase borrows.
                 self.demand_coerce(&arg, checked_ty, coerce_ty, None, AllowTwoPhase::Yes);
@@ -907,6 +945,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         errors: &mut Vec<traits::FulfillmentError<'tcx>>,
         final_arg_types: &[(usize, Ty<'tcx>, Ty<'tcx>)],
+        expr: &'tcx hir::Expr<'tcx>,
         call_sp: Span,
         args: &'tcx [hir::Expr<'tcx>],
     ) {
@@ -956,7 +995,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // We make sure that only *one* argument matches the obligation failure
                     // and we assign the obligation's span to its expression's.
                     error.obligation.cause.make_mut().span = args[ref_in].span;
-                    error.points_at_arg_span = true;
+                    let code = error.obligation.cause.code.clone();
+                    error.obligation.cause.make_mut().code =
+                        ObligationCauseCode::FunctionArgumentObligation {
+                            arg_hir_id: args[ref_in].hir_id,
+                            call_hir_id: expr.hir_id,
+                            parent_code: Lrc::new(code),
+                        };
                 }
             }
         }
diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs
index 5f26e701c0a..3da9fd159a7 100644
--- a/compiler/rustc_typeck/src/check/generator_interior.rs
+++ b/compiler/rustc_typeck/src/check/generator_interior.rs
@@ -1,6 +1,6 @@
 //! This calculates the types which has storage which lives across a suspension point in a
 //! generator from the perspective of typeck. The actual types used at runtime
-//! is calculated in `rustc_mir::transform::generator` and may be a subset of the
+//! is calculated in `rustc_const_eval::transform::generator` and may be a subset of the
 //! types computed here.
 
 use super::FnCtxt;
diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs
index 1c7d68a3d57..cbfdce96bc5 100644
--- a/compiler/rustc_typeck/src/check/method/probe.rs
+++ b/compiler/rustc_typeck/src/check/method/probe.rs
@@ -186,7 +186,7 @@ pub enum AutorefOrPtrAdjustment<'tcx> {
 impl<'tcx> AutorefOrPtrAdjustment<'tcx> {
     fn get_unsize(&self) -> Option<Ty<'tcx>> {
         match self {
-            AutorefOrPtrAdjustment::Autoref { mutbl: _, unsize } => unsize.clone(),
+            AutorefOrPtrAdjustment::Autoref { mutbl: _, unsize } => *unsize,
             AutorefOrPtrAdjustment::ToConstPtr => None,
         }
     }
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index a746ad7ad4b..9744f4f6483 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -1655,7 +1655,7 @@ fn compute_all_traits(tcx: TyCtxt<'_>, (): ()) -> &[DefId] {
         tcx: TyCtxt<'_>,
         traits: &mut Vec<DefId>,
         external_mods: &mut FxHashSet<DefId>,
-        res: Res,
+        res: Res<!>,
     ) {
         match res {
             Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) => {
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index 803c440bbc9..a10490a9a15 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -388,7 +388,7 @@ fn typeck_with_fallback<'tcx>(
             // from normalization. We could just discard these, but to align with
             // compare_method and elsewhere, we just add implied bounds for
             // these types.
-            let mut wf_tys = vec![];
+            let mut wf_tys = FxHashSet::default();
             // Compute the fty from point of view of inside the fn.
             let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
             wf_tys.extend(fn_sig.inputs_and_output.iter());
@@ -451,7 +451,7 @@ fn typeck_with_fallback<'tcx>(
 
             fcx.write_ty(id, expected_type);
 
-            (fcx, vec![])
+            (fcx, FxHashSet::default())
         };
 
         let fallback_has_occurred = fcx.type_inference_fallback();
@@ -475,7 +475,7 @@ fn typeck_with_fallback<'tcx>(
         fcx.select_all_obligations_or_error();
 
         if fn_sig.is_some() {
-            fcx.regionck_fn(id, body, span, &wf_tys);
+            fcx.regionck_fn(id, body, span, wf_tys);
         } else {
             fcx.regionck_expr(body);
         }
diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_typeck/src/check/op.rs
index 9b495fba197..a574a63d63b 100644
--- a/compiler/rustc_typeck/src/check/op.rs
+++ b/compiler/rustc_typeck/src/check/op.rs
@@ -680,42 +680,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         ex.span,
                         format!("cannot apply unary operator `{}`", op.as_str()),
                     );
-                    match actual.kind() {
-                        Uint(_) if op == hir::UnOp::Neg => {
-                            err.note("unsigned values cannot be negated");
-
-                            if let hir::ExprKind::Unary(
-                                _,
-                                hir::Expr {
-                                    kind:
-                                        hir::ExprKind::Lit(Spanned {
-                                            node: ast::LitKind::Int(1, _),
-                                            ..
-                                        }),
-                                    ..
-                                },
-                            ) = ex.kind
-                            {
-                                err.span_suggestion(
-                                    ex.span,
-                                    &format!(
-                                        "you may have meant the maximum value of `{}`",
-                                        actual
-                                    ),
-                                    format!("{}::MAX", actual),
-                                    Applicability::MaybeIncorrect,
-                                );
+
+                    let sp = self.tcx.sess.source_map().start_point(ex.span);
+                    if let Some(sp) =
+                        self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp)
+                    {
+                        // If the previous expression was a block expression, suggest parentheses
+                        // (turning this into a binary subtraction operation instead.)
+                        // for example, `{2} - 2` -> `({2}) - 2` (see src\test\ui\parser\expr-as-stmt.rs)
+                        self.tcx.sess.parse_sess.expr_parentheses_needed(&mut err, *sp);
+                    } else {
+                        match actual.kind() {
+                            Uint(_) if op == hir::UnOp::Neg => {
+                                err.note("unsigned values cannot be negated");
+
+                                if let hir::ExprKind::Unary(
+                                    _,
+                                    hir::Expr {
+                                        kind:
+                                            hir::ExprKind::Lit(Spanned {
+                                                node: ast::LitKind::Int(1, _),
+                                                ..
+                                            }),
+                                        ..
+                                    },
+                                ) = ex.kind
+                                {
+                                    err.span_suggestion(
+                                        ex.span,
+                                        &format!(
+                                            "you may have meant the maximum value of `{}`",
+                                            actual
+                                        ),
+                                        format!("{}::MAX", actual),
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                }
+                            }
+                            Str | Never | Char | Tuple(_) | Array(_, _) => {}
+                            Ref(_, ref lty, _) if *lty.kind() == Str => {}
+                            _ => {
+                                let missing_trait = match op {
+                                    hir::UnOp::Neg => "std::ops::Neg",
+                                    hir::UnOp::Not => "std::ops::Not",
+                                    hir::UnOp::Deref => "std::ops::UnDerf",
+                                };
+                                suggest_impl_missing(&mut err, operand_ty, &missing_trait);
                             }
-                        }
-                        Str | Never | Char | Tuple(_) | Array(_, _) => {}
-                        Ref(_, ref lty, _) if *lty.kind() == Str => {}
-                        _ => {
-                            let missing_trait = match op {
-                                hir::UnOp::Neg => "std::ops::Neg",
-                                hir::UnOp::Not => "std::ops::Not",
-                                hir::UnOp::Deref => "std::ops::UnDerf",
-                            };
-                            suggest_impl_missing(&mut err, operand_ty, &missing_trait);
                         }
                     }
                     err.emit();
diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs
index 140a9d1126d..a056ab6aef2 100644
--- a/compiler/rustc_typeck/src/check/pat.rs
+++ b/compiler/rustc_typeck/src/check/pat.rs
@@ -11,6 +11,7 @@ use rustc_infer::infer;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_middle::ty::subst::GenericArg;
 use rustc_middle::ty::{self, Adt, BindingMode, Ty, TypeFoldable};
+use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::{Span, Spanned};
@@ -1261,7 +1262,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         // Require `..` if struct has non_exhaustive attribute.
-        if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc {
+        let non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did.is_local();
+        if non_exhaustive && !etc {
             self.error_foreign_non_exhaustive_spat(pat, adt.variant_descr(), fields.is_empty());
         }
 
@@ -1276,7 +1278,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             if etc {
                 tcx.sess.struct_span_err(pat.span, "`..` cannot be used in union patterns").emit();
             }
-        } else if !etc && !unmentioned_fields.is_empty() {
+        } else if !unmentioned_fields.is_empty() {
             let accessible_unmentioned_fields: Vec<_> = unmentioned_fields
                 .iter()
                 .copied()
@@ -1284,16 +1286,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     field.vis.is_accessible_from(tcx.parent_module(pat.hir_id).to_def_id(), tcx)
                 })
                 .collect();
-
-            if accessible_unmentioned_fields.is_empty() {
-                unmentioned_err = Some(self.error_no_accessible_fields(pat, &fields));
-            } else {
-                unmentioned_err = Some(self.error_unmentioned_fields(
-                    pat,
-                    &accessible_unmentioned_fields,
-                    accessible_unmentioned_fields.len() != unmentioned_fields.len(),
-                    &fields,
-                ));
+            if non_exhaustive {
+                self.non_exhaustive_reachable_pattern(pat, &accessible_unmentioned_fields, adt_ty)
+            } else if !etc {
+                if accessible_unmentioned_fields.is_empty() {
+                    unmentioned_err = Some(self.error_no_accessible_fields(pat, &fields));
+                } else {
+                    unmentioned_err = Some(self.error_unmentioned_fields(
+                        pat,
+                        &accessible_unmentioned_fields,
+                        accessible_unmentioned_fields.len() != unmentioned_fields.len(),
+                        &fields,
+                    ));
+                }
             }
         }
         match (inexistent_fields_err, unmentioned_err) {
@@ -1604,6 +1609,51 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         err
     }
 
+    /// Report that a pattern for a `#[non_exhaustive]` struct marked with `non_exhaustive_omitted_patterns`
+    /// is not exhaustive enough.
+    ///
+    /// Nb: the partner lint for enums lives in `compiler/rustc_mir_build/src/thir/pattern/usefulness.rs`.
+    fn non_exhaustive_reachable_pattern(
+        &self,
+        pat: &Pat<'_>,
+        unmentioned_fields: &[(&ty::FieldDef, Ident)],
+        ty: Ty<'tcx>,
+    ) {
+        fn joined_uncovered_patterns(witnesses: &[&Ident]) -> String {
+            const LIMIT: usize = 3;
+            match witnesses {
+                [] => bug!(),
+                [witness] => format!("`{}`", witness),
+                [head @ .., tail] if head.len() < LIMIT => {
+                    let head: Vec<_> = head.iter().map(<_>::to_string).collect();
+                    format!("`{}` and `{}`", head.join("`, `"), tail)
+                }
+                _ => {
+                    let (head, tail) = witnesses.split_at(LIMIT);
+                    let head: Vec<_> = head.iter().map(<_>::to_string).collect();
+                    format!("`{}` and {} more", head.join("`, `"), tail.len())
+                }
+            }
+        }
+        let joined_patterns = joined_uncovered_patterns(
+            &unmentioned_fields.iter().map(|(_, i)| i).collect::<Vec<_>>(),
+        );
+
+        self.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, pat.hir_id, pat.span, |build| {
+        let mut lint = build.build("some fields are not explicitly listed");
+        lint.span_label(pat.span, format!("field{} {} not listed", rustc_errors::pluralize!(unmentioned_fields.len()), joined_patterns));
+
+        lint.help(
+            "ensure that all fields are mentioned explicitly by adding the suggested fields",
+        );
+        lint.note(&format!(
+            "the pattern is of type `{}` and the `non_exhaustive_omitted_patterns` attribute was found",
+            ty,
+        ));
+        lint.emit();
+    });
+    }
+
     /// Returns a diagnostic reporting a struct pattern which does not mention some fields.
     ///
     /// ```text
diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs
index 290fa5fc367..134604a0e32 100644
--- a/compiler/rustc_typeck/src/check/regionck.rs
+++ b/compiler/rustc_typeck/src/check/regionck.rs
@@ -76,6 +76,7 @@ use crate::check::dropck;
 use crate::check::FnCtxt;
 use crate::mem_categorization as mc;
 use crate::middle::region;
+use rustc_data_structures::stable_set::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
@@ -126,7 +127,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     /// Region checking during the WF phase for items. `wf_tys` are the
     /// types from which we should derive implied bounds, if any.
-    pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: &[Ty<'tcx>]) {
+    pub fn regionck_item(&self, item_id: hir::HirId, span: Span, wf_tys: FxHashSet<Ty<'tcx>>) {
         debug!("regionck_item(item.id={:?}, wf_tys={:?})", item_id, wf_tys);
         let subject = self.tcx.hir().local_def_id(item_id);
         let mut rcx = RegionCtxt::new(self, item_id, Subject(subject), self.param_env);
@@ -149,7 +150,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         fn_id: hir::HirId,
         body: &'tcx hir::Body<'tcx>,
         span: Span,
-        wf_tys: &[Ty<'tcx>],
+        wf_tys: FxHashSet<Ty<'tcx>>,
     ) {
         debug!("regionck_fn(id={})", fn_id);
         let subject = self.tcx.hir().body_owner_def_id(body.id());
@@ -286,15 +287,10 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
         // because it will have no effect.
         //
         // FIXME(#27579) return types should not be implied bounds
-        let fn_sig_tys: Vec<_> =
+        let fn_sig_tys: FxHashSet<_> =
             fn_sig.inputs().iter().cloned().chain(Some(fn_sig.output())).collect();
 
-        self.outlives_environment.add_implied_bounds(
-            self.fcx,
-            &fn_sig_tys[..],
-            body_id.hir_id,
-            span,
-        );
+        self.outlives_environment.add_implied_bounds(self.fcx, fn_sig_tys, body_id.hir_id, span);
         self.outlives_environment.save_implied_bounds(body_id.hir_id);
         self.link_fn_params(&body.params);
         self.visit_body(body);
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index 17716afe320..cb07fcf5fef 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -44,7 +44,7 @@ struct CheckWfFcxBuilder<'tcx> {
 impl<'tcx> CheckWfFcxBuilder<'tcx> {
     fn with_fcx<F>(&mut self, f: F)
     where
-        F: for<'b> FnOnce(&FnCtxt<'b, 'tcx>) -> Vec<Ty<'tcx>>,
+        F: for<'b> FnOnce(&FnCtxt<'b, 'tcx>) -> FxHashSet<Ty<'tcx>>,
     {
         let id = self.id;
         let span = self.span;
@@ -59,7 +59,7 @@ impl<'tcx> CheckWfFcxBuilder<'tcx> {
             }
             let wf_tys = f(&fcx);
             fcx.select_all_obligations_or_error();
-            fcx.regionck_item(id, span, &wf_tys);
+            fcx.regionck_item(id, span, wf_tys);
         });
     }
 }
@@ -394,7 +394,7 @@ fn check_associated_item(
         let item = fcx.tcx.associated_item(fcx.tcx.hir().local_def_id(item_id));
 
         let (mut implied_bounds, self_ty) = match item.container {
-            ty::TraitContainer(_) => (vec![], fcx.tcx.types.self_param),
+            ty::TraitContainer(_) => (FxHashSet::default(), fcx.tcx.types.self_param),
             ty::ImplContainer(def_id) => {
                 (fcx.impl_implied_bounds(def_id, span), fcx.tcx.type_of(def_id))
             }
@@ -553,7 +553,7 @@ fn check_type_defn<'tcx, F>(
         check_where_clauses(fcx, item.span, item.def_id.to_def_id(), None);
 
         // No implied bounds in a struct definition.
-        vec![]
+        FxHashSet::default()
     });
 }
 
@@ -579,7 +579,7 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
     for_item(tcx, item).with_fcx(|fcx| {
         check_where_clauses(fcx, item.span, item.def_id.to_def_id(), None);
 
-        vec![]
+        FxHashSet::default()
     });
 }
 
@@ -620,7 +620,7 @@ fn check_item_fn(
     for_id(tcx, item_id, span).with_fcx(|fcx| {
         let def_id = tcx.hir().local_def_id(item_id);
         let sig = tcx.fn_sig(def_id);
-        let mut implied_bounds = vec![];
+        let mut implied_bounds = FxHashSet::default();
         check_fn_or_method(fcx, ident.span, sig, decl, def_id.to_def_id(), &mut implied_bounds);
         implied_bounds
     })
@@ -659,7 +659,7 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: hir::HirId, ty_span: Span, allow_fo
         }
 
         // No implied bounds in a const, etc.
-        vec![]
+        FxHashSet::default()
     });
 }
 
@@ -918,14 +918,14 @@ fn check_fn_or_method<'fcx, 'tcx>(
     sig: ty::PolyFnSig<'tcx>,
     hir_decl: &hir::FnDecl<'_>,
     def_id: DefId,
-    implied_bounds: &mut Vec<Ty<'tcx>>,
+    implied_bounds: &mut FxHashSet<Ty<'tcx>>,
 ) {
     let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig);
 
     // Unnormalized types in signature are WF too
     implied_bounds.extend(sig.inputs());
     // FIXME(#27579) return types should not be implied bounds
-    implied_bounds.push(sig.output());
+    implied_bounds.insert(sig.output());
 
     // Normalize the input and output types one at a time, using a different
     // `WellFormedLoc` for each. We cannot call `normalize_associated_types`
@@ -977,7 +977,7 @@ fn check_fn_or_method<'fcx, 'tcx>(
     );
 
     // FIXME(#27579) return types should not be implied bounds
-    implied_bounds.push(sig.output());
+    implied_bounds.insert(sig.output());
 
     debug!(?implied_bounds);
 
@@ -1513,7 +1513,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .collect()
     }
 
-    pub(super) fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec<Ty<'tcx>> {
+    pub(super) fn impl_implied_bounds(
+        &self,
+        impl_def_id: DefId,
+        span: Span,
+    ) -> FxHashSet<Ty<'tcx>> {
         match self.tcx.impl_trait_ref(impl_def_id) {
             Some(trait_ref) => {
                 // Trait impl: take implied bounds from all types that
@@ -1526,7 +1530,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Inherent impl: take implied bounds from the `self` type.
                 let self_ty = self.tcx.type_of(impl_def_id);
                 let self_ty = self.normalize_associated_types_in(span, self_ty);
-                vec![self_ty]
+                std::array::IntoIter::new([self_ty]).collect()
             }
         }
     }
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 3688fa05e03..1bc7bc3e063 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -46,7 +46,7 @@ use rustc_session::lint;
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
-use rustc_target::spec::{abi, SanitizerSet};
+use rustc_target::spec::{abi, PanicStrategy, SanitizerSet};
 use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
 use std::iter;
 
@@ -450,9 +450,9 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
                             let suggestions = vec![
                                 (lt_sp, sugg),
                                 (
-                                    span,
+                                    span.with_hi(item_segment.ident.span.lo()),
                                     format!(
-                                        "{}::{}",
+                                        "{}::",
                                         // Replace the existing lifetimes with a new named lifetime.
                                         self.tcx
                                             .replace_late_bound_regions(poly_trait_ref, |_| {
@@ -465,7 +465,6 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
                                                 ))
                                             })
                                             .0,
-                                        item_segment.ident
                                     ),
                                 ),
                             ];
@@ -487,14 +486,13 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
                 | hir::Node::ForeignItem(_)
                 | hir::Node::TraitItem(_)
                 | hir::Node::ImplItem(_) => {
-                    err.span_suggestion(
-                        span,
+                    err.span_suggestion_verbose(
+                        span.with_hi(item_segment.ident.span.lo()),
                         "use a fully qualified path with inferred lifetimes",
                         format!(
-                            "{}::{}",
+                            "{}::",
                             // Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`.
                             self.tcx.anonymize_late_bound_regions(poly_trait_ref).skip_binder(),
-                            item_segment.ident
                         ),
                         Applicability::MaybeIncorrect,
                     );
@@ -2683,6 +2681,13 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
         codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
     }
 
+    // With -Z panic-in-drop=abort, drop_in_place never unwinds.
+    if tcx.sess.opts.debugging_opts.panic_in_drop == PanicStrategy::Abort {
+        if Some(id) == tcx.lang_items().drop_in_place_fn() {
+            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
+        }
+    }
+
     let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
 
     let mut inline_span = None;
diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs
index 749f681e92e..c703ca96ada 100644
--- a/compiler/rustc_typeck/src/lib.rs
+++ b/compiler/rustc_typeck/src/lib.rs
@@ -56,7 +56,6 @@ This API is completely unstable and subject to change.
 */
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![cfg_attr(bootstrap, feature(bindings_after_at))]
 #![feature(bool_to_option)]
 #![feature(crate_visibility_modifier)]
 #![feature(format_args_capture)]
@@ -69,7 +68,6 @@ This API is completely unstable and subject to change.
 #![feature(never_type)]
 #![feature(slice_partition_dedup)]
 #![feature(control_flow_enum)]
-#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 1a387f291cc..2aed9d03bc0 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -85,7 +85,6 @@
 #![feature(allow_internal_unstable)]
 #![feature(arbitrary_self_types)]
 #![feature(async_stream)]
-#![cfg_attr(bootstrap, feature(bindings_after_at))]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(cfg_sanitize)]
@@ -143,8 +142,6 @@
 #![feature(alloc_layout_extra)]
 #![feature(trusted_random_access)]
 #![feature(try_trait_v2)]
-#![cfg_attr(bootstrap, feature(min_type_alias_impl_trait))]
-#![cfg_attr(not(bootstrap), feature(type_alias_impl_trait))]
 #![feature(associated_type_bounds)]
 #![feature(slice_group_by)]
 #![feature(decl_macro)]
diff --git a/library/backtrace b/library/backtrace
-Subproject 4f925f8d81dfa57067537217e501e1dff743349
+Subproject cc89bb66f91b2b4a640b0b525ca5d753e3346d7
diff --git a/library/core/primitive_docs/box_into_raw.md b/library/core/primitive_docs/box_into_raw.md
new file mode 100644
index 00000000000..9dd0344c7c7
--- /dev/null
+++ b/library/core/primitive_docs/box_into_raw.md
@@ -0,0 +1 @@
+../std/boxed/struct.Box.html#method.into_raw
diff --git a/library/core/primitive_docs/fs_file.md b/library/core/primitive_docs/fs_file.md
new file mode 100644
index 00000000000..4023e340a51
--- /dev/null
+++ b/library/core/primitive_docs/fs_file.md
@@ -0,0 +1 @@
+../std/fs/struct.File.html
diff --git a/library/core/primitive_docs/io_bufread.md b/library/core/primitive_docs/io_bufread.md
new file mode 100644
index 00000000000..7beda2cd390
--- /dev/null
+++ b/library/core/primitive_docs/io_bufread.md
@@ -0,0 +1 @@
+../std/io/trait.BufRead.html
diff --git a/library/core/primitive_docs/io_read.md b/library/core/primitive_docs/io_read.md
new file mode 100644
index 00000000000..b7ecf5e273c
--- /dev/null
+++ b/library/core/primitive_docs/io_read.md
@@ -0,0 +1 @@
+../std/io/trait.Read.html
diff --git a/library/core/primitive_docs/io_seek.md b/library/core/primitive_docs/io_seek.md
new file mode 100644
index 00000000000..db0274d291c
--- /dev/null
+++ b/library/core/primitive_docs/io_seek.md
@@ -0,0 +1 @@
+../std/io/trait.Seek.html
diff --git a/library/core/primitive_docs/io_write.md b/library/core/primitive_docs/io_write.md
new file mode 100644
index 00000000000..92a3b88a79c
--- /dev/null
+++ b/library/core/primitive_docs/io_write.md
@@ -0,0 +1 @@
+../std/io/trait.Write.html
diff --git a/library/core/primitive_docs/net_tosocketaddrs.md b/library/core/primitive_docs/net_tosocketaddrs.md
new file mode 100644
index 00000000000..4daa10ddbe2
--- /dev/null
+++ b/library/core/primitive_docs/net_tosocketaddrs.md
@@ -0,0 +1 @@
+../std/net/trait.ToSocketAddrs.html
diff --git a/library/core/primitive_docs/process_exit.md b/library/core/primitive_docs/process_exit.md
new file mode 100644
index 00000000000..cae34d12d52
--- /dev/null
+++ b/library/core/primitive_docs/process_exit.md
@@ -0,0 +1 @@
+../std/process/fn.exit.html
diff --git a/library/core/primitive_docs/string_string.md b/library/core/primitive_docs/string_string.md
new file mode 100644
index 00000000000..303dc07b185
--- /dev/null
+++ b/library/core/primitive_docs/string_string.md
@@ -0,0 +1 @@
+../std/string/struct.String.html
diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs
index ca1c0ae7598..f14c2a46416 100644
--- a/library/core/src/bool.rs
+++ b/library/core/src/bool.rs
@@ -2,7 +2,8 @@
 
 #[lang = "bool"]
 impl bool {
-    /// Returns `Some(t)` if the `bool` is [`true`](keyword.true.html), or `None` otherwise.
+    /// Returns `Some(t)` if the `bool` is [`true`](../std/keyword.true.html),
+    /// or `None` otherwise.
     ///
     /// # Examples
     ///
@@ -18,7 +19,8 @@ impl bool {
         if self { Some(t) } else { None }
     }
 
-    /// Returns `Some(f())` if the `bool` is [`true`](keyword.true.html), or `None` otherwise.
+    /// Returns `Some(f())` if the `bool` is [`true`](../std/keyword.true.html),
+    /// or `None` otherwise.
     ///
     /// # Examples
     ///
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 2adf6a549e6..e56b631dbaf 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -1916,7 +1916,8 @@ impl<T: ?Sized> UnsafeCell<T> {
     /// ```
     #[inline(always)]
     #[stable(feature = "unsafe_cell_get_mut", since = "1.50.0")]
-    pub fn get_mut(&mut self) -> &mut T {
+    #[rustc_const_unstable(feature = "const_unsafecell_get_mut", issue = "88836")]
+    pub const fn get_mut(&mut self) -> &mut T {
         &mut self.value
     }
 
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index e6d3ac8f2d2..b1dd6aef974 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -24,7 +24,7 @@ impl char {
     /// decoding error.
     ///
     /// It can occur, for example, when giving ill-formed UTF-8 bytes to
-    /// [`String::from_utf8_lossy`](string/struct.String.html#method.from_utf8_lossy).
+    /// [`String::from_utf8_lossy`](../std/string/struct.String.html#method.from_utf8_lossy).
     #[stable(feature = "assoc_char_consts", since = "1.52.0")]
     pub const REPLACEMENT_CHARACTER: char = '\u{FFFD}';
 
@@ -96,7 +96,7 @@ impl char {
     /// Converts a `u32` to a `char`.
     ///
     /// Note that all `char`s are valid [`u32`]s, and can be cast to one with
-    /// [`as`](keyword.as.html):
+    /// [`as`](../std/keyword.as.html):
     ///
     /// ```
     /// let c = '💯';
@@ -372,7 +372,7 @@ impl char {
     /// println!("\\u{{2764}}");
     /// ```
     ///
-    /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
+    /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
     ///
     /// ```
     /// assert_eq!('❤'.escape_unicode().to_string(), "\\u{2764}");
@@ -448,7 +448,7 @@ impl char {
     /// println!("\\n");
     /// ```
     ///
-    /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
+    /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
     ///
     /// ```
     /// assert_eq!('\n'.escape_debug().to_string(), "\\n");
@@ -502,7 +502,7 @@ impl char {
     /// println!("\\\"");
     /// ```
     ///
-    /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
+    /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
     ///
     /// ```
     /// assert_eq!('"'.escape_default().to_string(), "\\\"");
@@ -937,7 +937,7 @@ impl char {
     /// println!("i\u{307}");
     /// ```
     ///
-    /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
+    /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
     ///
     /// ```
     /// assert_eq!('C'.to_lowercase().to_string(), "c");
@@ -1002,7 +1002,7 @@ impl char {
     /// println!("SS");
     /// ```
     ///
-    /// Using [`to_string`](string/trait.ToString.html#tymethod.to_string):
+    /// Using [`to_string`](../std/string/trait.ToString.html#tymethod.to_string):
     ///
     /// ```
     /// assert_eq!('c'.to_uppercase().to_string(), "C");
diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs
index 19faf9cddac..b02333b0288 100644
--- a/library/core/src/clone.rs
+++ b/library/core/src/clone.rs
@@ -105,6 +105,7 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 #[lang = "clone"]
 #[rustc_diagnostic_item = "Clone"]
+#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)]
 pub trait Clone: Sized {
     /// Returns a copy of the value.
     ///
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index aff789f2afa..166a8e3f28a 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -333,7 +333,6 @@ enum FlagV1 {
 impl<'a> Arguments<'a> {
     /// When using the format_args!() macro, this function is used to generate the
     /// Arguments structure.
-    #[cfg(not(bootstrap))]
     #[doc(hidden)]
     #[inline]
     #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
@@ -347,17 +346,6 @@ impl<'a> Arguments<'a> {
         }
         Arguments { pieces, fmt: None, args }
     }
-    #[cfg(bootstrap)]
-    #[doc(hidden)]
-    #[inline]
-    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
-    #[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
-    pub const fn new_v1(pieces: &'a [&'static str], args: &'a [ArgumentV1<'a>]) -> Arguments<'a> {
-        if pieces.len() < args.len() || pieces.len() > args.len() + 1 {
-            panic!("invalid args");
-        }
-        Arguments { pieces, fmt: None, args }
-    }
 
     /// This function is used to specify nonstandard formatting parameters.
     /// The `pieces` array must be at least as long as `fmt` to construct
@@ -365,7 +353,6 @@ impl<'a> Arguments<'a> {
     /// `CountIsParam` or `CountIsNextParam` has to point to an argument
     /// created with `argumentusize`. However, failing to do so doesn't cause
     /// unsafety, but will ignore invalid .
-    #[cfg(not(bootstrap))]
     #[doc(hidden)]
     #[inline]
     #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
@@ -377,18 +364,6 @@ impl<'a> Arguments<'a> {
     ) -> Arguments<'a> {
         Arguments { pieces, fmt: Some(fmt), args }
     }
-    #[cfg(bootstrap)]
-    #[doc(hidden)]
-    #[inline]
-    #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")]
-    #[rustc_const_unstable(feature = "const_fmt_arguments_new", issue = "none")]
-    pub const fn new_v1_formatted(
-        pieces: &'a [&'static str],
-        args: &'a [ArgumentV1<'a>],
-        fmt: &'a [rt::v1::Argument],
-    ) -> Arguments<'a> {
-        Arguments { pieces, fmt: Some(fmt), args }
-    }
 
     /// Estimates the length of the formatted text.
     ///
@@ -607,6 +582,7 @@ impl Display for Arguments<'_> {
 )]
 #[doc(alias = "{:?}")]
 #[rustc_diagnostic_item = "debug_trait"]
+#[cfg_attr(not(bootstrap), rustc_trivial_field_reads)]
 pub trait Debug {
     /// Formats the value using the given formatter.
     ///
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index ba878ff66a0..1c3afcdaa69 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -154,18 +154,6 @@ pub fn spin_loop() {
 /// [`std::convert::identity`]: crate::convert::identity
 #[inline]
 #[unstable(feature = "bench_black_box", issue = "64102")]
-#[cfg_attr(not(bootstrap), allow(unused_mut))]
-#[cfg_attr(bootstrap, allow(deprecated))]
-pub fn black_box<T>(mut dummy: T) -> T {
-    #[cfg(bootstrap)]
-    // SAFETY: the inline assembly is a no-op.
-    unsafe {
-        llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile");
-        dummy
-    }
-
-    #[cfg(not(bootstrap))]
-    {
-        crate::intrinsics::black_box(dummy)
-    }
+pub fn black_box<T>(dummy: T) -> T {
+    crate::intrinsics::black_box(dummy)
 }
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 9278dbb5498..3e26d46ddca 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1937,7 +1937,6 @@ extern "rust-intrinsic" {
     /// See documentation of [`std::hint::black_box`] for details.
     ///
     /// [`std::hint::black_box`]: crate::hint::black_box
-    #[cfg(not(bootstrap))]
     pub fn black_box<T>(dummy: T) -> T;
 }
 
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 330d3714247..b0a9d9f5ef5 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -2172,8 +2172,9 @@ pub trait Iterator {
     /// If the iterator is empty, returns [`None`]; otherwise, returns the
     /// result of the reduction.
     ///
+    /// The reducing function is a closure with two arguments: an 'accumulator', and an element.
     /// For iterators with at least one element, this is the same as [`fold()`]
-    /// with the first element of the iterator as the initial value, folding
+    /// with the first element of the iterator as the initial accumulator value, folding
     /// every subsequent element into it.
     ///
     /// [`fold()`]: Iterator::fold
@@ -2187,8 +2188,8 @@ pub trait Iterator {
     ///     where I: Iterator,
     ///           I::Item: Ord,
     /// {
-    ///     iter.reduce(|a, b| {
-    ///         if a >= b { a } else { b }
+    ///     iter.reduce(|accum, item| {
+    ///         if accum >= item { accum } else { item }
     ///     })
     /// }
     /// let a = [10, 20, 5, -23, 0];
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index d667fff4b81..265ba9f1bb9 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -69,7 +69,6 @@
 #![warn(missing_debug_implementations)]
 #![warn(missing_docs)]
 #![allow(explicit_outlives_requirements)]
-#![cfg_attr(bootstrap, allow(incomplete_features))] // if_let_guard
 //
 // Library features for const fns:
 #![feature(const_align_of_val)]
@@ -122,8 +121,6 @@
 #![feature(const_fn_floating_point_arithmetic)]
 #![feature(const_fn_fn_ptr_basics)]
 #![feature(const_fn_trait_bound)]
-#![cfg_attr(bootstrap, feature(const_fn_transmute))]
-#![cfg_attr(bootstrap, feature(const_fn_union))]
 #![feature(const_impl_trait)]
 #![feature(const_mut_refs)]
 #![feature(const_panic)]
@@ -133,6 +130,7 @@
 #![feature(decl_macro)]
 #![feature(doc_cfg)]
 #![feature(doc_notable_trait)]
+#![feature(doc_primitive)]
 #![feature(exhaustive_patterns)]
 #![feature(extern_types)]
 #![feature(fundamental)]
@@ -358,3 +356,5 @@ pub mod arch {
         /* compiler built-in */
     }
 }
+
+include!("primitive_docs.rs");
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index a3a074ac131..035a748f782 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -842,7 +842,6 @@ pub(crate) mod builtin {
     /// This macro is used by the panic macros for the `const_panic` feature.
     ///
     /// This macro will be removed once `format_args` is allowed in const contexts.
-    #[cfg(not(bootstrap))]
     #[unstable(feature = "const_format_args", issue = "none")]
     #[allow_internal_unstable(fmt_internals, const_fmt_arguments_new)]
     #[rustc_builtin_macro]
@@ -852,16 +851,6 @@ pub(crate) mod builtin {
         ($fmt:expr, $($args:tt)*) => {{ /* compiler built-in */ }};
     }
 
-    /// Same as `format_args`, but can be used in some const contexts.
-    #[cfg(bootstrap)]
-    #[unstable(feature = "const_format_args", issue = "none")]
-    #[macro_export]
-    macro_rules! const_format_args {
-        ($($t:tt)*) => {
-            $crate::format_args!($($t)*)
-        }
-    }
-
     /// Same as `format_args`, but adds a newline in the end.
     #[unstable(
         feature = "format_args_nl",
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 82962a1fe13..a7ed5bfaf85 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -99,17 +99,15 @@ pub trait Sized {
 /// `Unsize<dyn fmt::Debug>`.
 ///
 /// All implementations of `Unsize` are provided automatically by the compiler.
-///
-/// `Unsize` is implemented for:
-///
-/// - `[T; N]` is `Unsize<[T]>`
-/// - `T` is `Unsize<dyn Trait>` when `T: Trait`
-/// - `Foo<..., T, ...>` is `Unsize<Foo<..., U, ...>>` if:
-///   - `T: Unsize<U>`
-///   - Foo is a struct
-///   - Only the last field of `Foo` has a type involving `T`
-///   - `T` is not part of the type of any other fields
-///   - `Bar<T>: Unsize<Bar<U>>`, if the last field of `Foo` has type `Bar<T>`
+/// Those implementations are:
+///
+/// - Arrays `[T; N]` implement `Unsize<[T]>`.
+/// - Types implementing a trait `Trait` also implement `Unsize<dyn Trait>`.
+/// - Structs `Foo<..., T, ...>` implement `Unsize<Foo<..., U, ...>>` if all of these conditions
+///   are met:
+///   - `T: Unsize<U>`.
+///   - Only the last field of `Foo` has a type involving `T`.
+///   - `Bar<T>: Unsize<Bar<U>>`, where `Bar<T>` stands for the actual type of that last field.
 ///
 /// `Unsize` is used along with [`ops::CoerceUnsized`] to allow
 /// "user-defined" containers such as [`Rc`] to contain dynamically-sized
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 77643290cc4..2a02545041d 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -2350,7 +2350,6 @@ macro_rules! int_impl {
         #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
         // SAFETY: const sound because integers are plain old datatypes so we can always
         // transmute them to arrays of bytes
-        #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_fn_transmute))]
         #[inline]
         pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
             // SAFETY: integers are plain old datatypes so we can always transmute them to
@@ -2456,7 +2455,6 @@ macro_rules! int_impl {
         #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
         // SAFETY: const sound because integers are plain old datatypes so we can always
         // transmute to them
-        #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_fn_transmute))]
         #[inline]
         pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
             // SAFETY: integers are plain old datatypes so we can always transmute to them
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 46e64c33b84..7523d8ec976 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -1924,7 +1924,8 @@ macro_rules! uint_impl {
         }
 
         /// Calculates the smallest value greater than or equal to `self` that
-        /// is a multiple of `rhs`. If `rhs` is negative,
+        /// is a multiple of `rhs`. Returns `None` is `rhs` is zero or the
+        /// operation would result in overflow.
         ///
         /// # Examples
         ///
@@ -2118,7 +2119,6 @@ macro_rules! uint_impl {
         #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
         // SAFETY: const sound because integers are plain old datatypes so we can always
         // transmute them to arrays of bytes
-        #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_fn_transmute))]
         #[inline]
         pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
             // SAFETY: integers are plain old datatypes so we can always transmute them to
@@ -2224,7 +2224,6 @@ macro_rules! uint_impl {
         #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
         // SAFETY: const sound because integers are plain old datatypes so we can always
         // transmute to them
-        #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_fn_transmute))]
         #[inline]
         pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
             // SAFETY: integers are plain old datatypes so we can always transmute to them
diff --git a/library/core/src/num/wrapping.rs b/library/core/src/num/wrapping.rs
index be6d70320d4..b078cdf5479 100644
--- a/library/core/src/num/wrapping.rs
+++ b/library/core/src/num/wrapping.rs
@@ -32,6 +32,10 @@ use crate::ops::{Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign};
 ///
 /// assert_eq!(u32::MAX, (zero - one).0);
 /// ```
+///
+/// # Layout
+///
+/// `Wrapping<T>` is guaranteed to have the same layout and ABI as `T`.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)]
 #[repr(transparent)]
diff --git a/library/core/src/ops/bit.rs b/library/core/src/ops/bit.rs
index 51f80438173..92f45ac9e7e 100644
--- a/library/core/src/ops/bit.rs
+++ b/library/core/src/ops/bit.rs
@@ -30,6 +30,7 @@
 /// ```
 #[lang = "not"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[doc(alias = "!")]
 pub trait Not {
     /// The resulting type after applying the `!` operator.
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 9d5e03dd0de..907726f0c34 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -1173,7 +1173,7 @@ impl<T> Option<T> {
     // Entry-like operations to insert a value and return a reference
     /////////////////////////////////////////////////////////////////////////
 
-    /// Inserts `value` into the option then returns a mutable reference to it.
+    /// Inserts `value` into the option, then returns a mutable reference to it.
     ///
     /// If the option already contains a value, the old value is dropped.
     ///
@@ -1397,7 +1397,7 @@ impl<T> Option<T> {
 }
 
 impl<T, U> Option<(T, U)> {
-    /// Unzips an option containing a tuple of two options
+    /// Unzips an option containing a tuple of two options.
     ///
     /// If `self` is `Some((a, b))` this method returns `(Some(a), Some(b))`.
     /// Otherwise, `(None, None)` is returned.
@@ -1500,7 +1500,7 @@ impl<T: Clone> Option<&mut T> {
 }
 
 impl<T: Default> Option<T> {
-    /// Returns the contained [`Some`] value or a default
+    /// Returns the contained [`Some`] value or a default.
     ///
     /// Consumes the `self` argument then, if [`Some`], returns the contained
     /// value, otherwise if [`None`], returns the [default value] for that
@@ -1561,7 +1561,7 @@ impl<T: DerefMut> Option<T> {
     /// Converts from `Option<T>` (or `&mut Option<T>`) to `Option<&mut T::Target>`.
     ///
     /// Leaves the original `Option` in-place, creating a new one containing a mutable reference to
-    /// the inner type's `Deref::Target` type.
+    /// the inner type's [`Deref::Target`] type.
     ///
     /// # Examples
     ///
@@ -1701,7 +1701,7 @@ impl<'a, T> IntoIterator for &'a mut Option<T> {
 
 #[stable(since = "1.12.0", feature = "option_from")]
 impl<T> From<T> for Option<T> {
-    /// Copies `val` into a new `Some`.
+    /// Moves `val` into a new [`Some`].
     ///
     /// # Examples
     ///
@@ -1942,8 +1942,8 @@ unsafe impl<A> TrustedLen for IntoIter<A> {}
 impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
     /// Takes each element in the [`Iterator`]: if it is [`None`][Option::None],
     /// no further elements are taken, and the [`None`][Option::None] is
-    /// returned. Should no [`None`][Option::None] occur, a container with the
-    /// values of each [`Option`] is returned.
+    /// returned. Should no [`None`][Option::None] occur, a container of type
+    /// `V` containing the values of each [`Option`] is returned.
     ///
     /// # Examples
     ///
@@ -2039,7 +2039,7 @@ impl<T> ops::FromResidual for Option<T> {
 }
 
 impl<T> Option<Option<T>> {
-    /// Converts from `Option<Option<T>>` to `Option<T>`
+    /// Converts from `Option<Option<T>>` to `Option<T>`.
     ///
     /// # Examples
     ///
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index 85728551f53..02f32675247 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -48,13 +48,8 @@ pub fn panic(expr: &'static str) -> ! {
     // Arguments::new_v1 may allow the compiler to omit Formatter::pad from the
     // output binary, saving up to a few kilobytes.
     panic_fmt(
-        #[cfg(bootstrap)]
-        fmt::Arguments::new_v1(&[expr], &[]),
-        #[cfg(not(bootstrap))]
         // SAFETY: Arguments::new_v1 is safe with exactly one str and zero args
-        unsafe {
-            fmt::Arguments::new_v1(&[expr], &[])
-        },
+        unsafe { fmt::Arguments::new_v1(&[expr], &[]) },
     );
 }
 
@@ -82,7 +77,7 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
 #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
 #[cfg_attr(feature = "panic_immediate_abort", inline)]
 #[track_caller]
-#[cfg_attr(not(bootstrap), lang = "panic_fmt")] // needed for const-evaluated panics
+#[lang = "panic_fmt"] // needed for const-evaluated panics
 pub fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
     if cfg!(feature = "panic_immediate_abort") {
         super::intrinsics::abort()
@@ -102,7 +97,6 @@ pub fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
 }
 
 /// This function is used instead of panic_fmt in const eval.
-#[cfg(not(bootstrap))]
 #[lang = "const_panic_fmt"]
 pub const fn const_panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
     if let Some(msg) = fmt.as_str() {
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
new file mode 100644
index 00000000000..0de9126dab2
--- /dev/null
+++ b/library/core/src/primitive_docs.rs
@@ -0,0 +1,1307 @@
+// `library/{std,core}/src/primitive_docs.rs` should have the same contents.
+// These are different files so that relative links work properly without
+// having to have `CARGO_PKG_NAME` set, but conceptually they should always be the same.
+#[doc(primitive = "bool")]
+#[doc(alias = "true")]
+#[doc(alias = "false")]
+/// The boolean type.
+///
+/// The `bool` represents a value, which could only be either [`true`] or [`false`]. If you cast
+/// a `bool` into an integer, [`true`] will be 1 and [`false`] will be 0.
+///
+/// # Basic usage
+///
+/// `bool` implements various traits, such as [`BitAnd`], [`BitOr`], [`Not`], etc.,
+/// which allow us to perform boolean operations using `&`, `|` and `!`.
+///
+/// [`if`] requires a `bool` value as its conditional. [`assert!`], which is an
+/// important macro in testing, checks whether an expression is [`true`] and panics
+/// if it isn't.
+///
+/// ```
+/// let bool_val = true & false | false;
+/// assert!(!bool_val);
+/// ```
+///
+/// [`true`]: ../std/keyword.true.html
+/// [`false`]: ../std/keyword.false.html
+/// [`BitAnd`]: ops::BitAnd
+/// [`BitOr`]: ops::BitOr
+/// [`Not`]: ops::Not
+/// [`if`]: ../std/keyword.if.html
+///
+/// # Examples
+///
+/// A trivial example of the usage of `bool`:
+///
+/// ```
+/// let praise_the_borrow_checker = true;
+///
+/// // using the `if` conditional
+/// if praise_the_borrow_checker {
+///     println!("oh, yeah!");
+/// } else {
+///     println!("what?!!");
+/// }
+///
+/// // ... or, a match pattern
+/// match praise_the_borrow_checker {
+///     true => println!("keep praising!"),
+///     false => println!("you should praise!"),
+/// }
+/// ```
+///
+/// Also, since `bool` implements the [`Copy`] trait, we don't
+/// have to worry about the move semantics (just like the integer and float primitives).
+///
+/// Now an example of `bool` cast to integer type:
+///
+/// ```
+/// assert_eq!(true as i32, 1);
+/// assert_eq!(false as i32, 0);
+/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_bool {}
+
+#[doc(primitive = "never")]
+#[doc(alias = "!")]
+//
+/// The `!` type, also called "never".
+///
+/// `!` represents the type of computations which never resolve to any value at all. For example,
+/// the [`exit`] function `fn exit(code: i32) -> !` exits the process without ever returning, and
+/// so returns `!`.
+///
+/// `break`, `continue` and `return` expressions also have type `!`. For example we are allowed to
+/// write:
+///
+/// ```
+/// #![feature(never_type)]
+/// # fn foo() -> u32 {
+/// let x: ! = {
+///     return 123
+/// };
+/// # }
+/// ```
+///
+/// Although the `let` is pointless here, it illustrates the meaning of `!`. Since `x` is never
+/// assigned a value (because `return` returns from the entire function), `x` can be given type
+/// `!`. We could also replace `return 123` with a `panic!` or a never-ending `loop` and this code
+/// would still be valid.
+///
+/// A more realistic usage of `!` is in this code:
+///
+/// ```
+/// # fn get_a_number() -> Option<u32> { None }
+/// # loop {
+/// let num: u32 = match get_a_number() {
+///     Some(num) => num,
+///     None => break,
+/// };
+/// # }
+/// ```
+///
+/// Both match arms must produce values of type [`u32`], but since `break` never produces a value
+/// at all we know it can never produce a value which isn't a [`u32`]. This illustrates another
+/// behaviour of the `!` type - expressions with type `!` will coerce into any other type.
+///
+/// [`u32`]: prim@u32
+#[doc = concat!("[`exit`]: ", include_str!("../primitive_docs/process_exit.md"))]
+///
+/// # `!` and generics
+///
+/// ## Infallible errors
+///
+/// The main place you'll see `!` used explicitly is in generic code. Consider the [`FromStr`]
+/// trait:
+///
+/// ```
+/// trait FromStr: Sized {
+///     type Err;
+///     fn from_str(s: &str) -> Result<Self, Self::Err>;
+/// }
+/// ```
+///
+/// When implementing this trait for [`String`] we need to pick a type for [`Err`]. And since
+/// converting a string into a string will never result in an error, the appropriate type is `!`.
+/// (Currently the type actually used is an enum with no variants, though this is only because `!`
+/// was added to Rust at a later date and it may change in the future.) With an [`Err`] type of
+/// `!`, if we have to call [`String::from_str`] for some reason the result will be a
+/// [`Result<String, !>`] which we can unpack like this:
+///
+/// ```
+/// #![feature(exhaustive_patterns)]
+/// use std::str::FromStr;
+/// let Ok(s) = String::from_str("hello");
+/// ```
+///
+/// Since the [`Err`] variant contains a `!`, it can never occur. If the `exhaustive_patterns`
+/// feature is present this means we can exhaustively match on [`Result<T, !>`] by just taking the
+/// [`Ok`] variant. This illustrates another behaviour of `!` - it can be used to "delete" certain
+/// enum variants from generic types like `Result`.
+///
+/// ## Infinite loops
+///
+/// While [`Result<T, !>`] is very useful for removing errors, `!` can also be used to remove
+/// successes as well. If we think of [`Result<T, !>`] as "if this function returns, it has not
+/// errored," we get a very intuitive idea of [`Result<!, E>`] as well: if the function returns, it
+/// *has* errored.
+///
+/// For example, consider the case of a simple web server, which can be simplified to:
+///
+/// ```ignore (hypothetical-example)
+/// loop {
+///     let (client, request) = get_request().expect("disconnected");
+///     let response = request.process();
+///     response.send(client);
+/// }
+/// ```
+///
+/// Currently, this isn't ideal, because we simply panic whenever we fail to get a new connection.
+/// Instead, we'd like to keep track of this error, like this:
+///
+/// ```ignore (hypothetical-example)
+/// loop {
+///     match get_request() {
+///         Err(err) => break err,
+///         Ok((client, request)) => {
+///             let response = request.process();
+///             response.send(client);
+///         },
+///     }
+/// }
+/// ```
+///
+/// Now, when the server disconnects, we exit the loop with an error instead of panicking. While it
+/// might be intuitive to simply return the error, we might want to wrap it in a [`Result<!, E>`]
+/// instead:
+///
+/// ```ignore (hypothetical-example)
+/// fn server_loop() -> Result<!, ConnectionError> {
+///     loop {
+///         let (client, request) = get_request()?;
+///         let response = request.process();
+///         response.send(client);
+///     }
+/// }
+/// ```
+///
+/// Now, we can use `?` instead of `match`, and the return type makes a lot more sense: if the loop
+/// ever stops, it means that an error occurred. We don't even have to wrap the loop in an `Ok`
+/// because `!` coerces to `Result<!, ConnectionError>` automatically.
+///
+/// [`String::from_str`]: str::FromStr::from_str
+#[doc = concat!("[`String`]: ", include_str!("../primitive_docs/string_string.md"))]
+/// [`FromStr`]: str::FromStr
+///
+/// # `!` and traits
+///
+/// When writing your own traits, `!` should have an `impl` whenever there is an obvious `impl`
+/// which doesn't `panic!`. The reason is that functions returning an `impl Trait` where `!`
+/// does not have an `impl` of `Trait` cannot diverge as their only possible code path. In other
+/// words, they can't return `!` from every code path. As an example, this code doesn't compile:
+///
+/// ```compile_fail
+/// use std::ops::Add;
+///
+/// fn foo() -> impl Add<u32> {
+///     unimplemented!()
+/// }
+/// ```
+///
+/// But this code does:
+///
+/// ```
+/// use std::ops::Add;
+///
+/// fn foo() -> impl Add<u32> {
+///     if true {
+///         unimplemented!()
+///     } else {
+///         0
+///     }
+/// }
+/// ```
+///
+/// The reason is that, in the first example, there are many possible types that `!` could coerce
+/// to, because many types implement `Add<u32>`. However, in the second example,
+/// the `else` branch returns a `0`, which the compiler infers from the return type to be of type
+/// `u32`. Since `u32` is a concrete type, `!` can and will be coerced to it. See issue [#36375]
+/// for more information on this quirk of `!`.
+///
+/// [#36375]: https://github.com/rust-lang/rust/issues/36375
+///
+/// As it turns out, though, most traits can have an `impl` for `!`. Take [`Debug`]
+/// for example:
+///
+/// ```
+/// #![feature(never_type)]
+/// # use std::fmt;
+/// # trait Debug {
+/// #     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result;
+/// # }
+/// impl Debug for ! {
+///     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+///         *self
+///     }
+/// }
+/// ```
+///
+/// Once again we're using `!`'s ability to coerce into any other type, in this case
+/// [`fmt::Result`]. Since this method takes a `&!` as an argument we know that it can never be
+/// called (because there is no value of type `!` for it to be called with). Writing `*self`
+/// essentially tells the compiler "We know that this code can never be run, so just treat the
+/// entire function body as having type [`fmt::Result`]". This pattern can be used a lot when
+/// implementing traits for `!`. Generally, any trait which only has methods which take a `self`
+/// parameter should have such an impl.
+///
+/// On the other hand, one trait which would not be appropriate to implement is [`Default`]:
+///
+/// ```
+/// trait Default {
+///     fn default() -> Self;
+/// }
+/// ```
+///
+/// Since `!` has no values, it has no default value either. It's true that we could write an
+/// `impl` for this which simply panics, but the same is true for any type (we could `impl
+/// Default` for (eg.) [`File`] by just making [`default()`] panic.)
+///
+#[doc = concat!("[`File`]: ", include_str!("../primitive_docs/fs_file.md"))]
+/// [`Debug`]: fmt::Debug
+/// [`default()`]: Default::default
+///
+#[unstable(feature = "never_type", issue = "35121")]
+mod prim_never {}
+
+#[doc(primitive = "char")]
+/// A character type.
+///
+/// The `char` type represents a single character. More specifically, since
+/// 'character' isn't a well-defined concept in Unicode, `char` is a '[Unicode
+/// scalar value]', which is similar to, but not the same as, a '[Unicode code
+/// point]'.
+///
+/// [Unicode scalar value]: https://www.unicode.org/glossary/#unicode_scalar_value
+/// [Unicode code point]: https://www.unicode.org/glossary/#code_point
+///
+/// This documentation describes a number of methods and trait implementations on the
+/// `char` type. For technical reasons, there is additional, separate
+/// documentation in [the `std::char` module](char/index.html) as well.
+///
+/// # Representation
+///
+/// `char` is always four bytes in size. This is a different representation than
+/// a given character would have as part of a [`String`]. For example:
+///
+/// ```
+/// let v = vec!['h', 'e', 'l', 'l', 'o'];
+///
+/// // five elements times four bytes for each element
+/// assert_eq!(20, v.len() * std::mem::size_of::<char>());
+///
+/// let s = String::from("hello");
+///
+/// // five elements times one byte per element
+/// assert_eq!(5, s.len() * std::mem::size_of::<u8>());
+/// ```
+///
+#[doc = concat!("[`String`]: ", include_str!("../primitive_docs/string_string.md"))]
+///
+/// As always, remember that a human intuition for 'character' might not map to
+/// Unicode's definitions. For example, despite looking similar, the 'é'
+/// character is one Unicode code point while 'é' is two Unicode code points:
+///
+/// ```
+/// let mut chars = "é".chars();
+/// // U+00e9: 'latin small letter e with acute'
+/// assert_eq!(Some('\u{00e9}'), chars.next());
+/// assert_eq!(None, chars.next());
+///
+/// let mut chars = "é".chars();
+/// // U+0065: 'latin small letter e'
+/// assert_eq!(Some('\u{0065}'), chars.next());
+/// // U+0301: 'combining acute accent'
+/// assert_eq!(Some('\u{0301}'), chars.next());
+/// assert_eq!(None, chars.next());
+/// ```
+///
+/// This means that the contents of the first string above _will_ fit into a
+/// `char` while the contents of the second string _will not_. Trying to create
+/// a `char` literal with the contents of the second string gives an error:
+///
+/// ```text
+/// error: character literal may only contain one codepoint: 'é'
+/// let c = 'é';
+///         ^^^
+/// ```
+///
+/// Another implication of the 4-byte fixed size of a `char` is that
+/// per-`char` processing can end up using a lot more memory:
+///
+/// ```
+/// let s = String::from("love: ❤️");
+/// let v: Vec<char> = s.chars().collect();
+///
+/// assert_eq!(12, std::mem::size_of_val(&s[..]));
+/// assert_eq!(32, std::mem::size_of_val(&v[..]));
+/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_char {}
+
+#[doc(primitive = "unit")]
+#[doc(alias = "(")]
+#[doc(alias = ")")]
+#[doc(alias = "()")]
+//
+/// The `()` type, also called "unit".
+///
+/// The `()` type has exactly one value `()`, and is used when there
+/// is no other meaningful value that could be returned. `()` is most
+/// commonly seen implicitly: functions without a `-> ...` implicitly
+/// have return type `()`, that is, these are equivalent:
+///
+/// ```rust
+/// fn long() -> () {}
+///
+/// fn short() {}
+/// ```
+///
+/// The semicolon `;` can be used to discard the result of an
+/// expression at the end of a block, making the expression (and thus
+/// the block) evaluate to `()`. For example,
+///
+/// ```rust
+/// fn returns_i64() -> i64 {
+///     1i64
+/// }
+/// fn returns_unit() {
+///     1i64;
+/// }
+///
+/// let is_i64 = {
+///     returns_i64()
+/// };
+/// let is_unit = {
+///     returns_i64();
+/// };
+/// ```
+///
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_unit {}
+
+#[doc(primitive = "pointer")]
+#[doc(alias = "ptr")]
+#[doc(alias = "*")]
+#[doc(alias = "*const")]
+#[doc(alias = "*mut")]
+//
+/// Raw, unsafe pointers, `*const T`, and `*mut T`.
+///
+/// *[See also the `std::ptr` module](ptr).*
+///
+/// Working with raw pointers in Rust is uncommon, typically limited to a few patterns.
+/// Raw pointers can be unaligned or [`null`]. However, when a raw pointer is
+/// dereferenced (using the `*` operator), it must be non-null and aligned.
+///
+/// Storing through a raw pointer using `*ptr = data` calls `drop` on the old value, so
+/// [`write`] must be used if the type has drop glue and memory is not already
+/// initialized - otherwise `drop` would be called on the uninitialized memory.
+///
+/// Use the [`null`] and [`null_mut`] functions to create null pointers, and the
+/// [`is_null`] method of the `*const T` and `*mut T` types to check for null.
+/// The `*const T` and `*mut T` types also define the [`offset`] method, for
+/// pointer math.
+///
+/// # Common ways to create raw pointers
+///
+/// ## 1. Coerce a reference (`&T`) or mutable reference (`&mut T`).
+///
+/// ```
+/// let my_num: i32 = 10;
+/// let my_num_ptr: *const i32 = &my_num;
+/// let mut my_speed: i32 = 88;
+/// let my_speed_ptr: *mut i32 = &mut my_speed;
+/// ```
+///
+/// To get a pointer to a boxed value, dereference the box:
+///
+/// ```
+/// let my_num: Box<i32> = Box::new(10);
+/// let my_num_ptr: *const i32 = &*my_num;
+/// let mut my_speed: Box<i32> = Box::new(88);
+/// let my_speed_ptr: *mut i32 = &mut *my_speed;
+/// ```
+///
+/// This does not take ownership of the original allocation
+/// and requires no resource management later,
+/// but you must not use the pointer after its lifetime.
+///
+/// ## 2. Consume a box (`Box<T>`).
+///
+/// The [`into_raw`] function consumes a box and returns
+/// the raw pointer. It doesn't destroy `T` or deallocate any memory.
+///
+/// ```
+/// let my_speed: Box<i32> = Box::new(88);
+/// let my_speed: *mut i32 = Box::into_raw(my_speed);
+///
+/// // By taking ownership of the original `Box<T>` though
+/// // we are obligated to put it together later to be destroyed.
+/// unsafe {
+///     drop(Box::from_raw(my_speed));
+/// }
+/// ```
+///
+/// Note that here the call to [`drop`] is for clarity - it indicates
+/// that we are done with the given value and it should be destroyed.
+///
+/// ## 3. Create it using `ptr::addr_of!`
+///
+/// Instead of coercing a reference to a raw pointer, you can use the macros
+/// [`ptr::addr_of!`] (for `*const T`) and [`ptr::addr_of_mut!`] (for `*mut T`).
+/// These macros allow you to create raw pointers to fields to which you cannot
+/// create a reference (without causing undefined behaviour), such as an
+/// unaligned field. This might be necessary if packed structs or uninitialized
+/// memory is involved.
+///
+/// ```
+/// #[derive(Debug, Default, Copy, Clone)]
+/// #[repr(C, packed)]
+/// struct S {
+///     aligned: u8,
+///     unaligned: u32,
+/// }
+/// let s = S::default();
+/// let p = std::ptr::addr_of!(s.unaligned); // not allowed with coercion
+/// ```
+///
+/// ## 4. Get it from C.
+///
+/// ```
+/// # #![feature(rustc_private)]
+/// extern crate libc;
+///
+/// use std::mem;
+///
+/// unsafe {
+///     let my_num: *mut i32 = libc::malloc(mem::size_of::<i32>()) as *mut i32;
+///     if my_num.is_null() {
+///         panic!("failed to allocate memory");
+///     }
+///     libc::free(my_num as *mut libc::c_void);
+/// }
+/// ```
+///
+/// Usually you wouldn't literally use `malloc` and `free` from Rust,
+/// but C APIs hand out a lot of pointers generally, so are a common source
+/// of raw pointers in Rust.
+///
+/// [`null`]: ptr::null
+/// [`null_mut`]: ptr::null_mut
+/// [`is_null`]: pointer::is_null
+/// [`offset`]: pointer::offset
+#[doc = concat!("[`into_raw`]: ", include_str!("../primitive_docs/box_into_raw.md"))]
+/// [`drop`]: mem::drop
+/// [`write`]: ptr::write
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_pointer {}
+
+#[doc(primitive = "array")]
+#[doc(alias = "[]")]
+#[doc(alias = "[T;N]")] // unfortunately, rustdoc doesn't have fuzzy search for aliases
+#[doc(alias = "[T; N]")]
+/// A fixed-size array, denoted `[T; N]`, for the element type, `T`, and the
+/// non-negative compile-time constant size, `N`.
+///
+/// There are two syntactic forms for creating an array:
+///
+/// * A list with each element, i.e., `[x, y, z]`.
+/// * A repeat expression `[x; N]`, which produces an array with `N` copies of `x`.
+///   The type of `x` must be [`Copy`].
+///
+/// Note that `[expr; 0]` is allowed, and produces an empty array.
+/// This will still evaluate `expr`, however, and immediately drop the resulting value, so
+/// be mindful of side effects.
+///
+/// Arrays of *any* size implement the following traits if the element type allows it:
+///
+/// - [`Copy`]
+/// - [`Clone`]
+/// - [`Debug`]
+/// - [`IntoIterator`] (implemented for `[T; N]`, `&[T; N]` and `&mut [T; N]`)
+/// - [`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`]
+/// - [`Hash`]
+/// - [`AsRef`], [`AsMut`]
+/// - [`Borrow`], [`BorrowMut`]
+///
+/// Arrays of sizes from 0 to 32 (inclusive) implement the [`Default`] trait
+/// if the element type allows it. As a stopgap, trait implementations are
+/// statically generated up to size 32.
+///
+/// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on
+/// an array. Indeed, this provides most of the API for working with arrays.
+/// Slices have a dynamic size and do not coerce to arrays.
+///
+/// You can move elements out of an array with a [slice pattern]. If you want
+/// one element, see [`mem::replace`].
+///
+/// # Examples
+///
+/// ```
+/// let mut array: [i32; 3] = [0; 3];
+///
+/// array[1] = 1;
+/// array[2] = 2;
+///
+/// assert_eq!([1, 2], &array[1..]);
+///
+/// // This loop prints: 0 1 2
+/// for x in array {
+///     print!("{} ", x);
+/// }
+/// ```
+///
+/// You can also iterate over reference to the array's elements:
+///
+/// ```
+/// let array: [i32; 3] = [0; 3];
+///
+/// for x in &array { }
+/// ```
+///
+/// You can use a [slice pattern] to move elements out of an array:
+///
+/// ```
+/// fn move_away(_: String) { /* Do interesting things. */ }
+///
+/// let [john, roa] = ["John".to_string(), "Roa".to_string()];
+/// move_away(john);
+/// move_away(roa);
+/// ```
+///
+/// # Editions
+///
+/// Prior to Rust 1.53, arrays did not implement [`IntoIterator`] by value, so the method call
+/// `array.into_iter()` auto-referenced into a [slice iterator](slice::iter). Right now, the old
+/// behavior is preserved in the 2015 and 2018 editions of Rust for compatibility, ignoring
+/// [`IntoIterator`] by value. In the future, the behavior on the 2015 and 2018 edition
+/// might be made consistent to the behavior of later editions.
+///
+/// ```rust,edition2018
+/// // Rust 2015 and 2018:
+///
+/// # #![allow(array_into_iter)] // override our `deny(warnings)`
+/// let array: [i32; 3] = [0; 3];
+///
+/// // This creates a slice iterator, producing references to each value.
+/// for item in array.into_iter().enumerate() {
+///     let (i, x): (usize, &i32) = item;
+///     println!("array[{}] = {}", i, x);
+/// }
+///
+/// // The `array_into_iter` lint suggests this change for future compatibility:
+/// for item in array.iter().enumerate() {
+///     let (i, x): (usize, &i32) = item;
+///     println!("array[{}] = {}", i, x);
+/// }
+///
+/// // You can explicitly iterate an array by value using
+/// // `IntoIterator::into_iter` or `std::array::IntoIter::new`:
+/// for item in IntoIterator::into_iter(array).enumerate() {
+///     let (i, x): (usize, i32) = item;
+///     println!("array[{}] = {}", i, x);
+/// }
+/// ```
+///
+/// Starting in the 2021 edition, `array.into_iter()` uses `IntoIterator` normally to iterate
+/// by value, and `iter()` should be used to iterate by reference like previous editions.
+///
+/// ```rust,edition2021
+/// // Rust 2021:
+///
+/// let array: [i32; 3] = [0; 3];
+///
+/// // This iterates by reference:
+/// for item in array.iter().enumerate() {
+///     let (i, x): (usize, &i32) = item;
+///     println!("array[{}] = {}", i, x);
+/// }
+///
+/// // This iterates by value:
+/// for item in array.into_iter().enumerate() {
+///     let (i, x): (usize, i32) = item;
+///     println!("array[{}] = {}", i, x);
+/// }
+/// ```
+///
+/// Future language versions might start treating the `array.into_iter()`
+/// syntax on editions 2015 and 2018 the same as on edition 2021. So code using
+/// those older editions should still be written with this change in mind, to
+/// prevent breakage in the future. The safest way to accomplish this is to
+/// avoid the `into_iter` syntax on those editions. If an edition update is not
+/// viable/desired, there are multiple alternatives:
+/// * use `iter`, equivalent to the old behavior, creating references
+/// * use [`IntoIterator::into_iter`], equivalent to the post-2021 behavior (Rust 1.53+)
+/// * replace `for ... in array.into_iter() {` with `for ... in array {`,
+///   equivalent to the post-2021 behavior (Rust 1.53+)
+///
+/// ```rust,edition2018
+/// // Rust 2015 and 2018:
+///
+/// let array: [i32; 3] = [0; 3];
+///
+/// // This iterates by reference:
+/// for item in array.iter() {
+///     let x: &i32 = item;
+///     println!("{}", x);
+/// }
+///
+/// // This iterates by value:
+/// for item in IntoIterator::into_iter(array) {
+///     let x: i32 = item;
+///     println!("{}", x);
+/// }
+///
+/// // This iterates by value:
+/// for item in array {
+///     let x: i32 = item;
+///     println!("{}", x);
+/// }
+///
+/// // IntoIter can also start a chain.
+/// // This iterates by value:
+/// for item in IntoIterator::into_iter(array).enumerate() {
+///     let (i, x): (usize, i32) = item;
+///     println!("array[{}] = {}", i, x);
+/// }
+/// ```
+///
+/// [slice]: prim@slice
+/// [`Debug`]: fmt::Debug
+/// [`Hash`]: hash::Hash
+/// [`Borrow`]: borrow::Borrow
+/// [`BorrowMut`]: borrow::BorrowMut
+/// [slice pattern]: ../reference/patterns.html#slice-patterns
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_array {}
+
+#[doc(primitive = "slice")]
+#[doc(alias = "[")]
+#[doc(alias = "]")]
+#[doc(alias = "[]")]
+/// A dynamically-sized view into a contiguous sequence, `[T]`. Contiguous here
+/// means that elements are laid out so that every element is the same
+/// distance from its neighbors.
+///
+/// *[See also the `std::slice` module](crate::slice).*
+///
+/// Slices are a view into a block of memory represented as a pointer and a
+/// length.
+///
+/// ```
+/// // slicing a Vec
+/// let vec = vec![1, 2, 3];
+/// let int_slice = &vec[..];
+/// // coercing an array to a slice
+/// let str_slice: &[&str] = &["one", "two", "three"];
+/// ```
+///
+/// Slices are either mutable or shared. The shared slice type is `&[T]`,
+/// while the mutable slice type is `&mut [T]`, where `T` represents the element
+/// type. For example, you can mutate the block of memory that a mutable slice
+/// points to:
+///
+/// ```
+/// let mut x = [1, 2, 3];
+/// let x = &mut x[..]; // Take a full slice of `x`.
+/// x[1] = 7;
+/// assert_eq!(x, &[1, 7, 3]);
+/// ```
+///
+/// As slices store the length of the sequence they refer to, they have twice
+/// the size of pointers to [`Sized`](marker/trait.Sized.html) types.
+/// Also see the reference on
+/// [dynamically sized types](../reference/dynamically-sized-types.html).
+///
+/// ```
+/// # use std::rc::Rc;
+/// let pointer_size = std::mem::size_of::<&u8>();
+/// assert_eq!(2 * pointer_size, std::mem::size_of::<&[u8]>());
+/// assert_eq!(2 * pointer_size, std::mem::size_of::<*const [u8]>());
+/// assert_eq!(2 * pointer_size, std::mem::size_of::<Box<[u8]>>());
+/// assert_eq!(2 * pointer_size, std::mem::size_of::<Rc<[u8]>>());
+/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_slice {}
+
+#[doc(primitive = "str")]
+//
+/// String slices.
+///
+/// *[See also the `std::str` module](crate::str).*
+///
+/// The `str` type, also called a 'string slice', is the most primitive string
+/// type. It is usually seen in its borrowed form, `&str`. It is also the type
+/// of string literals, `&'static str`.
+///
+/// String slices are always valid UTF-8.
+///
+/// # Examples
+///
+/// String literals are string slices:
+///
+/// ```
+/// let hello = "Hello, world!";
+///
+/// // with an explicit type annotation
+/// let hello: &'static str = "Hello, world!";
+/// ```
+///
+/// They are `'static` because they're stored directly in the final binary, and
+/// so will be valid for the `'static` duration.
+///
+/// # Representation
+///
+/// A `&str` is made up of two components: a pointer to some bytes, and a
+/// length. You can look at these with the [`as_ptr`] and [`len`] methods:
+///
+/// ```
+/// use std::slice;
+/// use std::str;
+///
+/// let story = "Once upon a time...";
+///
+/// let ptr = story.as_ptr();
+/// let len = story.len();
+///
+/// // story has nineteen bytes
+/// assert_eq!(19, len);
+///
+/// // We can re-build a str out of ptr and len. This is all unsafe because
+/// // we are responsible for making sure the two components are valid:
+/// let s = unsafe {
+///     // First, we build a &[u8]...
+///     let slice = slice::from_raw_parts(ptr, len);
+///
+///     // ... and then convert that slice into a string slice
+///     str::from_utf8(slice)
+/// };
+///
+/// assert_eq!(s, Ok(story));
+/// ```
+///
+/// [`as_ptr`]: str::as_ptr
+/// [`len`]: str::len
+///
+/// Note: This example shows the internals of `&str`. `unsafe` should not be
+/// used to get a string slice under normal circumstances. Use `as_str`
+/// instead.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_str {}
+
+#[doc(primitive = "tuple")]
+#[doc(alias = "(")]
+#[doc(alias = ")")]
+#[doc(alias = "()")]
+//
+/// A finite heterogeneous sequence, `(T, U, ..)`.
+///
+/// Let's cover each of those in turn:
+///
+/// Tuples are *finite*. In other words, a tuple has a length. Here's a tuple
+/// of length `3`:
+///
+/// ```
+/// ("hello", 5, 'c');
+/// ```
+///
+/// 'Length' is also sometimes called 'arity' here; each tuple of a different
+/// length is a different, distinct type.
+///
+/// Tuples are *heterogeneous*. This means that each element of the tuple can
+/// have a different type. In that tuple above, it has the type:
+///
+/// ```
+/// # let _:
+/// (&'static str, i32, char)
+/// # = ("hello", 5, 'c');
+/// ```
+///
+/// Tuples are a *sequence*. This means that they can be accessed by position;
+/// this is called 'tuple indexing', and it looks like this:
+///
+/// ```rust
+/// let tuple = ("hello", 5, 'c');
+///
+/// assert_eq!(tuple.0, "hello");
+/// assert_eq!(tuple.1, 5);
+/// assert_eq!(tuple.2, 'c');
+/// ```
+///
+/// The sequential nature of the tuple applies to its implementations of various
+/// traits. For example, in [`PartialOrd`] and [`Ord`], the elements are compared
+/// sequentially until the first non-equal set is found.
+///
+/// For more about tuples, see [the book](../book/ch03-02-data-types.html#the-tuple-type).
+///
+/// # Trait implementations
+///
+/// If every type inside a tuple implements one of the following traits, then a
+/// tuple itself also implements it.
+///
+/// * [`Clone`]
+/// * [`Copy`]
+/// * [`PartialEq`]
+/// * [`Eq`]
+/// * [`PartialOrd`]
+/// * [`Ord`]
+/// * [`Debug`]
+/// * [`Default`]
+/// * [`Hash`]
+///
+/// [`Debug`]: fmt::Debug
+/// [`Hash`]: hash::Hash
+///
+/// Due to a temporary restriction in Rust's type system, these traits are only
+/// implemented on tuples of arity 12 or less. In the future, this may change.
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// let tuple = ("hello", 5, 'c');
+///
+/// assert_eq!(tuple.0, "hello");
+/// ```
+///
+/// Tuples are often used as a return type when you want to return more than
+/// one value:
+///
+/// ```
+/// fn calculate_point() -> (i32, i32) {
+///     // Don't do a calculation, that's not the point of the example
+///     (4, 5)
+/// }
+///
+/// let point = calculate_point();
+///
+/// assert_eq!(point.0, 4);
+/// assert_eq!(point.1, 5);
+///
+/// // Combining this with patterns can be nicer.
+///
+/// let (x, y) = calculate_point();
+///
+/// assert_eq!(x, 4);
+/// assert_eq!(y, 5);
+/// ```
+///
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_tuple {}
+
+#[doc(primitive = "f32")]
+/// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008).
+///
+/// This type can represent a wide range of decimal numbers, like `3.5`, `27`,
+/// `-113.75`, `0.0078125`, `34359738368`, `0`, `-1`. So unlike integer types
+/// (such as `i32`), floating point types can represent non-integer numbers,
+/// too.
+///
+/// However, being able to represent this wide range of numbers comes at the
+/// cost of precision: floats can only represent some of the real numbers and
+/// calculation with floats round to a nearby representable number. For example,
+/// `5.0` and `1.0` can be exactly represented as `f32`, but `1.0 / 5.0` results
+/// in `0.20000000298023223876953125` since `0.2` cannot be exactly represented
+/// as `f32`. Note, however, that printing floats with `println` and friends will
+/// often discard insignificant digits: `println!("{}", 1.0f32 / 5.0f32)` will
+/// print `0.2`.
+///
+/// Additionally, `f32` can represent some special values:
+///
+/// - −0.0: IEEE 754 floating point numbers have a bit that indicates their sign, so −0.0 is a
+///   possible value. For comparison −0.0 = +0.0, but floating point operations can carry
+///   the sign bit through arithmetic operations. This means −0.0 × +0.0 produces −0.0 and
+///   a negative number rounded to a value smaller than a float can represent also produces −0.0.
+/// - [∞](#associatedconstant.INFINITY) and
+///   [−∞](#associatedconstant.NEG_INFINITY): these result from calculations
+///   like `1.0 / 0.0`.
+/// - [NaN (not a number)](#associatedconstant.NAN): this value results from
+///   calculations like `(-1.0).sqrt()`. NaN has some potentially unexpected
+///   behavior: it is unequal to any float, including itself! It is also neither
+///   smaller nor greater than any float, making it impossible to sort. Lastly,
+///   it is considered infectious as almost all calculations where one of the
+///   operands is NaN will also result in NaN.
+///
+/// For more information on floating point numbers, see [Wikipedia][wikipedia].
+///
+/// *[See also the `std::f32::consts` module](crate::f32::consts).*
+///
+/// [wikipedia]: https://en.wikipedia.org/wiki/Single-precision_floating-point_format
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_f32 {}
+
+#[doc(primitive = "f64")]
+/// A 64-bit floating point type (specifically, the "binary64" type defined in IEEE 754-2008).
+///
+/// This type is very similar to [`f32`], but has increased
+/// precision by using twice as many bits. Please see [the documentation for
+/// `f32`][`f32`] or [Wikipedia on double precision
+/// values][wikipedia] for more information.
+///
+/// *[See also the `std::f64::consts` module](crate::f64::consts).*
+///
+/// [`f32`]: prim@f32
+/// [wikipedia]: https://en.wikipedia.org/wiki/Double-precision_floating-point_format
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_f64 {}
+
+#[doc(primitive = "i8")]
+//
+/// The 8-bit signed integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_i8 {}
+
+#[doc(primitive = "i16")]
+//
+/// The 16-bit signed integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_i16 {}
+
+#[doc(primitive = "i32")]
+//
+/// The 32-bit signed integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_i32 {}
+
+#[doc(primitive = "i64")]
+//
+/// The 64-bit signed integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_i64 {}
+
+#[doc(primitive = "i128")]
+//
+/// The 128-bit signed integer type.
+#[stable(feature = "i128", since = "1.26.0")]
+mod prim_i128 {}
+
+#[doc(primitive = "u8")]
+//
+/// The 8-bit unsigned integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_u8 {}
+
+#[doc(primitive = "u16")]
+//
+/// The 16-bit unsigned integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_u16 {}
+
+#[doc(primitive = "u32")]
+//
+/// The 32-bit unsigned integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_u32 {}
+
+#[doc(primitive = "u64")]
+//
+/// The 64-bit unsigned integer type.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_u64 {}
+
+#[doc(primitive = "u128")]
+//
+/// The 128-bit unsigned integer type.
+#[stable(feature = "i128", since = "1.26.0")]
+mod prim_u128 {}
+
+#[doc(primitive = "isize")]
+//
+/// The pointer-sized signed integer type.
+///
+/// The size of this primitive is how many bytes it takes to reference any
+/// location in memory. For example, on a 32 bit target, this is 4 bytes
+/// and on a 64 bit target, this is 8 bytes.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_isize {}
+
+#[doc(primitive = "usize")]
+//
+/// The pointer-sized unsigned integer type.
+///
+/// The size of this primitive is how many bytes it takes to reference any
+/// location in memory. For example, on a 32 bit target, this is 4 bytes
+/// and on a 64 bit target, this is 8 bytes.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_usize {}
+
+#[doc(primitive = "reference")]
+#[doc(alias = "&")]
+#[doc(alias = "&mut")]
+//
+/// References, both shared and mutable.
+///
+/// A reference represents a borrow of some owned value. You can get one by using the `&` or `&mut`
+/// operators on a value, or by using a [`ref`](../std/keyword.ref.html) or
+/// <code>[ref](../std/keyword.ref.html) [mut](../std/keyword.mut.html)</code> pattern.
+///
+/// For those familiar with pointers, a reference is just a pointer that is assumed to be
+/// aligned, not null, and pointing to memory containing a valid value of `T` - for example,
+/// <code>&[bool]</code> can only point to an allocation containing the integer values `1`
+/// ([`true`](../std/keyword.true.html)) or `0` ([`false`](../std/keyword.false.html)), but
+/// creating a <code>&[bool]</code> that points to an allocation containing
+/// the value `3` causes undefined behaviour.
+/// In fact, <code>[Option]\<&T></code> has the same memory representation as a
+/// nullable but aligned pointer, and can be passed across FFI boundaries as such.
+///
+/// In most cases, references can be used much like the original value. Field access, method
+/// calling, and indexing work the same (save for mutability rules, of course). In addition, the
+/// comparison operators transparently defer to the referent's implementation, allowing references
+/// to be compared the same as owned values.
+///
+/// References have a lifetime attached to them, which represents the scope for which the borrow is
+/// valid. A lifetime is said to "outlive" another one if its representative scope is as long or
+/// longer than the other. The `'static` lifetime is the longest lifetime, which represents the
+/// total life of the program. For example, string literals have a `'static` lifetime because the
+/// text data is embedded into the binary of the program, rather than in an allocation that needs
+/// to be dynamically managed.
+///
+/// `&mut T` references can be freely coerced into `&T` references with the same referent type, and
+/// references with longer lifetimes can be freely coerced into references with shorter ones.
+///
+/// Reference equality by address, instead of comparing the values pointed to, is accomplished via
+/// implicit reference-pointer coercion and raw pointer equality via [`ptr::eq`], while
+/// [`PartialEq`] compares values.
+///
+/// ```
+/// use std::ptr;
+///
+/// let five = 5;
+/// let other_five = 5;
+/// let five_ref = &five;
+/// let same_five_ref = &five;
+/// let other_five_ref = &other_five;
+///
+/// assert!(five_ref == same_five_ref);
+/// assert!(five_ref == other_five_ref);
+///
+/// assert!(ptr::eq(five_ref, same_five_ref));
+/// assert!(!ptr::eq(five_ref, other_five_ref));
+/// ```
+///
+/// For more information on how to use references, see [the book's section on "References and
+/// Borrowing"][book-refs].
+///
+/// [book-refs]: ../book/ch04-02-references-and-borrowing.html
+///
+/// # Trait implementations
+///
+/// The following traits are implemented for all `&T`, regardless of the type of its referent:
+///
+/// * [`Copy`]
+/// * [`Clone`] \(Note that this will not defer to `T`'s `Clone` implementation if it exists!)
+/// * [`Deref`]
+/// * [`Borrow`]
+/// * [`Pointer`]
+///
+/// [`Deref`]: ops::Deref
+/// [`Borrow`]: borrow::Borrow
+/// [`Pointer`]: fmt::Pointer
+///
+/// `&mut T` references get all of the above except `Copy` and `Clone` (to prevent creating
+/// multiple simultaneous mutable borrows), plus the following, regardless of the type of its
+/// referent:
+///
+/// * [`DerefMut`]
+/// * [`BorrowMut`]
+///
+/// [`DerefMut`]: ops::DerefMut
+/// [`BorrowMut`]: borrow::BorrowMut
+/// [bool]: prim@bool
+///
+/// The following traits are implemented on `&T` references if the underlying `T` also implements
+/// that trait:
+///
+/// * All the traits in [`std::fmt`] except [`Pointer`] and [`fmt::Write`]
+/// * [`PartialOrd`]
+/// * [`Ord`]
+/// * [`PartialEq`]
+/// * [`Eq`]
+/// * [`AsRef`]
+/// * [`Fn`] \(in addition, `&T` references get [`FnMut`] and [`FnOnce`] if `T: Fn`)
+/// * [`Hash`]
+/// * [`ToSocketAddrs`]
+///
+/// [`std::fmt`]: fmt
+/// ['Pointer`]: fmt::Pointer
+/// [`Hash`]: hash::Hash
+#[doc = concat!("[`ToSocketAddrs`]: ", include_str!("../primitive_docs/net_tosocketaddrs.md"))]
+///
+/// `&mut T` references get all of the above except `ToSocketAddrs`, plus the following, if `T`
+/// implements that trait:
+///
+/// * [`AsMut`]
+/// * [`FnMut`] \(in addition, `&mut T` references get [`FnOnce`] if `T: FnMut`)
+/// * [`fmt::Write`]
+/// * [`Iterator`]
+/// * [`DoubleEndedIterator`]
+/// * [`ExactSizeIterator`]
+/// * [`FusedIterator`]
+/// * [`TrustedLen`]
+/// * [`Send`] \(note that `&T` references only get `Send` if <code>T: [Sync]</code>)
+/// * [`io::Write`]
+/// * [`Read`]
+/// * [`Seek`]
+/// * [`BufRead`]
+///
+/// [`FusedIterator`]: iter::FusedIterator
+/// [`TrustedLen`]: iter::TrustedLen
+#[doc = concat!("[`Seek`]: ", include_str!("../primitive_docs/io_seek.md"))]
+#[doc = concat!("[`BufRead`]: ", include_str!("../primitive_docs/io_bufread.md"))]
+#[doc = concat!("[`Read`]: ", include_str!("../primitive_docs/io_read.md"))]
+#[doc = concat!("[`io::Write`]: ", include_str!("../primitive_docs/io_write.md"))]
+///
+/// Note that due to method call deref coercion, simply calling a trait method will act like they
+/// work on references as well as they do on owned values! The implementations described here are
+/// meant for generic contexts, where the final type `T` is a type parameter or otherwise not
+/// locally known.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_ref {}
+
+#[doc(primitive = "fn")]
+//
+/// Function pointers, like `fn(usize) -> bool`.
+///
+/// *See also the traits [`Fn`], [`FnMut`], and [`FnOnce`].*
+///
+/// [`Fn`]: ops::Fn
+/// [`FnMut`]: ops::FnMut
+/// [`FnOnce`]: ops::FnOnce
+///
+/// Function pointers are pointers that point to *code*, not data. They can be called
+/// just like functions. Like references, function pointers are, among other things, assumed to
+/// not be null, so if you want to pass a function pointer over FFI and be able to accommodate null
+/// pointers, make your type [`Option<fn()>`](core::option#options-and-pointers-nullable-pointers)
+/// with your required signature.
+///
+/// ### Safety
+///
+/// Plain function pointers are obtained by casting either plain functions, or closures that don't
+/// capture an environment:
+///
+/// ```
+/// fn add_one(x: usize) -> usize {
+///     x + 1
+/// }
+///
+/// let ptr: fn(usize) -> usize = add_one;
+/// assert_eq!(ptr(5), 6);
+///
+/// let clos: fn(usize) -> usize = |x| x + 5;
+/// assert_eq!(clos(5), 10);
+/// ```
+///
+/// In addition to varying based on their signature, function pointers come in two flavors: safe
+/// and unsafe. Plain `fn()` function pointers can only point to safe functions,
+/// while `unsafe fn()` function pointers can point to safe or unsafe functions.
+///
+/// ```
+/// fn add_one(x: usize) -> usize {
+///     x + 1
+/// }
+///
+/// unsafe fn add_one_unsafely(x: usize) -> usize {
+///     x + 1
+/// }
+///
+/// let safe_ptr: fn(usize) -> usize = add_one;
+///
+/// //ERROR: mismatched types: expected normal fn, found unsafe fn
+/// //let bad_ptr: fn(usize) -> usize = add_one_unsafely;
+///
+/// let unsafe_ptr: unsafe fn(usize) -> usize = add_one_unsafely;
+/// let really_safe_ptr: unsafe fn(usize) -> usize = add_one;
+/// ```
+///
+/// ### ABI
+///
+/// On top of that, function pointers can vary based on what ABI they use. This
+/// is achieved by adding the `extern` keyword before the type, followed by the
+/// ABI in question. The default ABI is "Rust", i.e., `fn()` is the exact same
+/// type as `extern "Rust" fn()`. A pointer to a function with C ABI would have
+/// type `extern "C" fn()`.
+///
+/// `extern "ABI" { ... }` blocks declare functions with ABI "ABI". The default
+/// here is "C", i.e., functions declared in an `extern {...}` block have "C"
+/// ABI.
+///
+/// For more information and a list of supported ABIs, see [the nomicon's
+/// section on foreign calling conventions][nomicon-abi].
+///
+/// [nomicon-abi]: ../nomicon/ffi.html#foreign-calling-conventions
+///
+/// ### Variadic functions
+///
+/// Extern function declarations with the "C" or "cdecl" ABIs can also be *variadic*, allowing them
+/// to be called with a variable number of arguments. Normal Rust functions, even those with an
+/// `extern "ABI"`, cannot be variadic. For more information, see [the nomicon's section on
+/// variadic functions][nomicon-variadic].
+///
+/// [nomicon-variadic]: ../nomicon/ffi.html#variadic-functions
+///
+/// ### Creating function pointers
+///
+/// When `bar` is the name of a function, then the expression `bar` is *not* a
+/// function pointer. Rather, it denotes a value of an unnameable type that
+/// uniquely identifies the function `bar`. The value is zero-sized because the
+/// type already identifies the function. This has the advantage that "calling"
+/// the value (it implements the `Fn*` traits) does not require dynamic
+/// dispatch.
+///
+/// This zero-sized type *coerces* to a regular function pointer. For example:
+///
+/// ```rust
+/// use std::mem;
+///
+/// fn bar(x: i32) {}
+///
+/// let not_bar_ptr = bar; // `not_bar_ptr` is zero-sized, uniquely identifying `bar`
+/// assert_eq!(mem::size_of_val(&not_bar_ptr), 0);
+///
+/// let bar_ptr: fn(i32) = not_bar_ptr; // force coercion to function pointer
+/// assert_eq!(mem::size_of_val(&bar_ptr), mem::size_of::<usize>());
+///
+/// let footgun = &bar; // this is a shared reference to the zero-sized type identifying `bar`
+/// ```
+///
+/// The last line shows that `&bar` is not a function pointer either. Rather, it
+/// is a reference to the function-specific ZST. `&bar` is basically never what you
+/// want when `bar` is a function.
+///
+/// ### Traits
+///
+/// Function pointers implement the following traits:
+///
+/// * [`Clone`]
+/// * [`PartialEq`]
+/// * [`Eq`]
+/// * [`PartialOrd`]
+/// * [`Ord`]
+/// * [`Hash`]
+/// * [`Pointer`]
+/// * [`Debug`]
+///
+/// [`Hash`]: hash::Hash
+/// [`Pointer`]: fmt::Pointer
+///
+/// Due to a temporary restriction in Rust's type system, these traits are only implemented on
+/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this
+/// may change.
+///
+/// In addition, function pointers of *any* signature, ABI, or safety are [`Copy`], and all *safe*
+/// function pointers implement [`Fn`], [`FnMut`], and [`FnOnce`]. This works because these traits
+/// are specially known to the compiler.
+#[stable(feature = "rust1", since = "1.0.0")]
+mod prim_fn {}
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 361a9b03aeb..a04e479e857 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -98,7 +98,6 @@ impl<T> [T] {
     #[rustc_const_stable(feature = "const_slice_len", since = "1.39.0")]
     #[inline]
     // SAFETY: const sound because we transmute out the length field as a usize (which it must be)
-    #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_fn_union))]
     pub const fn len(&self) -> usize {
         // FIXME: Replace with `crate::ptr::metadata(self)` when that is const-stable.
         // As of this writing this causes a "Const-stable functions can only call other
@@ -2258,9 +2257,9 @@ impl<T> [T] {
     /// assert!(match r { Ok(1..=4) => true, _ => false, });
     /// ```
     // Lint rustdoc::broken_intra_doc_links is allowed as `slice::sort_by_key` is
-    // in crate `alloc`, and as such doesn't exists yet when building `core`.
-    // links to downstream crate: #74481. Since primitives are only documented in
-    // libstd (#73423), this never leads to broken links in practice.
+    // in crate `alloc`, and as such doesn't exists yet when building `core`: #74481.
+    // This breaks links when slice is displayed in core, but changing it to use relative links
+    // would break when the item is re-exported. So allow the core links to be broken for now.
     #[allow(rustdoc::broken_intra_doc_links)]
     #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")]
     #[inline]
diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs
index e67c0d6487c..da6ef1b6678 100644
--- a/library/core/src/str/converts.rs
+++ b/library/core/src/str/converts.rs
@@ -157,7 +157,6 @@ pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "const_str_from_utf8_unchecked", since = "1.55.0")]
-#[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_fn_transmute))]
 pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
     // SAFETY: the caller must guarantee that the bytes `v` are valid UTF-8.
     // Also relies on `&str` and `&[u8]` having the same layout.
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index ca4e2e6b7f3..607fb627605 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -231,7 +231,6 @@ impl str {
     #[rustc_const_stable(feature = "str_as_bytes", since = "1.39.0")]
     #[inline(always)]
     #[allow(unused_attributes)]
-    #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_fn_transmute))]
     pub const fn as_bytes(&self) -> &[u8] {
         // SAFETY: const sound because we transmute two types with the same layout
         unsafe { mem::transmute(self) }
diff --git a/library/core/tests/fmt/builders.rs b/library/core/tests/fmt/builders.rs
index 7580010a28b..9567479c813 100644
--- a/library/core/tests/fmt/builders.rs
+++ b/library/core/tests/fmt/builders.rs
@@ -653,6 +653,7 @@ mod debug_list {
 fn test_formatting_parameters_are_forwarded() {
     use std::collections::{BTreeMap, BTreeSet};
     #[derive(Debug)]
+    #[allow(dead_code)]
     struct Foo {
         bar: u32,
         baz: u32,
diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs
index 7001e827ad8..bb05506defd 100644
--- a/library/proc_macro/src/bridge/mod.rs
+++ b/library/proc_macro/src/bridge/mod.rs
@@ -162,6 +162,8 @@ macro_rules! with_api {
                 fn source($self: $S::Span) -> $S::Span;
                 fn start($self: $S::Span) -> LineColumn;
                 fn end($self: $S::Span) -> LineColumn;
+                fn before($self: $S::Span) -> $S::Span;
+                fn after($self: $S::Span) -> $S::Span;
                 fn join($self: $S::Span, other: $S::Span) -> Option<$S::Span>;
                 fn resolved_at($self: $S::Span, at: $S::Span) -> $S::Span;
                 fn source_text($self: $S::Span) -> Option<String>;
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index 243922b18b5..e21a1507a62 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -357,6 +357,18 @@ impl Span {
         self.0.end().add_1_to_column()
     }
 
+    /// Creates an empty span pointing to directly before this span.
+    #[unstable(feature = "proc_macro_span_shrink", issue = "87552")]
+    pub fn before(&self) -> Span {
+        Span(self.0.before())
+    }
+
+    /// Creates an empty span pointing to directly after this span.
+    #[unstable(feature = "proc_macro_span_shrink", issue = "87552")]
+    pub fn after(&self) -> Span {
+        Span(self.0.after())
+    }
+
     /// Creates a new span encompassing `self` and `other`.
     ///
     /// Returns `None` if `self` and `other` are from different files.
diff --git a/library/std/primitive_docs/box_into_raw.md b/library/std/primitive_docs/box_into_raw.md
new file mode 100644
index 00000000000..307b9c85bd6
--- /dev/null
+++ b/library/std/primitive_docs/box_into_raw.md
@@ -0,0 +1 @@
+Box::into_raw
diff --git a/library/std/primitive_docs/fs_file.md b/library/std/primitive_docs/fs_file.md
new file mode 100644
index 00000000000..13e4540835e
--- /dev/null
+++ b/library/std/primitive_docs/fs_file.md
@@ -0,0 +1 @@
+fs::File
diff --git a/library/std/primitive_docs/io_bufread.md b/library/std/primitive_docs/io_bufread.md
new file mode 100644
index 00000000000..bb688e3a5cc
--- /dev/null
+++ b/library/std/primitive_docs/io_bufread.md
@@ -0,0 +1 @@
+io::BufRead
diff --git a/library/std/primitive_docs/io_read.md b/library/std/primitive_docs/io_read.md
new file mode 100644
index 00000000000..5118d7c4888
--- /dev/null
+++ b/library/std/primitive_docs/io_read.md
@@ -0,0 +1 @@
+io::Read
diff --git a/library/std/primitive_docs/io_seek.md b/library/std/primitive_docs/io_seek.md
new file mode 100644
index 00000000000..122e6df77b6
--- /dev/null
+++ b/library/std/primitive_docs/io_seek.md
@@ -0,0 +1 @@
+io::Seek
diff --git a/library/std/primitive_docs/io_write.md b/library/std/primitive_docs/io_write.md
new file mode 100644
index 00000000000..15dfc907a65
--- /dev/null
+++ b/library/std/primitive_docs/io_write.md
@@ -0,0 +1 @@
+io::Write
diff --git a/library/std/primitive_docs/net_tosocketaddrs.md b/library/std/primitive_docs/net_tosocketaddrs.md
new file mode 100644
index 00000000000..a01f318e887
--- /dev/null
+++ b/library/std/primitive_docs/net_tosocketaddrs.md
@@ -0,0 +1 @@
+net::ToSocketAddrs
diff --git a/library/std/primitive_docs/process_exit.md b/library/std/primitive_docs/process_exit.md
new file mode 100644
index 00000000000..565a71375cd
--- /dev/null
+++ b/library/std/primitive_docs/process_exit.md
@@ -0,0 +1 @@
+process::exit
diff --git a/library/std/primitive_docs/string_string.md b/library/std/primitive_docs/string_string.md
new file mode 100644
index 00000000000..ce7815ff91b
--- /dev/null
+++ b/library/std/primitive_docs/string_string.md
@@ -0,0 +1 @@
+string::String
diff --git a/library/std/src/collections/mod.rs b/library/std/src/collections/mod.rs
index 130bb5cb2b3..71645aadb1d 100644
--- a/library/std/src/collections/mod.rs
+++ b/library/std/src/collections/mod.rs
@@ -239,7 +239,7 @@
 //! Iterators also provide a series of *adapter* methods for performing common
 //! threads to sequences. Among the adapters are functional favorites like `map`,
 //! `fold`, `skip` and `take`. Of particular interest to collections is the
-//! `rev` adapter, that reverses any iterator that supports this operation. Most
+//! `rev` adapter, which reverses any iterator that supports this operation. Most
 //! collections provide reversible iterators as the way to iterate over them in
 //! reverse order.
 //!
diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs
index de05c377852..3b917550308 100644
--- a/library/std/src/ffi/c_str.rs
+++ b/library/std/src/ffi/c_str.rs
@@ -915,6 +915,7 @@ impl From<CString> for Box<CStr> {
 
 #[stable(feature = "cow_from_cstr", since = "1.28.0")]
 impl<'a> From<CString> for Cow<'a, CStr> {
+    /// Converts a [`CString`] into an owned [`Cow`] without copying or allocating.
     #[inline]
     fn from(s: CString) -> Cow<'a, CStr> {
         Cow::Owned(s)
@@ -923,6 +924,7 @@ impl<'a> From<CString> for Cow<'a, CStr> {
 
 #[stable(feature = "cow_from_cstr", since = "1.28.0")]
 impl<'a> From<&'a CStr> for Cow<'a, CStr> {
+    /// Converts a [`CStr`] into a borrowed [`Cow`] without copying or allocating.
     #[inline]
     fn from(s: &'a CStr) -> Cow<'a, CStr> {
         Cow::Borrowed(s)
@@ -931,6 +933,7 @@ impl<'a> From<&'a CStr> for Cow<'a, CStr> {
 
 #[stable(feature = "cow_from_cstr", since = "1.28.0")]
 impl<'a> From<&'a CString> for Cow<'a, CStr> {
+    /// Converts a `&`[`CString`] into a borrowed [`Cow`] without copying or allocating.
     #[inline]
     fn from(s: &'a CString) -> Cow<'a, CStr> {
         Cow::Borrowed(s.as_c_str())
diff --git a/library/std/src/io/buffered/tests.rs b/library/std/src/io/buffered/tests.rs
index f6c2b499567..d290c3c4660 100644
--- a/library/std/src/io/buffered/tests.rs
+++ b/library/std/src/io/buffered/tests.rs
@@ -468,9 +468,6 @@ struct ProgrammableSink {
     // Writes append to this slice
     pub buffer: Vec<u8>,
 
-    // Flush sets this flag
-    pub flushed: bool,
-
     // If true, writes will always be an error
     pub always_write_error: bool,
 
@@ -520,7 +517,6 @@ impl Write for ProgrammableSink {
         if self.always_flush_error {
             Err(io::Error::new(io::ErrorKind::Other, "test - always_flush_error"))
         } else {
-            self.flushed = true;
             Ok(())
         }
     }
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index e8466fa06b8..4a35d36a9de 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -1611,7 +1611,7 @@ pub trait Write {
     /// encountered.
     ///
     /// This method is primarily used to interface with the
-    /// [`format_args!()`] macro, but it is rare that this should
+    /// [`format_args!()`] macro, and it is rare that this should
     /// explicitly be called. The [`write!()`] macro should be favored to
     /// invoke this method instead.
     ///
diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs
index 749a441d182..2e938070374 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -77,7 +77,7 @@ mod as_keyword {}
 ///     '_inner: for j in 1..=200 {
 ///         println!("    inner iteration (j): {}", j);
 ///         if j >= 3 {
-///             // breaks from inner loop, let's outer loop continue.
+///             // breaks from inner loop, lets outer loop continue.
 ///             break;
 ///         }
 ///         if i >= 2 {
@@ -119,7 +119,7 @@ mod break_keyword {}
 
 #[doc(keyword = "const")]
 //
-/// Compile-time constants and compile-time evaluable functions.
+/// Compile-time constants, compile-time evaluable functions, and raw pointers.
 ///
 /// ## Compile-time constants
 ///
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 3a1eb625b57..83c6ba0e6ea 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -247,7 +247,6 @@
 #![feature(const_cstr_unchecked)]
 #![feature(const_fn_floating_point_arithmetic)]
 #![feature(const_fn_fn_ptr_basics)]
-#![cfg_attr(bootstrap, feature(const_fn_transmute))]
 #![feature(const_format_args)]
 #![feature(const_io_structs)]
 #![feature(const_ip)]
@@ -265,7 +264,7 @@
 #![feature(doc_keyword)]
 #![feature(doc_masked)]
 #![feature(doc_notable_trait)]
-#![cfg_attr(not(bootstrap), feature(doc_primitive))]
+#![feature(doc_primitive)]
 #![feature(dropck_eyepatch)]
 #![feature(duration_checked_float)]
 #![feature(duration_constants)]
diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs
index 4165a7beaa8..9cf7ba9d574 100644
--- a/library/std/src/net/ip.rs
+++ b/library/std/src/net/ip.rs
@@ -1166,7 +1166,6 @@ impl Ipv6Addr {
     ///
     /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
     /// ```
-    #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_fn_transmute))]
     #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -1228,7 +1227,6 @@ impl Ipv6Addr {
     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(),
     ///            [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]);
     /// ```
-    #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_fn_transmute))]
     #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs
index 5b4a9fa7979..223726d45d7 100644
--- a/library/std/src/net/tcp.rs
+++ b/library/std/src/net/tcp.rs
@@ -96,6 +96,18 @@ pub struct Incoming<'a> {
     listener: &'a TcpListener,
 }
 
+/// An iterator that infinitely [`accept`]s connections on a [`TcpListener`].
+///
+/// This `struct` is created by the [`TcpListener::into_incoming`] method.
+/// See its documentation for more.
+///
+/// [`accept`]: TcpListener::accept
+#[derive(Debug)]
+#[unstable(feature = "tcplistener_into_incoming", issue = "88339")]
+pub struct IntoIncoming {
+    listener: TcpListener,
+}
+
 impl TcpStream {
     /// Opens a TCP connection to a remote host.
     ///
@@ -845,6 +857,37 @@ impl TcpListener {
         Incoming { listener: self }
     }
 
+    /// Turn this into an iterator over the connections being received on this
+    /// listener.
+    ///
+    /// The returned iterator will never return [`None`] and will also not yield
+    /// the peer's [`SocketAddr`] structure. Iterating over it is equivalent to
+    /// calling [`TcpListener::accept`] in a loop.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(tcplistener_into_incoming)]
+    /// use std::net::{TcpListener, TcpStream};
+    ///
+    /// fn listen_on(port: u16) -> impl Iterator<Item = TcpStream> {
+    ///     let listener = TcpListener::bind("127.0.0.1:80").unwrap();
+    ///     listener.into_incoming()
+    ///         .filter_map(Result::ok) /* Ignore failed connections */
+    /// }
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     for stream in listen_on(80) {
+    ///         /* handle the connection here */
+    ///     }
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "tcplistener_into_incoming", issue = "88339")]
+    pub fn into_incoming(self) -> IntoIncoming {
+        IntoIncoming { listener: self }
+    }
+
     /// Sets the value for the `IP_TTL` option on this socket.
     ///
     /// This value sets the time-to-live field that is used in every packet sent
@@ -982,6 +1025,14 @@ impl<'a> Iterator for Incoming<'a> {
     }
 }
 
+#[unstable(feature = "tcplistener_into_incoming", issue = "88339")]
+impl Iterator for IntoIncoming {
+    type Item = io::Result<TcpStream>;
+    fn next(&mut self) -> Option<io::Result<TcpStream>> {
+        Some(self.listener.accept().map(|p| p.0))
+    }
+}
+
 impl AsInner<net_imp::TcpListener> for TcpListener {
     fn as_inner(&self) -> &net_imp::TcpListener {
         &self.0
diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs
index 79e69673007..069a5376a44 100644
--- a/library/std/src/os/mod.rs
+++ b/library/std/src/os/mod.rs
@@ -10,29 +10,20 @@ pub mod raw;
 // of a macro that is not vendored by Rust and included in the toolchain.
 // See https://github.com/rust-analyzer/rust-analyzer/issues/6038.
 
+// On certain platforms right now the "main modules" modules that are
+// documented don't compile (missing things in `libc` which is empty),
+// so just omit them with an empty module and add the "unstable" attribute.
+
+// Unix, linux, wasi and windows are handled a bit differently.
 #[cfg(all(
     doc,
-    not(any(
+    any(
         all(target_arch = "wasm32", not(target_os = "wasi")),
         all(target_vendor = "fortanix", target_env = "sgx")
-    ))
+    )
 ))]
-#[path = "."]
-mod doc {
-    // When documenting std we want to show the `unix`, `windows`, `linux` and `wasi`
-    // modules as these are the "main modules" that are used across platforms,
-    // so these modules are enabled when `cfg(doc)` is set.
-    // This should help show platform-specific functionality in a hopefully cross-platform
-    // way in the documentation.
-
-    pub mod unix;
-
-    pub mod linux;
-
-    pub mod wasi;
-
-    pub mod windows;
-}
+#[unstable(issue = "none", feature = "std_internals")]
+pub mod unix {}
 #[cfg(all(
     doc,
     any(
@@ -40,87 +31,115 @@ mod doc {
         all(target_vendor = "fortanix", target_env = "sgx")
     )
 ))]
-mod doc {
-    // On certain platforms right now the "main modules" modules that are
-    // documented don't compile (missing things in `libc` which is empty),
-    // so just omit them with an empty module.
-
-    #[unstable(issue = "none", feature = "std_internals")]
-    pub mod unix {}
-
-    #[unstable(issue = "none", feature = "std_internals")]
-    pub mod linux {}
-
-    #[unstable(issue = "none", feature = "std_internals")]
-    pub mod wasi {}
-
-    #[unstable(issue = "none", feature = "std_internals")]
-    pub mod windows {}
-}
-#[cfg(doc)]
-#[stable(feature = "os", since = "1.0.0")]
-pub use doc::*;
-
-#[cfg(not(doc))]
-#[path = "."]
-mod imp {
-    // If we're not documenting std then we only expose modules appropriate for the
-    // current platform.
-
-    #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
-    pub mod fortanix_sgx;
-
-    #[cfg(target_os = "hermit")]
-    #[path = "hermit/mod.rs"]
-    pub mod unix;
+#[unstable(issue = "none", feature = "std_internals")]
+pub mod linux {}
+#[cfg(all(
+    doc,
+    any(
+        all(target_arch = "wasm32", not(target_os = "wasi")),
+        all(target_vendor = "fortanix", target_env = "sgx")
+    )
+))]
+#[unstable(issue = "none", feature = "std_internals")]
+pub mod wasi {}
+#[cfg(all(
+    doc,
+    any(
+        all(target_arch = "wasm32", not(target_os = "wasi")),
+        all(target_vendor = "fortanix", target_env = "sgx")
+    )
+))]
+#[unstable(issue = "none", feature = "std_internals")]
+pub mod windows {}
 
-    #[cfg(target_os = "android")]
-    pub mod android;
-    #[cfg(target_os = "dragonfly")]
-    pub mod dragonfly;
-    #[cfg(target_os = "emscripten")]
-    pub mod emscripten;
-    #[cfg(target_os = "espidf")]
-    pub mod espidf;
-    #[cfg(target_os = "freebsd")]
-    pub mod freebsd;
-    #[cfg(target_os = "fuchsia")]
-    pub mod fuchsia;
-    #[cfg(target_os = "haiku")]
-    pub mod haiku;
-    #[cfg(target_os = "illumos")]
-    pub mod illumos;
-    #[cfg(target_os = "ios")]
-    pub mod ios;
-    #[cfg(target_os = "l4re")]
-    pub mod linux;
-    #[cfg(target_os = "linux")]
-    pub mod linux;
-    #[cfg(target_os = "macos")]
-    pub mod macos;
-    #[cfg(target_os = "netbsd")]
-    pub mod netbsd;
-    #[cfg(target_os = "openbsd")]
-    pub mod openbsd;
-    #[cfg(target_os = "redox")]
-    pub mod redox;
-    #[cfg(target_os = "solaris")]
-    pub mod solaris;
-    #[cfg(unix)]
-    pub mod unix;
+// unix
+#[cfg(not(all(
+    doc,
+    any(
+        all(target_arch = "wasm32", not(target_os = "wasi")),
+        all(target_vendor = "fortanix", target_env = "sgx")
+    )
+)))]
+#[cfg(target_os = "hermit")]
+#[path = "hermit/mod.rs"]
+pub mod unix;
+#[cfg(not(all(
+    doc,
+    any(
+        all(target_arch = "wasm32", not(target_os = "wasi")),
+        all(target_vendor = "fortanix", target_env = "sgx")
+    )
+)))]
+#[cfg(all(not(target_os = "hermit"), any(unix, doc)))]
+pub mod unix;
 
-    #[cfg(target_os = "vxworks")]
-    pub mod vxworks;
+// linux
+#[cfg(not(all(
+    doc,
+    any(
+        all(target_arch = "wasm32", not(target_os = "wasi")),
+        all(target_vendor = "fortanix", target_env = "sgx")
+    )
+)))]
+#[cfg(any(target_os = "linux", target_os = "l4re", doc))]
+pub mod linux;
 
-    #[cfg(target_os = "wasi")]
-    pub mod wasi;
+// wasi
+#[cfg(not(all(
+    doc,
+    any(
+        all(target_arch = "wasm32", not(target_os = "wasi")),
+        all(target_vendor = "fortanix", target_env = "sgx")
+    )
+)))]
+#[cfg(any(target_os = "wasi", doc))]
+pub mod wasi;
 
-    #[cfg(windows)]
-    pub mod windows;
-}
-#[cfg(not(doc))]
-#[stable(feature = "os", since = "1.0.0")]
-pub use imp::*;
+// windows
+#[cfg(not(all(
+    doc,
+    any(
+        all(target_arch = "wasm32", not(target_os = "wasi")),
+        all(target_vendor = "fortanix", target_env = "sgx")
+    )
+)))]
+#[cfg(any(windows, doc))]
+pub mod windows;
+
+// Others.
+#[cfg(target_os = "android")]
+pub mod android;
+#[cfg(target_os = "dragonfly")]
+pub mod dragonfly;
+#[cfg(target_os = "emscripten")]
+pub mod emscripten;
+#[cfg(target_os = "espidf")]
+pub mod espidf;
+#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
+pub mod fortanix_sgx;
+#[cfg(target_os = "freebsd")]
+pub mod freebsd;
+#[cfg(target_os = "fuchsia")]
+pub mod fuchsia;
+#[cfg(target_os = "haiku")]
+pub mod haiku;
+#[cfg(target_os = "illumos")]
+pub mod illumos;
+#[cfg(target_os = "ios")]
+pub mod ios;
+#[cfg(target_os = "macos")]
+pub mod macos;
+#[cfg(target_os = "netbsd")]
+pub mod netbsd;
+#[cfg(target_os = "openbsd")]
+pub mod openbsd;
+#[cfg(target_os = "redox")]
+pub mod redox;
+#[cfg(target_os = "solaris")]
+pub mod solaris;
+
+#[cfg(target_os = "vxworks")]
+pub mod vxworks;
 
 #[cfg(any(unix, target_os = "wasi", doc))]
 mod fd;
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 7de70091bec..231c9fc19c0 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -450,7 +450,7 @@ pub fn panicking() -> bool {
 #[cfg_attr(not(feature = "panic_immediate_abort"), track_caller)]
 #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
 #[cfg_attr(feature = "panic_immediate_abort", inline)]
-#[cfg_attr(all(not(bootstrap), not(test)), lang = "begin_panic_fmt")]
+#[cfg_attr(not(test), lang = "begin_panic_fmt")]
 pub fn begin_panic_fmt(msg: &fmt::Arguments<'_>) -> ! {
     if cfg!(feature = "panic_immediate_abort") {
         intrinsics::abort()
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index b85489dabe9..0de9126dab2 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -1,3 +1,6 @@
+// `library/{std,core}/src/primitive_docs.rs` should have the same contents.
+// These are different files so that relative links work properly without
+// having to have `CARGO_PKG_NAME` set, but conceptually they should always be the same.
 #[doc(primitive = "bool")]
 #[doc(alias = "true")]
 #[doc(alias = "false")]
@@ -20,12 +23,12 @@
 /// assert!(!bool_val);
 /// ```
 ///
-/// [`true`]: keyword.true.html
-/// [`false`]: keyword.false.html
+/// [`true`]: ../std/keyword.true.html
+/// [`false`]: ../std/keyword.false.html
 /// [`BitAnd`]: ops::BitAnd
 /// [`BitOr`]: ops::BitOr
 /// [`Not`]: ops::Not
-/// [`if`]: keyword.if.html
+/// [`if`]: ../std/keyword.if.html
 ///
 /// # Examples
 ///
@@ -103,7 +106,7 @@ mod prim_bool {}
 /// behaviour of the `!` type - expressions with type `!` will coerce into any other type.
 ///
 /// [`u32`]: prim@u32
-/// [`exit`]: process::exit
+#[doc = concat!("[`exit`]: ", include_str!("../primitive_docs/process_exit.md"))]
 ///
 /// # `!` and generics
 ///
@@ -188,7 +191,7 @@ mod prim_bool {}
 /// because `!` coerces to `Result<!, ConnectionError>` automatically.
 ///
 /// [`String::from_str`]: str::FromStr::from_str
-/// [`String`]: string::String
+#[doc = concat!("[`String`]: ", include_str!("../primitive_docs/string_string.md"))]
 /// [`FromStr`]: str::FromStr
 ///
 /// # `!` and traits
@@ -264,7 +267,7 @@ mod prim_bool {}
 /// `impl` for this which simply panics, but the same is true for any type (we could `impl
 /// Default` for (eg.) [`File`] by just making [`default()`] panic.)
 ///
-/// [`File`]: fs::File
+#[doc = concat!("[`File`]: ", include_str!("../primitive_docs/fs_file.md"))]
 /// [`Debug`]: fmt::Debug
 /// [`default()`]: Default::default
 ///
@@ -272,7 +275,6 @@ mod prim_bool {}
 mod prim_never {}
 
 #[doc(primitive = "char")]
-//
 /// A character type.
 ///
 /// The `char` type represents a single character. More specifically, since
@@ -304,7 +306,7 @@ mod prim_never {}
 /// assert_eq!(5, s.len() * std::mem::size_of::<u8>());
 /// ```
 ///
-/// [`String`]: string/struct.String.html
+#[doc = concat!("[`String`]: ", include_str!("../primitive_docs/string_string.md"))]
 ///
 /// As always, remember that a human intuition for 'character' might not map to
 /// Unicode's definitions. For example, despite looking similar, the 'é'
@@ -388,8 +390,11 @@ mod prim_char {}
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_unit {}
 
-#[doc(alias = "ptr")]
 #[doc(primitive = "pointer")]
+#[doc(alias = "ptr")]
+#[doc(alias = "*")]
+#[doc(alias = "*const")]
+#[doc(alias = "*mut")]
 //
 /// Raw, unsafe pointers, `*const T`, and `*mut T`.
 ///
@@ -496,16 +501,16 @@ mod prim_unit {}
 /// [`null_mut`]: ptr::null_mut
 /// [`is_null`]: pointer::is_null
 /// [`offset`]: pointer::offset
-/// [`into_raw`]: Box::into_raw
+#[doc = concat!("[`into_raw`]: ", include_str!("../primitive_docs/box_into_raw.md"))]
 /// [`drop`]: mem::drop
 /// [`write`]: ptr::write
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_pointer {}
 
+#[doc(primitive = "array")]
 #[doc(alias = "[]")]
 #[doc(alias = "[T;N]")] // unfortunately, rustdoc doesn't have fuzzy search for aliases
 #[doc(alias = "[T; N]")]
-#[doc(primitive = "array")]
 /// A fixed-size array, denoted `[T; N]`, for the element type, `T`, and the
 /// non-negative compile-time constant size, `N`.
 ///
@@ -578,9 +583,9 @@ mod prim_pointer {}
 /// # Editions
 ///
 /// Prior to Rust 1.53, arrays did not implement [`IntoIterator`] by value, so the method call
-/// `array.into_iter()` auto-referenced into a [slice iterator](slice::iter). Right now, the old behavior
-/// is preserved in the 2015 and 2018 editions of Rust for compatibility, ignoring
-/// `IntoIterator` by value. In the future, the behavior on the 2015 and 2018 edition
+/// `array.into_iter()` auto-referenced into a [slice iterator](slice::iter). Right now, the old
+/// behavior is preserved in the 2015 and 2018 editions of Rust for compatibility, ignoring
+/// [`IntoIterator`] by value. In the future, the behavior on the 2015 and 2018 edition
 /// might be made consistent to the behavior of later editions.
 ///
 /// ```rust,edition2018
@@ -612,8 +617,7 @@ mod prim_pointer {}
 /// Starting in the 2021 edition, `array.into_iter()` uses `IntoIterator` normally to iterate
 /// by value, and `iter()` should be used to iterate by reference like previous editions.
 ///
-#[cfg_attr(bootstrap, doc = "```rust,edition2021,ignore")]
-#[cfg_attr(not(bootstrap), doc = "```rust,edition2021")]
+/// ```rust,edition2021
 /// // Rust 2021:
 ///
 /// let array: [i32; 3] = [0; 3];
@@ -1040,15 +1044,15 @@ mod prim_usize {}
 /// References, both shared and mutable.
 ///
 /// A reference represents a borrow of some owned value. You can get one by using the `&` or `&mut`
-/// operators on a value, or by using a [`ref`](keyword.ref.html) or
-/// <code>[ref](keyword.ref.html) [mut](keyword.mut.html)</code> pattern.
+/// operators on a value, or by using a [`ref`](../std/keyword.ref.html) or
+/// <code>[ref](../std/keyword.ref.html) [mut](../std/keyword.mut.html)</code> pattern.
 ///
 /// For those familiar with pointers, a reference is just a pointer that is assumed to be
 /// aligned, not null, and pointing to memory containing a valid value of `T` - for example,
 /// <code>&[bool]</code> can only point to an allocation containing the integer values `1`
-/// ([`true`](keyword.true.html)) or `0` ([`false`](keyword.false.html)), but creating a
-/// <code>&[bool]</code> that points to an allocation containing the value `3` causes
-/// undefined behaviour.
+/// ([`true`](../std/keyword.true.html)) or `0` ([`false`](../std/keyword.false.html)), but
+/// creating a <code>&[bool]</code> that points to an allocation containing
+/// the value `3` causes undefined behaviour.
 /// In fact, <code>[Option]\<&T></code> has the same memory representation as a
 /// nullable but aligned pointer, and can be passed across FFI boundaries as such.
 ///
@@ -1115,6 +1119,7 @@ mod prim_usize {}
 ///
 /// [`DerefMut`]: ops::DerefMut
 /// [`BorrowMut`]: borrow::BorrowMut
+/// [bool]: prim@bool
 ///
 /// The following traits are implemented on `&T` references if the underlying `T` also implements
 /// that trait:
@@ -1132,7 +1137,7 @@ mod prim_usize {}
 /// [`std::fmt`]: fmt
 /// ['Pointer`]: fmt::Pointer
 /// [`Hash`]: hash::Hash
-/// [`ToSocketAddrs`]: net::ToSocketAddrs
+#[doc = concat!("[`ToSocketAddrs`]: ", include_str!("../primitive_docs/net_tosocketaddrs.md"))]
 ///
 /// `&mut T` references get all of the above except `ToSocketAddrs`, plus the following, if `T`
 /// implements that trait:
@@ -1153,9 +1158,10 @@ mod prim_usize {}
 ///
 /// [`FusedIterator`]: iter::FusedIterator
 /// [`TrustedLen`]: iter::TrustedLen
-/// [`Seek`]: io::Seek
-/// [`BufRead`]: io::BufRead
-/// [`Read`]: io::Read
+#[doc = concat!("[`Seek`]: ", include_str!("../primitive_docs/io_seek.md"))]
+#[doc = concat!("[`BufRead`]: ", include_str!("../primitive_docs/io_bufread.md"))]
+#[doc = concat!("[`Read`]: ", include_str!("../primitive_docs/io_read.md"))]
+#[doc = concat!("[`io::Write`]: ", include_str!("../primitive_docs/io_write.md"))]
 ///
 /// Note that due to method call deref coercion, simply calling a trait method will act like they
 /// work on references as well as they do on owned values! The implementations described here are
diff --git a/library/test/src/formatters/junit.rs b/library/test/src/formatters/junit.rs
index c4b0e1e5c23..aa244807514 100644
--- a/library/test/src/formatters/junit.rs
+++ b/library/test/src/formatters/junit.rs
@@ -53,7 +53,7 @@ impl<T: Write> OutputFormatter for JunitFormatter<T> {
         // Because the testsuit node holds some of the information as attributes, we can't write it
         // until all of the tests has ran. Instead of writting every result as they come in, we add
         // them to a Vec and write them all at once when run is complete.
-        let duration = exec_time.map(|t| t.0.clone()).unwrap_or_default();
+        let duration = exec_time.map(|t| t.0).unwrap_or_default();
         self.results.push((desc.clone(), result.clone(), duration));
         Ok(())
     }
diff --git a/library/test/src/term/terminfo/mod.rs b/library/test/src/term/terminfo/mod.rs
index f4c5a05d1e2..694473f52c1 100644
--- a/library/test/src/term/terminfo/mod.rs
+++ b/library/test/src/term/terminfo/mod.rs
@@ -16,6 +16,7 @@ use parser::compiled::{msys_terminfo, parse};
 use searcher::get_dbpath_for_term;
 
 /// A parsed terminfo database entry.
+#[allow(unused)]
 #[derive(Debug)]
 pub(crate) struct TermInfo {
     /// Names for the terminal
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index c8714117930..b7478d83955 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -589,11 +589,20 @@ impl Step for Rustc {
         cargo.rustdocflag("-Zunstable-options");
         cargo.rustdocflag("-Znormalize-docs");
         cargo.rustdocflag("--show-type-layout");
+        cargo.rustdocflag("--generate-link-to-definition");
         compile::rustc_cargo(builder, &mut cargo, target);
+        cargo.arg("-Zunstable-options");
         cargo.arg("-Zskip-rustdoc-fingerprint");
 
         // Only include compiler crates, no dependencies of those, such as `libc`.
+        // Do link to dependencies on `docs.rs` however using `rustdoc-map`.
         cargo.arg("--no-deps");
+        cargo.arg("-Zrustdoc-map");
+
+        // FIXME: `-Zrustdoc-map` does not yet correctly work for transitive dependencies,
+        // once this is no longer an issue the special case for `ena` can be removed.
+        cargo.rustdocflag("--extern-html-root-url");
+        cargo.rustdocflag("ena=https://docs.rs/ena/latest/");
 
         // Find dependencies for top level crates.
         let mut compiler_crates = HashSet::new();
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index d12e86b7c1d..386ffb384a8 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -925,6 +925,11 @@ impl Step for RustdocGUI {
                     .env("RUSTDOC", builder.rustdoc(self.compiler))
                     .env("RUSTC", builder.rustc(self.compiler))
                     .current_dir(path);
+                // FIXME: implement a `// compile-flags` command or similar
+                //        instead of hard-coding this test
+                if entry.file_name() == "link_to_definition" {
+                    cargo.env("RUSTDOCFLAGS", "-Zunstable-options --generate-link-to-definition");
+                }
                 builder.run(&mut cargo);
             }
         }
diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh
index c7ff78ca90c..70c57e07fde 100755
--- a/src/ci/docker/scripts/freebsd-toolchain.sh
+++ b/src/ci/docker/scripts/freebsd-toolchain.sh
@@ -53,7 +53,7 @@ files_to_extract=(
 for lib in c cxxrt gcc_s m thr util; do
   files_to_extract=("${files_to_extract[@]}" "./lib/lib${lib}.*" "./usr/lib/lib${lib}.*")
 done
-for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared; do
+for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared procstat; do
   files_to_extract=("${files_to_extract[@]}" "./usr/lib/lib${lib}.*")
 done
 
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index 6417f5a984a..c9f8692d418 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -635,6 +635,9 @@ jobs:
               SCRIPT: python x.py dist
               # RLS does not build for aarch64-pc-windows-msvc. See rust-lang/rls#1693
               DIST_REQUIRE_ALL_TOOLS: 0
+              # Hack around this SDK version, because it doesn't work with clang.
+              # See https://github.com/rust-lang/rust/issues/88796
+              WINDOWS_SDK_20348_HACK: 1
             <<: *job-windows-xl
 
           - name: dist-i686-mingw
diff --git a/src/ci/scripts/install-clang.sh b/src/ci/scripts/install-clang.sh
index 7b540b5c6e9..fd29d3a022a 100755
--- a/src/ci/scripts/install-clang.sh
+++ b/src/ci/scripts/install-clang.sh
@@ -37,6 +37,12 @@ if isMacOS; then
     # `clang-ar` by accident.
     ciCommandSetEnv AR "ar"
 elif isWindows && [[ ${CUSTOM_MINGW-0} -ne 1 ]]; then
+
+    if [[ ${WINDOWS_SDK_20348_HACK-0} -eq 1 ]]; then
+        rm -rf '/c/Program Files (x86)/Windows Kits/10/include/10.0.20348.0'
+        mv '/c/Program Files (x86)/Windows Kits/10/include/'10.0.{19041,20348}.0
+    fi
+
     # If we're compiling for MSVC then we, like most other distribution builders,
     # switch to clang as the compiler. This'll allow us eventually to enable LTO
     # amongst LLVM and rustc. Note that we only do this on MSVC as I don't think
diff --git a/src/ci/scripts/verify-backported-commits.sh b/src/ci/scripts/verify-backported-commits.sh
index 1023e4b0e28..d3da6d1ac91 100755
--- a/src/ci/scripts/verify-backported-commits.sh
+++ b/src/ci/scripts/verify-backported-commits.sh
@@ -18,14 +18,6 @@ verify_backported_commits_main() {
     exit 0
   fi
 
-  echo 'git: unshallowing the repository so we can check commits'
-  git fetch \
-    --no-tags \
-    --no-recurse-submodules \
-    --progress \
-    --prune \
-    --unshallow
-
   if [[ $ci_base_branch == "beta" ]]; then
     verify_cherries master "$BETA_LIMIT" \
       || exit 1
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
-Subproject c3a51e23859554369e6bbb5128dcef0e4f159fb
+Subproject 4c76da9ddb4650203c129fceffdea95a3466c20
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject 04f489c889235fe3b6dfe678ae5410d07deda95
+Subproject 9d4132b56c4999cd3ce1aeca5f1b2f2cb0d11c2
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject 95f1acf9a39d6f402f654e917e2c1dfdb779c5f
+Subproject 9198465b6ca8bed669df0cbb67c0e6d0b140803
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 6da0703beac..3ba06e87220 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -217,6 +217,7 @@ target | std | host | notes
 `armv5te-unknown-linux-uclibceabi` | ? |  | ARMv5TE Linux with uClibc
 `armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD
 `armv6-unknown-netbsd-eabihf` | ? |  |
+`armv6k-nintendo-3ds` | * |  | ARMv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain)
 `armv7-apple-ios` | ✓ |  | ARMv7 iOS, Cortex-a8
 `armv7-unknown-freebsd` | ✓ | ✓ | ARMv7 FreeBSD
 `armv7-unknown-netbsd-eabihf` | ✓ | ✓ |
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index dce98abcf53..b55db452f12 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -222,13 +222,13 @@ all these files are linked from every page, changing where they are can be cumbe
 specially cache them. This flag will rename all these files in the output to include the suffix in
 the filename. For example, `light.css` would become `light-suf.css` with the above command.
 
-### `--display-warnings`: display warnings when documenting or running documentation tests
+### `--display-doctest-warnings`: display warnings when documenting or running documentation tests
 
 Using this flag looks like this:
 
 ```bash
-$ rustdoc src/lib.rs -Z unstable-options --display-warnings
-$ rustdoc --test src/lib.rs -Z unstable-options --display-warnings
+$ rustdoc src/lib.rs -Z unstable-options --display-doctest-warnings
+$ rustdoc --test src/lib.rs -Z unstable-options --display-doctest-warnings
 ```
 
 The intent behind this flag is to allow the user to see warnings that occur within their library or
diff --git a/src/doc/unstable-book/src/compiler-flags/remap-cwd-prefix.md b/src/doc/unstable-book/src/compiler-flags/remap-cwd-prefix.md
new file mode 100644
index 00000000000..977d258529f
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/remap-cwd-prefix.md
@@ -0,0 +1,24 @@
+# `remap-cwd-prefix`
+
+The tracking issue for this feature is: [#87325](https://github.com/rust-lang/rust/issues/87325).
+
+------------------------
+
+This flag will rewrite absolute paths under the current working directory,
+replacing the current working directory prefix with a specified value.
+
+The given value may be absolute or relative, or empty. This switch takes
+precidence over `--remap-path-prefix` in case they would both match a given
+path.
+
+This flag helps to produce deterministic output, by removing the current working
+directory from build output, while allowing the command line to be universally
+reproducible, such that the same execution will work on all machines, regardless
+of build environment.
+
+## Example
+```sh
+# This would produce an absolute path to main.rs in build outputs of
+# "./main.rs".
+rustc -Z remap-cwd-prefix=. main.rs
+```
diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md
index a10928a7471..ccaf6e8733e 100644
--- a/src/doc/unstable-book/src/library-features/asm.md
+++ b/src/doc/unstable-book/src/library-features/asm.md
@@ -375,7 +375,7 @@ Any reuse of a named label, local or otherwise, can result in a assembler or lin
 
 As a consequence, you should only use GNU assembler **numeric** [local labels] inside inline assembly code. Defining symbols in assembly code may lead to assembler and/or linker errors due to duplicate symbol definitions.
 
-Moreover, on x86 when using the default intel syntax, due to [an llvm bug], you shouldn't use labels exclusively made of `0` and `1` digits, e.g. `0`, `11` or `101010`, as they may end up being interpreted as binary values. Using `option(att_syntax)` will avoid any ambiguity, but that affects the syntax of the _entire_ `asm!` block.
+Moreover, on x86 when using the default intel syntax, due to [an llvm bug], you shouldn't use labels exclusively made of `0` and `1` digits, e.g. `0`, `11` or `101010`, as they may end up being interpreted as binary values. Using `options(att_syntax)` will avoid any ambiguity, but that affects the syntax of the _entire_ `asm!` block.
 
 ```rust,allow_fail
 #![feature(asm)]
@@ -804,9 +804,9 @@ The following ABIs can be used with `clobber_abi`:
 
 | Architecture | ABI name | Clobbered registers |
 | ------------ | -------- | ------------------- |
-| x86-32 | `"C"`, `"system"`, `"efiapi"`, `"cdecl"`, `"stdcall"`, `"fastcall"` | `ax`, `cx`, `dx`, `xmm[0-7]`, `mm[0-7]`, `st([0-7])` |
-| x86-64 | `"C"`, `"system"` (on Windows), `"efiapi"`, `"win64"` | `ax`, `cx`, `dx`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `st([0-7])` |
-| x86-64 | `"C"`, `"system"` (on non-Windows), `"sysv64"` | `ax`, `cx`, `dx`, `si`, `di`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `st([0-7])` |
+| x86-32 | `"C"`, `"system"`, `"efiapi"`, `"cdecl"`, `"stdcall"`, `"fastcall"` | `ax`, `cx`, `dx`, `xmm[0-7]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` |
+| x86-64 | `"C"`, `"system"` (on Windows), `"efiapi"`, `"win64"` | `ax`, `cx`, `dx`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` |
+| x86-64 | `"C"`, `"system"` (on non-Windows), `"sysv64"` | `ax`, `cx`, `dx`, `si`, `di`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` |
 | AArch64 | `"C"`, `"system"`, `"efiapi"` | `x[0-17]`, `x30`, `v[0-31]`, `p[0-15]`, `ffr` |
 | ARM | `"C"`, `"system"`, `"efiapi"`, `"aapcs"` | `r[0-3]`, `r12`, `r14`, `s[0-15]`, `d[0-7]`, `d[16-31]` |
 | RISC-V | `"C"`, `"system"`, `"efiapi"` | `x1`, `x[5-7]`, `x[10-17]`, `x[28-31]`, `f[0-7]`, `f[10-17]`, `f[28-31]`, `v[0-31]` |
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index ff3641d6c9a..15d4563ad74 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -17,7 +17,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
         let param_env = self.cx.tcx.param_env(item_def_id);
         let ty = self.cx.tcx.type_of(item_def_id);
 
-        debug!("get_blanket_impls({:?})", ty);
+        trace!("get_blanket_impls({:?})", ty);
         let mut impls = Vec::new();
         for &trait_def_id in self.cx.tcx.all_traits(()).iter() {
             if !self.cx.cache.access_levels.is_public(trait_def_id)
@@ -28,9 +28,10 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
             // NOTE: doesn't use `for_each_relevant_impl` to avoid looking at anything besides blanket impls
             let trait_impls = self.cx.tcx.trait_impls_of(trait_def_id);
             for &impl_def_id in trait_impls.blanket_impls() {
-                debug!(
+                trace!(
                     "get_blanket_impls: Considering impl for trait '{:?}' {:?}",
-                    trait_def_id, impl_def_id
+                    trait_def_id,
+                    impl_def_id
                 );
                 let trait_ref = self.cx.tcx.impl_trait_ref(impl_def_id).unwrap();
                 let is_param = matches!(trait_ref.self_ty().kind(), ty::Param(_));
@@ -50,9 +51,11 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                         // FIXME(eddyb) ignoring `obligations` might cause false positives.
                         drop(obligations);
 
-                        debug!(
+                        trace!(
                             "invoking predicate_may_hold: param_env={:?}, trait_ref={:?}, ty={:?}",
-                            param_env, trait_ref, ty
+                            param_env,
+                            trait_ref,
+                            ty
                         );
                         let predicates = self
                             .cx
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 0c81a558430..29834c82b3d 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -447,9 +447,9 @@ crate fn build_impl(
     }
 
     let (merged_attrs, cfg) = merge_attrs(cx, parent_module.into(), load_attrs(cx, did), attrs);
-    debug!("merged_attrs={:?}", merged_attrs);
+    trace!("merged_attrs={:?}", merged_attrs);
 
-    debug!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id());
+    trace!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id());
     ret.push(clean::Item::from_def_id_and_attrs_and_parts(
         did,
         None,
@@ -482,12 +482,13 @@ fn build_module(
     // visit each node at most once.
     for &item in cx.tcx.item_children(did).iter() {
         if item.vis == ty::Visibility::Public {
-            if let Some(def_id) = item.res.mod_def_id() {
+            let res = item.res.expect_non_local();
+            if let Some(def_id) = res.mod_def_id() {
                 if did == def_id || !visited.insert(def_id) {
                     continue;
                 }
             }
-            if let Res::PrimTy(p) = item.res {
+            if let Res::PrimTy(p) = res {
                 // Primitive types can't be inlined so generate an import instead.
                 let prim_ty = clean::PrimitiveType::from(p);
                 items.push(clean::Item {
@@ -500,7 +501,7 @@ fn build_module(
                         clean::ImportSource {
                             path: clean::Path {
                                 global: false,
-                                res: item.res,
+                                res,
                                 segments: vec![clean::PathSegment {
                                     name: prim_ty.as_sym(),
                                     args: clean::GenericArgs::AngleBracketed {
@@ -515,9 +516,7 @@ fn build_module(
                     ))),
                     cfg: None,
                 });
-            } else if let Some(i) =
-                try_inline(cx, did, None, item.res, item.ident.name, None, visited)
-            {
+            } else if let Some(i) = try_inline(cx, did, None, res, item.ident.name, None, visited) {
                 items.extend(i)
             }
         }
@@ -557,7 +556,6 @@ fn build_macro(
     name: Symbol,
     import_def_id: Option<DefId>,
 ) -> clean::ItemKind {
-    let imported_from = cx.tcx.crate_name(def_id.krate);
     match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.sess()) {
         LoadedMacro::MacroDef(item_def, _) => {
             if let ast::ItemKind::MacroDef(ref def) = item_def.kind {
@@ -569,7 +567,6 @@ fn build_macro(
                         def_id,
                         cx.tcx.visibility(import_def_id.unwrap_or(def_id)),
                     ),
-                    imported_from: Some(imported_from),
                 })
             } else {
                 unreachable!()
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index a95300217ab..e281bbc59c2 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -11,6 +11,7 @@ crate mod utils;
 
 use rustc_ast as ast;
 use rustc_attr as attr;
+use rustc_const_eval::const_eval::{is_const_fn, is_unstable_const_fn};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
@@ -22,7 +23,6 @@ use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::subst::{InternalSubsts, Subst};
 use rustc_middle::ty::{self, AdtKind, DefIdTree, Lift, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
-use rustc_mir::const_eval::{is_const_fn, is_unstable_const_fn};
 use rustc_span::hygiene::{AstPass, MacroKind};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{self, ExpnKind};
@@ -164,14 +164,7 @@ impl Clean<Type> for (ty::TraitRef<'_>, &[TypeBinding]) {
             );
         }
         inline::record_extern_fqn(cx, trait_ref.def_id, kind);
-        let path = external_path(
-            cx,
-            cx.tcx.item_name(trait_ref.def_id),
-            Some(trait_ref.def_id),
-            true,
-            bounds.to_vec(),
-            trait_ref.substs,
-        );
+        let path = external_path(cx, trait_ref.def_id, true, bounds.to_vec(), trait_ref.substs);
 
         debug!("ty::TraitRef\n  subst: {:?}\n", trait_ref.substs);
 
@@ -906,7 +899,7 @@ impl Clean<bool> for hir::IsAuto {
 impl Clean<Type> for hir::TraitRef<'_> {
     fn clean(&self, cx: &mut DocContext<'_>) -> Type {
         let path = self.path.clean(cx);
-        resolve_type(cx, path, self.hir_ref_id)
+        resolve_type(cx, path)
     }
 }
 
@@ -1164,7 +1157,7 @@ impl Clean<Item> for ty::AssocItem {
 
 fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
     use rustc_hir::GenericParamCount;
-    let hir::Ty { hir_id, span, ref kind } = *hir_ty;
+    let hir::Ty { hir_id: _, span, ref kind } = *hir_ty;
     let qpath = match kind {
         hir::TyKind::Path(qpath) => qpath,
         _ => unreachable!(),
@@ -1271,7 +1264,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
                 return cx.enter_alias(ty_substs, lt_substs, ct_substs, |cx| ty.clean(cx));
             }
             let path = path.clean(cx);
-            resolve_type(cx, path, hir_id)
+            resolve_type(cx, path)
         }
         hir::QPath::Resolved(Some(ref qself), ref p) => {
             // Try to normalize `<X as Y>::T` to a type
@@ -1292,7 +1285,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
                 name: p.segments.last().expect("segments were empty").ident.name,
                 self_def_id: Some(DefId::local(qself.hir_id.owner.local_def_index)),
                 self_type: Box::new(qself.clean(cx)),
-                trait_: Box::new(resolve_type(cx, trait_path, hir_id)),
+                trait_: Box::new(resolve_type(cx, trait_path)),
             }
         }
         hir::QPath::TypeRelative(ref qself, ref segment) => {
@@ -1308,7 +1301,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
                 name: segment.ident.name,
                 self_def_id: res.opt_def_id(),
                 self_type: Box::new(qself.clean(cx)),
-                trait_: Box::new(resolve_type(cx, trait_path, hir_id)),
+                trait_: Box::new(resolve_type(cx, trait_path)),
             }
         }
         hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"),
@@ -1406,7 +1399,7 @@ fn normalize(cx: &mut DocContext<'tcx>, ty: Ty<'_>) -> Option<Ty<'tcx>> {
 
 impl<'tcx> Clean<Type> for Ty<'tcx> {
     fn clean(&self, cx: &mut DocContext<'_>) -> Type {
-        debug!("cleaning type: {:?}", self);
+        trace!("cleaning type: {:?}", self);
         let ty = normalize(cx, self).unwrap_or(self);
         match *ty.kind() {
             ty::Never => Never,
@@ -1448,19 +1441,12 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                     AdtKind::Enum => ItemType::Enum,
                 };
                 inline::record_extern_fqn(cx, did, kind);
-                let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], substs);
+                let path = external_path(cx, did, false, vec![], substs);
                 ResolvedPath { path, did, is_generic: false }
             }
             ty::Foreign(did) => {
                 inline::record_extern_fqn(cx, did, ItemType::ForeignType);
-                let path = external_path(
-                    cx,
-                    cx.tcx.item_name(did),
-                    None,
-                    false,
-                    vec![],
-                    InternalSubsts::empty(),
-                );
+                let path = external_path(cx, did, false, vec![], InternalSubsts::empty());
                 ResolvedPath { path, did, is_generic: false }
             }
             ty::Dynamic(ref obj, ref reg) => {
@@ -1484,8 +1470,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
 
                 for did in dids {
                     let empty = cx.tcx.intern_substs(&[]);
-                    let path =
-                        external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
+                    let path = external_path(cx, did, false, vec![], empty);
                     inline::record_extern_fqn(cx, did, ItemType::Trait);
                     let bound = PolyTrait {
                         trait_: ResolvedPath { path, did, is_generic: false },
@@ -1502,8 +1487,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
                     });
                 }
 
-                let path =
-                    external_path(cx, cx.tcx.item_name(did), Some(did), false, bindings, substs);
+                let path = external_path(cx, did, false, bindings, substs);
                 bounds.insert(
                     0,
                     PolyTrait {
@@ -1859,7 +1843,6 @@ impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Symbol>) {
                 }
                 ItemKind::Macro(ref macro_def) => MacroItem(Macro {
                     source: display_macro_source(cx, name, &macro_def, def_id, &item.vis),
-                    imported_from: None,
                 }),
                 ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => {
                     let items = item_ids
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 5eff56a2200..b3c320555f9 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -212,7 +212,7 @@ impl ExternalCrate {
     crate fn keywords(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, Symbol)> {
         let root = self.def_id();
 
-        let as_keyword = |res: Res| {
+        let as_keyword = |res: Res<!>| {
             if let Res::Def(DefKind::Mod, def_id) = res {
                 let attrs = tcx.get_attrs(def_id);
                 let mut keyword = None;
@@ -243,7 +243,8 @@ impl ExternalCrate {
                         hir::ItemKind::Use(ref path, hir::UseKind::Single)
                             if item.vis.node.is_pub() =>
                         {
-                            as_keyword(path.res).map(|(_, prim)| (id.def_id.to_def_id(), prim))
+                            as_keyword(path.res.expect_non_local())
+                                .map(|(_, prim)| (id.def_id.to_def_id(), prim))
                         }
                         _ => None,
                     }
@@ -274,7 +275,7 @@ impl ExternalCrate {
         // Also note that this does not attempt to deal with modules tagged
         // duplicately for the same primitive. This is handled later on when
         // rendering by delegating everything to a hash map.
-        let as_primitive = |res: Res| {
+        let as_primitive = |res: Res<!>| {
             if let Res::Def(DefKind::Mod, def_id) = res {
                 let attrs = tcx.get_attrs(def_id);
                 let mut prim = None;
@@ -309,7 +310,7 @@ impl ExternalCrate {
                         hir::ItemKind::Use(ref path, hir::UseKind::Single)
                             if item.vis.node.is_pub() =>
                         {
-                            as_primitive(path.res).map(|(_, prim)| {
+                            as_primitive(path.res.expect_non_local()).map(|(_, prim)| {
                                 // Pretend the primitive is local.
                                 (id.def_id.to_def_id(), prim)
                             })
@@ -461,60 +462,20 @@ impl Item {
             .map_or(&[][..], |v| v.as_slice())
             .iter()
             .filter_map(|ItemLink { link: s, link_text, did, ref fragment }| {
-                match did {
-                    Some(did) => {
-                        if let Ok((mut href, ..)) = href(did.clone(), cx) {
-                            if let Some(ref fragment) = *fragment {
-                                href.push('#');
-                                href.push_str(fragment);
-                            }
-                            Some(RenderedLink {
-                                original_text: s.clone(),
-                                new_text: link_text.clone(),
-                                href,
-                            })
-                        } else {
-                            None
-                        }
-                    }
-                    // FIXME(83083): using fragments as a side-channel for
-                    // primitive names is very unfortunate
-                    None => {
-                        let relative_to = &cx.current;
-                        if let Some(ref fragment) = *fragment {
-                            let url = match cx.cache().extern_locations.get(&self.def_id.krate()) {
-                                Some(&ExternalLocation::Local) => {
-                                    if relative_to[0] == "std" {
-                                        let depth = relative_to.len() - 1;
-                                        "../".repeat(depth)
-                                    } else {
-                                        let depth = relative_to.len();
-                                        format!("{}std/", "../".repeat(depth))
-                                    }
-                                }
-                                Some(ExternalLocation::Remote(ref s)) => {
-                                    format!("{}/std/", s.trim_end_matches('/'))
-                                }
-                                Some(ExternalLocation::Unknown) | None => {
-                                    format!("{}/std/", crate::DOC_RUST_LANG_ORG_CHANNEL)
-                                }
-                            };
-                            // This is a primitive so the url is done "by hand".
-                            let tail = fragment.find('#').unwrap_or_else(|| fragment.len());
-                            Some(RenderedLink {
-                                original_text: s.clone(),
-                                new_text: link_text.clone(),
-                                href: format!(
-                                    "{}primitive.{}.html{}",
-                                    url,
-                                    &fragment[..tail],
-                                    &fragment[tail..]
-                                ),
-                            })
-                        } else {
-                            panic!("This isn't a primitive?!");
-                        }
+                debug!(?did);
+                if let Ok((mut href, ..)) = href(*did, cx) {
+                    debug!(?href);
+                    if let Some(ref fragment) = *fragment {
+                        href.push('#');
+                        href.push_str(fragment);
                     }
+                    Some(RenderedLink {
+                        original_text: s.clone(),
+                        new_text: link_text.clone(),
+                        href,
+                    })
+                } else {
+                    None
                 }
             })
             .collect()
@@ -531,18 +492,10 @@ impl Item {
             .get(&self.def_id)
             .map_or(&[][..], |v| v.as_slice())
             .iter()
-            .filter_map(|ItemLink { link: s, link_text, did, fragment }| {
-                // FIXME(83083): using fragments as a side-channel for
-                // primitive names is very unfortunate
-                if did.is_some() || fragment.is_some() {
-                    Some(RenderedLink {
-                        original_text: s.clone(),
-                        new_text: link_text.clone(),
-                        href: String::new(),
-                    })
-                } else {
-                    None
-                }
+            .map(|ItemLink { link: s, link_text, .. }| RenderedLink {
+                original_text: s.clone(),
+                new_text: link_text.clone(),
+                href: String::new(),
             })
             .collect()
     }
@@ -963,7 +916,7 @@ crate struct Attributes {
     crate other_attrs: Vec<ast::Attribute>,
 }
 
-#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
 /// A link that has not yet been rendered.
 ///
 /// This link will be turned into a rendered link by [`Item::links`].
@@ -975,7 +928,7 @@ crate struct ItemLink {
     /// This may not be the same as `link` if there was a disambiguator
     /// in an intra-doc link (e.g. \[`fn@f`\])
     pub(crate) link_text: String,
-    pub(crate) did: Option<DefId>,
+    pub(crate) did: DefId,
     /// The url fragment to append to the link
     pub(crate) fragment: Option<String>,
 }
@@ -1158,7 +1111,7 @@ impl GenericBound {
     crate fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
         let did = cx.tcx.require_lang_item(LangItem::Sized, None);
         let empty = cx.tcx.intern_substs(&[]);
-        let path = external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
+        let path = external_path(cx, did, false, vec![], empty);
         inline::record_extern_fqn(cx, did, ItemType::Trait);
         GenericBound::TraitBound(
             PolyTrait {
@@ -1802,6 +1755,39 @@ impl PrimitiveType {
             Never => sym::never,
         }
     }
+
+    /// Returns the DefId of the module with `doc(primitive)` for this primitive type.
+    /// Panics if there is no such module.
+    ///
+    /// This gives precedence to primitives defined in the current crate, and deprioritizes primitives defined in `core`,
+    /// but otherwise, if multiple crates define the same primitive, there is no guarantee of which will be picked.
+    /// In particular, if a crate depends on both `std` and another crate that also defines `doc(primitive)`, then
+    /// it's entirely random whether `std` or the other crate is picked. (no_std crates are usually fine unless multiple dependencies define a primitive.)
+    crate fn primitive_locations(tcx: TyCtxt<'_>) -> &FxHashMap<PrimitiveType, DefId> {
+        static PRIMITIVE_LOCATIONS: OnceCell<FxHashMap<PrimitiveType, DefId>> = OnceCell::new();
+        PRIMITIVE_LOCATIONS.get_or_init(|| {
+            let mut primitive_locations = FxHashMap::default();
+            // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate.
+            // This is a degenerate case that I don't plan to support.
+            for &crate_num in tcx.crates(()) {
+                let e = ExternalCrate { crate_num };
+                let crate_name = e.name(tcx);
+                debug!(?crate_num, ?crate_name);
+                for &(def_id, prim) in &e.primitives(tcx) {
+                    // HACK: try to link to std instead where possible
+                    if crate_name == sym::core && primitive_locations.contains_key(&prim) {
+                        continue;
+                    }
+                    primitive_locations.insert(prim, def_id);
+                }
+            }
+            let local_primitives = ExternalCrate { crate_num: LOCAL_CRATE }.primitives(tcx);
+            for (def_id, prim) in local_primitives {
+                primitive_locations.insert(prim, def_id);
+            }
+            primitive_locations
+        })
+    }
 }
 
 impl From<ast::IntTy> for PrimitiveType {
@@ -2202,7 +2188,6 @@ crate struct ImportSource {
 #[derive(Clone, Debug)]
 crate struct Macro {
     crate source: String,
-    crate imported_from: Option<Symbol>,
 }
 
 #[derive(Clone, Debug)]
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index de2cd60d2ed..b0021d1234c 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -29,10 +29,6 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate {
     let krate = cx.tcx.hir().krate();
     let module = crate::visit_ast::RustdocVisitor::new(cx).visit(krate);
 
-    cx.cache.deref_trait_did = cx.tcx.lang_items().deref_trait();
-    cx.cache.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait();
-    cx.cache.owned_box_did = cx.tcx.lang_items().owned_box();
-
     let mut externs = Vec::new();
     for &cnum in cx.tcx.crates(()).iter() {
         externs.push(ExternalCrate { crate_num: cnum });
@@ -97,7 +93,7 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate {
 
 fn external_generic_args(
     cx: &mut DocContext<'_>,
-    trait_did: Option<DefId>,
+    did: DefId,
     has_self: bool,
     bindings: Vec<TypeBinding>,
     substs: SubstsRef<'_>,
@@ -125,42 +121,38 @@ fn external_generic_args(
         })
         .collect();
 
-    match trait_did {
-        // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
-        Some(did) if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() => {
-            assert!(ty_kind.is_some());
-            let inputs = match ty_kind {
-                Some(ty::Tuple(ref tys)) => tys.iter().map(|t| t.expect_ty().clean(cx)).collect(),
-                _ => return GenericArgs::AngleBracketed { args, bindings },
-            };
-            let output = None;
-            // FIXME(#20299) return type comes from a projection now
-            // match types[1].kind {
-            //     ty::Tuple(ref v) if v.is_empty() => None, // -> ()
-            //     _ => Some(types[1].clean(cx))
-            // };
-            GenericArgs::Parenthesized { inputs, output }
-        }
-        _ => GenericArgs::AngleBracketed { args, bindings },
+    if cx.tcx.fn_trait_kind_from_lang_item(did).is_some() {
+        let inputs = match ty_kind.unwrap() {
+            ty::Tuple(tys) => tys.iter().map(|t| t.expect_ty().clean(cx)).collect(),
+            _ => return GenericArgs::AngleBracketed { args, bindings },
+        };
+        let output = None;
+        // FIXME(#20299) return type comes from a projection now
+        // match types[1].kind {
+        //     ty::Tuple(ref v) if v.is_empty() => None, // -> ()
+        //     _ => Some(types[1].clean(cx))
+        // };
+        GenericArgs::Parenthesized { inputs, output }
+    } else {
+        GenericArgs::AngleBracketed { args, bindings }
     }
 }
 
-// trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
-// from Fn<(A, B,), C> to Fn(A, B) -> C
 pub(super) fn external_path(
     cx: &mut DocContext<'_>,
-    name: Symbol,
-    trait_did: Option<DefId>,
+    did: DefId,
     has_self: bool,
     bindings: Vec<TypeBinding>,
     substs: SubstsRef<'_>,
 ) -> Path {
+    let def_kind = cx.tcx.def_kind(did);
+    let name = cx.tcx.item_name(did);
     Path {
         global: false,
-        res: Res::Err,
+        res: Res::Def(def_kind, did),
         segments: vec![PathSegment {
             name,
-            args: external_generic_args(cx, trait_did, has_self, bindings, substs),
+            args: external_generic_args(cx, did, has_self, bindings, substs),
         }],
     }
 }
@@ -409,8 +401,8 @@ crate fn print_const_expr(tcx: TyCtxt<'_>, body: hir::BodyId) -> String {
 }
 
 /// Given a type Path, resolve it to a Type using the TyCtxt
-crate fn resolve_type(cx: &mut DocContext<'_>, path: Path, id: hir::HirId) -> Type {
-    debug!("resolve_type({:?},{:?})", path, id);
+crate fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type {
+    debug!("resolve_type({:?})", path);
 
     let is_generic = match path.res {
         Res::PrimTy(p) => return Primitive(PrimitiveType::from(p)),
@@ -418,7 +410,7 @@ crate fn resolve_type(cx: &mut DocContext<'_>, path: Path, id: hir::HirId) -> Ty
             return Generic(kw::SelfUpper);
         }
         Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => {
-            return Generic(Symbol::intern(&path.whole_name()));
+            return Generic(path.segments[0].name);
         }
         Res::SelfTy(..) | Res::Def(DefKind::TyParam | DefKind::AssocTy, _) => true,
         _ => false,
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 97930f10699..ac440a39515 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -137,7 +137,7 @@ crate struct Options {
     crate manual_passes: Vec<String>,
     /// Whether to display warnings during doc generation or while gathering doctests. By default,
     /// all non-rustdoc-specific lints are allowed when generating docs.
-    crate display_warnings: bool,
+    crate display_doctest_warnings: bool,
     /// Whether to run the `calculate-doc-coverage` pass, which counts the number of public items
     /// with and without documentation.
     crate show_coverage: bool,
@@ -192,7 +192,7 @@ impl fmt::Debug for Options {
             .field("persist_doctests", &self.persist_doctests)
             .field("default_passes", &self.default_passes)
             .field("manual_passes", &self.manual_passes)
-            .field("display_warnings", &self.display_warnings)
+            .field("display_doctest_warnings", &self.display_doctest_warnings)
             .field("show_coverage", &self.show_coverage)
             .field("crate_version", &self.crate_version)
             .field("render_options", &self.render_options)
@@ -632,7 +632,7 @@ impl Options {
         let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
         let playground_url = matches.opt_str("playground-url");
         let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
-        let display_warnings = matches.opt_present("display-warnings");
+        let display_doctest_warnings = matches.opt_present("display-doctest-warnings");
         let sort_modules_alphabetically = !matches.opt_present("sort-modules-by-appearance");
         let resource_suffix = matches.opt_str("resource-suffix").unwrap_or_default();
         let enable_minification = !matches.opt_present("disable-minification");
@@ -696,7 +696,7 @@ impl Options {
             test_args,
             default_passes,
             manual_passes,
-            display_warnings,
+            display_doctest_warnings,
             show_coverage,
             crate_version,
             test_run_directory,
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index bd1d970fc19..d86b3b785d1 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -204,7 +204,6 @@ crate fn create_config(
         lint_opts,
         describe_lints,
         lint_cap,
-        display_warnings,
         ..
     }: RustdocOptions,
 ) -> rustc_interface::Config {
@@ -237,7 +236,7 @@ crate fn create_config(
         maybe_sysroot,
         search_paths: libs,
         crate_types,
-        lint_opts: if !display_warnings { lint_opts } else { vec![] },
+        lint_opts,
         lint_cap,
         cg: codegen_options,
         externs,
diff --git a/src/librustdoc/docfs.rs b/src/librustdoc/docfs.rs
index 9b740acfcdf..a5fab1b3d42 100644
--- a/src/librustdoc/docfs.rs
+++ b/src/librustdoc/docfs.rs
@@ -11,7 +11,7 @@
 
 use std::fs;
 use std::io;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 use std::string::ToString;
 use std::sync::mpsc::Sender;
 
@@ -55,17 +55,17 @@ impl DocFS {
         fs::create_dir_all(path)
     }
 
-    crate fn write<P, C, E>(&self, path: P, contents: C) -> Result<(), E>
+    crate fn write<E>(
+        &self,
+        path: PathBuf,
+        contents: impl 'static + Send + AsRef<[u8]>,
+    ) -> Result<(), E>
     where
-        P: AsRef<Path>,
-        C: AsRef<[u8]>,
         E: PathError,
     {
         if !self.sync_only && cfg!(windows) {
             // A possible future enhancement after more detailed profiling would
             // be to create the file sync so errors are reported eagerly.
-            let path = path.as_ref().to_path_buf();
-            let contents = contents.as_ref().to_vec();
             let sender = self.errors.clone().expect("can't write after closing");
             rayon::spawn(move || {
                 fs::write(&path, contents).unwrap_or_else(|e| {
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index e6097f5cad7..dbeea9cddf3 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -40,7 +40,7 @@ crate struct TestOptions {
     crate no_crate_inject: bool,
     /// Whether to emit compilation warnings when compiling doctests. Setting this will suppress
     /// the default `#![allow(unused)]`.
-    crate display_warnings: bool,
+    crate display_doctest_warnings: bool,
     /// Additional crate-level attributes to add to doctests.
     crate attrs: Vec<String>,
 }
@@ -72,8 +72,8 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
         maybe_sysroot: options.maybe_sysroot.clone(),
         search_paths: options.libs.clone(),
         crate_types,
-        lint_opts: if !options.display_warnings { lint_opts } else { vec![] },
-        lint_cap: Some(options.lint_cap.clone().unwrap_or_else(|| lint::Forbid)),
+        lint_opts: if !options.display_doctest_warnings { lint_opts } else { vec![] },
+        lint_cap: Some(options.lint_cap.unwrap_or_else(|| lint::Forbid)),
         cg: options.codegen_options.clone(),
         externs: options.externs.clone(),
         unstable_features: options.render_options.unstable_features,
@@ -106,7 +106,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
     };
 
     let test_args = options.test_args.clone();
-    let display_warnings = options.display_warnings;
+    let display_doctest_warnings = options.display_doctest_warnings;
     let nocapture = options.nocapture;
     let externs = options.externs.clone();
     let json_unused_externs = options.json_unused_externs;
@@ -119,7 +119,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
                 let crate_attrs = tcx.hir().attrs(CRATE_HIR_ID);
 
                 let mut opts = scrape_test_config(crate_attrs);
-                opts.display_warnings |= options.display_warnings;
+                opts.display_doctest_warnings |= options.display_doctest_warnings;
                 let enable_per_target_ignores = options.enable_per_target_ignores;
                 let mut collector = Collector::new(
                     tcx.crate_name(LOCAL_CRATE),
@@ -163,7 +163,7 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
         Err(ErrorReported) => return Err(ErrorReported),
     };
 
-    run_tests(test_args, nocapture, display_warnings, tests);
+    run_tests(test_args, nocapture, display_doctest_warnings, tests);
 
     // Collect and warn about unused externs, but only if we've gotten
     // reports for each doctest
@@ -209,14 +209,18 @@ crate fn run(options: Options) -> Result<(), ErrorReported> {
 crate fn run_tests(
     mut test_args: Vec<String>,
     nocapture: bool,
-    display_warnings: bool,
+    display_doctest_warnings: bool,
     tests: Vec<test::TestDescAndFn>,
 ) {
     test_args.insert(0, "rustdoctest".to_string());
     if nocapture {
         test_args.push("--nocapture".to_string());
     }
-    test::test_main(&test_args, tests, Some(test::Options::new().display_output(display_warnings)));
+    test::test_main(
+        &test_args,
+        tests,
+        Some(test::Options::new().display_output(display_doctest_warnings)),
+    );
 }
 
 // Look for `#![doc(test(no_crate_inject))]`, used by crates in the std facade.
@@ -224,7 +228,7 @@ fn scrape_test_config(attrs: &[ast::Attribute]) -> TestOptions {
     use rustc_ast_pretty::pprust;
 
     let mut opts =
-        TestOptions { no_crate_inject: false, display_warnings: false, attrs: Vec::new() };
+        TestOptions { no_crate_inject: false, display_doctest_warnings: false, attrs: Vec::new() };
 
     let test_attrs: Vec<_> = attrs
         .iter()
@@ -504,7 +508,7 @@ crate fn make_test(
     let mut prog = String::new();
     let mut supports_color = false;
 
-    if opts.attrs.is_empty() && !opts.display_warnings {
+    if opts.attrs.is_empty() && !opts.display_doctest_warnings {
         // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some
         // lints that are commonly triggered in doctests. The crate-level test attributes are
         // commonly used to make tests fail in case they trigger warnings, so having this there in
diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs
index c49e45c0e25..18517080965 100644
--- a/src/librustdoc/doctest/tests.rs
+++ b/src/librustdoc/doctest/tests.rs
@@ -52,7 +52,8 @@ assert_eq!(2+2, 4);
 fn make_test_no_crate_inject() {
     // Even if you do use the crate within the test, setting `opts.no_crate_inject` will skip
     // adding it anyway.
-    let opts = TestOptions { no_crate_inject: true, display_warnings: false, attrs: vec![] };
+    let opts =
+        TestOptions { no_crate_inject: true, display_doctest_warnings: false, attrs: vec![] };
     let input = "use asdf::qwop;
 assert_eq!(2+2, 4);";
     let expected = "#![allow(unused)]
@@ -215,10 +216,10 @@ assert_eq!(2+2, 4);"
 }
 
 #[test]
-fn make_test_display_warnings() {
+fn make_test_display_doctest_warnings() {
     // If the user is asking to display doctest warnings, suppress the default `allow(unused)`.
     let mut opts = TestOptions::default();
-    opts.display_warnings = true;
+    opts.display_doctest_warnings = true;
     let input = "assert_eq!(2+2, 4);";
     let expected = "fn main() {
 assert_eq!(2+2, 4);
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index 1830909d944..bcfcc3d7039 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -6,7 +6,7 @@ use rustc_middle::middle::privacy::AccessLevels;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::sym;
 
-use crate::clean::{self, GetDefId, ItemId};
+use crate::clean::{self, GetDefId, ItemId, PrimitiveType};
 use crate::config::RenderOptions;
 use crate::fold::DocFolder;
 use crate::formats::item_type::ItemType;
@@ -98,9 +98,6 @@ crate struct Cache {
     stripped_mod: bool,
 
     crate search_index: Vec<IndexItem>,
-    crate deref_trait_did: Option<DefId>,
-    crate deref_mut_trait_did: Option<DefId>,
-    crate owned_box_did: Option<DefId>,
 
     // In rare case where a structure is defined in one module but implemented
     // in another, if the implementing module is parsed before defining module,
@@ -159,17 +156,16 @@ impl Cache {
             self.external_paths.insert(e.def_id(), (vec![name.to_string()], ItemType::Module));
         }
 
-        // Cache where all known primitives have their documentation located.
-        //
-        // Favor linking to as local extern as possible, so iterate all crates in
-        // reverse topological order.
-        for &e in krate.externs.iter().rev() {
-            for &(def_id, prim) in &e.primitives(tcx) {
-                self.primitive_locations.insert(prim, def_id);
-            }
-        }
-        for &(def_id, prim) in &krate.primitives {
-            self.primitive_locations.insert(prim, def_id);
+        // FIXME: avoid this clone (requires implementing Default manually)
+        self.primitive_locations = PrimitiveType::primitive_locations(tcx).clone();
+        for (prim, &def_id) in &self.primitive_locations {
+            let crate_name = tcx.crate_name(def_id.krate);
+            // Recall that we only allow primitive modules to be at the root-level of the crate.
+            // If that restriction is ever lifted, this will have to include the relative paths instead.
+            self.external_paths.insert(
+                def_id,
+                (vec![crate_name.to_string(), prim.as_sym().to_string()], ItemType::Primitive),
+            );
         }
 
         krate = CacheBuilder { tcx, cache: self }.fold_crate(krate);
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index ea045803489..2fde0017dc8 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -509,7 +509,11 @@ crate fn href_with_root_path(
         if shortty == ItemType::Module { fqp } else { &fqp[..fqp.len() - 1] }
     }
 
-    if !did.is_local() && !cache.access_levels.is_public(did) && !cache.document_private {
+    if !did.is_local()
+        && !cache.access_levels.is_public(did)
+        && !cache.document_private
+        && !cache.primitive_locations.values().any(|&id| id == did)
+    {
         return Err(HrefError::Private);
     }
 
@@ -517,6 +521,7 @@ crate fn href_with_root_path(
     let (fqp, shortty, mut url_parts) = match cache.paths.get(&did) {
         Some(&(ref fqp, shortty)) => (fqp, shortty, {
             let module_fqp = to_module_fqp(shortty, fqp);
+            debug!(?fqp, ?shortty, ?module_fqp);
             href_relative_parts(module_fqp, relative_to)
         }),
         None => {
@@ -548,6 +553,7 @@ crate fn href_with_root_path(
             url_parts.insert(0, root);
         }
     }
+    debug!(?url_parts);
     let last = &fqp.last().unwrap()[..];
     let filename;
     match shortty {
@@ -742,7 +748,7 @@ fn fmt_type<'cx>(
     use_absolute: bool,
     cx: &'cx Context<'_>,
 ) -> fmt::Result {
-    debug!("fmt_type(t = {:?})", t);
+    trace!("fmt_type(t = {:?})", t);
 
     match *t {
         clean::Generic(name) => write!(f, "{}", name),
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index f8fc9243e14..ece3ee640e2 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -5,6 +5,7 @@
 //!
 //! Use the `render_with_highlighting` to highlight some rust code.
 
+use crate::clean::PrimitiveType;
 use crate::html::escape::Escape;
 use crate::html::render::Context;
 
@@ -584,6 +585,13 @@ fn string<T: Display>(
                             .ok()
                             .map(|(url, _, _)| url)
                     }
+                    LinkFromSrc::Primitive(prim) => format::href_with_root_path(
+                        PrimitiveType::primitive_locations(context.tcx())[&prim],
+                        context,
+                        Some(context_info.root_path),
+                    )
+                    .ok()
+                    .map(|(url, _, _)| url),
                 }
             })
         {
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index aa3723eddfc..c971e231463 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -48,7 +48,7 @@ use pulldown_cmark::{
 mod tests;
 
 /// Options for rendering Markdown in the main body of documentation.
-pub(crate) fn opts() -> Options {
+pub(crate) fn main_body_opts() -> Options {
     Options::ENABLE_TABLES
         | Options::ENABLE_FOOTNOTES
         | Options::ENABLE_STRIKETHROUGH
@@ -56,9 +56,13 @@ pub(crate) fn opts() -> Options {
         | Options::ENABLE_SMART_PUNCTUATION
 }
 
-/// A subset of [`opts()`] used for rendering summaries.
+/// Options for rendering Markdown in summaries (e.g., in search results).
 pub(crate) fn summary_opts() -> Options {
-    Options::ENABLE_STRIKETHROUGH | Options::ENABLE_SMART_PUNCTUATION | Options::ENABLE_TABLES
+    Options::ENABLE_TABLES
+        | Options::ENABLE_FOOTNOTES
+        | Options::ENABLE_STRIKETHROUGH
+        | Options::ENABLE_TASKLISTS
+        | Options::ENABLE_SMART_PUNCTUATION
 }
 
 /// When `to_string` is called, this struct will emit the HTML corresponding to
@@ -441,6 +445,42 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
     }
 }
 
+/// Wrap HTML tables into `<div>` to prevent having the doc blocks width being too big.
+struct TableWrapper<'a, I: Iterator<Item = Event<'a>>> {
+    inner: I,
+    stored_events: VecDeque<Event<'a>>,
+}
+
+impl<'a, I: Iterator<Item = Event<'a>>> TableWrapper<'a, I> {
+    fn new(iter: I) -> Self {
+        Self { inner: iter, stored_events: VecDeque::new() }
+    }
+}
+
+impl<'a, I: Iterator<Item = Event<'a>>> Iterator for TableWrapper<'a, I> {
+    type Item = Event<'a>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        if let Some(first) = self.stored_events.pop_front() {
+            return Some(first);
+        }
+
+        let event = self.inner.next()?;
+
+        Some(match event {
+            Event::Start(Tag::Table(t)) => {
+                self.stored_events.push_back(Event::Start(Tag::Table(t)));
+                Event::Html(CowStr::Borrowed("<div>"))
+            }
+            Event::End(Tag::Table(t)) => {
+                self.stored_events.push_back(Event::Html(CowStr::Borrowed("</div>")));
+                Event::End(Tag::Table(t))
+            }
+            e => e,
+        })
+    }
+}
+
 type SpannedEvent<'a> = (Event<'a>, Range<usize>);
 
 /// Make headings links with anchor IDs and build up TOC.
@@ -692,6 +732,12 @@ crate fn find_testable_code<T: doctest::Tester>(
                     .join("\n");
 
                 nb_lines += doc[prev_offset..offset.start].lines().count();
+                // If there are characters between the preceding line ending and
+                // this code block, `str::lines` will return an additional line,
+                // which we subtract here.
+                if nb_lines != 0 && !&doc[prev_offset..offset.start].ends_with("\n") {
+                    nb_lines -= 1;
+                }
                 let line = tests.get_line() + nb_lines + 1;
                 tests.add_test(text, block_info, line);
                 prev_offset = offset.start;
@@ -975,7 +1021,7 @@ impl Markdown<'_> {
             }
         };
 
-        let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut replacer));
+        let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(&mut replacer));
         let p = p.into_offset_iter();
 
         let mut s = String::with_capacity(md.len() * 3 / 2);
@@ -983,6 +1029,7 @@ impl Markdown<'_> {
         let p = HeadingLinks::new(p, None, &mut ids);
         let p = Footnotes::new(p);
         let p = LinkReplacer::new(p.map(|(ev, _)| ev), links);
+        let p = TableWrapper::new(p);
         let p = CodeBlocks::new(p, codes, edition, playground);
         html::push_html(&mut s, p);
 
@@ -994,7 +1041,7 @@ impl MarkdownWithToc<'_> {
     crate fn into_string(self) -> String {
         let MarkdownWithToc(md, mut ids, codes, edition, playground) = self;
 
-        let p = Parser::new_ext(md, opts()).into_offset_iter();
+        let p = Parser::new_ext(md, main_body_opts()).into_offset_iter();
 
         let mut s = String::with_capacity(md.len() * 3 / 2);
 
@@ -1003,7 +1050,8 @@ impl MarkdownWithToc<'_> {
         {
             let p = HeadingLinks::new(p, Some(&mut toc), &mut ids);
             let p = Footnotes::new(p);
-            let p = CodeBlocks::new(p.map(|(ev, _)| ev), codes, edition, playground);
+            let p = TableWrapper::new(p.map(|(ev, _)| ev));
+            let p = CodeBlocks::new(p, codes, edition, playground);
             html::push_html(&mut s, p);
         }
 
@@ -1019,7 +1067,7 @@ impl MarkdownHtml<'_> {
         if md.is_empty() {
             return String::new();
         }
-        let p = Parser::new_ext(md, opts()).into_offset_iter();
+        let p = Parser::new_ext(md, main_body_opts()).into_offset_iter();
 
         // Treat inline HTML as plain text.
         let p = p.map(|event| match event.0 {
@@ -1031,7 +1079,8 @@ impl MarkdownHtml<'_> {
 
         let p = HeadingLinks::new(p, None, &mut ids);
         let p = Footnotes::new(p);
-        let p = CodeBlocks::new(p.map(|(ev, _)| ev), codes, edition, playground);
+        let p = TableWrapper::new(p.map(|(ev, _)| ev));
+        let p = CodeBlocks::new(p, codes, edition, playground);
         html::push_html(&mut s, p);
 
         s
@@ -1093,7 +1142,7 @@ fn markdown_summary_with_limit(
         }
     };
 
-    let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut replacer));
+    let p = Parser::new_with_broken_link_callback(md, summary_opts(), Some(&mut replacer));
     let mut p = LinkReplacer::new(p, link_names);
 
     let mut buf = HtmlWithLimit::new(length_limit);
@@ -1240,7 +1289,8 @@ crate fn markdown_links(md: &str) -> Vec<MarkdownLink> {
         });
         None
     };
-    let p = Parser::new_with_broken_link_callback(md, opts(), Some(&mut push)).into_offset_iter();
+    let p = Parser::new_with_broken_link_callback(md, main_body_opts(), Some(&mut push))
+        .into_offset_iter();
 
     // There's no need to thread an IdMap through to here because
     // the IDs generated aren't going to be emitted anywhere.
@@ -1279,7 +1329,7 @@ crate fn rust_code_blocks(md: &str, extra_info: &ExtraInfo<'_>) -> Vec<RustCodeB
         return code_blocks;
     }
 
-    let mut p = Parser::new_ext(md, opts()).into_offset_iter();
+    let mut p = Parser::new_ext(md, main_body_opts()).into_offset_iter();
 
     while let Some((event, offset)) = p.next() {
         if let Event::Start(Tag::CodeBlock(syntax)) = event {
diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs
index eca75ef013a..1e4cf3381f6 100644
--- a/src/librustdoc/html/markdown/tests.rs
+++ b/src/librustdoc/html/markdown/tests.rs
@@ -1,4 +1,4 @@
-use super::{plain_text_summary, short_markdown_summary};
+use super::{find_testable_code, plain_text_summary, short_markdown_summary};
 use super::{ErrorCodes, IdMap, Ignore, LangString, Markdown, MarkdownHtml};
 use rustc_span::edition::{Edition, DEFAULT_EDITION};
 
@@ -300,3 +300,25 @@ fn test_markdown_html_escape() {
     t("Struct<'a, T>", "<p>Struct&lt;’a, T&gt;</p>\n");
     t("Struct<br>", "<p>Struct&lt;br&gt;</p>\n");
 }
+
+#[test]
+fn test_find_testable_code_line() {
+    fn t(input: &str, expect: &[usize]) {
+        impl crate::doctest::Tester for Vec<usize> {
+            fn add_test(&mut self, _test: String, _config: LangString, line: usize) {
+                self.push(line);
+            }
+        }
+        let mut lines = Vec::<usize>::new();
+        find_testable_code(input, &mut lines, ErrorCodes::No, false, None);
+        assert_eq!(lines, expect);
+    }
+
+    t("", &[]);
+    t("```rust\n```", &[1]);
+    t(" ```rust\n```", &[1]);
+    t("\n```rust\n```", &[2]);
+    t("\n ```rust\n```", &[2]);
+    t("```rust\n```\n```rust\n```", &[1, 3]);
+    t("```rust\n```\n ```rust\n```", &[1, 3]);
+}
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 733bedfdde9..b99d2fe5aa0 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -69,7 +69,7 @@ crate struct Context<'tcx> {
 }
 
 // `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
-#[cfg(target_arch = "x86_64")]
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 rustc_data_structures::static_assert_size!(Context<'_>, 104);
 
 /// Shared mutable state used in [`Context`] and elsewhere.
@@ -574,7 +574,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             |buf: &mut Buffer| all.print(buf),
             &self.shared.style_files,
         );
-        self.shared.fs.write(final_file, v.as_bytes())?;
+        self.shared.fs.write(final_file, v)?;
 
         // Generating settings page.
         page.title = "Rustdoc settings";
@@ -596,14 +596,14 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             )?,
             &style_files,
         );
-        self.shared.fs.write(&settings_file, v.as_bytes())?;
+        self.shared.fs.write(settings_file, v)?;
         if let Some(ref redirections) = self.shared.redirections {
             if !redirections.borrow().is_empty() {
                 let redirect_map_path =
                     self.dst.join(&*crate_name.as_str()).join("redirect-map.json");
                 let paths = serde_json::to_string(&*redirections.borrow()).unwrap();
                 self.shared.ensure_dir(&self.dst.join(&*crate_name.as_str()))?;
-                self.shared.fs.write(&redirect_map_path, paths.as_bytes())?;
+                self.shared.fs.write(redirect_map_path, paths)?;
             }
         }
 
@@ -641,7 +641,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         if !buf.is_empty() {
             self.shared.ensure_dir(&self.dst)?;
             let joint_dst = self.dst.join("index.html");
-            scx.fs.write(&joint_dst, buf.as_bytes())?;
+            scx.fs.write(joint_dst, buf)?;
         }
 
         // Render sidebar-items.js used throughout this module.
@@ -653,7 +653,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             let items = self.build_sidebar_items(module);
             let js_dst = self.dst.join("sidebar-items.js");
             let v = format!("initSidebarItems({});", serde_json::to_string(&items).unwrap());
-            scx.fs.write(&js_dst, &v)?;
+            scx.fs.write(js_dst, v)?;
         }
         Ok(())
     }
@@ -687,7 +687,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             let file_name = &item_path(item_type, &name.as_str());
             self.shared.ensure_dir(&self.dst)?;
             let joint_dst = self.dst.join(file_name);
-            self.shared.fs.write(&joint_dst, buf.as_bytes())?;
+            self.shared.fs.write(joint_dst, buf)?;
 
             if !self.render_redirect_pages {
                 self.shared.all.borrow_mut().append(full_path(self, &item), &item_type);
@@ -705,7 +705,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
                 } else {
                     let v = layout::redirect(file_name);
                     let redir_dst = self.dst.join(redir_name);
-                    self.shared.fs.write(&redir_dst, v.as_bytes())?;
+                    self.shared.fs.write(redir_dst, v)?;
                 }
             }
         }
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 172fe5d164b..1f27357f6c6 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -51,6 +51,7 @@ use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::Mutability;
 use rustc_middle::middle::stability;
+use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::{kw, sym, Symbol};
 use serde::ser::SerializeSeq;
 use serde::{Serialize, Serializer};
@@ -224,7 +225,6 @@ struct AllTypes {
     opaque_tys: FxHashSet<ItemEntry>,
     statics: FxHashSet<ItemEntry>,
     constants: FxHashSet<ItemEntry>,
-    keywords: FxHashSet<ItemEntry>,
     attributes: FxHashSet<ItemEntry>,
     derives: FxHashSet<ItemEntry>,
     trait_aliases: FxHashSet<ItemEntry>,
@@ -245,7 +245,6 @@ impl AllTypes {
             opaque_tys: new_set(100),
             statics: new_set(100),
             constants: new_set(100),
-            keywords: new_set(100),
             attributes: new_set(100),
             derives: new_set(100),
             trait_aliases: new_set(100),
@@ -1069,13 +1068,13 @@ fn render_assoc_items(
         return;
     }
     if !traits.is_empty() {
-        let deref_impl = traits
-            .iter()
-            .find(|t| t.inner_impl().trait_.def_id_full(cache) == cache.deref_trait_did);
+        let deref_impl = traits.iter().find(|t| {
+            t.inner_impl().trait_.def_id_full(cache) == cx.tcx().lang_items().deref_trait()
+        });
         if let Some(impl_) = deref_impl {
-            let has_deref_mut = traits
-                .iter()
-                .any(|t| t.inner_impl().trait_.def_id_full(cache) == cache.deref_mut_trait_did);
+            let has_deref_mut = traits.iter().any(|t| {
+                t.inner_impl().trait_.def_id_full(cache) == cx.tcx().lang_items().deref_mut_trait()
+            });
             render_deref_methods(w, cx, impl_, containing_item, has_deref_mut);
         }
         let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) =
@@ -1165,7 +1164,7 @@ fn render_deref_methods(
     }
 }
 
-fn should_render_item(item: &clean::Item, deref_mut_: bool, cache: &Cache) -> bool {
+fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> bool {
     let self_type_opt = match *item.kind {
         clean::MethodItem(ref method, _) => method.decl.self_type(),
         clean::TyMethodItem(ref method) => method.decl.self_type(),
@@ -1179,7 +1178,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, cache: &Cache) -> bo
                 (mutability == Mutability::Mut, false, false)
             }
             SelfTy::SelfExplicit(clean::ResolvedPath { did, .. }) => {
-                (false, Some(did) == cache.owned_box_did, false)
+                (false, Some(did) == tcx.lang_items().owned_box(), false)
             }
             SelfTy::SelfValue => (false, false, true),
             _ => (false, false, false),
@@ -1302,7 +1301,7 @@ fn render_impl(
             && match render_mode {
                 RenderMode::Normal => true,
                 RenderMode::ForDeref { mut_: deref_mut_ } => {
-                    should_render_item(&item, deref_mut_, cx.cache())
+                    should_render_item(&item, deref_mut_, cx.tcx())
                 }
             };
 
@@ -1800,13 +1799,13 @@ fn get_methods(
     for_deref: bool,
     used_links: &mut FxHashSet<String>,
     deref_mut: bool,
-    cache: &Cache,
+    tcx: TyCtxt<'_>,
 ) -> Vec<String> {
     i.items
         .iter()
         .filter_map(|item| match item.name {
             Some(ref name) if !name.is_empty() && item.is_method() => {
-                if !for_deref || should_render_item(item, deref_mut, cache) {
+                if !for_deref || should_render_item(item, deref_mut, tcx) {
                     Some(format!(
                         "<a href=\"#{}\">{}</a>",
                         get_next_url(used_links, format!("method.{}", name)),
@@ -1868,7 +1867,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
             let mut ret = v
                 .iter()
                 .filter(|i| i.inner_impl().trait_.is_none())
-                .flat_map(move |i| get_methods(i.inner_impl(), false, used_links_bor, false, cache))
+                .flat_map(move |i| {
+                    get_methods(i.inner_impl(), false, used_links_bor, false, cx.tcx())
+                })
                 .collect::<Vec<_>>();
             if !ret.is_empty() {
                 // We want links' order to be reproducible so we don't use unstable sort.
@@ -1886,11 +1887,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
         }
 
         if v.iter().any(|i| i.inner_impl().trait_.is_some()) {
-            if let Some(impl_) = v
-                .iter()
-                .filter(|i| i.inner_impl().trait_.is_some())
-                .find(|i| i.inner_impl().trait_.def_id_full(cache) == cache.deref_trait_did)
-            {
+            if let Some(impl_) = v.iter().filter(|i| i.inner_impl().trait_.is_some()).find(|i| {
+                i.inner_impl().trait_.def_id_full(cache) == cx.tcx().lang_items().deref_trait()
+            }) {
                 sidebar_deref_methods(cx, out, impl_, v);
             }
 
@@ -1988,10 +1987,9 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
                 }
             }
         }
-        let deref_mut = v
-            .iter()
-            .filter(|i| i.inner_impl().trait_.is_some())
-            .any(|i| i.inner_impl().trait_.def_id_full(c) == c.deref_mut_trait_did);
+        let deref_mut = v.iter().filter(|i| i.inner_impl().trait_.is_some()).any(|i| {
+            i.inner_impl().trait_.def_id_full(c) == cx.tcx().lang_items().deref_mut_trait()
+        });
         let inner_impl = target
             .def_id_full(c)
             .or_else(|| {
@@ -2004,7 +2002,9 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
             let mut ret = impls
                 .iter()
                 .filter(|i| i.inner_impl().trait_.is_none())
-                .flat_map(|i| get_methods(i.inner_impl(), true, &mut used_links, deref_mut, c))
+                .flat_map(|i| {
+                    get_methods(i.inner_impl(), true, &mut used_links, deref_mut, cx.tcx())
+                })
                 .collect::<Vec<_>>();
             if !ret.is_empty() {
                 write!(
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 39ef641a3ac..52505f2d634 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -8,10 +8,12 @@ use rustc_hir as hir;
 use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::DefId;
 use rustc_middle::middle::stability;
+use rustc_middle::span_bug;
 use rustc_middle::ty::layout::LayoutError;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{Adt, TyCtxt};
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_target::abi::{Layout, Primitive, TagEncoding, Variants};
 
 use super::{
     collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_strs, notable_traits_decl,
@@ -254,6 +256,10 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
 
     debug!("{:?}", indices);
     let mut curty = None;
+    // See: https://github.com/rust-lang/rust/issues/88545
+    let item_table_block_size = 900usize;
+    let mut item_table_nth_element = 0usize;
+
     for &idx in &indices {
         let myitem = &items[idx];
         if myitem.is_stripped() {
@@ -273,11 +279,13 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
             write!(
                 w,
                 "<h2 id=\"{id}\" class=\"section-header\">\
-                       <a href=\"#{id}\">{name}</a></h2>\n{}",
+                    <a href=\"#{id}\">{name}</a>\
+                 </h2>\n{}",
                 ITEM_TABLE_OPEN,
                 id = cx.derive_id(short.to_owned()),
                 name = name
             );
+            item_table_nth_element = 0;
         }
 
         match *myitem.kind {
@@ -384,6 +392,13 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
                 );
             }
         }
+
+        item_table_nth_element += 1;
+        if item_table_nth_element > item_table_block_size {
+            w.write_str(ITEM_TABLE_CLOSE);
+            w.write_str(ITEM_TABLE_OPEN);
+            item_table_nth_element = 0;
+        }
     }
 
     if curty.is_some() {
@@ -942,15 +957,15 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
 }
 
 fn print_tuple_struct_fields(w: &mut Buffer, cx: &Context<'_>, s: &[clean::Item]) {
-    for (i, ty) in s
-        .iter()
-        .map(|f| if let clean::StructFieldItem(ref ty) = *f.kind { ty } else { unreachable!() })
-        .enumerate()
-    {
+    for (i, ty) in s.iter().enumerate() {
         if i > 0 {
             w.write_str(",&nbsp;");
         }
-        write!(w, "{}", ty.print(cx));
+        match *ty.kind {
+            clean::StrippedItem(box clean::StructFieldItem(_)) => w.write_str("_"),
+            clean::StructFieldItem(ref ty) => write!(w, "{}", ty.print(cx)),
+            _ => unreachable!(),
+        }
     }
 }
 
@@ -1066,24 +1081,27 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                     name = variant.name.as_ref().unwrap(),
                 );
                 for field in fields {
-                    use crate::clean::StructFieldItem;
-                    if let StructFieldItem(ref ty) = *field.kind {
-                        let id = cx.derive_id(format!(
-                            "variant.{}.field.{}",
-                            variant.name.as_ref().unwrap(),
-                            field.name.as_ref().unwrap()
-                        ));
-                        write!(
-                            w,
-                            "<span id=\"{id}\" class=\"variant small-section-header\">\
-                                 <a href=\"#{id}\" class=\"anchor field\"></a>\
-                                 <code>{f}:&nbsp;{t}</code>\
-                             </span>",
-                            id = id,
-                            f = field.name.as_ref().unwrap(),
-                            t = ty.print(cx)
-                        );
-                        document(w, cx, field, Some(variant));
+                    match *field.kind {
+                        clean::StrippedItem(box clean::StructFieldItem(_)) => {}
+                        clean::StructFieldItem(ref ty) => {
+                            let id = cx.derive_id(format!(
+                                "variant.{}.field.{}",
+                                variant.name.as_ref().unwrap(),
+                                field.name.as_ref().unwrap()
+                            ));
+                            write!(
+                                w,
+                                "<span id=\"{id}\" class=\"variant small-section-header\">\
+                                    <a href=\"#{id}\" class=\"anchor field\"></a>\
+                                    <code>{f}:&nbsp;{t}</code>\
+                                </span>",
+                                id = id,
+                                f = field.name.as_ref().unwrap(),
+                                t = ty.print(cx)
+                            );
+                            document(w, cx, field, Some(variant));
+                        }
+                        _ => unreachable!(),
                     }
                 }
                 w.write_str("</div></div>");
@@ -1621,6 +1639,15 @@ fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) {
 }
 
 fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
+    fn write_size_of_layout(w: &mut Buffer, layout: &Layout, tag_size: u64) {
+        if layout.abi.is_unsized() {
+            write!(w, "(unsized)");
+        } else {
+            let bytes = layout.size.bytes() - tag_size;
+            write!(w, "{size} byte{pl}", size = bytes, pl = if bytes == 1 { "" } else { "s" },);
+        }
+    }
+
     if !cx.shared.show_type_layout {
         return;
     }
@@ -1642,16 +1669,40 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
                  <a href=\"https://doc.rust-lang.org/reference/type-layout.html\">“Type Layout”</a> \
                  chapter for details on type layout guarantees.</p></div>"
             );
-            if ty_layout.layout.abi.is_unsized() {
-                writeln!(w, "<p><strong>Size:</strong> (unsized)</p>");
-            } else {
-                let bytes = ty_layout.layout.size.bytes();
-                writeln!(
-                    w,
-                    "<p><strong>Size:</strong> {size} byte{pl}</p>",
-                    size = bytes,
-                    pl = if bytes == 1 { "" } else { "s" },
-                );
+            w.write_str("<p><strong>Size:</strong> ");
+            write_size_of_layout(w, ty_layout.layout, 0);
+            writeln!(w, "</p>");
+            if let Variants::Multiple { variants, tag, tag_encoding, .. } =
+                &ty_layout.layout.variants
+            {
+                if !variants.is_empty() {
+                    w.write_str(
+                        "<p><strong>Size for each variant:</strong></p>\
+                            <ul>",
+                    );
+
+                    let adt = if let Adt(adt, _) = ty_layout.ty.kind() {
+                        adt
+                    } else {
+                        span_bug!(tcx.def_span(ty_def_id), "not an adt")
+                    };
+
+                    let tag_size = if let TagEncoding::Niche { .. } = tag_encoding {
+                        0
+                    } else if let Primitive::Int(i, _) = tag.value {
+                        i.size().bytes()
+                    } else {
+                        span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int")
+                    };
+
+                    for (index, layout) in variants.iter_enumerated() {
+                        let ident = adt.variants[index].ident;
+                        write!(w, "<li><code>{name}</code>: ", name = ident);
+                        write_size_of_layout(w, layout, tag_size);
+                        writeln!(w, "</li>");
+                    }
+                    w.write_str("</ul>");
+                }
             }
         }
         // This kind of layout error can occur with valid code, e.g. if you try to
diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs
index 54476d9c9a4..d517f3ac0e3 100644
--- a/src/librustdoc/html/render/span_map.rs
+++ b/src/librustdoc/html/render/span_map.rs
@@ -1,4 +1,4 @@
-use crate::clean;
+use crate::clean::{self, PrimitiveType};
 use crate::html::sources;
 
 use rustc_data_structures::fx::FxHashMap;
@@ -22,6 +22,7 @@ use std::path::{Path, PathBuf};
 crate enum LinkFromSrc {
     Local(clean::Span),
     External(DefId),
+    Primitive(PrimitiveType),
 }
 
 /// This function will do at most two things:
@@ -73,17 +74,20 @@ impl<'tcx> SpanMapVisitor<'tcx> {
                 Some(def_id)
             }
             Res::Local(_) => None,
+            Res::PrimTy(p) => {
+                // FIXME: Doesn't handle "path-like" primitives like arrays or tuples.
+                let span = path_span.unwrap_or(path.span);
+                self.matches.insert(span, LinkFromSrc::Primitive(PrimitiveType::from(p)));
+                return;
+            }
             Res::Err => return,
             _ => return,
         };
         if let Some(span) = self.tcx.hir().res_span(path.res) {
-            self.matches.insert(
-                path_span.unwrap_or_else(|| path.span),
-                LinkFromSrc::Local(clean::Span::new(span)),
-            );
-        } else if let Some(def_id) = info {
             self.matches
-                .insert(path_span.unwrap_or_else(|| path.span), LinkFromSrc::External(def_id));
+                .insert(path_span.unwrap_or(path.span), LinkFromSrc::Local(clean::Span::new(span)));
+        } else if let Some(def_id) = info {
+            self.matches.insert(path_span.unwrap_or(path.span), LinkFromSrc::External(def_id));
         }
     }
 }
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index 99cd98f7eae..1dd0917699b 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -105,10 +105,10 @@ impl Context<'_> {
         self.dst.join(&filename)
     }
 
-    fn write_shared<C: AsRef<[u8]>>(
+    fn write_shared(
         &self,
         resource: SharedResource<'_>,
-        contents: C,
+        contents: impl 'static + Send + AsRef<[u8]>,
         emit: &[EmitType],
     ) -> Result<(), Error> {
         if resource.should_emit(emit) {
@@ -121,25 +121,23 @@ impl Context<'_> {
     fn write_minify(
         &self,
         resource: SharedResource<'_>,
-        contents: &str,
+        contents: impl 'static + Send + AsRef<str> + AsRef<[u8]>,
         minify: bool,
         emit: &[EmitType],
     ) -> Result<(), Error> {
-        let tmp;
-        let contents = if minify {
-            tmp = if resource.extension() == Some(&OsStr::new("css")) {
+        if minify {
+            let contents = contents.as_ref();
+            let contents = if resource.extension() == Some(&OsStr::new("css")) {
                 minifier::css::minify(contents).map_err(|e| {
                     Error::new(format!("failed to minify CSS file: {}", e), resource.path(self))
                 })?
             } else {
                 minifier::js::minify(contents)
             };
-            tmp.as_bytes()
+            self.write_shared(resource, contents, emit)
         } else {
-            contents.as_bytes()
-        };
-
-        self.write_shared(resource, contents, emit)
+            self.write_shared(resource, contents, emit)
+        }
     }
 }
 
@@ -155,15 +153,21 @@ pub(super) fn write_shared(
     let lock_file = cx.dst.join(".lock");
     let _lock = try_err!(flock::Lock::new(&lock_file, true, true, true), &lock_file);
 
-    // The weird `: &_` is to work around a borrowck bug: https://github.com/rust-lang/rust/issues/41078#issuecomment-293646723
-    let write_minify = |p, c: &_| {
+    // Minified resources are usually toolchain resources. If they're not, they should use `cx.write_minify` directly.
+    fn write_minify(
+        basename: &'static str,
+        contents: impl 'static + Send + AsRef<str> + AsRef<[u8]>,
+        cx: &Context<'_>,
+        options: &RenderOptions,
+    ) -> Result<(), Error> {
         cx.write_minify(
-            SharedResource::ToolchainSpecific { basename: p },
-            c,
+            SharedResource::ToolchainSpecific { basename },
+            contents,
             options.enable_minification,
             &options.emit,
         )
-    };
+    }
+
     // Toolchain resources should never be dynamic.
     let write_toolchain = |p: &'static _, c: &'static _| {
         cx.write_shared(SharedResource::ToolchainSpecific { basename: p }, c, &options.emit)
@@ -210,12 +214,12 @@ pub(super) fn write_shared(
         "details.undocumented > summary::before, details.rustdoc-toggle > summary::before",
         "toggle-plus.svg",
     );
-    write_minify("rustdoc.css", &rustdoc_css)?;
+    write_minify("rustdoc.css", rustdoc_css, cx, options)?;
 
     // Add all the static files. These may already exist, but we just
     // overwrite them anyway to make sure that they're fresh and up-to-date.
-    write_minify("settings.css", static_files::SETTINGS_CSS)?;
-    write_minify("noscript.css", static_files::NOSCRIPT_CSS)?;
+    write_minify("settings.css", static_files::SETTINGS_CSS, cx, options)?;
+    write_minify("noscript.css", static_files::NOSCRIPT_CSS, cx, options)?;
 
     // To avoid "light.css" to be overwritten, we'll first run over the received themes and only
     // then we'll run over the "official" styles.
@@ -228,9 +232,9 @@ pub(super) fn write_shared(
 
         // Handle the official themes
         match theme {
-            "light" => write_minify("light.css", static_files::themes::LIGHT)?,
-            "dark" => write_minify("dark.css", static_files::themes::DARK)?,
-            "ayu" => write_minify("ayu.css", static_files::themes::AYU)?,
+            "light" => write_minify("light.css", static_files::themes::LIGHT, cx, options)?,
+            "dark" => write_minify("dark.css", static_files::themes::DARK, cx, options)?,
+            "ayu" => write_minify("ayu.css", static_files::themes::AYU, cx, options)?,
             _ => {
                 // Handle added third-party themes
                 let filename = format!("{}.{}", theme, extension);
@@ -264,26 +268,30 @@ pub(super) fn write_shared(
     // Maybe we can change the representation to move this out of main.js?
     write_minify(
         "main.js",
-        &static_files::MAIN_JS.replace(
+        static_files::MAIN_JS.replace(
             "/* INSERT THEMES HERE */",
             &format!(" = {}", serde_json::to_string(&themes).unwrap()),
         ),
+        cx,
+        options,
     )?;
-    write_minify("search.js", static_files::SEARCH_JS)?;
-    write_minify("settings.js", static_files::SETTINGS_JS)?;
+    write_minify("search.js", static_files::SEARCH_JS, cx, options)?;
+    write_minify("settings.js", static_files::SETTINGS_JS, cx, options)?;
 
     if cx.include_sources {
-        write_minify("source-script.js", static_files::sidebar::SOURCE_SCRIPT)?;
+        write_minify("source-script.js", static_files::sidebar::SOURCE_SCRIPT, cx, options)?;
     }
 
     {
         write_minify(
             "storage.js",
-            &format!(
+            format!(
                 "var resourcesSuffix = \"{}\";{}",
                 cx.shared.resource_suffix,
                 static_files::STORAGE_JS
             ),
+            cx,
+            options,
         )?;
     }
 
@@ -292,12 +300,12 @@ pub(super) fn write_shared(
         // This varies based on the invocation, so it can't go through the write_minify wrapper.
         cx.write_minify(
             SharedResource::InvocationSpecific { basename: "theme.css" },
-            &buffer,
+            buffer,
             options.enable_minification,
             &options.emit,
         )?;
     }
-    write_minify("normalize.css", static_files::NORMALIZE_CSS)?;
+    write_minify("normalize.css", static_files::NORMALIZE_CSS, cx, options)?;
     for (name, contents) in &*FILES_UNVERSIONED {
         cx.write_shared(SharedResource::Unversioned { name }, contents, &options.emit)?;
     }
@@ -512,7 +520,7 @@ pub(super) fn write_shared(
                 content,
                 &cx.shared.style_files,
             );
-            cx.shared.fs.write(&dst, v.as_bytes())?;
+            cx.shared.fs.write(dst, v)?;
         }
     }
 
@@ -603,7 +611,7 @@ pub(super) fn write_shared(
              }",
         );
         v.push_str("})()");
-        cx.shared.fs.write(&mydst, &v)?;
+        cx.shared.fs.write(mydst, v)?;
     }
     Ok(())
 }
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index bb90b195ddd..71c64231a21 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -208,7 +208,7 @@ impl SourceCollector<'_, 'tcx> {
             },
             &self.cx.shared.style_files,
         );
-        self.cx.shared.fs.write(&cur, v.as_bytes())?;
+        self.cx.shared.fs.write(cur, v)?;
         self.emitted_local_sources.insert(p);
         Ok(())
     }
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 23ca6eeaf3b..2d4bfc62af6 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -522,6 +522,11 @@ nav.sub {
 	position: relative;
 }
 
+.docblock > * {
+	max-width: 100%;
+	overflow-x: auto;
+}
+
 .content .out-of-band {
 	flex-grow: 0;
 	text-align: right;
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index f9ddef4120b..eada8f4a04d 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -217,7 +217,7 @@ a {
 	color: #c5c5c5;
 }
 body.source .example-wrap pre.rust a {
-	background: #c5c5c5;
+	background: #333;
 }
 
 .docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index e6bbd237cda..f8ea7a499b2 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -30,9 +30,7 @@ impl JsonRenderer<'_> {
             .get(&item.def_id)
             .into_iter()
             .flatten()
-            .filter_map(|clean::ItemLink { link, did, .. }| {
-                did.map(|did| (link.clone(), from_item_id(did.into())))
-            })
+            .map(|clean::ItemLink { link, did, .. }| (link.clone(), from_item_id((*did).into())))
             .collect();
         let docs = item.attrs.collapsed_doc_value();
         let attrs = item
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 2dbe4c42b88..f170561300c 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -34,6 +34,7 @@ extern crate rustc_ast;
 extern crate rustc_ast_lowering;
 extern crate rustc_ast_pretty;
 extern crate rustc_attr;
+extern crate rustc_const_eval;
 extern crate rustc_data_structures;
 extern crate rustc_driver;
 extern crate rustc_errors;
@@ -49,7 +50,6 @@ extern crate rustc_lint;
 extern crate rustc_lint_defs;
 extern crate rustc_metadata;
 extern crate rustc_middle;
-extern crate rustc_mir;
 extern crate rustc_parse;
 extern crate rustc_passes;
 extern crate rustc_resolve;
@@ -419,8 +419,12 @@ fn opts() -> Vec<RustcOptGroup> {
                 "URL",
             )
         }),
-        unstable("display-warnings", |o| {
-            o.optflagmulti("", "display-warnings", "to print code warnings when testing doc")
+        unstable("display-doctest-warnings", |o| {
+            o.optflagmulti(
+                "",
+                "display-doctest-warnings",
+                "show warnings that originate in doctests",
+            )
         }),
         stable("crate-version", |o| {
             o.optopt("", "crate-version", "crate version to print into documentation", "VERSION")
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index 80af2a7aaf5..2ae4897dc34 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -120,7 +120,7 @@ crate fn test(options: Options) -> Result<(), String> {
         .map_err(|err| format!("{}: {}", options.input.display(), err))?;
     let mut opts = TestOptions::default();
     opts.no_crate_inject = true;
-    opts.display_warnings = options.display_warnings;
+    opts.display_doctest_warnings = options.display_doctest_warnings;
     let mut collector = Collector::new(
         Symbol::intern(&options.input.display().to_string()),
         options.clone(),
@@ -138,7 +138,7 @@ crate fn test(options: Options) -> Result<(), String> {
     crate::doctest::run_tests(
         options.test_args,
         options.nocapture,
-        options.display_warnings,
+        options.display_doctest_warnings,
         collector.tests,
     );
     Ok(())
diff --git a/src/librustdoc/passes/bare_urls.rs b/src/librustdoc/passes/bare_urls.rs
index 56ef15eb884..37faa674292 100644
--- a/src/librustdoc/passes/bare_urls.rs
+++ b/src/librustdoc/passes/bare_urls.rs
@@ -2,7 +2,7 @@ use super::Pass;
 use crate::clean::*;
 use crate::core::DocContext;
 use crate::fold::DocFolder;
-use crate::html::markdown::opts;
+use crate::html::markdown::main_body_opts;
 use core::ops::Range;
 use pulldown_cmark::{Event, Parser, Tag};
 use regex::Regex;
@@ -83,7 +83,7 @@ impl<'a, 'tcx> DocFolder for BareUrlsLinter<'a, 'tcx> {
                 });
             };
 
-            let mut p = Parser::new_ext(&dox, opts()).into_offset_iter();
+            let mut p = Parser::new_ext(&dox, main_body_opts()).into_offset_iter();
 
             while let Some((event, range)) = p.next() {
                 match event {
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index 92e678e4c02..721af3313d2 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -4,8 +4,10 @@ use crate::fold::{self, DocFolder};
 use crate::html::markdown::{find_testable_code, ErrorCodes};
 use crate::passes::doc_test_lints::{should_have_doc_example, Tests};
 use crate::passes::Pass;
+use rustc_hir as hir;
 use rustc_lint::builtin::MISSING_DOCS;
 use rustc_middle::lint::LintLevelSource;
+use rustc_middle::ty::DefIdTree;
 use rustc_session::lint;
 use rustc_span::FileName;
 use serde::Serialize;
@@ -221,10 +223,42 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> {
                     .hir()
                     .local_def_id_to_hir_id(i.def_id.expect_def_id().expect_local());
                 let (level, source) = self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id);
+
+                // In case we have:
+                //
+                // ```
+                // enum Foo { Bar(u32) }
+                // // or:
+                // struct Bar(u32);
+                // ```
+                //
+                // there is no need to require documentation on the fields of tuple variants and
+                // tuple structs.
+                let should_be_ignored = i
+                    .def_id
+                    .as_def_id()
+                    .and_then(|def_id| self.ctx.tcx.parent(def_id))
+                    .and_then(|def_id| self.ctx.tcx.hir().get_if_local(def_id))
+                    .map(|node| {
+                        matches!(
+                            node,
+                            hir::Node::Variant(hir::Variant {
+                                data: hir::VariantData::Tuple(_, _),
+                                ..
+                            }) | hir::Node::Item(hir::Item {
+                                kind: hir::ItemKind::Struct(hir::VariantData::Tuple(_, _), _),
+                                ..
+                            })
+                        )
+                    })
+                    .unwrap_or(false);
+
                 // `missing_docs` is allow-by-default, so don't treat this as ignoring the item
-                // unless the user had an explicit `allow`
-                let should_have_docs =
-                    level != lint::Level::Allow || matches!(source, LintLevelSource::Default);
+                // unless the user had an explicit `allow`.
+                //
+                let should_have_docs = !should_be_ignored
+                    && (level != lint::Level::Allow || matches!(source, LintLevelSource::Default));
+
                 debug!("counting {:?} {:?} in {:?}", i.type_(), i.name, filename);
                 self.items.entry(filename).or_default().count_item(
                     has_docs,
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs
index d961340f1f8..c9f66d096f0 100644
--- a/src/librustdoc/passes/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/check_code_block_syntax.rs
@@ -101,9 +101,9 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
                     );
                 } else if empty_block {
                     diag.span_suggestion(
-                        sp.from_inner(InnerSpan::new(0, 3)),
+                        sp.from_inner(InnerSpan::new(0, 3)).shrink_to_hi(),
                         explanation,
-                        String::from("```text"),
+                        String::from("text"),
                         Applicability::MachineApplicable,
                     );
                 }
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 178c8c15a15..c0c37ee0611 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -14,7 +14,7 @@ use rustc_hir::def::{
 };
 use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_middle::ty::TyCtxt;
-use rustc_middle::{bug, ty};
+use rustc_middle::{bug, span_bug, ty};
 use rustc_resolve::ParentScope;
 use rustc_session::lint::Lint;
 use rustc_span::hygiene::{MacroKind, SyntaxContext};
@@ -98,14 +98,10 @@ impl Res {
         }
     }
 
-    fn def_id(self) -> DefId {
-        self.opt_def_id().expect("called def_id() on a primitive")
-    }
-
-    fn opt_def_id(self) -> Option<DefId> {
+    fn def_id(self, tcx: TyCtxt<'_>) -> DefId {
         match self {
-            Res::Def(_, id) => Some(id),
-            Res::Primitive(_) => None,
+            Res::Def(_, id) => id,
+            Res::Primitive(prim) => *PrimitiveType::primitive_locations(tcx).get(&prim).unwrap(),
         }
     }
 
@@ -237,10 +233,7 @@ enum AnchorFailure {
     /// link, Rustdoc disallows having a user-specified anchor.
     ///
     /// Most of the time this is fine, because you can just link to the page of
-    /// the item if you want to provide your own anchor. For primitives, though,
-    /// rustdoc uses the anchor as a side channel to know which page to link to;
-    /// it doesn't show up in the generated link. Ideally, rustdoc would remove
-    /// this limitation, allowing you to link to subheaders on primitives.
+    /// the item if you want to provide your own anchor.
     RustdocAnchorConflict(Res),
 }
 
@@ -388,7 +381,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                         ty::AssocKind::Const => "associatedconstant",
                         ty::AssocKind::Type => "associatedtype",
                     };
-                    let fragment = format!("{}#{}.{}", prim_ty.as_sym(), out, item_name);
+                    let fragment = format!("{}.{}", out, item_name);
                     (Res::Primitive(prim_ty), fragment, Some((kind.as_def_kind(), item.def_id)))
                 })
         })
@@ -475,14 +468,6 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                     return handle_variant(self.cx, res, extra_fragment);
                 }
                 // Not a trait item; just return what we found.
-                Res::Primitive(ty) => {
-                    if extra_fragment.is_some() {
-                        return Err(ErrorKind::AnchorFailure(
-                            AnchorFailure::RustdocAnchorConflict(res),
-                        ));
-                    }
-                    return Ok((res, Some(ty.as_sym().to_string())));
-                }
                 _ => return Ok((res, extra_fragment.clone())),
             }
         }
@@ -517,6 +502,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                 let (res, fragment, side_channel) =
                     self.resolve_associated_item(ty_res, item_name, ns, module_id)?;
                 let result = if extra_fragment.is_some() {
+                    // NOTE: can never be a primitive since `side_channel.is_none()` only when `res`
+                    // is a trait (and the side channel DefId is always an associated item).
                     let diag_res = side_channel.map_or(res, |(k, r)| Res::Def(k, r));
                     Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(diag_res)))
                 } else {
@@ -1152,7 +1139,7 @@ impl LinkCollector<'_, '_> {
             module_id = DefId { krate, index: CRATE_DEF_INDEX };
         }
 
-        let (mut res, mut fragment) = self.resolve_with_disambiguator_cached(
+        let (mut res, fragment) = self.resolve_with_disambiguator_cached(
             ResolutionInfo {
                 module_id,
                 dis: disambiguator,
@@ -1174,16 +1161,7 @@ impl LinkCollector<'_, '_> {
             if let Some(prim) = resolve_primitive(path_str, TypeNS) {
                 // `prim@char`
                 if matches!(disambiguator, Some(Disambiguator::Primitive)) {
-                    if fragment.is_some() {
-                        anchor_failure(
-                            self.cx,
-                            diag_info,
-                            AnchorFailure::RustdocAnchorConflict(prim),
-                        );
-                        return None;
-                    }
                     res = prim;
-                    fragment = Some(prim.name(self.cx.tcx).to_string());
                 } else {
                     // `[char]` when a `char` module is in scope
                     let candidates = vec![res, prim];
@@ -1303,12 +1281,17 @@ impl LinkCollector<'_, '_> {
                     }
                 }
 
-                Some(ItemLink { link: ori_link.link, link_text, did: None, fragment })
+                Some(ItemLink {
+                    link: ori_link.link,
+                    link_text,
+                    did: res.def_id(self.cx.tcx),
+                    fragment,
+                })
             }
             Res::Def(kind, id) => {
                 verify(kind, id)?;
                 let id = clean::register_res(self.cx, rustc_hir::def::Res::Def(kind, id));
-                Some(ItemLink { link: ori_link.link, link_text, did: Some(id), fragment })
+                Some(ItemLink { link: ori_link.link, link_text, did: id, fragment })
             }
         }
     }
@@ -1323,7 +1306,7 @@ impl LinkCollector<'_, '_> {
         if let Some(ref cached) = self.visited_links.get(&key) {
             match cached {
                 Some(cached) => {
-                    self.kind_side_channel.set(cached.side_channel.clone());
+                    self.kind_side_channel.set(cached.side_channel);
                     return Some(cached.res.clone());
                 }
                 None if cache_resolution_failure => return None,
@@ -2069,8 +2052,11 @@ fn anchor_failure(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>, failure: A
             diag.span_label(sp, "invalid anchor");
         }
         if let AnchorFailure::RustdocAnchorConflict(Res::Primitive(_)) = failure {
-            diag.note("this restriction may be lifted in a future release");
-            diag.note("see https://github.com/rust-lang/rust/issues/83083 for more information");
+            if let Some(sp) = sp {
+                span_bug!(sp, "anchors should be allowed now");
+            } else {
+                bug!("anchors should be allowed now");
+            }
         }
     });
 }
@@ -2198,10 +2184,11 @@ fn handle_variant(
     use rustc_middle::ty::DefIdTree;
 
     if extra_fragment.is_some() {
+        // NOTE: `res` can never be a primitive since this function is only called when `tcx.def_kind(res) == DefKind::Variant`.
         return Err(ErrorKind::AnchorFailure(AnchorFailure::RustdocAnchorConflict(res)));
     }
     cx.tcx
-        .parent(res.def_id())
+        .parent(res.def_id(cx.tcx))
         .map(|parent| {
             let parent_def = Res::Def(DefKind::Enum, parent);
             let variant = cx.tcx.expect_variant_res(res.as_hir_res().unwrap());
diff --git a/src/librustdoc/passes/doc_test_lints.rs b/src/librustdoc/passes/doc_test_lints.rs
index 03bc2b52f17..279d0dbda82 100644
--- a/src/librustdoc/passes/doc_test_lints.rs
+++ b/src/librustdoc/passes/doc_test_lints.rs
@@ -10,6 +10,7 @@ use crate::core::DocContext;
 use crate::fold::DocFolder;
 use crate::html::markdown::{find_testable_code, ErrorCodes, Ignore, LangString};
 use crate::visit_ast::inherits_doc_hidden;
+use rustc_hir as hir;
 use rustc_middle::lint::LintLevelSource;
 use rustc_session::lint;
 use rustc_span::symbol::sym;
@@ -67,15 +68,35 @@ crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> boo
                 | clean::ImportItem(_)
                 | clean::PrimitiveItem(_)
                 | clean::KeywordItem(_)
+                // check for trait impl
+                | clean::ImplItem(clean::Impl { trait_: Some(_), .. })
         )
     {
         return false;
     }
+
     // The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
     // would presumably panic if a fake `DefIndex` were passed.
     let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.def_id.expect_def_id().expect_local());
+
+    // check if parent is trait impl
+    if let Some(parent_hir_id) = cx.tcx.hir().find_parent_node(hir_id) {
+        if let Some(parent_node) = cx.tcx.hir().find(parent_hir_id) {
+            if matches!(
+                parent_node,
+                hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }),
+                    ..
+                })
+            ) {
+                return false;
+            }
+        }
+    }
+
     if cx.tcx.hir().attrs(hir_id).lists(sym::doc).has_word(sym::hidden)
         || inherits_doc_hidden(cx.tcx, hir_id)
+        || cx.tcx.hir().span(hir_id).in_derive_expansion()
     {
         return false;
     }
diff --git a/src/librustdoc/passes/html_tags.rs b/src/librustdoc/passes/html_tags.rs
index f29d38e3e07..a0144a5298e 100644
--- a/src/librustdoc/passes/html_tags.rs
+++ b/src/librustdoc/passes/html_tags.rs
@@ -2,7 +2,7 @@ use super::Pass;
 use crate::clean::*;
 use crate::core::DocContext;
 use crate::fold::DocFolder;
-use crate::html::markdown::opts;
+use crate::html::markdown::main_body_opts;
 use core::ops::Range;
 use pulldown_cmark::{Event, Parser, Tag};
 use std::iter::Peekable;
@@ -192,7 +192,7 @@ impl<'a, 'tcx> DocFolder for InvalidHtmlTagsLinter<'a, 'tcx> {
             let mut is_in_comment = None;
             let mut in_code_block = false;
 
-            let p = Parser::new_ext(&dox, opts()).into_offset_iter();
+            let p = Parser::new_ext(&dox, main_body_opts()).into_offset_iter();
 
             for (event, range) in p {
                 match event {
diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs
index 3e06b417314..3e98ba08fb9 100644
--- a/src/librustdoc/visit_lib.rs
+++ b/src/librustdoc/visit_lib.rs
@@ -67,7 +67,7 @@ impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> {
         }
     }
 
-    fn visit_item(&mut self, res: Res) {
+    fn visit_item(&mut self, res: Res<!>) {
         let def_id = res.def_id();
         let vis = self.tcx.visibility(def_id);
         let inherited_item_level = if vis == Visibility::Public { self.prev_level } else { None };
diff --git a/src/llvm-project b/src/llvm-project
-Subproject ec995b75d71c5f3b9a82fe084259477eb22f74d
+Subproject 86c7daa627aefda1371568b948eba21edf72074
diff --git a/src/stage0.json b/src/stage0.json
index 1160cd3ab4e..372204dbbf7 100644
--- a/src/stage0.json
+++ b/src/stage0.json
@@ -2,345 +2,347 @@
   "__comment": "Generated by `./x.py run src/tools/bump-stage0`. Run that command again to update the bootstrap compiler.",
   "dist_server": "https://static.rust-lang.org",
   "compiler": {
-    "date": "2021-08-22",
+    "date": "2021-09-08",
     "version": "beta"
   },
   "rustfmt": {
-    "date": "2021-08-26",
+    "date": "2021-09-08",
     "version": "nightly"
   },
   "checksums_sha256": {
-    "dist/2021-08-22/cargo-beta-aarch64-apple-darwin.tar.gz": "1aae6206b6ee057a53c6863d1aa9246a913bd8cc87945221ffe25a0763198ec9",
-    "dist/2021-08-22/cargo-beta-aarch64-apple-darwin.tar.xz": "9bb4026714d46f99077c4ec2ac1f818a059252996077569339a72704a1044cc5",
-    "dist/2021-08-22/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "127a066958fe2f67154ae5e5ffdf67e216cd9da5c8ca7f6f5818017ef647eb57",
-    "dist/2021-08-22/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "f62459d78c012d129a38f9f05975f784ca59f613cb77f273ac1be992320968ca",
-    "dist/2021-08-22/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "eb0e5765d0d37129a1e70680cb701fc7968baf98a183a25fbe495d5e1818a67c",
-    "dist/2021-08-22/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "8168902da36e32c2b2946ec18d41c4877191e3b5ec95276d85a1453541be8adf",
-    "dist/2021-08-22/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "e8a774fd383d0a7a3a1216ebd3a005fe01560002c8a28b89ce7f9a0ac522a07f",
-    "dist/2021-08-22/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "da7e246ca883ace9f9006257dd52756395307613f2bc10d86bacfe9b24f861c8",
-    "dist/2021-08-22/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "bc20e1ffe92aeca2a01bab6b1e383dfd7cecde01780bb2369ef5e10ef6e88bc7",
-    "dist/2021-08-22/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "5020ad70b694f18fa19be09d86983a7f396b38d71a65cf061438870d9264de45",
-    "dist/2021-08-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "53792dbfd932874bc7be8cf6683e5fa318afe9e59a3069f1c82279d9b66edcfd",
-    "dist/2021-08-22/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "cb393c4f0c0b6ef9c921733267192c01935fec55944c770765e3dcc37d9c20a8",
-    "dist/2021-08-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "96f017458f94370758b2cfa30f787707f548aeb9ca2dd9a52a43b27c73040b82",
-    "dist/2021-08-22/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "aa0b966b0ae33dc01714f16b3e511ae1f60da0a1a0e4de32e09cbe7a5e6a67b3",
-    "dist/2021-08-22/cargo-beta-i686-pc-windows-gnu.tar.gz": "38f9b818c71bbf607cd0db8e73b539506f42c529fb8a5053860e844914e0ade3",
-    "dist/2021-08-22/cargo-beta-i686-pc-windows-gnu.tar.xz": "ddfe1cee4f7d8a451ff5d1eb880c3e9ffa3fa1e59a8c12322e46562e379101de",
-    "dist/2021-08-22/cargo-beta-i686-pc-windows-msvc.tar.gz": "33d5d918ae8d35ecc760bf876573a51d62c98a46eb6c60c2e3ba8acba4ce6488",
-    "dist/2021-08-22/cargo-beta-i686-pc-windows-msvc.tar.xz": "0424f863ecf6e6d870325539637899720806a4130ffe815c724cdc34d8eb444f",
-    "dist/2021-08-22/cargo-beta-i686-unknown-linux-gnu.tar.gz": "d5e71781a82b424b28b90fe08d2ac4d86b37acd476bc36c106222128202a9476",
-    "dist/2021-08-22/cargo-beta-i686-unknown-linux-gnu.tar.xz": "65f860c74140318eb5c034a04c85e3eabfb31dfa8d70791d701f15d979d50361",
-    "dist/2021-08-22/cargo-beta-mips-unknown-linux-gnu.tar.gz": "034e491668d0f55b1fba9d606c2acb2d7d1d00db528f141207202ec6e5ca4410",
-    "dist/2021-08-22/cargo-beta-mips-unknown-linux-gnu.tar.xz": "f320d08c2116bcf1646f141426785e2b27488e48cf7e0ab97dab39efa4668efd",
-    "dist/2021-08-22/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "8bcb363d7dd7656bdeb5525df048dea384b34d564c98e3374c8c82f037e5074d",
-    "dist/2021-08-22/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "bbb924b505c82fef0d8912deb95b312d6547f96d15ff7cb06c5d77ee56c6fbbb",
-    "dist/2021-08-22/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "056e1662756321e884b84e662b9e465d58187f1fd9227ae4d7a9fce0110ddfb8",
-    "dist/2021-08-22/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "c01a661eee4e2ab0c93cc6575f8ae56c16b79bd0d5479d9f918004cf8a8abc2b",
-    "dist/2021-08-22/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "b74739855529627407a72244de3efd706ed99c347061513a677ebc7fd3b4e7c1",
-    "dist/2021-08-22/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "a275d7e95312e868636aa1539de0b2f490973119ffb4863f5534eed395c4113e",
-    "dist/2021-08-22/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "4f6326173b50952d933b02cc477156d5aad067798b347ce502889e607e98c84c",
-    "dist/2021-08-22/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "86ffca7848946079b62f083a92e47440a431b5c451aca3600efc0a5f3939ba2f",
-    "dist/2021-08-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "9c9406fcb15e88f93a23d0a275e44559e33b4a2eeab4403cbb2184bdca36318e",
-    "dist/2021-08-22/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "99ca6df78a1dfcb0c9a919f0eec47783f95399bae39271a6367c07b8ef346a5a",
-    "dist/2021-08-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "c24493b3e919ec268aa4b98da0a66332fa4e104210ed15b8f6c3b8c240ebeffe",
-    "dist/2021-08-22/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "7cfec0a0bae8471a32385a7c19d1ec17dba25ab1d6211cd062df73a9a1c030a2",
-    "dist/2021-08-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "8a8d81661cc1789185be6d4c13ac2ee602194a5526467ab34e4f23243cb9f474",
-    "dist/2021-08-22/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "b8ada6046b5351a627ae1fb4ee8ba059fa551f1de4444aba1d1915a27371d339",
-    "dist/2021-08-22/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "946d2d77ec784019f18372610ff438321e22f7e0d2e0045cc71180f3b2f6d376",
-    "dist/2021-08-22/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "2f3756d68b354341f98a3cfa4c89d78bf6e8c631dfb6477fceec5e6b00833d30",
-    "dist/2021-08-22/cargo-beta-x86_64-apple-darwin.tar.gz": "bccb3002b5cc3556555bb05208b7d64b9aee3a7dc3b482c03090ad0102c22570",
-    "dist/2021-08-22/cargo-beta-x86_64-apple-darwin.tar.xz": "a0f7dbfb008cb12bc7a8c9f464715e5aedfae175fdf5bb7bdf3d971072cd9b54",
-    "dist/2021-08-22/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "26fcc16d533e427eeded47f8c088aaa180602f68043f5dcd84755ac2166f16af",
-    "dist/2021-08-22/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "d5bc7bc9f2d5d2bbe7167f810b1334a86ddd694d111e145223474f8d6dee00af",
-    "dist/2021-08-22/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "6f3fe7f685324ff07995e5fb453462a1c4b5dac9208cd23935f6435af9146692",
-    "dist/2021-08-22/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "86e37578645f4436b7889c3b9c110888a2aff7af2833a7f5f38fa345a6f36e76",
-    "dist/2021-08-22/cargo-beta-x86_64-unknown-freebsd.tar.gz": "f0964def1f80732c1a67f0e4258a301ae2ee27d7ea474f70ab44816907a95ec3",
-    "dist/2021-08-22/cargo-beta-x86_64-unknown-freebsd.tar.xz": "6a4655c9b902b904b3dd2ca00dd656d0ef99c77e632f6d6ffc615486b4bfa543",
-    "dist/2021-08-22/cargo-beta-x86_64-unknown-illumos.tar.gz": "5aeb8db8c2e5afd80378a0aa1572c57ff021fb5dccb1bd914b994f0ca8764667",
-    "dist/2021-08-22/cargo-beta-x86_64-unknown-illumos.tar.xz": "0892a93f462e70aee33117de90caaa7b7ef363a27e573602c1d606c0309ae2d9",
-    "dist/2021-08-22/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "e4be5cd72bb220514c73d7da14ff2962dcd74b8602c1724d71538ab11da94132",
-    "dist/2021-08-22/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "0b643ba40ce6dbb270f85f45b2dd4d727051a896099493166cfad05c9be96b1f",
-    "dist/2021-08-22/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "998df5339f738815ab7c38b32df00eef09ff0e415a85d2ae2ab1c0836a380906",
-    "dist/2021-08-22/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "4ca058f973e2d439e812f839e57920dd9e73a0da9f9bf37889c06f3b1755b07e",
-    "dist/2021-08-22/cargo-beta-x86_64-unknown-netbsd.tar.gz": "6511df143067a3c3f6f741540f890f3bca46b11c01cda1c92e1708d0be30ebeb",
-    "dist/2021-08-22/cargo-beta-x86_64-unknown-netbsd.tar.xz": "4ebef9830e25fb28e12ea538e17a46cfe0748e6a14cf976048df056ae708b1ea",
-    "dist/2021-08-22/rust-std-beta-aarch64-apple-darwin.tar.gz": "6af3a7f720d5a7100683636c387865b3d4e9b5148ca04c1238662b81c8bbde9c",
-    "dist/2021-08-22/rust-std-beta-aarch64-apple-darwin.tar.xz": "459e63b66eb8e53e106896c3003183c5ef3803a8dd3d501d50e6d4e03343ad66",
-    "dist/2021-08-22/rust-std-beta-aarch64-apple-ios.tar.gz": "95c816378d57b5d7336373f7f53b603dd8a4efcf17634d4e008b6bd896947cac",
-    "dist/2021-08-22/rust-std-beta-aarch64-apple-ios.tar.xz": "209caeea6df90996d5239d0900767135bde716387317a10dc348b96aa818a93a",
-    "dist/2021-08-22/rust-std-beta-aarch64-fuchsia.tar.gz": "54ec6a313cc523fc568c4879cf36ab90bade8a1ae9c2ee89bafd57c2c9f3f754",
-    "dist/2021-08-22/rust-std-beta-aarch64-fuchsia.tar.xz": "82de1d66bf9cf226b80fea722d2828f368cbe75bc5d99a524193b50db6003636",
-    "dist/2021-08-22/rust-std-beta-aarch64-linux-android.tar.gz": "1a08cd54ff716d6ef3e53177e31787e8aa00f948054b42f94d791d3d59aa3169",
-    "dist/2021-08-22/rust-std-beta-aarch64-linux-android.tar.xz": "32c1b56cc223bab3e7f15de719488c874011dd6be622038ce5b1f7ff03b05c59",
-    "dist/2021-08-22/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "62a85f52db02e9afc659e84ea8bc3c8828f6a9fe4c1b58eecc3cefeb99e2d8ac",
-    "dist/2021-08-22/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "1e6126312252956f5ad887ca5e8271be3cf31ac8d793071f6af8c2adcdd57f00",
-    "dist/2021-08-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "5542b7e2ee1611f0410e2e962796cd7067e483b37730061a4f788f853f31c7c1",
-    "dist/2021-08-22/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "97f149839149fcff4004260eb119c1213f10a455b37a8256aec977bc04c9e2c0",
-    "dist/2021-08-22/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "48dada900d144fc9a17ff273ab44d9c4c5fb0cfbaae986d6396aaa6c9c5c22d5",
-    "dist/2021-08-22/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "c93b5da1e22138da0a97be32b9498a3ede270253a22a9d9275f610e349438bfb",
-    "dist/2021-08-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "904b39e24f5fe72393f943a5ecb3bfa6e07f3623a0cde911b161558660ee27d9",
-    "dist/2021-08-22/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "013646fe9e3f640ae820bfccce656c1bc94d0c3856613dbdea8b06574e072ad4",
-    "dist/2021-08-22/rust-std-beta-aarch64-unknown-none.tar.gz": "59de57b6902c755a2d92d5aa154452e84c747bc414605cebb367a4a17cf16ae7",
-    "dist/2021-08-22/rust-std-beta-aarch64-unknown-none.tar.xz": "9822fd8d21f863018ead909155ed7d931c5a9bb9ac6461c1f19609ad1a206a48",
-    "dist/2021-08-22/rust-std-beta-arm-linux-androideabi.tar.gz": "235bc683a244a69b1f36a875a418efb56af6e1f8411dbace6f9cef3ce1191f7d",
-    "dist/2021-08-22/rust-std-beta-arm-linux-androideabi.tar.xz": "a2d267e75d64e0bb96c9a8b78bb67db4ba46576edc51955108595c17ff285083",
-    "dist/2021-08-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "cc5d42c65ebc2733017a463c5a4903c681fd923dfa820ed6e420950f6c599ba5",
-    "dist/2021-08-22/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "1e9b3e5c0025c15f485eee6a39dc20ea62bfa777a820bd524817eeab07878e67",
-    "dist/2021-08-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "5f298d431d03d56112d2527c889d94296c03fb4187bbe26bd0e2be50bc9207ed",
-    "dist/2021-08-22/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "8be37b928562c4f08342b0661077dca25484d9e12e1e48b375fef02f6699fe87",
-    "dist/2021-08-22/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "db7d25058f4f39007495e864a20a398d307f9505721c9f5991db6d7065db50ee",
-    "dist/2021-08-22/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "fc858a2f2b7fe83cd148ee133b952ef8d63a6f39600fb101c7b98d37734484df",
-    "dist/2021-08-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "bc1ab01b0d7783c8cde71c1d4507fbf68330933e86d5b0280426eb9e9103ba38",
-    "dist/2021-08-22/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "18a1ca7fb88d56832ee5a331c3f3fa38ff2c72ecded3e093f4d6aef5e67e886d",
-    "dist/2021-08-22/rust-std-beta-armebv7r-none-eabi.tar.gz": "3eef0c676173ae40e3b1f900627c953955fdea5b3a24401bf69e9d433c9b0996",
-    "dist/2021-08-22/rust-std-beta-armebv7r-none-eabi.tar.xz": "58cdd696c46434bc0aea39b562aab818da1644da08bb385047b7b83cfedf9334",
-    "dist/2021-08-22/rust-std-beta-armebv7r-none-eabihf.tar.gz": "0035c38e059eac51cf8786bfde6162bb27ee8c642260af40646665902f9e4cc8",
-    "dist/2021-08-22/rust-std-beta-armebv7r-none-eabihf.tar.xz": "893d2d56614198da58327881684b1edab0a7d849eb8e3d6ba1705c192c98718e",
-    "dist/2021-08-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "489d6080bf6ab3dddfd490cc2c6cd956473389678eafe4b85b88e0ba06dfd73a",
-    "dist/2021-08-22/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "10ed28b9ce5b2d94492034e707a78d18540b096d1439faf5c7370d29c50ea105",
-    "dist/2021-08-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "febbed115d82f51d8c19b49f89a6fb9f1062826d6283e5877b8327b4b0572671",
-    "dist/2021-08-22/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "0f96c9b4bc3464cef4deeec087da38fc39d2cefb1cff7b413aedb8a79f412dc8",
-    "dist/2021-08-22/rust-std-beta-armv7-linux-androideabi.tar.gz": "8d407d9ddbe27ac708efb40d12b2292857c49f306afa018fd7df44116ccade3c",
-    "dist/2021-08-22/rust-std-beta-armv7-linux-androideabi.tar.xz": "253b5f4613369b4431296b1151b7c4228594889ac69674a0e3ef75438120868a",
-    "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "11e715bf0082733d94a796ed4e123f7ec77aa5fe0e8d037dd513dd69bc230a2e",
-    "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "a2d8a16c08721a406f8132f5deb960b65e38d3235a76b72d5f267b2bddb9ad91",
-    "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "2351b24b205851ff51e79a228416bb6ea801551050cb791464a0364a56a0133b",
-    "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "12da6b0947eebc24ae2a279bad6f1a50d26d57c956cb66840b5db6ef266975e4",
-    "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "96d333f046236bbfe809a5526e798197e8416442ddaec5e692aa642dd58f3397",
-    "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "f2d5832790120cceda3c07cb2dadb4d4e8e30228ffedbf4988a52573382689c1",
-    "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "d71cf49d01b781c55a64b174d4b91906771aeb90e885310576b5d77a068a8961",
-    "dist/2021-08-22/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "3e9b5c730f855b690103d44929384738748bdbc312fe5f8bdb9cb3fe1d8dc701",
-    "dist/2021-08-22/rust-std-beta-armv7a-none-eabi.tar.gz": "b0464837c6303c85d67ebcf45752ad9c859ea4ff013310c4ae64a2ff318db56b",
-    "dist/2021-08-22/rust-std-beta-armv7a-none-eabi.tar.xz": "13aec30cbdfb84483669a5d5a5d2f465f60692e997a6073d5f749c2950fe6a45",
-    "dist/2021-08-22/rust-std-beta-armv7r-none-eabi.tar.gz": "4c54b72683f8800f77b60889a8e91fe293a21916f756ab6fbe5f1e39884a11b2",
-    "dist/2021-08-22/rust-std-beta-armv7r-none-eabi.tar.xz": "5b917d543bd41f47ac8983cc5f3dfb19515b940eff644c5421f23575d8958e35",
-    "dist/2021-08-22/rust-std-beta-armv7r-none-eabihf.tar.gz": "305fce68a56206cffb34b4735fbff367b8d1f3131a043f5cf03de1ede9402323",
-    "dist/2021-08-22/rust-std-beta-armv7r-none-eabihf.tar.xz": "511fe782be16d7402519546af50427fc953f599773466668c0133e3d252874ce",
-    "dist/2021-08-22/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "31223e26db1d00219cf78e70c096aaec45a5ba2f2835dcb55edcc1e2e83e28b8",
-    "dist/2021-08-22/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "2453e08515943e38def4d65c8278f2d25c5b7dfa7883040346c0824abaab9cb0",
-    "dist/2021-08-22/rust-std-beta-i586-pc-windows-msvc.tar.gz": "1f22b735b50f2ccbb3ba99a27e4901b2da9d408361ad8ce2710ab61dbb6a8c46",
-    "dist/2021-08-22/rust-std-beta-i586-pc-windows-msvc.tar.xz": "e2f31b9933df67a5fdae28f26b38f907fb2607ccfc2a1f2e6b6fd9853eb6eb6a",
-    "dist/2021-08-22/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "a3d2d4184376f6d398a3b1bfbab881659408340287d61d7f29d70bb167824427",
-    "dist/2021-08-22/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "3803e83360d67e1866d2dada4f62fbf2a04ac3cbc7c347ba4ce97b2e6adf9ced",
-    "dist/2021-08-22/rust-std-beta-i586-unknown-linux-musl.tar.gz": "c2890c8ae6c3bb71811867ab953e774161415d454009d9f36a116c86994a9056",
-    "dist/2021-08-22/rust-std-beta-i586-unknown-linux-musl.tar.xz": "671191cab9795d52a7ed9762951de46a89988bb22233b6a0b09e85bdc5e5d904",
-    "dist/2021-08-22/rust-std-beta-i686-linux-android.tar.gz": "3e83c96f73f5b526e3f20939338e0b51a94898ffcfa3c7d08ef72966e9161f71",
-    "dist/2021-08-22/rust-std-beta-i686-linux-android.tar.xz": "8c96f60b63bdcec60ea52cbb3880f2d684b2b96a37b37946a24d893eafb4dc77",
-    "dist/2021-08-22/rust-std-beta-i686-pc-windows-gnu.tar.gz": "760e6deb8aec1185b8127bc012794463eefa87dd48a1fb69e6f79ccad45422e5",
-    "dist/2021-08-22/rust-std-beta-i686-pc-windows-gnu.tar.xz": "82809e4bf5b89cfad4d8c8770deb5c2bab4ed1f17463a09c728c25684b7d2d72",
-    "dist/2021-08-22/rust-std-beta-i686-pc-windows-msvc.tar.gz": "288086c4caf64a38b441937f9d3335b0ef419bb6a2693216b48aefe31c34f7ea",
-    "dist/2021-08-22/rust-std-beta-i686-pc-windows-msvc.tar.xz": "06bb31b48abfbfdf4c627d87717987cb0e721100f952e77435c156bd45eb02a3",
-    "dist/2021-08-22/rust-std-beta-i686-unknown-freebsd.tar.gz": "589d7aeabc268fb06f3fd7ff37dfff434924fe87fb778ffa366a27ebf815a26c",
-    "dist/2021-08-22/rust-std-beta-i686-unknown-freebsd.tar.xz": "b5b7bf0752034c4e79827e2155afbc7b2fd59a5220e8acf9b244023a725f9483",
-    "dist/2021-08-22/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "94c9450ad3915dd6367833b59e07b66083d653eaa72b3b486676c3475fcca86e",
-    "dist/2021-08-22/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "014e3abef9cbea6008653ba3e85c7cf074add0bbfa71afa90a9f577f014de19c",
-    "dist/2021-08-22/rust-std-beta-i686-unknown-linux-musl.tar.gz": "9897bea4ada2d49e055210699a757f59620d8092e9b40c3eba2dd9fde0205309",
-    "dist/2021-08-22/rust-std-beta-i686-unknown-linux-musl.tar.xz": "7c53fbd4643e4f9f5e441a79bdbbf8044b3d35d113ca2ce670462433c9299ce4",
-    "dist/2021-08-22/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "2d4af2bd5c632de7de1abf556acda7c4897f5475221a7e72d36d70236c90a332",
-    "dist/2021-08-22/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "f388bb0bbfa4d505101b6f087205cef9593b29d55d04dc0f08629d23df6f4dd5",
-    "dist/2021-08-22/rust-std-beta-mips-unknown-linux-musl.tar.gz": "7a35ebffe2858e68c8585c54d980edfb7fd84b3a78856110871d062f58e4c4d9",
-    "dist/2021-08-22/rust-std-beta-mips-unknown-linux-musl.tar.xz": "40ca86dbff7248854b86ae2a4c05efa5e240ae40d88a887a2681aa0c4995fad3",
-    "dist/2021-08-22/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "3d380de1f425c4e022037805b4687567870d84bd06375c26528e5a9529b1f0df",
-    "dist/2021-08-22/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "15f951100779f6535a25f91b58630951376d9191dabb3405b34a78246bd07d6b",
-    "dist/2021-08-22/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "d1d2f014a7d0c5b6140d282bf38d5fc4c7a93df0e484d9f893fe3ed25c5cf384",
-    "dist/2021-08-22/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "7f96e0ebaa820cf927962b0c0c584b4b96d3fd34e90e281162138937f145fde5",
-    "dist/2021-08-22/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "e6d8a5e5de7328d045ccc4c6457e82282c7b0a23bc35443f402672d94df088ef",
-    "dist/2021-08-22/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "d015d566ae58d854de39337ddfc31f29cdbb4e87320e20b0fbcc83912415d11f",
-    "dist/2021-08-22/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "cbbcf7edb5f785d89bc20c287a6dcab69eabbdfff0ed8d9283ea0766d98ccfee",
-    "dist/2021-08-22/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "4b988afc44729564783300cfd47b1ace974bd8eacb52cc553365fdd07b8b38e7",
-    "dist/2021-08-22/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "674d244f0d536ff053be6384ee9ba9b80db2cc6d9bd840434d26fabdb259d7be",
-    "dist/2021-08-22/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "07aa043aac39364935f6758e1d2200d6334b719e4b13ad7bcc9e693cfef90e3c",
-    "dist/2021-08-22/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "19aa1bc698c24eb1136de2a8ace0b872a472e9fb5b1c1fbd48d03fa8e3dab00b",
-    "dist/2021-08-22/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "a9db5dfaca379bcb6a2c3bb5c6d6eafe4dace2e814c7edb5fdf6a26595be2538",
-    "dist/2021-08-22/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "ebe482fecfce4ff0ee9dd514b984b9c04565470ecd7a24d94778d51e31107915",
-    "dist/2021-08-22/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "b663ce48f79cf4634d35e8c35f10c2c51d775c906b9c7a46ae6e67d7070e1b21",
-    "dist/2021-08-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "aeb314e2de96b9d7623a8b58d34fb1d290039b1ad63ad91da5052bbcb8569d66",
-    "dist/2021-08-22/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "87731e0ea78d1478f87c50d770618b7feb6d404ae257704a1a622bbfc4a079cc",
-    "dist/2021-08-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "5eeea41e13e8941e1a7e29dc649cc34fafad8ef01fdeffb133cf0dad6cc57997",
-    "dist/2021-08-22/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "3435ba7a88ad51266a32fdba648f1d4a60a918ad396261a03593a409db028f1b",
-    "dist/2021-08-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "d453444ef726401c683042f2d33c70fc078ef79d95d4cbd0f007d41bb8894e2b",
-    "dist/2021-08-22/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "ab83c5f5477bb3a800e2054d345ed48bba162c871788f7b187f875652f9e8163",
-    "dist/2021-08-22/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "d007269d819f76c53e211c8a2871db177c6f910de463f87ae1cc3d3e3f0d42b8",
-    "dist/2021-08-22/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "3bc82447155b9a453abe1788705b61ea41f017048a017d973a41a587b81b4bab",
-    "dist/2021-08-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "5c6b7fb54fa4effd3140848b9f7779b4139971f0666758bff43c8bc93877d962",
-    "dist/2021-08-22/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "4043a4dca70b44ff5471a3457fbc85218850ab0dd52bbeef87bc629170f07bc3",
-    "dist/2021-08-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "aaa6eee8c67c6c666cca044c75e0049fc982442647528263ac87bfd17bddd0e5",
-    "dist/2021-08-22/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "ce8633daef8fab199318c26cac981de0a7db1e93a066c05187f4f3165826da6a",
-    "dist/2021-08-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "d5323d5b0a8a9c4f7f688449ac4b39b1b0e30ae26fbdb355ab3477c033e86f74",
-    "dist/2021-08-22/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "e4dd4e3b3fef2434ad5b96d7c966576f9d27cca146bb1df3ec0dea92e65d1234",
-    "dist/2021-08-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "ca1e486ed9b37d64c4c1ff4ade719bd4d75ea42d862a53e7ce5106045498618e",
-    "dist/2021-08-22/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "b07b65d1df2b7147cfcda1aa8c43b64cb0f29290fe9518569969550fd176399e",
-    "dist/2021-08-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "3225c1a028dbff77a73c8209417261689dcffff8c9019bfb81d7c2ddf440999d",
-    "dist/2021-08-22/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "d219a81bc543d000200f0a11de6db87f5f0b135122150f37782d0e1132669ffc",
-    "dist/2021-08-22/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "92a70667972c1fa0e5963ef189a450f65861d779f2251e10884bc9dac3751e2a",
-    "dist/2021-08-22/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "31405140b78366c182ebcb02632983017409c3c282a2eac6716d410fc2f6d1a4",
-    "dist/2021-08-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "3f6dfab8290bdd2e12f7a4a8ba0e2b58006e0a0096357077cdd1392e94a81bd7",
-    "dist/2021-08-22/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "327a86e0e83ccaac9ebb5458e48906a5e83ec928fc01939758a50ce46c114334",
-    "dist/2021-08-22/rust-std-beta-sparcv9-sun-solaris.tar.gz": "c798402360747dac456746c4fb68de30e702ba6a3a1cea0bd5884546d1c2f714",
-    "dist/2021-08-22/rust-std-beta-sparcv9-sun-solaris.tar.xz": "63a9ebcbb4e97cd80c0c97ba6323614cc69a4ff15904e6120aae970a803b3402",
-    "dist/2021-08-22/rust-std-beta-thumbv6m-none-eabi.tar.gz": "bf1ae6e7ceeee0b9631d638aa33b29fc064699eebf1da192aed0b7c0a98f6866",
-    "dist/2021-08-22/rust-std-beta-thumbv6m-none-eabi.tar.xz": "da183dbff702ab18cf02d34c395c6dc70344b525c0d09bc26a8670b75e6e900a",
-    "dist/2021-08-22/rust-std-beta-thumbv7em-none-eabi.tar.gz": "f6c66612b1f500218927504a23eb3df1bd8ff5a6171d576ebb681bb0f426d5c6",
-    "dist/2021-08-22/rust-std-beta-thumbv7em-none-eabi.tar.xz": "8364308682a2c6e91b2c7bfacb09dd9a7487c106ae95c489286d13e641ecaaa0",
-    "dist/2021-08-22/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "711e05b89ab2cf2cc17aa7beeb5bc2aafcd851606a8dd535230e64bc5d232dea",
-    "dist/2021-08-22/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "f444669bde93eae4599db7624f830b031f4d4d116d0344829be3177558a5dfd1",
-    "dist/2021-08-22/rust-std-beta-thumbv7m-none-eabi.tar.gz": "9b4699b67763b7c2691a95c69827f6c8ce8847c64e0806b0c3f36f48848a7e4e",
-    "dist/2021-08-22/rust-std-beta-thumbv7m-none-eabi.tar.xz": "2c038bc6607b115f817859aae07c495d6d2a1bd4cfe9007f36494b9229a68d86",
-    "dist/2021-08-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "7634d01dfdb18a43bc8a230df711e8254f3bbc214b89844475bfba9eb920a5cf",
-    "dist/2021-08-22/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "ba0815d8b0d5600cd09148343bcbfa25004b3092bee1ed0e0673fdf8937ebf62",
-    "dist/2021-08-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "823ee6535da426700b0aed6a33201873d8b6611248506e436cdddae92a074a06",
-    "dist/2021-08-22/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "c4b21b5300959794c811653aa907fd259970b08c41d4ce303384b34783b142cf",
-    "dist/2021-08-22/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "d71ce2ec3eb040244c017dc7bb40342da106d097a579ab69312f1879d5c446c7",
-    "dist/2021-08-22/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "05375174c0d6f9480c5b504ee16823a28d2994bea0eee52242cef25f9d7b766d",
-    "dist/2021-08-22/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "9e9efb15d1718421b5537aca94dbc078d8cf4f1651b0b2e790af5fb0d8592ea4",
-    "dist/2021-08-22/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "d7ffe70ed73bf689c3edcccc1bfc23ba75737f2d0841d471720d23a67b2cd63e",
-    "dist/2021-08-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "704a086e751b96f1249bd295a9dc45f9aeee0d93bf96d2d6fe00ffaf33af3062",
-    "dist/2021-08-22/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "c7ea8e97a90c4e27f910f8ef1e64885540179dc55ef09e4f5a844bb7ab3d0c9b",
-    "dist/2021-08-22/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "2165a0868d21ce1cf10e6360f8384866a985358475cae1bfa74d33d3516db565",
-    "dist/2021-08-22/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "6909a1ace7b22fa66b175cbf3de0cc54708f0aa73baa3e2168f3e758698c26c8",
-    "dist/2021-08-22/rust-std-beta-wasm32-unknown-unknown.tar.gz": "dd2eb7f4fb9285c11cdbeddaee20a75179a1588486ccbcb7b6e32971790acaf6",
-    "dist/2021-08-22/rust-std-beta-wasm32-unknown-unknown.tar.xz": "9e51dc30f624af1410a77b4f77f01868ec141d6288b09827f7e3a313b276f78a",
-    "dist/2021-08-22/rust-std-beta-wasm32-wasi.tar.gz": "b29b2748928aaf72aa30117cfd8bd9c6c13a6c7255efe1bcbd6bf535aefb1294",
-    "dist/2021-08-22/rust-std-beta-wasm32-wasi.tar.xz": "90f58b108a9538e190fd3ecec97581b95c85ed27ebcbf1f4ef85b4e3248db0f5",
-    "dist/2021-08-22/rust-std-beta-x86_64-apple-darwin.tar.gz": "b6549bfeb4ad3de444ff7afce6baaa34ee7468d41480a86072cd3a26e1191de0",
-    "dist/2021-08-22/rust-std-beta-x86_64-apple-darwin.tar.xz": "44d77279c9997ebc5f4952fde208de6747f6b95e1887c1ac637f3f5170cda003",
-    "dist/2021-08-22/rust-std-beta-x86_64-apple-ios.tar.gz": "3a69d284711c0eab25a73b6d22a3fd92e6741e22a454d0210694c73c2775e6db",
-    "dist/2021-08-22/rust-std-beta-x86_64-apple-ios.tar.xz": "08b97affa6264d739eb31925f3d4a2fb0feb32e6b3eff770c580782bea216ca0",
-    "dist/2021-08-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "15334ea58e51d1d5f35f15c75a0f941b3648d9bc2acbb57a6c07b788c78aa6d2",
-    "dist/2021-08-22/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "7aad1c1dc41f5713fb9a3414b0cd64b78f3b8cd6bd12a9fe14318cbab5c804aa",
-    "dist/2021-08-22/rust-std-beta-x86_64-fuchsia.tar.gz": "48e706203750b335276140b8156c5c74ed48cd36aa7a6f732f7febe3d517da76",
-    "dist/2021-08-22/rust-std-beta-x86_64-fuchsia.tar.xz": "d0a14f312a2f91961f955352f6e508cdf5e5ac82be10837843ec7c87ed9d3ff9",
-    "dist/2021-08-22/rust-std-beta-x86_64-linux-android.tar.gz": "12a29451878739ba28838a8bf0eda9ab4826457a6ef249644bbe11e3afbde650",
-    "dist/2021-08-22/rust-std-beta-x86_64-linux-android.tar.xz": "f2fe871094a8dbd11bf15d9139ca0d630b9fc2c03d1bfed295d1ee01a8484910",
-    "dist/2021-08-22/rust-std-beta-x86_64-pc-solaris.tar.gz": "42237c674c4c5f6181da0eaeffc755a08087b87350770fca6a3d707158cd66f4",
-    "dist/2021-08-22/rust-std-beta-x86_64-pc-solaris.tar.xz": "167aa8827682e3a6c140a7607ede1c0ca90014634940c228dc538263b6e1ea8d",
-    "dist/2021-08-22/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "7517896917e38d12d3265b0202ea8bd839d8cfd08b9c6b2c6033b5f70d24f049",
-    "dist/2021-08-22/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "902b1a27c034206fd03457a52eb495c2bed5d3f4355e4d94d1dea05746e10df1",
-    "dist/2021-08-22/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "3b2143072753553cc05d40e0684fdbabe6eb8c436588ce2f29ca393f3c5a8609",
-    "dist/2021-08-22/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "47d03efe92f8fcfbdb192565dcf4db4e4c1c301ff4bd8cb15e0ae74c5ee00122",
-    "dist/2021-08-22/rust-std-beta-x86_64-sun-solaris.tar.gz": "7394b58442de5d444c1fdaef7d91da57f6bd64a50ccd8be518e2e620e0829036",
-    "dist/2021-08-22/rust-std-beta-x86_64-sun-solaris.tar.xz": "4839a52f87ec51bdf0438dfaeb57f3757b481ad47a7e86db9740d3e86e2c261f",
-    "dist/2021-08-22/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "a44012100040021f42335ba35be08570c86d72c371783e203fd1a6144d46a6fe",
-    "dist/2021-08-22/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "7279b03775bd896709700727d9db6030a05a4cad3842c1b225404bd1545a0ba9",
-    "dist/2021-08-22/rust-std-beta-x86_64-unknown-illumos.tar.gz": "ee719a8fc9a6a5ba1d47fc5d95ebdc8f692b473ed22202d3315de1aebcbae374",
-    "dist/2021-08-22/rust-std-beta-x86_64-unknown-illumos.tar.xz": "a85f334cf580035472b054383365c6da4509aa85a3901e6d30649c3e6f1af4f9",
-    "dist/2021-08-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "96884f6544e2d51034cac32618e4e35ee0c84467d8a80f635d8073980fed0ce6",
-    "dist/2021-08-22/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "98f745588c290a0319216d067a60ba3665506111bdcc4a773b5b850f9ac8107a",
-    "dist/2021-08-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "cb3249e99fd60a57cdab4a529c14eae3d76fc85768ec9cb9186eeafc32f45214",
-    "dist/2021-08-22/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "614acd645f9c79eda648236e6f3c028d9bb5482297059bfc93dab9f2e90d1478",
-    "dist/2021-08-22/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "c7988d678d330d31c3e88df27b9c2b482854d0b7f277f8126e2996a9f4180387",
-    "dist/2021-08-22/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "11d16c7f5b64e3d4bcfcad489c2710ca7e3cad12c82221848c51ed839688e02b",
-    "dist/2021-08-22/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "45f880920e746f53810fc70526e18ef807e6d4089ef147bed8c53c536624f646",
-    "dist/2021-08-22/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "0910b51938eed74ad4af9e07f74ea5648a143fbd142a9cb4fe1bc7f7b7bd6159",
-    "dist/2021-08-22/rust-std-beta-x86_64-unknown-redox.tar.gz": "c14fd257005a11026cc3ebf23fb9f2d35a6d99f9136471574d8c0d18fc66e3b7",
-    "dist/2021-08-22/rust-std-beta-x86_64-unknown-redox.tar.xz": "9c3438ecac2dfaf827039b506c114bdc06c05a69b81761abfb63f8a227950da7",
-    "dist/2021-08-22/rustc-beta-aarch64-apple-darwin.tar.gz": "357bb650d7377610e61a9ff2167a7fd480ca844322849e5dcc80a91edc5fffa5",
-    "dist/2021-08-22/rustc-beta-aarch64-apple-darwin.tar.xz": "3f0883cd2c1d1bc31dd89a72711ba6a22a1c455f28dc2d5644e70898614a637a",
-    "dist/2021-08-22/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "6366923332e491d21b5f448500fd56673fd21738e6edcbdb21c11fafb00723de",
-    "dist/2021-08-22/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "b0e7462540e6c96b373f6aebf6ab58ca4c2cc62627c5c5ec8b135516ce9098f9",
-    "dist/2021-08-22/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "21bdf608d2bc3799206065225410ccbb015a379cbcf79a901e4e9420d1a4feb4",
-    "dist/2021-08-22/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "4b1520615af8f2baad919740716c482cd5ac421bd87e44cde21788e79c996a4c",
-    "dist/2021-08-22/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "4aece49879bb274f0170b98941fa220d1ae4f1c4cb33c3fa7ae4146679675d1d",
-    "dist/2021-08-22/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "d3c565f7a2a1bcf21849122c1c6fbbf81ce1e8dbaf103e8f5c406b2f35aadde1",
-    "dist/2021-08-22/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "311df5769ba9a2889c1e9a97df6c1bd369224832a80789bae339121138e40513",
-    "dist/2021-08-22/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "e2818874f3f3d873e858e78585e60804971d57e206c023e8a1c82d03cc9ee5b3",
-    "dist/2021-08-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "9bb1e02517abfe3e626812cea2d389b26451db341bd1c56f5c06f90a71936cde",
-    "dist/2021-08-22/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "fe02b9b389297a781bbdac812ac3526973a221edc2cd7b2be4fcb197e817b148",
-    "dist/2021-08-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "c6733d130bda448d7801caa215d3f58abd6576119eb764a55c326344fcbbdede",
-    "dist/2021-08-22/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "0a553a9821eb076873976bf523c8b1278de367854d6fbca0728bde97768c4ec9",
-    "dist/2021-08-22/rustc-beta-i686-pc-windows-gnu.tar.gz": "c5a724275014bf1c244ff6ab878271747097b3f216e5753e3ca65c1714a2456a",
-    "dist/2021-08-22/rustc-beta-i686-pc-windows-gnu.tar.xz": "0a6ff560eb1a7d02e48661939bbb940cdb5d988ccacbcbdc0f7fa24890b0d9b2",
-    "dist/2021-08-22/rustc-beta-i686-pc-windows-msvc.tar.gz": "da487112240ab21c3b3f9d9816e7b4738022f58ba0e93c0772a8fcbb17ba0573",
-    "dist/2021-08-22/rustc-beta-i686-pc-windows-msvc.tar.xz": "944bd6f24ff92a748c804e3deac1994fe03cda4b897be3eb12f21d069add4cdd",
-    "dist/2021-08-22/rustc-beta-i686-unknown-linux-gnu.tar.gz": "e986624d0a97155a588c9b95c7470c1b322bbae11f9582ad62d2c914642400d9",
-    "dist/2021-08-22/rustc-beta-i686-unknown-linux-gnu.tar.xz": "dbaf95a9b3f6fccab5d59533be35f59b7901b31e61488f85032bd15bfb67eb34",
-    "dist/2021-08-22/rustc-beta-mips-unknown-linux-gnu.tar.gz": "374bd970d5cba1b9af4a36250dfea2eaacafd9e6b4b0d4d9165abdd11841d4c3",
-    "dist/2021-08-22/rustc-beta-mips-unknown-linux-gnu.tar.xz": "2ddec9e30d15f2e1f05e9a59c739f1be51fc8d836acda395aacfb933826a5637",
-    "dist/2021-08-22/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "a21a1c099324517b6da6dfd8f2154b4d32bfe69d3a1f386e1bc5be2c3743b938",
-    "dist/2021-08-22/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "b81fa8c2d534386ceb0bb0767c260e340cda7122e23c834afb17097976ff682d",
-    "dist/2021-08-22/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "2822fdb98095c292a4e0b0e6ee3be4e1cc5ffda42dae101b2c6a6c4bb7a1ec4e",
-    "dist/2021-08-22/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "7d40bef08d3f0d097755eae0b26057f579fd40f4968dd9e5cc82c2b9b67d9c0e",
-    "dist/2021-08-22/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "f64962ca9b60013ce98e634ebb5207dac14c7b39aca5de37db8a6b3debad7250",
-    "dist/2021-08-22/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "a3f8dfb574b3af0ac48011cc7ec69d9f3e89a1994a475c3c6920b0a110db141c",
-    "dist/2021-08-22/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "6dcce24fa93e66b69495df2d8e9aee15bbba263945fa3dea5cdb1d2c499c9744",
-    "dist/2021-08-22/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "038d888fea4ff185329b4ac93066167ec7cfd05a3f23be0a2fae5b8eab51d0ac",
-    "dist/2021-08-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "6a83680ff659d7b9717639d56eb18c230162ee4983ce5ac4aef78b8d9d0829ef",
-    "dist/2021-08-22/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "43313c88c1950ec36549f023d8e7b6c6cccb9749159115dad5255451c65f98c8",
-    "dist/2021-08-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "635544e9035d213ac7e3a82d08b445b2a446119511c219c0ad870f185133f76d",
-    "dist/2021-08-22/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "e2fca8f43e37ed2d4896df1429e9b806f02b0e8bdd0f136cf16f606eb1ac15e2",
-    "dist/2021-08-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "ae8bafeb6423cb270b3a2538db07946d35f2514d5d5116ea085a78e4b80596aa",
-    "dist/2021-08-22/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "c8abe082666ea792414943eab46d00727acafa97760e799a4d22ec9ff27a810f",
-    "dist/2021-08-22/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "b680196dea6eb4bf49afa002e6115645a67c2f7ed6de8ffcc0ace6ed2c193c76",
-    "dist/2021-08-22/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "1d3cca881398f45c8ef9db64820cd2afb542b55517c9ea66b71955a31fb7fad1",
-    "dist/2021-08-22/rustc-beta-x86_64-apple-darwin.tar.gz": "493431cd41fae24883877615ca83c1a4e94cafa7e6d6f587dfcce9782c36edaa",
-    "dist/2021-08-22/rustc-beta-x86_64-apple-darwin.tar.xz": "08b5610cc53cfe64914866b115ca15d184df83cf0c8bb65106380bd875bf62cb",
-    "dist/2021-08-22/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "17c0e93976b2a83df5f6baabd67412389550f3694268e5478440c8579efbbd18",
-    "dist/2021-08-22/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "0e736cf5ac25a78e611ea89589a8f6f0eda9891646579fe0a0b8853ab210ee19",
-    "dist/2021-08-22/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "33f17eb3e95e4b00895c234f5d2d2c9ce19d1d36811bebc3f92bcfeed770a6bf",
-    "dist/2021-08-22/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "b26e0adcfeb9b95dce5d39c7d34126a405d9705cf58a6ee560b10eeb274b6ef0",
-    "dist/2021-08-22/rustc-beta-x86_64-unknown-freebsd.tar.gz": "27d6e27acb2d060b59e35789b81779f48a520670ad1590cb46b9862a6be74a63",
-    "dist/2021-08-22/rustc-beta-x86_64-unknown-freebsd.tar.xz": "39670b9f1865ab74458dded5a9e9f181045c8eb7e7bc82ffc308fcbc5bc26267",
-    "dist/2021-08-22/rustc-beta-x86_64-unknown-illumos.tar.gz": "d970bcce7178cc0ddb96de50450da71b236ab56861efd399da03f916ce059685",
-    "dist/2021-08-22/rustc-beta-x86_64-unknown-illumos.tar.xz": "6d6bda8752a6b205ca8e155624f671e716e80c78256f052c22dc2e53c379b589",
-    "dist/2021-08-22/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "e667282411745dfa982922d139a26058097250c33e83ca955e75b65c6098f651",
-    "dist/2021-08-22/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "7ed509f918aed5d259479663911427564c066b41487d4550050a9c07096344d9",
-    "dist/2021-08-22/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "59b3aac5504deea4daf79d5ee90951c3df5247568419a3605c8895698e7a460c",
-    "dist/2021-08-22/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "941f93fd0a542b9aa6b35fe26a5145085cf758c10b185e9892acf52796efe944",
-    "dist/2021-08-22/rustc-beta-x86_64-unknown-netbsd.tar.gz": "755987f90f50bbcf9881f62849bfc5749e41d95e5d6b2a35c7fce4218ba3dc60",
-    "dist/2021-08-22/rustc-beta-x86_64-unknown-netbsd.tar.xz": "09cead4864a49e750d91438149b74fa4c0d4b923efda40ba638b2ca0d3ad97c6",
-    "dist/2021-08-26/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "17e7cb26d7c13cc14d826966a4b93e9c152b46f2d7081038e8d3385ed5d3ba43",
-    "dist/2021-08-26/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "85f896275ecef1d491bb8beab54ab13d612d49fb8386b6b61d9121f52fb15e44",
-    "dist/2021-08-26/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "e948e456f51a9fb983d36d15352d8e7782051e1fb62a4adad2ae973725aa6091",
-    "dist/2021-08-26/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "d21b59cc2c1706e9c14bf1464b17ed5bd51e2d225e1b3ea53c13d90ae34d4a2d",
-    "dist/2021-08-26/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "a51b04fa8b159ac5c80ec1db0518cf589a8530820863870173347941a5d3e0e0",
-    "dist/2021-08-26/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "bbb801bd4ddaeb4d2494039943e8ac746fd41fb625d3c544af2a79587f9e327e",
-    "dist/2021-08-26/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "8d94c74ac727b381433ff010d6a5b6576d326c88418afb1ee8a67de5731c1bd9",
-    "dist/2021-08-26/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "da44eae518dc561f89c810d4a5f50da38b938e22542193595be615c147973ee9",
-    "dist/2021-08-26/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "11e8422a4b4ab386015c54cf488c40297e6b63006989c40b1e4321a325333433",
-    "dist/2021-08-26/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "b8e835cfd7f32a823ed00d174c4158220b8572c2d76486c60a20cbdad11bb216",
-    "dist/2021-08-26/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "ff7a412a7923a24cb118979cc772863e6d9844ab6bcc619d9adca6d36b89daf8",
-    "dist/2021-08-26/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "4fcf56bfbae46ff5cf7c28d787992d5d108231659e447cecbd25035009e0c783",
-    "dist/2021-08-26/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "4ae574d1aab0e0c191327fa5ad79a4e9367702ef3fd1655661a8c253bf55b7e3",
-    "dist/2021-08-26/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "8786f646813f5ab71f5786efa6cc14e567a9dd1b2532b34d9d85ee900dafe68c",
-    "dist/2021-08-26/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "752fdf667b1f4713b6ad3378a15835902fd7fea200c8d37f28a444dc3616b89d",
-    "dist/2021-08-26/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "43e401e2112120970c4a7e3dacbc5ea631c1816f27db33a28f5b9cc49e4dd5da",
-    "dist/2021-08-26/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "6935d612513b61092b36bae3a2cb11c29e05cd8773c65aa61b4451dab8cb9f43",
-    "dist/2021-08-26/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "326177f9fda4923b010fdbefbb9703aee727b4d2871ffb1cc97321c09fc3ff51",
-    "dist/2021-08-26/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "875d3d7fc0e1cfda7b029656b27436f2b9d332b3f46988dba1cfbfd8d244cd7e",
-    "dist/2021-08-26/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "4b3e9d27d256cbbe65c0330d557dbcdd6b6144222936680705f9e74deabe80f0",
-    "dist/2021-08-26/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "d26a73c2ccaee81d92980a3cca0508abfce7a02f56f25f3bf9c06e6fcf3aa537",
-    "dist/2021-08-26/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "3f69c9a1161aeb25f03681e43d35388bf75a0e20e086d6e353911aa839fcd294",
-    "dist/2021-08-26/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "401fbf935e3b06e185f4426a655f2d38e058409921486758f60363f92bbc8117",
-    "dist/2021-08-26/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "325d89dc02f7aea4803539211c45d8044986d55f7d1331a231b5d0c0ecfe5238",
-    "dist/2021-08-26/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "3da7ef60aff98439a1c58d504bc62aac1d2cfa29879a28968c5a61b72e9fa33f",
-    "dist/2021-08-26/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "3aa2757120df94d2660b7e909e4a7d66aa73ca9f9b700231d1f21bdea2b0b5db",
-    "dist/2021-08-26/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "74a28139895365cdffdece9920ba6fd31a982cd5620342fbdd653084621b7726",
-    "dist/2021-08-26/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "7915f9e15b274e938d5e318544322d233434b6554a25ff063181e7f9cc8a8ef9",
-    "dist/2021-08-26/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "3b56ab5ce09e8f90ee80ccfcfdbc30f52309547b5123ef474a78cbbd6ca64dad",
-    "dist/2021-08-26/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "dcb27f9d9f425b81d7ac21025eae60b2e5bbb4cb1e2c21e6970f28e5a574cbb6",
-    "dist/2021-08-26/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "cb5627d2075b726c4a30b36cdf234371d02f1fe0b545fd50e02b65588b7bbe5f",
-    "dist/2021-08-26/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "d7d075dc678d545fedfdff220dd6b9b9c91cbf5b58fd9cb486777c596c20c20f",
-    "dist/2021-08-26/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "fe6af0046c2a6cc8c66d0d51590c7a725115fe785b06bed555c9c68dfaf9819f",
-    "dist/2021-08-26/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "559b98d646138414c3e0878bdc8245db35c17f9e804ccc0935c4f397672debcd",
-    "dist/2021-08-26/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "cda6141eff957bf7f7580b093d261d690fd660961722c37b19c390cb4ce85ecf",
-    "dist/2021-08-26/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "7c4eaccfd5704b0d6e7dfeb6cd70922625df90391f1e27e48bc75f0e79b3832a",
-    "dist/2021-08-26/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "1d16189f4fe2c5d6fb572e279eab121408c1d85d5fecb6a3f25b00ed748b8b14",
-    "dist/2021-08-26/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "99be46da8f40418b48261e61a645acd4755c132baf9e2f3a2ca64e853daab9ec",
-    "dist/2021-08-26/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "82daf2631178e46d94ce2a2718327c5e17da755397cfcddaff4b9d695aa88f3a",
-    "dist/2021-08-26/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "6288c9cbf5e33c59597d990bf99c9536414bb73aa0bcedf1175dab4c6dd9d188",
-    "dist/2021-08-26/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "29e13fd9d3eb61ea609bbb55bc5f36df094623f1f1a154d9554212bf4021b8cb",
-    "dist/2021-08-26/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "c287a80d6388527213d820c22d723fb9e17018425795f499521e7580ed9f6aed",
-    "dist/2021-08-26/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "2eefa9ae776a7760b3111b39e2c732d2303c4aab2e124cfbef2f7dddc32bdc30",
-    "dist/2021-08-26/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "a5544207cad0be04393f3a17f8f743340bf468d20a60aa44bbf3b1ea476e54d4",
-    "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "b4dfbc422e7b51db45555e6d1b775b214bf633ec6c93303fb7c52e4e25db69e4",
-    "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "158c6366adaaaf17d0d40f64a9c8887fc20f1c7600fb31b102fcc3bcbd388221",
-    "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "6fda2931d41c4c42b5f59df4a789ff3c2082ff65892e1318439aec555834a34e",
-    "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "25a2823ba3668506fe9bb85c1f51d2406b8654c4197d1dc7d88ee19f35e77756",
-    "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "2a79c57d33aca5bb6c0cc2497d6853a4df259537ba55acc66460be03c82cc9c0",
-    "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "065d95fc9b2d741ba1e8d20b90820a6ad72ce0cb802fd24842aacf01c3a7a589",
-    "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "313ea554f824d0176f44406ed70854736eefe94911182396c896ed454a07e6b8",
-    "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "23cce7c791cc4f49d5240898803b47f393b5f2f064a3273ffd290a8cf97b7591",
-    "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "0416a1a4ad3b9c9e1bf7bd67e49f16e7a4011ebd784966f439ac04a87cb4042f",
-    "dist/2021-08-26/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "64b29ff6dabc46d124ccf08e8fe351a2d46ed527efe98de36d38c0ec59b226cc"
+    "dist/2021-09-08/cargo-beta-aarch64-apple-darwin.tar.gz": "5bc2e21b10c153fd070c1a9b9af8ff68ada71f10953d8261bd8aa5f599878db3",
+    "dist/2021-09-08/cargo-beta-aarch64-apple-darwin.tar.xz": "95082b292ccf8e0fdd637f591dd3180297c48ec13ccbcb3e1a2c115feb17463f",
+    "dist/2021-09-08/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "7de49c4e1db688089dd566647c23233fb4ff21dbb4025a4be37d18b11cc82e2f",
+    "dist/2021-09-08/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "35394e3c08a3dd392958187b091b3bdc576a6bf0d2d139556df21cd3ff1d21cc",
+    "dist/2021-09-08/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "a71153dde967a7816636dce62ba4334baadad4b926b25dc54c068c5cb293df9a",
+    "dist/2021-09-08/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "d4e33616af35dd7564a73e702eb6eab7eae5da7a980f518bd3d34f4cf0d05440",
+    "dist/2021-09-08/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "f76545e48977d2ebad75d3cf745d81ca709d59ca02a6c66ee3d049d8ca145463",
+    "dist/2021-09-08/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "79cf346367022c3a1ba58fd134f8189fa7781e702871d56f60dc1fff9d318570",
+    "dist/2021-09-08/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "7884e6a177a2469f21dee177564e03490fc541e877f0a1858e17162a9037298c",
+    "dist/2021-09-08/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "6fb307038c827d4e915224bc17709929628bdc5eda625644eaa4df992de75718",
+    "dist/2021-09-08/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "a367fc19f65b07cfec4732d3bd13aa662581d9aca886d56c93bad171948c9593",
+    "dist/2021-09-08/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "161eabe9fc1a0031f9fb044da4cc4c2cf376c6a018695f9fa1f5d7ce96c742d1",
+    "dist/2021-09-08/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "35587eeb680443f759c6cc9526186d51e35b08683f9c8a112d692324b62afae4",
+    "dist/2021-09-08/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "8fea8765c22e9751379585d381ad14aa0faab811cfaf40dbb55a60c82146b91e",
+    "dist/2021-09-08/cargo-beta-i686-pc-windows-gnu.tar.gz": "9e7e075e79cfca74b1185067962e3b37118ed32c8258d6746f05891f742226cb",
+    "dist/2021-09-08/cargo-beta-i686-pc-windows-gnu.tar.xz": "50f34954765c542076e7a6d9dbaf3a8e8dbfbabfa95bbc76e95eb1fb52e1227a",
+    "dist/2021-09-08/cargo-beta-i686-pc-windows-msvc.tar.gz": "eb93a58581ff485b44013d3623d0f4afb0fc2e3a3c7ff1898b74faad6f7bf48d",
+    "dist/2021-09-08/cargo-beta-i686-pc-windows-msvc.tar.xz": "1913dd2d4b0c56a6e5ec3686fa03eafc716006cc1fcdcfd81cf1b7984b9532b1",
+    "dist/2021-09-08/cargo-beta-i686-unknown-linux-gnu.tar.gz": "04b3f5ca4f4a24a2555c186600f683730a59f807d3525248c1d8f2f674cd00a6",
+    "dist/2021-09-08/cargo-beta-i686-unknown-linux-gnu.tar.xz": "c730e3f619d69d221277f3b44a188746980eb7a0c79dab9a252cea6bc4a1e54b",
+    "dist/2021-09-08/cargo-beta-mips-unknown-linux-gnu.tar.gz": "94fc426e50671c39d7a272b9636ce43bc3242f1b6a302555914127ab73ce6c65",
+    "dist/2021-09-08/cargo-beta-mips-unknown-linux-gnu.tar.xz": "c44957519099e19edfeceed53b99674d9b98731b20ca7494621fb0dcc6488ed5",
+    "dist/2021-09-08/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "377a998bba44a16bb401bf56c4be2e38f1c40e37f71335f93ba8e54d20d7a3c3",
+    "dist/2021-09-08/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "2406c2ac61d9b494b3a6327d991a6846a18c867fc581892874a2e3e83f4d49fe",
+    "dist/2021-09-08/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "52c7d8009a6ca8701912c9e02c1278dacd2b6c2bdb218416d1e3db2c750b7536",
+    "dist/2021-09-08/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "764820946adfd6594c7c9c4f97cb06d1c639ae2621ded3059d234a0cef97b1dd",
+    "dist/2021-09-08/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "d351cbcd87d10d54bde4311d6fc902a655e8c74ffb16b2a85cfb8e5ad30faeda",
+    "dist/2021-09-08/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "ec7235af6ae25ce30c61d06f94bd398018878b741d8d94edad8e3dbaaad0cc2e",
+    "dist/2021-09-08/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "11d983f439f46a1b49d72b0e8ec1dd5f78c72c23f305476ce3b56ec20167ccc9",
+    "dist/2021-09-08/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "327fcdfcc7679178e734293e23e752d44bf1a4c44a88e5b2d89bfa7f95b7876c",
+    "dist/2021-09-08/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "52f827f09376c0f21419cbff1e56d30337d140c1c097d5a38d4541f65545d3d2",
+    "dist/2021-09-08/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "e9f956aaa4f8428b813d27c43a8602671a27f567d206f769da7b14e5029f5a1f",
+    "dist/2021-09-08/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "b59d4814b99031a9e418fd423833500a3436b65b0696974d1d6a2f7598ecce2d",
+    "dist/2021-09-08/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "5751e2453329e1fe2378cf9e7ade93c75df7a31d4dbeb0f14fde9c3cfbc5d5b1",
+    "dist/2021-09-08/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "a3d97d9efad02108166878a9a30d3485a9f6db0768bbef5c98e86540c6f4901c",
+    "dist/2021-09-08/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "e8c3bf169cdcf9192363c9ace37457a94720d36ff1b607e178796dac933f652f",
+    "dist/2021-09-08/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "51fc38135a45870bd01bbcee4b69f5e7055424b1cfa36d4c0272613baf3185c2",
+    "dist/2021-09-08/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "bc392d660368c856ab1bc96b603699d492f03b226a0d60812a1bb19ca6c05ff3",
+    "dist/2021-09-08/cargo-beta-x86_64-apple-darwin.tar.gz": "ea1804dfe7b806368f278adcb887e4aa023ff7f533bee84541415cb0862ed836",
+    "dist/2021-09-08/cargo-beta-x86_64-apple-darwin.tar.xz": "69fa3524d2bb2bbbf0c0a4e18ecbec3eeae791f9b60547d6adf0fa20123c4a41",
+    "dist/2021-09-08/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "611c3653a03ca05effb06b5857b77cb24fd87ae5f1d294df980c96a57b8a9a74",
+    "dist/2021-09-08/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "cca04b2298bea6b447daa806af2313da4797072d27ecc3202bd0633b5a1d5fb4",
+    "dist/2021-09-08/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "763d4ec911a374d348468a38d07caa8d559330c6179f5cd40b5a54ccdb355580",
+    "dist/2021-09-08/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "37d24786e764c3af201cba07ef88a27fac97d150d7711cfdbb625e957b9f0139",
+    "dist/2021-09-08/cargo-beta-x86_64-unknown-freebsd.tar.gz": "f39494da3f92c39be50579f26d7f09d8e5f985e3566f8742aacc1446ab9f92c1",
+    "dist/2021-09-08/cargo-beta-x86_64-unknown-freebsd.tar.xz": "b65f8024b47d4784ab59e4722e522e54442852bbe16906760f2708e2b0d0fe65",
+    "dist/2021-09-08/cargo-beta-x86_64-unknown-illumos.tar.gz": "072bb564f73a97bdc6d58970735191d8da0831926dcd155a946f0fde1f382a02",
+    "dist/2021-09-08/cargo-beta-x86_64-unknown-illumos.tar.xz": "fc6a9c6d4cceeac868b37e200ed193981b8d70e8408d8e4b4765e149a9075c3a",
+    "dist/2021-09-08/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "8074fc6912e4bdbae269a334f21d0ead7bb0f28344ad67d71f65487baf21cc35",
+    "dist/2021-09-08/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "32a8471b2fb91b62aeda637bdb1368c67d1b17daaeea2592517666393857af16",
+    "dist/2021-09-08/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "19dbfab31784d0615d0e84c526e98d9f47332492744bd1ab4fc7434c0762c5ad",
+    "dist/2021-09-08/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "510734acf369b92a3f1eb30921a96f393ae207af7dffe6a83df66c350bd1a510",
+    "dist/2021-09-08/cargo-beta-x86_64-unknown-netbsd.tar.gz": "85e2fb4ab2ca3eff3ce98ab1c74c996a6b9cd2c20ff3f47c8624e261ac254195",
+    "dist/2021-09-08/cargo-beta-x86_64-unknown-netbsd.tar.xz": "2b1cff0bfa9bcece19e61f4be680ebaa05663e918fc9f3a20516efd91244e1c6",
+    "dist/2021-09-08/rust-std-beta-aarch64-apple-darwin.tar.gz": "54386650675047126f2b418485a5b2ca8bf3b568231fe54914512ae09809276e",
+    "dist/2021-09-08/rust-std-beta-aarch64-apple-darwin.tar.xz": "c7613b2089562353502560a6521139dfd7fd58a96c772877cf2ea7bfd62920d4",
+    "dist/2021-09-08/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "a80e59fa3885f73973d9c3eb50628718eda015b1e62f328152ee95971acb10c2",
+    "dist/2021-09-08/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "b0b65575680186ae6c032fabad5dd4352d17ec2d29ecc22771ab9f86a54b90e8",
+    "dist/2021-09-08/rust-std-beta-aarch64-apple-ios.tar.gz": "22fdfea8abb345a32ca47ce658c601c36d7838cf22383a34470db643a14e89b3",
+    "dist/2021-09-08/rust-std-beta-aarch64-apple-ios.tar.xz": "3a145167eb7bd82e59df7bd009f69f4951efb1487cf002c584625c24be35f4c0",
+    "dist/2021-09-08/rust-std-beta-aarch64-fuchsia.tar.gz": "97d1614ad18e71a09326d65ec4bb631c9974f4d3c63c9438b180646579227f7d",
+    "dist/2021-09-08/rust-std-beta-aarch64-fuchsia.tar.xz": "aabd6f6c8548b6576986f6fa2632ced035f0ad504da05d3dfd92ab0202104ff9",
+    "dist/2021-09-08/rust-std-beta-aarch64-linux-android.tar.gz": "5e67121330fd7e095f86c5dc71bd5180ec1669ad819ccf0bb4b38b46f35bcf94",
+    "dist/2021-09-08/rust-std-beta-aarch64-linux-android.tar.xz": "b3d72ba51cca485d742117c70915a5e57404d3f8c80356c8df388eba913e136d",
+    "dist/2021-09-08/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "f3eaf16070eb770d464a844e72257cca4ccce4ee2c380f276e82d259d8781326",
+    "dist/2021-09-08/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "846480e3eaf8d21fb4d99659a68e71259da613e54cfd098470c139e38ea5a447",
+    "dist/2021-09-08/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "198be5989e4d2d479582ef2002ec3041105555cbb86488ba563fce35ae1c5c18",
+    "dist/2021-09-08/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "706148bf9e562cf61d6f882a330e0fd150eb0593136a370cf559c54b6723f4c1",
+    "dist/2021-09-08/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "8e2718c2509c3db0696599dbd93f7a9c846228374ec0e24bf9f7b876a7714d71",
+    "dist/2021-09-08/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "e44e11ca1ac94d2335c19891fc8b85394b3935a86fa51c8a2c558faf8606c7bc",
+    "dist/2021-09-08/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "9439bb56b5c11e9fab00e02e7f931c4582a6dbb3aeb7b20e5ad0fe5420dd27d0",
+    "dist/2021-09-08/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "5e3187685291d52c500aba70de657478e08b5a69ecbf381f2ae41cb78cfd82d3",
+    "dist/2021-09-08/rust-std-beta-aarch64-unknown-none.tar.gz": "69c5da7ba93aeb93f8f7a6b581f1895b427c377c8f624274cf2691cacf845acc",
+    "dist/2021-09-08/rust-std-beta-aarch64-unknown-none.tar.xz": "8d66841c5e9e20d35b3791bbd10fb97e73b7abf602fee52a939a7096e0040eb0",
+    "dist/2021-09-08/rust-std-beta-arm-linux-androideabi.tar.gz": "4901f22f057d78331d298c23b66a39b2caa39580b19adc007fa8a4780483b27c",
+    "dist/2021-09-08/rust-std-beta-arm-linux-androideabi.tar.xz": "ba5d5016a625f433dc2fdacb3a1c462a08cdf9cdfcd202a966f16386e58362cb",
+    "dist/2021-09-08/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "0ea2986826d17ea1baeecda1c73af27e41830d22aa10722ac18e1427a3c11295",
+    "dist/2021-09-08/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "11e8397c3b6cc2f0ce7c8d725e8bc8dd0a7b7c800174ca3f4da6ee4c32e338e9",
+    "dist/2021-09-08/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "019fb984e383342a3ec4069f7f62bbc33c9b9609202b571ae32fe6b0ddd2dd60",
+    "dist/2021-09-08/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "e86d5310c9181ccfd432bc93e6715d109f26608bea97fee0d9f0d2efaaa7126a",
+    "dist/2021-09-08/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "1a7c7bf25c54c9a394a671d7f23e5cb08d6501b25bbb687159a208dfa16b0d33",
+    "dist/2021-09-08/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "e8deaf7cf0031d73e93ac1f61713836a0413f644639f8f602d234bd583c660c2",
+    "dist/2021-09-08/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "0d72ae75cc1b59146dd799cb85a8c60ea9c4169f53f17b8eeb74da644bad0e21",
+    "dist/2021-09-08/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "1dd8c951a7e13e68686e9a9a3eb0ecdae83fb178454a0ace9c649b5b47fc9a50",
+    "dist/2021-09-08/rust-std-beta-armebv7r-none-eabi.tar.gz": "8b4b4163b746618c2dde450a7151ccdbfaf9732311fb959d11336bd78bfa8d25",
+    "dist/2021-09-08/rust-std-beta-armebv7r-none-eabi.tar.xz": "fa6ef79c9a3ac07c0cebe908eebab2a32f578f0838c0f939bf8f4136aed7a499",
+    "dist/2021-09-08/rust-std-beta-armebv7r-none-eabihf.tar.gz": "487c64e8251564373437f94b5e94d81bec50b61e77c39c691ce912cf95236d0d",
+    "dist/2021-09-08/rust-std-beta-armebv7r-none-eabihf.tar.xz": "2bae0e0b2383ee6182ce8df4dd26993aaa56aa4dd89e6cac1982a48414ca5d5c",
+    "dist/2021-09-08/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "bb5ca2b48383b27d181d90e4802cd387cacab9c00fca853c0deeb317270851b0",
+    "dist/2021-09-08/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "f7bf769be48434faddf3dbed8264b1ab5dbbb3657f5b71640ad9330b3340ca29",
+    "dist/2021-09-08/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "c88db813417a1263408cc3bffeaf03b45db7b2c0a89c8441b3f4e7514473a0c3",
+    "dist/2021-09-08/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "3c5a3ea4ce9a6826dd3fc1eaae8615701bf3b5c53d56fe6948432229f027ac1c",
+    "dist/2021-09-08/rust-std-beta-armv7-linux-androideabi.tar.gz": "3d45d64267149d222337421be4cd5207812125f9b2df253f507f0cc2cba37219",
+    "dist/2021-09-08/rust-std-beta-armv7-linux-androideabi.tar.xz": "ee71e74b369b42a9c2258bf5d9c8c7119ee65b8951d4655c477a4593ec2cf3fa",
+    "dist/2021-09-08/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "949bce55fc6047a37f8ea26e21cc69557ad66a45c688442f2be06a8cab503358",
+    "dist/2021-09-08/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "28ec52f486459b436c0097db2b400a202ad1280591f2612cadf4daec1ef4e4a8",
+    "dist/2021-09-08/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "0f7782f0b6874c858de7171d255f12fe309e9255ad55a6406577feae3702fbc0",
+    "dist/2021-09-08/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "cf3bc863ecd6da3fb45c3d2f5b6741d57ff778b1bb2e4f0d05480c9aab480bbf",
+    "dist/2021-09-08/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "35e3647a940d2e2e37ed3a5b7c1a789f94b7f1a256f0bd339630bb7b0342c2e0",
+    "dist/2021-09-08/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "ed1ec913fd3e821501e52be1d3cdac3fbe5a6c00acd17204b1891aa5fa3e6f93",
+    "dist/2021-09-08/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "2fc9f5791717cc876d155f4cbb672dabf9fa308ac67636e50a75a5b5ea11369f",
+    "dist/2021-09-08/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "91ac6c321d172cfb62e6772c2c7340110fb9801a8d44814b69b477f611f09c58",
+    "dist/2021-09-08/rust-std-beta-armv7a-none-eabi.tar.gz": "69661706ec6749f851d6a967f69fc8e4de8e5a58da2a771129b22202918f6ce8",
+    "dist/2021-09-08/rust-std-beta-armv7a-none-eabi.tar.xz": "45275aea14a3f4547e0e2f11ce2cf364ac2c749cf0df467a54e27b39b65a5fe2",
+    "dist/2021-09-08/rust-std-beta-armv7r-none-eabi.tar.gz": "63ea71e69e36d916baca6eb42b4b4b6f2f69870063526533a2699f66fc0cb317",
+    "dist/2021-09-08/rust-std-beta-armv7r-none-eabi.tar.xz": "2d6f4ca658991a7b426d50330371922888706944eb3c1603288d4be2fa4f5457",
+    "dist/2021-09-08/rust-std-beta-armv7r-none-eabihf.tar.gz": "3d27ea42bd3a419ccf7f28b9ff040e077f3e963948924f996aaf718abeeb1709",
+    "dist/2021-09-08/rust-std-beta-armv7r-none-eabihf.tar.xz": "8f6bc34715629354b4d9f71d7a8693171b667604d237b433f7444df1228d2a36",
+    "dist/2021-09-08/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "f83bdc7e73590beab7ec915bb7a3a7531e485d7f73cf9c65150102748207d874",
+    "dist/2021-09-08/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "1068750fb0b4a7ec35b5674a6c7fb0368b043bee6df0fbe360f521c7c2f08b94",
+    "dist/2021-09-08/rust-std-beta-i586-pc-windows-msvc.tar.gz": "506bd86d803953bb086e057c6b2ee1fd9ffa0e08a0d7162189119cd21668cc0f",
+    "dist/2021-09-08/rust-std-beta-i586-pc-windows-msvc.tar.xz": "b608aff18260165b51acbc06d551c5eb003928f2c7551f83a1ac1782442826ac",
+    "dist/2021-09-08/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "c90eca1f2326cfa916e225199e2526719fc9b6f18e2b789366a9668a52eba339",
+    "dist/2021-09-08/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "ab382cc6c67bceaf76555a2c71c5f26e46802fe7c2713e173744b14371b742a5",
+    "dist/2021-09-08/rust-std-beta-i586-unknown-linux-musl.tar.gz": "dd52e44df6cd8bbac61d484e574d363125662fef270695e962900995a05818b3",
+    "dist/2021-09-08/rust-std-beta-i586-unknown-linux-musl.tar.xz": "e9c4bba480b748625898dc047b950a142ccda9e9fe1e329365741f09f640e843",
+    "dist/2021-09-08/rust-std-beta-i686-linux-android.tar.gz": "bb2e1dea2aae2f726420d8a5cd112f1bed6e06e95053f10c6497b1be878b180e",
+    "dist/2021-09-08/rust-std-beta-i686-linux-android.tar.xz": "df15194a40cce8c574b219164b75590ad9c55c03ab811682ebe89db004c651f4",
+    "dist/2021-09-08/rust-std-beta-i686-pc-windows-gnu.tar.gz": "c7b38618dda1cd13d52c59bb9a4632458aa7b20d90b01478fb506801c3fb41eb",
+    "dist/2021-09-08/rust-std-beta-i686-pc-windows-gnu.tar.xz": "83390b595e3273f0b02e05878064429a1815f18bceb7e0d77a63c5caecaebfeb",
+    "dist/2021-09-08/rust-std-beta-i686-pc-windows-msvc.tar.gz": "e7c6c8e5ae9d02e9f3c33b174862d1d6e0caf357c7c3cd510e63cc3472db816b",
+    "dist/2021-09-08/rust-std-beta-i686-pc-windows-msvc.tar.xz": "feb49ed3fdf25d7703134afefc3c04b0ed23d87adc02945bccac4b30c425fa16",
+    "dist/2021-09-08/rust-std-beta-i686-unknown-freebsd.tar.gz": "f633cb1bd2636eceaa87d98a214aa73907502aa92d4cb1a1869870c9bc6ad23a",
+    "dist/2021-09-08/rust-std-beta-i686-unknown-freebsd.tar.xz": "cd61b7dfe7ead85a79469008717bc52cb76572fc9688f82a50f07b0c7e0fafb2",
+    "dist/2021-09-08/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "b22f1285e8d179a372060916bc2a6d609499231f805b5cec2ef8d1e5d0c70d71",
+    "dist/2021-09-08/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "24fd3c052bdec08615e54438fbccd9e43c9956d25b1bfce6f3640eb164aa6f5d",
+    "dist/2021-09-08/rust-std-beta-i686-unknown-linux-musl.tar.gz": "df63f460486eeb9a11ed53c35814495e931492aed5abe44a841cd7a43a9e3719",
+    "dist/2021-09-08/rust-std-beta-i686-unknown-linux-musl.tar.xz": "3ba2d402c01b099b89518acded3734a552f64a330a7d21732ce641cf25cd5c8d",
+    "dist/2021-09-08/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "4cc5b2cfa6747155a0e0c6a7a835abd464bc9610fd071197af1ac50ab8f2fa1c",
+    "dist/2021-09-08/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "28f70f287f4cceba042b9574b16ce0403d73785bc6261c9a6739d770d5f354f9",
+    "dist/2021-09-08/rust-std-beta-mips-unknown-linux-musl.tar.gz": "04a8dc4e8144330f326dba5182928cf91c50c4b3513df0b67d55d601d3524a7e",
+    "dist/2021-09-08/rust-std-beta-mips-unknown-linux-musl.tar.xz": "06a91efa4f8ab42c3a0f9c2ae9279da87bb2a239f1032d1faa3583febace37cc",
+    "dist/2021-09-08/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "887728123ccd4bb75f4d42bffc1d2b7f46d8bdc4554a77b12578507cb44e7fd5",
+    "dist/2021-09-08/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "987598a67a36f428fa8fb21e0239aa345e952a1e6c64fefcc2fe2feda56bb864",
+    "dist/2021-09-08/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "2110b1b7456366668e093d27013d7002e302c6ecccff63c147c0346cd9a452b7",
+    "dist/2021-09-08/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "d6f16eca6526aeeef3ec7d0a9948ff5da3b7eff6e4bb9203a9546037df1f8d55",
+    "dist/2021-09-08/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "36a510c2a8fbc751416183b88680685c232646289504d2e2422e5208cd11670b",
+    "dist/2021-09-08/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "2f2a7a533d30cdb437bf31d18fb547680d646ec1765ca6c5fe16e449dbf3b613",
+    "dist/2021-09-08/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "09472066c8403c059e9d34ac2f7a4387e61726c45dd5ff2bc03b85543d8376c0",
+    "dist/2021-09-08/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "83c4a0f9ed4fa2884d1d193b79693c3af4e9c8603b9a1f3bd6eb827ba09a5466",
+    "dist/2021-09-08/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "739998734f48c9591b7aed3452d8425e2c916d202341ff63931fa473e3eb9a25",
+    "dist/2021-09-08/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "83be5e72fc8597f51c6b2cc216d90c8dba6be509b44fa25f3d7d285e1c54c7c0",
+    "dist/2021-09-08/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "0a02455697ac62af66b359d5b73436ce7b18274abd18ffa13b7f0f9c1df72f82",
+    "dist/2021-09-08/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "1cc6fe6ecfe4c10c2957806e56c1a0aa256ef5bb3ad4ca47f24aae42cf0fc0e3",
+    "dist/2021-09-08/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "f90d70acfa78388fe8e54a62f4fd9e773bd1455b036f6af13a5feec072de11e8",
+    "dist/2021-09-08/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "d2c491b6fb62bc5279447e7f5d96fbb679a225ec13d6c96c8f80cad859b0f5f8",
+    "dist/2021-09-08/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "17e9bca285df96b3bcd48297c89c096aab6b545d783e261103f7b364c214c09d",
+    "dist/2021-09-08/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "d4a8679af46449daa4db0acc23bda23aa5c8f35fb2ca9d0e065b35e30d6fc649",
+    "dist/2021-09-08/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "845cab4436d36b6eb2a914ab7c48bd49626a04053eee918fbbb78aba1d1e0a4a",
+    "dist/2021-09-08/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "b399647f0d9e8458570e8a9ab11b30d7258fa396ab019037b5bb391dbe65ead7",
+    "dist/2021-09-08/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "6c84662ba3c210b9d7c3332473cdc95dcf3e238d9c9010581accfafa37cdf4f8",
+    "dist/2021-09-08/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "594aba2abb126a615c93bb5c7927eb5a2ccdbe4c54c22bfdfa9cacf99e268889",
+    "dist/2021-09-08/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "439f5d5f1d2ee9db18c6e3b0bb831b037234852067a91f1a15bca38ca38b7a0b",
+    "dist/2021-09-08/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "227fa2ff323d20a2a8c29e0167fac78c7b88b8db3368b009b75d4a1cd49b7b29",
+    "dist/2021-09-08/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "5055560e4dc3df90bf127bb5133c8d2d0ba662c1b1b20d63453cd60ee3e04947",
+    "dist/2021-09-08/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "df1267905fe5a23c2ddc47fc0ade249bd663e6d3e8982193cb2a2a638e747e5c",
+    "dist/2021-09-08/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "2a702d0d0a0e2cf17a42eac549bd751eadc4398182f42590e3322cc7420b4cd1",
+    "dist/2021-09-08/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "98e5d336ee07556ff0fe01f89f9059cb977fa36d5f87ee8633aebb5fa6c8762b",
+    "dist/2021-09-08/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "de64e6d171a2c11e16142b1e964c0f0e0d6e4bab2e9e9d5d8121ee77fbdb60de",
+    "dist/2021-09-08/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "1dbb24b1ed6510f098f63933a596f1f58907c22320eb79394dce341af7d7b59a",
+    "dist/2021-09-08/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "66af911664286500164db018c0aad12a85da035fc1e2d6cffbe7603ff0145624",
+    "dist/2021-09-08/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "e8abd1f9f7344842af5f6a85d75404c1589fd17efbe5a8008ab52f082b7b3772",
+    "dist/2021-09-08/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "a9f06d8862f9bb805f438b1c01464dd7a9cd07ecd04b1246727ac290891da54f",
+    "dist/2021-09-08/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "6143b4b36bbdd1c56b978e9a2afc012163610fac7b8fb9bd9f24abb4e970b21d",
+    "dist/2021-09-08/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "5cb4c0616056f36c7cfe446fa97e146fd5c525be1de8bbdb5017ad0d07a9561d",
+    "dist/2021-09-08/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "9d2397f9d70956ddd50b37f8a7dba71d3cea9df5fa128e35d92cb162d7f938d4",
+    "dist/2021-09-08/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "b7e0fe340919a37cf8daeb1a747392c53fce4dafc84331f998479c3c12572973",
+    "dist/2021-09-08/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "464b2601346e014b2f5a9cc64dd32897be915742a5c75eeacf82691277c4f8de",
+    "dist/2021-09-08/rust-std-beta-sparcv9-sun-solaris.tar.gz": "40c61118e3e85343f6ea3059e41e3d2e3108f540331d8114948447307eea9b5f",
+    "dist/2021-09-08/rust-std-beta-sparcv9-sun-solaris.tar.xz": "3dfb77e1315a8367b4a5665ae9419843a8cb953ce4726b35307e7c7199514616",
+    "dist/2021-09-08/rust-std-beta-thumbv6m-none-eabi.tar.gz": "66632c7fad29f275ccfed907e395db12e621b17909e5e026d192f0b552fd4be1",
+    "dist/2021-09-08/rust-std-beta-thumbv6m-none-eabi.tar.xz": "a308cdebc35d65d8208fe2b2dc7b45dfb1a64405478d86b82bfb28115174a129",
+    "dist/2021-09-08/rust-std-beta-thumbv7em-none-eabi.tar.gz": "c342b21b5f61dcddea74b89f60f1d0d0622c5aedc79550d316b8744b522bda6f",
+    "dist/2021-09-08/rust-std-beta-thumbv7em-none-eabi.tar.xz": "a3b00a6b9b3fb8942700f91d32077520185a7c21d25620193cbe2e730a021f64",
+    "dist/2021-09-08/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "18f15f7e2ffe97f7be99e246144e6b9ad7445b1b66382112e71e08137a36b840",
+    "dist/2021-09-08/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "16eb54bf02813d45c6ff328ec7db8f16daf0e57dedfad7247249af2ec5133d4b",
+    "dist/2021-09-08/rust-std-beta-thumbv7m-none-eabi.tar.gz": "14bdada81be2379b2ead0212cc34add3ace87bd222532ada2a00b603180db946",
+    "dist/2021-09-08/rust-std-beta-thumbv7m-none-eabi.tar.xz": "f6cfa6bdcee91a6cab748fced0d2be7642b83cbe7d5fdcdf638fc3e86277d17e",
+    "dist/2021-09-08/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "e11e35a643c0a9983fb1f1e8f60ac073a4ee48c4a9f3e757f4fb55ea8364046d",
+    "dist/2021-09-08/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "2ee5fc11fb01f84e2346a17745c935f75d400a2448ec49d9e3535c98c3d67a73",
+    "dist/2021-09-08/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "61b26681fdb6957c3acd9aa32b011605786bed196cd71334d966ad9289efbb2f",
+    "dist/2021-09-08/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "bfd3391ebdc20690ede1a8a606f59df9009a473962deb04d3a89b266d0a89949",
+    "dist/2021-09-08/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "ae8d90bdd3d2faa2623ec30935e3e93bf3af6ad036eaae72bc8a3d086f7cd054",
+    "dist/2021-09-08/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "66ce451e2a0830808aa996b4643fa6ca6d89a072467d9df659ad4e202b73d561",
+    "dist/2021-09-08/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "1afbb6a4ee9ec38b7ad1c67c3df3371d188b831ffdb58ae96227e5c9a017f5d9",
+    "dist/2021-09-08/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "8c1e0000926fb4ff370763396e69aef70ed7871c33f01bc2d429abf31ee8d211",
+    "dist/2021-09-08/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "169852e1ae03792a8f492954258d08bc1483615e7121d587476ac4fc065c79a1",
+    "dist/2021-09-08/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "1da32effe4416f0cd5448a9061d57dd2f4b541f737a7036d20d78fd44f715ddb",
+    "dist/2021-09-08/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "39d22c8ff2620d4e6569eb75c86d4135a288bba00dcc479f4371a1e7e52fee4b",
+    "dist/2021-09-08/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "c34b1abdb8e3f3f913564a472b18dc52b239d7e327a4bd89d9bd0290d0b31635",
+    "dist/2021-09-08/rust-std-beta-wasm32-unknown-unknown.tar.gz": "ae284aa5819407e8daf022fbbf1f5d279366077faf25a6653d9c518ab3fe710e",
+    "dist/2021-09-08/rust-std-beta-wasm32-unknown-unknown.tar.xz": "be7a5b763db13ab1582a5f98fe7fb9ab1facdd645a7fe4544e0cbec9d1c58e76",
+    "dist/2021-09-08/rust-std-beta-wasm32-wasi.tar.gz": "ac9f39cb7924f48fc29d666dfda3c6001b6880d6efd956acfa734389ef7b5dbe",
+    "dist/2021-09-08/rust-std-beta-wasm32-wasi.tar.xz": "04d20256cea7b2394f72f6c0895a9d249fbd641fcaf616a628ad703e79c950a2",
+    "dist/2021-09-08/rust-std-beta-x86_64-apple-darwin.tar.gz": "c304a11e2361b42f80fb9c6f239cbfbd2b7ffdcf00fe49ac94e3a6d4a9d2d2b3",
+    "dist/2021-09-08/rust-std-beta-x86_64-apple-darwin.tar.xz": "35d51256fc42481b8265a02d756bb9bd84a23240156ed1fdf84ee3adaa77b8c2",
+    "dist/2021-09-08/rust-std-beta-x86_64-apple-ios.tar.gz": "6eec11897fe08b43fece4a1cf0ecec1ca247b3d01656b4a2a159815fbe13c626",
+    "dist/2021-09-08/rust-std-beta-x86_64-apple-ios.tar.xz": "faddd6de72f17f669e38dc2e9ef5cdd4b729cdbccaae6a7711c54b173d86bfd2",
+    "dist/2021-09-08/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "6741696a588c4e723d279e388d446271b773c6029a823c5e2135a08a018c6083",
+    "dist/2021-09-08/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "a62d276ad6a4832cadd3ef4c587cc77f588774b93b2807dc1ab9e0acff037838",
+    "dist/2021-09-08/rust-std-beta-x86_64-fuchsia.tar.gz": "38a61746734681a97e84419709bd3ebc722207db656737e7be75479e0d991f9f",
+    "dist/2021-09-08/rust-std-beta-x86_64-fuchsia.tar.xz": "b85bbcd1353315e5c4eef82707912566f6a1f94f706350ae0474a29ff33b603e",
+    "dist/2021-09-08/rust-std-beta-x86_64-linux-android.tar.gz": "de32ea66a8228857a34f39d8d47e6cb32a4db9efd73100e97afe12bf58f6d520",
+    "dist/2021-09-08/rust-std-beta-x86_64-linux-android.tar.xz": "e2f89e63a379ba8182acf1b4fba33f790e0cdf4675bc46239840ecde613b1835",
+    "dist/2021-09-08/rust-std-beta-x86_64-pc-solaris.tar.gz": "6136d0607905fe49617a8171896bfada258eb84cb00e8042fd67bef29732a714",
+    "dist/2021-09-08/rust-std-beta-x86_64-pc-solaris.tar.xz": "00a98839ab7d2302feeaa0fdbedc169bfb2bd7229c27aa274954efc73b52c4f3",
+    "dist/2021-09-08/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "2f711c4a26ed3b876e64e256bf1b4040552e80a06bec352a9d3479ed8ed6aca9",
+    "dist/2021-09-08/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "e479e495292512d67414d3056c322ea368559a0d95d827f944bae7382bea4e4a",
+    "dist/2021-09-08/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "ce43642d886784242a3914b799b1a77b60df642af2a41f75eac186b7f1b6104e",
+    "dist/2021-09-08/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "a83d236d59f04f3a51a6a34ccf7b79b4b2f269dc50e147d61e1e9c4a57925835",
+    "dist/2021-09-08/rust-std-beta-x86_64-sun-solaris.tar.gz": "a8e7f979fc8ad5bdaa4ea2965c305a3296dfe88ffa235cdb7aea8234e4a46138",
+    "dist/2021-09-08/rust-std-beta-x86_64-sun-solaris.tar.xz": "72ed0fb32e53b283c6a0e1752d231915b98504164965f7e2b5f06d8550e4c338",
+    "dist/2021-09-08/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "1f5535f9d44afdacf059681587239bf4d21985f1dfbd3ace94c864c2d7616a42",
+    "dist/2021-09-08/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "5faf349a9cc231c144c52de40f2a487a935c6f6146614547e64cabb26f037a23",
+    "dist/2021-09-08/rust-std-beta-x86_64-unknown-illumos.tar.gz": "0ae64780c9a944a32bc51b5efef9f0818025a423819ef60fdc799945d52bfd73",
+    "dist/2021-09-08/rust-std-beta-x86_64-unknown-illumos.tar.xz": "b3308afe75af668878959db95b039c6e1c4416badf67ee650b07f5cf07f14ab2",
+    "dist/2021-09-08/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "f8078421bde37f74dd0ffe0ea44704778baca779e502cb760371340a6bfa15a5",
+    "dist/2021-09-08/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "cc26d8fd139b35e13cf75c2942727bba7899a874d95f865c127b0c3af15707cd",
+    "dist/2021-09-08/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "6e0ef50cb8c4ce19d7de517ad51581c4d80043fa489278c0ba984a5d408269db",
+    "dist/2021-09-08/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "5c9380fb472de93ebfe59b21f2a74b5f19a632ef6eccf77a89cf0b26ce2054a7",
+    "dist/2021-09-08/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "264c78d59e71d4fa232f6f10713ee61d94c270e493eabad7318877afa46b7327",
+    "dist/2021-09-08/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "af3e5b1883e8fa7d49e64ce8754d656d2992eba33b8ec5f92245f2a82793abf4",
+    "dist/2021-09-08/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "0797448414c3421577705e725814dbf833a44b0930875fe418aa1eed9ebf6121",
+    "dist/2021-09-08/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "bd3ec2d0fde1e11a75bfc3b684c2d564bd5068519d1c5a382ae09379337236c9",
+    "dist/2021-09-08/rust-std-beta-x86_64-unknown-redox.tar.gz": "449ea2e6ed2e1b4d656f8da8390f2e22cbbe40713e5f91cbc85971f36488402d",
+    "dist/2021-09-08/rust-std-beta-x86_64-unknown-redox.tar.xz": "5424c5b4aa5588de73734dcd43cd1ff9bf0e0ba244749a1519afc94c8f2057e2",
+    "dist/2021-09-08/rustc-beta-aarch64-apple-darwin.tar.gz": "b14f7853a9353b71d7babeeb136fbb595b5c23144ac1bd72e70b74227a1685ca",
+    "dist/2021-09-08/rustc-beta-aarch64-apple-darwin.tar.xz": "af2ab319357b3b4a2810a52c824f8f308d2c3f41ea1ed30ba9ef9ff6a4769dde",
+    "dist/2021-09-08/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "c09a6bdbe6dccbdcd366a695d54be4e0a472fa1ca5bf30bf7eaf389534e2f70c",
+    "dist/2021-09-08/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "9fad7bc10840340081cd29166aa788843a9950e293d6ced71a26e36bf0eafe9e",
+    "dist/2021-09-08/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "d20cdcc681b0506e73ccd0b484a7b7394a08615d2d195318d0f2c5af3063581b",
+    "dist/2021-09-08/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "07d0b4393149f854dca2d622a6ac8d6cb9fc62d2d24977bcf50cdc1824fe6a32",
+    "dist/2021-09-08/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "dbe81393d5253521adceda8027b103edef45a031120e92f2e9e89564e85863c2",
+    "dist/2021-09-08/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "40edabc1e00f228815c88798543f55081e3dfe352f88753f5592479de9236b4b",
+    "dist/2021-09-08/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "114dce61c5bf25be9f3cb33cd0c7500b1a60f5cbebef27547458312b8ddb8f4d",
+    "dist/2021-09-08/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "abc9130f7116badf9949f5a3ecd6820787e40bb590ebbd5c867b05cedfbdce5f",
+    "dist/2021-09-08/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "cbebd112f0dd96258ed19b25762af60c9bac30669ae229d6b8456049779c890f",
+    "dist/2021-09-08/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "cff6cbf35aba285cfb5f5d2f8a9dee5edefc7c22843ae0198e693993d556fcae",
+    "dist/2021-09-08/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "c20cf9a2e72f712f02ed867e9c4babe02d7ff22d62eb96cb127054010b6731b6",
+    "dist/2021-09-08/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "aa1b6cd4f9153fba338eb5c8a90ace06d742c97e659c3ffbca75125e5477b828",
+    "dist/2021-09-08/rustc-beta-i686-pc-windows-gnu.tar.gz": "3308d1e3ee0ae40f8db301601c73bf6eace168b570e9ab952760e28bd970a240",
+    "dist/2021-09-08/rustc-beta-i686-pc-windows-gnu.tar.xz": "0a019f66979c2542bf9fb268bad143cd55deac6f1502a4393464bb26a1e21c76",
+    "dist/2021-09-08/rustc-beta-i686-pc-windows-msvc.tar.gz": "31016537cedf38ef83e29a6125445946834a06ec2fda51ef799566baeb47211d",
+    "dist/2021-09-08/rustc-beta-i686-pc-windows-msvc.tar.xz": "a997b98b7a28358bd4ed394ddd3af62e5b19d7a33a61f55bf973b06fb9b95fe5",
+    "dist/2021-09-08/rustc-beta-i686-unknown-linux-gnu.tar.gz": "ddfba3dfb711db2ebb4cd7149172a738200b8e38a98f7ec5e5bbc81515be5453",
+    "dist/2021-09-08/rustc-beta-i686-unknown-linux-gnu.tar.xz": "5b0435f652dc749216735fc06599a3c6916a867ab82dc126d0cde872855dac83",
+    "dist/2021-09-08/rustc-beta-mips-unknown-linux-gnu.tar.gz": "6408766f8c58c13ba51347375dc5ed0fb7c247c8aee9b8a89e3369c70541c397",
+    "dist/2021-09-08/rustc-beta-mips-unknown-linux-gnu.tar.xz": "18a41553893aa8ff4c80fef252e8ba80c383d2809a57123fe89e89172a5839c5",
+    "dist/2021-09-08/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "28078984a80c4cb0e65391ae213390059a9eebff028209861d23c82b4db0a11c",
+    "dist/2021-09-08/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "277cfaafab145858ee5102a657c597abbdfa33ed2d6f1c8806f218bad91b2d8f",
+    "dist/2021-09-08/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "8c8c92719f3d299047089031cb29ce209e2954466415449d37d474e88a732d8e",
+    "dist/2021-09-08/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "d055a61cd0ec951edbc703180c190ef4dbed3391d1b2472668340642e205fecb",
+    "dist/2021-09-08/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "95433c7dc0437f61a024276c10a0654128bd0e873597932297140f82e34ad201",
+    "dist/2021-09-08/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "a3660c9909e3821537a275e37121950d6adbc87b85959e80fd7b72c6e3b7b944",
+    "dist/2021-09-08/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "07384f5fba55ad572753fc85ad6b2d231d94b31f009defb694c8632b38eeeb62",
+    "dist/2021-09-08/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "f0985ea483fbad75a9cff021db6c230c5c322eff942da667a0dd6cb3e37bb2c6",
+    "dist/2021-09-08/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "81a7ddf94bf62f45dde9199df8b28ac9971d23b1817906e119ca4ea32000b08d",
+    "dist/2021-09-08/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "7ce055fd68b1c5e3c48c9f03289cd4eb3af619cc30a7103056b20fe842a92db8",
+    "dist/2021-09-08/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "6b853d5c2fd2dc61d89c26bf5b365f48a9c535dd30aa672f28f254af8fbcc9e3",
+    "dist/2021-09-08/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "32c659ea9578759020f291099f16b1d12eebae30e07d35568e69cd0721576c24",
+    "dist/2021-09-08/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "a73a918ec89b759f19b605df527471acbbcfd2e3debcd0601d7a3956f645bcf0",
+    "dist/2021-09-08/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "eabdfdac435195844bdfaaa5f8bf6b57cf045742c6180c3ff0822bd85fac40f5",
+    "dist/2021-09-08/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "a626ed9d5ce779e7fd8ab17d4dc83130a57200669730851bc68eb01d88bade7d",
+    "dist/2021-09-08/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "67f195e60d88b3e0f1a702f7ba0cefded2dca6ffc03ede1f9b6e4fd38592eb6d",
+    "dist/2021-09-08/rustc-beta-x86_64-apple-darwin.tar.gz": "01e5b6d7153866ada9d3c1caee5c95da58296acd7007aa93338171cc349af304",
+    "dist/2021-09-08/rustc-beta-x86_64-apple-darwin.tar.xz": "a0b87b79f87e97a746ad311f2bf36ee9d5784f504f844427415e4a983ea4a0ac",
+    "dist/2021-09-08/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "54ff5dfa917a5ebbaf77185d4efff9700d248dd66746dcb3942e29917495dd3b",
+    "dist/2021-09-08/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "2d9dddd6b9a3ef6c5bb0758dbee171f08882292ba17e1f98445a9cf196f9c02c",
+    "dist/2021-09-08/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "359690df63e15260f028d6838f4f5007f828c4a977cc657513b8ab6900f1d126",
+    "dist/2021-09-08/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "6d8d2b9d5964fe690d4f6fd7ee643bce5f049d19e33c7f3b580502ba83ce5ea5",
+    "dist/2021-09-08/rustc-beta-x86_64-unknown-freebsd.tar.gz": "5e47aa933805000f806984b09222808636eddcb58ea0b95913eae6c4f0ce913c",
+    "dist/2021-09-08/rustc-beta-x86_64-unknown-freebsd.tar.xz": "4e01128800f479a96597ce7eee9d2e76a5128ae1c13a4e0e2eb52e36d43cf559",
+    "dist/2021-09-08/rustc-beta-x86_64-unknown-illumos.tar.gz": "51cdd463ec6402dac5a4b0ab3b0e303ad97ba49c2a63e1cfa2d8036d060fd67a",
+    "dist/2021-09-08/rustc-beta-x86_64-unknown-illumos.tar.xz": "498cca6f9826a9180759a0446627e2e6dba50b6bf1051044e6e09dc714d7b3e7",
+    "dist/2021-09-08/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "59314c4c868e57a76f7cb4dd80cd9a7e6230b87080784db44349420c950efddc",
+    "dist/2021-09-08/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "8b3e2cdba3ff86144029f7c7446825dff79937ed8a30df15a33a779e9f694227",
+    "dist/2021-09-08/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "56dc8f8914bbe5beaa1e369fdc22d99ef98c9d864e24f5b7d64cf6188c400b1c",
+    "dist/2021-09-08/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "66cf18df72034540d756b29d69a4148123029ff512fc831a786fe15a9641382b",
+    "dist/2021-09-08/rustc-beta-x86_64-unknown-netbsd.tar.gz": "2315fd067e858501b4df44f2a4d042cef3f70b7314ee6cfe24749849b8d386ae",
+    "dist/2021-09-08/rustc-beta-x86_64-unknown-netbsd.tar.xz": "62b429e67f24365963b0744e9b4807ae2cb7aa280a5e425882e4894a2d3225fb",
+    "dist/2021-09-08/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "691922fb32f3da37532bb9be974ad1717af521ec2b71bca4bbb5e57f3c4cc3fa",
+    "dist/2021-09-08/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "2c9667209094b7a603d50d3dc684c505b2ab855c64dcd8b23fe09248a6e13cee",
+    "dist/2021-09-08/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "daee571bf222bb7addf0d495991acf3f5001b69bb97d31bb43f0466b4e43c600",
+    "dist/2021-09-08/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "f6d31e21f798427c5483256d54b25b6dca1d61ff8c601384c62648959ebbce25",
+    "dist/2021-09-08/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "98b2eaf259a1bfdc70e40a52e891920dec7fc6132ad8d2420f91655c793ea340",
+    "dist/2021-09-08/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "a97c1c2646f9628fcc92818d21f4925568681976727686701116d0e6a71693a7",
+    "dist/2021-09-08/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "a4df0726fba466a5180471d3e63735c2b5ee9794e9f42026b1e8ae404dd43ab6",
+    "dist/2021-09-08/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "92846ab58a75bddc0270c9f42234a6585edc9a382e2018baa776aa74bb13e444",
+    "dist/2021-09-08/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "a8dbc2a00d359c95f05b0b3cf08a12b6df9f888157ba57fa9ba4a134cf271075",
+    "dist/2021-09-08/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "44b17a06b015f9701291cec7e60b0932c5ebc29244f4a6e35736e9f5ccf47c41",
+    "dist/2021-09-08/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "ee54b0a25f061c29ea22977c7d36d6fa6bf85abee3b108135b53bcb37028af0b",
+    "dist/2021-09-08/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "0a721d2526a78f7e70f9a6c49d156b1c18cd627c066bc8f09b084910864ec252",
+    "dist/2021-09-08/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "584ba68113add6e113cffb5c93a8000cfea16d621ba337dc68cd4d106f5e2759",
+    "dist/2021-09-08/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "e450429fcd37f15b6e200f62d9cb4790b39b7227e0246b667c82fa3b9ecf1b75",
+    "dist/2021-09-08/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "e0aa68b96699402e7cc09329055826f63ac9899cf22828d56cf393476a70405a",
+    "dist/2021-09-08/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "6f10f279f81c35c718446e837f5f22fb61841c45f5172abb2d0d4a035065edcd",
+    "dist/2021-09-08/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "aeb05fcb66830d395bf9a819a05a44f179cad3f35016f76fa60a4959f9e3c69e",
+    "dist/2021-09-08/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "351ee1490533ac9fa00a21c6db6087cb498b0034cb21358d29a8b944bf0f77e3",
+    "dist/2021-09-08/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "418b0481fd2b074e9a0f195b9e07f888652642aced34136044bad997f7500802",
+    "dist/2021-09-08/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "90d04308cbfc845462687206bf13182d907afebd02bdf88cca9a27eb8f1e7e28",
+    "dist/2021-09-08/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "0d2f54c9927ac9de3c00f8f703d52d8310d1b36baa84dbcddf1159759b4bff06",
+    "dist/2021-09-08/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "7f2b33077267e6ae064b12c7d0082115ea7f011f168f0d0e3ad9dc7ac9d39705",
+    "dist/2021-09-08/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "bdc9fa2cdb295e453460f1bf7b12efaa673955c27b01f22df626de989c3e1a28",
+    "dist/2021-09-08/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "bacd376fe18068010ada3e52c531de5a07dcc8232f988feb9e90be59986efb3b",
+    "dist/2021-09-08/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "fdc93a8295c563be29793d36b6b1e25f579d187b7e234ced6f17b1fe3c1fac02",
+    "dist/2021-09-08/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "289fd400d4959968c0ffccd787d613943c8534527913d0dbed69e8a7251ca32c",
+    "dist/2021-09-08/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "2e655b764843cea5f0e70e2a5b2a0f13dd5fa65c4055f42c547e36372af08296",
+    "dist/2021-09-08/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "07f6657648d1d7033030e9e2d05bfb9ea0022e63ae72320074a3d09ac9639d09",
+    "dist/2021-09-08/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "b78878ec58d6b932d3d1f8e1fefdb7871b1404c701ab0d2f8645246b458ba650",
+    "dist/2021-09-08/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "dfa79cb51708794d2c814bff6a60a63ca5358df3670179f9a9ae828811e72ad8",
+    "dist/2021-09-08/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "017de1a82a0e3988d1216771082b5d0e3e083dc51d4a0f0266f1e610bac166da",
+    "dist/2021-09-08/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "a0a46a62b9af14d2147939967e545ad812d9acebe3d1ed861321a6dfd8d554ca",
+    "dist/2021-09-08/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "54dff0daec5dd2a2ab23cf4e92bf9b2d71839c37144b52e5b5aa899ddf027bda",
+    "dist/2021-09-08/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "e743e45dc695e0bd9a1ce5fdd183f89951a329ec433bb510d37c47b435152a7b",
+    "dist/2021-09-08/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "0e04ae69e03d9e7e8d1d60a265c7ed3c3608a19aaef6ad4aa7ae2b280d3552b8",
+    "dist/2021-09-08/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "6ec865bd38b0fde2c9c823f4cb110b96c2aac4f7976cc2a6be48ffa214aa4bc7",
+    "dist/2021-09-08/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "3b833517415dee73b1e0d381df441a96856e3bac77f101545624c382aad7902c",
+    "dist/2021-09-08/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "7a8a447cc2167d0a998ad3858dfec88beb8658043655087d208affbc94aa3e62",
+    "dist/2021-09-08/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "20de8ad3aa7507dd9657c4a4b959c38cc7f732a87bb757183033f78a96288e45",
+    "dist/2021-09-08/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "99561b207ba61b455d1522d95143ca4ccc6474187be2f38f1ebff2ed63d0092e",
+    "dist/2021-09-08/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "145eb25cc3b295060c5f5a354ea2321cd39df17ea4e3a5c73c3eea105f7454a4",
+    "dist/2021-09-08/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "356ede5cd8a7d51f9e25a54c329b1be1da7d6fe418cbe86fdae9c8bcd9970ac4",
+    "dist/2021-09-08/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "0cc0f10763b73c5e4c8bdcd15a563d7e9d705b192ed6e8edc50dd6a71b874761",
+    "dist/2021-09-08/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "d734aefabe95fa03710dc75e9851c8f2e654f19cec1381ecb18281837d19db38",
+    "dist/2021-09-08/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "e1c28472a81312560ca36719f0b61b7212a07d63e85d745f97cd8e3b9ea8f191",
+    "dist/2021-09-08/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "4d6a62738f842e54666c608a466c64f896097ffa65d10d30361704e4b8496eed",
+    "dist/2021-09-08/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "75b21690480f6214ed174ca86297d9a41f37731560adf5782ccd7116b0df583a",
+    "dist/2021-09-08/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "5c08f45f557da789d39bf203dfbcf2667f4196dedad327a19dc3ad5bb783079d",
+    "dist/2021-09-08/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "a7d579672b94978e8427584f7e9d2b6534f320719252db46fc6ee85082d646ff",
+    "dist/2021-09-08/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "6ffbdb558b9d25e9d923534413b25dc99bb5b9cc92b4774d5255cf70ec20b20d",
+    "dist/2021-09-08/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "fba0e7bc1401b830223b5207b63808e28403f48d1591c7d47c1681519c1883f7",
+    "dist/2021-09-08/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "644b3acc47cd7bbbb5405683ce94e7f32a8313ad265da753026bdb6c3687b608",
+    "dist/2021-09-08/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "3f152caa88299ab8aca2c6d39a5e36af995b95e3394c7d514ed94e87f7c61fa3",
+    "dist/2021-09-08/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "5f92b4d12a9eaa50b29b81a3dff1959e59966f362b67c346b74403138fdb320d"
   }
 }
diff --git a/src/test/assembly/niche-prefer-zero.rs b/src/test/assembly/niche-prefer-zero.rs
new file mode 100644
index 00000000000..0ab37a618da
--- /dev/null
+++ b/src/test/assembly/niche-prefer-zero.rs
@@ -0,0 +1,25 @@
+// Check that niche selection prefers zero and that jumps are optimized away.
+// See https://github.com/rust-lang/rust/pull/87794
+// assembly-output: emit-asm
+// only-x86
+// compile-flags: -Copt-level=3
+
+#![crate_type = "lib"]
+
+#[repr(u8)]
+pub enum Size {
+    One = 1,
+    Two = 2,
+    Three = 3,
+}
+
+#[no_mangle]
+pub fn handle(x: Option<Size>) -> u8 {
+    match x {
+        None => 0,
+        Some(size) => size as u8,
+    }
+}
+
+// There should be no jumps in output
+// CHECK-NOT: j
diff --git a/src/test/codegen/panic-in-drop-abort.rs b/src/test/codegen/panic-in-drop-abort.rs
new file mode 100644
index 00000000000..62d093507dd
--- /dev/null
+++ b/src/test/codegen/panic-in-drop-abort.rs
@@ -0,0 +1,54 @@
+// compile-flags: -Z panic-in-drop=abort -O
+
+// Ensure that unwinding code paths are eliminated from the output after
+// optimization.
+
+#![crate_type = "lib"]
+use std::any::Any;
+use std::mem::forget;
+
+pub struct ExternDrop;
+impl Drop for ExternDrop {
+    #[inline(always)]
+    fn drop(&mut self) {
+        // This call may potentially unwind.
+        extern "Rust" {
+            fn extern_drop();
+        }
+        unsafe {
+            extern_drop();
+        }
+    }
+}
+
+struct AssertNeverDrop;
+impl Drop for AssertNeverDrop {
+    #[inline(always)]
+    fn drop(&mut self) {
+        // This call should be optimized away as unreachable.
+        extern "C" {
+            fn should_not_appear_in_output();
+        }
+        unsafe {
+            should_not_appear_in_output();
+        }
+    }
+}
+
+// CHECK-LABEL: normal_drop
+// CHECK-NOT: should_not_appear_in_output
+#[no_mangle]
+pub fn normal_drop(x: ExternDrop) {
+    let guard = AssertNeverDrop;
+    drop(x);
+    forget(guard);
+}
+
+// CHECK-LABEL: indirect_drop
+// CHECK-NOT: should_not_appear_in_output
+#[no_mangle]
+pub fn indirect_drop(x: Box<dyn Any>) {
+    let guard = AssertNeverDrop;
+    drop(x);
+    forget(guard);
+}
diff --git a/src/test/debuginfo/basic-types.rs b/src/test/debuginfo/basic-types.rs
index c35c3255498..d300e374bec 100644
--- a/src/test/debuginfo/basic-types.rs
+++ b/src/test/debuginfo/basic-types.rs
@@ -9,6 +9,10 @@
 // This fails on lldb 6.0.1 on x86-64 Fedora 28; so ignore Linux for now.
 // ignore-linux
 
+// This started failing in windows too. See https://github.com/rust-lang/rust/issues/88796
+// FIXME: fix and unignore this on windows
+// ignore-windows
+
 // compile-flags:-g
 
 // === GDB TESTS ===================================================================================
diff --git a/src/test/debuginfo/msvc-pretty-enums.rs b/src/test/debuginfo/msvc-pretty-enums.rs
index 9463f82c797..67b5da510f8 100644
--- a/src/test/debuginfo/msvc-pretty-enums.rs
+++ b/src/test/debuginfo/msvc-pretty-enums.rs
@@ -2,6 +2,10 @@
 // ignore-tidy-linelength
 // compile-flags:-g
 
+// This started failing recently. See https://github.com/rust-lang/rust/issues/88796
+// FIXME: fix and unignore this
+// ignore-windows
+
 // cdb-command: g
 
 // Note: The natvis used to visualize niche-layout enums don't work correctly in cdb
diff --git a/src/test/debuginfo/mutex.rs b/src/test/debuginfo/mutex.rs
index 40bea30f125..4a529541bae 100644
--- a/src/test/debuginfo/mutex.rs
+++ b/src/test/debuginfo/mutex.rs
@@ -3,6 +3,8 @@
 // cdb-only
 // min-cdb-version: 10.0.21287.1005
 // compile-flags:-g
+// FIXME: Failed on update to 10.0.22000.1
+// ignore-windows
 
 // === CDB TESTS ==================================================================================
 //
diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs
index baeada69d1c..cb2e6c618b1 100644
--- a/src/test/debuginfo/pretty-std.rs
+++ b/src/test/debuginfo/pretty-std.rs
@@ -6,6 +6,10 @@
 // min-lldb-version: 310
 // min-cdb-version: 10.0.18317.1001
 
+// This started failing recently. See https://github.com/rust-lang/rust/issues/88796
+// FIXME: fix and unignore this
+// ignore-windows
+
 // === GDB TESTS ===================================================================================
 
 // gdb-command: run
diff --git a/src/test/incremental/change_symbol_export_status.rs b/src/test/incremental/change_symbol_export_status.rs
index 9b3b381d621..dd3dce4e720 100644
--- a/src/test/incremental/change_symbol_export_status.rs
+++ b/src/test/incremental/change_symbol_export_status.rs
@@ -1,9 +1,15 @@
-// revisions: rpass1 rpass2
+// revisions: rpass1 rpass2 rpass3 rpass4
 // compile-flags: -Zquery-dep-graph
+// [rpass1]compile-flags: -Zincremental-ignore-spans
+// [rpass2]compile-flags: -Zincremental-ignore-spans
+// [rpass3]compile-flags: -Zincremental-relative-spans
+// [rpass4]compile-flags: -Zincremental-relative-spans
 
 #![feature(rustc_attrs)]
-#![rustc_partition_codegened(module = "change_symbol_export_status-mod1", cfg = "rpass2")]
+#![rustc_partition_reused(module = "change_symbol_export_status-mod1", cfg = "rpass2")]
 #![rustc_partition_reused(module = "change_symbol_export_status-mod2", cfg = "rpass2")]
+#![rustc_partition_reused(module = "change_symbol_export_status-mod1", cfg = "rpass4")]
+#![rustc_partition_reused(module = "change_symbol_export_status-mod2", cfg = "rpass4")]
 
 // This test case makes sure that a change in symbol visibility is detected by
 // our dependency tracking. We do this by changing a module's visibility to
@@ -13,13 +19,13 @@
 // even from an executable. Plain Rust functions are only exported from Rust
 // libraries, which our test infrastructure does not support.
 
-#[cfg(rpass1)]
+#[cfg(any(rpass1,rpass3))]
 pub mod mod1 {
     #[no_mangle]
     pub fn foo() {}
 }
 
-#[cfg(rpass2)]
+#[cfg(any(rpass2,rpass4))]
 mod mod1 {
     #[no_mangle]
     pub fn foo() {}
diff --git a/src/test/incremental/hashes/call_expressions.rs b/src/test/incremental/hashes/call_expressions.rs
index d4201400f0f..648f71f9230 100644
--- a/src/test/incremental/hashes/call_expressions.rs
+++ b/src/test/incremental/hashes/call_expressions.rs
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 
 #![allow(warnings)]
@@ -19,14 +25,16 @@ fn callee2(_x: u32, _y: i64) {}
 
 
 // Change Callee (Function)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_callee_function() {
     callee1(1, 2)
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_callee_function() {
     callee2(1, 2)
 }
@@ -34,14 +42,16 @@ pub fn change_callee_function() {
 
 
 // Change Argument (Function)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_argument_function() {
     callee1(1, 2)
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_argument_function() {
     callee1(1, 3)
 }
@@ -50,13 +60,15 @@ pub fn change_argument_function() {
 
 // Change Callee Indirectly (Function)
 mod change_callee_indirectly_function {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::callee1 as callee;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::callee2 as callee;
 
     #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn change_callee_indirectly_function() {
         callee(1, 2)
     }
@@ -70,15 +82,17 @@ impl Struct {
 }
 
 // Change Callee (Method)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_callee_method() {
     let s = Struct;
     s.method1('x', true);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_callee_method() {
     let s = Struct;
     s.method2('x', true);
@@ -87,15 +101,17 @@ pub fn change_callee_method() {
 
 
 // Change Argument (Method)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_argument_method() {
     let s = Struct;
     s.method1('x', true);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_argument_method() {
     let s = Struct;
     s.method1('y', true);
@@ -104,15 +120,17 @@ pub fn change_argument_method() {
 
 
 // Change Callee (Method, UFCS)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_ufcs_callee_method() {
     let s = Struct;
     Struct::method1(&s, 'x', true);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_ufcs_callee_method() {
     let s = Struct;
     Struct::method2(&s, 'x', true);
@@ -121,32 +139,36 @@ pub fn change_ufcs_callee_method() {
 
 
 // Change Argument (Method, UFCS)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_argument_method_ufcs() {
     let s = Struct;
     Struct::method1(&s, 'x', true);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_argument_method_ufcs() {
     let s = Struct;
-    Struct::method1(&s, 'x', false);
+    Struct::method1(&s, 'x',false);
 }
 
 
 
 // Change To UFCS
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_to_ufcs() {
     let s = Struct;
-    s.method1('x', true);
+    s.method1('x', true); // ------
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 // One might think this would be expanded in the hir_owner_nodes/Mir, but it actually
 // results in slightly different hir_owner/Mir.
 pub fn change_to_ufcs() {
@@ -162,15 +184,15 @@ impl Struct2 {
 
 // Change UFCS Callee Indirectly
 pub mod change_ufcs_callee_indirectly {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::Struct as Struct;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::Struct2 as Struct;
 
     #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
     #[rustc_clean(cfg="cfail3")]
-
-
+    #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn change_ufcs_callee_indirectly() {
         let s = Struct;
         Struct::method1(&s, 'q', false)
diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs
index 4a00a6c72f7..2a4306fc17c 100644
--- a/src/test/incremental/hashes/closure_expressions.rs
+++ b/src/test/incremental/hashes/closure_expressions.rs
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans -Zmir-opt-level=0
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -Zmir-opt-level=0
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -15,14 +21,16 @@
 
 
 // Change closure body
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_closure_body() {
     let _ = || 1u32;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_closure_body() {
     let _ = || 3u32;
 }
@@ -30,15 +38,17 @@ pub fn change_closure_body() {
 
 
 // Add parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_parameter() {
     let x = 0u32;
-    let _ = || x + 1;
+    let _ = |      | x + 1;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_parameter() {
     let x = 0u32;
     let _ = |x: u32| x + 1;
@@ -47,14 +57,16 @@ pub fn add_parameter() {
 
 
 // Change parameter pattern
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_parameter_pattern() {
-    let _ = |x: (u32,)| x;
+    let _ = | x  : (u32,)| x;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_parameter_pattern() {
     let _ = |(x,): (u32,)| x;
 }
@@ -62,14 +74,16 @@ pub fn change_parameter_pattern() {
 
 
 // Add `move` to closure
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_move() {
-    let _ = || 1;
+    let _ =      || 1;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_move() {
     let _ = move || 1;
 }
@@ -77,15 +91,17 @@ pub fn add_move() {
 
 
 // Add type ascription to parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_type_ascription_to_parameter() {
-    let closure = |x| x + 1u32;
+    let closure = |x     | x + 1u32;
     let _: u32 = closure(1);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner_nodes, typeck")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner_nodes, typeck")]
+#[rustc_clean(cfg = "cfail6")]
 pub fn add_type_ascription_to_parameter() {
     let closure = |x: u32| x + 1u32;
     let _: u32 = closure(1);
@@ -94,15 +110,17 @@ pub fn add_type_ascription_to_parameter() {
 
 
 // Change parameter type
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_parameter_type() {
     let closure = |x: u32| (x as u64) + 1;
     let _ = closure(1);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_parameter_type() {
     let closure = |x: u16| (x as u64) + 1;
     let _ = closure(1);
diff --git a/src/test/incremental/hashes/consts.rs b/src/test/incremental/hashes/consts.rs
index 6e0db6a49aa..c85f0bbecdb 100644
--- a/src/test/incremental/hashes/consts.rs
+++ b/src/test/incremental/hashes/consts.rs
@@ -7,7 +7,7 @@
 
 // build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// compile-flags: -Z query-dep-graph
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/hashes/enum_constructors.rs b/src/test/incremental/hashes/enum_constructors.rs
index 26ff6b109dc..7522fa5a026 100644
--- a/src/test/incremental/hashes/enum_constructors.rs
+++ b/src/test/incremental/hashes/enum_constructors.rs
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans -Zmir-opt-level=0
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph -Zmir-opt-level=0
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -24,7 +30,7 @@ pub enum Enum {
 }
 
 // Change field value (struct-like) -----------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_field_value_struct_like() -> Enum {
     Enum::Struct {
         x: 0,
@@ -33,9 +39,11 @@ pub fn change_field_value_struct_like() -> Enum {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_field_value_struct_like() -> Enum {
     Enum::Struct {
         x: 0,
@@ -47,7 +55,7 @@ pub fn change_field_value_struct_like() -> Enum {
 
 
 // Change field order (struct-like) -----------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_field_order_struct_like() -> Enum {
     Enum::Struct {
         x: 3,
@@ -56,9 +64,11 @@ pub fn change_field_order_struct_like() -> Enum {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 // FIXME(michaelwoerister):Interesting. I would have thought that that changes the MIR. And it
 // would if it were not all constants
 pub fn change_field_order_struct_like() -> Enum {
@@ -86,18 +96,20 @@ pub enum Enum2 {
 }
 
 // Change constructor path (struct-like) ------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_constructor_path_struct_like() {
-    let _ = Enum::Struct {
+    let _ = Enum ::Struct {
         x: 0,
         y: 1,
         z: 2,
     };
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_constructor_path_struct_like() {
     let _ = Enum2::Struct {
         x: 0,
@@ -109,18 +121,20 @@ pub fn change_constructor_path_struct_like() {
 
 
 // Change variant (regular struct) ------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_constructor_variant_struct_like() {
-    let _ = Enum2::Struct {
+    let _ = Enum2::Struct  {
         x: 0,
         y: 1,
         z: 2,
     };
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_constructor_variant_struct_like() {
     let _ = Enum2::Struct2 {
         x: 0,
@@ -132,9 +146,9 @@ pub fn change_constructor_variant_struct_like() {
 
 // Change constructor path indirectly (struct-like) -------------------------
 pub mod change_constructor_path_indirectly_struct_like {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::Enum as TheEnum;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::Enum2 as TheEnum;
 
     #[rustc_clean(
@@ -143,6 +157,12 @@ pub mod change_constructor_path_indirectly_struct_like {
                 typeck"
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        cfg="cfail5",
+        except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\
+                typeck"
+    )]
+    #[rustc_clean(cfg="cfail6")]
     pub fn function() -> TheEnum {
         TheEnum::Struct {
             x: 0,
@@ -156,13 +176,15 @@ pub mod change_constructor_path_indirectly_struct_like {
 // Change constructor variant indirectly (struct-like) ---------------------------
 pub mod change_constructor_variant_indirectly_struct_like {
     use super::Enum2;
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::Enum2::Struct as Variant;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::Enum2::Struct2 as Variant;
 
     #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn function() -> Enum2 {
         Variant {
             x: 0,
@@ -174,14 +196,16 @@ pub mod change_constructor_variant_indirectly_struct_like {
 
 
 // Change field value (tuple-like) -------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_field_value_tuple_like() -> Enum {
     Enum::Tuple(0, 1, 2)
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_field_value_tuple_like() -> Enum {
     Enum::Tuple(0, 1, 3)
 }
@@ -189,17 +213,22 @@ pub fn change_field_value_tuple_like() -> Enum {
 
 
 // Change constructor path (tuple-like) --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_constructor_path_tuple_like() {
-    let _ = Enum::Tuple(0, 1, 2);
+    let _ = Enum ::Tuple(0, 1, 2);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(
     cfg="cfail2",
     except="hir_owner_nodes,optimized_mir,typeck"
 )]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(
+    cfg="cfail5",
+    except="hir_owner_nodes,optimized_mir,typeck"
+)]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_constructor_path_tuple_like() {
     let _ = Enum2::Tuple(0, 1, 2);
 }
@@ -207,17 +236,22 @@ pub fn change_constructor_path_tuple_like() {
 
 
 // Change constructor variant (tuple-like) --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_constructor_variant_tuple_like() {
-    let _ = Enum2::Tuple(0, 1, 2);
+    let _ = Enum2::Tuple (0, 1, 2);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(
     cfg="cfail2",
     except="hir_owner_nodes,optimized_mir,typeck"
 )]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(
+    cfg="cfail5",
+    except="hir_owner_nodes,optimized_mir,typeck"
+)]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_constructor_variant_tuple_like() {
     let _ = Enum2::Tuple2(0, 1, 2);
 }
@@ -225,9 +259,9 @@ pub fn change_constructor_variant_tuple_like() {
 
 // Change constructor path indirectly (tuple-like) ---------------------------
 pub mod change_constructor_path_indirectly_tuple_like {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::Enum as TheEnum;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::Enum2 as TheEnum;
 
     #[rustc_clean(
@@ -236,6 +270,12 @@ pub mod change_constructor_path_indirectly_tuple_like {
                 typeck"
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        cfg="cfail5",
+        except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\
+                typeck"
+    )]
+    #[rustc_clean(cfg="cfail6")]
     pub fn function() -> TheEnum {
         TheEnum::Tuple(0, 1, 2)
     }
@@ -246,13 +286,15 @@ pub mod change_constructor_path_indirectly_tuple_like {
 // Change constructor variant indirectly (tuple-like) ---------------------------
 pub mod change_constructor_variant_indirectly_tuple_like {
     use super::Enum2;
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::Enum2::Tuple as Variant;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::Enum2::Tuple2 as Variant;
 
     #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn function() -> Enum2 {
         Variant(0, 1, 2)
     }
@@ -272,14 +314,16 @@ pub enum Clike2 {
 }
 
 // Change constructor path (C-like) --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_constructor_path_c_like() {
-    let _x = Clike::B;
+    let _x = Clike ::B;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_constructor_path_c_like() {
     let _x = Clike2::B;
 }
@@ -287,14 +331,16 @@ pub fn change_constructor_path_c_like() {
 
 
 // Change constructor variant (C-like) --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_constructor_variant_c_like() {
     let _x = Clike::A;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_constructor_variant_c_like() {
     let _x = Clike::C;
 }
@@ -302,9 +348,9 @@ pub fn change_constructor_variant_c_like() {
 
 // Change constructor path indirectly (C-like) ---------------------------
 pub mod change_constructor_path_indirectly_c_like {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::Clike as TheEnum;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::Clike2 as TheEnum;
 
     #[rustc_clean(
@@ -313,6 +359,12 @@ pub mod change_constructor_path_indirectly_c_like {
                 typeck"
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        cfg="cfail5",
+        except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,\
+                typeck"
+    )]
+    #[rustc_clean(cfg="cfail6")]
     pub fn function() -> TheEnum {
         TheEnum::B
     }
@@ -323,13 +375,15 @@ pub mod change_constructor_path_indirectly_c_like {
 // Change constructor variant indirectly (C-like) ---------------------------
 pub mod change_constructor_variant_indirectly_c_like {
     use super::Clike;
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::Clike::A as Variant;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::Clike::B as Variant;
 
     #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn function() -> Clike {
         Variant
     }
diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs
index 76bff3cad38..ab9c740844b 100644
--- a/src/test/incremental/hashes/enum_defs.rs
+++ b/src/test/incremental/hashes/enum_defs.rs
@@ -11,8 +11,14 @@
 // the same between rev2 and rev3.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -22,12 +28,14 @@
 
 
 // Change enum visibility -----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumVisibility { A }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub enum EnumVisibility {
     A
 }
@@ -35,15 +43,17 @@ pub enum EnumVisibility {
 
 
 // Change name of a c-style variant -------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeNameCStyleVariant {
     Variant1,
     Variant2,
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeNameCStyleVariant {
     Variant1,
     Variant2Changed,
@@ -52,15 +62,17 @@ enum EnumChangeNameCStyleVariant {
 
 
 // Change name of a tuple-style variant ---------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeNameTupleStyleVariant {
     Variant1,
     Variant2(u32, f32),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeNameTupleStyleVariant {
     Variant1,
     Variant2Changed(u32, f32),
@@ -69,15 +81,17 @@ enum EnumChangeNameTupleStyleVariant {
 
 
 // Change name of a struct-style variant --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeNameStructStyleVariant {
     Variant1,
     Variant2 { a: u32, b: f32 },
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeNameStructStyleVariant {
     Variant1,
     Variant2Changed { a: u32, b: f32 },
@@ -86,31 +100,33 @@ enum EnumChangeNameStructStyleVariant {
 
 
 // Change the value of a c-style variant --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeValueCStyleVariant0 {
     Variant1,
     Variant2 = 11,
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeValueCStyleVariant0 {
     Variant1,
-
-    Variant2 =
-        22,
+    Variant2 = 22,
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeValueCStyleVariant1 {
     Variant1,
     Variant2,
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeValueCStyleVariant1 {
     Variant1,
     Variant2 = 11,
@@ -119,14 +135,16 @@ enum EnumChangeValueCStyleVariant1 {
 
 
 // Add a c-style variant ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddCStyleVariant {
     Variant1,
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddCStyleVariant {
     Variant1,
     Variant2,
@@ -135,15 +153,17 @@ enum EnumAddCStyleVariant {
 
 
 // Remove a c-style variant ---------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumRemoveCStyleVariant {
     Variant1,
     Variant2,
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumRemoveCStyleVariant {
     Variant1,
 }
@@ -151,14 +171,16 @@ enum EnumRemoveCStyleVariant {
 
 
 // Add a tuple-style variant --------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddTupleStyleVariant {
     Variant1,
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddTupleStyleVariant {
     Variant1,
     Variant2(u32, f32),
@@ -167,15 +189,17 @@ enum EnumAddTupleStyleVariant {
 
 
 // Remove a tuple-style variant -----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumRemoveTupleStyleVariant {
     Variant1,
     Variant2(u32, f32),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumRemoveTupleStyleVariant {
     Variant1,
 }
@@ -183,14 +207,16 @@ enum EnumRemoveTupleStyleVariant {
 
 
 // Add a struct-style variant -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddStructStyleVariant {
     Variant1,
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddStructStyleVariant {
     Variant1,
     Variant2 { a: u32, b: f32 },
@@ -199,15 +225,17 @@ enum EnumAddStructStyleVariant {
 
 
 // Remove a struct-style variant ----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumRemoveStructStyleVariant {
     Variant1,
     Variant2 { a: u32, b: f32 },
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumRemoveStructStyleVariant {
     Variant1,
 }
@@ -215,14 +243,16 @@ enum EnumRemoveStructStyleVariant {
 
 
 // Change the type of a field in a tuple-style variant ------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeFieldTypeTupleStyleVariant {
     Variant1(u32, u32),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeFieldTypeTupleStyleVariant {
     Variant1(u32,
         u64),
@@ -231,15 +261,17 @@ enum EnumChangeFieldTypeTupleStyleVariant {
 
 
 // Change the type of a field in a struct-style variant -----------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeFieldTypeStructStyleVariant {
     Variant1,
     Variant2 { a: u32, b: u32 },
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeFieldTypeStructStyleVariant {
     Variant1,
     Variant2 {
@@ -251,14 +283,16 @@ enum EnumChangeFieldTypeStructStyleVariant {
 
 
 // Change the name of a field in a struct-style variant -----------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeFieldNameStructStyleVariant {
     Variant1 { a: u32, b: u32 },
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeFieldNameStructStyleVariant {
     Variant1 { a: u32, c: u32 },
 }
@@ -266,14 +300,16 @@ enum EnumChangeFieldNameStructStyleVariant {
 
 
 // Change order of fields in a tuple-style variant ----------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeOrderTupleStyleVariant {
     Variant1(u32, u64),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeOrderTupleStyleVariant {
     Variant1(
         u64,
@@ -283,14 +319,16 @@ enum EnumChangeOrderTupleStyleVariant {
 
 
 // Change order of fields in a struct-style variant ---------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeFieldOrderStructStyleVariant {
     Variant1 { a: u32, b: f32 },
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeFieldOrderStructStyleVariant {
     Variant1 { b: f32, a: u32 },
 }
@@ -298,14 +336,16 @@ enum EnumChangeFieldOrderStructStyleVariant {
 
 
 // Add a field to a tuple-style variant ---------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddFieldTupleStyleVariant {
     Variant1(u32, u32),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddFieldTupleStyleVariant {
     Variant1(u32, u32, u32),
 }
@@ -313,14 +353,16 @@ enum EnumAddFieldTupleStyleVariant {
 
 
 // Add a field to a struct-style variant --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddFieldStructStyleVariant {
     Variant1 { a: u32, b: u32 },
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddFieldStructStyleVariant {
     Variant1 { a: u32, b: u32, c: u32 },
 }
@@ -328,15 +370,17 @@ enum EnumAddFieldStructStyleVariant {
 
 
 // Add #[must_use] to the enum ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddMustUse {
     Variant1,
     Variant2,
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 #[must_use]
 enum EnumAddMustUse {
     Variant1,
@@ -346,15 +390,17 @@ enum EnumAddMustUse {
 
 
 // Add #[repr(C)] to the enum -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddReprC {
     Variant1,
     Variant2,
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="type_of")]
+#[rustc_clean(cfg="cfail6")]
 #[repr(C)]
 enum EnumAddReprC {
     Variant1,
@@ -364,14 +410,16 @@ enum EnumAddReprC {
 
 
 // Change the name of a type parameter ----------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeNameOfTypeParameter<S> {
     Variant1(S),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeNameOfTypeParameter<T> {
     Variant1(T),
 }
@@ -379,15 +427,17 @@ enum EnumChangeNameOfTypeParameter<T> {
 
 
 // Add a type parameter ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddTypeParameter<S> {
     Variant1(S),
     Variant2(S),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddTypeParameter<S, T> {
     Variant1(S),
     Variant2(T),
@@ -396,14 +446,16 @@ enum EnumAddTypeParameter<S, T> {
 
 
 // Change the name of a lifetime parameter ------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumChangeNameOfLifetimeParameter<'a> {
     Variant1(&'a u32),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumChangeNameOfLifetimeParameter<'b> {
     Variant1(&'b u32),
 }
@@ -411,15 +463,17 @@ enum EnumChangeNameOfLifetimeParameter<'b> {
 
 
 // Add a lifetime parameter ---------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddLifetimeParameter<'a> {
     Variant1(&'a u32),
     Variant2(&'a u32),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddLifetimeParameter<'a, 'b> {
     Variant1(&'a u32),
     Variant2(&'b u32),
@@ -428,30 +482,34 @@ enum EnumAddLifetimeParameter<'a, 'b> {
 
 
 // Add a lifetime bound to a lifetime parameter -------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddLifetimeParameterBound<'a, 'b> {
     Variant1(&'a u32),
     Variant2(&'b u32),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddLifetimeParameterBound<'a, 'b: 'a> {
     Variant1(&'a u32),
     Variant2(&'b u32),
 }
 
 // Add a lifetime bound to a type parameter -----------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddLifetimeBoundToParameter<'a, T> {
     Variant1(T),
     Variant2(&'a u32),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddLifetimeBoundToParameter<'a, T: 'a> {
     Variant1(T),
     Variant2(&'a u32),
@@ -460,14 +518,16 @@ enum EnumAddLifetimeBoundToParameter<'a, T: 'a> {
 
 
 // Add a trait bound to a type parameter --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddTraitBound<S> {
     Variant1(S),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddTraitBound<T: Sync> {
     Variant1(T),
 }
@@ -475,15 +535,17 @@ enum EnumAddTraitBound<T: Sync> {
 
 
 // Add a lifetime bound to a lifetime parameter in where clause ---------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddLifetimeParameterBoundWhere<'a, 'b> {
     Variant1(&'a u32),
     Variant2(&'b u32),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddLifetimeParameterBoundWhere<'a, 'b> where 'b: 'a {
     Variant1(&'a u32),
     Variant2(&'b u32),
@@ -492,15 +554,17 @@ enum EnumAddLifetimeParameterBoundWhere<'a, 'b> where 'b: 'a {
 
 
 // Add a lifetime bound to a type parameter in where clause -------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddLifetimeBoundToParameterWhere<'a, T> {
     Variant1(T),
     Variant2(&'a u32),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddLifetimeBoundToParameterWhere<'a, T> where T: 'a {
     Variant1(T),
     Variant2(&'a u32),
@@ -509,14 +573,16 @@ enum EnumAddLifetimeBoundToParameterWhere<'a, T> where T: 'a {
 
 
 // Add a trait bound to a type parameter in where clause ----------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumAddTraitBoundWhere<S> {
     Variant1(S),
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumAddTraitBoundWhere<T> where T: Sync {
     Variant1(T),
 }
@@ -524,15 +590,17 @@ enum EnumAddTraitBoundWhere<T> where T: Sync {
 
 
 // In an enum with two variants, swap usage of type parameters ----------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumSwapUsageTypeParameters<A, B> {
     Variant1 { a: A },
     Variant2 { a: B },
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumSwapUsageTypeParameters<A, B> {
     Variant1 {
         a: B
@@ -545,15 +613,17 @@ enum EnumSwapUsageTypeParameters<A, B> {
 
 
 // In an enum with two variants, swap usage of lifetime parameters ------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 enum EnumSwapUsageLifetimeParameters<'a, 'b> {
     Variant1 { a: &'a u32 },
     Variant2 { b: &'b u32 },
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 enum EnumSwapUsageLifetimeParameters<'a, 'b> {
     Variant1 {
         a: &'b u32
@@ -572,13 +642,15 @@ struct ReferencedType2;
 
 // Change field type in tuple-style variant indirectly by modifying a use statement
 mod change_field_type_indirectly_tuple_style {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedType1 as FieldType;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedType2 as FieldType;
 
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+    #[rustc_clean(cfg="cfail6")]
     enum TupleStyle {
         Variant1(
             FieldType
@@ -590,13 +662,15 @@ mod change_field_type_indirectly_tuple_style {
 
 // Change field type in record-style variant indirectly by modifying a use statement
 mod change_field_type_indirectly_struct_style {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedType1 as FieldType;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedType2 as FieldType;
 
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+    #[rustc_clean(cfg="cfail6")]
     enum StructStyle {
         Variant1 {
             a: FieldType
@@ -613,13 +687,15 @@ trait ReferencedTrait2 {}
 
 // Change trait bound of type parameter indirectly by modifying a use statement
 mod change_trait_bound_indirectly {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedTrait1 as Trait;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedTrait2 as Trait;
 
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")]
+    #[rustc_clean(cfg="cfail6")]
     enum Enum<T: Trait> {
         Variant1(T)
     }
@@ -629,13 +705,15 @@ mod change_trait_bound_indirectly {
 
 // Change trait bound of type parameter in where clause indirectly by modifying a use statement
 mod change_trait_bound_indirectly_where {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedTrait1 as Trait;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedTrait2 as Trait;
 
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")]
+    #[rustc_clean(cfg="cfail6")]
     enum Enum<T> where T: Trait {
         Variant1(T)
     }
diff --git a/src/test/incremental/hashes/exported_vs_not.rs b/src/test/incremental/hashes/exported_vs_not.rs
index 40b6925bc72..d5fb8a2e534 100644
--- a/src/test/incremental/hashes/exported_vs_not.rs
+++ b/src/test/incremental/hashes/exported_vs_not.rs
@@ -1,6 +1,12 @@
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -10,14 +16,16 @@
 //         the hash of the hir_owner_nodes node should change, but not the hash of
 //         either the hir_owner or the Metadata node.
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn body_not_exported_to_metadata() -> u32 {
     1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn body_not_exported_to_metadata() -> u32 {
     2
 }
@@ -28,15 +36,17 @@ pub fn body_not_exported_to_metadata() -> u32 {
 //         marked as #[inline]. Only the hash of the hir_owner depnode should be
 //         unaffected by a change to the body.
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 #[inline]
 pub fn body_exported_to_metadata_because_of_inline() -> u32 {
     1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 #[inline]
 pub fn body_exported_to_metadata_because_of_inline() -> u32 {
     2
@@ -48,15 +58,17 @@ pub fn body_exported_to_metadata_because_of_inline() -> u32 {
 //         generic. Only the hash of the hir_owner depnode should be
 //         unaffected by a change to the body.
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 #[inline]
 pub fn body_exported_to_metadata_because_of_generic() -> u32 {
     1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 #[inline]
 pub fn body_exported_to_metadata_because_of_generic() -> u32 {
     2
diff --git a/src/test/incremental/hashes/extern_mods.rs b/src/test/incremental/hashes/extern_mods.rs
index 1160bc376c4..783407a9e04 100644
--- a/src/test/incremental/hashes/extern_mods.rs
+++ b/src/test/incremental/hashes/extern_mods.rs
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -15,146 +21,168 @@
 #![crate_type = "rlib"]
 
 // Change function name --------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 extern "C" {
     pub fn change_function_name1(c: i64) -> i32;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner")]
+#[rustc_clean(cfg = "cfail6")]
 extern "C" {
     pub fn change_function_name2(c: i64) -> i32;
 }
 
 // Change parameter name -------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 extern "C" {
     pub fn change_parameter_name(c: i64) -> i32;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 extern "C" {
     pub fn change_parameter_name(d: i64) -> i32;
 }
 
 // Change parameter type -------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 extern "C" {
     pub fn change_parameter_type(c: i64) -> i32;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 extern "C" {
     pub fn change_parameter_type(c: i32) -> i32;
 }
 
 // Change return type ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 extern "C" {
     pub fn change_return_type(c: i32) -> i32;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 extern "C" {
-    pub fn change_return_type(c: i32) -> i8;
+    pub fn change_return_type(c: i32) -> i8 ;
 }
 
 // Add parameter ---------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 extern "C" {
-    pub fn add_parameter(c: i32) -> i32;
+    pub fn add_parameter(c: i32        ) -> i32;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 extern "C" {
     pub fn add_parameter(c: i32, d: i32) -> i32;
 }
 
 // Add return type -------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 extern "C" {
-    pub fn add_return_type(c: i32);
+    pub fn add_return_type(c: i32)       ;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 extern "C" {
     pub fn add_return_type(c: i32) -> i32;
 }
 
 // Make function variadic ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 extern "C" {
-    pub fn make_function_variadic(c: i32);
+    pub fn make_function_variadic(c: i32     );
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 extern "C" {
     pub fn make_function_variadic(c: i32, ...);
 }
 
 // Change calling convention ---------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 extern "C" {
     pub fn change_calling_convention(c: i32);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner")]
+#[rustc_clean(cfg = "cfail6")]
 extern "rust-call" {
     pub fn change_calling_convention(c: i32);
 }
 
 // Make function public --------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 extern "C" {
     fn make_function_public(c: i32);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner")]
+#[rustc_clean(cfg = "cfail6")]
 extern "C" {
     pub fn make_function_public(c: i32);
 }
 
 // Add function ----------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 extern "C" {
     pub fn add_function1(c: i32);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner")]
+#[rustc_clean(cfg = "cfail6")]
 extern "C" {
     pub fn add_function1(c: i32);
     pub fn add_function2();
 }
 
 // Change link-name ------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 #[link(name = "foo")]
 extern "C" {
     pub fn change_link_name(c: i32);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 #[link(name = "bar")]
 extern "C" {
     pub fn change_link_name(c: i32);
@@ -165,13 +193,15 @@ type c_i64 = i64;
 
 // Indirectly change parameter type --------------------------------------------
 mod indirectly_change_parameter_type {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::c_i32 as c_int;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::c_i64 as c_int;
 
     #[rustc_clean(cfg = "cfail2")]
     #[rustc_clean(cfg = "cfail3")]
+    #[rustc_clean(cfg = "cfail5")]
+    #[rustc_clean(cfg = "cfail6")]
     extern "C" {
         pub fn indirectly_change_parameter_type(c: c_int);
     }
@@ -179,13 +209,15 @@ mod indirectly_change_parameter_type {
 
 // Indirectly change return type --------------------------------------------
 mod indirectly_change_return_type {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::c_i32 as c_int;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::c_i64 as c_int;
 
     #[rustc_clean(cfg = "cfail2")]
     #[rustc_clean(cfg = "cfail3")]
+    #[rustc_clean(cfg = "cfail5")]
+    #[rustc_clean(cfg = "cfail6")]
     extern "C" {
         pub fn indirectly_change_return_type() -> c_int;
     }
diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs
index e1460503d2d..5a944d28a0b 100644
--- a/src/test/incremental/hashes/for_loops.rs
+++ b/src/test/incremental/hashes/for_loops.rs
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -15,7 +21,7 @@
 
 
 // Change loop body ------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_loop_body() {
     let mut _x = 0;
     for _ in 0..1 {
@@ -24,9 +30,11 @@ pub fn change_loop_body() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_loop_body() {
     let mut _x = 0;
     for _ in 0..1 {
@@ -38,7 +46,7 @@ pub fn change_loop_body() {
 
 
 // Change iteration variable name ----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_iteration_variable_name() {
     let mut _x = 0;
     for _i in 0..1 {
@@ -47,9 +55,11 @@ pub fn change_iteration_variable_name() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_iteration_variable_name() {
     let mut _x = 0;
     for _a in 0..1 {
@@ -61,18 +71,20 @@ pub fn change_iteration_variable_name() {
 
 
 // Change iteration variable pattern -------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_iteration_variable_pattern() {
     let mut _x = 0;
-    for _i in &[0, 1, 2] {
+    for  _i in &[0, 1, 2] {
         _x = 1;
         break;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck, promoted_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_iteration_variable_pattern() {
     let mut _x = 0;
     for &_i in &[0, 1, 2] {
@@ -84,7 +96,7 @@ pub fn change_iteration_variable_pattern() {
 
 
 // Change iterable -------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_iterable() {
     let mut _x = 0;
     for _ in &[0, 1, 2] {
@@ -93,9 +105,11 @@ pub fn change_iterable() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, promoted_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, promoted_mir, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_iterable() {
     let mut _x = 0;
     for _ in &[0, 1, 3] {
@@ -107,17 +121,20 @@ pub fn change_iterable() {
 
 
 // Add break -------------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_break() {
     let mut _x = 0;
     for _ in 0..1 {
         _x = 1;
+        // ---
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_break() {
     let mut _x = 0;
     for _ in 0..1 {
@@ -129,18 +146,20 @@ pub fn add_break() {
 
 
 // Add loop label --------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label() {
     let mut _x = 0;
-    for _ in 0..1 {
+            for _ in 0..1 {
         _x = 1;
         break;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label() {
     let mut _x = 0;
     'label: for _ in 0..1 {
@@ -152,18 +171,20 @@ pub fn add_loop_label() {
 
 
 // Add loop label to break -----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: for _ in 0..1 {
         _x = 1;
-        break;
+        break       ;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: for _ in 0..1 {
@@ -175,7 +196,7 @@ pub fn add_loop_label_to_break() {
 
 
 // Change break label ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_break_label() {
     let mut _x = 0;
     'outer: for _ in 0..1 {
@@ -186,9 +207,11 @@ pub fn change_break_label() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_break_label() {
     let mut _x = 0;
     'outer: for _ in 0..1 {
@@ -202,18 +225,20 @@ pub fn change_break_label() {
 
 
 // Add loop label to continue --------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: for _ in 0..1 {
         _x = 1;
-        continue;
+        continue       ;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: for _ in 0..1 {
@@ -225,7 +250,7 @@ pub fn add_loop_label_to_continue() {
 
 
 // Change continue label ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_continue_label() {
     let mut _x = 0;
     'outer: for _ in 0..1 {
@@ -236,9 +261,11 @@ pub fn change_continue_label() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_continue_label() {
     let mut _x = 0;
     'outer: for _ in 0..1 {
@@ -252,7 +279,7 @@ pub fn change_continue_label() {
 
 
 // Change continue to break ----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_continue_to_break() {
     let mut _x = 0;
     for _ in 0..1 {
@@ -261,13 +288,15 @@ pub fn change_continue_to_break() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
     for _ in 0..1 {
         _x = 1;
-        break;
+        break   ;
     }
 }
diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs
index c8530c70f78..4124eada188 100644
--- a/src/test/incremental/hashes/function_interfaces.rs
+++ b/src/test/incremental/hashes/function_interfaces.rs
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(linkage)]
@@ -16,248 +22,310 @@
 
 // Add Parameter ---------------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_parameter() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(
     cfg = "cfail2",
     except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+    cfg = "cfail5",
+    except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
 pub fn add_parameter(p: i32) {}
 
 // Add Return Type -------------------------------------------------------------
 
-#[cfg(cfail1)]
-pub fn add_return_type() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn add_return_type()       {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg = "cfail6")]
 pub fn add_return_type() -> () {}
 
 // Change Parameter Type -------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn type_of_parameter(p: i32) {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(
     cfg = "cfail2",
     except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+    cfg = "cfail5",
+    except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
 pub fn type_of_parameter(p: i64) {}
 
 // Change Parameter Type Reference ---------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn type_of_parameter_ref(p: &i32) {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(
     cfg = "cfail2",
     except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+    cfg = "cfail5",
+    except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
 pub fn type_of_parameter_ref(p: &mut i32) {}
 
 // Change Parameter Order ------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn order_of_parameters(p1: i32, p2: i64) {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(
     cfg = "cfail2",
     except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+    cfg = "cfail5",
+    except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
 pub fn order_of_parameters(p2: i64, p1: i32) {}
 
 // Unsafe ----------------------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn make_unsafe() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(
     cfg = "cfail2",
     except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+    cfg = "cfail5",
+    except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
 pub unsafe fn make_unsafe() {}
 
 // Extern ----------------------------------------------------------------------
 
-#[cfg(cfail1)]
-pub fn make_extern() {}
+#[cfg(any(cfail1,cfail4))]
+pub            fn make_extern() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")]
+#[rustc_clean(cfg = "cfail6")]
 pub extern "C" fn make_extern() {}
 
 // Type Parameter --------------------------------------------------------------
 
-#[cfg(cfail1)]
-pub fn type_parameter() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn type_parameter   () {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(
     cfg = "cfail2",
     except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of"
 )]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+    cfg = "cfail5",
+    except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of"
+)]
+#[rustc_clean(cfg = "cfail6")]
 pub fn type_parameter<T>() {}
 
 // Lifetime Parameter ----------------------------------------------------------
 
-#[cfg(cfail1)]
-pub fn lifetime_parameter() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn lifetime_parameter    () {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, generics_of,fn_sig")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, generics_of,fn_sig")]
+#[rustc_clean(cfg = "cfail6")]
 pub fn lifetime_parameter<'a>() {}
 
 // Trait Bound -----------------------------------------------------------------
 
-#[cfg(cfail1)]
-pub fn trait_bound<T>() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn trait_bound<T    >() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn trait_bound<T: Eq>() {}
 
 // Builtin Bound ---------------------------------------------------------------
 
-#[cfg(cfail1)]
-pub fn builtin_bound<T>() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn builtin_bound<T      >() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")]
+#[rustc_clean(cfg = "cfail6")]
 pub fn builtin_bound<T: Send>() {}
 
 // Lifetime Bound --------------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn lifetime_bound<'a, T>() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(
     cfg = "cfail2",
     except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+    cfg = "cfail5",
+    except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig,optimized_mir"
+)]
+#[rustc_clean(cfg = "cfail6")]
 pub fn lifetime_bound<'a, T: 'a>() {}
 
 // Second Trait Bound ----------------------------------------------------------
 
-#[cfg(cfail1)]
-pub fn second_trait_bound<T: Eq>() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn second_trait_bound<T: Eq        >() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
 pub fn second_trait_bound<T: Eq + Clone>() {}
 
 // Second Builtin Bound --------------------------------------------------------
 
-#[cfg(cfail1)]
-pub fn second_builtin_bound<T: Send>() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn second_builtin_bound<T: Send        >() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")]
+#[rustc_clean(cfg = "cfail6")]
 pub fn second_builtin_bound<T: Send + Sized>() {}
 
 // Second Lifetime Bound -------------------------------------------------------
 
-#[cfg(cfail1)]
-pub fn second_lifetime_bound<'a, 'b, T: 'a>() {}
+#[cfg(any(cfail1,cfail4))]
+pub fn second_lifetime_bound<'a, 'b, T: 'a     >() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(
     cfg = "cfail2",
     except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig"
 )]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(
+    cfg = "cfail5",
+    except = "hir_owner, hir_owner_nodes, generics_of, type_of, predicates_of,fn_sig"
+)]
+#[rustc_clean(cfg = "cfail6")]
 pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {}
 
 // Inline ----------------------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn inline() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 #[inline]
 pub fn inline() {}
 
 // Inline Never ----------------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 #[inline(always)]
 pub fn inline_never() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 #[inline(never)]
 pub fn inline_never() {}
 
 // No Mangle -------------------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn no_mangle() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 #[no_mangle]
 pub fn no_mangle() {}
 
 // Linkage ---------------------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn linkage() {}
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
 #[linkage = "weak_odr"]
 pub fn linkage() {}
 
 // Return Impl Trait -----------------------------------------------------------
 
-#[cfg(cfail1)]
-pub fn return_impl_trait() -> i32 {
+#[cfg(any(cfail1,cfail4))]
+pub fn return_impl_trait() -> i32        {
     0
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, typeck, fn_sig")]
 #[rustc_clean(cfg = "cfail3")]
+#[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, typeck, fn_sig, optimized_mir")]
+#[rustc_clean(cfg = "cfail6")]
 pub fn return_impl_trait() -> impl Clone {
     0
 }
 
 // Change Return Impl Trait ----------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_return_impl_trait() -> impl Clone {
     0u32
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg = "cfail2")]
 #[rustc_clean(cfg = "cfail3")]
-pub fn change_return_impl_trait() -> impl Copy {
+#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail6")]
+pub fn change_return_impl_trait() -> impl  Copy {
     0u32
 }
 
@@ -267,9 +335,9 @@ pub struct ReferencedType1;
 pub struct ReferencedType2;
 
 pub mod change_return_type_indirectly {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedType1 as ReturnType;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedType2 as ReturnType;
 
     #[rustc_clean(
@@ -277,6 +345,11 @@ pub mod change_return_type_indirectly {
         except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
     )]
     #[rustc_clean(cfg = "cfail3")]
+    #[rustc_clean(
+        cfg = "cfail5",
+        except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+    )]
+    #[rustc_clean(cfg = "cfail6")]
     pub fn indirect_return_type() -> ReturnType {
         ReturnType {}
     }
@@ -285,9 +358,9 @@ pub mod change_return_type_indirectly {
 // Change Parameter Type Indirectly --------------------------------------------
 
 pub mod change_parameter_type_indirectly {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedType1 as ParameterType;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedType2 as ParameterType;
 
     #[rustc_clean(
@@ -295,6 +368,11 @@ pub mod change_parameter_type_indirectly {
         except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
     )]
     #[rustc_clean(cfg = "cfail3")]
+    #[rustc_clean(
+        cfg = "cfail5",
+        except = "hir_owner, hir_owner_nodes, optimized_mir, typeck, fn_sig"
+    )]
+    #[rustc_clean(cfg = "cfail6")]
     pub fn indirect_parameter_type(p: ParameterType) {}
 }
 
@@ -304,26 +382,30 @@ pub trait ReferencedTrait1 {}
 pub trait ReferencedTrait2 {}
 
 pub mod change_trait_bound_indirectly {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedTrait1 as Trait;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedTrait2 as Trait;
 
     #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
     #[rustc_clean(cfg = "cfail3")]
+    #[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")]
+    #[rustc_clean(cfg = "cfail6")]
     pub fn indirect_trait_bound<T: Trait>(p: T) {}
 }
 
 // Change Trait Bound Indirectly In Where Clause -------------------------------
 
 pub mod change_trait_bound_indirectly_in_where_clause {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedTrait1 as Trait;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedTrait2 as Trait;
 
     #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_nodes, predicates_of")]
     #[rustc_clean(cfg = "cfail3")]
+    #[rustc_clean(cfg = "cfail5", except = "hir_owner, hir_owner_nodes, predicates_of")]
+    #[rustc_clean(cfg = "cfail6")]
     pub fn indirect_trait_bound_where<T>(p: T)
     where
         T: Trait,
diff --git a/src/test/incremental/hashes/if_expressions.rs b/src/test/incremental/hashes/if_expressions.rs
index ddae9c9f032..0c5e73b0107 100644
--- a/src/test/incremental/hashes/if_expressions.rs
+++ b/src/test/incremental/hashes/if_expressions.rs
@@ -6,27 +6,34 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
-
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
 #![crate_type="rlib"]
 
 // Change condition (if)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_condition(x: bool) -> u32 {
-    if x {
+    if  x {
         return 1
     }
 
     return 0
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_condition(x: bool) -> u32 {
     if !x {
         return 1
@@ -36,7 +43,7 @@ pub fn change_condition(x: bool) -> u32 {
 }
 
 // Change then branch (if)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_then_branch(x: bool) -> u32 {
     if x {
         return 1
@@ -45,9 +52,11 @@ pub fn change_then_branch(x: bool) -> u32 {
     return 0
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_then_branch(x: bool) -> u32 {
     if x {
         return 2
@@ -59,7 +68,7 @@ pub fn change_then_branch(x: bool) -> u32 {
 
 
 // Change else branch (if)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_else_branch(x: bool) -> u32 {
     if x {
         1
@@ -68,9 +77,11 @@ pub fn change_else_branch(x: bool) -> u32 {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_else_branch(x: bool) -> u32 {
     if x {
         1
@@ -82,20 +93,23 @@ pub fn change_else_branch(x: bool) -> u32 {
 
 
 // Add else branch (if)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_else_branch(x: bool) -> u32 {
     let mut ret = 1;
 
     if x {
         ret = 2;
+    /*----*/
     }
 
     ret
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_else_branch(x: bool) -> u32 {
     let mut ret = 1;
 
@@ -110,7 +124,7 @@ pub fn add_else_branch(x: bool) -> u32 {
 
 
 // Change condition (if let)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_condition_if_let(x: Option<u32>) -> u32 {
     if let Some(_x) = x {
         return 1
@@ -119,11 +133,13 @@ pub fn change_condition_if_let(x: Option<u32>) -> u32 {
     0
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_condition_if_let(x: Option<u32>) -> u32 {
-    if let Some(_) = x {
+    if let Some(_ ) = x {
         return 1
     }
 
@@ -133,18 +149,20 @@ pub fn change_condition_if_let(x: Option<u32>) -> u32 {
 
 
 // Change then branch (if let)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
     if let Some(x) = x {
-        return x
+        return x //-
     }
 
     0
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
     if let Some(x) = x {
         return x + 1
@@ -156,7 +174,7 @@ pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
 
 
 // Change else branch (if let)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
     if let Some(x) = x {
         x
@@ -165,9 +183,11 @@ pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
     if let Some(x) = x {
         x
@@ -179,20 +199,23 @@ pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
 
 
 // Add else branch (if let)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_else_branch_if_let(x: Option<u32>) -> u32 {
     let mut ret = 1;
 
     if let Some(x) = x {
         ret = x;
+    /*----*/
     }
 
     ret
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_else_branch_if_let(x: Option<u32>) -> u32 {
     let mut ret = 1;
 
diff --git a/src/test/incremental/hashes/indexing_expressions.rs b/src/test/incremental/hashes/indexing_expressions.rs
index 49ee7a9cac0..0532f4a0fd6 100644
--- a/src/test/incremental/hashes/indexing_expressions.rs
+++ b/src/test/incremental/hashes/indexing_expressions.rs
@@ -6,22 +6,30 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
 #![crate_type="rlib"]
 
 // Change simple index
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 fn change_simple_index(slice: &[u32]) -> u32 {
     slice[3]
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 fn change_simple_index(slice: &[u32]) -> u32 {
     slice[4]
 }
@@ -29,14 +37,16 @@ fn change_simple_index(slice: &[u32]) -> u32 {
 
 
 // Change lower bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 fn change_lower_bound(slice: &[u32]) -> &[u32] {
     &slice[3..5]
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 fn change_lower_bound(slice: &[u32]) -> &[u32] {
     &slice[2..5]
 }
@@ -44,14 +54,16 @@ fn change_lower_bound(slice: &[u32]) -> &[u32] {
 
 
 // Change upper bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 fn change_upper_bound(slice: &[u32]) -> &[u32] {
     &slice[3..5]
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 fn change_upper_bound(slice: &[u32]) -> &[u32] {
     &slice[3..7]
 }
@@ -59,14 +71,16 @@ fn change_upper_bound(slice: &[u32]) -> &[u32] {
 
 
 // Add lower bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 fn add_lower_bound(slice: &[u32]) -> &[u32] {
-    &slice[..4]
+    &slice[ ..4]
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 fn add_lower_bound(slice: &[u32]) -> &[u32] {
     &slice[3..4]
 }
@@ -74,14 +88,16 @@ fn add_lower_bound(slice: &[u32]) -> &[u32] {
 
 
 // Add upper bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 fn add_upper_bound(slice: &[u32]) -> &[u32] {
-    &slice[3..]
+    &slice[3.. ]
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 fn add_upper_bound(slice: &[u32]) -> &[u32] {
     &slice[3..7]
 }
@@ -89,29 +105,33 @@ fn add_upper_bound(slice: &[u32]) -> &[u32] {
 
 
 // Change mutability
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 fn change_mutability(slice: &mut [u32]) -> u32 {
     (&mut slice[3..5])[0]
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 fn change_mutability(slice: &mut [u32]) -> u32 {
-    (&slice[3..5])[0]
+    (&    slice[3..5])[0]
 }
 
 
 
 // Exclusive to inclusive range
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] {
-    &slice[3..7]
+    &slice[3.. 7]
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 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 284a95f1a68..d711cc20dd7 100644
--- a/src/test/incremental/hashes/inherent_impls.rs
+++ b/src/test/incremental/hashes/inherent_impls.rs
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 
 #![allow(warnings)]
@@ -17,36 +23,46 @@
 pub struct Foo;
 
 // Change Method Name -----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
     pub fn method_name() { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,associated_item_def_ids")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,associated_item_def_ids")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn method_name2() { }
 }
 
 // Change Method Body -----------------------------------------------------------
 //
 // This should affect the method itself, but not the impl.
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
-    pub fn method_body() { }
+    //--------------------------------------------------------------------------------------
+    //--------------------------
+    //--------------------------------------------------------------------------------------
+    //--------------------------
+    pub fn method_body() {
+        // -----------------------
+    }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
-    #[rustc_clean(
-        cfg="cfail2",
-        except="hir_owner_nodes,optimized_mir,promoted_mir,typeck"
-    )]
+    #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,promoted_mir,typeck")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,promoted_mir,typeck")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn method_body() {
         println!("Hello, world!");
     }
@@ -56,21 +72,40 @@ impl Foo {
 // Change Method Body (inlined) ------------------------------------------------
 //
 // This should affect the method itself, but not the impl.
-#[cfg(cfail1)]
-impl Foo {
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+    //------------
+    //---------------
+    //------------------------------------------------------------
+    //
+    //--------------------------
+    //------------
+    //---------------
+    //------------------------------------------------------------
+    //
+    //--------------------------
     #[inline]
-    pub fn method_body_inlined() { }
+    pub fn method_body_inlined() {
+        // -----------------------
+    }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
         except="hir_owner_nodes,optimized_mir,promoted_mir,typeck"
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        cfg="cfail5",
+        except="hir_owner_nodes,optimized_mir,promoted_mir,typeck"
+    )]
+    #[rustc_clean(cfg="cfail6")]
     #[inline]
     pub fn method_body_inlined() {
         println!("Hello, world!");
@@ -79,146 +114,205 @@ impl Foo {
 
 
 // Change Method Privacy -------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
     pub fn method_privacy() { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(cfg="cfail2", except="associated_item,hir_owner,hir_owner_nodes")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="associated_item,hir_owner,hir_owner_nodes,optimized_mir")]
+    #[rustc_clean(cfg="cfail6")]
     fn method_privacy() { }
 }
 
 // Change Method Selfness -----------------------------------------------------------
-#[cfg(cfail1)]
-impl Foo {
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+    //------------
+    //---------------
+    //---------------------------------------------------------------------------------------------
+    //
+    //--------------------------
+    //------------
+    //---------------
+    //---------------------------------------------------------------------------------------------
+    //
+    //--------------------------
     pub fn method_selfness() { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
         except="hir_owner,hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir",
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        cfg="cfail5",
+        except="hir_owner,hir_owner_nodes,fn_sig,generics_of,typeck,associated_item,optimized_mir",
+    )]
+    #[rustc_clean(cfg="cfail6")]
     pub fn method_selfness(&self) { }
 }
 
 // Change Method Selfmutness ---------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
-    pub fn method_selfmutness(&self) { }
+    //------------------------------------------------------------------------------------------
+    //--------------------------
+    //------------------------------------------------------------------------------------------
+    //--------------------------
+    pub fn method_selfmutness(&    self) { }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
-    #[rustc_clean(
-        cfg="cfail2",
-        except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir"
-    )]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn method_selfmutness(&mut self) { }
 }
 
 
 
 // Add Method To Impl ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
     pub fn add_method_to_impl1(&self) { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,associated_item_def_ids")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,associated_item_def_ids")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_method_to_impl1(&self) { }
 
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_method_to_impl2(&self) { }
 }
 
 
 
 // Add Method Parameter --------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
-    pub fn add_method_parameter(&self) { }
+    //------------------------------------------------------------------------------------------
+    //--------------------------
+    //------------------------------------------------------------------------------------------
+    //--------------------------
+    pub fn add_method_parameter(&self        ) { }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
-    #[rustc_clean(
-        cfg="cfail2",
-        except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir"
-    )]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_method_parameter(&self, _: i32) { }
 }
 
 
 
 // Change Method Parameter Name ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
+    //------------------------------------------------------------------
+    //--------------------------
+    //------------------------------------------------------------------
+    //--------------------------
     pub fn change_method_parameter_name(&self, a: i64) { }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn change_method_parameter_name(&self, b: i64) { }
 }
 
 
 
 // Change Method Return Type ---------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
+    //------------------------------------------------------------------------------------------
+    //--------------------------
+    //------------------------------------------------------------------------------------------
+    //--------------------------
     pub fn change_method_return_type(&self) -> u16 { 0 }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
-    #[rustc_clean(
-        cfg="cfail2",
-        except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,typeck")]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,typeck")]
     #[rustc_clean(cfg="cfail3")]
-    pub fn change_method_return_type(&self) -> u8 { 0 }
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,optimized_mir,typeck")]
+    #[rustc_clean(cfg="cfail6")]
+    pub fn change_method_return_type(&self) -> u32 { 0 }
 }
 
 
 
 // Make Method #[inline] -------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
+    //--------------------------
+    //--------------------------
+    //--------------------------
+    //--------------------------
+    //-------
     pub fn make_method_inline(&self) -> u8 { 0 }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     #[inline]
     pub fn make_method_inline(&self) -> u8 { 0 }
 }
@@ -226,85 +320,129 @@ impl Foo {
 
 
 //  Change order of parameters -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
+    //------------------------------------------------------------------
+    //--------------------------
+    //------------------------------------------------------------------
+    //--------------------------
     pub fn change_method_parameter_order(&self, a: i64, b: i64) { }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn change_method_parameter_order(&self, b: i64, a: i64) { }
 }
 
 
 
 // Make method unsafe ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
-    pub fn make_method_unsafe(&self) { }
+    //------------------------------------------------------------------------------------------
+    //--------------------------
+    //------------------------------------------------------------------------------------------
+    //--------------------------
+    pub        fn make_method_unsafe(&self) { }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
-    #[rustc_clean(
-        cfg="cfail2",
-        except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir"
-    )]
+    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir")]
+    #[rustc_clean(cfg="cfail6")]
     pub unsafe fn make_method_unsafe(&self) { }
 }
 
 
 
 // Make method extern ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
-    pub fn make_method_extern(&self) { }
+    //----------------------------------------------------------------------------
+    //--------------------------
+    //----------------------------------------------------------------------------
+    //--------------------------
+    pub            fn make_method_extern(&self) { }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck")]
+    #[rustc_clean(cfg="cfail6")]
     pub extern "C" fn make_method_extern(&self) { }
 }
 
 
 
 // Change method calling convention --------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
-    pub extern "C" fn change_method_calling_convention(&self) { }
+    //----------------------------------------------------------------------------
+    //--------------------------
+    //----------------------------------------------------------------------------
+    //--------------------------
+    pub extern "C"      fn change_method_calling_convention(&self) { }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig,typeck")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,typeck")]
+    #[rustc_clean(cfg="cfail6")]
     pub extern "system" fn change_method_calling_convention(&self) { }
 }
 
 
 
 // Add Lifetime Parameter to Method --------------------------------------------
-#[cfg(cfail1)]
-impl Foo {
-    pub fn add_lifetime_parameter_to_method(&self) { }
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+    // -----------------------------------------------------
+    // ---------------------------------------------------------
+    // ----------------------------------------------------------
+    // -------------------------------------------------------
+    // -------------------------------------------------------
+    // --------------------------------------------------------
+    // ----------------------------------------------------------
+    // -----------------------------------------------------------
+    // ----------------------------------------------------------
+    // --------------------------------------------------------------------
+    // -------------------------
+    // --------------------------------------------------------------------------------
+    // -------------------------
+    pub fn add_lifetime_parameter_to_method    (&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     // Warning: Note that `typeck` are coming up clean here.
     // The addition or removal of lifetime parameters that don't
@@ -317,20 +455,43 @@ impl Foo {
     // `typeck` appear dirty, that might be the cause. -nmatsakis
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,fn_sig")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,fn_sig,generics_of")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_lifetime_parameter_to_method<'a>(&self) { }
 }
 
 
 
 // Add Type Parameter To Method ------------------------------------------------
-#[cfg(cfail1)]
-impl Foo {
-    pub fn add_type_parameter_to_method(&self) { }
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+    // -----------------------------------------------------
+    // ---------------------------------------------------------------
+    // -------------------------------------------------------------
+    // -----------------------------------------------------
+    // -------------------------------------------------------------
+    // ---------------------------------------------------
+    // ------------------------------------------------------------
+    // ------------------------------------------------------
+    // -------------------------------------------------
+    // -----------
+    // --------------
+    // ----------------------------------------------------------------------
+    //
+    // -------------------------
+    // -----------
+    // --------------
+    // ----------------------------------------------------------------------
+    //
+    // -------------------------
+    pub fn add_type_parameter_to_method   (&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     // Warning: Note that `typeck` are coming up clean here.
     // The addition or removal of type parameters that don't appear in
@@ -346,40 +507,83 @@ impl Foo {
         except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of",
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        cfg="cfail5",
+        except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of",
+    )]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_type_parameter_to_method<T>(&self) { }
 }
 
 
 
 // Add Lifetime Bound to Lifetime Parameter of Method --------------------------
-#[cfg(cfail1)]
-impl Foo {
-    pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b>(&self) { }
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+    //------------
+    //---------------
+    //-----------------------------------------------------------------------------
+    //
+    //--------------------------
+    //------------
+    //---------------
+    //-----------------------------------------------------------------------------
+    //
+    //--------------------------
+    pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b    >(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(
         cfg="cfail2",
         except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig"
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        cfg="cfail5",
+        except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig"
+    )]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { }
 }
 
 
 
 // Add Lifetime Bound to Type Parameter of Method ------------------------------
-#[cfg(cfail1)]
-impl Foo {
-    pub fn add_lifetime_bound_to_type_param_of_method<'a, T>(&self) { }
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+    // -----------------------------------------------------
+    // ----------------------------------------------------------
+    // -------------------------------------------------------------
+    // -------------------------------------------------
+    // -------------------------------------------------------------
+    // ---------------------------------------------------
+    // ------------------------------------------------------------
+    // ------------------------------------------------------
+    // -------------------------------------------------
+    // -----------
+    // --------------
+    // ----------------------------------------------------------------------------
+    //
+    // -------------------------
+    // -----------
+    // --------------
+    // ----------------------------------------------------------------------------
+    //
+    // -------------------------
+    pub fn add_lifetime_bound_to_type_param_of_method<'a, T    >(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     // Warning: Note that `typeck` are coming up clean here.
     // The addition or removal of bounds that don't appear in the
@@ -390,23 +594,45 @@ impl Foo {
     // generics before the body, then the `HirId` for things in the
     // body will be affected. So if you start to see `typeck`
     // appear dirty, that might be the cause. -nmatsakis
-    #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of,predicates_of,\
-                                        type_of,fn_sig")]
+    #[rustc_clean(
+        cfg="cfail2",
+        except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig"
+    )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        cfg="cfail5",
+        except="hir_owner,hir_owner_nodes,generics_of,predicates_of,type_of,fn_sig"
+    )]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { }
 }
 
 
 
 // Add Trait Bound to Type Parameter of Method ------------------------------
-#[cfg(cfail1)]
-impl Foo {
-    pub fn add_trait_bound_to_type_param_of_method<T>(&self) { }
-}
-
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(any(cfail1,cfail4))]
+impl Foo {
+    // -----------------------------------------------------
+    // ----------------------------------------------------------
+    // -------------------------------------------------------------
+    // -------------------------------------------------
+    // -------------------------------------------------------------
+    // ---------------------------------------------------
+    // ------------------------------------------------------------
+    // ------------------------------------------------------
+    // -------------------------------------------------
+    // ---------------------------------------------------------------------------
+    // -------------------------
+    // ---------------------------------------------------------------------------
+    // -------------------------
+    pub fn add_trait_bound_to_type_param_of_method<T       >(&self) { }
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     // Warning: Note that `typeck` are coming up clean here.
     // The addition or removal of bounds that don't appear in the
@@ -419,23 +645,34 @@ impl Foo {
     // appear dirty, that might be the cause. -nmatsakis
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,predicates_of")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,predicates_of")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_trait_bound_to_type_param_of_method<T: Clone>(&self) { }
 }
 
 
 
 // Add #[no_mangle] to Method --------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Foo {
+    //--------------------------
+    //--------------------------
+    //--------------------------
+    //--------------------------
+    //----------
     pub fn add_no_mangle_to_method(&self) { }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl Foo {
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     #[no_mangle]
     pub fn add_no_mangle_to_method(&self) { }
 }
@@ -445,71 +682,90 @@ impl Foo {
 struct Bar<T>(T);
 
 // Add Type Parameter To Impl --------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Bar<u32> {
     pub fn add_type_parameter_to_impl(&self) { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,generics_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,generics_of")]
+#[rustc_clean(cfg="cfail6")]
 impl<T> Bar<T> {
     #[rustc_clean(
         cfg="cfail2",
         except="generics_of,fn_sig,typeck,type_of,optimized_mir"
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        cfg="cfail5",
+        except="generics_of,fn_sig,typeck,type_of,optimized_mir"
+    )]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_type_parameter_to_impl(&self) { }
 }
 
 
 
 // Change Self Type of Impl ----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl Bar<u32> {
     pub fn change_impl_self_type(&self) { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner")]
+#[rustc_clean(cfg="cfail6")]
 impl Bar<u64> {
     #[rustc_clean(cfg="cfail2", except="fn_sig,optimized_mir,typeck")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="fn_sig,optimized_mir,typeck")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn change_impl_self_type(&self) { }
 }
 
 
 
 // Add Lifetime Bound to Impl --------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl<T> Bar<T> {
     pub fn add_lifetime_bound_to_impl_parameter(&self) { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl<T: 'static> Bar<T> {
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_lifetime_bound_to_impl_parameter(&self) { }
 }
 
 
 
 // Add Trait Bound to Impl Parameter -------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl<T> Bar<T> {
     pub fn add_trait_bound_to_impl_parameter(&self) { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 impl<T: Clone> Bar<T> {
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     pub fn add_trait_bound_to_impl_parameter(&self) { }
 }
 
@@ -518,12 +774,12 @@ impl<T: Clone> Bar<T> {
 pub fn instantiation_root() {
     Foo::method_privacy();
 
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     {
         Bar(0u32).change_impl_self_type();
     }
 
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     {
         Bar(0u64).change_impl_self_type();
     }
diff --git a/src/test/incremental/hashes/inline_asm.rs b/src/test/incremental/hashes/inline_asm.rs
index 7fd9975bc22..a5d53258a7b 100644
--- a/src/test/incremental/hashes/inline_asm.rs
+++ b/src/test/incremental/hashes/inline_asm.rs
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -17,7 +23,7 @@
 
 
 // Change template
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_template(a: i32) -> i32 {
     let c: i32;
@@ -32,9 +38,11 @@ pub fn change_template(a: i32) -> i32 {
     c
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_template(a: i32) -> i32 {
     let c: i32;
@@ -52,7 +60,7 @@ pub fn change_template(a: i32) -> i32 {
 
 
 // Change output
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_output(a: i32) -> i32 {
     let mut _out1: i32 = 0;
@@ -68,9 +76,11 @@ pub fn change_output(a: i32) -> i32 {
     _out1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_output(a: i32) -> i32 {
     let mut _out1: i32 = 0;
@@ -89,7 +99,7 @@ pub fn change_output(a: i32) -> i32 {
 
 
 // Change input
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_input(_a: i32, _b: i32) -> i32 {
     let _out;
@@ -104,9 +114,11 @@ pub fn change_input(_a: i32, _b: i32) -> i32 {
     _out
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_input(_a: i32, _b: i32) -> i32 {
     let _out;
@@ -124,7 +136,7 @@ pub fn change_input(_a: i32, _b: i32) -> i32 {
 
 
 // Change input constraint
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
     let _out;
@@ -139,9 +151,11 @@ pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
     _out
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
     let _out;
@@ -159,7 +173,7 @@ pub fn change_input_constraint(_a: i32, _b: i32) -> i32 {
 
 
 // Change clobber
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_clobber(_a: i32) -> i32 {
     let _out;
@@ -167,16 +181,18 @@ pub fn change_clobber(_a: i32) -> i32 {
         llvm_asm!("add 1, $0"
                   : "=r"(_out)
                   : "0"(_a)
-                  :
+                  :/*--*/
                   :
                   );
     }
     _out
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_clobber(_a: i32) -> i32 {
     let _out;
@@ -194,7 +210,7 @@ pub fn change_clobber(_a: i32) -> i32 {
 
 
 // Change options
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_options(_a: i32) -> i32 {
     let _out;
@@ -203,15 +219,17 @@ pub fn change_options(_a: i32) -> i32 {
                   : "=r"(_out)
                   : "0"(_a)
                   :
-                  :
+                  :/*-------*/
                   );
     }
     _out
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 pub fn change_options(_a: i32) -> i32 {
     let _out;
diff --git a/src/test/incremental/hashes/let_expressions.rs b/src/test/incremental/hashes/let_expressions.rs
index 918e72582d6..a9f90ca9fed 100644
--- a/src/test/incremental/hashes/let_expressions.rs
+++ b/src/test/incremental/hashes/let_expressions.rs
@@ -6,24 +6,30 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
-
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
 #![crate_type="rlib"]
 
 // Change Name -----------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_name() {
     let _x = 2u64;
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_name() {
     let _y = 2u64;
 }
@@ -31,15 +37,16 @@ pub fn change_name() {
 
 
 // Add Type --------------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_type() {
-    let _x = 2u32;
+    let _x      = 2u32;
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_type() {
     let _x: u32 = 2u32;
 }
@@ -47,31 +54,33 @@ pub fn add_type() {
 
 
 // Change Type -----------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_type() {
     let _x: u64 = 2;
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_type() {
-    let _x: u8 = 2;
+    let _x: u8  = 2;
 }
 
 
 
 // Change Mutability of Reference Type -----------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_mutability_of_reference_type() {
-    let _x: &u64;
+    let _x: &    u64;
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_mutability_of_reference_type() {
     let _x: &mut u64;
 }
@@ -79,31 +88,33 @@ pub fn change_mutability_of_reference_type() {
 
 
 // Change Mutability of Slot ---------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_mutability_of_slot() {
     let mut _x: u64 = 0;
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_mutability_of_slot() {
-    let _x: u64 = 0;
+    let     _x: u64 = 0;
 }
 
 
 
 // Change Simple Binding to Pattern --------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_simple_binding_to_pattern() {
-    let _x = (0u8, 'x');
+    let  _x      = (0u8, 'x');
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_simple_binding_to_pattern() {
     let (_a, _b) = (0u8, 'x');
 }
@@ -111,15 +122,16 @@ pub fn change_simple_binding_to_pattern() {
 
 
 // Change Name in Pattern ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_name_in_pattern() {
     let (_a, _b) = (1u8, 'y');
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_name_in_pattern() {
     let (_a, _c) = (1u8, 'y');
 }
@@ -127,15 +139,16 @@ pub fn change_name_in_pattern() {
 
 
 // Add `ref` in Pattern --------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_ref_in_pattern() {
-    let (_a, _b) = (1u8, 'y');
+    let (    _a, _b) = (1u8, 'y');
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_ref_in_pattern() {
     let (ref _a, _b) = (1u8, 'y');
 }
@@ -143,15 +156,16 @@ pub fn add_ref_in_pattern() {
 
 
 // Add `&` in Pattern ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_amp_in_pattern() {
-    let (_a, _b) = (&1u8, 'y');
+    let ( _a, _b) = (&1u8, 'y');
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_amp_in_pattern() {
     let (&_a, _b) = (&1u8, 'y');
 }
@@ -159,15 +173,16 @@ pub fn add_amp_in_pattern() {
 
 
 // Change Mutability of Binding in Pattern -------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_mutability_of_binding_in_pattern() {
-    let (_a, _b) = (99u8, 'q');
+    let (    _a, _b) = (99u8, 'q');
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_mutability_of_binding_in_pattern() {
     let (mut _a, _b) = (99u8, 'q');
 }
@@ -175,15 +190,16 @@ pub fn change_mutability_of_binding_in_pattern() {
 
 
 // Add Initializer -------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_initializer() {
-    let _x: i16;
+    let _x: i16       ;
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,typeck,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_initializer() {
     let _x: i16 = 3i16;
 }
@@ -191,15 +207,16 @@ pub fn add_initializer() {
 
 
 // Change Initializer ----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_initializer() {
     let _x = 4u16;
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_initializer() {
     let _x = 5u16;
 }
diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs
index 178def016a2..6fef31f5b32 100644
--- a/src/test/incremental/hashes/loop_expressions.rs
+++ b/src/test/incremental/hashes/loop_expressions.rs
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -15,7 +21,7 @@
 
 
 // Change loop body
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_loop_body() {
     let mut _x = 0;
     loop {
@@ -24,9 +30,11 @@ pub fn change_loop_body() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_loop_body() {
     let mut _x = 0;
     loop {
@@ -38,17 +46,20 @@ pub fn change_loop_body() {
 
 
 // Add break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_break() {
     let mut _x = 0;
     loop {
         _x = 1;
+        //----
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_break() {
     let mut _x = 0;
     loop {
@@ -60,18 +71,20 @@ pub fn add_break() {
 
 
 // Add loop label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label() {
     let mut _x = 0;
-    loop {
+    /*---*/ loop {
         _x = 1;
         break;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label() {
     let mut _x = 0;
     'label: loop {
@@ -83,18 +96,20 @@ pub fn add_loop_label() {
 
 
 // Add loop label to break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: loop {
         _x = 1;
-        break;
+        break       ;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: loop {
@@ -106,7 +121,7 @@ pub fn add_loop_label_to_break() {
 
 
 // Change break label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_break_label() {
     let mut _x = 0;
     'outer: loop {
@@ -117,9 +132,11 @@ pub fn change_break_label() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_break_label() {
     let mut _x = 0;
     'outer: loop {
@@ -133,18 +150,20 @@ pub fn change_break_label() {
 
 
 // Add loop label to continue
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: loop {
         _x = 1;
-        continue;
+        continue       ;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: loop {
@@ -156,7 +175,7 @@ pub fn add_loop_label_to_continue() {
 
 
 // Change continue label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_continue_label() {
     let mut _x = 0;
     'outer: loop {
@@ -167,9 +186,11 @@ pub fn change_continue_label() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_continue_label() {
     let mut _x = 0;
     'outer: loop {
@@ -183,7 +204,7 @@ pub fn change_continue_label() {
 
 
 // Change continue to break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_continue_to_break() {
     let mut _x = 0;
     loop {
@@ -192,13 +213,15 @@ pub fn change_continue_to_break() {
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
     loop {
         _x = 1;
-        break;
+        break   ;
     }
 }
diff --git a/src/test/incremental/hashes/match_expressions.rs b/src/test/incremental/hashes/match_expressions.rs
index 969f930f57b..314461b5909 100644
--- a/src/test/incremental/hashes/match_expressions.rs
+++ b/src/test/incremental/hashes/match_expressions.rs
@@ -6,28 +6,35 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
-
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
 #![crate_type="rlib"]
 
 // Add Arm ---------------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_arm(x: u32) -> u32 {
     match x {
         0 => 0,
         1 => 1,
+        /*---*/
         _ => 100,
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_arm(x: u32) -> u32 {
     match x {
         0 => 0,
@@ -40,7 +47,7 @@ pub fn add_arm(x: u32) -> u32 {
 
 
 // Change Order Of Arms --------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_order_of_arms(x: u32) -> u32 {
     match x {
         0 => 0,
@@ -49,10 +56,11 @@ pub fn change_order_of_arms(x: u32) -> u32 {
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_order_of_arms(x: u32) -> u32 {
     match x {
         1 => 1,
@@ -64,19 +72,20 @@ pub fn change_order_of_arms(x: u32) -> u32 {
 
 
 // Add Guard Clause ------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_guard_clause(x: u32, y: bool) -> u32 {
     match x {
         0 => 0,
-        1 => 1,
+        1      => 1,
         _ => 100,
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_guard_clause(x: u32, y: bool) -> u32 {
     match x {
         0 => 0,
@@ -88,19 +97,20 @@ pub fn add_guard_clause(x: u32, y: bool) -> u32 {
 
 
 // Change Guard Clause ------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_guard_clause(x: u32, y: bool) -> u32 {
     match x {
         0 => 0,
-        1 if y => 1,
+        1 if  y => 1,
         _ => 100,
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_guard_clause(x: u32, y: bool) -> u32 {
     match x {
         0 => 0,
@@ -112,19 +122,20 @@ pub fn change_guard_clause(x: u32, y: bool) -> u32 {
 
 
 // Add @-Binding ---------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_at_binding(x: u32) -> u32 {
     match x {
         0 => 0,
         1 => 1,
-        _ => x,
+            _ => x,
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_at_binding(x: u32) -> u32 {
     match x {
         0 => 0,
@@ -136,7 +147,7 @@ pub fn add_at_binding(x: u32) -> u32 {
 
 
 // Change Name of @-Binding ----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_name_of_at_binding(x: u32) -> u32 {
     match x {
         0 => 0,
@@ -145,10 +156,11 @@ pub fn change_name_of_at_binding(x: u32) -> u32 {
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_name_of_at_binding(x: u32) -> u32 {
     match x {
         0 => 0,
@@ -160,18 +172,19 @@ pub fn change_name_of_at_binding(x: u32) -> u32 {
 
 
 // Change Simple Binding To Pattern --------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_simple_name_to_pattern(x: u32) -> u32 {
     match (x, x & 1) {
         (0, 0) => 0,
-        a => 1,
+         a     => 1,
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_simple_name_to_pattern(x: u32) -> u32 {
     match (x, x & 1) {
         (0, 0) => 0,
@@ -182,7 +195,7 @@ pub fn change_simple_name_to_pattern(x: u32) -> u32 {
 
 
 // Change Name In Pattern ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_name_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
         (a, 0) => 0,
@@ -191,10 +204,11 @@ pub fn change_name_in_pattern(x: u32) -> u32 {
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_name_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
         (b, 0) => 0,
@@ -206,18 +220,19 @@ pub fn change_name_in_pattern(x: u32) -> u32 {
 
 
 // Change Mutability Of Binding In Pattern -------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
-        (a, 0) => 0,
+        (    a, 0) => 0,
         _ => 1,
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
         (mut a, 0) => 0,
@@ -228,18 +243,19 @@ pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 {
 
 
 // Add `ref` To Binding In Pattern -------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
-        (a, 0) => 0,
+        (    a, 0) => 0,
         _ => 1,
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 {
     match (x, x & 1) {
         (ref a, 0) => 0,
@@ -250,18 +266,19 @@ pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 {
 
 
 // Add `&` To Binding In Pattern -------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 {
     match (&x, x & 1) {
-        (a, 0) => 0,
+        ( a, 0) => 0,
         _ => 1,
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 {
     match (&x, x & 1) {
         (&a, 0) => 0,
@@ -272,7 +289,7 @@ pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 {
 
 
 // Change RHS Of Arm -----------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_rhs_of_arm(x: u32) -> u32 {
     match x {
         0 => 0,
@@ -281,10 +298,11 @@ pub fn change_rhs_of_arm(x: u32) -> u32 {
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_rhs_of_arm(x: u32) -> u32 {
     match x {
         0 => 0,
@@ -296,19 +314,20 @@ pub fn change_rhs_of_arm(x: u32) -> u32 {
 
 
 // Add Alternative To Arm ------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_alternative_to_arm(x: u32) -> u32 {
     match x {
-        0 => 0,
+        0     => 0,
         1 => 1,
         _ => 2,
     }
 }
 
-#[cfg(not(cfail1))]
-#[rustc_clean(cfg="cfail2",
-    except="hir_owner_nodes,optimized_mir,typeck")]
+#[cfg(not(any(cfail1,cfail4)))]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_alternative_to_arm(x: u32) -> u32 {
     match x {
         0 | 7 => 0,
diff --git a/src/test/incremental/hashes/statics.rs b/src/test/incremental/hashes/statics.rs
index 6f4089c60fe..2b2658b2f5f 100644
--- a/src/test/incremental/hashes/statics.rs
+++ b/src/test/incremental/hashes/statics.rs
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -17,86 +23,102 @@
 
 
 // Change static visibility
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 static STATIC_VISIBILITY: u8 = 0;
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub static STATIC_VISIBILITY: u8 = 0;
 
 
 // Change static mutability
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 static STATIC_MUTABILITY: u8 = 0;
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 static mut STATIC_MUTABILITY: u8 = 0;
 
 
 // Add linkage attribute
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 static STATIC_LINKAGE: u8 = 0;
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 #[linkage="weak_odr"]
 static STATIC_LINKAGE: u8 = 0;
 
 
 // Add no_mangle attribute
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 static STATIC_NO_MANGLE: u8 = 0;
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 #[no_mangle]
 static STATIC_NO_MANGLE: u8 = 0;
 
 
 // Add thread_local attribute
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 static STATIC_THREAD_LOCAL: u8 = 0;
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 #[thread_local]
 static STATIC_THREAD_LOCAL: u8 = 0;
 
 
 // Change type from i16 to u64
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 static STATIC_CHANGE_TYPE_1: i16 = 0;
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 static STATIC_CHANGE_TYPE_1: u64 = 0;
 
 
 // Change type from Option<i8> to Option<u16>
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 static STATIC_CHANGE_TYPE_2: Option<i8> = None;
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+#[rustc_clean(cfg="cfail6")]
 static STATIC_CHANGE_TYPE_2: Option<u16> = None;
 
 
 // Change value between simple literals
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 static STATIC_CHANGE_VALUE_1: i16 = {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     { 1 }
 
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     { 2 }
 };
 
@@ -104,31 +126,37 @@ static STATIC_CHANGE_VALUE_1: i16 = {
 // Change value between expressions
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 static STATIC_CHANGE_VALUE_2: i16 = {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     { 1 + 1 }
 
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     { 1 + 2 }
 };
 
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 static STATIC_CHANGE_VALUE_3: i16 = {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     { 2 + 3 }
 
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     { 2 * 3 }
 };
 
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 static STATIC_CHANGE_VALUE_4: i16 = {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     { 1 + 2 * 3 }
 
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     { 1 + 2 * 4 }
 };
 
@@ -138,17 +166,21 @@ struct ReferencedType1;
 struct ReferencedType2;
 
 mod static_change_type_indirectly {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedType1 as Type;
 
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedType2 as Type;
 
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+    #[rustc_clean(cfg="cfail6")]
     static STATIC_CHANGE_TYPE_INDIRECTLY_1: Type = Type;
 
     #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_nodes,type_of")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5", except="hir_owner,hir_owner_nodes,type_of")]
+    #[rustc_clean(cfg="cfail6")]
     static STATIC_CHANGE_TYPE_INDIRECTLY_2: Option<Type> = None;
 }
diff --git a/src/test/incremental/hashes/struct_constructors.rs b/src/test/incremental/hashes/struct_constructors.rs
index edec03d4f05..6a626204630 100644
--- a/src/test/incremental/hashes/struct_constructors.rs
+++ b/src/test/incremental/hashes/struct_constructors.rs
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -21,7 +27,7 @@ pub struct RegularStruct {
 }
 
 // Change field value (regular struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_field_value_regular_struct() -> RegularStruct {
     RegularStruct {
         x: 0,
@@ -30,9 +36,11 @@ pub fn change_field_value_regular_struct() -> RegularStruct {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_field_value_regular_struct() -> RegularStruct {
     RegularStruct {
         x: 0,
@@ -44,7 +52,7 @@ pub fn change_field_value_regular_struct() -> RegularStruct {
 
 
 // Change field order (regular struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_field_order_regular_struct() -> RegularStruct {
     RegularStruct {
         x: 3,
@@ -53,9 +61,11 @@ pub fn change_field_order_regular_struct() -> RegularStruct {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_field_order_regular_struct() -> RegularStruct {
     RegularStruct {
         y: 4,
@@ -67,7 +77,7 @@ pub fn change_field_order_regular_struct() -> RegularStruct {
 
 
 // Add field (regular struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_field_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
         x: 3,
@@ -77,13 +87,16 @@ pub fn add_field_regular_struct() -> RegularStruct {
 
     RegularStruct {
         x: 7,
+        // --
         .. struct1
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_field_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
         x: 3,
@@ -101,7 +114,7 @@ pub fn add_field_regular_struct() -> RegularStruct {
 
 
 // Change field label (regular struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_field_label_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
         x: 3,
@@ -116,9 +129,11 @@ pub fn change_field_label_regular_struct() -> RegularStruct {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_field_label_regular_struct() -> RegularStruct {
     let struct1 = RegularStruct {
         x: 3,
@@ -142,18 +157,20 @@ pub struct RegularStruct2 {
 }
 
 // Change constructor path (regular struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_constructor_path_regular_struct() {
-    let _ = RegularStruct {
+    let _ = RegularStruct  {
         x: 0,
         y: 1,
         z: 2,
     };
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_constructor_path_regular_struct() {
     let _ = RegularStruct2 {
         x: 0,
@@ -166,9 +183,9 @@ pub fn change_constructor_path_regular_struct() {
 
 // Change constructor path indirectly (regular struct)
 pub mod change_constructor_path_indirectly_regular_struct {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::RegularStruct as Struct;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::RegularStruct2 as Struct;
 
     #[rustc_clean(
@@ -176,6 +193,11 @@ pub mod change_constructor_path_indirectly_regular_struct {
         except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck"
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        cfg="cfail5",
+        except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck"
+    )]
+    #[rustc_clean(cfg="cfail6")]
     pub fn function() -> Struct {
         Struct {
             x: 0,
@@ -190,14 +212,16 @@ pub mod change_constructor_path_indirectly_regular_struct {
 pub struct TupleStruct(i32, i64, i16);
 
 // Change field value (tuple struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_field_value_tuple_struct() -> TupleStruct {
     TupleStruct(0, 1, 2)
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_field_value_tuple_struct() -> TupleStruct {
     TupleStruct(0, 1, 3)
 }
@@ -207,14 +231,16 @@ pub fn change_field_value_tuple_struct() -> TupleStruct {
 pub struct TupleStruct2(u16, u16, u16);
 
 // Change constructor path (tuple struct)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_constructor_path_tuple_struct() {
-    let _ = TupleStruct(0, 1, 2);
+    let _ = TupleStruct (0, 1, 2);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_constructor_path_tuple_struct() {
     let _ = TupleStruct2(0, 1, 2);
 }
@@ -223,12 +249,17 @@ pub fn change_constructor_path_tuple_struct() {
 
 // Change constructor path indirectly (tuple struct)
 pub mod change_constructor_path_indirectly_tuple_struct {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::TupleStruct as Struct;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::TupleStruct2 as Struct;
 
     #[rustc_clean(
+        cfg="cfail5",
+        except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck"
+    )]
+    #[rustc_clean(cfg="cfail6")]
+    #[rustc_clean(
         cfg="cfail2",
         except="fn_sig,hir_owner,hir_owner_nodes,optimized_mir,typeck"
     )]
diff --git a/src/test/incremental/hashes/struct_defs.rs b/src/test/incremental/hashes/struct_defs.rs
index 0ce5aeaaf50..b5d8a3ab341 100644
--- a/src/test/incremental/hashes/struct_defs.rs
+++ b/src/test/incremental/hashes/struct_defs.rs
@@ -11,42 +11,53 @@
 // the same between rev2 and rev3.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
-
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
 #![crate_type="rlib"]
 
 // Layout ----------------------------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub struct LayoutPacked;
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="type_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 #[repr(packed)]
 pub struct LayoutPacked;
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct LayoutC;
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="type_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 #[repr(C)]
 struct LayoutC;
 
 
 // Tuple Struct Change Field Type ----------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct TupleStructFieldType(i32);
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 // 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(
@@ -56,12 +67,14 @@ struct TupleStructFieldType(
 
 // Tuple Struct Add Field ------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct TupleStructAddField(i32);
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct TupleStructAddField(
     i32,
     u32
@@ -70,23 +83,27 @@ struct TupleStructAddField(
 
 // Tuple Struct Field Visibility -----------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct TupleStructFieldVisibility(char);
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct TupleStructFieldVisibility(pub char);
 
 
 // Record Struct Field Type ----------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct RecordStructFieldType { x: f32 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 // 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 {
@@ -96,23 +113,27 @@ struct RecordStructFieldType {
 
 // Record Struct Field Name ----------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct RecordStructFieldName { x: f32 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct RecordStructFieldName { y: f32 }
 
 
 // Record Struct Add Field -----------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct RecordStructAddField { x: f32 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct RecordStructAddField {
     x: f32,
     y: () }
@@ -120,12 +141,14 @@ struct RecordStructAddField {
 
 // Record Struct Field Visibility ----------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct RecordStructFieldVisibility { x: f32 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct RecordStructFieldVisibility {
     pub x: f32
 }
@@ -133,34 +156,40 @@ struct RecordStructFieldVisibility {
 
 // Add Lifetime Parameter ------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct AddLifetimeParameter<'a>(&'a f32, &'a f64);
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct AddLifetimeParameter<'a, 'b>(&'a f32, &'b f64);
 
 
 // Add Lifetime Parameter Bound ------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct AddLifetimeParameterBound<'a, 'b>(&'a f32, &'b f64);
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct AddLifetimeParameterBound<'a, 'b: 'a>(
     &'a f32,
     &'b f64
 );
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64);
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct AddLifetimeParameterBoundWhereClause<'a, 'b>(
     &'a f32,
     &'b f64)
@@ -169,12 +198,14 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>(
 
 // Add Type Parameter ----------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct AddTypeParameter<T1>(T1, T1);
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,type_of,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct AddTypeParameter<T1, T2>(
      // The field contains the parent's Generics, so it's dirty even though its
      // type hasn't changed.
@@ -185,23 +216,27 @@ struct AddTypeParameter<T1, T2>(
 
 // Add Type Parameter Bound ----------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct AddTypeParameterBound<T>(T);
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct AddTypeParameterBound<T: Send>(
     T
 );
 
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct AddTypeParameterBoundWhereClause<T>(T);
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 struct AddTypeParameterBoundWhereClause<T>(
     T
 ) where T: Sync;
@@ -214,17 +249,21 @@ struct AddTypeParameterBoundWhereClause<T>(
 // Note: there is no #[cfg(...)], so this is ALWAYS compiled
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub struct EmptyStruct;
 
 
 // Visibility ------------------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 struct Visibility;
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub struct Visibility;
 
 struct ReferencedType1;
@@ -232,13 +271,15 @@ struct ReferencedType2;
 
 // Tuple Struct Change Field Type Indirectly -----------------------------------
 mod tuple_struct_change_field_type_indirectly {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedType1 as FieldType;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedType2 as FieldType;
 
     #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     struct TupleStruct(
         FieldType
     );
@@ -247,13 +288,15 @@ mod tuple_struct_change_field_type_indirectly {
 
 // Record Struct Change Field Type Indirectly -----------------------------------
 mod record_struct_change_field_type_indirectly {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedType1 as FieldType;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedType2 as FieldType;
 
     #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     struct RecordStruct {
         _x: FieldType
     }
@@ -267,24 +310,28 @@ trait ReferencedTrait2 {}
 
 // Change Trait Bound Indirectly -----------------------------------------------
 mod change_trait_bound_indirectly {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedTrait1 as Trait;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedTrait2 as Trait;
 
     #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     struct Struct<T: Trait>(T);
 }
 
 // Change Trait Bound Indirectly In Where Clause -------------------------------
 mod change_trait_bound_indirectly_in_where_clause {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedTrait1 as Trait;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedTrait2 as Trait;
 
     #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     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 a604ca5ca82..9cbd110d68a 100644
--- a/src/test/incremental/hashes/trait_defs.rs
+++ b/src/test/incremental/hashes/trait_defs.rs
@@ -11,8 +11,14 @@
 // the same between rev2 and rev3.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -21,35 +27,41 @@
 
 
 // Change trait visibility
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitVisibility { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub trait TraitVisibility { }
 
 
 
 // Change trait unsafety
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitUnsafety { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 unsafe trait TraitUnsafety { }
 
 
 
 // Add method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddMethod {
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub trait TraitAddMethod {
     fn method();
 }
@@ -57,14 +69,16 @@ pub trait TraitAddMethod {
 
 
 // Change name of method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeMethodName {
     fn method();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeMethodName {
     fn methodChanged();
 }
@@ -72,157 +86,227 @@ trait TraitChangeMethodName {
 
 
 // Add return type to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddReturnType {
-    fn method();
+    //-----------------------------------------------------
+    //--------------------------
+    //-----------------------------------------------------
+    //--------------------------
+    fn method()       ;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddReturnType {
     #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method() -> u32;
 }
 
 
 
 // Change return type of method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeReturnType {
+    // --------------------------------------------------------------------
+    // -------------------------
+    // --------------------------------------------------------------------
+    // -------------------------
     fn method() -> u32;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeReturnType {
     #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method() -> u64;
 }
 
 
 
 // Add parameter to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddParameterToMethod {
-    fn method();
+    // ----------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------
+    // -------------------------
+    fn method(      );
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddParameterToMethod {
     #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method(a: u32);
 }
 
 
 
 // Change name of method parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeMethodParameterName {
+    //------------------------------------------------------
+    //----------------------------------------------
+    //--------------------------
+    //----------------------------------------------
+    //--------------------------
     fn method(a: u32);
+
+    //------------------------------------------------------------------
+    //--------------------------
+    //------------------------------------------------------------------
+    //--------------------------
     fn with_default(x: i32) {}
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeMethodParameterName {
     // FIXME(#38501) This should preferably always be clean.
     #[rustc_clean(except="hir_owner", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method(b: u32);
 
     #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn with_default(y: i32) {}
 }
 
 
 
 // Change type of method parameter (i32 => i64)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeMethodParameterType {
+    // ----------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------
+    // -------------------------
     fn method(a: i32);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeMethodParameterType {
     #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method(a: i64);
 }
 
 
 
 // Change type of method parameter (&i32 => &mut i32)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeMethodParameterTypeRef {
-    fn method(a: &i32);
+    // ----------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------
+    // -------------------------
+    fn method(a: &    i32);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeMethodParameterTypeRef {
     #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method(a: &mut i32);
 }
 
 
 
 // Change order of method parameters
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeMethodParametersOrder {
+    // ----------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------
+    // -------------------------
     fn method(a: i32, b: i64);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeMethodParametersOrder {
     #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method(b: i64, a: i32);
 }
 
 
 
 // Add default implementation to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddMethodAutoImplementation {
     fn method();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddMethodAutoImplementation {
     #[rustc_clean(except="hir_owner,associated_item", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,associated_item", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method() { }
 }
 
 
 
 // Change order of methods
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeOrderOfMethods {
     fn method0();
     fn method1();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeOrderOfMethods {
     fn method1();
     fn method0();
@@ -231,134 +315,198 @@ trait TraitChangeOrderOfMethods {
 
 
 // Change mode of self parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeModeSelfRefToMut {
-    fn method(&self);
+    // ----------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------
+    // -------------------------
+    fn method(&    self);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeModeSelfRefToMut {
     #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method(&mut self);
 }
 
 
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeModeSelfOwnToMut: Sized {
-    fn method(self) {}
+    // ----------------------------------------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------------------------------------
+    // -------------------------
+    fn method(    self) {}
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeModeSelfOwnToMut: Sized {
     #[rustc_clean(except="hir_owner,hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method(mut self) {}
 }
 
 
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeModeSelfOwnToRef {
-    fn method(self);
+    // ----------------------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------------------
+    // -------------------------
+    fn method( self);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeModeSelfOwnToRef {
     #[rustc_clean(except="hir_owner,fn_sig,generics_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig,generics_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method(&self);
 }
 
 
 
 // Add unsafe modifier to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddUnsafeModifier {
-    fn method();
+    // ----------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------
+    // -------------------------
+    fn method()       ;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddUnsafeModifier {
     #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     unsafe fn method();
 }
 
 
 
 // Add extern modifier to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddExternModifier {
-    fn method();
+    // ----------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------
+    // -------------------------
+    fn method()           ;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddExternModifier {
     #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     extern "C" fn method();
 }
 
 
 
 // Change extern "C" to extern "stdcall"
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeExternCToRustIntrinsic {
-    extern "C" fn method();
+    // ----------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------
+    // -------------------------
+    extern "C"       fn method();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeExternCToRustIntrinsic {
     #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     extern "stdcall" fn method();
 }
 
 
 
 // Add type parameter to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddTypeParameterToMethod {
-    fn method();
+    // -------------------------------------------------------------------------------
+    // -------------------------
+    // -------------------------------------------------------------------------------
+    // -------------------------
+    fn method   ();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddTypeParameterToMethod {
     #[rustc_clean(except="hir_owner,generics_of,predicates_of,type_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,generics_of,predicates_of,type_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method<T>();
 }
 
 
 
 // Add lifetime parameter to method
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddLifetimeParameterToMethod {
-    fn method();
+    // ----------------------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------------------
+    // -------------------------
+    fn method    ();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddLifetimeParameterToMethod {
     #[rustc_clean(except="hir_owner,fn_sig,generics_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,fn_sig,generics_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method<'a>();
 }
 
@@ -369,137 +517,220 @@ trait ReferencedTrait0 { }
 trait ReferencedTrait1 { }
 
 // Add trait bound to method type parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddTraitBoundToMethodTypeParameter {
-    fn method<T>();
+    // ---------------------------------------------------------------------------
+    // -------------------------
+    // ---------------------------------------------------------------------------
+    // -------------------------
+    fn method<T                  >();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddTraitBoundToMethodTypeParameter {
     #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method<T: ReferencedTrait0>();
 }
 
 
 
 // Add builtin bound to method type parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddBuiltinBoundToMethodTypeParameter {
-    fn method<T>();
+    // ---------------------------------------------------------------------------
+    // -------------------------
+    // ---------------------------------------------------------------------------
+    // -------------------------
+    fn method<T       >();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddBuiltinBoundToMethodTypeParameter {
     #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method<T: Sized>();
 }
 
 
 
 // Add lifetime bound to method lifetime parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddLifetimeBoundToMethodLifetimeParameter {
-    fn method<'a, 'b>(a: &'a u32, b: &'b u32);
-}
-
-#[cfg(not(cfail1))]
+    // -----------
+    // -----------------------------------------------------------------------------
+    // --------------
+    //
+    // -------------------------
+    // -----------
+    // -----------------------------------------------------------------------------
+    // --------------
+    //
+    // -------------------------
+    fn method<'a, 'b    >(a: &'a u32, b: &'b u32);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddLifetimeBoundToMethodLifetimeParameter {
     #[rustc_clean(
         except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of",
         cfg="cfail2",
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of",
+        cfg="cfail5",
+    )]
+    #[rustc_clean(cfg="cfail6")]
     fn method<'a, 'b: 'a>(a: &'a u32, b: &'b u32);
 }
 
 
 
 // Add second trait bound to method type parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondTraitBoundToMethodTypeParameter {
-    fn method<T: ReferencedTrait0>();
+    // ---------------------------------------------------------------------------
+    // -------------------------
+    // ---------------------------------------------------------------------------
+    // -------------------------
+    fn method<T: ReferencedTrait0                   >();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondTraitBoundToMethodTypeParameter {
     #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method<T: ReferencedTrait0 + ReferencedTrait1>();
 }
 
 
 
 // Add second builtin bound to method type parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
-    fn method<T: Sized>();
+    // ---------------------------------------------------------------------------
+    // -------------------------
+    // ---------------------------------------------------------------------------
+    // -------------------------
+    fn method<T: Sized       >();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondBuiltinBoundToMethodTypeParameter {
     #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method<T: Sized + Sync>();
 }
 
 
 
 // Add second lifetime bound to method lifetime parameter
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
-    fn method<'a, 'b, 'c: 'a>(a: &'a u32, b: &'b u32, c: &'c u32);
-}
-
-#[cfg(not(cfail1))]
+    // -----------
+    // -----------------------------------------------------------------------------
+    // --------------
+    //
+    // -------------------------
+    // -----------
+    // -----------------------------------------------------------------------------
+    // --------------
+    //
+    // -------------------------
+    fn method<'a, 'b, 'c: 'a     >(a: &'a u32, b: &'b u32, c: &'c u32);
+}
+
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter {
     #[rustc_clean(
         except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of",
         cfg="cfail2",
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        except="hir_owner,hir_owner_nodes,generics_of,predicates_of,fn_sig,type_of",
+        cfg="cfail5",
+    )]
+    #[rustc_clean(cfg="cfail6")]
     fn method<'a, 'b, 'c: 'a + 'b>(a: &'a u32, b: &'b u32, c: &'c u32);
 }
 
 
 
 // Add associated type
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddAssociatedType {
-
-    #[rustc_clean(except="hir_owner", cfg="cfail2")]
-    #[rustc_clean(cfg="cfail3")]
+    //--------------------------
+    //--------------------------
+    // -------------
+
+    //--------------------------
+    //--------------------------
+    //--------------------------
+    //--------------------------
     fn method();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddAssociatedType {
+    #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail6")]
     type Associated;
 
+    #[rustc_clean(cfg="cfail2")]
+    #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method();
 }
 
 
 
 // Add trait bound to associated type
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddTraitBoundToAssociatedType {
-    type Associated;
+    // ---------------------------------------------
+    // -------------------------
+    // ---------------------------------------------
+    // -------------------------
+    type Associated                  ;
 
     fn method();
 }
@@ -507,12 +738,16 @@ trait TraitAddTraitBoundToAssociatedType {
 
 // Apparently the type bound contributes to the predicates of the trait, but
 // does not change the associated item itself.
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddTraitBoundToAssociatedType {
     #[rustc_clean(except="hir_owner", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     type Associated: ReferencedTrait0;
 
     fn method();
@@ -521,19 +756,27 @@ trait TraitAddTraitBoundToAssociatedType {
 
 
 // Add lifetime bound to associated type
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddLifetimeBoundToAssociatedType<'a> {
-    type Associated;
+    // ---------------------------------------------
+    // -------------------------
+    // ---------------------------------------------
+    // -------------------------
+    type Associated    ;
 
     fn method();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddLifetimeBoundToAssociatedType<'a> {
     #[rustc_clean(except="hir_owner", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     type Associated: 'a;
 
     fn method();
@@ -542,19 +785,23 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> {
 
 
 // Add default to associated type
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddDefaultToAssociatedType {
     type Associated;
 
     fn method();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddDefaultToAssociatedType {
     #[rustc_clean(except="hir_owner,associated_item", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,associated_item", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     type Associated = ReferenceType0;
 
     fn method();
@@ -563,14 +810,16 @@ trait TraitAddDefaultToAssociatedType {
 
 
 // Add associated constant
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddAssociatedConstant {
     fn method();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddAssociatedConstant {
     const Value: u32;
 
@@ -580,269 +829,331 @@ trait TraitAddAssociatedConstant {
 
 
 // Add initializer to associated constant
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddInitializerToAssociatedConstant {
     const Value: u32;
 
     fn method();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddInitializerToAssociatedConstant {
     #[rustc_clean(except="hir_owner,associated_item", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,associated_item", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     const Value: u32 = 1;
 
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method();
 }
 
 
 
 // Change type of associated constant
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitChangeTypeOfAssociatedConstant {
+    // -----------------------------------------------------
+    // -------------------------
+    // -----------------------------------------------------
+    // -------------------------
     const Value: u32;
 
+    // -------------------------
+    // -------------------------
+    // -------------------------
+    // -------------------------
     fn method();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitChangeTypeOfAssociatedConstant {
     #[rustc_clean(except="hir_owner,type_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,type_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     const Value: f64;
 
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method();
 }
 
 
 
 // Add super trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSuperTrait { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSuperTrait : ReferencedTrait0 { }
 
 
 
 // Add builtin bound (Send or Copy)
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddBuiltiBound { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddBuiltiBound : Send { }
 
 
 
 // Add 'static lifetime bound to trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddStaticLifetimeBound { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddStaticLifetimeBound : 'static { }
 
 
 
 // Add super trait as second bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddTraitAsSecondBound : ReferencedTrait0 { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddTraitAsSecondBound : ReferencedTrait0 + ReferencedTrait1 { }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddTraitAsSecondBoundFromBuiltin : Send { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { }
 
 
 
 // Add builtin bound as second bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 + Send { }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin : Send { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { }
 
 
 
 // Add 'static bounds as second bound
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 + 'static { }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { }
 
 
 
 // Add type parameter to trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddTypeParameterToTrait { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,generics_of,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddTypeParameterToTrait<T> { }
 
 
 
 // Add lifetime parameter to trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddLifetimeParameterToTrait { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,generics_of,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddLifetimeParameterToTrait<'a> { }
 
 
 
 // Add trait bound to type parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddTraitBoundToTypeParameterOfTrait<T> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0> { }
 
 
 
 // Add lifetime bound to type parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { }
 
 
 
 // Add lifetime bound to lifetime parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a, 'b> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { }
 
 
 
 // Add builtin bound to type parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddBuiltinBoundToTypeParameterOfTrait<T> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddBuiltinBoundToTypeParameterOfTrait<T: Send> { }
 
 
 
 // Add second type parameter to trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondTypeParameterToTrait<T> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondTypeParameterToTrait<T, S> { }
 
 
 
 // Add second lifetime parameter to trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondLifetimeParameterToTrait<'a> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { }
 
 
 
 // Add second trait bound to type parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondTraitBoundToTypeParameterOfTrait<T: ReferencedTrait0 + ReferencedTrait1> { }
 
 
 
 // Add second lifetime bound to type parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { }
 
 
 
 // Add second lifetime bound to lifetime parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b, 'c> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> { }
 
 
 
 // Add second builtin bound to type parameter of trait
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait<T: Send> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait<T: Send + Sync> { }
 
 
@@ -853,105 +1164,125 @@ struct ReferenceType1 {}
 
 
 // Add trait bound to type parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddTraitBoundToTypeParameterOfTraitWhere<T> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddTraitBoundToTypeParameterOfTraitWhere<T> where T: ReferencedTrait0 { }
 
 
 
 // Add lifetime bound to type parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { }
 
 
 
 // Add lifetime bound to lifetime parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b { }
 
 
 
 // Add builtin bound to type parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere<T> { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { }
 
 
 
 // Add second trait bound to type parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere<T> where T: ReferencedTrait0 { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere<T>
     where T: ReferencedTrait0 + ReferencedTrait1 { }
 
 
 
 // Add second lifetime bound to type parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,generics_of,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a + 'b { }
 
 
 
 // Add second lifetime bound to lifetime parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b + 'c { }
 
 
 
 // Add second builtin bound to type parameter of trait in where clause
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send { }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere<T> where T: Send + Sync { }
 
 
 // Change return type of method indirectly by modifying a use statement
 mod change_return_type_of_method_indirectly_use {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferenceType0 as ReturnType;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferenceType1 as ReturnType;
 
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     trait TraitChangeReturnType {
         #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail2")]
         #[rustc_clean(cfg="cfail3")]
+        #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig", cfg="cfail5")]
+        #[rustc_clean(cfg="cfail6")]
         fn method() -> ReturnType;
     }
 }
@@ -960,9 +1291,9 @@ mod change_return_type_of_method_indirectly_use {
 
 // Change type of method parameter indirectly by modifying a use statement
 mod change_method_parameter_type_indirectly_by_use {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferenceType0 as ArgType;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferenceType1 as ArgType;
 
     #[rustc_clean(cfg="cfail2")]
@@ -978,9 +1309,9 @@ mod change_method_parameter_type_indirectly_by_use {
 
 // Change trait bound of method type parameter indirectly by modifying a use statement
 mod change_method_parameter_type_bound_indirectly_by_use {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedTrait0 as Bound;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedTrait1 as Bound;
 
     #[rustc_clean(cfg="cfail2")]
@@ -997,16 +1328,20 @@ mod change_method_parameter_type_bound_indirectly_by_use {
 // Change trait bound of method type parameter in where clause indirectly
 // by modifying a use statement
 mod change_method_parameter_type_bound_indirectly_by_use_where {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedTrait0 as Bound;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedTrait1 as Bound;
 
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     trait TraitChangeBoundOfMethodTypeParameterWhere {
         #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
         #[rustc_clean(cfg="cfail3")]
+        #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+        #[rustc_clean(cfg="cfail6")]
         fn method<T>(a: T) where T: Bound;
     }
 }
@@ -1015,9 +1350,9 @@ mod change_method_parameter_type_bound_indirectly_by_use_where {
 
 // Change trait bound of trait type parameter indirectly by modifying a use statement
 mod change_method_type_parameter_bound_indirectly {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedTrait0 as Bound;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedTrait1 as Bound;
 
     #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
@@ -1032,13 +1367,15 @@ mod change_method_type_parameter_bound_indirectly {
 // Change trait bound of trait type parameter in where clause indirectly
 // by modifying a use statement
 mod change_method_type_parameter_bound_indirectly_where {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1,cfail4))]
     use super::ReferencedTrait0 as Bound;
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1,cfail4)))]
     use super::ReferencedTrait1 as Bound;
 
     #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,predicates_of", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     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 2d547f1748c..d623810115e 100644
--- a/src/test/incremental/hashes/trait_impls.rs
+++ b/src/test/incremental/hashes/trait_impls.rs
@@ -6,9 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
-
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -19,29 +24,35 @@ struct Foo;
 
 // Change Method Name -----------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub trait ChangeMethodNameTrait {
     fn method_name();
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl ChangeMethodNameTrait for Foo {
     fn method_name() { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub trait ChangeMethodNameTrait {
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail6")]
     fn method_name2();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl ChangeMethodNameTrait for Foo {
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail6")]
     fn method_name2() { }
 }
 
@@ -53,17 +64,27 @@ pub trait ChangeMethodBodyTrait {
     fn method_name();
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl ChangeMethodBodyTrait for Foo {
-    fn method_name() { }
+    // ----------------------------------------------------------
+    // -------------------------
+    // ----------------------------------------------------------
+    // -------------------------
+    fn method_name() {
+        //
+    }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl ChangeMethodBodyTrait for Foo {
     #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner_nodes,typeck", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method_name() {
         ()
     }
@@ -77,18 +98,28 @@ pub trait ChangeMethodBodyTraitInlined {
     fn method_name();
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl ChangeMethodBodyTraitInlined for Foo {
+    // ------------------------------------------------------------------------
+    // -------------------------
+    // ------------------------------------------------------------------------
+    // -------------------------
     #[inline]
-    fn method_name() { }
+    fn method_name() {
+        // -----
+    }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl ChangeMethodBodyTraitInlined for Foo {
     #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner_nodes,typeck,optimized_mir", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     #[inline]
     fn method_name() {
         panic!()
@@ -97,30 +128,37 @@ impl ChangeMethodBodyTraitInlined for Foo {
 
 // Change Method Selfness ------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub trait ChangeMethodSelfnessTrait {
     fn method_name();
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl ChangeMethodSelfnessTrait for Foo {
     fn method_name() { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 pub trait ChangeMethodSelfnessTrait {
     fn method_name(&self);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl ChangeMethodSelfnessTrait for Foo {
     #[rustc_clean(
         except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir",
         cfg="cfail2",
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir",
+        cfg="cfail5",
+    )]
+    #[rustc_clean(cfg="cfail6")]
     fn method_name(&self) {
         ()
     }
@@ -128,130 +166,151 @@ impl ChangeMethodSelfnessTrait for Foo {
 
 // Change Method Selfness -----------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub trait RemoveMethodSelfnessTrait {
     fn method_name(&self);
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl RemoveMethodSelfnessTrait for Foo {
     fn method_name(&self) { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 pub trait RemoveMethodSelfnessTrait {
     fn method_name();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl RemoveMethodSelfnessTrait for Foo {
     #[rustc_clean(
         except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir",
         cfg="cfail2",
     )]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(
+        except="hir_owner,hir_owner_nodes,associated_item,generics_of,fn_sig,typeck,optimized_mir",
+        cfg="cfail5",
+    )]
+    #[rustc_clean(cfg="cfail6")]
     fn method_name() {}
 }
 
 // Change Method Selfmutness -----------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub trait ChangeMethodSelfmutnessTrait {
     fn method_name(&self);
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl ChangeMethodSelfmutnessTrait for Foo {
-    fn method_name(&self) { }
+    // -----------------------------------------------------------------------------------------
+    // -------------------------
+    // -----------------------------------------------------------------------------------------
+    // -------------------------
+    fn method_name(&    self) {}
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 pub trait ChangeMethodSelfmutnessTrait {
     fn method_name(&mut self);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl ChangeMethodSelfmutnessTrait for Foo {
     #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method_name(&mut self) {}
 }
 
 // Change item kind -----------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub trait ChangeItemKindTrait {
     fn name();
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl ChangeItemKindTrait for Foo {
     fn name() { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 pub trait ChangeItemKindTrait {
     type name;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl ChangeItemKindTrait for Foo {
     type name = ();
 }
 
 // Remove item -----------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub trait RemoveItemTrait {
     type TypeName;
     fn method_name();
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl RemoveItemTrait for Foo {
     type TypeName = ();
     fn method_name() { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 pub trait RemoveItemTrait {
     type TypeName;
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl RemoveItemTrait for Foo {
     type TypeName = ();
 }
 
 // Add item -----------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub trait AddItemTrait {
     type TypeName;
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl AddItemTrait for Foo {
     type TypeName = ();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 pub trait AddItemTrait {
     type TypeName;
     fn method_name();
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,associated_item_def_ids", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl AddItemTrait for Foo {
     type TypeName = ();
     fn method_name() { }
@@ -259,28 +318,34 @@ impl AddItemTrait for Foo {
 
 // Change has-value -----------------------------------------------------------
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub trait ChangeHasValueTrait {
     fn method_name();
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl ChangeHasValueTrait for Foo {
     fn method_name() { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub trait ChangeHasValueTrait {
     #[rustc_clean(except="hir_owner,associated_item", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,associated_item", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method_name() { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl ChangeHasValueTrait for Foo {
     fn method_name() { }
 }
@@ -291,69 +356,91 @@ pub trait AddDefaultTrait {
     fn method_name();
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl AddDefaultTrait for Foo {
-    fn method_name() { }
+    // -------------------------------------------------------------------------------------------
+    // -------------------------
+            fn method_name() { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl AddDefaultTrait for Foo {
     #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,associated_item,optimized_mir", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     default fn method_name() { }
 }
 
 // Add arguments
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub trait AddArgumentTrait {
     fn method_name(&self);
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl AddArgumentTrait for Foo {
-    fn method_name(&self) { }
+    // -----------------------------------------------------------------------------------------
+    // -------------------------
+    // -----------------------------------------------------------------------------------------
+    // -------------------------
+    fn method_name(&self         ) { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 pub trait AddArgumentTrait {
     fn method_name(&self, x: u32);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl AddArgumentTrait for Foo {
     #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method_name(&self, _x: u32) { }
 }
 
 // Change argument type
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub trait ChangeArgumentTypeTrait {
     fn method_name(&self, x: u32);
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl ChangeArgumentTypeTrait for Foo {
-    fn method_name(&self, _x: u32) { }
+    // -----------------------------------------------------------------------------------------
+    // -------------------------
+    // -----------------------------------------------------------------------------------------
+    // -------------------------
+    fn method_name(&self, _x: u32 ) { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 pub trait ChangeArgumentTypeTrait {
     fn method_name(&self, x: char);
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl ChangeArgumentTypeTrait for Foo {
     #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="hir_owner,hir_owner_nodes,fn_sig,typeck,optimized_mir", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn method_name(&self, _x: char) { }
 }
 
@@ -366,21 +453,28 @@ trait AddTypeParameterToImpl<T> {
     fn id(t: T) -> T;
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl AddTypeParameterToImpl<u32> for Bar<u32> {
     fn id(t: u32) -> u32 { t }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,generics_of,impl_trait_ref", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
-impl<T> AddTypeParameterToImpl<T> for Bar<T> {
+#[rustc_clean(except="hir_owner,generics_of,impl_trait_ref", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
+impl<TTT> AddTypeParameterToImpl<TTT> for Bar<TTT> {
     #[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 }
+    #[rustc_clean(
+        except="hir_owner,hir_owner_nodes,generics_of,fn_sig,type_of,typeck,optimized_mir",
+        cfg="cfail5",
+    )]
+    #[rustc_clean(cfg="cfail6")]
+    fn id(t: TTT) -> TTT { t }
 }
 
 
@@ -390,17 +484,21 @@ trait ChangeSelfTypeOfImpl {
     fn id(self) -> Self;
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl ChangeSelfTypeOfImpl for u32 {
     fn id(self) -> Self { self }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,impl_trait_ref", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,impl_trait_ref", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl ChangeSelfTypeOfImpl for u64 {
     #[rustc_clean(except="fn_sig,typeck,optimized_mir", cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(except="fn_sig,typeck,optimized_mir", cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn id(self) -> Self { self }
 }
 
@@ -411,17 +509,21 @@ trait AddLifetimeBoundToImplParameter {
     fn id(self) -> Self;
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl<T> AddLifetimeBoundToImplParameter for T {
     fn id(self) -> Self { self }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl<T: 'static> AddLifetimeBoundToImplParameter for T {
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn id(self) -> Self { self }
 }
 
@@ -432,17 +534,21 @@ trait AddTraitBoundToImplParameter {
     fn id(self) -> Self;
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl<T> AddTraitBoundToImplParameter for T {
     fn id(self) -> Self { self }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner,hir_owner_nodes", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl<T: Clone> AddTraitBoundToImplParameter for T {
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     fn id(self) -> Self { self }
 }
 
@@ -453,17 +559,26 @@ trait AddNoMangleToMethod {
     fn add_no_mangle_to_method(&self) { }
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl AddNoMangleToMethod for Foo {
+    // -------------------------
+    // -------------------------
+    // -------------------------
+    // -------------------------
+    // ---------
     fn add_no_mangle_to_method(&self) { }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl AddNoMangleToMethod for Foo {
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     #[no_mangle]
     fn add_no_mangle_to_method(&self) { }
 }
@@ -474,17 +589,26 @@ trait MakeMethodInline {
     fn make_method_inline(&self) -> u8 { 0 }
 }
 
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 impl MakeMethodInline for Foo {
+    // -------------------------
+    // -------------------------
+    // -------------------------
+    // -------------------------
+    // ------
     fn make_method_inline(&self) -> u8 { 0 }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 impl MakeMethodInline for Foo {
     #[rustc_clean(cfg="cfail2")]
     #[rustc_clean(cfg="cfail3")]
+    #[rustc_clean(cfg="cfail5")]
+    #[rustc_clean(cfg="cfail6")]
     #[inline]
     fn make_method_inline(&self) -> u8 { 0 }
 }
diff --git a/src/test/incremental/hashes/type_defs.rs b/src/test/incremental/hashes/type_defs.rs
index d874be060c2..70c199bc3be 100644
--- a/src/test/incremental/hashes/type_defs.rs
+++ b/src/test/incremental/hashes/type_defs.rs
@@ -12,7 +12,7 @@
 
 // build-pass (FIXME(62277): could be check-pass?)
 // revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// compile-flags: -Z query-dep-graph
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
diff --git a/src/test/incremental/hashes/unary_and_binary_exprs.rs b/src/test/incremental/hashes/unary_and_binary_exprs.rs
index 687580ec8af..8d8345e10f5 100644
--- a/src/test/incremental/hashes/unary_and_binary_exprs.rs
+++ b/src/test/incremental/hashes/unary_and_binary_exprs.rs
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -15,44 +21,50 @@
 
 
 // Change constant operand of negation -----------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn const_negation() -> i32 {
     -10
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn const_negation() -> i32 {
-    -1
+     -1
 }
 
 
 
 // Change constant operand of bitwise not --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn const_bitwise_not() -> i32 {
     !100
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn const_bitwise_not() -> i32 {
-    !99
+     !99
 }
 
 
 
 // Change variable operand of negation -----------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn var_negation(x: i32, y: i32) -> i32 {
     -x
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn var_negation(x: i32, y: i32) -> i32 {
     -y
 }
@@ -60,14 +72,16 @@ pub fn var_negation(x: i32, y: i32) -> i32 {
 
 
 // Change variable operand of bitwise not --------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
     !x
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
     !y
 }
@@ -75,14 +89,16 @@ pub fn var_bitwise_not(x: i32, y: i32) -> i32 {
 
 
 // Change variable operand of deref --------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn var_deref(x: &i32, y: &i32) -> i32 {
     *x
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn var_deref(x: &i32, y: &i32) -> i32 {
     *y
 }
@@ -90,14 +106,16 @@ pub fn var_deref(x: &i32, y: &i32) -> i32 {
 
 
 // Change first constant operand of addition -----------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn first_const_add() -> i32 {
     1 + 3
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn first_const_add() -> i32 {
     2 + 3
 }
@@ -105,14 +123,16 @@ pub fn first_const_add() -> i32 {
 
 
 // Change second constant operand of addition -----------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn second_const_add() -> i32 {
     1 + 2
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn second_const_add() -> i32 {
     1 + 3
 }
@@ -120,14 +140,16 @@ pub fn second_const_add() -> i32 {
 
 
 // Change first variable operand of addition -----------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn first_var_add(a: i32, b: i32) -> i32 {
     a + 2
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn first_var_add(a: i32, b: i32) -> i32 {
     b + 2
 }
@@ -135,14 +157,16 @@ pub fn first_var_add(a: i32, b: i32) -> i32 {
 
 
 // Change second variable operand of addition ----------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn second_var_add(a: i32, b: i32) -> i32 {
     1 + a
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn second_var_add(a: i32, b: i32) -> i32 {
     1 + b
 }
@@ -150,14 +174,16 @@ pub fn second_var_add(a: i32, b: i32) -> i32 {
 
 
 // Change operator from + to - -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn plus_to_minus(a: i32) -> i32 {
     1 + a
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn plus_to_minus(a: i32) -> i32 {
     1 - a
 }
@@ -165,14 +191,16 @@ pub fn plus_to_minus(a: i32) -> i32 {
 
 
 // Change operator from + to * -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn plus_to_mult(a: i32) -> i32 {
     1 + a
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn plus_to_mult(a: i32) -> i32 {
     1 * a
 }
@@ -180,14 +208,16 @@ pub fn plus_to_mult(a: i32) -> i32 {
 
 
 // Change operator from + to / -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn plus_to_div(a: i32) -> i32 {
     1 + a
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn plus_to_div(a: i32) -> i32 {
     1 / a
 }
@@ -195,14 +225,16 @@ pub fn plus_to_div(a: i32) -> i32 {
 
 
 // Change operator from + to % -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn plus_to_mod(a: i32) -> i32 {
     1 + a
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn plus_to_mod(a: i32) -> i32 {
     1 % a
 }
@@ -210,14 +242,16 @@ pub fn plus_to_mod(a: i32) -> i32 {
 
 
 // Change operator from && to || -----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn and_to_or(a: bool, b: bool) -> bool {
     a && b
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn and_to_or(a: bool, b: bool) -> bool {
     a || b
 }
@@ -225,14 +259,16 @@ pub fn and_to_or(a: bool, b: bool) -> bool {
 
 
 // Change operator from & to | -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
     1 & a
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
     1 | a
 }
@@ -240,14 +276,16 @@ pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 {
 
 
 // Change operator from & to ^ -------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
     1 & a
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
     1 ^ a
 }
@@ -255,14 +293,16 @@ pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 {
 
 
 // Change operator from & to << ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn bitwise_and_to_lshift(a: i32) -> i32 {
-    a & 1
+    a  & 1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn bitwise_and_to_lshift(a: i32) -> i32 {
     a << 1
 }
@@ -270,14 +310,16 @@ pub fn bitwise_and_to_lshift(a: i32) -> i32 {
 
 
 // Change operator from & to >> ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn bitwise_and_to_rshift(a: i32) -> i32 {
-    a & 1
+    a  & 1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn bitwise_and_to_rshift(a: i32) -> i32 {
     a >> 1
 }
@@ -285,14 +327,16 @@ pub fn bitwise_and_to_rshift(a: i32) -> i32 {
 
 
 // Change operator from == to != -----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn eq_to_uneq(a: i32) -> bool {
     a == 1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn eq_to_uneq(a: i32) -> bool {
     a != 1
 }
@@ -300,44 +344,50 @@ pub fn eq_to_uneq(a: i32) -> bool {
 
 
 // Change operator from == to < ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn eq_to_lt(a: i32) -> bool {
     a == 1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn eq_to_lt(a: i32) -> bool {
-    a < 1
+    a  < 1
 }
 
 
 
 // Change operator from == to > ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn eq_to_gt(a: i32) -> bool {
     a == 1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn eq_to_gt(a: i32) -> bool {
-    a > 1
+    a  > 1
 }
 
 
 
 // Change operator from == to <= -----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn eq_to_le(a: i32) -> bool {
     a == 1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn eq_to_le(a: i32) -> bool {
     a <= 1
 }
@@ -345,14 +395,16 @@ pub fn eq_to_le(a: i32) -> bool {
 
 
 // Change operator from == to >= -----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn eq_to_ge(a: i32) -> bool {
     a == 1
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn eq_to_ge(a: i32) -> bool {
     a >= 1
 }
@@ -360,16 +412,18 @@ pub fn eq_to_ge(a: i32) -> bool {
 
 
 // Change type in cast expression ----------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn type_cast(a: u8) -> u64 {
     let b = a as i32;
     let c = b as u64;
     c
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir,typeck", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir,typeck", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn type_cast(a: u8) -> u64 {
     let b = a as u32;
     let c = b as u64;
@@ -379,14 +433,16 @@ pub fn type_cast(a: u8) -> u64 {
 
 
 // Change value in cast expression ---------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn value_cast(a: u32) -> i32 {
     1 as i32
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn value_cast(a: u32) -> i32 {
     2 as i32
 }
@@ -394,7 +450,7 @@ pub fn value_cast(a: u32) -> i32 {
 
 
 // Change place in assignment --------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn place() -> i32 {
     let mut x = 10;
     let mut y = 11;
@@ -402,9 +458,11 @@ pub fn place() -> i32 {
     x
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn place() -> i32 {
     let mut x = 10;
     let mut y = 11;
@@ -415,16 +473,18 @@ pub fn place() -> i32 {
 
 
 // Change r-value in assignment ------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn rvalue() -> i32 {
     let mut x = 10;
     x = 9;
     x
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn rvalue() -> i32 {
     let mut x = 10;
     x = 8;
@@ -434,14 +494,16 @@ pub fn rvalue() -> i32 {
 
 
 // Change index into slice -----------------------------------------------------
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 {
     s[i]
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail2")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(except="hir_owner_nodes,optimized_mir", cfg="cfail5")]
+#[rustc_clean(cfg="cfail6")]
 pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 {
     s[j]
 }
diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs
index d385974893c..64a6517836c 100644
--- a/src/test/incremental/hashes/while_let_loops.rs
+++ b/src/test/incremental/hashes/while_let_loops.rs
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -15,7 +21,7 @@
 
 
 // Change loop body
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_loop_body() {
     let mut _x = 0;
     while let Some(0u32) = None {
@@ -24,9 +30,11 @@ pub fn change_loop_body() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_loop_body() {
     let mut _x = 0;
     while let Some(0u32) = None {
@@ -38,7 +46,7 @@ pub fn change_loop_body() {
 
 
 // Change loop body
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_loop_condition() {
     let mut _x = 0;
     while let Some(0u32) = None {
@@ -47,9 +55,11 @@ pub fn change_loop_condition() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_loop_condition() {
     let mut _x = 0;
     while let Some(1u32) = None {
@@ -61,17 +71,20 @@ pub fn change_loop_condition() {
 
 
 // Add break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_break() {
     let mut _x = 0;
     while let Some(0u32) = None {
         _x = 1;
+        // ---
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_break() {
     let mut _x = 0;
     while let Some(0u32) = None {
@@ -83,18 +96,20 @@ pub fn add_break() {
 
 
 // Add loop label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label() {
     let mut _x = 0;
-    while let Some(0u32) = None {
+            while let Some(0u32) = None {
         _x = 1;
         break;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label() {
     let mut _x = 0;
     'label: while let Some(0u32) = None {
@@ -106,18 +121,20 @@ pub fn add_loop_label() {
 
 
 // Add loop label to break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: while let Some(0u32) = None {
         _x = 1;
-        break;
+        break       ;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: while let Some(0u32) = None {
@@ -129,7 +146,7 @@ pub fn add_loop_label_to_break() {
 
 
 // Change break label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_break_label() {
     let mut _x = 0;
     'outer: while let Some(0u32) = None {
@@ -140,9 +157,11 @@ pub fn change_break_label() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_break_label() {
     let mut _x = 0;
     'outer: while let Some(0u32) = None {
@@ -154,18 +173,20 @@ pub fn change_break_label() {
 }
 
 // Add loop label to continue
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: while let Some(0u32) = None {
         _x = 1;
-        continue;
+        continue       ;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: while let Some(0u32) = None {
@@ -177,7 +198,7 @@ pub fn add_loop_label_to_continue() {
 
 
 // Change continue label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_continue_label() {
     let mut _x = 0;
     'outer: while let Some(0u32) = None {
@@ -188,9 +209,11 @@ pub fn change_continue_label() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_continue_label() {
     let mut _x = 0;
     'outer: while let Some(0u32) = None {
@@ -204,7 +227,7 @@ pub fn change_continue_label() {
 
 
 // Change continue to break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_continue_to_break() {
     let mut _x = 0;
     while let Some(0u32) = None {
@@ -213,13 +236,15 @@ pub fn change_continue_to_break() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
     while let Some(0u32) = None {
         _x = 1;
-        break;
+        break   ;
     }
 }
diff --git a/src/test/incremental/hashes/while_loops.rs b/src/test/incremental/hashes/while_loops.rs
index 299622e45c6..b8796d3446b 100644
--- a/src/test/incremental/hashes/while_loops.rs
+++ b/src/test/incremental/hashes/while_loops.rs
@@ -6,8 +6,14 @@
 // rev3 and make sure that the hash has not changed.
 
 // build-pass (FIXME(62277): could be check-pass?)
-// revisions: cfail1 cfail2 cfail3
-// compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// compile-flags: -Z query-dep-graph
+// [cfail1]compile-flags: -Zincremental-ignore-spans
+// [cfail2]compile-flags: -Zincremental-ignore-spans
+// [cfail3]compile-flags: -Zincremental-ignore-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 
 #![allow(warnings)]
 #![feature(rustc_attrs)]
@@ -15,7 +21,7 @@
 
 
 // Change loop body
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_loop_body() {
     let mut _x = 0;
     while true {
@@ -24,9 +30,11 @@ pub fn change_loop_body() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_loop_body() {
     let mut _x = 0;
     while true {
@@ -38,18 +46,20 @@ pub fn change_loop_body() {
 
 
 // Change loop body
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_loop_condition() {
     let mut _x = 0;
-    while true {
+    while true  {
         _x = 1;
         break;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_loop_condition() {
     let mut _x = 0;
     while false {
@@ -61,17 +71,20 @@ pub fn change_loop_condition() {
 
 
 // Add break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_break() {
     let mut _x = 0;
     while true {
         _x = 1;
+        // ---
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_break() {
     let mut _x = 0;
     while true {
@@ -83,18 +96,20 @@ pub fn add_break() {
 
 
 // Add loop label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label() {
     let mut _x = 0;
-    while true {
+            while true {
         _x = 1;
         break;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label() {
     let mut _x = 0;
     'label: while true {
@@ -106,18 +121,20 @@ pub fn add_loop_label() {
 
 
 // Add loop label to break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: while true {
         _x = 1;
-        break;
+        break       ;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label_to_break() {
     let mut _x = 0;
     'label: while true {
@@ -129,7 +146,7 @@ pub fn add_loop_label_to_break() {
 
 
 // Change break label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_break_label() {
     let mut _x = 0;
     'outer: while true {
@@ -140,9 +157,11 @@ pub fn change_break_label() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_break_label() {
     let mut _x = 0;
     'outer: while true {
@@ -156,18 +175,20 @@ pub fn change_break_label() {
 
 
 // Add loop label to continue
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: while true {
         _x = 1;
-        continue;
+        continue       ;
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
+#[rustc_clean(cfg="cfail6")]
 pub fn add_loop_label_to_continue() {
     let mut _x = 0;
     'label: while true {
@@ -179,7 +200,7 @@ pub fn add_loop_label_to_continue() {
 
 
 // Change continue label
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_continue_label() {
     let mut _x = 0;
     'outer: while true {
@@ -190,9 +211,11 @@ pub fn change_continue_label() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_continue_label() {
     let mut _x = 0;
     'outer: while true {
@@ -206,7 +229,7 @@ pub fn change_continue_label() {
 
 
 // Change continue to break
-#[cfg(cfail1)]
+#[cfg(any(cfail1,cfail4))]
 pub fn change_continue_to_break() {
     let mut _x = 0;
     while true {
@@ -215,13 +238,15 @@ pub fn change_continue_to_break() {
     }
 }
 
-#[cfg(not(cfail1))]
+#[cfg(not(any(cfail1,cfail4)))]
 #[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir")]
 #[rustc_clean(cfg="cfail3")]
+#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
+#[rustc_clean(cfg="cfail6")]
 pub fn change_continue_to_break() {
     let mut _x = 0;
     while true {
         _x = 1;
-        break;
+        break   ;
     }
 }
diff --git a/src/test/incremental/spans_significant_w_debuginfo.rs b/src/test/incremental/spans_significant_w_debuginfo.rs
index 8506636e22b..639454cc975 100644
--- a/src/test/incremental/spans_significant_w_debuginfo.rs
+++ b/src/test/incremental/spans_significant_w_debuginfo.rs
@@ -1,16 +1,21 @@
 // This test makes sure that just changing a definition's location in the
 // source file also changes its incr. comp. hash, if debuginfo is enabled.
 
-// revisions:rpass1 rpass2
+// revisions:rpass1 rpass2 rpass3 rpass4
 
 // ignore-asmjs wasm2js does not support source maps yet
 // compile-flags: -g -Z query-dep-graph
+// [rpass3]compile-flags: -Zincremental-relative-spans
+// [rpass4]compile-flags: -Zincremental-relative-spans
 
 #![feature(rustc_attrs)]
+#![rustc_partition_codegened(module = "spans_significant_w_debuginfo", cfg = "rpass2")]
+#![rustc_partition_codegened(module = "spans_significant_w_debuginfo", cfg = "rpass4")]
 
-#[cfg(rpass1)]
+#[cfg(any(rpass1, rpass3))]
 pub fn main() {}
 
-#[cfg(rpass2)]
-#[rustc_clean(except="hir_owner,hir_owner_nodes,optimized_mir", cfg="rpass2")]
+#[cfg(any(rpass2, rpass4))]
+#[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir", cfg = "rpass2")]
+#[rustc_clean(cfg = "rpass4")]
 pub fn main() {}
diff --git a/src/test/incremental/spans_significant_w_panic.rs b/src/test/incremental/spans_significant_w_panic.rs
index a29b61ab153..e9e35791aa1 100644
--- a/src/test/incremental/spans_significant_w_panic.rs
+++ b/src/test/incremental/spans_significant_w_panic.rs
@@ -1,19 +1,29 @@
 // This test makes sure that just changing a definition's location in the
 // source file also changes its incr. comp. hash, if debuginfo is enabled.
 
-// revisions:rpass1 rpass2
+// revisions:rpass1 rpass2 rpass3 rpass4
+// [rpass3]compile-flags: -Zincremental-relative-spans
+// [rpass4]compile-flags: -Zincremental-relative-spans
 
 // compile-flags: -C overflow-checks=on -Z query-dep-graph
 
 #![feature(rustc_attrs)]
+#![feature(bench_black_box)]
+#![rustc_partition_codegened(module = "spans_significant_w_panic", cfg = "rpass2")]
+#![rustc_partition_codegened(module = "spans_significant_w_panic", cfg = "rpass4")]
 
-#[cfg(rpass1)]
+#[cfg(any(rpass1, rpass3))]
 pub fn main() {
-    let _ = 0u8 + 1;
+    if std::hint::black_box(false) {
+        panic!()
+    }
 }
 
-#[cfg(rpass2)]
-#[rustc_clean(except="hir_owner,hir_owner_nodes,optimized_mir", cfg="rpass2")]
+#[cfg(any(rpass2, rpass4))]
+#[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir", cfg = "rpass2")]
+#[rustc_clean(cfg = "rpass4")]
 pub fn main() {
-    let _ = 0u8 + 1;
+    if std::hint::black_box(false) {
+        panic!()
+    }
 }
diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs
index 866f51d759e..cae7b4aab75 100644
--- a/src/test/incremental/string_constant.rs
+++ b/src/test/incremental/string_constant.rs
@@ -1,5 +1,7 @@
-// revisions: cfail1 cfail2
+// revisions: cfail1 cfail2 cfail3 cfail4
 // compile-flags: -Z query-dep-graph
+// [cfail3]compile-flags: -Zincremental-relative-spans
+// [cfail4]compile-flags: -Zincremental-relative-spans
 // build-pass (FIXME(62277): could be check-pass?)
 
 #![allow(warnings)]
@@ -10,15 +12,15 @@
 // Therefore, the compiler deduces (correctly) that typeck is not
 // needed even for callers of `x`.
 
-
 pub mod x {
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1, cfail3))]
     pub fn x() {
         println!("{}", "1");
     }
 
-    #[cfg(cfail2)]
-    #[rustc_clean(except="hir_owner,hir_owner_nodes,optimized_mir,promoted_mir", cfg="cfail2")]
+    #[cfg(any(cfail2, cfail4))]
+    #[rustc_clean(except = "hir_owner,hir_owner_nodes,optimized_mir,promoted_mir", cfg = "cfail2")]
+    #[rustc_clean(except = "hir_owner_nodes,promoted_mir", cfg = "cfail4")]
     pub fn x() {
         println!("{}", "2");
     }
@@ -27,7 +29,8 @@ pub mod x {
 pub mod y {
     use x;
 
-    #[rustc_clean(cfg="cfail2")]
+    #[rustc_clean(cfg = "cfail2")]
+    #[rustc_clean(cfg = "cfail4")]
     pub fn y() {
         x::x();
     }
@@ -36,7 +39,8 @@ pub mod y {
 pub mod z {
     use y;
 
-    #[rustc_clean(cfg="cfail2")]
+    #[rustc_clean(cfg = "cfail2")]
+    #[rustc_clean(cfg = "cfail4")]
     pub fn z() {
         y::y();
     }
diff --git a/src/test/incremental/thinlto/cgu_keeps_identical_fn.rs b/src/test/incremental/thinlto/cgu_keeps_identical_fn.rs
index 0fd5abee118..31f329a7f72 100644
--- a/src/test/incremental/thinlto/cgu_keeps_identical_fn.rs
+++ b/src/test/incremental/thinlto/cgu_keeps_identical_fn.rs
@@ -3,36 +3,61 @@
 // ends up with any spans in its LLVM bitecode, so LLVM is able to skip
 // re-building any modules which import 'inlined_fn'
 
-// revisions: cfail1 cfail2 cfail3
+// revisions: cfail1 cfail2 cfail3 cfail4 cfail5 cfail6
+// [cfail4]compile-flags: -Zincremental-relative-spans
+// [cfail5]compile-flags: -Zincremental-relative-spans
+// [cfail6]compile-flags: -Zincremental-relative-spans
 // compile-flags: -Z query-dep-graph -O
 // build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(rustc_attrs)]
-#![crate_type="rlib"]
-
-#![rustc_expected_cgu_reuse(module="cgu_keeps_identical_fn-foo",
-                            cfg="cfail2",
-                            kind="no")]
-#![rustc_expected_cgu_reuse(module="cgu_keeps_identical_fn-foo",
-                            cfg="cfail3",
-                            kind="post-lto")]
-
-#![rustc_expected_cgu_reuse(module="cgu_keeps_identical_fn-bar",
-                            cfg="cfail2",
-                            kind="post-lto")]
-#![rustc_expected_cgu_reuse(module="cgu_keeps_identical_fn-bar",
-                            cfg="cfail3",
-                            kind="post-lto")]
+#![crate_type = "rlib"]
+#![rustc_expected_cgu_reuse(module = "cgu_keeps_identical_fn-foo", cfg = "cfail2", kind = "no")]
+#![rustc_expected_cgu_reuse(
+    module = "cgu_keeps_identical_fn-foo",
+    cfg = "cfail3",
+    kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+    module = "cgu_keeps_identical_fn-foo",
+    cfg = "cfail5",
+    kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+    module = "cgu_keeps_identical_fn-foo",
+    cfg = "cfail6",
+    kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+    module = "cgu_keeps_identical_fn-bar",
+    cfg = "cfail2",
+    kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+    module = "cgu_keeps_identical_fn-bar",
+    cfg = "cfail3",
+    kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+    module = "cgu_keeps_identical_fn-bar",
+    cfg = "cfail5",
+    kind = "post-lto"
+)]
+#![rustc_expected_cgu_reuse(
+    module = "cgu_keeps_identical_fn-bar",
+    cfg = "cfail6",
+    kind = "post-lto"
+)]
 
 mod foo {
 
     // Trivial functions like this one are imported very reliably by ThinLTO.
-    #[cfg(cfail1)]
+    #[cfg(any(cfail1, cfail4))]
     pub fn inlined_fn() -> u32 {
         1234
     }
 
-    #[cfg(not(cfail1))]
+    #[cfg(not(any(cfail1, cfail4)))]
     pub fn inlined_fn() -> u32 {
         1234
     }
diff --git a/src/test/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff
new file mode 100644
index 00000000000..3f5f71f8082
--- /dev/null
+++ b/src/test/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff
@@ -0,0 +1,24 @@
+- // MIR for `align_of` before LowerIntrinsics
++ // MIR for `align_of` after LowerIntrinsics
+  
+  fn align_of() -> usize {
+      let mut _0: usize;                   // return place in scope 0 at $DIR/lower_intrinsics.rs:18:25: 18:30
+  
+      bb0: {
+-         _0 = std::intrinsics::min_align_of::<T>() -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:42
+-                                          // mir::Constant
+-                                          // + span: $DIR/lower_intrinsics.rs:19:5: 19:40
+-                                          // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::min_align_of::<T>}, val: Value(Scalar(<ZST>)) }
++         _0 = AlignOf(T);                 // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:42
++         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:42
+      }
+  
+      bb1: {
+          return;                          // scope 0 at $DIR/lower_intrinsics.rs:20:2: 20:2
+      }
+  
+      bb2 (cleanup): {
+          resume;                          // scope 0 at $DIR/lower_intrinsics.rs:18:1: 20:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
index f427375e5a6..d9b441a470c 100644
--- a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
+++ b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
@@ -2,127 +2,127 @@
 + // MIR for `discriminant` after LowerIntrinsics
   
   fn discriminant(_1: T) -> () {
-      debug t => _1;                       // in scope 0 at $DIR/lower_intrinsics.rs:68:24: 68:25
-      let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:68:30: 68:30
-      let _2: <T as std::marker::DiscriminantKind>::Discriminant; // in scope 0 at $DIR/lower_intrinsics.rs:69:5: 69:45
-      let mut _3: &T;                      // in scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44
-      let _4: &T;                          // in scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44
-      let _5: u8;                          // in scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45
-      let mut _6: &i32;                    // in scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
-      let _7: &i32;                        // in scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
-      let _8: i32;                         // in scope 0 at $DIR/lower_intrinsics.rs:70:43: 70:44
-      let _9: u8;                          // in scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46
-      let mut _10: &();                    // in scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
-      let _11: &();                        // in scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
-      let _12: ();                         // in scope 0 at $DIR/lower_intrinsics.rs:71:43: 71:45
-      let _13: isize;                      // in scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48
-      let mut _14: &E;                     // in scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
-      let _15: &E;                         // in scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
-      let _16: E;                          // in scope 0 at $DIR/lower_intrinsics.rs:72:43: 72:47
-      let mut _17: &E;                     // in scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
-      let mut _18: &();                    // in scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
-      let mut _19: &i32;                   // in scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
+      debug t => _1;                       // in scope 0 at $DIR/lower_intrinsics.rs:73:24: 73:25
+      let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:73:30: 73:30
+      let _2: <T as std::marker::DiscriminantKind>::Discriminant; // in scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45
+      let mut _3: &T;                      // in scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44
+      let _4: &T;                          // in scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44
+      let _5: u8;                          // in scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45
+      let mut _6: &i32;                    // in scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
+      let _7: &i32;                        // in scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
+      let _8: i32;                         // in scope 0 at $DIR/lower_intrinsics.rs:75:43: 75:44
+      let _9: u8;                          // in scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46
+      let mut _10: &();                    // in scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+      let _11: &();                        // in scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+      let _12: ();                         // in scope 0 at $DIR/lower_intrinsics.rs:76:43: 76:45
+      let _13: isize;                      // in scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48
+      let mut _14: &E;                     // in scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+      let _15: &E;                         // in scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+      let _16: E;                          // in scope 0 at $DIR/lower_intrinsics.rs:77:43: 77:47
+      let mut _17: &E;                     // in scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+      let mut _18: &();                    // in scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+      let mut _19: &i32;                   // in scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:69:5: 69:45
-          StorageLive(_3);                 // scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44
-          StorageLive(_4);                 // scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44
-          _4 = &_1;                        // scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44
-          _3 = &(*_4);                     // scope 0 at $DIR/lower_intrinsics.rs:69:42: 69:44
--         _2 = discriminant_value::<T>(move _3) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:69:5: 69:45
+          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45
+          StorageLive(_3);                 // scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44
+          StorageLive(_4);                 // scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44
+          _4 = &_1;                        // scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44
+          _3 = &(*_4);                     // scope 0 at $DIR/lower_intrinsics.rs:74:42: 74:44
+-         _2 = discriminant_value::<T>(move _3) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:69:5: 69:41
+-                                          // + span: $DIR/lower_intrinsics.rs:74:5: 74:41
 -                                          // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r T) -> <T as std::marker::DiscriminantKind>::Discriminant {std::intrinsics::discriminant_value::<T>}, val: Value(Scalar(<ZST>)) }
-+         _2 = discriminant((*_3));        // scope 0 at $DIR/lower_intrinsics.rs:69:5: 69:45
-+         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:69:5: 69:45
++         _2 = discriminant((*_3));        // scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45
++         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:74:5: 74:45
       }
   
       bb1: {
-          StorageDead(_3);                 // scope 0 at $DIR/lower_intrinsics.rs:69:44: 69:45
-          StorageDead(_4);                 // scope 0 at $DIR/lower_intrinsics.rs:69:45: 69:46
-          StorageDead(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:69:45: 69:46
-          StorageLive(_5);                 // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45
-          StorageLive(_6);                 // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
-          StorageLive(_7);                 // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
-          _19 = const discriminant::<T>::promoted[2]; // scope 0 at $DIR/lower_intrinsics.rs:70:42: 70:44
+          StorageDead(_3);                 // scope 0 at $DIR/lower_intrinsics.rs:74:44: 74:45
+          StorageDead(_4);                 // scope 0 at $DIR/lower_intrinsics.rs:74:45: 74:46
+          StorageDead(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:74:45: 74:46
+          StorageLive(_5);                 // scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45
+          StorageLive(_6);                 // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
+          StorageLive(_7);                 // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
+          _19 = const discriminant::<T>::promoted[2]; // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
                                            // ty::Const
                                            // + ty: &i32
                                            // + 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_: Some([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
+                                           // + span: $DIR/lower_intrinsics.rs:75:42: 75:44
+                                           // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[2]) }) }
+          _7 = &(*_19);                    // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
+          _6 = &(*_7);                     // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
+-         _5 = discriminant_value::<i32>(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:70:5: 70:41
+-                                          // + span: $DIR/lower_intrinsics.rs:75:5: 75:41
 -                                          // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r i32) -> <i32 as std::marker::DiscriminantKind>::Discriminant {std::intrinsics::discriminant_value::<i32>}, val: Value(Scalar(<ZST>)) }
-+         _5 = discriminant((*_6));        // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45
-+         goto -> bb2;                     // scope 0 at $DIR/lower_intrinsics.rs:70:5: 70:45
++         _5 = discriminant((*_6));        // scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45
++         goto -> bb2;                     // scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45
       }
   
       bb2: {
-          StorageDead(_6);                 // scope 0 at $DIR/lower_intrinsics.rs:70:44: 70:45
-          StorageDead(_7);                 // scope 0 at $DIR/lower_intrinsics.rs:70:45: 70:46
-          StorageDead(_5);                 // scope 0 at $DIR/lower_intrinsics.rs:70:45: 70:46
-          StorageLive(_9);                 // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46
-          StorageLive(_10);                // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
-          StorageLive(_11);                // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
-          _18 = const discriminant::<T>::promoted[1]; // scope 0 at $DIR/lower_intrinsics.rs:71:42: 71:45
+          StorageDead(_6);                 // scope 0 at $DIR/lower_intrinsics.rs:75:44: 75:45
+          StorageDead(_7);                 // scope 0 at $DIR/lower_intrinsics.rs:75:45: 75:46
+          StorageDead(_5);                 // scope 0 at $DIR/lower_intrinsics.rs:75:45: 75:46
+          StorageLive(_9);                 // scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46
+          StorageLive(_10);                // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+          StorageLive(_11);                // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+          _18 = const discriminant::<T>::promoted[1]; // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
                                            // ty::Const
                                            // + ty: &()
                                            // + 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_: Some([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
+                                           // + span: $DIR/lower_intrinsics.rs:76:42: 76:45
+                                           // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[1]) }) }
+          _11 = &(*_18);                   // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+          _10 = &(*_11);                   // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
+-         _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:71:5: 71:41
+-                                          // + span: $DIR/lower_intrinsics.rs:76:5: 76:41
 -                                          // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r ()) -> <() as std::marker::DiscriminantKind>::Discriminant {std::intrinsics::discriminant_value::<()>}, val: Value(Scalar(<ZST>)) }
-+         _9 = discriminant((*_10));       // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46
-+         goto -> bb3;                     // scope 0 at $DIR/lower_intrinsics.rs:71:5: 71:46
++         _9 = discriminant((*_10));       // scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46
++         goto -> bb3;                     // scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46
       }
   
       bb3: {
-          StorageDead(_10);                // scope 0 at $DIR/lower_intrinsics.rs:71:45: 71:46
-          StorageDead(_11);                // scope 0 at $DIR/lower_intrinsics.rs:71:46: 71:47
-          StorageDead(_9);                 // scope 0 at $DIR/lower_intrinsics.rs:71:46: 71:47
-          StorageLive(_13);                // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48
-          StorageLive(_14);                // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
-          StorageLive(_15);                // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
-          _17 = const discriminant::<T>::promoted[0]; // scope 0 at $DIR/lower_intrinsics.rs:72:42: 72:47
+          StorageDead(_10);                // scope 0 at $DIR/lower_intrinsics.rs:76:45: 76:46
+          StorageDead(_11);                // scope 0 at $DIR/lower_intrinsics.rs:76:46: 76:47
+          StorageDead(_9);                 // scope 0 at $DIR/lower_intrinsics.rs:76:46: 76:47
+          StorageLive(_13);                // scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48
+          StorageLive(_14);                // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+          StorageLive(_15);                // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+          _17 = const discriminant::<T>::promoted[0]; // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
                                            // ty::Const
                                            // + ty: &E
                                            // + 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_: Some([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
+                                           // + span: $DIR/lower_intrinsics.rs:77:42: 77:47
+                                           // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[2872]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[0]) }) }
+          _15 = &(*_17);                   // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+          _14 = &(*_15);                   // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
+-         _13 = discriminant_value::<E>(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:72:5: 72:41
+-                                          // + span: $DIR/lower_intrinsics.rs:77:5: 77:41
 -                                          // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r E) -> <E as std::marker::DiscriminantKind>::Discriminant {std::intrinsics::discriminant_value::<E>}, val: Value(Scalar(<ZST>)) }
-+         _13 = discriminant((*_14));      // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48
-+         goto -> bb4;                     // scope 0 at $DIR/lower_intrinsics.rs:72:5: 72:48
++         _13 = discriminant((*_14));      // scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48
++         goto -> bb4;                     // scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48
       }
   
       bb4: {
-          StorageDead(_14);                // scope 0 at $DIR/lower_intrinsics.rs:72:47: 72:48
-          StorageDead(_15);                // scope 0 at $DIR/lower_intrinsics.rs:72:48: 72:49
-          StorageDead(_13);                // scope 0 at $DIR/lower_intrinsics.rs:72:48: 72:49
-          _0 = const ();                   // scope 0 at $DIR/lower_intrinsics.rs:68:30: 73:2
-          drop(_1) -> bb5;                 // scope 0 at $DIR/lower_intrinsics.rs:73:1: 73:2
+          StorageDead(_14);                // scope 0 at $DIR/lower_intrinsics.rs:77:47: 77:48
+          StorageDead(_15);                // scope 0 at $DIR/lower_intrinsics.rs:77:48: 77:49
+          StorageDead(_13);                // scope 0 at $DIR/lower_intrinsics.rs:77:48: 77:49
+          _0 = const ();                   // scope 0 at $DIR/lower_intrinsics.rs:73:30: 78:2
+          drop(_1) -> bb5;                 // scope 0 at $DIR/lower_intrinsics.rs:78:1: 78:2
       }
   
       bb5: {
-          return;                          // scope 0 at $DIR/lower_intrinsics.rs:73:2: 73:2
+          return;                          // scope 0 at $DIR/lower_intrinsics.rs:78:2: 78:2
       }
   
       bb6 (cleanup): {
-          resume;                          // scope 0 at $DIR/lower_intrinsics.rs:68:1: 73:2
+          resume;                          // scope 0 at $DIR/lower_intrinsics.rs:73:1: 78:2
       }
   }
   
diff --git a/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir b/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir
index 380f6ce9ba7..2f3fd9ad285 100644
--- a/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir
+++ b/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir
@@ -1,32 +1,32 @@
 // MIR for `f_u64` before PreCodegen
 
 fn f_u64() -> () {
-    let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:34:16: 34:16
-    let mut _1: u64;                     // in scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21
-    scope 1 (inlined f_dispatch::<u64>) { // at $DIR/lower_intrinsics.rs:35:5: 35:21
-        debug t => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        let _2: ();                      // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        let mut _3: u64;                 // in scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        scope 2 (inlined std::mem::size_of::<u64>) { // at $DIR/lower_intrinsics.rs:35:5: 35:21
+    let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:39:16: 39:16
+    let mut _1: u64;                     // in scope 0 at $DIR/lower_intrinsics.rs:40:5: 40:21
+    scope 1 (inlined f_dispatch::<u64>) { // at $DIR/lower_intrinsics.rs:40:5: 40:21
+        debug t => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        let _2: ();                      // in scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        let mut _3: u64;                 // in scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        scope 2 (inlined std::mem::size_of::<u64>) { // at $DIR/lower_intrinsics.rs:40:5: 40:21
         }
     }
 
     bb0: {
-        StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        _1 = const 0_u64;                // scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        _3 = move _1;                    // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        _2 = f_non_zst::<u64>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
+        StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        _1 = const 0_u64;                // scope 0 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        _3 = move _1;                    // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        _2 = f_non_zst::<u64>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
                                          // mir::Constant
-                                         // + span: $DIR/lower_intrinsics.rs:35:5: 35:21
+                                         // + span: $DIR/lower_intrinsics.rs:40:5: 40:21
                                          // + literal: Const { ty: fn(u64) {f_non_zst::<u64>}, val: Value(Scalar(<ZST>)) }
     }
 
     bb1: {
-        StorageDead(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        StorageDead(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:35:5: 35:21
-        return;                          // scope 0 at $DIR/lower_intrinsics.rs:36:2: 36:2
+        StorageDead(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        StorageDead(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:40:5: 40:21
+        return;                          // scope 0 at $DIR/lower_intrinsics.rs:41:2: 41:2
     }
 }
diff --git a/src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir b/src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir
index 2b9ffaaf971..690405c4748 100644
--- a/src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir
+++ b/src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir
@@ -1,27 +1,27 @@
 // MIR for `f_unit` before PreCodegen
 
 fn f_unit() -> () {
-    let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:28:17: 28:17
-    let mut _1: ();                      // in scope 0 at $DIR/lower_intrinsics.rs:29:16: 29:18
-    scope 1 (inlined f_dispatch::<()>) { // at $DIR/lower_intrinsics.rs:29:5: 29:19
-        debug t => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19
-        let _2: ();                      // in scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19
-        scope 2 (inlined std::mem::size_of::<()>) { // at $DIR/lower_intrinsics.rs:29:5: 29:19
+    let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:33:17: 33:17
+    let mut _1: ();                      // in scope 0 at $DIR/lower_intrinsics.rs:34:16: 34:18
+    scope 1 (inlined f_dispatch::<()>) { // at $DIR/lower_intrinsics.rs:34:5: 34:19
+        debug t => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:34:5: 34:19
+        let _2: ();                      // in scope 1 at $DIR/lower_intrinsics.rs:34:5: 34:19
+        scope 2 (inlined std::mem::size_of::<()>) { // at $DIR/lower_intrinsics.rs:34:5: 34:19
         }
     }
 
     bb0: {
-        StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:29:16: 29:18
-        StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19
-        _2 = f_zst::<()>(const ()) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19
+        StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:34:16: 34:18
+        StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:34:5: 34:19
+        _2 = f_zst::<()>(const ()) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:34:5: 34:19
                                          // mir::Constant
-                                         // + span: $DIR/lower_intrinsics.rs:29:5: 29:19
+                                         // + span: $DIR/lower_intrinsics.rs:34:5: 34:19
                                          // + literal: Const { ty: fn(()) {f_zst::<()>}, val: Value(Scalar(<ZST>)) }
     }
 
     bb1: {
-        StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:29:5: 29:19
-        StorageDead(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:29:18: 29:19
-        return;                          // scope 0 at $DIR/lower_intrinsics.rs:30:2: 30:2
+        StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:34:5: 34:19
+        StorageDead(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:34:18: 34:19
+        return;                          // scope 0 at $DIR/lower_intrinsics.rs:35:2: 35:2
     }
 }
diff --git a/src/test/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff
index 096bba64c0b..7e1e066366c 100644
--- a/src/test/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff
+++ b/src/test/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff
@@ -2,32 +2,32 @@
 + // MIR for `forget` after LowerIntrinsics
   
   fn forget(_1: T) -> () {
-      debug t => _1;                       // in scope 0 at $DIR/lower_intrinsics.rs:18:18: 18:19
-      let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:18:24: 18:24
-      let mut _2: T;                       // in scope 0 at $DIR/lower_intrinsics.rs:19:30: 19:31
+      debug t => _1;                       // in scope 0 at $DIR/lower_intrinsics.rs:23:18: 23:19
+      let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:23:24: 23:24
+      let mut _2: T;                       // in scope 0 at $DIR/lower_intrinsics.rs:24:30: 24:31
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:19:30: 19:31
-          _2 = move _1;                    // scope 0 at $DIR/lower_intrinsics.rs:19:30: 19:31
--         _0 = std::intrinsics::forget::<T>(move _2) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:32
+          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:24:30: 24:31
+          _2 = move _1;                    // scope 0 at $DIR/lower_intrinsics.rs:24:30: 24:31
+-         _0 = std::intrinsics::forget::<T>(move _2) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:24:5: 24:32
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:19:5: 19:29
+-                                          // + span: $DIR/lower_intrinsics.rs:24:5: 24:29
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(T) {std::intrinsics::forget::<T>}, val: Value(Scalar(<ZST>)) }
-+         _0 = const ();                   // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:32
-+         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:19:5: 19:32
++         _0 = const ();                   // scope 0 at $DIR/lower_intrinsics.rs:24:5: 24:32
++         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:24:5: 24:32
       }
   
       bb1: {
-          StorageDead(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:19:31: 19:32
-          goto -> bb2;                     // scope 0 at $DIR/lower_intrinsics.rs:20:1: 20:2
+          StorageDead(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:24:31: 24:32
+          goto -> bb2;                     // scope 0 at $DIR/lower_intrinsics.rs:25:1: 25:2
       }
   
       bb2: {
-          return;                          // scope 0 at $DIR/lower_intrinsics.rs:20:2: 20:2
+          return;                          // scope 0 at $DIR/lower_intrinsics.rs:25:2: 25:2
       }
   
       bb3 (cleanup): {
-          resume;                          // scope 0 at $DIR/lower_intrinsics.rs:18:1: 20:2
+          resume;                          // scope 0 at $DIR/lower_intrinsics.rs:23:1: 25:2
       }
   }
   
diff --git a/src/test/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff
index 218b1c96433..276227d8c01 100644
--- a/src/test/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff
+++ b/src/test/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff
@@ -2,34 +2,34 @@
 + // MIR for `non_const` after LowerIntrinsics
   
   fn non_const() -> usize {
-      let mut _0: usize;                   // return place in scope 0 at $DIR/lower_intrinsics.rs:55:26: 55:31
-      let _1: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}; // in scope 0 at $DIR/lower_intrinsics.rs:57:9: 57:18
-      let mut _2: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}; // in scope 0 at $DIR/lower_intrinsics.rs:58:5: 58:14
+      let mut _0: usize;                   // return place in scope 0 at $DIR/lower_intrinsics.rs:60:26: 60:31
+      let _1: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}; // in scope 0 at $DIR/lower_intrinsics.rs:62:9: 62:18
+      let mut _2: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}; // in scope 0 at $DIR/lower_intrinsics.rs:63:5: 63:14
       scope 1 {
-          debug size_of_t => _1;           // in scope 1 at $DIR/lower_intrinsics.rs:57:9: 57:18
+          debug size_of_t => _1;           // in scope 1 at $DIR/lower_intrinsics.rs:62:9: 62:18
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:57:9: 57:18
-          _1 = std::intrinsics::size_of::<T>; // scope 0 at $DIR/lower_intrinsics.rs:57:21: 57:51
+          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:62:9: 62:18
+          _1 = std::intrinsics::size_of::<T>; // scope 0 at $DIR/lower_intrinsics.rs:62:21: 62:51
                                            // mir::Constant
-                                           // + span: $DIR/lower_intrinsics.rs:57:21: 57:51
+                                           // + span: $DIR/lower_intrinsics.rs:62:21: 62:51
                                            // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}, val: Value(Scalar(<ZST>)) }
-          StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:14
-          _2 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:14
--         _0 = move _2() -> bb1;           // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:16
-+         _0 = SizeOf(T);                  // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:16
-+         goto -> bb1;                     // scope 1 at $DIR/lower_intrinsics.rs:58:5: 58:16
+          StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:63:5: 63:14
+          _2 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:63:5: 63:14
+-         _0 = move _2() -> bb1;           // scope 1 at $DIR/lower_intrinsics.rs:63:5: 63:16
++         _0 = SizeOf(T);                  // scope 1 at $DIR/lower_intrinsics.rs:63:5: 63:16
++         goto -> bb1;                     // scope 1 at $DIR/lower_intrinsics.rs:63:5: 63:16
       }
   
       bb1: {
-          StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:58:15: 58:16
-          StorageDead(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:59:1: 59:2
-          return;                          // scope 0 at $DIR/lower_intrinsics.rs:59:2: 59:2
+          StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:63:15: 63:16
+          StorageDead(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:64:1: 64:2
+          return;                          // scope 0 at $DIR/lower_intrinsics.rs:64:2: 64:2
       }
   
       bb2 (cleanup): {
-          resume;                          // scope 0 at $DIR/lower_intrinsics.rs:55:1: 59:2
+          resume;                          // scope 0 at $DIR/lower_intrinsics.rs:60:1: 64:2
       }
   }
   
diff --git a/src/test/mir-opt/lower_intrinsics.rs b/src/test/mir-opt/lower_intrinsics.rs
index d9891465dab..8a8880dad02 100644
--- a/src/test/mir-opt/lower_intrinsics.rs
+++ b/src/test/mir-opt/lower_intrinsics.rs
@@ -14,6 +14,11 @@ pub fn size_of<T>() -> usize {
     core::intrinsics::size_of::<T>()
 }
 
+// EMIT_MIR lower_intrinsics.align_of.LowerIntrinsics.diff
+pub fn align_of<T>() -> usize {
+    core::intrinsics::min_align_of::<T>()
+}
+
 // EMIT_MIR lower_intrinsics.forget.LowerIntrinsics.diff
 pub fn forget<T>(t: T) {
     core::intrinsics::forget(t)
diff --git a/src/test/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
index a04b79d47d4..50711f574f1 100644
--- a/src/test/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
+++ b/src/test/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
@@ -2,25 +2,25 @@
 + // MIR for `unreachable` after LowerIntrinsics
   
   fn unreachable() -> ! {
-      let mut _0: !;                       // return place in scope 0 at $DIR/lower_intrinsics.rs:23:25: 23:26
-      let mut _1: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:23:27: 25:2
-      let _2: ();                          // in scope 0 at $DIR/lower_intrinsics.rs:24:14: 24:45
-      let mut _3: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:24:14: 24:45
+      let mut _0: !;                       // return place in scope 0 at $DIR/lower_intrinsics.rs:28:25: 28:26
+      let mut _1: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:28:27: 30:2
+      let _2: ();                          // in scope 0 at $DIR/lower_intrinsics.rs:29:14: 29:45
+      let mut _3: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:29:14: 29:45
       scope 1 {
       }
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:24:5: 24:47
-          StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:24:14: 24:45
--         std::intrinsics::unreachable();  // scope 1 at $DIR/lower_intrinsics.rs:24:14: 24:45
+          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:29:5: 29:47
+          StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:29:14: 29:45
+-         std::intrinsics::unreachable();  // scope 1 at $DIR/lower_intrinsics.rs:29:14: 29:45
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_intrinsics.rs:24:14: 24:43
+-                                          // + span: $DIR/lower_intrinsics.rs:29:14: 29:43
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn() -> ! {std::intrinsics::unreachable}, val: Value(Scalar(<ZST>)) }
-+         unreachable;                     // scope 1 at $DIR/lower_intrinsics.rs:24:14: 24:45
++         unreachable;                     // scope 1 at $DIR/lower_intrinsics.rs:29:14: 29:45
       }
   
       bb1 (cleanup): {
-          resume;                          // scope 0 at $DIR/lower_intrinsics.rs:23:1: 25:2
+          resume;                          // scope 0 at $DIR/lower_intrinsics.rs:28:1: 30:2
       }
   }
   
diff --git a/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff b/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
index 6d6c2721973..02f6e55a9a8 100644
--- a/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
+++ b/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
@@ -80,7 +80,7 @@
 -         StorageDead(_7);                 // scope 3 at $DIR/remove_storage_markers.rs:8:18: 8:19
 -         StorageDead(_6);                 // scope 2 at $DIR/remove_storage_markers.rs:10:5: 10:6
 -         StorageDead(_4);                 // scope 1 at $DIR/remove_storage_markers.rs:10:5: 10:6
--         StorageDead(_2);                 // scope 1 at $DIR/remove_storage_markers.rs:8:18: 8:19
+-         StorageDead(_2);                 // scope 1 at $DIR/remove_storage_markers.rs:10:5: 10:6
 -         StorageDead(_1);                 // scope 0 at $DIR/remove_storage_markers.rs:11:1: 11:2
           return;                          // scope 0 at $DIR/remove_storage_markers.rs:11:2: 11:2
       }
diff --git a/src/test/pretty/anonymous-types.rs b/src/test/pretty/anonymous-types.rs
deleted file mode 100644
index 5ff452e8e43..00000000000
--- a/src/test/pretty/anonymous-types.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Test for issue 85480
-// Pretty print anonymous struct and union types
-
-// pp-exact
-// pretty-compare-only
-
-struct Foo {
-    _: union {
-           _: struct {
-                  a: u8,
-                  b: u16,
-              },
-           c: u32,
-       },
-    d: u64,
-    e: f32,
-}
-
-type A =
- struct {
-     field: u8,
- };
-
-fn main() { }
diff --git a/src/test/run-make-fulldeps/obtain-borrowck/driver.rs b/src/test/run-make-fulldeps/obtain-borrowck/driver.rs
index 308df0b030c..961ea518c13 100644
--- a/src/test/run-make-fulldeps/obtain-borrowck/driver.rs
+++ b/src/test/run-make-fulldeps/obtain-borrowck/driver.rs
@@ -11,13 +11,14 @@
 //! `optimized_mir` and pulls out the MIR bodies with the borrowck information
 //! from the thread local storage.
 
+extern crate rustc_borrowck;
 extern crate rustc_driver;
 extern crate rustc_hir;
 extern crate rustc_interface;
 extern crate rustc_middle;
-extern crate rustc_mir;
 extern crate rustc_session;
 
+use rustc_borrowck::consumers::BodyWithBorrowckFacts;
 use rustc_driver::Compilation;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
@@ -26,7 +27,6 @@ use rustc_interface::{Config, Queries};
 use rustc_middle::ty::query::query_values::mir_borrowck;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_mir::consumers::BodyWithBorrowckFacts;
 use rustc_session::Session;
 use std::cell::RefCell;
 use std::collections::HashMap;
@@ -108,7 +108,7 @@ thread_local! {
 }
 
 fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> mir_borrowck<'tcx> {
-    let body_with_facts = rustc_mir::consumers::get_body_with_borrowck_facts(
+    let body_with_facts = rustc_borrowck::consumers::get_body_with_borrowck_facts(
         tcx,
         ty::WithOptConstParam::unknown(def_id),
     );
@@ -120,7 +120,7 @@ fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> mir_borrowck<'tc
         assert!(map.insert(def_id, body_with_facts).is_none());
     });
     let mut providers = Providers::default();
-    rustc_mir::provide(&mut providers);
+    rustc_borrowck::provide(&mut providers);
     let original_mir_borrowck = providers.mir_borrowck;
     original_mir_borrowck(tcx, def_id)
 }
diff --git a/src/test/run-make-fulldeps/reproducible-build/Makefile b/src/test/run-make-fulldeps/reproducible-build/Makefile
index a17ec212cfd..adccc153568 100644
--- a/src/test/run-make-fulldeps/reproducible-build/Makefile
+++ b/src/test/run-make-fulldeps/reproducible-build/Makefile
@@ -9,9 +9,19 @@ all:  \
 	opt \
 	link_paths \
 	remap_paths \
-	different_source_dirs \
+	different_source_dirs_rlib \
+	remap_cwd_rlib \
+	remap_cwd_to_empty \
 	extern_flags
 
+# TODO: Builds of `bin` crate types are not deterministic with debuginfo=2 on
+# Windows.
+# See: https://github.com/rust-lang/rust/pull/87320#issuecomment-920105533
+# Issue: https://github.com/rust-lang/rust/issues/88982
+#
+#	different_source_dirs_bin \
+#	remap_cwd_bin \
+
 smoke:
 	rm -rf $(TMPDIR) && mkdir $(TMPDIR)
 	$(RUSTC) linker.rs -O
@@ -52,7 +62,19 @@ remap_paths:
 	$(RUSTC) reproducible-build.rs --crate-type rlib --remap-path-prefix=/b=/c
 	cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1
 
-different_source_dirs:
+different_source_dirs_bin:
+	rm -rf $(TMPDIR) && mkdir $(TMPDIR)
+	$(RUSTC) reproducible-build-aux.rs
+	mkdir $(TMPDIR)/test
+	cp reproducible-build.rs $(TMPDIR)/test
+	$(RUSTC) reproducible-build.rs --crate-type bin --remap-path-prefix=$$PWD=/b
+	cp $(TMPDIR)/reproducible-build $(TMPDIR)/foo
+	(cd $(TMPDIR)/test && $(RUSTC) reproducible-build.rs \
+		--remap-path-prefix=$(TMPDIR)/test=/b \
+		--crate-type bin)
+	cmp "$(TMPDIR)/reproducible-build" "$(TMPDIR)/foo" || exit 1
+
+different_source_dirs_rlib:
 	rm -rf $(TMPDIR) && mkdir $(TMPDIR)
 	$(RUSTC) reproducible-build-aux.rs
 	mkdir $(TMPDIR)/test
@@ -64,6 +86,45 @@ different_source_dirs:
 		--crate-type rlib)
 	cmp "$(TMPDIR)/libreproducible_build.rlib" "$(TMPDIR)/libfoo.rlib" || exit 1
 
+remap_cwd_bin:
+	rm -rf $(TMPDIR) && mkdir $(TMPDIR)
+	$(RUSTC) reproducible-build-aux.rs
+	mkdir $(TMPDIR)/test
+	cp reproducible-build.rs $(TMPDIR)/test
+	$(RUSTC) reproducible-build.rs --crate-type bin -C debuginfo=2 \
+	  -Z remap-cwd-prefix=.
+	cp $(TMPDIR)/reproducible-build $(TMPDIR)/first
+	(cd $(TMPDIR)/test && \
+	 $(RUSTC) reproducible-build.rs --crate-type bin -C debuginfo=2 \
+	   -Z remap-cwd-prefix=.)
+	cmp "$(TMPDIR)/first" "$(TMPDIR)/reproducible-build" || exit 1
+
+remap_cwd_rlib:
+	rm -rf $(TMPDIR) && mkdir $(TMPDIR)
+	$(RUSTC) reproducible-build-aux.rs
+	mkdir $(TMPDIR)/test
+	cp reproducible-build.rs $(TMPDIR)/test
+	$(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \
+	  -Z remap-cwd-prefix=.
+	cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfirst.rlib
+	(cd $(TMPDIR)/test && \
+	 $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \
+	   -Z remap-cwd-prefix=.)
+	cmp "$(TMPDIR)/libfirst.rlib" "$(TMPDIR)/libreproducible_build.rlib" || exit 1
+
+remap_cwd_to_empty:
+	rm -rf $(TMPDIR) && mkdir $(TMPDIR)
+	$(RUSTC) reproducible-build-aux.rs
+	mkdir $(TMPDIR)/test
+	cp reproducible-build.rs $(TMPDIR)/test
+	$(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \
+	  -Z remap-cwd-prefix=
+	cp $(TMPDIR)/libreproducible_build.rlib $(TMPDIR)/libfirst.rlib
+	(cd $(TMPDIR)/test && \
+	 $(RUSTC) reproducible-build.rs --crate-type rlib -C debuginfo=2 \
+	   -Z remap-cwd-prefix=)
+	cmp "$(TMPDIR)/libfirst.rlib" "$(TMPDIR)/libreproducible_build.rlib" || exit 1
+
 extern_flags:
 	rm -rf $(TMPDIR) && mkdir $(TMPDIR)
 	$(RUSTC) reproducible-build-aux.rs
diff --git a/src/test/run-make-fulldeps/sepcomp-cci-copies/Makefile b/src/test/run-make-fulldeps/sepcomp-cci-copies/Makefile
index 36f913ff3fa..77d1d71e9b2 100644
--- a/src/test/run-make-fulldeps/sepcomp-cci-copies/Makefile
+++ b/src/test/run-make-fulldeps/sepcomp-cci-copies/Makefile
@@ -3,7 +3,7 @@
 # Check that cross-crate inlined items are inlined in all compilation units
 # that refer to them, and not in any other compilation units.
 # Note that we have to pass `-C codegen-units=6` because up to two CGUs may be
-# created for each source module (see `rustc_mir::monomorphize::partitioning`).
+# created for each source module (see `rustc_const_eval::monomorphize::partitioning`).
 
 all:
 	$(RUSTC) cci_lib.rs
diff --git a/src/test/rustdoc-gui/code-sidebar-toggle.goml b/src/test/rustdoc-gui/code-sidebar-toggle.goml
index 00326e9bbc4..6fb92e19660 100644
--- a/src/test/rustdoc-gui/code-sidebar-toggle.goml
+++ b/src/test/rustdoc-gui/code-sidebar-toggle.goml
@@ -1,5 +1,6 @@
 goto: file://|DOC_PATH|/test_docs/index.html
 click: ".srclink"
+wait-for: "#sidebar-toggle"
 click: "#sidebar-toggle"
 wait-for: 500
 fail: true
diff --git a/src/test/rustdoc-gui/docblock-table-overflow.goml b/src/test/rustdoc-gui/docblock-table-overflow.goml
index 9ab7cd0fa07..10f516d2dae 100644
--- a/src/test/rustdoc-gui/docblock-table-overflow.goml
+++ b/src/test/rustdoc-gui/docblock-table-overflow.goml
@@ -7,3 +7,11 @@ compare-elements-property: (".top-doc .docblock", ".top-doc .docblock > p", ["sc
 assert-property: (".top-doc .docblock", {"scrollWidth": "816"})
 // However, since there is overflow in the <table>, its scroll width is bigger.
 assert-property: (".top-doc .docblock table", {"scrollWidth": "1573"})
+
+// Checking it works on other doc blocks as well...
+
+// Logically, the ".docblock" and the "<p>" should have the same scroll width.
+compare-elements-property: ("#implementations + details .docblock", "#implementations + details .docblock > p", ["scrollWidth"])
+assert-property: ("#implementations + details .docblock", {"scrollWidth": "816"})
+// However, since there is overflow in the <table>, its scroll width is bigger.
+assert-property: ("#implementations + details .docblock table", {"scrollWidth": "1573"})
diff --git a/src/test/rustdoc-gui/jump-to-def-background.goml b/src/test/rustdoc-gui/jump-to-def-background.goml
new file mode 100644
index 00000000000..3df899e0f26
--- /dev/null
+++ b/src/test/rustdoc-gui/jump-to-def-background.goml
@@ -0,0 +1,23 @@
+// We check the background color on the jump to definition links in the source code page.
+goto: file://|DOC_PATH|/src/link_to_definition/lib.rs.html
+
+// Set the theme to dark.
+local-storage: {"rustdoc-theme": "dark", "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false"}
+// We reload the page so the local storage settings are being used.
+reload:
+
+assert-css: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(51, 51, 51)"}, ALL)
+
+// Set the theme to ayu.
+local-storage: {"rustdoc-theme": "ayu", "rustdoc-preferred-dark-theme": "ayu", "rustdoc-use-system-theme": "false"}
+// We reload the page so the local storage settings are being used.
+reload:
+
+assert-css: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(51, 51, 51)"}, ALL)
+
+// Set the theme to light.
+local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
+// We reload the page so the local storage settings are being used.
+reload:
+
+assert-css: ("body.source .example-wrap pre.rust a", {"background-color": "rgb(238, 238, 238)"}, ALL)
diff --git a/src/test/rustdoc-gui/src/lib2/lib.rs b/src/test/rustdoc-gui/src/lib2/lib.rs
index cb63a9f6002..d5835b78d2f 100644
--- a/src/test/rustdoc-gui/src/lib2/lib.rs
+++ b/src/test/rustdoc-gui/src/lib2/lib.rs
@@ -67,6 +67,15 @@ pub mod long_table {
     ///
     /// I wanna sqdkfnqds f dsqf qds f dsqf dsq f dsq f qds f qds f qds f dsqq f dsf sqdf dsq fds f dsq f dq f ds fq sd fqds f dsq f sqd fsq df sd fdsqfqsd fdsq f dsq f dsqfd s dfq
     pub struct Foo;
+
+    /// | This::is::a::kinda::very::long::header::number::one | This::is::a::kinda::very::long::header::number::two | This::is::a::kinda::very::long::header::number::one | This::is::a::kinda::very::long::header::number::two |
+    /// | ----------- | ----------- | ----------- | ----------- |
+    /// | This::is::a::kinda::long::content::number::one | This::is::a::kinda::very::long::content::number::two | This::is::a::kinda::long::content::number::one | This::is::a::kinda::very::long::content::number::two |
+    ///
+    /// I wanna sqdkfnqds f dsqf qds f dsqf dsq f dsq f qds f qds f qds f dsqq f dsf sqdf dsq fds f dsq f dq f ds fq sd fqds f dsq f sqd fsq df sd fdsqfqsd fdsq f dsq f dsqfd s dfq
+    impl Foo {
+        pub fn foo(&self) {}
+    }
 }
 
 pub mod summary_table {
diff --git a/src/test/rustdoc-gui/src/link_to_definition/Cargo.lock b/src/test/rustdoc-gui/src/link_to_definition/Cargo.lock
new file mode 100644
index 00000000000..e4b4e52d028
--- /dev/null
+++ b/src/test/rustdoc-gui/src/link_to_definition/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "link_to_definition"
+version = "0.1.0"
diff --git a/src/test/rustdoc-gui/src/link_to_definition/Cargo.toml b/src/test/rustdoc-gui/src/link_to_definition/Cargo.toml
new file mode 100644
index 00000000000..cdd294d74d3
--- /dev/null
+++ b/src/test/rustdoc-gui/src/link_to_definition/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "link_to_definition"
+version = "0.1.0"
+edition = "2018"
+
+[lib]
+path = "lib.rs"
diff --git a/src/test/rustdoc-gui/src/link_to_definition/lib.rs b/src/test/rustdoc-gui/src/link_to_definition/lib.rs
new file mode 100644
index 00000000000..de9ee66a2ba
--- /dev/null
+++ b/src/test/rustdoc-gui/src/link_to_definition/lib.rs
@@ -0,0 +1,6 @@
+pub struct Bar {
+    pub a: String,
+    pub b: u32,
+}
+
+pub fn foo(_b: &Bar) {}
diff --git a/src/test/rustdoc-js-std/multi-query.js b/src/test/rustdoc-js-std/multi-query.js
index 01e54065189..1c92d019606 100644
--- a/src/test/rustdoc-js-std/multi-query.js
+++ b/src/test/rustdoc-js-std/multi-query.js
@@ -2,8 +2,9 @@ const QUERY = 'str,u8';
 
 const EXPECTED = {
     'others': [
-        { 'path': 'std', 'name': 'str' },
-        { 'path': 'std', 'name': 'u8' },
-        { 'path': 'std::ffi', 'name': 'CStr' },
+        { 'path': 'std', 'name': 'str', 'href': '../std/primitive.str.html' },
+        { 'path': 'std', 'name': 'u8', 'href': '../std/primitive.u8.html'  },
+        { 'path': 'std', 'name': 'str', 'href': '../std/str/index.html' },
+        { 'path': 'std', 'name': 'u8', 'href': '../std/u8/index.html' },
     ],
 };
diff --git a/src/test/rustdoc-ui/coverage/enum-tuple-documented.rs b/src/test/rustdoc-ui/coverage/enum-tuple-documented.rs
new file mode 100644
index 00000000000..e9c165b1916
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/enum-tuple-documented.rs
@@ -0,0 +1,37 @@
+// compile-flags:-Z unstable-options --show-coverage
+// check-pass
+
+// The point of this test is to ensure that the number of "documented" items
+// is higher than in `enum-tuple.rs`.
+
+//! (remember the crate root is still a module)
+
+/// so check out this enum here
+pub enum ThisEnum {
+    /// VarOne.
+    VarOne(
+        /// hello!
+        String,
+    ),
+    /// Var Two.
+    VarTwo(
+        /// Hello
+        String,
+        /// Bis repetita.
+        String,
+    ),
+}
+
+/// Struct.
+pub struct ThisStruct(
+    /// hello
+    u32,
+);
+
+/// Struct.
+pub struct ThisStruct2(
+    /// hello
+    u32,
+    /// Bis repetita.
+    u8,
+);
diff --git a/src/test/rustdoc-ui/coverage/enum-tuple-documented.stdout b/src/test/rustdoc-ui/coverage/enum-tuple-documented.stdout
new file mode 100644
index 00000000000..82c98f43f3d
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/enum-tuple-documented.stdout
@@ -0,0 +1,7 @@
++-------------------------------------+------------+------------+------------+------------+
+| File                                | Documented | Percentage |   Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...overage/enum-tuple-documented.rs |          9 |     100.0% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total                               |          9 |     100.0% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
diff --git a/src/test/rustdoc-ui/coverage/enum-tuple.rs b/src/test/rustdoc-ui/coverage/enum-tuple.rs
new file mode 100644
index 00000000000..5fb20545075
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/enum-tuple.rs
@@ -0,0 +1,18 @@
+// compile-flags:-Z unstable-options --show-coverage
+// check-pass
+
+//! (remember the crate root is still a module)
+
+/// so check out this enum here
+pub enum ThisEnum {
+    /// No need to document the field if there is only one in a tuple variant!
+    VarOne(String),
+    /// But if there is more than one... still fine!
+    VarTwo(String, String),
+}
+
+/// Struct.
+pub struct ThisStruct(u32);
+
+/// Struct.
+pub struct ThisStruct2(u32, u8);
diff --git a/src/test/rustdoc-ui/coverage/enum-tuple.stdout b/src/test/rustdoc-ui/coverage/enum-tuple.stdout
new file mode 100644
index 00000000000..a3377d59c07
--- /dev/null
+++ b/src/test/rustdoc-ui/coverage/enum-tuple.stdout
@@ -0,0 +1,7 @@
++-------------------------------------+------------+------------+------------+------------+
+| File                                | Documented | Percentage |   Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...ustdoc-ui/coverage/enum-tuple.rs |          6 |     100.0% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total                               |          6 |     100.0% |          0 |       0.0% |
++-------------------------------------+------------+------------+------------+------------+
diff --git a/src/test/rustdoc-ui/coverage/enums.stdout b/src/test/rustdoc-ui/coverage/enums.stdout
index 414d60c86d3..64c012c1f66 100644
--- a/src/test/rustdoc-ui/coverage/enums.stdout
+++ b/src/test/rustdoc-ui/coverage/enums.stdout
@@ -1,7 +1,7 @@
 +-------------------------------------+------------+------------+------------+------------+
 | File                                | Documented | Percentage |   Examples | Percentage |
 +-------------------------------------+------------+------------+------------+------------+
-| ...est/rustdoc-ui/coverage/enums.rs |          6 |      66.7% |          0 |       0.0% |
+| ...est/rustdoc-ui/coverage/enums.rs |          6 |      75.0% |          0 |       0.0% |
 +-------------------------------------+------------+------------+------------+------------+
-| Total                               |          6 |      66.7% |          0 |       0.0% |
+| Total                               |          6 |      75.0% |          0 |       0.0% |
 +-------------------------------------+------------+------------+------------+------------+
diff --git a/src/test/rustdoc-ui/display-output.rs b/src/test/rustdoc-ui/display-output.rs
new file mode 100644
index 00000000000..5e390029dca
--- /dev/null
+++ b/src/test/rustdoc-ui/display-output.rs
@@ -0,0 +1,9 @@
+// check-pass
+// compile-flags:-Zunstable-options --display-doctest-warnings --test
+// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
+// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
+
+/// ```
+/// let x = 12;
+/// ```
+pub fn foo() {}
diff --git a/src/test/rustdoc-ui/display-output.stdout b/src/test/rustdoc-ui/display-output.stdout
new file mode 100644
index 00000000000..00467b9359e
--- /dev/null
+++ b/src/test/rustdoc-ui/display-output.stdout
@@ -0,0 +1,24 @@
+
+running 1 test
+test $DIR/display-output.rs - foo (line 6) ... ok
+
+successes:
+
+---- $DIR/display-output.rs - foo (line 6) stdout ----
+warning: unused variable: `x`
+  --> $DIR/display-output.rs:7:5
+   |
+LL | let x = 12;
+   |     ^ help: if this is intentional, prefix it with an underscore: `_x`
+   |
+   = note: `#[warn(unused_variables)]` on by default
+
+warning: 1 warning emitted
+
+
+
+successes:
+    $DIR/display-output.rs - foo (line 6)
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/src/test/rustdoc-ui/intra-doc/anchors.rs b/src/test/rustdoc-ui/intra-doc/anchors.rs
index 6785cb7abea..34e11c7c7b7 100644
--- a/src/test/rustdoc-ui/intra-doc/anchors.rs
+++ b/src/test/rustdoc-ui/intra-doc/anchors.rs
@@ -37,13 +37,3 @@ pub fn bar() {}
 /// Damn enum's variants: [Enum::A#whatever].
 //~^ ERROR `Enum::A#whatever` contains an anchor
 pub fn enum_link() {}
-
-/// Primitives?
-///
-/// [u32#hello]
-//~^ ERROR `u32#hello` contains an anchor
-pub fn x() {}
-
-/// [prim@usize#x]
-//~^ ERROR `prim@usize#x` contains an anchor
-pub mod usize {}
diff --git a/src/test/rustdoc-ui/intra-doc/anchors.stderr b/src/test/rustdoc-ui/intra-doc/anchors.stderr
index d63e1ee60b3..0d226b27753 100644
--- a/src/test/rustdoc-ui/intra-doc/anchors.stderr
+++ b/src/test/rustdoc-ui/intra-doc/anchors.stderr
@@ -1,19 +1,3 @@
-error: `prim@usize#x` contains an anchor, but links to builtin types are already anchored
-  --> $DIR/anchors.rs:47:6
-   |
-LL | /// [prim@usize#x]
-   |      ^^^^^^^^^^--
-   |                |
-   |                invalid anchor
-   |
-note: the lint level is defined here
-  --> $DIR/anchors.rs:1:9
-   |
-LL | #![deny(rustdoc::broken_intra_doc_links)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: this restriction may be lifted in a future release
-   = note: see https://github.com/rust-lang/rust/issues/83083 for more information
-
 error: `Foo::f#hola` contains an anchor, but links to fields are already anchored
   --> $DIR/anchors.rs:25:15
    |
@@ -21,6 +5,12 @@ LL | /// Or maybe [Foo::f#hola].
    |               ^^^^^^-----
    |                     |
    |                     invalid anchor
+   |
+note: the lint level is defined here
+  --> $DIR/anchors.rs:1:9
+   |
+LL | #![deny(rustdoc::broken_intra_doc_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `hello#people#!` contains multiple anchors
   --> $DIR/anchors.rs:31:28
@@ -38,16 +28,5 @@ LL | /// Damn enum's variants: [Enum::A#whatever].
    |                                   |
    |                                   invalid anchor
 
-error: `u32#hello` contains an anchor, but links to builtin types are already anchored
-  --> $DIR/anchors.rs:43:6
-   |
-LL | /// [u32#hello]
-   |      ^^^------
-   |         |
-   |         invalid anchor
-   |
-   = note: this restriction may be lifted in a future release
-   = note: see https://github.com/rust-lang/rust/issues/83083 for more information
-
-error: aborting due to 5 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/test/rustdoc-ui/invalid-syntax.stderr b/src/test/rustdoc-ui/invalid-syntax.stderr
index 5b1846a49d1..4c6249cc6d9 100644
--- a/src/test/rustdoc-ui/invalid-syntax.stderr
+++ b/src/test/rustdoc-ui/invalid-syntax.stderr
@@ -14,7 +14,7 @@ LL | | /// ```
 help: mark blocks that do not contain Rust code as text
    |
 LL | /// ```text
-   |     ~~~~~~~
+   |        ++++
 
 warning: could not parse code block as Rust code
   --> $DIR/invalid-syntax.rs:9:5
@@ -32,7 +32,7 @@ LL | | /// ```
 help: mark blocks that do not contain Rust code as text
    |
 LL | /// ```text
-   |     ~~~~~~~
+   |        ++++
 
 warning: could not parse code block as Rust code
   --> $DIR/invalid-syntax.rs:21:5
@@ -47,7 +47,7 @@ LL | | /// ```
 help: mark blocks that do not contain Rust code as text
    |
 LL | /// ```text
-   |     ~~~~~~~
+   |        ++++
 
 warning: could not parse code block as Rust code
   --> $DIR/invalid-syntax.rs:35:5
@@ -123,7 +123,7 @@ LL | | /// ```
 help: mark blocks that do not contain Rust code as text
    |
 LL | /// ```text
-   |     ~~~~~~~
+   |        ++++
 
 warning: could not parse code block as Rust code
   --> $DIR/invalid-syntax.rs:92:9
@@ -148,7 +148,7 @@ LL | | /// ```
 help: mark blocks that do not contain Rust code as text
    |
 LL | /// ```text
-   |     ~~~~~~~
+   |        ++++
 
 warning: 12 warnings emitted
 
diff --git a/src/test/rustdoc-ui/lint-missing-doc-code-example.rs b/src/test/rustdoc-ui/lint-missing-doc-code-example.rs
index 41e88477926..fac6342cd24 100644
--- a/src/test/rustdoc-ui/lint-missing-doc-code-example.rs
+++ b/src/test/rustdoc-ui/lint-missing-doc-code-example.rs
@@ -70,6 +70,22 @@ pub union Union {
     b: f32,
 }
 
+// no code example and it's fine!
+impl Clone for Struct {
+    fn clone(&self) -> Self {
+        Self { field: self.field }
+    }
+}
+
+
+
+/// doc
+///
+/// ```
+/// println!("hello");
+/// ```
+#[derive(Clone)]
+pub struct NiceStruct;
 
 #[doc(hidden)]
 pub mod foo {
diff --git a/src/test/rustdoc/auxiliary/issue-15318.rs b/src/test/rustdoc/auxiliary/issue-15318.rs
index 83cc31b587c..695fa58ef1d 100644
--- a/src/test/rustdoc/auxiliary/issue-15318.rs
+++ b/src/test/rustdoc/auxiliary/issue-15318.rs
@@ -1,6 +1,15 @@
+// no-prefer-dynamic
 // compile-flags: -Cmetadata=aux
-
+#![crate_type = "rlib"]
 #![doc(html_root_url = "http://example.com/")]
+#![feature(lang_items)]
+#![no_std]
+
+#[lang = "eh_personality"]
+fn foo() {}
+
+#[panic_handler]
+fn bar(_: &core::panic::PanicInfo) -> ! { loop {} }
 
 /// dox
 #[doc(primitive = "pointer")]
diff --git a/src/test/rustdoc/auxiliary/primitive-doc.rs b/src/test/rustdoc/auxiliary/primitive-doc.rs
index a5b69740dd4..e8da852a57e 100644
--- a/src/test/rustdoc/auxiliary/primitive-doc.rs
+++ b/src/test/rustdoc/auxiliary/primitive-doc.rs
@@ -1,5 +1,8 @@
 // compile-flags: --crate-type lib --edition 2018
 
+#![feature(no_core)]
+#![no_core]
+
 #[doc(primitive = "usize")]
 /// This is the built-in type `usize`.
 mod usize {
diff --git a/src/test/rustdoc/check-source-code-urls-to-def-std.rs b/src/test/rustdoc/check-source-code-urls-to-def-std.rs
new file mode 100644
index 00000000000..b129ceb5b73
--- /dev/null
+++ b/src/test/rustdoc/check-source-code-urls-to-def-std.rs
@@ -0,0 +1,17 @@
+// compile-flags: -Zunstable-options --generate-link-to-definition
+
+#![crate_name = "foo"]
+
+// @has 'src/foo/check-source-code-urls-to-def-std.rs.html'
+
+fn babar() {}
+
+// @has - '//a[@href="{{channel}}/std/primitive.u32.html"]' 'u32'
+// @has - '//a[@href="{{channel}}/std/primitive.str.html"]' 'str'
+// @has - '//a[@href="{{channel}}/std/primitive.bool.html"]' 'bool'
+// @has - '//a[@href="../../src/foo/check-source-code-urls-to-def-std.rs.html#7"]' 'babar'
+pub fn foo(a: u32, b: &str, c: String) {
+    let x = 12;
+    let y: bool = true;
+    babar();
+}
diff --git a/src/test/rustdoc/check-source-code-urls-to-def.rs b/src/test/rustdoc/check-source-code-urls-to-def.rs
index e3ae79ccdb1..0cb8e423016 100644
--- a/src/test/rustdoc/check-source-code-urls-to-def.rs
+++ b/src/test/rustdoc/check-source-code-urls-to-def.rs
@@ -27,6 +27,8 @@ impl Foo {
 fn babar() {}
 
 // @has - '//a/@href' '/struct.String.html'
+// @has - '//a/@href' '/primitive.u32.html'
+// @has - '//a/@href' '/primitive.str.html'
 // @count - '//a[@href="../../src/foo/check-source-code-urls-to-def.rs.html#21"]' 5
 // @has - '//a[@href="../../source_code/struct.SourceCode.html"]' 'source_code::SourceCode'
 pub fn foo(a: u32, b: &str, c: String, d: Foo, e: bar::Bar, f: source_code::SourceCode) {
@@ -40,5 +42,9 @@ pub fn foo(a: u32, b: &str, c: String, d: Foo, e: bar::Bar, f: source_code::Sour
 
 // @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#14-16"]' 'bar::sub::Trait'
 // @has - '//a[@href="../../src/foo/auxiliary/source-code-bar.rs.html#14-16"]' 'Trait'
-pub fn foo2<T: bar::sub::Trait, V: Trait>(t: &T, v: &V) {
+pub fn foo2<T: bar::sub::Trait, V: Trait>(t: &T, v: &V, b: bool) {
 }
+
+// @has - '//a[@href="../../foo/primitive.bool.html"]' 'bool'
+#[doc(primitive = "bool")]
+mod whatever {}
diff --git a/src/test/rustdoc/cross-crate-primitive-doc.rs b/src/test/rustdoc/cross-crate-primitive-doc.rs
index 05376e4680e..120b6e9747f 100644
--- a/src/test/rustdoc/cross-crate-primitive-doc.rs
+++ b/src/test/rustdoc/cross-crate-primitive-doc.rs
@@ -1,9 +1,13 @@
 // aux-build:primitive-doc.rs
 // compile-flags: --extern-html-root-url=primitive_doc=../ -Z unstable-options
+// ignore-windows
 
-#![no_std]
+#![feature(no_core)]
+#![no_core]
 
 extern crate primitive_doc;
 
 // @has 'cross_crate_primitive_doc/fn.foo.html' '//a[@href="../primitive_doc/primitive.usize.html"]' 'usize'
+// @has 'cross_crate_primitive_doc/fn.foo.html' '//a[@href="../primitive_doc/primitive.usize.html"]' 'link'
+/// [link](usize)
 pub fn foo() -> usize { 0 }
diff --git a/src/test/rustdoc/intra-doc/anchors.rs b/src/test/rustdoc/intra-doc/anchors.rs
index 8ec1a7b4f90..3d4c464960b 100644
--- a/src/test/rustdoc/intra-doc/anchors.rs
+++ b/src/test/rustdoc/intra-doc/anchors.rs
@@ -10,3 +10,15 @@ pub struct Something;
 ///
 /// To link to [Something#Anchor!]
 pub struct SomeOtherType;
+
+/// Primitives?
+///
+/// [u32#hello]
+// @has anchors/fn.x.html
+// @has - '//a/@href' '{{channel}}/std/primitive.u32.html#hello'
+pub fn x() {}
+
+/// [prim@usize#x]
+// @has anchors/usize/index.html
+// @has - '//a/@href' '{{channel}}/std/primitive.usize.html#x'
+pub mod usize {}
diff --git a/src/test/rustdoc/intra-doc/auxiliary/my-core.rs b/src/test/rustdoc/intra-doc/auxiliary/my-core.rs
index 54e986be9ec..92cfd46188b 100644
--- a/src/test/rustdoc/intra-doc/auxiliary/my-core.rs
+++ b/src/test/rustdoc/intra-doc/auxiliary/my-core.rs
@@ -2,6 +2,10 @@
 #![no_core]
 #![crate_type="rlib"]
 
+#[doc(primitive = "char")]
+/// Some char docs
+mod char {}
+
 #[lang = "char"]
 impl char {
     pub fn len_utf8(self) -> usize {
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 9347d7bb428..5a92a28556e 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="{{channel}}/std/primitive.char.html"]' 'char'
-// @has - '//*[@id="main"]//a[@href="{{channel}}/std/primitive.char.html#method.len_utf8"]' 'char::len_utf8'
+// @has - '//*[@id="main"]//a[@href="../my_core/primitive.char.html"]' 'char'
+// @has - '//*[@id="main"]//a[@href="../my_core/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 124faa9a636..cfb3c3842ab 100644
--- a/src/test/rustdoc/intra-doc/prim-methods-local.rs
+++ b/src/test/rustdoc/intra-doc/prim-methods-local.rs
@@ -5,10 +5,13 @@
 
 
 // @has prim_methods_local/index.html
-// @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'
+// @has - '//*[@id="main"]//a[@href="primitive.char.html"]' 'char'
+// @has - '//*[@id="main"]//a[@href="primitive.char.html#method.len_utf8"]' 'char::len_utf8'
 
-//! A [`char`] and its [`char::len_utf8`].
+//! A [prim@`char`] and its [`char::len_utf8`].
+
+#[doc(primitive = "char")]
+mod char {}
 
 #[lang = "char"]
 impl char {
diff --git a/src/test/rustdoc/intra-link-prim-self.rs b/src/test/rustdoc/intra-link-prim-self.rs
index 4744c84b622..8c47f7ef77e 100644
--- a/src/test/rustdoc/intra-link-prim-self.rs
+++ b/src/test/rustdoc/intra-link-prim-self.rs
@@ -7,8 +7,8 @@
 /// [Self::f]
 /// [Self::MAX]
 // @has intra_link_prim_self/primitive.usize.html
-// @has - '//a[@href="{{channel}}/std/primitive.usize.html#method.f"]' 'Self::f'
-// @has - '//a[@href="{{channel}}/std/primitive.usize.html#associatedconstant.MAX"]' 'Self::MAX'
+// @has - '//a[@href="primitive.usize.html#method.f"]' 'Self::f'
+// @has - '//a[@href="primitive.usize.html#associatedconstant.MAX"]' 'Self::MAX'
 impl usize {
     /// Some docs
     pub fn f() {}
diff --git a/src/test/rustdoc/issue-15318-2.rs b/src/test/rustdoc/issue-15318-2.rs
index 2af811ad5bb..f7f5052a36d 100644
--- a/src/test/rustdoc/issue-15318-2.rs
+++ b/src/test/rustdoc/issue-15318-2.rs
@@ -1,5 +1,6 @@
 // aux-build:issue-15318.rs
 // ignore-cross-compile
+#![no_std]
 
 extern crate issue_15318;
 
diff --git a/src/test/rustdoc/issue-88600.rs b/src/test/rustdoc/issue-88600.rs
new file mode 100644
index 00000000000..3761805b48b
--- /dev/null
+++ b/src/test/rustdoc/issue-88600.rs
@@ -0,0 +1,34 @@
+// This test ensure that #[doc(hidden)] is applied correctly in enum variant fields.
+
+// Denotes a field which should be hidden.
+pub struct H;
+
+// Denotes a field which should not be hidden (shown).
+pub struct S;
+
+// @has issue_88600/enum.FooEnum.html
+pub enum FooEnum {
+    // @has - '//*[@id="variant.HiddenTupleItem"]//code' 'HiddenTupleItem(_)'
+    // @count - '//*[@id="variant.HiddenTupleItem.field.0"]' 0
+    HiddenTupleItem(#[doc(hidden)] H),
+    // @has - '//*[@id="variant.MultipleHidden"]//code' 'MultipleHidden(_, _)'
+    // @count - '//*[@id="variant.MultipleHidden.field.0"]' 0
+    // @count - '//*[@id="variant.MultipleHidden.field.1"]' 0
+    MultipleHidden(#[doc(hidden)] H, #[doc(hidden)] H),
+    // @has - '//*[@id="variant.MixedHiddenFirst"]//code' 'MixedHiddenFirst(_, S)'
+    // @count - '//*[@id="variant.MixedHiddenFirst.field.0"]' 0
+    // @has - '//*[@id="variant.MixedHiddenFirst.field.1"]' '1: S'
+    MixedHiddenFirst(#[doc(hidden)] H, S),
+    // @has - '//*[@id="variant.MixedHiddenLast"]//code' 'MixedHiddenLast(S, _)'
+    // @has - '//*[@id="variant.MixedHiddenLast.field.0"]' '0: S'
+    // @count - '//*[@id="variant.MixedHiddenLast.field.1"]' 0
+    MixedHiddenLast(S, #[doc(hidden)] H),
+    // @has - '//*[@id="variant.HiddenStruct"]//code' 'HiddenStruct'
+    // @count - '//*[@id="variant.HiddenStruct.field.h"]' 0
+    // @has - '//*[@id="variant.HiddenStruct.field.s"]' 's: S'
+    HiddenStruct {
+        #[doc(hidden)]
+        h: H,
+        s: S,
+    },
+}
diff --git a/src/test/rustdoc/no_std-primitive.rs b/src/test/rustdoc/no_std-primitive.rs
new file mode 100644
index 00000000000..22fd392dd36
--- /dev/null
+++ b/src/test/rustdoc/no_std-primitive.rs
@@ -0,0 +1,6 @@
+#![no_std]
+
+/// Link to [intra-doc link][u8]
+// @has 'no_std_primitive/fn.foo.html' '//a[@href="{{channel}}/core/primitive.u8.html"]' 'intra-doc link'
+// @has - '//a[@href="{{channel}}/core/primitive.u8.html"]' 'u8'
+pub fn foo() -> u8 {}
diff --git a/src/test/rustdoc/primitive/no_std.rs b/src/test/rustdoc/primitive/no_std.rs
new file mode 100644
index 00000000000..f0f70cb6c18
--- /dev/null
+++ b/src/test/rustdoc/primitive/no_std.rs
@@ -0,0 +1,16 @@
+#![no_std]
+#![deny(warnings)]
+#![deny(rustdoc::broken_intra_doc_links)]
+
+// @has no_std/fn.foo.html '//a/[@href="{{channel}}/core/primitive.u8.html"]' 'u8'
+// @has no_std/fn.foo.html '//a/[@href="{{channel}}/core/primitive.u8.html"]' 'primitive link'
+/// Link to [primitive link][u8]
+pub fn foo() -> u8 {}
+
+// Test that all primitives can be linked to.
+/// [isize] [i8] [i16] [i32] [i64] [i128]
+/// [usize] [u8] [u16] [u32] [u64] [u128]
+/// [f32] [f64]
+/// [char] [bool] [str] [slice] [array] [tuple] [unit]
+/// [pointer] [reference] [fn] [never]
+pub fn bar() {}
diff --git a/src/test/rustdoc/synthetic_auto/no-redundancy.rs b/src/test/rustdoc/synthetic_auto/no-redundancy.rs
index f727c9a47f2..16ab876e829 100644
--- a/src/test/rustdoc/synthetic_auto/no-redundancy.rs
+++ b/src/test/rustdoc/synthetic_auto/no-redundancy.rs
@@ -10,7 +10,7 @@ where
 
 // @has no_redundancy/struct.Outer.html
 // @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
-// "impl<T> Send for Outer<T> where T: Copy + Send"
+// "impl<T> Send for Outer<T> where T: Send + Copy"
 pub struct Outer<T> {
     inner_field: Inner<T>,
 }
diff --git a/src/test/rustdoc/table-in-docblock.rs b/src/test/rustdoc/table-in-docblock.rs
new file mode 100644
index 00000000000..858b589196e
--- /dev/null
+++ b/src/test/rustdoc/table-in-docblock.rs
@@ -0,0 +1,16 @@
+#![crate_name = "foo"]
+
+// @has foo/struct.Foo.html
+// @count - '//*[@class="docblock"]/div/table' 2
+// @!has - '//*[@class="docblock"]/table'
+/// | hello | hello2 |
+/// | ----- | ------ |
+/// | data  | data2  |
+pub struct Foo;
+
+impl Foo {
+    /// | hello | hello2 |
+    /// | ----- | ------ |
+    /// | data  | data2  |
+    pub fn foo(&self) {}
+}
diff --git a/src/test/rustdoc/type-layout.rs b/src/test/rustdoc/type-layout.rs
index 272911de681..0868486fa59 100644
--- a/src/test/rustdoc/type-layout.rs
+++ b/src/test/rustdoc/type-layout.rs
@@ -52,3 +52,21 @@ pub struct Unsized([u8]);
 
 // @!has type_layout/trait.MyTrait.html 'Size: '
 pub trait MyTrait {}
+
+// @has type_layout/enum.Variants.html 'Size: '
+// @has - '2 bytes'
+// @has - '<code>A</code>: 0 bytes'
+// @has - '<code>B</code>: 1 byte'
+pub enum Variants {
+    A,
+    B(u8),
+}
+
+// @has type_layout/enum.WithNiche.html 'Size: '
+// @has - //p '4 bytes'
+// @has - '<code>None</code>: 0 bytes'
+// @has - '<code>Some</code>: 4 bytes'
+pub enum WithNiche {
+    None,
+    Some(std::num::NonZeroU32),
+}
diff --git a/src/test/ui/anon-params/anon-params-denied-2018.stderr b/src/test/ui/anon-params/anon-params-denied-2018.stderr
index 55905e5ca6a..bb60c898e81 100644
--- a/src/test/ui/anon-params/anon-params-denied-2018.stderr
+++ b/src/test/ui/anon-params/anon-params-denied-2018.stderr
@@ -8,15 +8,15 @@ LL |     fn foo(i32);
 help: if this is a `self` type, give it a parameter name
    |
 LL |     fn foo(self: i32);
-   |            ~~~~~~~~~
+   |            +++++
 help: if this is a parameter name, give it a type
    |
 LL |     fn foo(i32: TypeName);
-   |            ~~~~~~~~~~~~~
+   |               ++++++++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL |     fn foo(_: i32);
-   |            ~~~~~~
+   |            ++
 
 error: expected one of `:`, `@`, or `|`, found `)`
   --> $DIR/anon-params-denied-2018.rs:9:29
@@ -28,7 +28,7 @@ LL |     fn foo_with_ref(&mut i32);
 help: if this is a `self` type, give it a parameter name
    |
 LL |     fn foo_with_ref(self: &mut i32);
-   |                     ~~~~~~~~~~~~~~
+   |                     +++++
 help: if this is a parameter name, give it a type
    |
 LL |     fn foo_with_ref(i32: &mut TypeName);
@@ -36,7 +36,7 @@ LL |     fn foo_with_ref(i32: &mut TypeName);
 help: if this is a type, explicitly ignore the parameter name
    |
 LL |     fn foo_with_ref(_: &mut i32);
-   |                     ~~~~~~~~~~~
+   |                     ++
 
 error: expected one of `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
   --> $DIR/anon-params-denied-2018.rs:12:47
@@ -96,15 +96,15 @@ LL |     fn bar_with_default_impl(String, String) {}
 help: if this is a `self` type, give it a parameter name
    |
 LL |     fn bar_with_default_impl(self: String, String) {}
-   |                              ~~~~~~~~~~~~
+   |                              +++++
 help: if this is a parameter name, give it a type
    |
 LL |     fn bar_with_default_impl(String: TypeName, String) {}
-   |                              ~~~~~~~~~~~~~~~~
+   |                                    ++++++++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL |     fn bar_with_default_impl(_: String, String) {}
-   |                              ~~~~~~~~~
+   |                              ++
 
 error: expected one of `:`, `@`, or `|`, found `)`
   --> $DIR/anon-params-denied-2018.rs:22:44
@@ -116,11 +116,11 @@ LL |     fn bar_with_default_impl(String, String) {}
 help: if this is a parameter name, give it a type
    |
 LL |     fn bar_with_default_impl(String, String: TypeName) {}
-   |                                      ~~~~~~~~~~~~~~~~
+   |                                            ++++++++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL |     fn bar_with_default_impl(String, _: String) {}
-   |                                      ~~~~~~~~~
+   |                                      ++
 
 error: expected one of `:`, `@`, or `|`, found `,`
   --> $DIR/anon-params-denied-2018.rs:27:22
@@ -132,11 +132,11 @@ LL |     fn baz(a:usize, b, c: usize) -> usize {
 help: if this is a parameter name, give it a type
    |
 LL |     fn baz(a:usize, b: TypeName, c: usize) -> usize {
-   |                     ~~~~~~~~~~~
+   |                      ++++++++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL |     fn baz(a:usize, _: b, c: usize) -> usize {
-   |                     ~~~~
+   |                     ++
 
 error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/array-slice-vec/slice_binary_search.rs b/src/test/ui/array-slice-vec/slice_binary_search.rs
index 12236960179..4d8022ecba7 100644
--- a/src/test/ui/array-slice-vec/slice_binary_search.rs
+++ b/src/test/ui/array-slice-vec/slice_binary_search.rs
@@ -2,6 +2,7 @@
 
 // Test binary_search_by_key lifetime. Issue #34683
 
+#[allow(dead_code)]
 #[derive(Debug)]
 struct Assignment {
     topic: String,
diff --git a/src/test/ui/asm/parse-error.rs b/src/test/ui/asm/parse-error.rs
index 3ec3c72d38d..fa14c52cf0a 100644
--- a/src/test/ui/asm/parse-error.rs
+++ b/src/test/ui/asm/parse-error.rs
@@ -76,6 +76,12 @@ fn main() {
         //~^ ERROR asm template must be a string literal
         asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
         //~^ ERROR asm template must be a string literal
+        asm!("{}", in(reg) _);
+        //~^ ERROR _ cannot be used for input operands
+        asm!("{}", inout(reg) _);
+        //~^ ERROR _ cannot be used for input operands
+        asm!("{}", inlateout(reg) _);
+        //~^ ERROR _ cannot be used for input operands
     }
 }
 
diff --git a/src/test/ui/asm/parse-error.stderr b/src/test/ui/asm/parse-error.stderr
index 423003c99d4..78d342cc1da 100644
--- a/src/test/ui/asm/parse-error.stderr
+++ b/src/test/ui/asm/parse-error.stderr
@@ -214,62 +214,80 @@ LL |         asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
    |
    = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
 
+error: _ cannot be used for input operands
+  --> $DIR/parse-error.rs:79:28
+   |
+LL |         asm!("{}", in(reg) _);
+   |                            ^
+
+error: _ cannot be used for input operands
+  --> $DIR/parse-error.rs:81:31
+   |
+LL |         asm!("{}", inout(reg) _);
+   |                               ^
+
+error: _ cannot be used for input operands
+  --> $DIR/parse-error.rs:83:35
+   |
+LL |         asm!("{}", inlateout(reg) _);
+   |                                   ^
+
 error: requires at least a template string argument
-  --> $DIR/parse-error.rs:84:1
+  --> $DIR/parse-error.rs:90:1
    |
 LL | global_asm!();
    | ^^^^^^^^^^^^^^
 
 error: asm template must be a string literal
-  --> $DIR/parse-error.rs:86:13
+  --> $DIR/parse-error.rs:92:13
    |
 LL | global_asm!(FOO);
    |             ^^^
 
 error: expected token: `,`
-  --> $DIR/parse-error.rs:88:18
+  --> $DIR/parse-error.rs:94:18
    |
 LL | global_asm!("{}" FOO);
    |                  ^^^ expected `,`
 
 error: expected operand, options, or additional template string
-  --> $DIR/parse-error.rs:90:19
+  --> $DIR/parse-error.rs:96:19
    |
 LL | global_asm!("{}", FOO);
    |                   ^^^ expected operand, options, or additional template string
 
 error: expected expression, found end of macro arguments
-  --> $DIR/parse-error.rs:92:24
+  --> $DIR/parse-error.rs:98:24
    |
 LL | global_asm!("{}", const);
    |                        ^ expected expression
 
 error: expected one of `,`, `.`, `?`, or an operator, found `FOO`
-  --> $DIR/parse-error.rs:94:30
+  --> $DIR/parse-error.rs:100:30
    |
 LL | global_asm!("{}", const(reg) FOO);
    |                              ^^^ expected one of `,`, `.`, `?`, or an operator
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `FOO`
-  --> $DIR/parse-error.rs:96:25
+  --> $DIR/parse-error.rs:102:25
    |
 LL | global_asm!("", options(FOO));
    |                         ^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
-  --> $DIR/parse-error.rs:98:25
+  --> $DIR/parse-error.rs:104:25
    |
 LL | global_asm!("", options(nomem FOO));
    |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected one of `)`, `att_syntax`, or `raw`, found `nomem`
-  --> $DIR/parse-error.rs:100:25
+  --> $DIR/parse-error.rs:106:25
    |
 LL | global_asm!("", options(nomem, FOO));
    |                         ^^^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: arguments are not allowed after options
-  --> $DIR/parse-error.rs:102:30
+  --> $DIR/parse-error.rs:108:30
    |
 LL | global_asm!("{}", options(), const FOO);
    |                   ---------  ^^^^^^^^^ argument
@@ -277,25 +295,25 @@ LL | global_asm!("{}", options(), const FOO);
    |                   previous options
 
 error: expected string literal
-  --> $DIR/parse-error.rs:104:29
+  --> $DIR/parse-error.rs:110:29
    |
 LL | global_asm!("", clobber_abi(FOO));
    |                             ^^^ not a string literal
 
 error: expected `)`, found `FOO`
-  --> $DIR/parse-error.rs:106:33
+  --> $DIR/parse-error.rs:112:33
    |
 LL | global_asm!("", clobber_abi("C" FOO));
    |                                 ^^^ expected `)`
 
 error: expected `)`, found `,`
-  --> $DIR/parse-error.rs:108:32
+  --> $DIR/parse-error.rs:114:32
    |
 LL | global_asm!("", clobber_abi("C", FOO));
    |                                ^ expected `)`
 
 error: arguments are not allowed after clobber_abi
-  --> $DIR/parse-error.rs:110:37
+  --> $DIR/parse-error.rs:116:37
    |
 LL | global_asm!("{}", clobber_abi("C"), const FOO);
    |                   ----------------  ^^^^^^^^^ argument
@@ -303,13 +321,13 @@ LL | global_asm!("{}", clobber_abi("C"), const FOO);
    |                   clobber_abi
 
 error: `clobber_abi` cannot be used with `global_asm!`
-  --> $DIR/parse-error.rs:110:19
+  --> $DIR/parse-error.rs:116:19
    |
 LL | global_asm!("{}", clobber_abi("C"), const FOO);
    |                   ^^^^^^^^^^^^^^^^
 
 error: clobber_abi is not allowed after options
-  --> $DIR/parse-error.rs:113:28
+  --> $DIR/parse-error.rs:119:28
    |
 LL | global_asm!("", options(), clobber_abi("C"));
    |                 ---------  ^^^^^^^^^^^^^^^^
@@ -317,7 +335,7 @@ LL | global_asm!("", options(), clobber_abi("C"));
    |                 options
 
 error: clobber_abi is not allowed after options
-  --> $DIR/parse-error.rs:115:30
+  --> $DIR/parse-error.rs:121:30
    |
 LL | global_asm!("{}", options(), clobber_abi("C"), const FOO);
    |                   ---------  ^^^^^^^^^^^^^^^^
@@ -325,7 +343,7 @@ LL | global_asm!("{}", options(), clobber_abi("C"), const FOO);
    |                   options
 
 error: clobber_abi specified multiple times
-  --> $DIR/parse-error.rs:117:35
+  --> $DIR/parse-error.rs:123:35
    |
 LL | global_asm!("", clobber_abi("C"), clobber_abi("C"));
    |                 ----------------  ^^^^^^^^^^^^^^^^
@@ -333,7 +351,7 @@ LL | global_asm!("", clobber_abi("C"), clobber_abi("C"));
    |                 clobber_abi previously specified here
 
 error: duplicate argument named `a`
-  --> $DIR/parse-error.rs:119:35
+  --> $DIR/parse-error.rs:125:35
    |
 LL | global_asm!("{a}", a = const FOO, a = const BAR);
    |                    -------------  ^^^^^^^^^^^^^ duplicate argument
@@ -341,7 +359,7 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR);
    |                    previously here
 
 error: argument never used
-  --> $DIR/parse-error.rs:119:35
+  --> $DIR/parse-error.rs:125:35
    |
 LL | global_asm!("{a}", a = const FOO, a = const BAR);
    |                                   ^^^^^^^^^^^^^ argument never used
@@ -349,19 +367,19 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
 
 error: expected one of `clobber_abi`, `const`, or `options`, found `""`
-  --> $DIR/parse-error.rs:122:28
+  --> $DIR/parse-error.rs:128:28
    |
 LL | global_asm!("", options(), "");
    |                            ^^ expected one of `clobber_abi`, `const`, or `options`
 
 error: expected one of `clobber_abi`, `const`, or `options`, found `"{}"`
-  --> $DIR/parse-error.rs:124:30
+  --> $DIR/parse-error.rs:130:30
    |
 LL | global_asm!("{}", const FOO, "{}", const FOO);
    |                              ^^^^ expected one of `clobber_abi`, `const`, or `options`
 
 error: asm template must be a string literal
-  --> $DIR/parse-error.rs:126:13
+  --> $DIR/parse-error.rs:132:13
    |
 LL | global_asm!(format!("{{{}}}", 0), const FOO);
    |             ^^^^^^^^^^^^^^^^^^^^
@@ -369,7 +387,7 @@ LL | global_asm!(format!("{{{}}}", 0), const FOO);
    = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: asm template must be a string literal
-  --> $DIR/parse-error.rs:128:20
+  --> $DIR/parse-error.rs:134:20
    |
 LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
    |                    ^^^^^^^^^^^^^^^^^^^^
@@ -439,6 +457,6 @@ LL |     let mut bar = 0;
 LL |         asm!("{1}", in("eax") foo, const bar);
    |                                          ^^^ non-constant value
 
-error: aborting due to 63 previous errors
+error: aborting due to 66 previous errors
 
 For more information about this error, try `rustc --explain E0435`.
diff --git a/src/test/ui/associated-consts/associated-const-in-trait.stderr b/src/test/ui/associated-consts/associated-const-in-trait.stderr
index 7b459410824..fc949f24948 100644
--- a/src/test/ui/associated-consts/associated-const-in-trait.stderr
+++ b/src/test/ui/associated-consts/associated-const-in-trait.stderr
@@ -4,7 +4,6 @@ error[E0038]: the trait `Trait` cannot be made into an object
 LL | impl dyn Trait {
    |      ^^^^^^^^^ `Trait` cannot be made into an object
    |
-   = help: consider moving `N` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/associated-const-in-trait.rs:6:11
    |
@@ -12,6 +11,7 @@ LL | trait Trait {
    |       ----- this trait cannot be made into an object...
 LL |     const N: usize;
    |           ^ ...because it contains this associated `const`
+   = help: consider moving `N` to another trait
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-item/issue-48027.stderr b/src/test/ui/associated-item/issue-48027.stderr
index 77915a80a79..7b158f1d754 100644
--- a/src/test/ui/associated-item/issue-48027.stderr
+++ b/src/test/ui/associated-item/issue-48027.stderr
@@ -21,7 +21,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL | impl dyn Bar {}
    |      ^^^^^^^ `Bar` cannot be made into an object
    |
-   = help: consider moving `X` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-48027.rs:2:11
    |
@@ -29,6 +28,7 @@ LL | trait Bar {
    |       --- this trait cannot be made into an object...
 LL |     const X: usize;
    |           ^ ...because it contains this associated `const`
+   = help: consider moving `X` to another trait
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr b/src/test/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr
index 474b3c5c717..19fc2f652c6 100644
--- a/src/test/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr
+++ b/src/test/ui/associated-types/associated-type-projection-ambig-between-bound-and-where-clause.stderr
@@ -13,11 +13,11 @@ LL | fn a<C:Vehicle+Box>(_: C::Color) {
 help: use fully qualified syntax to disambiguate
    |
 LL | fn a<C:Vehicle+Box>(_: <C as Box>::Color) {
-   |                        ~~~~~~~~~~~~~~~~~
+   |                        ~~~~~~~~~~~~
 help: use fully qualified syntax to disambiguate
    |
 LL | fn a<C:Vehicle+Box>(_: <C as Vehicle>::Color) {
-   |                        ~~~~~~~~~~~~~~~~~~~~~
+   |                        ~~~~~~~~~~~~~~~~
 
 error[E0221]: ambiguous associated type `Color` in bounds of `C`
   --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:20:12
@@ -34,11 +34,11 @@ LL | fn b<C>(_: C::Color) where C : Vehicle+Box {
 help: use fully qualified syntax to disambiguate
    |
 LL | fn b<C>(_: <C as Box>::Color) where C : Vehicle+Box {
-   |            ~~~~~~~~~~~~~~~~~
+   |            ~~~~~~~~~~~~
 help: use fully qualified syntax to disambiguate
    |
 LL | fn b<C>(_: <C as Vehicle>::Color) where C : Vehicle+Box {
-   |            ~~~~~~~~~~~~~~~~~~~~~
+   |            ~~~~~~~~~~~~~~~~
 
 error[E0221]: ambiguous associated type `Color` in bounds of `C`
   --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:24:12
@@ -55,11 +55,11 @@ LL | fn c<C>(_: C::Color) where C : Vehicle, C : Box {
 help: use fully qualified syntax to disambiguate
    |
 LL | fn c<C>(_: <C as Box>::Color) where C : Vehicle, C : Box {
-   |            ~~~~~~~~~~~~~~~~~
+   |            ~~~~~~~~~~~~
 help: use fully qualified syntax to disambiguate
    |
 LL | fn c<C>(_: <C as Vehicle>::Color) where C : Vehicle, C : Box {
-   |            ~~~~~~~~~~~~~~~~~~~~~
+   |            ~~~~~~~~~~~~~~~~
 
 error[E0221]: ambiguous associated type `Color` in bounds of `X`
   --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:35:20
@@ -76,11 +76,11 @@ LL |     fn e(&self, _: X::Color) where X : Box;
 help: use fully qualified syntax to disambiguate
    |
 LL |     fn e(&self, _: <X as Box>::Color) where X : Box;
-   |                    ~~~~~~~~~~~~~~~~~
+   |                    ~~~~~~~~~~~~
 help: use fully qualified syntax to disambiguate
    |
 LL |     fn e(&self, _: <X as Vehicle>::Color) where X : Box;
-   |                    ~~~~~~~~~~~~~~~~~~~~~
+   |                    ~~~~~~~~~~~~~~~~
 
 error[E0221]: ambiguous associated type `Color` in bounds of `X`
   --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:38:20
@@ -97,11 +97,11 @@ LL |     fn f(&self, _: X::Color) where X : Box { }
 help: use fully qualified syntax to disambiguate
    |
 LL |     fn f(&self, _: <X as Box>::Color) where X : Box { }
-   |                    ~~~~~~~~~~~~~~~~~
+   |                    ~~~~~~~~~~~~
 help: use fully qualified syntax to disambiguate
    |
 LL |     fn f(&self, _: <X as Vehicle>::Color) where X : Box { }
-   |                    ~~~~~~~~~~~~~~~~~~~~~
+   |                    ~~~~~~~~~~~~~~~~
 
 error[E0221]: ambiguous associated type `Color` in bounds of `X`
   --> $DIR/associated-type-projection-ambig-between-bound-and-where-clause.rs:30:20
@@ -118,11 +118,11 @@ LL |     fn d(&self, _: X::Color) where X : Box { }
 help: use fully qualified syntax to disambiguate
    |
 LL |     fn d(&self, _: <X as Box>::Color) where X : Box { }
-   |                    ~~~~~~~~~~~~~~~~~
+   |                    ~~~~~~~~~~~~
 help: use fully qualified syntax to disambiguate
    |
 LL |     fn d(&self, _: <X as Vehicle>::Color) where X : Box { }
-   |                    ~~~~~~~~~~~~~~~~~~~~~
+   |                    ~~~~~~~~~~~~~~~~
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr b/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr
index e6e95336bb5..66a4899c77f 100644
--- a/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr
+++ b/src/test/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr
@@ -21,11 +21,11 @@ LL | fn dent<C:BoxCar>(c: C, color: C::Color) {
 help: use fully qualified syntax to disambiguate
    |
 LL | fn dent<C:BoxCar>(c: C, color: <C as Vehicle>::Color) {
-   |                                ~~~~~~~~~~~~~~~~~~~~~
+   |                                ~~~~~~~~~~~~~~~~
 help: use fully qualified syntax to disambiguate
    |
 LL | fn dent<C:BoxCar>(c: C, color: <C as Box>::Color) {
-   |                                ~~~~~~~~~~~~~~~~~
+   |                                ~~~~~~~~~~~~
 
 error[E0222]: ambiguous associated type `Color` in bounds of `BoxCar`
   --> $DIR/associated-type-projection-from-multiple-supertraits.rs:23:37
@@ -74,11 +74,11 @@ LL | fn paint<C:BoxCar>(c: C, d: C::Color) {
 help: use fully qualified syntax to disambiguate
    |
 LL | fn paint<C:BoxCar>(c: C, d: <C as Vehicle>::Color) {
-   |                             ~~~~~~~~~~~~~~~~~~~~~
+   |                             ~~~~~~~~~~~~~~~~
 help: use fully qualified syntax to disambiguate
    |
 LL | fn paint<C:BoxCar>(c: C, d: <C as Box>::Color) {
-   |                             ~~~~~~~~~~~~~~~~~
+   |                             ~~~~~~~~~~~~
 
 error[E0191]: the value of the associated types `Color` (from trait `Box`), `Color` (from trait `Vehicle`) must be specified
   --> $DIR/associated-type-projection-from-multiple-supertraits.rs:32:32
diff --git a/src/test/ui/associated-types/associated-types-bound-failure.stderr b/src/test/ui/associated-types/associated-types-bound-failure.stderr
index edcd2bf85ad..e66c6b35ca1 100644
--- a/src/test/ui/associated-types/associated-types-bound-failure.stderr
+++ b/src/test/ui/associated-types/associated-types-bound-failure.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `<G as GetToInt>::R: ToInt` is not satisfied
   --> $DIR/associated-types-bound-failure.rs:19:19
    |
 LL |     ToInt::to_int(&g.get())
-   |                   ^^^^^^^^ the trait `ToInt` is not implemented for `<G as GetToInt>::R`
+   |     ------------- ^^^^^^^^ the trait `ToInt` is not implemented for `<G as GetToInt>::R`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by `ToInt::to_int`
   --> $DIR/associated-types-bound-failure.rs:6:5
diff --git a/src/test/ui/associated-types/associated-types-path-1.stderr b/src/test/ui/associated-types/associated-types-path-1.stderr
index 8f94b24e7b6..6512d60b2c2 100644
--- a/src/test/ui/associated-types/associated-types-path-1.stderr
+++ b/src/test/ui/associated-types/associated-types-path-1.stderr
@@ -19,11 +19,11 @@ LL | pub fn f2<T: Foo + Bar>(a: T, x: T::A) {}
 help: use fully qualified syntax to disambiguate
    |
 LL | pub fn f2<T: Foo + Bar>(a: T, x: <T as Bar>::A) {}
-   |                                  ~~~~~~~~~~~~~
+   |                                  ~~~~~~~~~~~~
 help: use fully qualified syntax to disambiguate
    |
 LL | pub fn f2<T: Foo + Bar>(a: T, x: <T as Foo>::A) {}
-   |                                  ~~~~~~~~~~~~~
+   |                                  ~~~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-types/associated-types-path-2.rs b/src/test/ui/associated-types/associated-types-path-2.rs
index c993e1d2720..912dedfdceb 100644
--- a/src/test/ui/associated-types/associated-types-path-2.rs
+++ b/src/test/ui/associated-types/associated-types-path-2.rs
@@ -28,13 +28,11 @@ pub fn f1_int_uint() {
 pub fn f1_uint_uint() {
     f1(2u32, 4u32);
     //~^ ERROR `u32: Foo` is not satisfied
-    //~| ERROR `u32: Foo` is not satisfied
 }
 
 pub fn f1_uint_int() {
     f1(2u32, 4i32);
     //~^ ERROR `u32: Foo` is not satisfied
-    //~| ERROR `u32: Foo` is not satisfied
 }
 
 pub fn f2_int() {
diff --git a/src/test/ui/associated-types/associated-types-path-2.stderr b/src/test/ui/associated-types/associated-types-path-2.stderr
index c4ea4ae6bc0..15a5245d54d 100644
--- a/src/test/ui/associated-types/associated-types-path-2.stderr
+++ b/src/test/ui/associated-types/associated-types-path-2.stderr
@@ -7,13 +7,15 @@ LL |     f1(2i32, 4i32);
 help: change the type of the numeric literal from `i32` to `u32`
    |
 LL |     f1(2i32, 4u32);
-   |              ~~~~
+   |               ~~~
 
 error[E0277]: the trait bound `u32: Foo` is not satisfied
-  --> $DIR/associated-types-path-2.rs:29:5
+  --> $DIR/associated-types-path-2.rs:29:14
    |
 LL |     f1(2u32, 4u32);
-   |     ^^ the trait `Foo` is not implemented for `u32`
+   |     --       ^^^^ the trait `Foo` is not implemented for `u32`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `f1`
   --> $DIR/associated-types-path-2.rs:13:14
@@ -22,16 +24,12 @@ LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
    |              ^^^ required by this bound in `f1`
 
 error[E0277]: the trait bound `u32: Foo` is not satisfied
-  --> $DIR/associated-types-path-2.rs:29:5
-   |
-LL |     f1(2u32, 4u32);
-   |     ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
-
-error[E0277]: the trait bound `u32: Foo` is not satisfied
-  --> $DIR/associated-types-path-2.rs:35:5
+  --> $DIR/associated-types-path-2.rs:34:14
    |
 LL |     f1(2u32, 4i32);
-   |     ^^ the trait `Foo` is not implemented for `u32`
+   |     --       ^^^^ the trait `Foo` is not implemented for `u32`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `f1`
   --> $DIR/associated-types-path-2.rs:13:14
@@ -39,14 +37,8 @@ note: required by a bound in `f1`
 LL | pub fn f1<T: Foo>(a: T, x: T::A) {}
    |              ^^^ required by this bound in `f1`
 
-error[E0277]: the trait bound `u32: Foo` is not satisfied
-  --> $DIR/associated-types-path-2.rs:35:5
-   |
-LL |     f1(2u32, 4i32);
-   |     ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `u32`
-
 error[E0308]: mismatched types
-  --> $DIR/associated-types-path-2.rs:41:18
+  --> $DIR/associated-types-path-2.rs:39:18
    |
 LL |     let _: i32 = f2(2i32);
    |            ---   ^^^^^^^^ expected `i32`, found `u32`
@@ -56,9 +48,9 @@ LL |     let _: i32 = f2(2i32);
 help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
    |
 LL |     let _: i32 = f2(2i32).try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                          ++++++++++++++++++++
 
-error: aborting due to 6 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0277, E0308.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr
index 989624bdd93..c508006c3a4 100644
--- a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr
+++ b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-fn.stderr
@@ -2,7 +2,12 @@ error[E0212]: cannot use the associated type of a trait with uninferred generic
   --> $DIR/associated-types-project-from-hrtb-in-fn.rs:13:8
    |
 LL |     x: I::A)
-   |        ^^^^ help: use a fully qualified path with inferred lifetimes: `<I as Foo<&isize>>::A`
+   |        ^^^^
+   |
+help: use a fully qualified path with inferred lifetimes
+   |
+LL |     x: <I as Foo<&isize>>::A)
+   |        ~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.stderr b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.stderr
index d457f9f8468..48433b15286 100644
--- a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.stderr
+++ b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-trait-method.stderr
@@ -2,13 +2,23 @@ error[E0212]: cannot use the associated type of a trait with uninferred generic
   --> $DIR/associated-types-project-from-hrtb-in-trait-method.rs:13:32
    |
 LL |     fn some_method(&self, arg: I::A);
-   |                                ^^^^ help: use a fully qualified path with inferred lifetimes: `<I as Foo<&isize>>::A`
+   |                                ^^^^
+   |
+help: use a fully qualified path with inferred lifetimes
+   |
+LL |     fn some_method(&self, arg: <I as Foo<&isize>>::A);
+   |                                ~~~~~~~~~~~~~~~~~~~~
 
 error[E0212]: cannot use the associated type of a trait with uninferred generic parameters
   --> $DIR/associated-types-project-from-hrtb-in-trait-method.rs:32:24
    |
 LL |     fn mango(&self) -> X::Assoc {
-   |                        ^^^^^^^^ help: use a fully qualified path with inferred lifetimes: `<X as Banana<'_>>::Assoc`
+   |                        ^^^^^^^^
+   |
+help: use a fully qualified path with inferred lifetimes
+   |
+LL |     fn mango(&self) -> <X as Banana<'_>>::Assoc {
+   |                        ~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr b/src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr
index e36572740f6..22daaf32910 100644
--- a/src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr
+++ b/src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
   --> $DIR/issue-27675-unchecked-bounds.rs:15:31
    |
 LL |     copy::<dyn Setup<From=T>>(t)
-   |                               ^ the trait `Copy` is not implemented for `T`
+   |     ------------------------- ^ the trait `Copy` is not implemented for `T`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `copy`
   --> $DIR/issue-27675-unchecked-bounds.rs:10:12
diff --git a/src/test/ui/associated-types/issue-36499.stderr b/src/test/ui/associated-types/issue-36499.stderr
index ff450f60acc..610798d880f 100644
--- a/src/test/ui/associated-types/issue-36499.stderr
+++ b/src/test/ui/associated-types/issue-36499.stderr
@@ -1,8 +1,14 @@
-error: expected expression, found `+`
+error: leading `+` is not supported
   --> $DIR/issue-36499.rs:4:9
    |
 LL |     2 + +2;
-   |         ^ expected expression
+   |         ^ unexpected `+`
+   |
+help: try removing the `+`
+   |
+LL -     2 + +2;
+LL +     2 + 2;
+   | 
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/async-await/issue-72442.stderr b/src/test/ui/async-await/issue-72442.stderr
index b79b6bc4492..919abf64603 100644
--- a/src/test/ui/async-await/issue-72442.stderr
+++ b/src/test/ui/async-await/issue-72442.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `Option<&str>: AsRef<Path>` is not satisfied
   --> $DIR/issue-72442.rs:12:36
    |
 LL |             let mut f = File::open(path.to_str())?;
-   |                                    ^^^^^^^^^^^^^ the trait `AsRef<Path>` is not implemented for `Option<&str>`
+   |                         ---------- ^^^^^^^^^^^^^ the trait `AsRef<Path>` is not implemented for `Option<&str>`
+   |                         |
+   |                         required by a bound introduced by this call
    |
 note: required by a bound in `File::open`
   --> $SRC_DIR/std/src/fs.rs:LL:COL
diff --git a/src/test/ui/async-await/issues/issue-54752-async-block.stderr b/src/test/ui/async-await/issues/issue-54752-async-block.stderr
index e39a049e2d3..0aea56ddb70 100644
--- a/src/test/ui/async-await/issues/issue-54752-async-block.stderr
+++ b/src/test/ui/async-await/issues/issue-54752-async-block.stderr
@@ -2,9 +2,14 @@ warning: unnecessary parentheses around assigned value
   --> $DIR/issue-54752-async-block.rs:6:22
    |
 LL | fn main() { let _a = (async  { }); }
-   |                      ^^^^^^^^^^^^ help: remove these parentheses
+   |                      ^          ^
    |
    = note: `#[warn(unused_parens)]` on by default
+help: remove these parentheses
+   |
+LL - fn main() { let _a = (async  { }); }
+LL + fn main() { let _a = async  { }; }
+   | 
 
 warning: 1 warning emitted
 
diff --git a/src/test/ui/borrowck/borrowck-unused-mut-locals.rs b/src/test/ui/borrowck/borrowck-unused-mut-locals.rs
index fd0e346e2b4..23ef975cbbc 100644
--- a/src/test/ui/borrowck/borrowck-unused-mut-locals.rs
+++ b/src/test/ui/borrowck/borrowck-unused-mut-locals.rs
@@ -1,4 +1,5 @@
 // run-pass
+#![allow(dead_code)]
 #![deny(unused_mut)]
 
 #[derive(Debug)]
diff --git a/src/test/ui/borrowck/issue-82462.nll.stderr b/src/test/ui/borrowck/issue-82462.nll.stderr
new file mode 100644
index 00000000000..10497c30e64
--- /dev/null
+++ b/src/test/ui/borrowck/issue-82462.nll.stderr
@@ -0,0 +1,22 @@
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/issue-82462.rs:18:9
+   |
+LL |     for x in DroppingSlice(&*v).iter() {
+   |              ------------------
+   |              |               |
+   |              |               immutable borrow occurs here
+   |              a temporary with access to the immutable borrow is created here ...
+LL |         v.push(*x);
+   |         ^ mutable borrow occurs here
+LL |         break;
+LL |     }
+   |     - ... and the immutable borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `DroppingSlice`
+   |
+help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
+   |
+LL |     };
+   |      +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/borrowck/issue-82462.rs b/src/test/ui/borrowck/issue-82462.rs
new file mode 100644
index 00000000000..5a3c64255cc
--- /dev/null
+++ b/src/test/ui/borrowck/issue-82462.rs
@@ -0,0 +1,21 @@
+struct DroppingSlice<'a>(&'a [i32]);
+
+impl Drop for DroppingSlice<'_> {
+    fn drop(&mut self) {
+        println!("hi from slice");
+    }
+}
+
+impl DroppingSlice<'_> {
+    fn iter(&self) -> std::slice::Iter<'_, i32> {
+        self.0.iter()
+    }
+}
+
+fn main() {
+    let mut v = vec![1, 2, 3, 4];
+    for x in DroppingSlice(&*v).iter() {
+        v.push(*x); //~ERROR
+        break;
+    }
+}
diff --git a/src/test/ui/borrowck/issue-82462.stderr b/src/test/ui/borrowck/issue-82462.stderr
new file mode 100644
index 00000000000..a2c291f7797
--- /dev/null
+++ b/src/test/ui/borrowck/issue-82462.stderr
@@ -0,0 +1,22 @@
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
+  --> $DIR/issue-82462.rs:18:9
+   |
+LL |     for x in DroppingSlice(&*v).iter() {
+   |              ------------------
+   |              |               |
+   |              |               immutable borrow occurs here
+   |              a temporary with access to the immutable borrow is created here ...
+LL |         v.push(*x);
+   |         ^^^^^^^^^^ mutable borrow occurs here
+LL |         break;
+LL |     }
+   |     - ... and the immutable borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `DroppingSlice`
+   |
+help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped
+   |
+LL |     };
+   |      +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
diff --git a/src/test/ui/box/into-boxed-slice-fail.stderr b/src/test/ui/box/into-boxed-slice-fail.stderr
index 5e3b43a47ee..2f1dec9d209 100644
--- a/src/test/ui/box/into-boxed-slice-fail.stderr
+++ b/src/test/ui/box/into-boxed-slice-fail.stderr
@@ -2,7 +2,9 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
   --> $DIR/into-boxed-slice-fail.rs:7:35
    |
 LL |     let _ = Box::into_boxed_slice(boxed_slice);
-   |                                   ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |             --------------------- ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `Sized` is not implemented for `[u8]`
 note: required by `Box::<T, A>::into_boxed_slice`
@@ -24,7 +26,9 @@ error[E0277]: the size for values of type `dyn Debug` cannot be known at compila
   --> $DIR/into-boxed-slice-fail.rs:11:35
    |
 LL |     let _ = Box::into_boxed_slice(boxed_trait);
-   |                                   ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |             --------------------- ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `Sized` is not implemented for `dyn Debug`
 note: required by `Box::<T, A>::into_boxed_slice`
diff --git a/src/test/ui/chalkify/type_inference.stderr b/src/test/ui/chalkify/type_inference.stderr
index a4a480ac64d..14d43c1474c 100644
--- a/src/test/ui/chalkify/type_inference.stderr
+++ b/src/test/ui/chalkify/type_inference.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `{float}: Bar` is not satisfied
   --> $DIR/type_inference.rs:27:14
    |
 LL |     only_bar(x);
-   |              ^ the trait `Bar` is not implemented for `{float}`
+   |     -------- ^ the trait `Bar` is not implemented for `{float}`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the following implementations were found:
              <i32 as Bar>
diff --git a/src/test/ui/closure-expected.stderr b/src/test/ui/closure-expected.stderr
index 6c77d080967..d4f23078043 100644
--- a/src/test/ui/closure-expected.stderr
+++ b/src/test/ui/closure-expected.stderr
@@ -2,7 +2,9 @@ error[E0277]: expected a `FnOnce<()>` closure, found `{integer}`
   --> $DIR/closure-expected.rs:3:23
    |
 LL |     let y = x.or_else(4);
-   |                       ^ expected an `FnOnce<()>` closure, found `{integer}`
+   |               ------- ^ expected an `FnOnce<()>` closure, found `{integer}`
+   |               |
+   |               required by a bound introduced by this call
    |
    = help: the trait `FnOnce<()>` is not implemented for `{integer}`
    = note: wrap the `{integer}` in a closure with no arguments: `|| { /* code */ }`
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.rs
index 1cc22fac352..3399bc0018e 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.rs
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.rs
@@ -3,6 +3,7 @@
 // check-pass
 #![allow(unreachable_code)]
 #![warn(unused)]
+#![allow(dead_code)]
 
 #[derive(Debug)]
 struct Point {
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr
index 4eac5a2d282..74109772724 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr
@@ -1,5 +1,5 @@
 warning: value captured by `a` is never read
-  --> $DIR/liveness.rs:23:9
+  --> $DIR/liveness.rs:24:9
    |
 LL |         a = 1;
    |         ^
@@ -13,7 +13,7 @@ LL | #![warn(unused)]
    = help: did you mean to capture by reference instead?
 
 warning: unused variable: `a`
-  --> $DIR/liveness.rs:32:9
+  --> $DIR/liveness.rs:33:9
    |
 LL |         a += 1;
    |         ^
@@ -27,7 +27,7 @@ LL | #![warn(unused)]
    = help: did you mean to capture by reference instead?
 
 warning: value assigned to `a` is never read
-  --> $DIR/liveness.rs:52:9
+  --> $DIR/liveness.rs:53:9
    |
 LL |         a += 1;
    |         ^
@@ -35,7 +35,7 @@ LL |         a += 1;
    = help: maybe it is overwritten before being read?
 
 warning: value assigned to `a` is never read
-  --> $DIR/liveness.rs:76:13
+  --> $DIR/liveness.rs:77:13
    |
 LL |             a = Some("d1");
    |             ^
@@ -43,7 +43,7 @@ LL |             a = Some("d1");
    = help: maybe it is overwritten before being read?
 
 warning: value assigned to `b` is never read
-  --> $DIR/liveness.rs:84:13
+  --> $DIR/liveness.rs:85:13
    |
 LL |             b = Some("e1");
    |             ^
@@ -51,7 +51,7 @@ LL |             b = Some("e1");
    = help: maybe it is overwritten before being read?
 
 warning: value assigned to `b` is never read
-  --> $DIR/liveness.rs:86:13
+  --> $DIR/liveness.rs:87:13
    |
 LL |             b = Some("e2");
    |             ^
@@ -59,7 +59,7 @@ LL |             b = Some("e2");
    = help: maybe it is overwritten before being read?
 
 warning: unused variable: `b`
-  --> $DIR/liveness.rs:84:13
+  --> $DIR/liveness.rs:85:13
    |
 LL |             b = Some("e1");
    |             ^
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs
index 10a7d07a1df..465c9476ba6 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.rs
@@ -2,6 +2,7 @@
 
 // check-pass
 #![warn(unused)]
+#![allow(dead_code)]
 
 #[derive(Debug)]
 struct MyStruct {
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr
index f74303e3dd6..11a440554f7 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr
@@ -1,5 +1,5 @@
 warning: value assigned to `a` is never read
-  --> $DIR/liveness_unintentional_copy.rs:19:9
+  --> $DIR/liveness_unintentional_copy.rs:20:9
    |
 LL |         a = s;
    |         ^
@@ -13,7 +13,7 @@ LL | #![warn(unused)]
    = help: maybe it is overwritten before being read?
 
 warning: unused variable: `a`
-  --> $DIR/liveness_unintentional_copy.rs:19:9
+  --> $DIR/liveness_unintentional_copy.rs:20:9
    |
 LL |         a = s;
    |         ^
@@ -27,7 +27,7 @@ LL | #![warn(unused)]
    = help: did you mean to capture by reference instead?
 
 warning: unused variable: `a`
-  --> $DIR/liveness_unintentional_copy.rs:35:9
+  --> $DIR/liveness_unintentional_copy.rs:36:9
    |
 LL |         a += x;
    |         ^
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs
index 045fe78040a..ed222b3148f 100644
--- a/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs
+++ b/src/test/ui/closures/2229_closure_analysis/run_pass/struct-pattern-matching-with-methods.rs
@@ -1,6 +1,7 @@
 // edition:2021
 //check-pass
 #![warn(unused)]
+#![allow(dead_code)]
 #![feature(rustc_attrs)]
 
 #[derive(Debug, Clone, Copy)]
diff --git a/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs b/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs
index 8e4f91c27e2..3f7ddf93f06 100644
--- a/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs
+++ b/src/test/ui/closures/2229_closure_analysis/run_pass/unsafe_ptr.rs
@@ -3,6 +3,8 @@
 
 // Test that we can use raw ptrs when using `capture_disjoint_fields`.
 
+#![allow(dead_code)]
+
 #[derive(Debug)]
 struct S {
     s: String,
diff --git a/src/test/ui/closures/closure-bounds-subtype.stderr b/src/test/ui/closures/closure-bounds-subtype.stderr
index bfea4979dec..1a40326d986 100644
--- a/src/test/ui/closures/closure-bounds-subtype.stderr
+++ b/src/test/ui/closures/closure-bounds-subtype.stderr
@@ -2,7 +2,9 @@ error[E0277]: `F` cannot be shared between threads safely
   --> $DIR/closure-bounds-subtype.rs:13:22
    |
 LL |     take_const_owned(f);
-   |                      ^ `F` cannot be shared between threads safely
+   |     ---------------- ^ `F` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `take_const_owned`
   --> $DIR/closure-bounds-subtype.rs:4:50
diff --git a/src/test/ui/closures/coerce-unsafe-to-closure.stderr b/src/test/ui/closures/coerce-unsafe-to-closure.stderr
index ab035d03b05..4a47e054915 100644
--- a/src/test/ui/closures/coerce-unsafe-to-closure.stderr
+++ b/src/test/ui/closures/coerce-unsafe-to-closure.stderr
@@ -2,7 +2,9 @@ error[E0277]: expected a `FnOnce<(&str,)>` closure, found `unsafe extern "rust-i
   --> $DIR/coerce-unsafe-to-closure.rs:2:44
    |
 LL |     let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
-   |                                            ^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&str,)>` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
+   |                                        --- ^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&str,)>` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
+   |                                        |
+   |                                        required by a bound introduced by this call
    |
    = help: the trait `FnOnce<(&str,)>` is not implemented for `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
 
diff --git a/src/test/ui/coercion/issue-88097.rs b/src/test/ui/coercion/issue-88097.rs
new file mode 100644
index 00000000000..e543e1bae92
--- /dev/null
+++ b/src/test/ui/coercion/issue-88097.rs
@@ -0,0 +1,31 @@
+// In #88097, the compiler attempted to coerce a closure type to itself via
+// a function pointer, which caused an unnecessary error. Check that this
+// behavior has been fixed.
+
+// check-pass
+
+fn peculiar() -> impl Fn(u8) -> u8 {
+    return |x| x + 1
+}
+
+fn peculiar2() -> impl Fn(u8) -> u8 {
+    return |x| x + 1;
+}
+
+fn peculiar3() -> impl Fn(u8) -> u8 {
+    let f = |x| x + 1;
+    return f
+}
+
+fn peculiar4() -> impl Fn(u8) -> u8 {
+    let f = |x| x + 1;
+    f
+}
+
+fn peculiar5() -> impl Fn(u8) -> u8 {
+    let f = |x| x + 1;
+    let g = |x| x + 2;
+    return if true { f } else { g }
+}
+
+fn main() {}
diff --git a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr
index a2b779e2954..e9090c1b6bc 100644
--- a/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr
+++ b/src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.stderr
@@ -4,7 +4,6 @@ error[E0038]: the trait `NotObjectSafe` cannot be made into an object
 LL | impl NotObjectSafe for dyn NotObjectSafe { }
    |                        ^^^^^^^^^^^^^^^^^ `NotObjectSafe` cannot be made into an object
    |
-   = help: consider moving `eq` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:6:43
    |
@@ -12,6 +11,7 @@ LL | trait NotObjectSafe { fn eq(&self, other: Self); }
    |       -------------                       ^^^^ ...because method `eq` references the `Self` type in this parameter
    |       |
    |       this trait cannot be made into an object...
+   = help: consider moving `eq` to another trait
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr b/src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr
index cf842b19085..2e2dac288a1 100644
--- a/src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr
+++ b/src/test/ui/coherence/coherence-unsafe-trait-object-impl.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `&dyn Trait: Trait` is not satisfied
   --> $DIR/coherence-unsafe-trait-object-impl.rs:15:13
    |
 LL |     takes_t(t);
-   |             ^ the trait `Trait` is not implemented for `&dyn Trait`
+   |     ------- ^ the trait `Trait` is not implemented for `&dyn Trait`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `takes_t`
   --> $DIR/coherence-unsafe-trait-object-impl.rs:10:15
diff --git a/src/test/ui/const-generics/broken-mir-2.rs b/src/test/ui/const-generics/broken-mir-2.rs
index f9e03151374..9d62281178c 100644
--- a/src/test/ui/const-generics/broken-mir-2.rs
+++ b/src/test/ui/const-generics/broken-mir-2.rs
@@ -1,4 +1,7 @@
 // run-pass
+
+#![allow(dead_code)]
+
 use std::fmt::Debug;
 
 #[derive(Debug)]
diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs b/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs
new file mode 100644
index 00000000000..916d60c0e0d
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.rs
@@ -0,0 +1,11 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+fn foo<const N: u8>(a: [(); N as usize]) {
+    bar::<{ N as usize as usize }>();
+    //~^ error: unconstrained generic constant
+}
+
+fn bar<const N: usize>() {}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr b/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr
new file mode 100644
index 00000000000..d48b639dbde
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr
@@ -0,0 +1,10 @@
+error: unconstrained generic constant
+  --> $DIR/abstract-consts-as-cast-5.rs:5:11
+   |
+LL |     bar::<{ N as usize as usize }>();
+   |           ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { N as usize as usize }]:`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr b/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr
index deb6f3bd12c..9b3c32a9397 100644
--- a/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr
@@ -10,7 +10,7 @@ error: overly complex generic constant
   --> $DIR/array-size-in-generic-struct-param.rs:19:15
    |
 LL |     arr: [u8; CFG.arr_size],
-   |               ^^^^^^^^^^^^ unsupported projection
+   |               ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
    |
    = help: consider moving this anonymous constant into a `const` function
 
diff --git a/src/test/ui/const-generics/generic_const_exprs/closures.stderr b/src/test/ui/const-generics/generic_const_exprs/closures.stderr
index 9f0b7252e83..95dae4ecc04 100644
--- a/src/test/ui/const-generics/generic_const_exprs/closures.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/closures.stderr
@@ -4,7 +4,7 @@ error: overly complex generic constant
 LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
    |                                   ^^^^-------^^
    |                                       |
-   |                                       unsupported rvalue
+   |                                       unsupported operation in generic constant, this may be supported in the future
    |
    = help: consider moving this anonymous constant into a `const` function
 
diff --git a/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr b/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr
index 5749defb3e1..c9f84799522 100644
--- a/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr
@@ -2,9 +2,7 @@ error: overly complex generic constant
   --> $DIR/let-bindings.rs:6:68
    |
 LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
-   |                                                                    ^^^^^^-^^^^^^^^^^^^^
-   |                                                                          |
-   |                                                                          unsupported statement
+   |                                                                    ^^^^^^^^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
    |
    = help: consider moving this anonymous constant into a `const` function
 
@@ -12,9 +10,7 @@ error: overly complex generic constant
   --> $DIR/let-bindings.rs:6:35
    |
 LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
-   |                                   ^^^^^^-^^^^^^^^^^^^^
-   |                                         |
-   |                                         unsupported statement
+   |                                   ^^^^^^^^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
    |
    = help: consider moving this anonymous constant into a `const` function
 
diff --git a/src/test/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr b/src/test/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr
index 319e6c2c032..4e1d71f1545 100644
--- a/src/test/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/object-safety-err-ret.stderr
@@ -4,7 +4,6 @@ error[E0038]: the trait `Foo` cannot be made into an object
 LL | fn use_dyn(v: &dyn Foo) {
    |                ^^^^^^^ `Foo` cannot be made into an object
    |
-   = help: consider moving `test` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/object-safety-err-ret.rs:8:23
    |
@@ -12,6 +11,7 @@ LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn test(&self) -> [u8; bar::<Self>()];
    |                       ^^^^^^^^^^^^^^^^^^^ ...because method `test` references the `Self` type in its return type
+   = help: consider moving `test` to another trait
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs b/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs
new file mode 100644
index 00000000000..c0404d35b08
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.rs
@@ -0,0 +1,35 @@
+#![feature(generic_const_exprs, adt_const_params, const_trait_impl)]
+#![allow(incomplete_features)]
+
+// test `N + N` unifies with explicit function calls for non-builtin-types
+#[derive(PartialEq, Eq)]
+struct Foo(u8);
+
+impl const std::ops::Add for Foo {
+    type Output = Self;
+
+    fn add(self, rhs: Self) -> Self::Output {
+        self
+    }
+}
+
+struct Evaluatable<const N: Foo>;
+
+fn foo<const N: Foo>(a: Evaluatable<{ N + N }>) {
+    bar::<{ std::ops::Add::add(N, N) }>();
+}
+
+fn bar<const N: Foo>() {}
+
+// test that `N + N` unifies with explicit function calls for builin-types
+struct Evaluatable2<const N: usize>;
+
+fn foo2<const N: usize>(a: Evaluatable2<{ N + N }>) {
+    bar2::<{ std::ops::Add::add(N, N) }>();
+    //~^ error: unconstrained generic constant
+    // FIXME(generic_const_exprs) make this not an error
+}
+
+fn bar2<const N: usize>() {}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr b/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr
new file mode 100644
index 00000000000..d18c7916f5f
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr
@@ -0,0 +1,10 @@
+error: unconstrained generic constant
+  --> $DIR/unify-op-with-fn-call.rs:28:12
+   |
+LL |     bar2::<{ std::ops::Add::add(N, N) }>();
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { std::ops::Add::add(N, N) }]:`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr b/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr
index 1687dbbcbe3..3da91b19a5e 100644
--- a/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr
@@ -2,9 +2,7 @@ error: overly complex generic constant
   --> $DIR/unused_expr.rs:4:34
    |
 LL | fn add<const N: usize>() -> [u8; { N + 1; 5 }] {
-   |                                  ^^-----^^^^^
-   |                                    |
-   |                                    dead code
+   |                                  ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
    |
    = help: consider moving this anonymous constant into a `const` function
 
@@ -12,9 +10,7 @@ error: overly complex generic constant
   --> $DIR/unused_expr.rs:9:34
    |
 LL | fn div<const N: usize>() -> [u8; { N / 1; 5 }] {
-   |                                  ^^-----^^^^^
-   |                                    |
-   |                                    dead code
+   |                                  ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
    |
    = help: consider moving this anonymous constant into a `const` function
 
@@ -22,9 +18,7 @@ error: overly complex generic constant
   --> $DIR/unused_expr.rs:16:38
    |
 LL | fn fn_call<const N: usize>() -> [u8; { foo(N); 5 }] {
-   |                                      ^^------^^^^^
-   |                                        |
-   |                                        dead code
+   |                                      ^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
    |
    = help: consider moving this anonymous constant into a `const` function
 
diff --git a/src/test/ui/const-generics/issues/issue-67375.full.stderr b/src/test/ui/const-generics/issues/issue-67375.full.stderr
index 5386ef56a24..d7b52063dc4 100644
--- a/src/test/ui/const-generics/issues/issue-67375.full.stderr
+++ b/src/test/ui/const-generics/issues/issue-67375.full.stderr
@@ -2,9 +2,9 @@ error: overly complex generic constant
   --> $DIR/issue-67375.rs:7:17
    |
 LL |     inner: [(); { [|_: &T| {}; 0].len() }],
-   |                 ^^^----------^^^^^^^^^^^^
-   |                    |
-   |                    unsupported rvalue
+   |                 ^^---------------^^^^^^^^
+   |                   |
+   |                   unsupported operation in generic constant
    |
    = help: consider moving this anonymous constant into a `const` function
 
diff --git a/src/test/ui/const-generics/issues/issue-67945-2.full.stderr b/src/test/ui/const-generics/issues/issue-67945-2.full.stderr
index 118cf447c01..fe0351a8292 100644
--- a/src/test/ui/const-generics/issues/issue-67945-2.full.stderr
+++ b/src/test/ui/const-generics/issues/issue-67945-2.full.stderr
@@ -5,11 +5,10 @@ LL |       A: [(); {
    |  _____________^
 LL | |
 LL | |         let x: Option<Box<Self>> = None;
-   | |                                    ---- unsupported rvalue
 LL | |
 LL | |         0
 LL | |     }],
-   | |_____^
+   | |_____^ unsupported operation in generic constant, this may be supported in the future
    |
    = help: consider moving this anonymous constant into a `const` function
 
diff --git a/src/test/ui/const-generics/issues/issue-86530.stderr b/src/test/ui/const-generics/issues/issue-86530.stderr
index 7cdfc9dfcdf..c63857b2314 100644
--- a/src/test/ui/const-generics/issues/issue-86530.stderr
+++ b/src/test/ui/const-generics/issues/issue-86530.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `&str: X` is not satisfied
   --> $DIR/issue-86530.rs:16:7
    |
 LL |     z(" ");
-   |       ^^^ the trait `X` is not implemented for `&str`
+   |     - ^^^ the trait `X` is not implemented for `&str`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `z`
   --> $DIR/issue-86530.rs:10:8
diff --git a/src/test/ui/const-generics/type-dependent/type-mismatch.full.stderr b/src/test/ui/const-generics/type-dependent/type-mismatch.full.stderr
index 02108d85960..70bc6405798 100644
--- a/src/test/ui/const-generics/type-dependent/type-mismatch.full.stderr
+++ b/src/test/ui/const-generics/type-dependent/type-mismatch.full.stderr
@@ -7,7 +7,7 @@ LL |     assert_eq!(R.method::<1u16>(), 1);
 help: change the type of the numeric literal from `u16` to `u8`
    |
 LL |     assert_eq!(R.method::<1u8>(), 1);
-   |                           ~~~
+   |                            ~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/type-dependent/type-mismatch.min.stderr b/src/test/ui/const-generics/type-dependent/type-mismatch.min.stderr
index 02108d85960..70bc6405798 100644
--- a/src/test/ui/const-generics/type-dependent/type-mismatch.min.stderr
+++ b/src/test/ui/const-generics/type-dependent/type-mismatch.min.stderr
@@ -7,7 +7,7 @@ LL |     assert_eq!(R.method::<1u16>(), 1);
 help: change the type of the numeric literal from `u16` to `u8`
    |
 LL |     assert_eq!(R.method::<1u8>(), 1);
-   |                           ~~~
+   |                            ~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/unused_braces.stderr b/src/test/ui/const-generics/unused_braces.stderr
index 5e1bace5492..533fcabd418 100644
--- a/src/test/ui/const-generics/unused_braces.stderr
+++ b/src/test/ui/const-generics/unused_braces.stderr
@@ -2,13 +2,18 @@ warning: unnecessary braces around const expression
   --> $DIR/unused_braces.rs:9:14
    |
 LL |     let _: A<{ 7 }>;
-   |              ^^^^^ help: remove these braces
+   |              ^^ ^^
    |
 note: the lint level is defined here
   --> $DIR/unused_braces.rs:3:9
    |
 LL | #![warn(unused_braces)]
    |         ^^^^^^^^^^^^^
+help: remove these braces
+   |
+LL -     let _: A<{ 7 }>;
+LL +     let _: A<7>;
+   | 
 
 warning: 1 warning emitted
 
diff --git a/src/test/ui/consts/issue-88649.rs b/src/test/ui/consts/issue-88649.rs
new file mode 100644
index 00000000000..43e562b5a7d
--- /dev/null
+++ b/src/test/ui/consts/issue-88649.rs
@@ -0,0 +1,18 @@
+// check-pass
+#![crate_type = "lib"]
+
+enum Foo {
+    Variant1(bool),
+    Variant2(bool),
+}
+
+const _: () = {
+    let mut n = 0;
+    while n < 2 {
+        match Foo::Variant1(true) {
+            Foo::Variant1(x) | Foo::Variant2(x) if x => {}
+            _ => {}
+        }
+        n += 1;
+    }
+};
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
index fcbf39d3869..d1c2a04d6a6 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
@@ -214,6 +214,9 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl
    |
 LL | impl<T: std::fmt::Debug> Foo<T> {
    |      ^
+LL |
+LL |     const fn foo(&self) {}
+   |     ------------------- function declared as const here
    |
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
@@ -223,6 +226,9 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl
    |
 LL | impl<T: std::fmt::Debug + Sized> Foo<T> {
    |      ^
+LL |
+LL |     const fn foo2(&self) {}
+   |     -------------------- function declared as const here
    |
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
@@ -232,6 +238,9 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl
    |
 LL | impl<T: Sync + Sized> Foo<T> {
    |      ^
+LL |
+LL |     const fn foo3(&self) {}
+   |     -------------------- function declared as const here
    |
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
@@ -292,7 +301,9 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl
   --> $DIR/min_const_fn.rs:139:41
    |
 LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 }
-   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | -------------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | function declared as const here
    |
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
@@ -301,7 +312,9 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl
   --> $DIR/min_const_fn.rs:139:42
    |
 LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 }
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | -------------------------------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | function declared as const here
    |
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
@@ -310,7 +323,9 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl
   --> $DIR/min_const_fn.rs:139:42
    |
 LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 }
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | -------------------------------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | function declared as const here
    |
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr
index ce844a2f071..2cad8a862be 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr
@@ -1,6 +1,8 @@
 error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn_dyn.rs:9:5
    |
+LL | const fn no_inner_dyn_trait2(x: Hide) {
+   | ------------------------------------- function declared as const here
 LL |     x.0.field;
    |     ^^^^^^^^^
    |
@@ -11,7 +13,9 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl
   --> $DIR/min_const_fn_dyn.rs:12:66
    |
 LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
-   |                                                                  ^^
+   | -----------------------------------------                        ^^
+   | |
+   | function declared as const here
    |
    = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
    = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable
diff --git a/src/test/ui/derives/clone-debug-dead-code.rs b/src/test/ui/derives/clone-debug-dead-code.rs
new file mode 100644
index 00000000000..80e91320939
--- /dev/null
+++ b/src/test/ui/derives/clone-debug-dead-code.rs
@@ -0,0 +1,45 @@
+// Checks that derived implementations of Clone and Debug do not
+// contribute to dead code analysis (issue #84647).
+
+#![forbid(dead_code)]
+
+struct A { f: () }
+//~^ ERROR: field is never read: `f`
+
+#[derive(Clone)]
+struct B { f: () }
+//~^ ERROR: field is never read: `f`
+
+#[derive(Debug)]
+struct C { f: () }
+//~^ ERROR: field is never read: `f`
+
+#[derive(Debug,Clone)]
+struct D { f: () }
+//~^ ERROR: field is never read: `f`
+
+struct E { f: () }
+//~^ ERROR: field is never read: `f`
+// Custom impl, still doesn't read f
+impl Clone for E {
+    fn clone(&self) -> Self {
+        Self { f: () }
+    }
+}
+
+struct F { f: () }
+// Custom impl that actually reads f
+impl Clone for F {
+    fn clone(&self) -> Self {
+        Self { f: self.f }
+    }
+}
+
+fn main() {
+    let _ = A { f: () };
+    let _ = B { f: () };
+    let _ = C { f: () };
+    let _ = D { f: () };
+    let _ = E { f: () };
+    let _ = F { f: () };
+}
diff --git a/src/test/ui/derives/clone-debug-dead-code.stderr b/src/test/ui/derives/clone-debug-dead-code.stderr
new file mode 100644
index 00000000000..226007f3647
--- /dev/null
+++ b/src/test/ui/derives/clone-debug-dead-code.stderr
@@ -0,0 +1,38 @@
+error: field is never read: `f`
+  --> $DIR/clone-debug-dead-code.rs:6:12
+   |
+LL | struct A { f: () }
+   |            ^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/clone-debug-dead-code.rs:4:11
+   |
+LL | #![forbid(dead_code)]
+   |           ^^^^^^^^^
+
+error: field is never read: `f`
+  --> $DIR/clone-debug-dead-code.rs:10:12
+   |
+LL | struct B { f: () }
+   |            ^^^^^
+
+error: field is never read: `f`
+  --> $DIR/clone-debug-dead-code.rs:14:12
+   |
+LL | struct C { f: () }
+   |            ^^^^^
+
+error: field is never read: `f`
+  --> $DIR/clone-debug-dead-code.rs:18:12
+   |
+LL | struct D { f: () }
+   |            ^^^^^
+
+error: field is never read: `f`
+  --> $DIR/clone-debug-dead-code.rs:21:12
+   |
+LL | struct E { f: () }
+   |            ^^^^^
+
+error: aborting due to 5 previous errors
+
diff --git a/src/test/ui/derives/deriving-copyclone.stderr b/src/test/ui/derives/deriving-copyclone.stderr
index ecdbbff4d97..2538b5533a6 100644
--- a/src/test/ui/derives/deriving-copyclone.stderr
+++ b/src/test/ui/derives/deriving-copyclone.stderr
@@ -2,10 +2,11 @@ error[E0277]: the trait bound `C: Copy` is not satisfied
   --> $DIR/deriving-copyclone.rs:31:13
    |
 LL |     is_copy(B { a: 1, b: C });
-   |             ^^^^^^^^^^^^^^^^
-   |             |
-   |             expected an implementor of trait `Copy`
-   |             help: consider borrowing here: `&B { a: 1, b: C }`
+   |     ------- ^^^^^^^^^^^^^^^^
+   |     |       |
+   |     |       expected an implementor of trait `Copy`
+   |     |       help: consider borrowing here: `&B { a: 1, b: C }`
+   |     required by a bound introduced by this call
    |
 note: required because of the requirements on the impl of `Copy` for `B<C>`
   --> $DIR/deriving-copyclone.rs:9:10
@@ -23,10 +24,11 @@ error[E0277]: the trait bound `C: Clone` is not satisfied
   --> $DIR/deriving-copyclone.rs:32:14
    |
 LL |     is_clone(B { a: 1, b: C });
-   |              ^^^^^^^^^^^^^^^^
-   |              |
-   |              expected an implementor of trait `Clone`
-   |              help: consider borrowing here: `&B { a: 1, b: C }`
+   |     -------- ^^^^^^^^^^^^^^^^
+   |     |        |
+   |     |        expected an implementor of trait `Clone`
+   |     |        help: consider borrowing here: `&B { a: 1, b: C }`
+   |     required by a bound introduced by this call
    |
 note: required because of the requirements on the impl of `Clone` for `B<C>`
   --> $DIR/deriving-copyclone.rs:9:16
@@ -44,10 +46,11 @@ error[E0277]: the trait bound `D: Copy` is not satisfied
   --> $DIR/deriving-copyclone.rs:35:13
    |
 LL |     is_copy(B { a: 1, b: D });
-   |             ^^^^^^^^^^^^^^^^
-   |             |
-   |             expected an implementor of trait `Copy`
-   |             help: consider borrowing here: `&B { a: 1, b: D }`
+   |     ------- ^^^^^^^^^^^^^^^^
+   |     |       |
+   |     |       expected an implementor of trait `Copy`
+   |     |       help: consider borrowing here: `&B { a: 1, b: D }`
+   |     required by a bound introduced by this call
    |
 note: required because of the requirements on the impl of `Copy` for `B<D>`
   --> $DIR/deriving-copyclone.rs:9:10
diff --git a/src/test/ui/deriving/deriving-clone-generic-struct.rs b/src/test/ui/deriving/deriving-clone-generic-struct.rs
index f6e105555fd..4374d1594e4 100644
--- a/src/test/ui/deriving/deriving-clone-generic-struct.rs
+++ b/src/test/ui/deriving/deriving-clone-generic-struct.rs
@@ -1,6 +1,8 @@
 // run-pass
 // pretty-expanded FIXME #23616
 
+#![allow(dead_code)]
+
 #[derive(Clone)]
 struct S<T> {
     foo: (),
diff --git a/src/test/ui/deriving/deriving-clone-struct.rs b/src/test/ui/deriving/deriving-clone-struct.rs
index 7b0a1d20260..b93cbe5f8b6 100644
--- a/src/test/ui/deriving/deriving-clone-struct.rs
+++ b/src/test/ui/deriving/deriving-clone-struct.rs
@@ -1,6 +1,8 @@
 // run-pass
 // pretty-expanded FIXME #23616
 
+#![allow(dead_code)]
+
 #[derive(Clone)]
 struct S {
     _int: isize,
diff --git a/src/test/ui/deriving/deriving-clone-tuple-struct.rs b/src/test/ui/deriving/deriving-clone-tuple-struct.rs
index 166f1be55e0..7ad3f034713 100644
--- a/src/test/ui/deriving/deriving-clone-tuple-struct.rs
+++ b/src/test/ui/deriving/deriving-clone-tuple-struct.rs
@@ -1,6 +1,8 @@
 // run-pass
 // pretty-expanded FIXME #23616
 
+#![allow(dead_code)]
+
 #[derive(Clone)]
 struct S((), ());
 
diff --git a/src/test/ui/deriving/deriving-in-fn.rs b/src/test/ui/deriving/deriving-in-fn.rs
index 8931e94a4f8..07f91d05973 100644
--- a/src/test/ui/deriving/deriving-in-fn.rs
+++ b/src/test/ui/deriving/deriving-in-fn.rs
@@ -1,4 +1,7 @@
 // run-pass
+
+#![allow(dead_code)]
+
 pub fn main() {
     #[derive(Debug)]
     struct Foo {
diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
index fcb4ea1d592..c7458916c53 100644
--- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
+++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `i8: Foo<i32>` is not satisfied
   --> $DIR/issue-39802-show-5-trait-impls.rs:24:21
    |
 LL |     Foo::<i32>::bar(&1i8);
-   |                     ^^^^ the trait `Foo<i32>` is not implemented for `i8`
+   |     --------------- ^^^^ the trait `Foo<i32>` is not implemented for `i8`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the following implementations were found:
              <i8 as Foo<bool>>
@@ -20,7 +22,9 @@ error[E0277]: the trait bound `u8: Foo<i32>` is not satisfied
   --> $DIR/issue-39802-show-5-trait-impls.rs:25:21
    |
 LL |     Foo::<i32>::bar(&1u8);
-   |                     ^^^^ the trait `Foo<i32>` is not implemented for `u8`
+   |     --------------- ^^^^ the trait `Foo<i32>` is not implemented for `u8`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the following implementations were found:
              <u8 as Foo<bool>>
@@ -37,7 +41,9 @@ error[E0277]: the trait bound `bool: Foo<i32>` is not satisfied
   --> $DIR/issue-39802-show-5-trait-impls.rs:26:21
    |
 LL |     Foo::<i32>::bar(&true);
-   |                     ^^^^^ the trait `Foo<i32>` is not implemented for `bool`
+   |     --------------- ^^^^^ the trait `Foo<i32>` is not implemented for `bool`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the following implementations were found:
              <bool as Foo<bool>>
diff --git a/src/test/ui/discrim/discrim-ill-typed.stderr b/src/test/ui/discrim/discrim-ill-typed.stderr
index 3d8049cba9c..27f516341ee 100644
--- a/src/test/ui/discrim/discrim-ill-typed.stderr
+++ b/src/test/ui/discrim/discrim-ill-typed.stderr
@@ -7,7 +7,7 @@ LL |         OhNo = 0_u8,
 help: change the type of the numeric literal from `u8` to `i8`
    |
 LL |         OhNo = 0_i8,
-   |                ~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/discrim-ill-typed.rs:28:16
@@ -18,7 +18,7 @@ LL |         OhNo = 0_i8,
 help: change the type of the numeric literal from `i8` to `u8`
    |
 LL |         OhNo = 0_u8,
-   |                ~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/discrim-ill-typed.rs:41:16
@@ -29,7 +29,7 @@ LL |         OhNo = 0_u16,
 help: change the type of the numeric literal from `u16` to `i16`
    |
 LL |         OhNo = 0_i16,
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/discrim-ill-typed.rs:54:16
@@ -40,7 +40,7 @@ LL |         OhNo = 0_i16,
 help: change the type of the numeric literal from `i16` to `u16`
    |
 LL |         OhNo = 0_u16,
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/discrim-ill-typed.rs:67:16
@@ -51,7 +51,7 @@ LL |         OhNo = 0_u32,
 help: change the type of the numeric literal from `u32` to `i32`
    |
 LL |         OhNo = 0_i32,
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/discrim-ill-typed.rs:80:16
@@ -62,7 +62,7 @@ LL |         OhNo = 0_i32,
 help: change the type of the numeric literal from `i32` to `u32`
    |
 LL |         OhNo = 0_u32,
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/discrim-ill-typed.rs:93:16
@@ -73,7 +73,7 @@ LL |         OhNo = 0_u64,
 help: change the type of the numeric literal from `u64` to `i64`
    |
 LL |         OhNo = 0_i64,
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/discrim-ill-typed.rs:106:16
@@ -84,7 +84,7 @@ LL |         OhNo = 0_i64,
 help: change the type of the numeric literal from `i64` to `u64`
    |
 LL |         OhNo = 0_u64,
-   |                ~~~~~
+   |                  ~~~
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/enum-discriminant/niche-prefer-zero.rs b/src/test/ui/enum-discriminant/niche-prefer-zero.rs
new file mode 100644
index 00000000000..f20607a8903
--- /dev/null
+++ b/src/test/ui/enum-discriminant/niche-prefer-zero.rs
@@ -0,0 +1,14 @@
+// Check that niche selection prefers zero.
+// See https://github.com/rust-lang/rust/pull/87794
+// run-pass
+#[repr(u8)]
+pub enum Size {
+    One = 1,
+    Two = 2,
+    Three = 3,
+}
+
+fn main() {
+    // check that `None` is zero
+    assert_eq!(0, unsafe { std::mem::transmute::<Option<Size>, u8>(None) });
+}
diff --git a/src/test/ui/error-codes/E0038.stderr b/src/test/ui/error-codes/E0038.stderr
index cead9776e4a..3773d6f5234 100644
--- a/src/test/ui/error-codes/E0038.stderr
+++ b/src/test/ui/error-codes/E0038.stderr
@@ -4,7 +4,6 @@ error[E0038]: the trait `Trait` cannot be made into an object
 LL | fn call_foo(x: Box<dyn Trait>) {
    |                    ^^^^^^^^^ `Trait` cannot be made into an object
    |
-   = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/E0038.rs:2:22
    |
@@ -12,6 +11,7 @@ LL | trait Trait {
    |       ----- this trait cannot be made into an object...
 LL |     fn foo(&self) -> Self;
    |                      ^^^^ ...because method `foo` references the `Self` type in its return type
+   = help: consider moving `foo` to another trait
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0221.stderr b/src/test/ui/error-codes/E0221.stderr
index 86966d520e7..f3dbf122de3 100644
--- a/src/test/ui/error-codes/E0221.stderr
+++ b/src/test/ui/error-codes/E0221.stderr
@@ -13,11 +13,11 @@ LL |         let _: Self::A;
 help: use fully qualified syntax to disambiguate
    |
 LL |         let _: <Self as Foo>::A;
-   |                ~~~~~~~~~~~~~~~~
+   |                ~~~~~~~~~~~~~~~
 help: use fully qualified syntax to disambiguate
    |
 LL |         let _: <Self as Bar>::A;
-   |                ~~~~~~~~~~~~~~~~
+   |                ~~~~~~~~~~~~~~~
 
 error[E0221]: ambiguous associated type `Err` in bounds of `Self`
   --> $DIR/E0221.rs:21:16
@@ -26,12 +26,13 @@ LL |     type Err: T3;
    |     ------------- ambiguous `Err` from `My`
 LL |     fn test() {
 LL |         let _: Self::Err;
-   |                ^^^^^^^^^
-   |                |
-   |                ambiguous associated type `Err`
-   |                help: use fully qualified syntax to disambiguate: `<Self as My>::Err`
+   |                ^^^^^^^^^ ambiguous associated type `Err`
    |
    = note: associated type `Self` could derive from `FromStr`
+help: use fully qualified syntax to disambiguate
+   |
+LL |         let _: <Self as My>::Err;
+   |                ~~~~~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/error-codes/E0277.stderr b/src/test/ui/error-codes/E0277.stderr
index c82665aa580..2b4784d7ecc 100644
--- a/src/test/ui/error-codes/E0277.stderr
+++ b/src/test/ui/error-codes/E0277.stderr
@@ -16,7 +16,9 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied
   --> $DIR/E0277.rs:15:15
    |
 LL |     some_func(5i32);
-   |               ^^^^ the trait `Foo` is not implemented for `i32`
+   |     --------- ^^^^ the trait `Foo` is not implemented for `i32`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `some_func`
   --> $DIR/E0277.rs:7:17
diff --git a/src/test/ui/error-should-say-copy-not-pod.stderr b/src/test/ui/error-should-say-copy-not-pod.stderr
index 8c6025e708e..637eb27db01 100644
--- a/src/test/ui/error-should-say-copy-not-pod.stderr
+++ b/src/test/ui/error-should-say-copy-not-pod.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
   --> $DIR/error-should-say-copy-not-pod.rs:6:17
    |
 LL |     check_bound("nocopy".to_string());
-   |                 ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+   |     ----------- ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check_bound`
   --> $DIR/error-should-say-copy-not-pod.rs:3:18
diff --git a/src/test/ui/expr/malformed_closure/missing_braces_around_block.fixed b/src/test/ui/expr/malformed_closure/missing_braces_around_block.fixed
new file mode 100644
index 00000000000..c50b9a12b6d
--- /dev/null
+++ b/src/test/ui/expr/malformed_closure/missing_braces_around_block.fixed
@@ -0,0 +1,19 @@
+// This snippet ensures that no attempt to recover on a semicolon instead of
+// comma is made next to a closure body.
+//
+// If this recovery happens, then plenty of errors are emitted. Here, we expect
+// only one error.
+//
+// This is part of issue #88065:
+// https://github.com/rust-lang/rust/issues/88065
+
+// run-rustfix
+
+fn main() {
+    let num = 5;
+    (1..num).reduce(|a, b| {
+        //~^ ERROR: closure bodies that contain statements must be surrounded by braces
+        println!("{}", a);
+        a * b
+    }).unwrap();
+}
diff --git a/src/test/ui/expr/malformed_closure/missing_braces_around_block.rs b/src/test/ui/expr/malformed_closure/missing_braces_around_block.rs
new file mode 100644
index 00000000000..58c81f3a6e2
--- /dev/null
+++ b/src/test/ui/expr/malformed_closure/missing_braces_around_block.rs
@@ -0,0 +1,19 @@
+// This snippet ensures that no attempt to recover on a semicolon instead of
+// comma is made next to a closure body.
+//
+// If this recovery happens, then plenty of errors are emitted. Here, we expect
+// only one error.
+//
+// This is part of issue #88065:
+// https://github.com/rust-lang/rust/issues/88065
+
+// run-rustfix
+
+fn main() {
+    let num = 5;
+    (1..num).reduce(|a, b|
+        //~^ ERROR: closure bodies that contain statements must be surrounded by braces
+        println!("{}", a);
+        a * b
+    ).unwrap();
+}
diff --git a/src/test/ui/expr/malformed_closure/missing_braces_around_block.stderr b/src/test/ui/expr/malformed_closure/missing_braces_around_block.stderr
new file mode 100644
index 00000000000..dac9a8cfc69
--- /dev/null
+++ b/src/test/ui/expr/malformed_closure/missing_braces_around_block.stderr
@@ -0,0 +1,38 @@
+error: closure bodies that contain statements must be surrounded by braces
+  --> $DIR/missing_braces_around_block.rs:14:26
+   |
+LL |     (1..num).reduce(|a, b|
+   |                          ^
+...
+LL |     ).unwrap();
+   |     ^
+   |
+note: statement found outside of a block
+  --> $DIR/missing_braces_around_block.rs:16:26
+   |
+LL |         println!("{}", a);
+   |         -----------------^ this `;` turns the preceding closure into a statement
+   |         |
+   |         this expression is a statement because of the trailing semicolon
+note: the closure body may be incorrectly delimited
+  --> $DIR/missing_braces_around_block.rs:14:21
+   |
+LL |       (1..num).reduce(|a, b|
+   |  _____________________^
+LL | |
+LL | |         println!("{}", a);
+   | |_________________________^ this is the parsed closure...
+LL |           a * b
+LL |       ).unwrap();
+   |       - ...but likely you meant the closure to end here
+help: try adding braces
+   |
+LL ~     (1..num).reduce(|a, b| {
+LL |
+LL |         println!("{}", a);
+LL |         a * b
+LL ~     }).unwrap();
+   |
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/expr/malformed_closure/ruby_style_closure.rs b/src/test/ui/expr/malformed_closure/ruby_style_closure.rs
new file mode 100644
index 00000000000..e4341e19687
--- /dev/null
+++ b/src/test/ui/expr/malformed_closure/ruby_style_closure.rs
@@ -0,0 +1,16 @@
+// Part of issue #27300.
+// The problem here is that ruby-style closures are parsed as blocks whose
+// first statement is a closure. See the issue for more details:
+// https://github.com/rust-lang/rust/issues/27300
+
+// Note: this test represents what the compiler currently emits. The error
+// message will be improved later.
+
+fn main() {
+    let p = Some(45).and_then({
+        //~^ expected a `FnOnce<({integer},)>` closure, found `Option<_>`
+        |x| println!("doubling {}", x);
+        Some(x * 2)
+        //~^ ERROR: cannot find value `x` in this scope
+    });
+}
diff --git a/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr
new file mode 100644
index 00000000000..14d28b59648
--- /dev/null
+++ b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr
@@ -0,0 +1,27 @@
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/ruby_style_closure.rs:13:14
+   |
+LL |         Some(x * 2)
+   |              ^ not found in this scope
+
+error[E0277]: expected a `FnOnce<({integer},)>` closure, found `Option<_>`
+  --> $DIR/ruby_style_closure.rs:10:31
+   |
+LL |       let p = Some(45).and_then({
+   |  ______________________--------_^
+   | |                      |
+   | |                      required by a bound introduced by this call
+LL | |
+LL | |         |x| println!("doubling {}", x);
+LL | |         Some(x * 2)
+   | |         -----------
+LL | |
+LL | |     });
+   | |_____^ expected an `FnOnce<({integer},)>` closure, found `Option<_>`
+   |
+   = help: the trait `FnOnce<({integer},)>` is not implemented for `Option<_>`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0425.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/extern/extern-wrong-value-type.stderr b/src/test/ui/extern/extern-wrong-value-type.stderr
index 74981ebb76c..c6f0d5df9b5 100644
--- a/src/test/ui/extern/extern-wrong-value-type.stderr
+++ b/src/test/ui/extern/extern-wrong-value-type.stderr
@@ -2,7 +2,9 @@ error[E0277]: expected a `Fn<()>` closure, found `extern "C" fn() {f}`
   --> $DIR/extern-wrong-value-type.rs:9:11
    |
 LL |     is_fn(f);
-   |           ^ expected an `Fn<()>` closure, found `extern "C" fn() {f}`
+   |     ----- ^ expected an `Fn<()>` closure, found `extern "C" fn() {f}`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Fn<()>` is not implemented for `extern "C" fn() {f}`
    = note: wrap the `extern "C" fn() {f}` in a closure with no arguments: `|| { /* code */ }`
diff --git a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr
index a3bd65e518e..72cb4cc843c 100644
--- a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr
+++ b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr
@@ -40,7 +40,6 @@ error[E0038]: the trait `NonObjectSafe3` cannot be made into an object
 LL | fn takes_non_object_safe_box(obj: Box<dyn NonObjectSafe3>) {
    |                                       ^^^^^^^^^^^^^^^^^^ `NonObjectSafe3` cannot be made into an object
    |
-   = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/feature-gate-object_safe_for_dispatch.rs:11:8
    |
@@ -48,6 +47,7 @@ LL | trait NonObjectSafe3 {
    |       -------------- this trait cannot be made into an object...
 LL |     fn foo<T>(&self);
    |        ^^^ ...because method `foo` has generic type parameters
+   = help: consider moving `foo` to another trait
 
 error[E0038]: the trait `NonObjectSafe4` cannot be made into an object
   --> $DIR/feature-gate-object_safe_for_dispatch.rs:31:35
@@ -55,7 +55,6 @@ error[E0038]: the trait `NonObjectSafe4` cannot be made into an object
 LL | fn return_non_object_safe_rc() -> std::rc::Rc<dyn NonObjectSafe4> {
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `NonObjectSafe4` cannot be made into an object
    |
-   = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/feature-gate-object_safe_for_dispatch.rs:15:22
    |
@@ -63,6 +62,7 @@ LL | trait NonObjectSafe4 {
    |       -------------- this trait cannot be made into an object...
 LL |     fn foo(&self, s: &Self);
    |                      ^^^^^ ...because method `foo` references the `Self` type in this parameter
+   = help: consider moving `foo` to another trait
 
 error[E0038]: the trait `NonObjectSafe1` cannot be made into an object
   --> $DIR/feature-gate-object_safe_for_dispatch.rs:38:16
diff --git a/src/test/ui/feature-gates/feature-gate-unnamed_fields.rs b/src/test/ui/feature-gates/feature-gate-unnamed_fields.rs
deleted file mode 100644
index bd815dbcc92..00000000000
--- a/src/test/ui/feature-gates/feature-gate-unnamed_fields.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-struct Foo {
-    foo: u8,
-    _: union { //~ ERROR unnamed fields are not yet fully implemented [E0658]
-    //~^ ERROR unnamed fields are not yet fully implemented [E0658]
-    //~| ERROR anonymous unions are unimplemented
-        bar: u8,
-        baz: u16
-    }
-}
-
-union Bar {
-    foobar: u8,
-    _: struct { //~ ERROR unnamed fields are not yet fully implemented [E0658]
-    //~^ ERROR unnamed fields are not yet fully implemented [E0658]
-    //~| ERROR anonymous structs are unimplemented
-    //~| ERROR unions may not contain fields that need dropping [E0740]
-        foobaz: u8,
-        barbaz: u16
-    }
-}
-
-struct S;
-struct Baz {
-    _: S //~ ERROR unnamed fields are not yet fully implemented [E0658]
-}
-
-fn main(){}
diff --git a/src/test/ui/feature-gates/feature-gate-unnamed_fields.stderr b/src/test/ui/feature-gates/feature-gate-unnamed_fields.stderr
deleted file mode 100644
index 4f3ab85c987..00000000000
--- a/src/test/ui/feature-gates/feature-gate-unnamed_fields.stderr
+++ /dev/null
@@ -1,111 +0,0 @@
-error[E0658]: unnamed fields are not yet fully implemented
-  --> $DIR/feature-gate-unnamed_fields.rs:3:5
-   |
-LL |     _: union {
-   |     ^
-   |
-   = note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
-   = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
-
-error[E0658]: unnamed fields are not yet fully implemented
-  --> $DIR/feature-gate-unnamed_fields.rs:3:8
-   |
-LL |       _: union {
-   |  ________^
-LL | |
-LL | |
-LL | |         bar: u8,
-LL | |         baz: u16
-LL | |     }
-   | |_____^
-   |
-   = note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
-   = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
-
-error[E0658]: unnamed fields are not yet fully implemented
-  --> $DIR/feature-gate-unnamed_fields.rs:13:5
-   |
-LL |     _: struct {
-   |     ^
-   |
-   = note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
-   = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
-
-error[E0658]: unnamed fields are not yet fully implemented
-  --> $DIR/feature-gate-unnamed_fields.rs:13:8
-   |
-LL |       _: struct {
-   |  ________^
-LL | |
-LL | |
-LL | |
-LL | |         foobaz: u8,
-LL | |         barbaz: u16
-LL | |     }
-   | |_____^
-   |
-   = note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
-   = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
-
-error[E0658]: unnamed fields are not yet fully implemented
-  --> $DIR/feature-gate-unnamed_fields.rs:24:5
-   |
-LL |     _: S
-   |     ^
-   |
-   = note: see issue #49804 <https://github.com/rust-lang/rust/issues/49804> for more information
-   = help: add `#![feature(unnamed_fields)]` to the crate attributes to enable
-
-error: anonymous unions are unimplemented
-  --> $DIR/feature-gate-unnamed_fields.rs:3:8
-   |
-LL |       _: union {
-   |  ________^
-LL | |
-LL | |
-LL | |         bar: u8,
-LL | |         baz: u16
-LL | |     }
-   | |_____^
-
-error: anonymous structs are unimplemented
-  --> $DIR/feature-gate-unnamed_fields.rs:13:8
-   |
-LL |       _: struct {
-   |  ________^
-LL | |
-LL | |
-LL | |
-LL | |         foobaz: u8,
-LL | |         barbaz: u16
-LL | |     }
-   | |_____^
-
-error[E0740]: unions may not contain fields that need dropping
-  --> $DIR/feature-gate-unnamed_fields.rs:13:5
-   |
-LL | /     _: struct {
-LL | |
-LL | |
-LL | |
-LL | |         foobaz: u8,
-LL | |         barbaz: u16
-LL | |     }
-   | |_____^
-   |
-note: `std::mem::ManuallyDrop` can be used to wrap the type
-  --> $DIR/feature-gate-unnamed_fields.rs:13:5
-   |
-LL | /     _: struct {
-LL | |
-LL | |
-LL | |
-LL | |         foobaz: u8,
-LL | |         barbaz: u16
-LL | |     }
-   | |_____^
-
-error: aborting due to 8 previous errors
-
-Some errors have detailed explanations: E0658, E0740.
-For more information about an error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
index fbb18c8c490..0f7520ef7f8 100644
--- a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
+++ b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
@@ -12,10 +12,10 @@ LL | fn foo(x: &dyn Foo) {
    |           +
 
 error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known at compilation time
-  --> $DIR/feature-gate-unsized_fn_params.rs:24:5
+  --> $DIR/feature-gate-unsized_fn_params.rs:24:9
    |
 LL |     foo(*x);
-   |     ^^^ doesn't have a size known at compile-time
+   |         ^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
    = note: all function arguments must have a statically known size
diff --git a/src/test/ui/float-literal-inference-restrictions.stderr b/src/test/ui/float-literal-inference-restrictions.stderr
index 263b5e594e1..454373c322e 100644
--- a/src/test/ui/float-literal-inference-restrictions.stderr
+++ b/src/test/ui/float-literal-inference-restrictions.stderr
@@ -19,7 +19,7 @@ LL |     let y: f32 = 1f64;
 help: change the type of the numeric literal from `f64` to `f32`
    |
 LL |     let y: f32 = 1f32;
-   |                  ~~~~
+   |                   ~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/fn/fn-trait-formatting.stderr b/src/test/ui/fn/fn-trait-formatting.stderr
index 57a25b8e48b..f9fb3a0ef26 100644
--- a/src/test/ui/fn/fn-trait-formatting.stderr
+++ b/src/test/ui/fn/fn-trait-formatting.stderr
@@ -35,7 +35,9 @@ error[E0277]: expected a `Fn<(isize,)>` closure, found `{integer}`
   --> $DIR/fn-trait-formatting.rs:19:14
    |
 LL |     needs_fn(1);
-   |              ^ expected an `Fn<(isize,)>` closure, found `{integer}`
+   |     -------- ^ expected an `Fn<(isize,)>` closure, found `{integer}`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Fn<(isize,)>` is not implemented for `{integer}`
 note: required by a bound in `needs_fn`
diff --git a/src/test/ui/generator/static-not-unpin.stderr b/src/test/ui/generator/static-not-unpin.stderr
index 7ae128d072d..4ae745b0ffe 100644
--- a/src/test/ui/generator/static-not-unpin.stderr
+++ b/src/test/ui/generator/static-not-unpin.stderr
@@ -2,7 +2,9 @@ error[E0277]: `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6]` cannot b
   --> $DIR/static-not-unpin.rs:14:18
    |
 LL |     assert_unpin(generator);
-   |                  ^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6]`
+   |     ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6]`
+   |     |
+   |     required by a bound introduced by this call
    |
    = note: consider using `Box::pin`
 note: required by a bound in `assert_unpin`
diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr
index 8651789688e..a55642490f9 100644
--- a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr
+++ b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr
@@ -4,7 +4,6 @@ error[E0038]: the trait `Foo` cannot be made into an object
 LL | fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
    |
-   = help: consider moving `A` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/gat-in-trait-path.rs:5:10
    |
@@ -12,6 +11,7 @@ LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     type A<'a> where Self: 'a;
    |          ^ ...because it contains the generic associated type `A`
+   = help: consider moving `A` to another trait
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generic-associated-types/impl_bounds.rs b/src/test/ui/generic-associated-types/impl_bounds.rs
index 01edad00a89..27c135cb7cf 100644
--- a/src/test/ui/generic-associated-types/impl_bounds.rs
+++ b/src/test/ui/generic-associated-types/impl_bounds.rs
@@ -15,7 +15,7 @@ impl<T> Foo for Fooy<T> {
     type A<'a> where Self: 'static = (&'a ());
     //~^ ERROR the parameter type `T` may not live long enough
     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
-    //~^ ERROR lifetime bound not satisfied
+    //~^ ERROR `impl` associated type
     //~| ERROR lifetime bound not satisfied
     type C where Self: Copy = String;
     //~^ ERROR the trait bound `T: Copy` is not satisfied
diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr
index 8cf923ca3ac..73415e0faac 100644
--- a/src/test/ui/generic-associated-types/impl_bounds.stderr
+++ b/src/test/ui/generic-associated-types/impl_bounds.stderr
@@ -5,24 +5,16 @@ LL |     type A<'a> where Self: 'static = (&'a ());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `T: 'static`...
-   = note: ...so that the type `Fooy<T>` will meet its required lifetime bounds
+   = note: ...so that the definition in impl matches the definition from the trait
 
-error[E0478]: lifetime bound not satisfied
+error: `impl` associated type signature for `B` doesn't match `trait` associated type signature
   --> $DIR/impl_bounds.rs:17:5
    |
+LL |     type B<'a, 'b> where 'a: 'b;
+   |     ---------------------------- expected
+...
 LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: lifetime parameter instantiated with the lifetime `'b` as defined on the associated item at 17:16
-  --> $DIR/impl_bounds.rs:17:16
-   |
-LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
-   |                ^^
-note: but lifetime parameter must outlive the lifetime `'a` as defined on the associated item at 17:12
-  --> $DIR/impl_bounds.rs:17:12
-   |
-LL |     type B<'a, 'b> where 'b: 'a = (&'a(), &'b ());
-   |            ^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found
 
 error[E0478]: lifetime bound not satisfied
   --> $DIR/impl_bounds.rs:17:5
diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.stderr b/src/test/ui/generic-associated-types/issue-67510-pass.stderr
index b4b89ab0473..7dd1bdf891e 100644
--- a/src/test/ui/generic-associated-types/issue-67510-pass.stderr
+++ b/src/test/ui/generic-associated-types/issue-67510-pass.stderr
@@ -4,7 +4,6 @@ error[E0038]: the trait `X` cannot be made into an object
 LL | fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
    |                       ^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object
    |
-   = help: consider moving `Y` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-67510-pass.rs:4:10
    |
@@ -12,6 +11,7 @@ LL | trait X {
    |       - this trait cannot be made into an object...
 LL |     type Y<'a>;
    |          ^ ...because it contains the generic associated type `Y`
+   = help: consider moving `Y` to another trait
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generic-associated-types/issue-76535.stderr b/src/test/ui/generic-associated-types/issue-76535.stderr
index 246454f0612..0a7eb5dde60 100644
--- a/src/test/ui/generic-associated-types/issue-76535.stderr
+++ b/src/test/ui/generic-associated-types/issue-76535.stderr
@@ -20,7 +20,6 @@ error[E0038]: the trait `SuperTrait` cannot be made into an object
 LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
    |
-   = help: consider moving `SubType` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-76535.rs:6:10
    |
@@ -28,6 +27,7 @@ LL | pub trait SuperTrait {
    |           ---------- this trait cannot be made into an object...
 LL |     type SubType<'a>: SubTrait;
    |          ^^^^^^^ ...because it contains the generic associated type `SubType`
+   = help: consider moving `SubType` to another trait
 
 error[E0038]: the trait `SuperTrait` cannot be made into an object
   --> $DIR/issue-76535.rs:36:57
@@ -35,7 +35,6 @@ error[E0038]: the trait `SuperTrait` cannot be made into an object
 LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
    |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
    |
-   = help: consider moving `SubType` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-76535.rs:6:10
    |
@@ -43,6 +42,7 @@ LL | pub trait SuperTrait {
    |           ---------- this trait cannot be made into an object...
 LL |     type SubType<'a>: SubTrait;
    |          ^^^^^^^ ...because it contains the generic associated type `SubType`
+   = help: consider moving `SubType` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn SuperTrait<SubType = SubStruct<'_>>>>` for `Box<SuperStruct>`
    = note: required by cast to type `Box<dyn SuperTrait<SubType = SubStruct<'_>>>`
 
diff --git a/src/test/ui/generic-associated-types/issue-78671.stderr b/src/test/ui/generic-associated-types/issue-78671.stderr
index b9273083956..17dd0ff4a0c 100644
--- a/src/test/ui/generic-associated-types/issue-78671.stderr
+++ b/src/test/ui/generic-associated-types/issue-78671.stderr
@@ -20,7 +20,6 @@ error[E0038]: the trait `CollectionFamily` cannot be made into an object
 LL |     Box::new(Family) as &dyn CollectionFamily<Member=usize>
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` cannot be made into an object
    |
-   = help: consider moving `Member` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-78671.rs:4:10
    |
@@ -28,6 +27,7 @@ LL | trait CollectionFamily {
    |       ---------------- this trait cannot be made into an object...
 LL |     type Member<T>;
    |          ^^^^^^ ...because it contains the generic associated type `Member`
+   = help: consider moving `Member` to another trait
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/generic-associated-types/issue-79422.stderr b/src/test/ui/generic-associated-types/issue-79422.stderr
index 8d8ef6bf836..b6f856a97e7 100644
--- a/src/test/ui/generic-associated-types/issue-79422.stderr
+++ b/src/test/ui/generic-associated-types/issue-79422.stderr
@@ -20,7 +20,6 @@ error[E0038]: the trait `MapLike` cannot be made into an object
 LL |         as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
    |
-   = help: consider moving `VRefCont` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-79422.rs:20:10
    |
@@ -28,6 +27,7 @@ LL | trait MapLike<K, V> {
    |       ------- this trait cannot be made into an object...
 LL |     type VRefCont<'a>: RefCont<'a, V>;
    |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
+   = help: consider moving `VRefCont` to another trait
 
 error[E0038]: the trait `MapLike` cannot be made into an object
   --> $DIR/issue-79422.rs:41:13
@@ -35,7 +35,6 @@ error[E0038]: the trait `MapLike` cannot be made into an object
 LL |     let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
    |
-   = help: consider moving `VRefCont` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-79422.rs:20:10
    |
@@ -43,6 +42,7 @@ LL | trait MapLike<K, V> {
    |       ------- this trait cannot be made into an object...
 LL |     type VRefCont<'a>: RefCont<'a, V>;
    |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
+   = help: consider moving `VRefCont` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>>` for `Box<BTreeMap<u8, u8>>`
    = note: required by cast to type `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
 
diff --git a/src/test/ui/generic-associated-types/issue-86787.stderr b/src/test/ui/generic-associated-types/issue-86787.stderr
index 04cd84b0801..e1ff7729211 100644
--- a/src/test/ui/generic-associated-types/issue-86787.stderr
+++ b/src/test/ui/generic-associated-types/issue-86787.stderr
@@ -9,7 +9,7 @@ LL | |     <Left as HasChildrenOf>::T: 'a,
 LL | |     <Right as HasChildrenOf>::T: 'a
    | |                                    - help: consider adding a where clause: `, <Left as HasChildrenOf>::T: 'a`
 LL | |     = Either<&'a Left::T, &'a Right::T>;
-   | |________________________________________^ ...so that the type `<Left as HasChildrenOf>::T` will meet its required lifetime bounds
+   | |________________________________________^ ...so that the definition in impl matches the definition from the trait
 
 error[E0309]: the associated type `<Right as HasChildrenOf>::T` may not live long enough
   --> $DIR/issue-86787.rs:23:5
@@ -22,7 +22,7 @@ LL | |     <Left as HasChildrenOf>::T: 'a,
 LL | |     <Right as HasChildrenOf>::T: 'a
    | |                                    - help: consider adding a where clause: `, <Right as HasChildrenOf>::T: 'a`
 LL | |     = Either<&'a Left::T, &'a Right::T>;
-   | |________________________________________^ ...so that the type `<Right as HasChildrenOf>::T` will meet its required lifetime bounds
+   | |________________________________________^ ...so that the definition in impl matches the definition from the trait
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs
new file mode 100644
index 00000000000..ad9f2e3e4ec
--- /dev/null
+++ b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.rs
@@ -0,0 +1,13 @@
+// check-fail
+
+#![feature(generic_associated_types)]
+
+trait Foo {
+    type Assoc<'a, 'b>;
+}
+impl Foo for () {
+    type Assoc<'a, 'b> where 'a: 'b = ();
+    //~^ `impl` associated type
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr
new file mode 100644
index 00000000000..0e183c8d69a
--- /dev/null
+++ b/src/test/ui/generic-associated-types/missing-where-clause-on-trait.stderr
@@ -0,0 +1,11 @@
+error: `impl` associated type signature for `Assoc` doesn't match `trait` associated type signature
+  --> $DIR/missing-where-clause-on-trait.rs:9:5
+   |
+LL |     type Assoc<'a, 'b>;
+   |     ------------------- expected
+...
+LL |     type Assoc<'a, 'b> where 'a: 'b = ();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/generic-associated-types/trait-objects.stderr b/src/test/ui/generic-associated-types/trait-objects.stderr
index 6429bb8159e..5ab37910207 100644
--- a/src/test/ui/generic-associated-types/trait-objects.stderr
+++ b/src/test/ui/generic-associated-types/trait-objects.stderr
@@ -4,7 +4,6 @@ error[E0038]: the trait `StreamingIterator` cannot be made into an object
 LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize {
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object
    |
-   = help: consider moving `Item` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/trait-objects.rs:4:10
    |
@@ -12,6 +11,7 @@ LL | trait StreamingIterator {
    |       ----------------- this trait cannot be made into an object...
 LL |     type Item<'a> where Self: 'a;
    |          ^^^^ ...because it contains the generic associated type `Item`
+   = help: consider moving `Item` to another trait
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr
index 8311c147ee3..b13226fef6e 100644
--- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-1.stderr
@@ -1,11 +1,19 @@
 error[E0631]: type mismatch in closure arguments
   --> $DIR/issue-62529-1.rs:80:10
    |
-LL |     task(annotate(
-   |          ^^^^^^^^ expected signature of `for<'r> fn(<RefMutFamily<usize> as FamilyLt<'r>>::Out) -> _`
-...
-LL |         |value: &mut usize| {
-   |         ------------------- found signature of `for<'r> fn(&'r mut usize) -> _`
+LL |       task(annotate(
+   |  _____----_^
+   | |     |
+   | |     required by a bound introduced by this call
+LL | |
+LL | |
+LL | |         Annotate::<RefMutFamily<usize>>::new(),
+LL | |         |value: &mut usize| {
+   | |         ------------------- found signature of `for<'r> fn(&'r mut usize) -> _`
+LL | |             *value = 2;
+LL | |         }
+LL | |     ));
+   | |_____^ expected signature of `for<'r> fn(<RefMutFamily<usize> as FamilyLt<'r>>::Out) -> _`
    |
 note: required by a bound in `annotate`
   --> $DIR/issue-62529-1.rs:44:8
@@ -20,7 +28,9 @@ error[E0277]: the size for values of type `impl Execute` cannot be known at comp
   --> $DIR/issue-62529-1.rs:80:10
    |
 LL |       task(annotate(
-   |  __________^
+   |  _____----_^
+   | |     |
+   | |     required by a bound introduced by this call
 LL | |
 LL | |
 LL | |         Annotate::<RefMutFamily<usize>>::new(),
@@ -44,7 +54,9 @@ error[E0277]: the trait bound `impl Execute: Execute` is not satisfied
   --> $DIR/issue-62529-1.rs:80:10
    |
 LL |       task(annotate(
-   |  __________^
+   |  _____----_^
+   | |     |
+   | |     required by a bound introduced by this call
 LL | |
 LL | |
 LL | |         Annotate::<RefMutFamily<usize>>::new(),
diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr
index d8267712c2b..8cda76b9490 100644
--- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr
+++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied
   --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:47:26
    |
 LL |     want_bar_for_any_ccx(b);
-   |                          ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
+   |     -------------------- ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `want_bar_for_any_ccx`
   --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:32:15
diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr
index a510c05055c..88793a1525b 100644
--- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr
+++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `for<'tcx> F: Foo<'tcx>` is not satisfied
   --> $DIR/hrtb-higher-ranker-supertraits.rs:18:26
    |
 LL |     want_foo_for_any_tcx(f);
-   |                          ^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F`
+   |     -------------------- ^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `want_foo_for_any_tcx`
   --> $DIR/hrtb-higher-ranker-supertraits.rs:22:15
@@ -20,7 +22,9 @@ error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied
   --> $DIR/hrtb-higher-ranker-supertraits.rs:35:26
    |
 LL |     want_bar_for_any_ccx(b);
-   |                          ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
+   |     -------------------- ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `want_bar_for_any_ccx`
   --> $DIR/hrtb-higher-ranker-supertraits.rs:39:15
diff --git a/src/test/ui/hrtb/issue-88446.rs b/src/test/ui/hrtb/issue-88446.rs
new file mode 100644
index 00000000000..571b8531757
--- /dev/null
+++ b/src/test/ui/hrtb/issue-88446.rs
@@ -0,0 +1,35 @@
+// check-pass
+
+trait Yokeable<'a> {
+    type Output: 'a;
+}
+impl<'a> Yokeable<'a> for () {
+    type Output = ();
+}
+
+trait DataMarker<'data> {
+    type Yokeable: for<'a> Yokeable<'a>;
+}
+impl<'data> DataMarker<'data> for () {
+    type Yokeable = ();
+}
+
+struct DataPayload<'data, M>(&'data M);
+
+impl DataPayload<'static, ()> {
+    pub fn map_project_with_capture<M2, T>(
+        _: for<'a> fn(
+            capture: T,
+            std::marker::PhantomData<&'a ()>,
+        ) -> <M2::Yokeable as Yokeable<'a>>::Output,
+    ) -> DataPayload<'static, M2>
+    where
+        M2: DataMarker<'static>,
+    {
+        todo!()
+    }
+}
+
+fn main() {
+    let _: DataPayload<()> = DataPayload::<()>::map_project_with_capture::<_, &()>(|_, _| todo!());
+}
diff --git a/src/test/ui/indexing-requires-a-uint.stderr b/src/test/ui/indexing-requires-a-uint.stderr
index 1bcb89de2ba..24f42f22f37 100644
--- a/src/test/ui/indexing-requires-a-uint.stderr
+++ b/src/test/ui/indexing-requires-a-uint.stderr
@@ -16,7 +16,7 @@ LL |     bar::<isize>(i);  // i should not be re-coerced back to an isize
 help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit
    |
 LL |     bar::<isize>(i.try_into().unwrap());  // i should not be re-coerced back to an isize
-   |                  ~~~~~~~~~~~~~~~~~~~~~
+   |                   ++++++++++++++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/inference/issue-71309.rs b/src/test/ui/inference/issue-71309.rs
new file mode 100644
index 00000000000..c31107d8fed
--- /dev/null
+++ b/src/test/ui/inference/issue-71309.rs
@@ -0,0 +1,7 @@
+fn foo(x: Result<i32, ()>) -> Result<(), ()> {
+    let y: u32 = x?;
+    //~^ ERROR: `?` operator has incompatible types
+    Ok(())
+}
+
+fn main() {}
diff --git a/src/test/ui/inference/issue-71309.stderr b/src/test/ui/inference/issue-71309.stderr
new file mode 100644
index 00000000000..af8714f1c80
--- /dev/null
+++ b/src/test/ui/inference/issue-71309.stderr
@@ -0,0 +1,15 @@
+error[E0308]: `?` operator has incompatible types
+  --> $DIR/issue-71309.rs:2:18
+   |
+LL |     let y: u32 = x?;
+   |                  ^^ expected `u32`, found `i32`
+   |
+   = note: `?` operator cannot convert from `i32` to `u32`
+help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
+   |
+LL |     let y: u32 = x?.try_into().unwrap();
+   |                    ++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/integer-literal-suffix-inference.stderr b/src/test/ui/integer-literal-suffix-inference.stderr
index c9cfbc506be..4c29c4a1cb0 100644
--- a/src/test/ui/integer-literal-suffix-inference.stderr
+++ b/src/test/ui/integer-literal-suffix-inference.stderr
@@ -7,7 +7,7 @@ LL |     id_i8(a16);
 help: you can convert an `i16` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     id_i8(a16.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:41:11
@@ -18,7 +18,7 @@ LL |     id_i8(a32);
 help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     id_i8(a32.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:44:11
@@ -29,7 +29,7 @@ LL |     id_i8(a64);
 help: you can convert an `i64` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     id_i8(a64.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:47:11
@@ -40,16 +40,18 @@ LL |     id_i8(asize);
 help: you can convert an `isize` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     id_i8(asize.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:51:12
    |
 LL |     id_i16(a8);
-   |            ^^
-   |            |
-   |            expected `i16`, found `i8`
-   |            help: you can convert an `i8` to an `i16`: `a8.into()`
+   |            ^^ expected `i16`, found `i8`
+   |
+help: you can convert an `i8` to an `i16`
+   |
+LL |     id_i16(a8.into());
+   |              +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:55:12
@@ -60,7 +62,7 @@ LL |     id_i16(a32);
 help: you can convert an `i32` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     id_i16(a32.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:58:12
@@ -71,7 +73,7 @@ LL |     id_i16(a64);
 help: you can convert an `i64` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     id_i16(a64.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:61:12
@@ -82,25 +84,29 @@ LL |     id_i16(asize);
 help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     id_i16(asize.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:65:12
    |
 LL |     id_i32(a8);
-   |            ^^
-   |            |
-   |            expected `i32`, found `i8`
-   |            help: you can convert an `i8` to an `i32`: `a8.into()`
+   |            ^^ expected `i32`, found `i8`
+   |
+help: you can convert an `i8` to an `i32`
+   |
+LL |     id_i32(a8.into());
+   |              +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:68:12
    |
 LL |     id_i32(a16);
-   |            ^^^
-   |            |
-   |            expected `i32`, found `i16`
-   |            help: you can convert an `i16` to an `i32`: `a16.into()`
+   |            ^^^ expected `i32`, found `i16`
+   |
+help: you can convert an `i16` to an `i32`
+   |
+LL |     id_i32(a16.into());
+   |               +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:72:12
@@ -111,7 +117,7 @@ LL |     id_i32(a64);
 help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
    |
 LL |     id_i32(a64.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:75:12
@@ -122,34 +128,40 @@ LL |     id_i32(asize);
 help: you can convert an `isize` to an `i32` and panic if the converted value doesn't fit
    |
 LL |     id_i32(asize.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:79:12
    |
 LL |     id_i64(a8);
-   |            ^^
-   |            |
-   |            expected `i64`, found `i8`
-   |            help: you can convert an `i8` to an `i64`: `a8.into()`
+   |            ^^ expected `i64`, found `i8`
+   |
+help: you can convert an `i8` to an `i64`
+   |
+LL |     id_i64(a8.into());
+   |              +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:82:12
    |
 LL |     id_i64(a16);
-   |            ^^^
-   |            |
-   |            expected `i64`, found `i16`
-   |            help: you can convert an `i16` to an `i64`: `a16.into()`
+   |            ^^^ expected `i64`, found `i16`
+   |
+help: you can convert an `i16` to an `i64`
+   |
+LL |     id_i64(a16.into());
+   |               +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:85:12
    |
 LL |     id_i64(a32);
-   |            ^^^
-   |            |
-   |            expected `i64`, found `i32`
-   |            help: you can convert an `i32` to an `i64`: `a32.into()`
+   |            ^^^ expected `i64`, found `i32`
+   |
+help: you can convert an `i32` to an `i64`
+   |
+LL |     id_i64(a32.into());
+   |               +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:89:12
@@ -160,25 +172,29 @@ LL |     id_i64(asize);
 help: you can convert an `isize` to an `i64` and panic if the converted value doesn't fit
    |
 LL |     id_i64(asize.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:93:14
    |
 LL |     id_isize(a8);
-   |              ^^
-   |              |
-   |              expected `isize`, found `i8`
-   |              help: you can convert an `i8` to an `isize`: `a8.into()`
+   |              ^^ expected `isize`, found `i8`
+   |
+help: you can convert an `i8` to an `isize`
+   |
+LL |     id_isize(a8.into());
+   |                +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:96:14
    |
 LL |     id_isize(a16);
-   |              ^^^
-   |              |
-   |              expected `isize`, found `i16`
-   |              help: you can convert an `i16` to an `isize`: `a16.into()`
+   |              ^^^ expected `isize`, found `i16`
+   |
+help: you can convert an `i16` to an `isize`
+   |
+LL |     id_isize(a16.into());
+   |                 +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:99:14
@@ -189,7 +205,7 @@ LL |     id_isize(a32);
 help: you can convert an `i32` to an `isize` and panic if the converted value doesn't fit
    |
 LL |     id_isize(a32.try_into().unwrap());
-   |              ~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:102:14
@@ -200,7 +216,7 @@ LL |     id_isize(a64);
 help: you can convert an `i64` to an `isize` and panic if the converted value doesn't fit
    |
 LL |     id_isize(a64.try_into().unwrap());
-   |              ~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:108:11
@@ -211,7 +227,7 @@ LL |     id_i8(c16);
 help: you can convert an `i16` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     id_i8(c16.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:111:11
@@ -222,7 +238,7 @@ LL |     id_i8(c32);
 help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     id_i8(c32.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:114:11
@@ -233,16 +249,18 @@ LL |     id_i8(c64);
 help: you can convert an `i64` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     id_i8(c64.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:118:12
    |
 LL |     id_i16(c8);
-   |            ^^
-   |            |
-   |            expected `i16`, found `i8`
-   |            help: you can convert an `i8` to an `i16`: `c8.into()`
+   |            ^^ expected `i16`, found `i8`
+   |
+help: you can convert an `i8` to an `i16`
+   |
+LL |     id_i16(c8.into());
+   |              +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:122:12
@@ -253,7 +271,7 @@ LL |     id_i16(c32);
 help: you can convert an `i32` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     id_i16(c32.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:125:12
@@ -264,25 +282,29 @@ LL |     id_i16(c64);
 help: you can convert an `i64` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     id_i16(c64.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:129:12
    |
 LL |     id_i32(c8);
-   |            ^^
-   |            |
-   |            expected `i32`, found `i8`
-   |            help: you can convert an `i8` to an `i32`: `c8.into()`
+   |            ^^ expected `i32`, found `i8`
+   |
+help: you can convert an `i8` to an `i32`
+   |
+LL |     id_i32(c8.into());
+   |              +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:132:12
    |
 LL |     id_i32(c16);
-   |            ^^^
-   |            |
-   |            expected `i32`, found `i16`
-   |            help: you can convert an `i16` to an `i32`: `c16.into()`
+   |            ^^^ expected `i32`, found `i16`
+   |
+help: you can convert an `i16` to an `i32`
+   |
+LL |     id_i32(c16.into());
+   |               +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:136:12
@@ -293,34 +315,40 @@ LL |     id_i32(c64);
 help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
    |
 LL |     id_i32(c64.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:140:12
    |
 LL |     id_i64(a8);
-   |            ^^
-   |            |
-   |            expected `i64`, found `i8`
-   |            help: you can convert an `i8` to an `i64`: `a8.into()`
+   |            ^^ expected `i64`, found `i8`
+   |
+help: you can convert an `i8` to an `i64`
+   |
+LL |     id_i64(a8.into());
+   |              +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:143:12
    |
 LL |     id_i64(a16);
-   |            ^^^
-   |            |
-   |            expected `i64`, found `i16`
-   |            help: you can convert an `i16` to an `i64`: `a16.into()`
+   |            ^^^ expected `i64`, found `i16`
+   |
+help: you can convert an `i16` to an `i64`
+   |
+LL |     id_i64(a16.into());
+   |               +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:146:12
    |
 LL |     id_i64(a32);
-   |            ^^^
-   |            |
-   |            expected `i64`, found `i32`
-   |            help: you can convert an `i32` to an `i64`: `a32.into()`
+   |            ^^^ expected `i64`, found `i32`
+   |
+help: you can convert an `i32` to an `i64`
+   |
+LL |     id_i64(a32.into());
+   |               +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:152:11
@@ -331,7 +359,7 @@ LL |     id_u8(b16);
 help: you can convert a `u16` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     id_u8(b16.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:155:11
@@ -342,7 +370,7 @@ LL |     id_u8(b32);
 help: you can convert a `u32` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     id_u8(b32.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:158:11
@@ -353,7 +381,7 @@ LL |     id_u8(b64);
 help: you can convert a `u64` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     id_u8(b64.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~
+   |              ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:161:11
@@ -364,16 +392,18 @@ LL |     id_u8(bsize);
 help: you can convert a `usize` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     id_u8(bsize.try_into().unwrap());
-   |           ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:165:12
    |
 LL |     id_u16(b8);
-   |            ^^
-   |            |
-   |            expected `u16`, found `u8`
-   |            help: you can convert a `u8` to a `u16`: `b8.into()`
+   |            ^^ expected `u16`, found `u8`
+   |
+help: you can convert a `u8` to a `u16`
+   |
+LL |     id_u16(b8.into());
+   |              +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:169:12
@@ -384,7 +414,7 @@ LL |     id_u16(b32);
 help: you can convert a `u32` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     id_u16(b32.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:172:12
@@ -395,7 +425,7 @@ LL |     id_u16(b64);
 help: you can convert a `u64` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     id_u16(b64.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:175:12
@@ -406,25 +436,29 @@ LL |     id_u16(bsize);
 help: you can convert a `usize` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     id_u16(bsize.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:179:12
    |
 LL |     id_u32(b8);
-   |            ^^
-   |            |
-   |            expected `u32`, found `u8`
-   |            help: you can convert a `u8` to a `u32`: `b8.into()`
+   |            ^^ expected `u32`, found `u8`
+   |
+help: you can convert a `u8` to a `u32`
+   |
+LL |     id_u32(b8.into());
+   |              +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:182:12
    |
 LL |     id_u32(b16);
-   |            ^^^
-   |            |
-   |            expected `u32`, found `u16`
-   |            help: you can convert a `u16` to a `u32`: `b16.into()`
+   |            ^^^ expected `u32`, found `u16`
+   |
+help: you can convert a `u16` to a `u32`
+   |
+LL |     id_u32(b16.into());
+   |               +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:186:12
@@ -435,7 +469,7 @@ LL |     id_u32(b64);
 help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     id_u32(b64.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:189:12
@@ -446,34 +480,40 @@ LL |     id_u32(bsize);
 help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     id_u32(bsize.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:193:12
    |
 LL |     id_u64(b8);
-   |            ^^
-   |            |
-   |            expected `u64`, found `u8`
-   |            help: you can convert a `u8` to a `u64`: `b8.into()`
+   |            ^^ expected `u64`, found `u8`
+   |
+help: you can convert a `u8` to a `u64`
+   |
+LL |     id_u64(b8.into());
+   |              +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:196:12
    |
 LL |     id_u64(b16);
-   |            ^^^
-   |            |
-   |            expected `u64`, found `u16`
-   |            help: you can convert a `u16` to a `u64`: `b16.into()`
+   |            ^^^ expected `u64`, found `u16`
+   |
+help: you can convert a `u16` to a `u64`
+   |
+LL |     id_u64(b16.into());
+   |               +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:199:12
    |
 LL |     id_u64(b32);
-   |            ^^^
-   |            |
-   |            expected `u64`, found `u32`
-   |            help: you can convert a `u32` to a `u64`: `b32.into()`
+   |            ^^^ expected `u64`, found `u32`
+   |
+help: you can convert a `u32` to a `u64`
+   |
+LL |     id_u64(b32.into());
+   |               +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:203:12
@@ -484,25 +524,29 @@ LL |     id_u64(bsize);
 help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit
    |
 LL |     id_u64(bsize.try_into().unwrap());
-   |            ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:207:14
    |
 LL |     id_usize(b8);
-   |              ^^
-   |              |
-   |              expected `usize`, found `u8`
-   |              help: you can convert a `u8` to a `usize`: `b8.into()`
+   |              ^^ expected `usize`, found `u8`
+   |
+help: you can convert a `u8` to a `usize`
+   |
+LL |     id_usize(b8.into());
+   |                +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:210:14
    |
 LL |     id_usize(b16);
-   |              ^^^
-   |              |
-   |              expected `usize`, found `u16`
-   |              help: you can convert a `u16` to a `usize`: `b16.into()`
+   |              ^^^ expected `usize`, found `u16`
+   |
+help: you can convert a `u16` to a `usize`
+   |
+LL |     id_usize(b16.into());
+   |                 +++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:213:14
@@ -513,7 +557,7 @@ LL |     id_usize(b32);
 help: you can convert a `u32` to a `usize` and panic if the converted value doesn't fit
    |
 LL |     id_usize(b32.try_into().unwrap());
-   |              ~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/integer-literal-suffix-inference.rs:216:14
@@ -524,7 +568,7 @@ LL |     id_usize(b64);
 help: you can convert a `u64` to a `usize` and panic if the converted value doesn't fit
    |
 LL |     id_usize(b64.try_into().unwrap());
-   |              ~~~~~~~~~~~~~~~~~~~~~~~
+   |                 ++++++++++++++++++++
 
 error: aborting due to 52 previous errors
 
diff --git a/src/test/ui/issues/issue-13359.stderr b/src/test/ui/issues/issue-13359.stderr
index 0796ede52a9..075c92e65de 100644
--- a/src/test/ui/issues/issue-13359.stderr
+++ b/src/test/ui/issues/issue-13359.stderr
@@ -7,7 +7,7 @@ LL |     foo(1*(1 as isize));
 help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     foo((1*(1 as isize)).try_into().unwrap());
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |         +              +++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/issue-13359.rs:10:9
@@ -18,7 +18,7 @@ LL |     bar(1*(1 as usize));
 help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     bar((1*(1 as usize)).try_into().unwrap());
-   |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |         +              +++++++++++++++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-1362.stderr b/src/test/ui/issues/issue-1362.stderr
index a925fc29c8c..babbb6e519b 100644
--- a/src/test/ui/issues/issue-1362.stderr
+++ b/src/test/ui/issues/issue-1362.stderr
@@ -9,7 +9,7 @@ LL |   let x: u32 = 20i32;
 help: change the type of the numeric literal from `i32` to `u32`
    |
 LL |   let x: u32 = 20u32;
-   |                ~~~~~
+   |                  ~~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-1448-2.stderr b/src/test/ui/issues/issue-1448-2.stderr
index 6bf76c4904d..da44566d075 100644
--- a/src/test/ui/issues/issue-1448-2.stderr
+++ b/src/test/ui/issues/issue-1448-2.stderr
@@ -7,7 +7,7 @@ LL |     println!("{}", foo(10i32));
 help: change the type of the numeric literal from `i32` to `u32`
    |
 LL |     println!("{}", foo(10u32));
-   |                        ~~~~~
+   |                          ~~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17651.rs b/src/test/ui/issues/issue-17651.rs
index 08f352c11fa..7629a5a3be1 100644
--- a/src/test/ui/issues/issue-17651.rs
+++ b/src/test/ui/issues/issue-17651.rs
@@ -4,5 +4,4 @@
 fn main() {
     (|| Box::new(*(&[0][..])))();
     //~^ ERROR the size for values of type
-    //~| ERROR the size for values of type
 }
diff --git a/src/test/ui/issues/issue-17651.stderr b/src/test/ui/issues/issue-17651.stderr
index ee1464fd848..214477f6c60 100644
--- a/src/test/ui/issues/issue-17651.stderr
+++ b/src/test/ui/issues/issue-17651.stderr
@@ -2,7 +2,9 @@ error[E0277]: the size for values of type `[{integer}]` cannot be known at compi
   --> $DIR/issue-17651.rs:5:18
    |
 LL |     (|| Box::new(*(&[0][..])))();
-   |                  ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |         -------- ^^^^^^^^^^^ doesn't have a size known at compile-time
+   |         |
+   |         required by a bound introduced by this call
    |
    = help: the trait `Sized` is not implemented for `[{integer}]`
 note: required by `Box::<T>::new`
@@ -11,16 +13,6 @@ note: required by `Box::<T>::new`
 LL |     pub fn new(x: T) -> Self {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time
-  --> $DIR/issue-17651.rs:5:9
-   |
-LL |     (|| Box::new(*(&[0][..])))();
-   |         ^^^^^^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `[{integer}]`
-   = note: all function arguments must have a statically known size
-   = help: unsized fn params are gated as an unstable feature
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-18959.stderr b/src/test/ui/issues/issue-18959.stderr
index 2a5416ce85b..b9e27873636 100644
--- a/src/test/ui/issues/issue-18959.stderr
+++ b/src/test/ui/issues/issue-18959.stderr
@@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL | fn foo(b: &dyn Bar) {
    |            ^^^^^^^ `Bar` cannot be made into an object
    |
-   = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-18959.rs:1:20
    |
@@ -12,6 +11,7 @@ LL | pub trait Foo { fn foo<T>(&self, ext_thing: &T); }
    |                    ^^^ ...because method `foo` has generic type parameters
 LL | pub trait Bar: Foo { }
    |           --- this trait cannot be made into an object...
+   = help: consider moving `foo` to another trait
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-19358.rs b/src/test/ui/issues/issue-19358.rs
index f66e0a1c078..3970a4155e9 100644
--- a/src/test/ui/issues/issue-19358.rs
+++ b/src/test/ui/issues/issue-19358.rs
@@ -1,4 +1,7 @@
 // run-pass
+
+#![allow(dead_code)]
+
 trait Trait { fn dummy(&self) { } }
 
 #[derive(Debug)]
diff --git a/src/test/ui/issues/issue-19538.stderr b/src/test/ui/issues/issue-19538.stderr
index 555d0ff0dc7..7b37e1f95dc 100644
--- a/src/test/ui/issues/issue-19538.stderr
+++ b/src/test/ui/issues/issue-19538.stderr
@@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL |     let test: &mut dyn Bar = &mut thing;
    |               ^^^^^^^^^^^^ `Bar` cannot be made into an object
    |
-   = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-19538.rs:2:8
    |
@@ -13,6 +12,7 @@ LL |     fn foo<T>(&self, val: T);
 ...
 LL | trait Bar: Foo { }
    |       --- this trait cannot be made into an object...
+   = help: consider moving `foo` to another trait
 
 error[E0038]: the trait `Bar` cannot be made into an object
   --> $DIR/issue-19538.rs:17:30
@@ -20,7 +20,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL |     let test: &mut dyn Bar = &mut thing;
    |                              ^^^^^^^^^^ `Bar` cannot be made into an object
    |
-   = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-19538.rs:2:8
    |
@@ -29,6 +28,7 @@ LL |     fn foo<T>(&self, val: T);
 ...
 LL | trait Bar: Foo { }
    |       --- this trait cannot be made into an object...
+   = help: consider moving `foo` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<&mut dyn Bar>` for `&mut Thing`
    = note: required by cast to type `&mut dyn Bar`
 
diff --git a/src/test/ui/issues/issue-20605.stderr b/src/test/ui/issues/issue-20605.stderr
index 25a90df4561..ce3ab6b5998 100644
--- a/src/test/ui/issues/issue-20605.stderr
+++ b/src/test/ui/issues/issue-20605.stderr
@@ -2,9 +2,12 @@ error[E0277]: the size for values of type `dyn Iterator<Item = &'a mut u8>` cann
   --> $DIR/issue-20605.rs:2:17
    |
 LL |     for item in *things { *item = 0 }
-   |                 ^^^^^^^ doesn't have a size known at compile-time
+   |                 ^^^^^^^
+   |                 |
+   |                 expected an implementor of trait `IntoIterator`
+   |                 help: consider mutably borrowing here: `&mut *things`
    |
-   = help: the trait `Sized` is not implemented for `dyn Iterator<Item = &'a mut u8>`
+   = note: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
    = note: required because of the requirements on the impl of `IntoIterator` for `dyn Iterator<Item = &'a mut u8>`
 note: required by `into_iter`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
diff --git a/src/test/ui/issues/issue-23966.stderr b/src/test/ui/issues/issue-23966.stderr
index fff9b3c303a..9c87ee6104a 100644
--- a/src/test/ui/issues/issue-23966.stderr
+++ b/src/test/ui/issues/issue-23966.stderr
@@ -2,7 +2,9 @@ error[E0277]: expected a `FnMut<(_, char)>` closure, found `()`
   --> $DIR/issue-23966.rs:2:32
    |
 LL |     "".chars().fold(|_, _| (), ());
-   |                                ^^ expected an `FnMut<(_, char)>` closure, found `()`
+   |                ----            ^^ expected an `FnMut<(_, char)>` closure, found `()`
+   |                |
+   |                required by a bound introduced by this call
    |
    = help: the trait `FnMut<(_, char)>` is not implemented for `()`
 
diff --git a/src/test/ui/issues/issue-25076.stderr b/src/test/ui/issues/issue-25076.stderr
index ece99596e58..159cc484c5d 100644
--- a/src/test/ui/issues/issue-25076.stderr
+++ b/src/test/ui/issues/issue-25076.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `(): InOut<_>` is not satisfied
   --> $DIR/issue-25076.rs:10:20
    |
 LL |     do_fold(bot(), ());
-   |                    ^^ the trait `InOut<_>` is not implemented for `()`
+   |     -------        ^^ the trait `InOut<_>` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `do_fold`
   --> $DIR/issue-25076.rs:5:18
diff --git a/src/test/ui/issues/issue-28098.stderr b/src/test/ui/issues/issue-28098.stderr
index 70caeb0ea39..6a74f4ed489 100644
--- a/src/test/ui/issues/issue-28098.stderr
+++ b/src/test/ui/issues/issue-28098.stderr
@@ -2,7 +2,9 @@ error[E0277]: `()` is not an iterator
   --> $DIR/issue-28098.rs:2:28
    |
 LL |     let _ = Iterator::next(&mut ());
-   |                            ^^^^^^^ `()` is not an iterator
+   |             -------------- ^^^^^^^ `()` is not an iterator
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `Iterator` is not implemented for `()`
 note: required by `std::iter::Iterator::next`
@@ -29,7 +31,9 @@ error[E0277]: `()` is not an iterator
   --> $DIR/issue-28098.rs:9:28
    |
 LL |     let _ = Iterator::next(&mut ());
-   |                            ^^^^^^^ `()` is not an iterator
+   |             -------------- ^^^^^^^ `()` is not an iterator
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `Iterator` is not implemented for `()`
 note: required by `std::iter::Iterator::next`
@@ -50,7 +54,9 @@ error[E0277]: `()` is not an iterator
   --> $DIR/issue-28098.rs:18:28
    |
 LL |     let _ = Iterator::next(&mut ());
-   |                            ^^^^^^^ `()` is not an iterator
+   |             -------------- ^^^^^^^ `()` is not an iterator
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `Iterator` is not implemented for `()`
 note: required by `std::iter::Iterator::next`
@@ -63,7 +69,9 @@ error[E0277]: `()` is not an iterator
   --> $DIR/issue-28098.rs:22:28
    |
 LL |     let _ = Iterator::next(&mut ());
-   |                            ^^^^^^^ `()` is not an iterator
+   |             -------------- ^^^^^^^ `()` is not an iterator
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `Iterator` is not implemented for `()`
 note: required by `std::iter::Iterator::next`
diff --git a/src/test/ui/issues/issue-30355.stderr b/src/test/ui/issues/issue-30355.stderr
index 79f5db650d9..71bbdf5dec7 100644
--- a/src/test/ui/issues/issue-30355.stderr
+++ b/src/test/ui/issues/issue-30355.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/issue-30355.rs:5:6
+  --> $DIR/issue-30355.rs:5:8
    |
 LL |     &X(*Y)
-   |      ^ doesn't have a size known at compile-time
+   |        ^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[u8]`
    = note: all function arguments must have a statically known size
diff --git a/src/test/ui/issues/issue-34255-1.rs b/src/test/ui/issues/issue-34255-1.rs
index b1071934bb2..c70cd8b5077 100644
--- a/src/test/ui/issues/issue-34255-1.rs
+++ b/src/test/ui/issues/issue-34255-1.rs
@@ -6,5 +6,5 @@ enum Test {
 
 fn main() {
     Test::Drill(field: 42);
-    //~^ ERROR expected type, found
+    //~^ ERROR invalid `struct` delimiters or `fn` call arguments
 }
diff --git a/src/test/ui/issues/issue-34255-1.stderr b/src/test/ui/issues/issue-34255-1.stderr
index c8bad3b3bb5..fbff75e37d9 100644
--- a/src/test/ui/issues/issue-34255-1.stderr
+++ b/src/test/ui/issues/issue-34255-1.stderr
@@ -1,13 +1,18 @@
-error: expected type, found `42`
-  --> $DIR/issue-34255-1.rs:8:24
+error: invalid `struct` delimiters or `fn` call arguments
+  --> $DIR/issue-34255-1.rs:8:5
    |
 LL |     Test::Drill(field: 42);
-   |                      - ^^ expected type
-   |                      |
-   |                      tried to parse a type due to this type ascription
+   |     ^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
-   = note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
+help: if `Test::Drill` is a struct, use braces as delimiters
+   |
+LL |     Test::Drill { field: 42 };
+   |                 ~           ~
+help: if `Test::Drill` is a function, use the arguments directly
+   |
+LL -     Test::Drill(field: 42);
+LL +     Test::Drill(42);
+   | 
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-3794.rs b/src/test/ui/issues/issue-3794.rs
index 408d8d866d8..1809e822c54 100644
--- a/src/test/ui/issues/issue-3794.rs
+++ b/src/test/ui/issues/issue-3794.rs
@@ -1,5 +1,6 @@
 // run-pass
 #![feature(box_syntax)]
+#![allow(dead_code)]
 
 trait T {
     fn print(&self);
diff --git a/src/test/ui/issues/issue-47706-trait.stderr b/src/test/ui/issues/issue-47706-trait.stderr
index 8a6a199148c..2e542644b70 100644
--- a/src/test/ui/issues/issue-47706-trait.stderr
+++ b/src/test/ui/issues/issue-47706-trait.stderr
@@ -4,7 +4,9 @@ error[E0593]: function is expected to take a single 0-tuple as argument, but it
 LL |     fn f(&self, _: ()) {
    |     ------------------ takes 2 distinct arguments
 LL |         None::<()>.map(Self::f);
-   |                        ^^^^^^^ expected function that takes a single 0-tuple as argument
+   |                    --- ^^^^^^^ expected function that takes a single 0-tuple as argument
+   |                    |
+   |                    required by a bound introduced by this call
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-47706.stderr b/src/test/ui/issues/issue-47706.stderr
index d9680a26e09..acf7626c634 100644
--- a/src/test/ui/issues/issue-47706.stderr
+++ b/src/test/ui/issues/issue-47706.stderr
@@ -5,7 +5,9 @@ LL |     pub fn new(foo: Option<i32>, _: ()) -> Foo {
    |     ------------------------------------------ takes 2 arguments
 ...
 LL |         self.foo.map(Foo::new)
-   |                      ^^^^^^^^ expected function that takes 1 argument
+   |                  --- ^^^^^^^^ expected function that takes 1 argument
+   |                  |
+   |                  required by a bound introduced by this call
 
 error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
   --> $DIR/issue-47706.rs:27:9
@@ -14,7 +16,9 @@ LL |     Bar(i32),
    |     -------- takes 1 argument
 ...
 LL |     foo(Qux::Bar);
-   |         ^^^^^^^^ expected function that takes 0 arguments
+   |     --- ^^^^^^^^ expected function that takes 0 arguments
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `foo`
   --> $DIR/issue-47706.rs:22:8
diff --git a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.rs b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.rs
index bb74f0e0dc3..35402dff675 100644
--- a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.rs
+++ b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.rs
@@ -6,7 +6,7 @@ fn missing_discourses() -> Result<isize, ()> {
 
 fn forbidden_narratives() -> Result<isize, ()> {
     missing_discourses()?
-    //~^ ERROR try expression alternatives have incompatible types
+    //~^ ERROR: `?` operator has incompatible types
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
index 2c821aa2308..0f61e03c3b5 100644
--- a/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
+++ b/src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr
@@ -1,9 +1,10 @@
-error[E0308]: try expression alternatives have incompatible types
+error[E0308]: `?` operator has incompatible types
   --> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5
    |
 LL |     missing_discourses()?
    |     ^^^^^^^^^^^^^^^^^^^^^ expected enum `Result`, found `isize`
    |
+   = note: `?` operator cannot convert from `isize` to `Result<isize, ()>`
    = note: expected enum `Result<isize, ()>`
               found type `isize`
 help: try removing this `?`
diff --git a/src/test/ui/issues/issue-56031.stderr b/src/test/ui/issues/issue-56031.stderr
index 3d7acee0a56..7ee5bc6ec61 100644
--- a/src/test/ui/issues/issue-56031.stderr
+++ b/src/test/ui/issues/issue-56031.stderr
@@ -3,6 +3,16 @@ error: missing trait in a trait impl
    |
 LL | impl for T {}
    |     ^
+   |
+help: add a trait here
+   |
+LL | impl Trait for T {}
+   |      +++++
+help: for an inherent impl, drop this `for`
+   |
+LL - impl for T {}
+LL + impl T {}
+   | 
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-59494.stderr b/src/test/ui/issues/issue-59494.stderr
index 90af47dfa79..9b7fe1ef786 100644
--- a/src/test/ui/issues/issue-59494.stderr
+++ b/src/test/ui/issues/issue-59494.stderr
@@ -2,7 +2,9 @@ error[E0277]: expected a `Fn<(_,)>` closure, found `impl Fn<(((_, _), _),)>`
   --> $DIR/issue-59494.rs:21:22
    |
 LL |     let t8 = t8n(t7, t7p(f, g));
-   |                      ^^^^^^^^^ expected an `Fn<(_,)>` closure, found `impl Fn<(((_, _), _),)>`
+   |              ---     ^^^^^^^^^ expected an `Fn<(_,)>` closure, found `impl Fn<(((_, _), _),)>`
+   |              |
+   |              required by a bound introduced by this call
    |
    = help: the trait `Fn<(_,)>` is not implemented for `impl Fn<(((_, _), _),)>`
 note: required by a bound in `t8n`
diff --git a/src/test/ui/issues/issue-60218.stderr b/src/test/ui/issues/issue-60218.stderr
index ac33cfd0402..870b2501447 100644
--- a/src/test/ui/issues/issue-60218.stderr
+++ b/src/test/ui/issues/issue-60218.stderr
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `&u32: Foo` is not satisfied
-  --> $DIR/issue-60218.rs:18:5
+  --> $DIR/issue-60218.rs:18:27
    |
 LL |     trigger_error(vec![], |x: &u32| x)
-   |     ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `&u32`
+   |     -------------         ^^^^^^^^^^^ the trait `Foo` is not implemented for `&u32`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `trigger_error`
   --> $DIR/issue-60218.rs:13:72
diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr
index 2ee55105214..34893cd8f19 100644
--- a/src/test/ui/issues/issue-60283.stderr
+++ b/src/test/ui/issues/issue-60283.stderr
@@ -2,10 +2,11 @@ error[E0631]: type mismatch in function arguments
   --> $DIR/issue-60283.rs:17:13
    |
 LL |     foo((), drop)
-   |             ^^^^
-   |             |
-   |             expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _`
-   |             found signature of `fn(()) -> _`
+   |     ---     ^^^^
+   |     |       |
+   |     |       expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _`
+   |     |       found signature of `fn(()) -> _`
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `foo`
   --> $DIR/issue-60283.rs:12:16
@@ -20,7 +21,9 @@ error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be kn
   --> $DIR/issue-60283.rs:17:13
    |
 LL |     foo((), drop)
-   |             ^^^^ doesn't have a size known at compile-time
+   |     ---     ^^^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sized` is not implemented for `<() as Trait<'_>>::Item`
 note: required by a bound in `std::mem::drop`
diff --git a/src/test/ui/issues/issue-66353.stderr b/src/test/ui/issues/issue-66353.stderr
index 59a521c7360..282e236d3d0 100644
--- a/src/test/ui/issues/issue-66353.stderr
+++ b/src/test/ui/issues/issue-66353.stderr
@@ -8,7 +8,9 @@ error[E0277]: the trait bound `(): _Func<_>` is not satisfied
   --> $DIR/issue-66353.rs:12:41
    |
 LL |     _Func::< <() as _A>::AssocT >::func(());
-   |                                         ^^ the trait `_Func<_>` is not implemented for `()`
+   |     ----------------------------------- ^^ the trait `_Func<_>` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by `_Func::func`
   --> $DIR/issue-66353.rs:4:5
diff --git a/src/test/ui/issues/issue-86865.rs b/src/test/ui/issues/issue-86865.rs
new file mode 100644
index 00000000000..01e0a20a511
--- /dev/null
+++ b/src/test/ui/issues/issue-86865.rs
@@ -0,0 +1,11 @@
+use std::fmt::Write;
+
+fn main() {
+    println!(b"foo");
+    //~^ ERROR format argument must be a string literal
+    //~| HELP consider removing the leading `b`
+    let mut s = String::new();
+    write!(s, b"foo{}", "bar");
+    //~^ ERROR format argument must be a string literal
+    //~| HELP consider removing the leading `b`
+}
diff --git a/src/test/ui/issues/issue-86865.stderr b/src/test/ui/issues/issue-86865.stderr
new file mode 100644
index 00000000000..eed75536631
--- /dev/null
+++ b/src/test/ui/issues/issue-86865.stderr
@@ -0,0 +1,18 @@
+error: format argument must be a string literal
+  --> $DIR/issue-86865.rs:4:14
+   |
+LL |     println!(b"foo");
+   |              -^^^^^
+   |              |
+   |              help: consider removing the leading `b`
+
+error: format argument must be a string literal
+  --> $DIR/issue-86865.rs:8:15
+   |
+LL |     write!(s, b"foo{}", "bar");
+   |               -^^^^^^^
+   |               |
+   |               help: consider removing the leading `b`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/issues/issue-87199.stderr b/src/test/ui/issues/issue-87199.stderr
index fc9418b36b6..0ec5e73f39a 100644
--- a/src/test/ui/issues/issue-87199.stderr
+++ b/src/test/ui/issues/issue-87199.stderr
@@ -20,7 +20,9 @@ error[E0277]: the size for values of type `[i32]` cannot be known at compilation
   --> $DIR/issue-87199.rs:18:22
    |
 LL |     ref_arg::<[i32]>(&[5]);
-   |                      ^^^^ doesn't have a size known at compile-time
+   |     ---------------- ^^^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sized` is not implemented for `[i32]`
 note: required by a bound in `ref_arg`
diff --git a/src/test/ui/issues/issue-8761.stderr b/src/test/ui/issues/issue-8761.stderr
index 4c67dbf6796..c70093bafb6 100644
--- a/src/test/ui/issues/issue-8761.stderr
+++ b/src/test/ui/issues/issue-8761.stderr
@@ -7,7 +7,7 @@ LL |     A = 1i64,
 help: change the type of the numeric literal from `i64` to `isize`
    |
 LL |     A = 1isize,
-   |         ~~~~~~
+   |          ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/issue-8761.rs:5:9
@@ -18,7 +18,7 @@ LL |     B = 2u8
 help: change the type of the numeric literal from `u8` to `isize`
    |
 LL |     B = 2isize
-   |         ~~~~~~
+   |          ~~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/kindck/kindck-impl-type-params-2.stderr b/src/test/ui/kindck/kindck-impl-type-params-2.stderr
index 60ad68cec41..89975e9683d 100644
--- a/src/test/ui/kindck/kindck-impl-type-params-2.stderr
+++ b/src/test/ui/kindck/kindck-impl-type-params-2.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
   --> $DIR/kindck-impl-type-params-2.rs:13:16
    |
 LL |     take_param(&x);
-   |                ^^ the trait `Copy` is not implemented for `Box<{integer}>`
+   |     ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required because of the requirements on the impl of `Foo` for `Box<{integer}>`
   --> $DIR/kindck-impl-type-params-2.rs:6:14
diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr b/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr
index ac43c549d8d..016cd393c85 100644
--- a/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr
+++ b/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
   --> $DIR/kindck-inherited-copy-bound.rs:21:16
    |
 LL |     take_param(&x);
-   |                ^^ the trait `Copy` is not implemented for `Box<{integer}>`
+   |     ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required because of the requirements on the impl of `Foo` for `Box<{integer}>`
   --> $DIR/kindck-inherited-copy-bound.rs:14:14
diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr b/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr
index a486ab17c88..eaf34dff41b 100644
--- a/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr
+++ b/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
   --> $DIR/kindck-inherited-copy-bound.rs:21:16
    |
 LL |     take_param(&x);
-   |                ^^ the trait `Copy` is not implemented for `Box<{integer}>`
+   |     ---------- ^^ the trait `Copy` is not implemented for `Box<{integer}>`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required because of the requirements on the impl of `Foo` for `Box<{integer}>`
   --> $DIR/kindck-inherited-copy-bound.rs:14:14
diff --git a/src/test/ui/lifetimes/lifetime-errors/issue_74400.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/issue_74400.nll.stderr
new file mode 100644
index 00000000000..5a1294f948f
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/issue_74400.nll.stderr
@@ -0,0 +1,30 @@
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/issue_74400.rs:12:5
+   |
+LL |     f(data, identity)
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `T: 'static`...
+
+error[E0308]: mismatched types
+  --> $DIR/issue_74400.rs:12:5
+   |
+LL |     f(data, identity)
+   |     ^^^^^^^^^^^^^^^^^ one type is more general than the other
+   |
+   = note: expected type `for<'r> Fn<(&'r T,)>`
+              found type `Fn<(&T,)>`
+
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/issue_74400.rs:12:5
+   |
+LL |     f(data, identity)
+   |     ^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
+   |
+   = note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 T,)>`, for some specific lifetime `'2`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0308, E0310.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/lifetimes/lifetime-errors/issue_74400.rs b/src/test/ui/lifetimes/lifetime-errors/issue_74400.rs
new file mode 100644
index 00000000000..f83384524f7
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/issue_74400.rs
@@ -0,0 +1,13 @@
+//! Regression test for #74400: Type mismatch in function arguments E0631, E0271 are falsely
+//! recognized as E0308 mismatched types.
+
+use std::convert::identity;
+
+fn main() {}
+
+fn f<T, S>(data: &[T], key: impl Fn(&T) -> S) {
+}
+
+fn g<T>(data: &[T]) {
+    f(data, identity) //~ ERROR implementation of `FnOnce` is not general
+}
diff --git a/src/test/ui/lifetimes/lifetime-errors/issue_74400.stderr b/src/test/ui/lifetimes/lifetime-errors/issue_74400.stderr
new file mode 100644
index 00000000000..d972861a2b5
--- /dev/null
+++ b/src/test/ui/lifetimes/lifetime-errors/issue_74400.stderr
@@ -0,0 +1,11 @@
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/issue_74400.rs:12:5
+   |
+LL |     f(data, identity)
+   |     ^ implementation of `FnOnce` is not general enough
+   |
+   = note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 T,)>`, for some specific lifetime `'2`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/lint-unnecessary-parens.stderr b/src/test/ui/lint/lint-unnecessary-parens.stderr
index 9eae7da9004..1d5f9ebb5e5 100644
--- a/src/test/ui/lint/lint-unnecessary-parens.stderr
+++ b/src/test/ui/lint/lint-unnecessary-parens.stderr
@@ -2,109 +2,210 @@ error: unnecessary parentheses around `return` value
   --> $DIR/lint-unnecessary-parens.rs:13:12
    |
 LL |     return (1);
-   |            ^^^ help: remove these parentheses
+   |            ^ ^
    |
 note: the lint level is defined here
   --> $DIR/lint-unnecessary-parens.rs:3:9
    |
 LL | #![deny(unused_parens)]
    |         ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -     return (1);
+LL +     return 1;
+   | 
 
 error: unnecessary parentheses around `return` value
   --> $DIR/lint-unnecessary-parens.rs:16:12
    |
 LL |     return (X { y });
-   |            ^^^^^^^^^ help: remove these parentheses
+   |            ^       ^
+   |
+help: remove these parentheses
+   |
+LL -     return (X { y });
+LL +     return X { y };
+   | 
 
 error: unnecessary parentheses around type
   --> $DIR/lint-unnecessary-parens.rs:19:46
    |
 LL | pub fn unused_parens_around_return_type() -> (u32) {
-   |                                              ^^^^^ help: remove these parentheses
+   |                                              ^   ^
+   |
+help: remove these parentheses
+   |
+LL - pub fn unused_parens_around_return_type() -> (u32) {
+LL + pub fn unused_parens_around_return_type() -> u32 {
+   | 
 
 error: unnecessary parentheses around block return value
   --> $DIR/lint-unnecessary-parens.rs:25:9
    |
 LL |         (5)
-   |         ^^^ help: remove these parentheses
+   |         ^ ^
+   |
+help: remove these parentheses
+   |
+LL -         (5)
+LL +         5
+   | 
 
 error: unnecessary parentheses around block return value
   --> $DIR/lint-unnecessary-parens.rs:27:5
    |
 LL |     (5)
-   |     ^^^ help: remove these parentheses
+   |     ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     (5)
+LL +     5
+   | 
 
 error: unnecessary parentheses around assigned value
   --> $DIR/lint-unnecessary-parens.rs:44:31
    |
 LL | pub const CONST_ITEM: usize = (10);
-   |                               ^^^^ help: remove these parentheses
+   |                               ^  ^
+   |
+help: remove these parentheses
+   |
+LL - pub const CONST_ITEM: usize = (10);
+LL + pub const CONST_ITEM: usize = 10;
+   | 
 
 error: unnecessary parentheses around assigned value
   --> $DIR/lint-unnecessary-parens.rs:45:33
    |
 LL | pub static STATIC_ITEM: usize = (10);
-   |                                 ^^^^ help: remove these parentheses
+   |                                 ^  ^
+   |
+help: remove these parentheses
+   |
+LL - pub static STATIC_ITEM: usize = (10);
+LL + pub static STATIC_ITEM: usize = 10;
+   | 
 
 error: unnecessary parentheses around function argument
   --> $DIR/lint-unnecessary-parens.rs:49:9
    |
 LL |     bar((true));
-   |         ^^^^^^ help: remove these parentheses
+   |         ^    ^
+   |
+help: remove these parentheses
+   |
+LL -     bar((true));
+LL +     bar(true);
+   | 
 
 error: unnecessary parentheses around `if` condition
   --> $DIR/lint-unnecessary-parens.rs:51:8
    |
 LL |     if (true) {}
-   |        ^^^^^^ help: remove these parentheses
+   |        ^    ^
+   |
+help: remove these parentheses
+   |
+LL -     if (true) {}
+LL +     if true {}
+   | 
 
 error: unnecessary parentheses around `while` condition
   --> $DIR/lint-unnecessary-parens.rs:52:11
    |
 LL |     while (true) {}
-   |           ^^^^^^ help: remove these parentheses
+   |           ^    ^
+   |
+help: remove these parentheses
+   |
+LL -     while (true) {}
+LL +     while true {}
+   | 
 
 error: unnecessary parentheses around `match` scrutinee expression
   --> $DIR/lint-unnecessary-parens.rs:53:11
    |
 LL |     match (true) {
-   |           ^^^^^^ help: remove these parentheses
+   |           ^    ^
+   |
+help: remove these parentheses
+   |
+LL -     match (true) {
+LL +     match true {
+   | 
 
 error: unnecessary parentheses around `let` scrutinee expression
   --> $DIR/lint-unnecessary-parens.rs:56:16
    |
 LL |     if let 1 = (1) {}
-   |                ^^^ help: remove these parentheses
+   |                ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     if let 1 = (1) {}
+LL +     if let 1 = 1 {}
+   | 
 
 error: unnecessary parentheses around `let` scrutinee expression
   --> $DIR/lint-unnecessary-parens.rs:57:19
    |
 LL |     while let 1 = (2) {}
-   |                   ^^^ help: remove these parentheses
+   |                   ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     while let 1 = (2) {}
+LL +     while let 1 = 2 {}
+   | 
 
 error: unnecessary parentheses around method argument
   --> $DIR/lint-unnecessary-parens.rs:73:24
    |
 LL |     X { y: false }.foo((true));
-   |                        ^^^^^^ help: remove these parentheses
+   |                        ^    ^
+   |
+help: remove these parentheses
+   |
+LL -     X { y: false }.foo((true));
+LL +     X { y: false }.foo(true);
+   | 
 
 error: unnecessary parentheses around assigned value
   --> $DIR/lint-unnecessary-parens.rs:75:18
    |
 LL |     let mut _a = (0);
-   |                  ^^^ help: remove these parentheses
+   |                  ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     let mut _a = (0);
+LL +     let mut _a = 0;
+   | 
 
 error: unnecessary parentheses around assigned value
   --> $DIR/lint-unnecessary-parens.rs:76:10
    |
 LL |     _a = (0);
-   |          ^^^ help: remove these parentheses
+   |          ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     _a = (0);
+LL +     _a = 0;
+   | 
 
 error: unnecessary parentheses around assigned value
   --> $DIR/lint-unnecessary-parens.rs:77:11
    |
 LL |     _a += (1);
-   |           ^^^ help: remove these parentheses
+   |           ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     _a += (1);
+LL +     _a += 1;
+   | 
 
 error: aborting due to 17 previous errors
 
diff --git a/src/test/ui/lint/suggestions.stderr b/src/test/ui/lint/suggestions.stderr
index cad25146255..255772ff402 100644
--- a/src/test/ui/lint/suggestions.stderr
+++ b/src/test/ui/lint/suggestions.stderr
@@ -10,13 +10,18 @@ warning: unnecessary parentheses around assigned value
   --> $DIR/suggestions.rs:48:31
    |
 LL |         let mut registry_no = (format!("NX-{}", 74205));
-   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
+   |                               ^                       ^
    |
 note: the lint level is defined here
   --> $DIR/suggestions.rs:4:21
    |
 LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896
    |                     ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -         let mut registry_no = (format!("NX-{}", 74205));
+LL +         let mut registry_no = format!("NX-{}", 74205);
+   | 
 
 warning: variable does not need to be mutable
   --> $DIR/suggestions.rs:48:13
diff --git a/src/test/ui/lint/unused/issue-54538-unused-parens-lint.stderr b/src/test/ui/lint/unused/issue-54538-unused-parens-lint.stderr
index e6d0a359c5c..677b96d3f32 100644
--- a/src/test/ui/lint/unused/issue-54538-unused-parens-lint.stderr
+++ b/src/test/ui/lint/unused/issue-54538-unused-parens-lint.stderr
@@ -2,151 +2,294 @@ error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:16:9
    |
 LL |     let (a) = 0;
-   |         ^^^ help: remove these parentheses
+   |         ^ ^
    |
 note: the lint level is defined here
   --> $DIR/issue-54538-unused-parens-lint.rs:13:9
    |
 LL | #![deny(unused_parens)]
    |         ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -     let (a) = 0;
+LL +     let a = 0;
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:17:9
    |
 LL |     for (a) in 0..1 {}
-   |         ^^^ help: remove these parentheses
+   |         ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     for (a) in 0..1 {}
+LL +     for a in 0..1 {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:18:12
    |
 LL |     if let (a) = 0 {}
-   |            ^^^ help: remove these parentheses
+   |            ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     if let (a) = 0 {}
+LL +     if let a = 0 {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:19:15
    |
 LL |     while let (a) = 0 {}
-   |               ^^^ help: remove these parentheses
+   |               ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     while let (a) = 0 {}
+LL +     while let a = 0 {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:20:12
    |
 LL |     fn foo((a): u8) {}
-   |            ^^^ help: remove these parentheses
+   |            ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     fn foo((a): u8) {}
+LL +     fn foo(a: u8) {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:21:14
    |
 LL |     let _ = |(a): u8| 0;
-   |              ^^^ help: remove these parentheses
+   |              ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     let _ = |(a): u8| 0;
+LL +     let _ = |a: u8| 0;
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:49:12
    |
 LL |     if let (0 | 1) = 0 {}
-   |            ^^^^^^^ help: remove these parentheses
+   |            ^     ^
+   |
+help: remove these parentheses
+   |
+LL -     if let (0 | 1) = 0 {}
+LL +     if let 0 | 1 = 0 {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:50:13
    |
 LL |     if let ((0 | 1),) = (0,) {}
-   |             ^^^^^^^ help: remove these parentheses
+   |             ^     ^
+   |
+help: remove these parentheses
+   |
+LL -     if let ((0 | 1),) = (0,) {}
+LL +     if let (0 | 1,) = (0,) {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:51:13
    |
 LL |     if let [(0 | 1)] = [0] {}
-   |             ^^^^^^^ help: remove these parentheses
+   |             ^     ^
+   |
+help: remove these parentheses
+   |
+LL -     if let [(0 | 1)] = [0] {}
+LL +     if let [0 | 1] = [0] {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:52:16
    |
 LL |     if let 0 | (1 | 2) = 0 {}
-   |                ^^^^^^^ help: remove these parentheses
+   |                ^     ^
+   |
+help: remove these parentheses
+   |
+LL -     if let 0 | (1 | 2) = 0 {}
+LL +     if let 0 | 1 | 2 = 0 {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:54:15
    |
 LL |     if let TS((0 | 1)) = TS(0) {}
-   |               ^^^^^^^ help: remove these parentheses
+   |               ^     ^
+   |
+help: remove these parentheses
+   |
+LL -     if let TS((0 | 1)) = TS(0) {}
+LL +     if let TS(0 | 1) = TS(0) {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:56:20
    |
 LL |     if let NS { f: (0 | 1) } = (NS { f: 0 }) {}
-   |                    ^^^^^^^ help: remove these parentheses
+   |                    ^     ^
+   |
+help: remove these parentheses
+   |
+LL -     if let NS { f: (0 | 1) } = (NS { f: 0 }) {}
+LL +     if let NS { f: 0 | 1 } = (NS { f: 0 }) {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:66:9
    |
 LL |         (_) => {}
-   |         ^^^ help: remove these parentheses
+   |         ^ ^
+   |
+help: remove these parentheses
+   |
+LL -         (_) => {}
+LL +         _ => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:67:9
    |
 LL |         (y) => {}
-   |         ^^^ help: remove these parentheses
+   |         ^ ^
+   |
+help: remove these parentheses
+   |
+LL -         (y) => {}
+LL +         y => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:68:9
    |
 LL |         (ref r) => {}
-   |         ^^^^^^^ help: remove these parentheses
+   |         ^     ^
+   |
+help: remove these parentheses
+   |
+LL -         (ref r) => {}
+LL +         ref r => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:69:9
    |
 LL |         (e @ 1...2) => {}
-   |         ^^^^^^^^^^^ help: remove these parentheses
+   |         ^         ^
+   |
+help: remove these parentheses
+   |
+LL -         (e @ 1...2) => {}
+LL +         e @ 1...2 => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:75:9
    |
 LL |         (e @ &(1...2)) => {}
-   |         ^^^^^^^^^^^^^^ help: remove these parentheses
+   |         ^            ^
+   |
+help: remove these parentheses
+   |
+LL -         (e @ &(1...2)) => {}
+LL +         e @ &(1...2) => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:76:10
    |
 LL |         &(_) => {}
-   |          ^^^ help: remove these parentheses
+   |          ^ ^
+   |
+help: remove these parentheses
+   |
+LL -         &(_) => {}
+LL +         &_ => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:87:9
    |
 LL |         (_) => {}
-   |         ^^^ help: remove these parentheses
+   |         ^ ^
+   |
+help: remove these parentheses
+   |
+LL -         (_) => {}
+LL +         _ => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:88:9
    |
 LL |         (y) => {}
-   |         ^^^ help: remove these parentheses
+   |         ^ ^
+   |
+help: remove these parentheses
+   |
+LL -         (y) => {}
+LL +         y => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:89:9
    |
 LL |         (ref r) => {}
-   |         ^^^^^^^ help: remove these parentheses
+   |         ^     ^
+   |
+help: remove these parentheses
+   |
+LL -         (ref r) => {}
+LL +         ref r => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:90:9
    |
 LL |         (e @ 1..=2) => {}
-   |         ^^^^^^^^^^^ help: remove these parentheses
+   |         ^         ^
+   |
+help: remove these parentheses
+   |
+LL -         (e @ 1..=2) => {}
+LL +         e @ 1..=2 => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:96:9
    |
 LL |         (e @ &(1..=2)) => {}
-   |         ^^^^^^^^^^^^^^ help: remove these parentheses
+   |         ^            ^
+   |
+help: remove these parentheses
+   |
+LL -         (e @ &(1..=2)) => {}
+LL +         e @ &(1..=2) => {}
+   | 
 
 error: unnecessary parentheses around pattern
   --> $DIR/issue-54538-unused-parens-lint.rs:97:10
    |
 LL |         &(_) => {}
-   |          ^^^ help: remove these parentheses
+   |          ^ ^
+   |
+help: remove these parentheses
+   |
+LL -         &(_) => {}
+LL +         &_ => {}
+   | 
 
 error: aborting due to 24 previous errors
 
diff --git a/src/test/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr b/src/test/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr
index 3f6260dc6e1..a715093df4c 100644
--- a/src/test/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr
+++ b/src/test/ui/lint/unused/issue-74883-unused-paren-baren-yield.stderr
@@ -2,49 +2,83 @@ error: unnecessary parentheses around `let` scrutinee expression
   --> $DIR/issue-74883-unused-paren-baren-yield.rs:14:29
    |
 LL |         while let Some(_) = ({yield}) {}
-   |                             ^^^^^^^^^ help: remove these parentheses
+   |                             ^       ^
    |
 note: the lint level is defined here
   --> $DIR/issue-74883-unused-paren-baren-yield.rs:3:24
    |
 LL | #![deny(unused_braces, unused_parens)]
    |                        ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -         while let Some(_) = ({yield}) {}
+LL +         while let Some(_) = {yield} {}
+   | 
 
 error: unnecessary parentheses around `let` scrutinee expression
   --> $DIR/issue-74883-unused-paren-baren-yield.rs:15:29
    |
 LL |         while let Some(_) = ((yield)) {}
-   |                             ^^^^^^^^^ help: remove these parentheses
+   |                             ^       ^
+   |
+help: remove these parentheses
+   |
+LL -         while let Some(_) = ((yield)) {}
+LL +         while let Some(_) = (yield) {}
+   | 
 
 error: unnecessary braces around block return value
   --> $DIR/issue-74883-unused-paren-baren-yield.rs:16:10
    |
 LL |         {{yield}};
-   |          ^^^^^^^ help: remove these braces
+   |          ^     ^
    |
 note: the lint level is defined here
   --> $DIR/issue-74883-unused-paren-baren-yield.rs:3:9
    |
 LL | #![deny(unused_braces, unused_parens)]
    |         ^^^^^^^^^^^^^
+help: remove these braces
+   |
+LL -         {{yield}};
+LL +         {yield};
+   | 
 
 error: unnecessary parentheses around block return value
   --> $DIR/issue-74883-unused-paren-baren-yield.rs:17:10
    |
 LL |         {( yield )};
-   |          ^^^^^^^^^ help: remove these parentheses
+   |          ^^     ^^
+   |
+help: remove these parentheses
+   |
+LL -         {( yield )};
+LL +         {yield};
+   | 
 
 error: unnecessary parentheses around block return value
   --> $DIR/issue-74883-unused-paren-baren-yield.rs:18:30
    |
 LL |         while let Some(_) = {(yield)} {}
-   |                              ^^^^^^^ help: remove these parentheses
+   |                              ^     ^
+   |
+help: remove these parentheses
+   |
+LL -         while let Some(_) = {(yield)} {}
+LL +         while let Some(_) = {yield} {}
+   | 
 
 error: unnecessary braces around block return value
   --> $DIR/issue-74883-unused-paren-baren-yield.rs:19:30
    |
 LL |         while let Some(_) = {{yield}} {}
-   |                              ^^^^^^^ help: remove these braces
+   |                              ^     ^
+   |
+help: remove these braces
+   |
+LL -         while let Some(_) = {{yield}} {}
+LL +         while let Some(_) = {yield} {}
+   | 
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/lint/unused_braces.stderr b/src/test/ui/lint/unused_braces.stderr
index 8fa5dfde61d..7d6fef00ac1 100644
--- a/src/test/ui/lint/unused_braces.stderr
+++ b/src/test/ui/lint/unused_braces.stderr
@@ -2,43 +2,71 @@ warning: unnecessary parentheses around assigned value
   --> $DIR/unused_braces.rs:10:13
    |
 LL |     let _ = (7);
-   |             ^^^ help: remove these parentheses
+   |             ^ ^
    |
 note: the lint level is defined here
   --> $DIR/unused_braces.rs:4:24
    |
 LL | #![warn(unused_braces, unused_parens)]
    |                        ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -     let _ = (7);
+LL +     let _ = 7;
+   | 
 
 warning: unnecessary braces around `if` condition
   --> $DIR/unused_braces.rs:26:8
    |
 LL |     if { true } {
-   |        ^^^^^^^^ help: remove these braces
+   |        ^^    ^^
    |
 note: the lint level is defined here
   --> $DIR/unused_braces.rs:4:9
    |
 LL | #![warn(unused_braces, unused_parens)]
    |         ^^^^^^^^^^^^^
+help: remove these braces
+   |
+LL -     if { true } {
+LL +     if true {
+   | 
 
 warning: unnecessary braces around `while` condition
   --> $DIR/unused_braces.rs:30:11
    |
 LL |     while { false } {
-   |           ^^^^^^^^^ help: remove these braces
+   |           ^^     ^^
+   |
+help: remove these braces
+   |
+LL -     while { false } {
+LL +     while false {
+   | 
 
 warning: unnecessary braces around const expression
   --> $DIR/unused_braces.rs:34:17
    |
 LL |     let _: [u8; { 3 }];
-   |                 ^^^^^ help: remove these braces
+   |                 ^^ ^^
+   |
+help: remove these braces
+   |
+LL -     let _: [u8; { 3 }];
+LL +     let _: [u8; 3];
+   | 
 
 warning: unnecessary braces around function argument
   --> $DIR/unused_braces.rs:37:13
    |
 LL |     consume({ 7 });
-   |             ^^^^^ help: remove these braces
+   |             ^^ ^^
+   |
+help: remove these braces
+   |
+LL -     consume({ 7 });
+LL +     consume(7);
+   | 
 
 warning: 5 warnings emitted
 
diff --git a/src/test/ui/lint/unused_braces_borrow.stderr b/src/test/ui/lint/unused_braces_borrow.stderr
index f018c46fcd3..5a5326cab3b 100644
--- a/src/test/ui/lint/unused_braces_borrow.stderr
+++ b/src/test/ui/lint/unused_braces_borrow.stderr
@@ -2,13 +2,18 @@ warning: unnecessary braces around function argument
   --> $DIR/unused_braces_borrow.rs:24:13
    |
 LL |     consume({ a.b });
-   |             ^^^^^^^ help: remove these braces
+   |             ^^   ^^
    |
 note: the lint level is defined here
   --> $DIR/unused_braces_borrow.rs:4:9
    |
 LL | #![warn(unused_braces)]
    |         ^^^^^^^^^^^^^
+help: remove these braces
+   |
+LL -     consume({ a.b });
+LL +     consume(a.b);
+   | 
 
 warning: 1 warning emitted
 
diff --git a/src/test/ui/lint/unused_parens_json_suggestion.stderr b/src/test/ui/lint/unused_parens_json_suggestion.stderr
index 09f0fc90032..498c25d2e1c 100644
--- a/src/test/ui/lint/unused_parens_json_suggestion.stderr
+++ b/src/test/ui/lint/unused_parens_json_suggestion.stderr
@@ -1,14 +1,19 @@
-{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":596,"byte_end":609,"line_start":16,"line_end":16,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));
+{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":596,"byte_end":597,"line_start":16,"line_end":16,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":"    let _a = (1 / (2 + 3));
   --> $DIR/unused_parens_json_suggestion.rs:16:14
    |
 LL |     let _a = (1 / (2 + 3));
-   |              ^^^^^^^^^^^^^ help: remove these parentheses
+   |              ^           ^
    |
 note: the lint level is defined here
   --> $DIR/unused_parens_json_suggestion.rs:10:9
    |
 LL | #![deny(unused_parens)]
    |         ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -     let _a = (1 / (2 + 3));
+LL +     let _a = 1 / (2 + 3);
+   | 
 
 "}
 {"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error
diff --git a/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr b/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr
index 5fb67fd7c95..08291b10fcc 100644
--- a/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr
+++ b/src/test/ui/lint/unused_parens_remove_json_suggestion.stderr
@@ -1,70 +1,123 @@
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":500,"byte_end":504,"line_start":17,"line_end":17,"column_start":8,"column_end":12,"is_primary":true,"text":[{"text":"    if (_b) {
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":500,"byte_end":501,"line_start":17,"line_end":17,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":"    if (_b) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:17:8
    |
 LL |     if (_b) {
-   |        ^^^^ help: remove these parentheses
+   |        ^  ^
    |
 note: the lint level is defined here
   --> $DIR/unused_parens_remove_json_suggestion.rs:10:9
    |
 LL | #![deny(unused_parens)]
    |         ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -     if (_b) {
+LL +     if _b {
+   | 
 
 "}
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":631,"byte_end":634,"line_start":28,"line_end":28,"column_start":7,"column_end":10,"is_primary":true,"text":[{"text":"    if(c) {
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":631,"byte_end":632,"line_start":28,"line_end":28,"column_start":7,"column_end":8,"is_primary":true,"text":[{"text":"    if(c) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:28:7
    |
 LL |     if(c) {
-   |       ^^^ help: remove these parentheses
+   |       ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     if(c) {
+LL +     if c {
+   | 
 
 "}
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":711,"byte_end":714,"line_start":32,"line_end":32,"column_start":8,"column_end":11,"is_primary":true,"text":[{"text":"    if (c){
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":711,"byte_end":712,"line_start":32,"line_end":32,"column_start":8,"column_end":9,"is_primary":true,"text":[{"text":"    if (c){
   --> $DIR/unused_parens_remove_json_suggestion.rs:32:8
    |
 LL |     if (c){
-   |        ^^^ help: remove these parentheses
+   |        ^ ^
+   |
+help: remove these parentheses
+   |
+LL -     if (c){
+LL +     if c {
+   | 
 
 "}
-{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":808,"line_start":36,"line_end":36,"column_start":11,"column_end":26,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":11,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":808,"line_start":36,"line_end":36,"column_start":11,"column_end":26,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":11,"highlight_end":26}],"label":null,"suggested_replacement":"false && true ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":794,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":807,"byte_end":808,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":793,"byte_end":794,"line_start":36,"line_end":36,"column_start":11,"column_end":12,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":11,"highlight_end":12}],"label":null,"suggested_replacement":"","suggestion_applicability":"MachineApplicable","expansion":null},{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":807,"byte_end":808,"line_start":36,"line_end":36,"column_start":25,"column_end":26,"is_primary":true,"text":[{"text":"    while (false && true){","highlight_start":25,"highlight_end":26}],"label":null,"suggested_replacement":" ","suggestion_applicability":"MachineApplicable","expansion":null}],"children":[],"rendered":null}],"rendered":"error: unnecessary parentheses around `while` condition
   --> $DIR/unused_parens_remove_json_suggestion.rs:36:11
    |
 LL |     while (false && true){
-   |           ^^^^^^^^^^^^^^^ help: remove these parentheses
+   |           ^             ^
+   |
+help: remove these parentheses
+   |
+LL -     while (false && true){
+LL +     while false && true {
+   | 
 
 "}
-{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":821,"byte_end":824,"line_start":37,"line_end":37,"column_start":12,"column_end":15,"is_primary":true,"text":[{"text":"        if (c) {
+{"message":"unnecessary parentheses around `if` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":821,"byte_end":822,"line_start":37,"line_end":37,"column_start":12,"column_end":13,"is_primary":true,"text":[{"text":"        if (c) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:37:12
    |
 LL |         if (c) {
-   |            ^^^ help: remove these parentheses
+   |            ^ ^
+   |
+help: remove these parentheses
+   |
+LL -         if (c) {
+LL +         if c {
+   | 
 
 "}
-{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":918,"byte_end":933,"line_start":43,"line_end":43,"column_start":10,"column_end":25,"is_primary":true,"text":[{"text":"    while(true && false) {
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":918,"byte_end":919,"line_start":43,"line_end":43,"column_start":10,"column_end":11,"is_primary":true,"text":[{"text":"    while(true && false) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:43:10
    |
 LL |     while(true && false) {
-   |          ^^^^^^^^^^^^^^^ help: remove these parentheses
+   |          ^             ^
+   |
+help: remove these parentheses
+   |
+LL -     while(true && false) {
+LL +     while true && false {
+   | 
 
 "}
-{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":995,"line_start":44,"line_end":44,"column_start":18,"column_end":26,"is_primary":true,"text":[{"text":"        for _ in (0 .. 3){
+{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":987,"byte_end":988,"line_start":44,"line_end":44,"column_start":18,"column_end":19,"is_primary":true,"text":[{"text":"        for _ in (0 .. 3){
   --> $DIR/unused_parens_remove_json_suggestion.rs:44:18
    |
 LL |         for _ in (0 .. 3){
-   |                  ^^^^^^^^ help: remove these parentheses
+   |                  ^      ^
+   |
+help: remove these parentheses
+   |
+LL -         for _ in (0 .. 3){
+LL +         for _ in 0 .. 3 {
+   | 
 
 "}
-{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1096,"line_start":49,"line_end":49,"column_start":14,"column_end":22,"is_primary":true,"text":[{"text":"    for _ in (0 .. 3) {
+{"message":"unnecessary parentheses around `for` iterator expression","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1088,"byte_end":1089,"line_start":49,"line_end":49,"column_start":14,"column_end":15,"is_primary":true,"text":[{"text":"    for _ in (0 .. 3) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:49:14
    |
 LL |     for _ in (0 .. 3) {
-   |              ^^^^^^^^ help: remove these parentheses
+   |              ^      ^
+   |
+help: remove these parentheses
+   |
+LL -     for _ in (0 .. 3) {
+LL +     for _ in 0 .. 3 {
+   | 
 
 "}
-{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1147,"byte_end":1162,"line_start":50,"line_end":50,"column_start":15,"column_end":30,"is_primary":true,"text":[{"text":"        while (true && false) {
+{"message":"unnecessary parentheses around `while` condition","code":{"code":"unused_parens","explanation":null},"level":"error","spans":[{"file_name":"$DIR/unused_parens_remove_json_suggestion.rs","byte_start":1147,"byte_end":1148,"line_start":50,"line_end":50,"column_start":15,"column_end":16,"is_primary":true,"text":[{"text":"        while (true && false) {
   --> $DIR/unused_parens_remove_json_suggestion.rs:50:15
    |
 LL |         while (true && false) {
-   |               ^^^^^^^^^^^^^^^ help: remove these parentheses
+   |               ^             ^
+   |
+help: remove these parentheses
+   |
+LL -         while (true && false) {
+LL +         while true && false {
+   | 
 
 "}
 {"message":"aborting due to 9 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 9 previous errors
diff --git a/src/test/ui/meta/expected-error-correct-rev.a.stderr b/src/test/ui/meta/expected-error-correct-rev.a.stderr
index 75c1f695d7e..4adeebe2a59 100644
--- a/src/test/ui/meta/expected-error-correct-rev.a.stderr
+++ b/src/test/ui/meta/expected-error-correct-rev.a.stderr
@@ -9,7 +9,7 @@ LL |     let x: u32 = 22_usize;
 help: change the type of the numeric literal from `usize` to `u32`
    |
 LL |     let x: u32 = 22_u32;
-   |                  ~~~~~~
+   |                     ~~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/meta/meta-expected-error-wrong-rev.a.stderr b/src/test/ui/meta/meta-expected-error-wrong-rev.a.stderr
index 7985357d0ae..012071df2bb 100644
--- a/src/test/ui/meta/meta-expected-error-wrong-rev.a.stderr
+++ b/src/test/ui/meta/meta-expected-error-wrong-rev.a.stderr
@@ -9,7 +9,7 @@ LL |     let x: u32 = 22_usize;
 help: change the type of the numeric literal from `usize` to `u32`
    |
 LL |     let x: u32 = 22_u32;
-   |                  ~~~~~~
+   |                     ~~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
index e725e74efc2..4b494c96115 100644
--- a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
+++ b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.stderr
@@ -17,7 +17,7 @@ LL |     let y: usize = x.foo();
 help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
    |
 LL |     let y: usize = x.foo().try_into().unwrap();
-   |                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                           ++++++++++++++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/mir/remove-zsts-query-cycle.rs b/src/test/ui/mir/remove-zsts-query-cycle.rs
new file mode 100644
index 00000000000..8f93c6cadff
--- /dev/null
+++ b/src/test/ui/mir/remove-zsts-query-cycle.rs
@@ -0,0 +1,16 @@
+// Regression test for #88972. Used to cause a query cycle:
+//   optimized mir -> remove zsts -> layout of a generator -> optimized mir.
+//
+// edition:2018
+// compile-flags: --crate-type=lib
+// build-pass
+
+pub async fn listen() -> Result<(), std::io::Error> {
+    let f = do_async();
+    std::mem::forget(f);
+    Ok(())
+}
+
+pub async fn do_async() {
+    listen().await.unwrap()
+}
diff --git a/src/test/ui/mismatched_types/E0631.stderr b/src/test/ui/mismatched_types/E0631.stderr
index c8e81c93e2c..1f2e169c681 100644
--- a/src/test/ui/mismatched_types/E0631.stderr
+++ b/src/test/ui/mismatched_types/E0631.stderr
@@ -33,7 +33,9 @@ LL |     fn f(_: u64) {}
    |     ------------ found signature of `fn(u64) -> _`
 ...
 LL |     foo(f);
-   |         ^ expected signature of `fn(usize) -> _`
+   |     --- ^ expected signature of `fn(usize) -> _`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `foo`
   --> $DIR/E0631.rs:3:11
@@ -48,7 +50,9 @@ LL |     fn f(_: u64) {}
    |     ------------ found signature of `fn(u64) -> _`
 ...
 LL |     bar(f);
-   |         ^ expected signature of `fn(usize) -> _`
+   |     --- ^ expected signature of `fn(usize) -> _`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `bar`
   --> $DIR/E0631.rs:4:11
diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr
index 67900172464..e8fcf80e940 100644
--- a/src/test/ui/mismatched_types/closure-arg-count.stderr
+++ b/src/test/ui/mismatched_types/closure-arg-count.stderr
@@ -119,7 +119,9 @@ error[E0593]: function is expected to take a single 2-tuple as argument, but it
   --> $DIR/closure-arg-count.rs:24:57
    |
 LL |     let _it = vec![1, 2, 3].into_iter().enumerate().map(foo);
-   |                                                         ^^^ expected function that takes a single 2-tuple as argument
+   |                                                     --- ^^^ expected function that takes a single 2-tuple as argument
+   |                                                     |
+   |                                                     required by a bound introduced by this call
 ...
 LL | fn foo() {}
    | -------- takes 0 arguments
@@ -130,13 +132,17 @@ error[E0593]: closure is expected to take a single 2-tuple as argument, but it t
 LL |     let bar = |i, x, y| i;
    |               --------- takes 3 distinct arguments
 LL |     let _it = vec![1, 2, 3].into_iter().enumerate().map(bar);
-   |                                                         ^^^ expected closure that takes a single 2-tuple as argument
+   |                                                     --- ^^^ expected closure that takes a single 2-tuple as argument
+   |                                                     |
+   |                                                     required by a bound introduced by this call
 
 error[E0593]: function is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
   --> $DIR/closure-arg-count.rs:29:57
    |
 LL |     let _it = vec![1, 2, 3].into_iter().enumerate().map(qux);
-   |                                                         ^^^ expected function that takes a single 2-tuple as argument
+   |                                                     --- ^^^ expected function that takes a single 2-tuple as argument
+   |                                                     |
+   |                                                     required by a bound introduced by this call
 ...
 LL | fn qux(x: usize, y: usize) {}
    | -------------------------- takes 2 distinct arguments
@@ -145,13 +151,17 @@ error[E0593]: function is expected to take 1 argument, but it takes 2 arguments
   --> $DIR/closure-arg-count.rs:32:45
    |
 LL |     let _it = vec![1, 2, 3].into_iter().map(usize::checked_add);
-   |                                             ^^^^^^^^^^^^^^^^^^ expected function that takes 1 argument
+   |                                         --- ^^^^^^^^^^^^^^^^^^ expected function that takes 1 argument
+   |                                         |
+   |                                         required by a bound introduced by this call
 
 error[E0593]: function is expected to take 0 arguments, but it takes 1 argument
   --> $DIR/closure-arg-count.rs:35:10
    |
 LL |     call(Foo);
-   |          ^^^ expected function that takes 0 arguments
+   |     ---- ^^^ expected function that takes 0 arguments
+   |     |
+   |     required by a bound introduced by this call
 ...
 LL | struct Foo(u8);
    | --------------- takes 1 argument
diff --git a/src/test/ui/mismatched_types/fn-variance-1.stderr b/src/test/ui/mismatched_types/fn-variance-1.stderr
index afde894b304..ce1dde94b5d 100644
--- a/src/test/ui/mismatched_types/fn-variance-1.stderr
+++ b/src/test/ui/mismatched_types/fn-variance-1.stderr
@@ -5,7 +5,9 @@ LL | fn takes_mut(x: &mut isize) { }
    | --------------------------- found signature of `for<'r> fn(&'r mut isize) -> _`
 ...
 LL |     apply(&3, takes_mut);
-   |               ^^^^^^^^^ expected signature of `fn(&{integer}) -> _`
+   |     -----     ^^^^^^^^^ expected signature of `fn(&{integer}) -> _`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `apply`
   --> $DIR/fn-variance-1.rs:5:37
@@ -20,7 +22,9 @@ LL | fn takes_imm(x: &isize) { }
    | ----------------------- found signature of `for<'r> fn(&'r isize) -> _`
 ...
 LL |     apply(&mut 3, takes_imm);
-   |                   ^^^^^^^^^ expected signature of `fn(&mut {integer}) -> _`
+   |     -----         ^^^^^^^^^ expected signature of `fn(&mut {integer}) -> _`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `apply`
   --> $DIR/fn-variance-1.rs:5:37
diff --git a/src/test/ui/mismatched_types/issue-26480.stderr b/src/test/ui/mismatched_types/issue-26480.stderr
index e480bb250b2..3e2ebf43b8c 100644
--- a/src/test/ui/mismatched_types/issue-26480.stderr
+++ b/src/test/ui/mismatched_types/issue-26480.stderr
@@ -11,7 +11,7 @@ LL |     write!(hello);
 help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit
    |
 LL |                   ($arr.len() * size_of($arr[0])).try_into().unwrap());
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                   +                             +++++++++++++++++++++
 
 error[E0605]: non-primitive cast: `{integer}` as `()`
   --> $DIR/issue-26480.rs:22:19
diff --git a/src/test/ui/mismatched_types/numeric-literal-cast.stderr b/src/test/ui/mismatched_types/numeric-literal-cast.stderr
index 7ab52249798..55e45a8f162 100644
--- a/src/test/ui/mismatched_types/numeric-literal-cast.stderr
+++ b/src/test/ui/mismatched_types/numeric-literal-cast.stderr
@@ -7,7 +7,7 @@ LL |     foo(1u8);
 help: change the type of the numeric literal from `u8` to `u16`
    |
 LL |     foo(1u16);
-   |         ~~~~
+   |          ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-literal-cast.rs:8:10
@@ -18,7 +18,7 @@ LL |     foo1(2f32);
 help: change the type of the numeric literal from `f32` to `f64`
    |
 LL |     foo1(2f64);
-   |          ~~~~
+   |           ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-literal-cast.rs:10:10
@@ -29,7 +29,7 @@ LL |     foo2(3i16);
 help: change the type of the numeric literal from `i16` to `i32`
    |
 LL |     foo2(3i32);
-   |          ~~~~
+   |           ~~~
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs
index ad59462e9bd..44ec28f53cc 100644
--- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs
+++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.rs
@@ -16,5 +16,6 @@ pub fn main() {
     let z = call_it(3, f);
     //~^ ERROR type mismatch
     //~| NOTE expected signature of `fn(isize, isize) -> _`
+    //~| NOTE required by a bound introduced by this call
     println!("{}", z);
 }
diff --git a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
index 4406f8a9e58..f9ef5bc4e39 100644
--- a/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
+++ b/src/test/ui/mismatched_types/unboxed-closures-vtable-mismatch.stderr
@@ -5,7 +5,9 @@ LL |     let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y });
    |                       ----------------------------- found signature of `fn(usize, isize) -> _`
 LL |
 LL |     let z = call_it(3, f);
-   |                        ^ expected signature of `fn(isize, isize) -> _`
+   |             -------    ^ expected signature of `fn(isize, isize) -> _`
+   |             |
+   |             required by a bound introduced by this call
    |
 note: required by a bound in `call_it`
   --> $DIR/unboxed-closures-vtable-mismatch.rs:7:14
diff --git a/src/test/ui/monomorphize-abi-alignment.rs b/src/test/ui/monomorphize-abi-alignment.rs
index 637b09fc04e..a8d8bd1d5fd 100644
--- a/src/test/ui/monomorphize-abi-alignment.rs
+++ b/src/test/ui/monomorphize-abi-alignment.rs
@@ -1,6 +1,7 @@
 // run-pass
 
 #![allow(non_upper_case_globals)]
+#![allow(dead_code)]
 /*!
  * On x86_64-linux-gnu and possibly other platforms, structs get 8-byte "preferred" alignment,
  * but their "ABI" alignment (i.e., what actually matters for data layout) is the largest alignment
diff --git a/src/test/ui/moves/move-1-unique.rs b/src/test/ui/moves/move-1-unique.rs
index 48baead074a..7d3987f6560 100644
--- a/src/test/ui/moves/move-1-unique.rs
+++ b/src/test/ui/moves/move-1-unique.rs
@@ -1,5 +1,6 @@
 // run-pass
 #![allow(unused_mut)]
+#![allow(dead_code)]
 #![feature(box_syntax)]
 
 #[derive(Clone)]
diff --git a/src/test/ui/moves/move-3-unique.rs b/src/test/ui/moves/move-3-unique.rs
index 55b10e057d8..d23a852433f 100644
--- a/src/test/ui/moves/move-3-unique.rs
+++ b/src/test/ui/moves/move-3-unique.rs
@@ -1,5 +1,6 @@
 // run-pass
 #![allow(unused_mut)]
+#![allow(dead_code)]
 #![feature(box_syntax)]
 
 #[derive(Clone)]
diff --git a/src/test/ui/mutexguard-sync.stderr b/src/test/ui/mutexguard-sync.stderr
index 172e257ebf0..b3c77b13eaf 100644
--- a/src/test/ui/mutexguard-sync.stderr
+++ b/src/test/ui/mutexguard-sync.stderr
@@ -2,7 +2,9 @@ error[E0277]: `Cell<i32>` cannot be shared between threads safely
   --> $DIR/mutexguard-sync.rs:11:15
    |
 LL |     test_sync(guard);
-   |               ^^^^^ `Cell<i32>` cannot be shared between threads safely
+   |     --------- ^^^^^ `Cell<i32>` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sync` is not implemented for `Cell<i32>`
    = note: required because of the requirements on the impl of `Sync` for `MutexGuard<'_, Cell<i32>>`
diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr
index e4e10716388..b6108572292 100644
--- a/src/test/ui/namespace/namespace-mix.stderr
+++ b/src/test/ui/namespace/namespace-mix.stderr
@@ -100,7 +100,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:33:11
    |
 LL |     check(m1::S{});
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -112,7 +114,9 @@ error[E0277]: the trait bound `c::S: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:35:11
    |
 LL |     check(m2::S{});
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `c::S`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `c::S`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -124,7 +128,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:36:11
    |
 LL |     check(m2::S);
-   |           ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -136,7 +142,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:39:11
    |
 LL |     check(xm1::S{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -148,7 +156,9 @@ error[E0277]: the trait bound `namespace_mix::c::S: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:41:11
    |
 LL |     check(xm2::S{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::S`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::S`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -160,7 +170,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:42:11
    |
 LL |     check(xm2::S);
-   |           ^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -172,7 +184,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:55:11
    |
 LL |     check(m3::TS{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -184,7 +198,9 @@ error[E0277]: the trait bound `fn() -> c::TS {c::TS}: Impossible` is not satisfi
   --> $DIR/namespace-mix.rs:56:11
    |
 LL |     check(m3::TS);
-   |           ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS}`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS}`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -196,7 +212,9 @@ error[E0277]: the trait bound `c::TS: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:57:11
    |
 LL |     check(m4::TS{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `c::TS`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::TS`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -208,7 +226,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:58:11
    |
 LL |     check(m4::TS);
-   |           ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -220,7 +240,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:61:11
    |
 LL |     check(xm3::TS{});
-   |           ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -232,7 +254,9 @@ error[E0277]: the trait bound `fn() -> namespace_mix::c::TS {namespace_mix::c::T
   --> $DIR/namespace-mix.rs:62:11
    |
 LL |     check(xm3::TS);
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -244,7 +268,9 @@ error[E0277]: the trait bound `namespace_mix::c::TS: Impossible` is not satisfie
   --> $DIR/namespace-mix.rs:63:11
    |
 LL |     check(xm4::TS{});
-   |           ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::TS`
+   |     ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::TS`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -256,7 +282,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:64:11
    |
 LL |     check(xm4::TS);
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -268,7 +296,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:77:11
    |
 LL |     check(m5::US{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -280,7 +310,9 @@ error[E0277]: the trait bound `c::US: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:78:11
    |
 LL |     check(m5::US);
-   |           ^^^^^^ the trait `Impossible` is not implemented for `c::US`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `c::US`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -292,7 +324,9 @@ error[E0277]: the trait bound `c::US: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:79:11
    |
 LL |     check(m6::US{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `c::US`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::US`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -304,7 +338,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:80:11
    |
 LL |     check(m6::US);
-   |           ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -316,7 +352,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:83:11
    |
 LL |     check(xm5::US{});
-   |           ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -328,7 +366,9 @@ error[E0277]: the trait bound `namespace_mix::c::US: Impossible` is not satisfie
   --> $DIR/namespace-mix.rs:84:11
    |
 LL |     check(xm5::US);
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -340,7 +380,9 @@ error[E0277]: the trait bound `namespace_mix::c::US: Impossible` is not satisfie
   --> $DIR/namespace-mix.rs:85:11
    |
 LL |     check(xm6::US{});
-   |           ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US`
+   |     ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::US`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -352,7 +394,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:86:11
    |
 LL |     check(xm6::US);
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -364,7 +408,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:99:11
    |
 LL |     check(m7::V{});
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -376,7 +422,9 @@ error[E0277]: the trait bound `c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:101:11
    |
 LL |     check(m8::V{});
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `c::E`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `c::E`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -388,7 +436,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:102:11
    |
 LL |     check(m8::V);
-   |           ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -400,7 +450,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:105:11
    |
 LL |     check(xm7::V{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -412,7 +464,9 @@ error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:107:11
    |
 LL |     check(xm8::V{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -424,7 +478,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:108:11
    |
 LL |     check(xm8::V);
-   |           ^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -436,7 +492,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:121:11
    |
 LL |     check(m9::TV{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -448,7 +506,9 @@ error[E0277]: the trait bound `fn() -> c::E {c::E::TV}: Impossible` is not satis
   --> $DIR/namespace-mix.rs:122:11
    |
 LL |     check(m9::TV);
-   |           ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::E {c::E::TV}`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::E {c::E::TV}`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -460,7 +520,9 @@ error[E0277]: the trait bound `c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:123:11
    |
 LL |     check(mA::TV{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `c::E`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::E`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -472,7 +534,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:124:11
    |
 LL |     check(mA::TV);
-   |           ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -484,7 +548,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:127:11
    |
 LL |     check(xm9::TV{});
-   |           ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -496,7 +562,9 @@ error[E0277]: the trait bound `fn() -> namespace_mix::c::E {namespace_mix::xm7::
   --> $DIR/namespace-mix.rs:128:11
    |
 LL |     check(xm9::TV);
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -508,7 +576,9 @@ error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:129:11
    |
 LL |     check(xmA::TV{});
-   |           ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+   |     ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -520,7 +590,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:130:11
    |
 LL |     check(xmA::TV);
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -532,7 +604,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:143:11
    |
 LL |     check(mB::UV{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -544,7 +618,9 @@ error[E0277]: the trait bound `c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:144:11
    |
 LL |     check(mB::UV);
-   |           ^^^^^^ the trait `Impossible` is not implemented for `c::E`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `c::E`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -556,7 +632,9 @@ error[E0277]: the trait bound `c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:145:11
    |
 LL |     check(mC::UV{});
-   |           ^^^^^^^^ the trait `Impossible` is not implemented for `c::E`
+   |     ----- ^^^^^^^^ the trait `Impossible` is not implemented for `c::E`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -568,7 +646,9 @@ error[E0277]: the trait bound `c::Item: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:146:11
    |
 LL |     check(mC::UV);
-   |           ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -580,7 +660,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:149:11
    |
 LL |     check(xmB::UV{});
-   |           ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -592,7 +674,9 @@ error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:150:11
    |
 LL |     check(xmB::UV);
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -604,7 +688,9 @@ error[E0277]: the trait bound `namespace_mix::c::E: Impossible` is not satisfied
   --> $DIR/namespace-mix.rs:151:11
    |
 LL |     check(xmC::UV{});
-   |           ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+   |     ----- ^^^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::E`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
@@ -616,7 +702,9 @@ error[E0277]: the trait bound `namespace_mix::c::Item: Impossible` is not satisf
   --> $DIR/namespace-mix.rs:152:11
    |
 LL |     check(xmC::UV);
-   |           ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `namespace_mix::c::Item`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `check`
   --> $DIR/namespace-mix.rs:21:13
diff --git a/src/test/ui/no_send-rc.stderr b/src/test/ui/no_send-rc.stderr
index f8be5e76f7a..ce25da559da 100644
--- a/src/test/ui/no_send-rc.stderr
+++ b/src/test/ui/no_send-rc.stderr
@@ -2,7 +2,9 @@ error[E0277]: `Rc<{integer}>` cannot be sent between threads safely
   --> $DIR/no_send-rc.rs:7:9
    |
 LL |     bar(x);
-   |         ^ `Rc<{integer}>` cannot be sent between threads safely
+   |     --- ^ `Rc<{integer}>` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Send` is not implemented for `Rc<{integer}>`
 note: required by a bound in `bar`
diff --git a/src/test/ui/no_send-struct.stderr b/src/test/ui/no_send-struct.stderr
index 2f8cf3569ae..ee7bdf282b7 100644
--- a/src/test/ui/no_send-struct.stderr
+++ b/src/test/ui/no_send-struct.stderr
@@ -2,7 +2,9 @@ error[E0277]: `Foo` cannot be sent between threads safely
   --> $DIR/no_send-struct.rs:15:9
    |
 LL |     bar(x);
-   |         ^ `Foo` cannot be sent between threads safely
+   |     --- ^ `Foo` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Send` is not implemented for `Foo`
 note: required by a bound in `bar`
diff --git a/src/test/ui/no_share-struct.stderr b/src/test/ui/no_share-struct.stderr
index 8983b086789..9ce3a318f1d 100644
--- a/src/test/ui/no_share-struct.stderr
+++ b/src/test/ui/no_share-struct.stderr
@@ -2,7 +2,9 @@ error[E0277]: `Foo` cannot be shared between threads safely
   --> $DIR/no_share-struct.rs:12:9
    |
 LL |     bar(x);
-   |         ^ `Foo` cannot be shared between threads safely
+   |     --- ^ `Foo` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sync` is not implemented for `Foo`
 note: required by a bound in `bar`
diff --git a/src/test/ui/numeric/const-scope.stderr b/src/test/ui/numeric/const-scope.stderr
index 6732391e1a1..4e4bcdf234d 100644
--- a/src/test/ui/numeric/const-scope.stderr
+++ b/src/test/ui/numeric/const-scope.stderr
@@ -7,7 +7,7 @@ LL | const C: i32 = 1i8;
 help: change the type of the numeric literal from `i8` to `i32`
    |
 LL | const C: i32 = 1i32;
-   |                ~~~~
+   |                 ~~~
 
 error[E0308]: mismatched types
   --> $DIR/const-scope.rs:2:15
@@ -26,7 +26,7 @@ LL |     let c: i32 = 1i8;
 help: change the type of the numeric literal from `i8` to `i32`
    |
 LL |     let c: i32 = 1i32;
-   |                  ~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/const-scope.rs:6:17
@@ -47,7 +47,7 @@ LL |     let c: i32 = 1i8;
 help: change the type of the numeric literal from `i8` to `i32`
    |
 LL |     let c: i32 = 1i32;
-   |                  ~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/const-scope.rs:11:17
@@ -60,7 +60,7 @@ LL |     let d: i8 = c;
 help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     let d: i8 = c.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~
+   |                  ++++++++++++++++++++
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/numeric/len.stderr b/src/test/ui/numeric/len.stderr
index 9a3248c5720..6319c1ead24 100644
--- a/src/test/ui/numeric/len.stderr
+++ b/src/test/ui/numeric/len.stderr
@@ -7,7 +7,7 @@ LL |     test(array.len());
 help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     test(array.len().try_into().unwrap());
-   |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/numeric/numeric-cast-2.stderr b/src/test/ui/numeric/numeric-cast-2.stderr
index 83d8ce5eea9..a7b342739aa 100644
--- a/src/test/ui/numeric/numeric-cast-2.stderr
+++ b/src/test/ui/numeric/numeric-cast-2.stderr
@@ -9,27 +9,33 @@ LL |     let x: u16 = foo();
 help: you can convert an `i32` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     let x: u16 = foo().try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-2.rs:7:18
    |
 LL |     let y: i64 = x + x;
-   |            ---   ^^^^^
-   |            |     |
-   |            |     expected `i64`, found `u16`
-   |            |     help: you can convert a `u16` to an `i64`: `(x + x).into()`
+   |            ---   ^^^^^ expected `i64`, found `u16`
+   |            |
    |            expected due to this
+   |
+help: you can convert a `u16` to an `i64`
+   |
+LL |     let y: i64 = (x + x).into();
+   |                  +     ++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-2.rs:9:18
    |
 LL |     let z: i32 = x + x;
-   |            ---   ^^^^^
-   |            |     |
-   |            |     expected `i32`, found `u16`
-   |            |     help: you can convert a `u16` to an `i32`: `(x + x).into()`
+   |            ---   ^^^^^ expected `i32`, found `u16`
+   |            |
    |            expected due to this
+   |
+help: you can convert a `u16` to an `i32`
+   |
+LL |     let z: i32 = (x + x).into();
+   |                  +     ++++++++
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/numeric/numeric-cast-binop.stderr b/src/test/ui/numeric/numeric-cast-binop.stderr
index b0ff50748fe..2f58f164985 100644
--- a/src/test/ui/numeric/numeric-cast-binop.stderr
+++ b/src/test/ui/numeric/numeric-cast-binop.stderr
@@ -7,7 +7,7 @@ LL |         x_u8 > x_u16;
 help: you can convert `x_u8` from `u8` to `u16`, matching the type of `x_u16`
    |
 LL |         u16::from(x_u8) > x_u16;
-   |         ~~~~~~~~~~~~~~~
+   |         ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:25:16
@@ -18,7 +18,7 @@ LL |         x_u8 > x_u32;
 help: you can convert `x_u8` from `u8` to `u32`, matching the type of `x_u32`
    |
 LL |         u32::from(x_u8) > x_u32;
-   |         ~~~~~~~~~~~~~~~
+   |         ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:27:16
@@ -29,7 +29,7 @@ LL |         x_u8 > x_u64;
 help: you can convert `x_u8` from `u8` to `u64`, matching the type of `x_u64`
    |
 LL |         u64::from(x_u8) > x_u64;
-   |         ~~~~~~~~~~~~~~~
+   |         ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:29:16
@@ -40,7 +40,7 @@ LL |         x_u8 > x_u128;
 help: you can convert `x_u8` from `u8` to `u128`, matching the type of `x_u128`
    |
 LL |         u128::from(x_u8) > x_u128;
-   |         ~~~~~~~~~~~~~~~~
+   |         +++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:31:16
@@ -51,16 +51,18 @@ LL |         x_u8 > x_usize;
 help: you can convert `x_u8` from `u8` to `usize`, matching the type of `x_usize`
    |
 LL |         usize::from(x_u8) > x_usize;
-   |         ~~~~~~~~~~~~~~~~~
+   |         ++++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:34:17
    |
 LL |         x_u16 > x_u8;
-   |                 ^^^^
-   |                 |
-   |                 expected `u16`, found `u8`
-   |                 help: you can convert a `u8` to a `u16`: `x_u8.into()`
+   |                 ^^^^ expected `u16`, found `u8`
+   |
+help: you can convert a `u8` to a `u16`
+   |
+LL |         x_u16 > x_u8.into();
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:36:17
@@ -71,7 +73,7 @@ LL |         x_u16 > x_u32;
 help: you can convert `x_u16` from `u16` to `u32`, matching the type of `x_u32`
    |
 LL |         u32::from(x_u16) > x_u32;
-   |         ~~~~~~~~~~~~~~~~
+   |         ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:38:17
@@ -82,7 +84,7 @@ LL |         x_u16 > x_u64;
 help: you can convert `x_u16` from `u16` to `u64`, matching the type of `x_u64`
    |
 LL |         u64::from(x_u16) > x_u64;
-   |         ~~~~~~~~~~~~~~~~
+   |         ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:40:17
@@ -93,7 +95,7 @@ LL |         x_u16 > x_u128;
 help: you can convert `x_u16` from `u16` to `u128`, matching the type of `x_u128`
    |
 LL |         u128::from(x_u16) > x_u128;
-   |         ~~~~~~~~~~~~~~~~~
+   |         +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:42:17
@@ -104,25 +106,29 @@ LL |         x_u16 > x_usize;
 help: you can convert `x_u16` from `u16` to `usize`, matching the type of `x_usize`
    |
 LL |         usize::from(x_u16) > x_usize;
-   |         ~~~~~~~~~~~~~~~~~~
+   |         ++++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:45:17
    |
 LL |         x_u32 > x_u8;
-   |                 ^^^^
-   |                 |
-   |                 expected `u32`, found `u8`
-   |                 help: you can convert a `u8` to a `u32`: `x_u8.into()`
+   |                 ^^^^ expected `u32`, found `u8`
+   |
+help: you can convert a `u8` to a `u32`
+   |
+LL |         x_u32 > x_u8.into();
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:47:17
    |
 LL |         x_u32 > x_u16;
-   |                 ^^^^^
-   |                 |
-   |                 expected `u32`, found `u16`
-   |                 help: you can convert a `u16` to a `u32`: `x_u16.into()`
+   |                 ^^^^^ expected `u32`, found `u16`
+   |
+help: you can convert a `u16` to a `u32`
+   |
+LL |         x_u32 > x_u16.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:49:17
@@ -133,7 +139,7 @@ LL |         x_u32 > x_u64;
 help: you can convert `x_u32` from `u32` to `u64`, matching the type of `x_u64`
    |
 LL |         u64::from(x_u32) > x_u64;
-   |         ~~~~~~~~~~~~~~~~
+   |         ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:51:17
@@ -144,7 +150,7 @@ LL |         x_u32 > x_u128;
 help: you can convert `x_u32` from `u32` to `u128`, matching the type of `x_u128`
    |
 LL |         u128::from(x_u32) > x_u128;
-   |         ~~~~~~~~~~~~~~~~~
+   |         +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:53:17
@@ -155,34 +161,40 @@ LL |         x_u32 > x_usize;
 help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
    |
 LL |         x_u32 > x_usize.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:56:17
    |
 LL |         x_u64 > x_u8;
-   |                 ^^^^
-   |                 |
-   |                 expected `u64`, found `u8`
-   |                 help: you can convert a `u8` to a `u64`: `x_u8.into()`
+   |                 ^^^^ expected `u64`, found `u8`
+   |
+help: you can convert a `u8` to a `u64`
+   |
+LL |         x_u64 > x_u8.into();
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:58:17
    |
 LL |         x_u64 > x_u16;
-   |                 ^^^^^
-   |                 |
-   |                 expected `u64`, found `u16`
-   |                 help: you can convert a `u16` to a `u64`: `x_u16.into()`
+   |                 ^^^^^ expected `u64`, found `u16`
+   |
+help: you can convert a `u16` to a `u64`
+   |
+LL |         x_u64 > x_u16.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:60:17
    |
 LL |         x_u64 > x_u32;
-   |                 ^^^^^
-   |                 |
-   |                 expected `u64`, found `u32`
-   |                 help: you can convert a `u32` to a `u64`: `x_u32.into()`
+   |                 ^^^^^ expected `u64`, found `u32`
+   |
+help: you can convert a `u32` to a `u64`
+   |
+LL |         x_u64 > x_u32.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:62:17
@@ -193,7 +205,7 @@ LL |         x_u64 > x_u128;
 help: you can convert `x_u64` from `u64` to `u128`, matching the type of `x_u128`
    |
 LL |         u128::from(x_u64) > x_u128;
-   |         ~~~~~~~~~~~~~~~~~
+   |         +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:64:17
@@ -204,43 +216,51 @@ LL |         x_u64 > x_usize;
 help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit
    |
 LL |         x_u64 > x_usize.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:67:18
    |
 LL |         x_u128 > x_u8;
-   |                  ^^^^
-   |                  |
-   |                  expected `u128`, found `u8`
-   |                  help: you can convert a `u8` to a `u128`: `x_u8.into()`
+   |                  ^^^^ expected `u128`, found `u8`
+   |
+help: you can convert a `u8` to a `u128`
+   |
+LL |         x_u128 > x_u8.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:69:18
    |
 LL |         x_u128 > x_u16;
-   |                  ^^^^^
-   |                  |
-   |                  expected `u128`, found `u16`
-   |                  help: you can convert a `u16` to a `u128`: `x_u16.into()`
+   |                  ^^^^^ expected `u128`, found `u16`
+   |
+help: you can convert a `u16` to a `u128`
+   |
+LL |         x_u128 > x_u16.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:71:18
    |
 LL |         x_u128 > x_u32;
-   |                  ^^^^^
-   |                  |
-   |                  expected `u128`, found `u32`
-   |                  help: you can convert a `u32` to a `u128`: `x_u32.into()`
+   |                  ^^^^^ expected `u128`, found `u32`
+   |
+help: you can convert a `u32` to a `u128`
+   |
+LL |         x_u128 > x_u32.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:73:18
    |
 LL |         x_u128 > x_u64;
-   |                  ^^^^^
-   |                  |
-   |                  expected `u128`, found `u64`
-   |                  help: you can convert a `u64` to a `u128`: `x_u64.into()`
+   |                  ^^^^^ expected `u128`, found `u64`
+   |
+help: you can convert a `u64` to a `u128`
+   |
+LL |         x_u128 > x_u64.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:75:18
@@ -251,25 +271,29 @@ LL |         x_u128 > x_usize;
 help: you can convert a `usize` to a `u128` and panic if the converted value doesn't fit
    |
 LL |         x_u128 > x_usize.try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:78:19
    |
 LL |         x_usize > x_u8;
-   |                   ^^^^
-   |                   |
-   |                   expected `usize`, found `u8`
-   |                   help: you can convert a `u8` to a `usize`: `x_u8.into()`
+   |                   ^^^^ expected `usize`, found `u8`
+   |
+help: you can convert a `u8` to a `usize`
+   |
+LL |         x_usize > x_u8.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:80:19
    |
 LL |         x_usize > x_u16;
-   |                   ^^^^^
-   |                   |
-   |                   expected `usize`, found `u16`
-   |                   help: you can convert a `u16` to a `usize`: `x_u16.into()`
+   |                   ^^^^^ expected `usize`, found `u16`
+   |
+help: you can convert a `u16` to a `usize`
+   |
+LL |         x_usize > x_u16.into();
+   |                        +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:82:19
@@ -280,7 +304,7 @@ LL |         x_usize > x_u32;
 help: you can convert a `u32` to a `usize` and panic if the converted value doesn't fit
    |
 LL |         x_usize > x_u32.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:84:19
@@ -291,7 +315,7 @@ LL |         x_usize > x_u64;
 help: you can convert a `u64` to a `usize` and panic if the converted value doesn't fit
    |
 LL |         x_usize > x_u64.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:86:19
@@ -302,7 +326,7 @@ LL |         x_usize > x_u128;
 help: you can convert a `u128` to a `usize` and panic if the converted value doesn't fit
    |
 LL |         x_usize > x_u128.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:92:16
@@ -313,7 +337,7 @@ LL |         x_i8 > x_i16;
 help: you can convert `x_i8` from `i8` to `i16`, matching the type of `x_i16`
    |
 LL |         i16::from(x_i8) > x_i16;
-   |         ~~~~~~~~~~~~~~~
+   |         ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:94:16
@@ -324,7 +348,7 @@ LL |         x_i8 > x_i32;
 help: you can convert `x_i8` from `i8` to `i32`, matching the type of `x_i32`
    |
 LL |         i32::from(x_i8) > x_i32;
-   |         ~~~~~~~~~~~~~~~
+   |         ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:96:16
@@ -335,7 +359,7 @@ LL |         x_i8 > x_i64;
 help: you can convert `x_i8` from `i8` to `i64`, matching the type of `x_i64`
    |
 LL |         i64::from(x_i8) > x_i64;
-   |         ~~~~~~~~~~~~~~~
+   |         ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:98:16
@@ -346,7 +370,7 @@ LL |         x_i8 > x_i128;
 help: you can convert `x_i8` from `i8` to `i128`, matching the type of `x_i128`
    |
 LL |         i128::from(x_i8) > x_i128;
-   |         ~~~~~~~~~~~~~~~~
+   |         +++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:100:16
@@ -357,16 +381,18 @@ LL |         x_i8 > x_isize;
 help: you can convert `x_i8` from `i8` to `isize`, matching the type of `x_isize`
    |
 LL |         isize::from(x_i8) > x_isize;
-   |         ~~~~~~~~~~~~~~~~~
+   |         ++++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:103:17
    |
 LL |         x_i16 > x_i8;
-   |                 ^^^^
-   |                 |
-   |                 expected `i16`, found `i8`
-   |                 help: you can convert an `i8` to an `i16`: `x_i8.into()`
+   |                 ^^^^ expected `i16`, found `i8`
+   |
+help: you can convert an `i8` to an `i16`
+   |
+LL |         x_i16 > x_i8.into();
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:105:17
@@ -377,7 +403,7 @@ LL |         x_i16 > x_i32;
 help: you can convert `x_i16` from `i16` to `i32`, matching the type of `x_i32`
    |
 LL |         i32::from(x_i16) > x_i32;
-   |         ~~~~~~~~~~~~~~~~
+   |         ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:107:17
@@ -388,7 +414,7 @@ LL |         x_i16 > x_i64;
 help: you can convert `x_i16` from `i16` to `i64`, matching the type of `x_i64`
    |
 LL |         i64::from(x_i16) > x_i64;
-   |         ~~~~~~~~~~~~~~~~
+   |         ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:109:17
@@ -399,7 +425,7 @@ LL |         x_i16 > x_i128;
 help: you can convert `x_i16` from `i16` to `i128`, matching the type of `x_i128`
    |
 LL |         i128::from(x_i16) > x_i128;
-   |         ~~~~~~~~~~~~~~~~~
+   |         +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:111:17
@@ -410,25 +436,29 @@ LL |         x_i16 > x_isize;
 help: you can convert `x_i16` from `i16` to `isize`, matching the type of `x_isize`
    |
 LL |         isize::from(x_i16) > x_isize;
-   |         ~~~~~~~~~~~~~~~~~~
+   |         ++++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:114:17
    |
 LL |         x_i32 > x_i8;
-   |                 ^^^^
-   |                 |
-   |                 expected `i32`, found `i8`
-   |                 help: you can convert an `i8` to an `i32`: `x_i8.into()`
+   |                 ^^^^ expected `i32`, found `i8`
+   |
+help: you can convert an `i8` to an `i32`
+   |
+LL |         x_i32 > x_i8.into();
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:116:17
    |
 LL |         x_i32 > x_i16;
-   |                 ^^^^^
-   |                 |
-   |                 expected `i32`, found `i16`
-   |                 help: you can convert an `i16` to an `i32`: `x_i16.into()`
+   |                 ^^^^^ expected `i32`, found `i16`
+   |
+help: you can convert an `i16` to an `i32`
+   |
+LL |         x_i32 > x_i16.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:118:17
@@ -439,7 +469,7 @@ LL |         x_i32 > x_i64;
 help: you can convert `x_i32` from `i32` to `i64`, matching the type of `x_i64`
    |
 LL |         i64::from(x_i32) > x_i64;
-   |         ~~~~~~~~~~~~~~~~
+   |         ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:120:17
@@ -450,7 +480,7 @@ LL |         x_i32 > x_i128;
 help: you can convert `x_i32` from `i32` to `i128`, matching the type of `x_i128`
    |
 LL |         i128::from(x_i32) > x_i128;
-   |         ~~~~~~~~~~~~~~~~~
+   |         +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:122:17
@@ -461,34 +491,40 @@ LL |         x_i32 > x_isize;
 help: you can convert an `isize` to an `i32` and panic if the converted value doesn't fit
    |
 LL |         x_i32 > x_isize.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:125:17
    |
 LL |         x_i64 > x_i8;
-   |                 ^^^^
-   |                 |
-   |                 expected `i64`, found `i8`
-   |                 help: you can convert an `i8` to an `i64`: `x_i8.into()`
+   |                 ^^^^ expected `i64`, found `i8`
+   |
+help: you can convert an `i8` to an `i64`
+   |
+LL |         x_i64 > x_i8.into();
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:127:17
    |
 LL |         x_i64 > x_i16;
-   |                 ^^^^^
-   |                 |
-   |                 expected `i64`, found `i16`
-   |                 help: you can convert an `i16` to an `i64`: `x_i16.into()`
+   |                 ^^^^^ expected `i64`, found `i16`
+   |
+help: you can convert an `i16` to an `i64`
+   |
+LL |         x_i64 > x_i16.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:129:17
    |
 LL |         x_i64 > x_i32;
-   |                 ^^^^^
-   |                 |
-   |                 expected `i64`, found `i32`
-   |                 help: you can convert an `i32` to an `i64`: `x_i32.into()`
+   |                 ^^^^^ expected `i64`, found `i32`
+   |
+help: you can convert an `i32` to an `i64`
+   |
+LL |         x_i64 > x_i32.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:131:17
@@ -499,7 +535,7 @@ LL |         x_i64 > x_i128;
 help: you can convert `x_i64` from `i64` to `i128`, matching the type of `x_i128`
    |
 LL |         i128::from(x_i64) > x_i128;
-   |         ~~~~~~~~~~~~~~~~~
+   |         +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:133:17
@@ -510,43 +546,51 @@ LL |         x_i64 > x_isize;
 help: you can convert an `isize` to an `i64` and panic if the converted value doesn't fit
    |
 LL |         x_i64 > x_isize.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:136:18
    |
 LL |         x_i128 > x_i8;
-   |                  ^^^^
-   |                  |
-   |                  expected `i128`, found `i8`
-   |                  help: you can convert an `i8` to an `i128`: `x_i8.into()`
+   |                  ^^^^ expected `i128`, found `i8`
+   |
+help: you can convert an `i8` to an `i128`
+   |
+LL |         x_i128 > x_i8.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:138:18
    |
 LL |         x_i128 > x_i16;
-   |                  ^^^^^
-   |                  |
-   |                  expected `i128`, found `i16`
-   |                  help: you can convert an `i16` to an `i128`: `x_i16.into()`
+   |                  ^^^^^ expected `i128`, found `i16`
+   |
+help: you can convert an `i16` to an `i128`
+   |
+LL |         x_i128 > x_i16.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:140:18
    |
 LL |         x_i128 > x_i32;
-   |                  ^^^^^
-   |                  |
-   |                  expected `i128`, found `i32`
-   |                  help: you can convert an `i32` to an `i128`: `x_i32.into()`
+   |                  ^^^^^ expected `i128`, found `i32`
+   |
+help: you can convert an `i32` to an `i128`
+   |
+LL |         x_i128 > x_i32.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:142:18
    |
 LL |         x_i128 > x_i64;
-   |                  ^^^^^
-   |                  |
-   |                  expected `i128`, found `i64`
-   |                  help: you can convert an `i64` to an `i128`: `x_i64.into()`
+   |                  ^^^^^ expected `i128`, found `i64`
+   |
+help: you can convert an `i64` to an `i128`
+   |
+LL |         x_i128 > x_i64.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:144:18
@@ -557,25 +601,29 @@ LL |         x_i128 > x_isize;
 help: you can convert an `isize` to an `i128` and panic if the converted value doesn't fit
    |
 LL |         x_i128 > x_isize.try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:147:19
    |
 LL |         x_isize > x_i8;
-   |                   ^^^^
-   |                   |
-   |                   expected `isize`, found `i8`
-   |                   help: you can convert an `i8` to an `isize`: `x_i8.into()`
+   |                   ^^^^ expected `isize`, found `i8`
+   |
+help: you can convert an `i8` to an `isize`
+   |
+LL |         x_isize > x_i8.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:149:19
    |
 LL |         x_isize > x_i16;
-   |                   ^^^^^
-   |                   |
-   |                   expected `isize`, found `i16`
-   |                   help: you can convert an `i16` to an `isize`: `x_i16.into()`
+   |                   ^^^^^ expected `isize`, found `i16`
+   |
+help: you can convert an `i16` to an `isize`
+   |
+LL |         x_isize > x_i16.into();
+   |                        +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:151:19
@@ -586,7 +634,7 @@ LL |         x_isize > x_i32;
 help: you can convert an `i32` to an `isize` and panic if the converted value doesn't fit
    |
 LL |         x_isize > x_i32.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:153:19
@@ -597,7 +645,7 @@ LL |         x_isize > x_i64;
 help: you can convert an `i64` to an `isize` and panic if the converted value doesn't fit
    |
 LL |         x_isize > x_i64.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:155:19
@@ -608,7 +656,7 @@ LL |         x_isize > x_i128;
 help: you can convert an `i128` to an `isize` and panic if the converted value doesn't fit
    |
 LL |         x_isize > x_i128.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:161:16
@@ -619,7 +667,7 @@ LL |         x_u8 > x_i8;
 help: you can convert an `i8` to a `u8` and panic if the converted value doesn't fit
    |
 LL |         x_u8 > x_i8.try_into().unwrap();
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:163:16
@@ -630,7 +678,7 @@ LL |         x_u8 > x_i16;
 help: you can convert `x_u8` from `u8` to `i16`, matching the type of `x_i16`
    |
 LL |         i16::from(x_u8) > x_i16;
-   |         ~~~~~~~~~~~~~~~
+   |         ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:165:16
@@ -641,7 +689,7 @@ LL |         x_u8 > x_i32;
 help: you can convert `x_u8` from `u8` to `i32`, matching the type of `x_i32`
    |
 LL |         i32::from(x_u8) > x_i32;
-   |         ~~~~~~~~~~~~~~~
+   |         ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:167:16
@@ -652,7 +700,7 @@ LL |         x_u8 > x_i64;
 help: you can convert `x_u8` from `u8` to `i64`, matching the type of `x_i64`
    |
 LL |         i64::from(x_u8) > x_i64;
-   |         ~~~~~~~~~~~~~~~
+   |         ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:169:16
@@ -663,7 +711,7 @@ LL |         x_u8 > x_i128;
 help: you can convert `x_u8` from `u8` to `i128`, matching the type of `x_i128`
    |
 LL |         i128::from(x_u8) > x_i128;
-   |         ~~~~~~~~~~~~~~~~
+   |         +++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:171:16
@@ -674,7 +722,7 @@ LL |         x_u8 > x_isize;
 help: you can convert `x_u8` from `u8` to `isize`, matching the type of `x_isize`
    |
 LL |         isize::from(x_u8) > x_isize;
-   |         ~~~~~~~~~~~~~~~~~
+   |         ++++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:174:17
@@ -685,7 +733,7 @@ LL |         x_u16 > x_i8;
 help: you can convert an `i8` to a `u16` and panic if the converted value doesn't fit
    |
 LL |         x_u16 > x_i8.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:176:17
@@ -696,7 +744,7 @@ LL |         x_u16 > x_i16;
 help: you can convert an `i16` to a `u16` and panic if the converted value doesn't fit
    |
 LL |         x_u16 > x_i16.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:178:17
@@ -707,7 +755,7 @@ LL |         x_u16 > x_i32;
 help: you can convert `x_u16` from `u16` to `i32`, matching the type of `x_i32`
    |
 LL |         i32::from(x_u16) > x_i32;
-   |         ~~~~~~~~~~~~~~~~
+   |         ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:180:17
@@ -718,7 +766,7 @@ LL |         x_u16 > x_i64;
 help: you can convert `x_u16` from `u16` to `i64`, matching the type of `x_i64`
    |
 LL |         i64::from(x_u16) > x_i64;
-   |         ~~~~~~~~~~~~~~~~
+   |         ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:182:17
@@ -729,7 +777,7 @@ LL |         x_u16 > x_i128;
 help: you can convert `x_u16` from `u16` to `i128`, matching the type of `x_i128`
    |
 LL |         i128::from(x_u16) > x_i128;
-   |         ~~~~~~~~~~~~~~~~~
+   |         +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:184:17
@@ -740,7 +788,7 @@ LL |         x_u16 > x_isize;
 help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit
    |
 LL |         x_u16 > x_isize.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:187:17
@@ -751,7 +799,7 @@ LL |         x_u32 > x_i8;
 help: you can convert an `i8` to a `u32` and panic if the converted value doesn't fit
    |
 LL |         x_u32 > x_i8.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:189:17
@@ -762,7 +810,7 @@ LL |         x_u32 > x_i16;
 help: you can convert an `i16` to a `u32` and panic if the converted value doesn't fit
    |
 LL |         x_u32 > x_i16.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:191:17
@@ -773,7 +821,7 @@ LL |         x_u32 > x_i32;
 help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
    |
 LL |         x_u32 > x_i32.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:193:17
@@ -784,7 +832,7 @@ LL |         x_u32 > x_i64;
 help: you can convert `x_u32` from `u32` to `i64`, matching the type of `x_i64`
    |
 LL |         i64::from(x_u32) > x_i64;
-   |         ~~~~~~~~~~~~~~~~
+   |         ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:195:17
@@ -795,7 +843,7 @@ LL |         x_u32 > x_i128;
 help: you can convert `x_u32` from `u32` to `i128`, matching the type of `x_i128`
    |
 LL |         i128::from(x_u32) > x_i128;
-   |         ~~~~~~~~~~~~~~~~~
+   |         +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:197:17
@@ -806,7 +854,7 @@ LL |         x_u32 > x_isize;
 help: you can convert an `isize` to a `u32` and panic if the converted value doesn't fit
    |
 LL |         x_u32 > x_isize.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:200:17
@@ -817,7 +865,7 @@ LL |         x_u64 > x_i8;
 help: you can convert an `i8` to a `u64` and panic if the converted value doesn't fit
    |
 LL |         x_u64 > x_i8.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:202:17
@@ -828,7 +876,7 @@ LL |         x_u64 > x_i16;
 help: you can convert an `i16` to a `u64` and panic if the converted value doesn't fit
    |
 LL |         x_u64 > x_i16.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:204:17
@@ -839,7 +887,7 @@ LL |         x_u64 > x_i32;
 help: you can convert an `i32` to a `u64` and panic if the converted value doesn't fit
    |
 LL |         x_u64 > x_i32.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:206:17
@@ -850,7 +898,7 @@ LL |         x_u64 > x_i64;
 help: you can convert an `i64` to a `u64` and panic if the converted value doesn't fit
    |
 LL |         x_u64 > x_i64.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:208:17
@@ -861,7 +909,7 @@ LL |         x_u64 > x_i128;
 help: you can convert `x_u64` from `u64` to `i128`, matching the type of `x_i128`
    |
 LL |         i128::from(x_u64) > x_i128;
-   |         ~~~~~~~~~~~~~~~~~
+   |         +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:210:17
@@ -872,7 +920,7 @@ LL |         x_u64 > x_isize;
 help: you can convert an `isize` to a `u64` and panic if the converted value doesn't fit
    |
 LL |         x_u64 > x_isize.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:213:18
@@ -883,7 +931,7 @@ LL |         x_u128 > x_i8;
 help: you can convert an `i8` to a `u128` and panic if the converted value doesn't fit
    |
 LL |         x_u128 > x_i8.try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:215:18
@@ -894,7 +942,7 @@ LL |         x_u128 > x_i16;
 help: you can convert an `i16` to a `u128` and panic if the converted value doesn't fit
    |
 LL |         x_u128 > x_i16.try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:217:18
@@ -905,7 +953,7 @@ LL |         x_u128 > x_i32;
 help: you can convert an `i32` to a `u128` and panic if the converted value doesn't fit
    |
 LL |         x_u128 > x_i32.try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:219:18
@@ -916,7 +964,7 @@ LL |         x_u128 > x_i64;
 help: you can convert an `i64` to a `u128` and panic if the converted value doesn't fit
    |
 LL |         x_u128 > x_i64.try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:221:18
@@ -927,7 +975,7 @@ LL |         x_u128 > x_i128;
 help: you can convert an `i128` to a `u128` and panic if the converted value doesn't fit
    |
 LL |         x_u128 > x_i128.try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:223:18
@@ -938,7 +986,7 @@ LL |         x_u128 > x_isize;
 help: you can convert an `isize` to a `u128` and panic if the converted value doesn't fit
    |
 LL |         x_u128 > x_isize.try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:226:19
@@ -949,7 +997,7 @@ LL |         x_usize > x_i8;
 help: you can convert an `i8` to a `usize` and panic if the converted value doesn't fit
    |
 LL |         x_usize > x_i8.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:228:19
@@ -960,7 +1008,7 @@ LL |         x_usize > x_i16;
 help: you can convert an `i16` to a `usize` and panic if the converted value doesn't fit
    |
 LL |         x_usize > x_i16.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:230:19
@@ -971,7 +1019,7 @@ LL |         x_usize > x_i32;
 help: you can convert an `i32` to a `usize` and panic if the converted value doesn't fit
    |
 LL |         x_usize > x_i32.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:232:19
@@ -982,7 +1030,7 @@ LL |         x_usize > x_i64;
 help: you can convert an `i64` to a `usize` and panic if the converted value doesn't fit
    |
 LL |         x_usize > x_i64.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:234:19
@@ -993,7 +1041,7 @@ LL |         x_usize > x_i128;
 help: you can convert an `i128` to a `usize` and panic if the converted value doesn't fit
    |
 LL |         x_usize > x_i128.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:236:19
@@ -1004,7 +1052,7 @@ LL |         x_usize > x_isize;
 help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
    |
 LL |         x_usize > x_isize.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                          ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:242:16
@@ -1015,7 +1063,7 @@ LL |         x_i8 > x_u8;
 help: you can convert a `u8` to an `i8` and panic if the converted value doesn't fit
    |
 LL |         x_i8 > x_u8.try_into().unwrap();
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:244:16
@@ -1026,7 +1074,7 @@ LL |         x_i8 > x_u16;
 help: you can convert a `u16` to an `i8` and panic if the converted value doesn't fit
    |
 LL |         x_i8 > x_u16.try_into().unwrap();
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:246:16
@@ -1037,7 +1085,7 @@ LL |         x_i8 > x_u32;
 help: you can convert a `u32` to an `i8` and panic if the converted value doesn't fit
    |
 LL |         x_i8 > x_u32.try_into().unwrap();
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:248:16
@@ -1048,7 +1096,7 @@ LL |         x_i8 > x_u64;
 help: you can convert a `u64` to an `i8` and panic if the converted value doesn't fit
    |
 LL |         x_i8 > x_u64.try_into().unwrap();
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:250:16
@@ -1059,7 +1107,7 @@ LL |         x_i8 > x_u128;
 help: you can convert a `u128` to an `i8` and panic if the converted value doesn't fit
    |
 LL |         x_i8 > x_u128.try_into().unwrap();
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:252:16
@@ -1070,16 +1118,18 @@ LL |         x_i8 > x_usize;
 help: you can convert a `usize` to an `i8` and panic if the converted value doesn't fit
    |
 LL |         x_i8 > x_usize.try_into().unwrap();
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:255:17
    |
 LL |         x_i16 > x_u8;
-   |                 ^^^^
-   |                 |
-   |                 expected `i16`, found `u8`
-   |                 help: you can convert a `u8` to an `i16`: `x_u8.into()`
+   |                 ^^^^ expected `i16`, found `u8`
+   |
+help: you can convert a `u8` to an `i16`
+   |
+LL |         x_i16 > x_u8.into();
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:257:17
@@ -1090,7 +1140,7 @@ LL |         x_i16 > x_u16;
 help: you can convert a `u16` to an `i16` and panic if the converted value doesn't fit
    |
 LL |         x_i16 > x_u16.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:259:17
@@ -1101,7 +1151,7 @@ LL |         x_i16 > x_u32;
 help: you can convert a `u32` to an `i16` and panic if the converted value doesn't fit
    |
 LL |         x_i16 > x_u32.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:261:17
@@ -1112,7 +1162,7 @@ LL |         x_i16 > x_u64;
 help: you can convert a `u64` to an `i16` and panic if the converted value doesn't fit
    |
 LL |         x_i16 > x_u64.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:263:17
@@ -1123,7 +1173,7 @@ LL |         x_i16 > x_u128;
 help: you can convert a `u128` to an `i16` and panic if the converted value doesn't fit
    |
 LL |         x_i16 > x_u128.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:265:17
@@ -1134,25 +1184,29 @@ LL |         x_i16 > x_usize;
 help: you can convert a `usize` to an `i16` and panic if the converted value doesn't fit
    |
 LL |         x_i16 > x_usize.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:268:17
    |
 LL |         x_i32 > x_u8;
-   |                 ^^^^
-   |                 |
-   |                 expected `i32`, found `u8`
-   |                 help: you can convert a `u8` to an `i32`: `x_u8.into()`
+   |                 ^^^^ expected `i32`, found `u8`
+   |
+help: you can convert a `u8` to an `i32`
+   |
+LL |         x_i32 > x_u8.into();
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:270:17
    |
 LL |         x_i32 > x_u16;
-   |                 ^^^^^
-   |                 |
-   |                 expected `i32`, found `u16`
-   |                 help: you can convert a `u16` to an `i32`: `x_u16.into()`
+   |                 ^^^^^ expected `i32`, found `u16`
+   |
+help: you can convert a `u16` to an `i32`
+   |
+LL |         x_i32 > x_u16.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:272:17
@@ -1163,7 +1217,7 @@ LL |         x_i32 > x_u32;
 help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
    |
 LL |         x_i32 > x_u32.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:274:17
@@ -1174,7 +1228,7 @@ LL |         x_i32 > x_u64;
 help: you can convert a `u64` to an `i32` and panic if the converted value doesn't fit
    |
 LL |         x_i32 > x_u64.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:276:17
@@ -1185,7 +1239,7 @@ LL |         x_i32 > x_u128;
 help: you can convert a `u128` to an `i32` and panic if the converted value doesn't fit
    |
 LL |         x_i32 > x_u128.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:278:17
@@ -1196,34 +1250,40 @@ LL |         x_i32 > x_usize;
 help: you can convert a `usize` to an `i32` and panic if the converted value doesn't fit
    |
 LL |         x_i32 > x_usize.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:281:17
    |
 LL |         x_i64 > x_u8;
-   |                 ^^^^
-   |                 |
-   |                 expected `i64`, found `u8`
-   |                 help: you can convert a `u8` to an `i64`: `x_u8.into()`
+   |                 ^^^^ expected `i64`, found `u8`
+   |
+help: you can convert a `u8` to an `i64`
+   |
+LL |         x_i64 > x_u8.into();
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:283:17
    |
 LL |         x_i64 > x_u16;
-   |                 ^^^^^
-   |                 |
-   |                 expected `i64`, found `u16`
-   |                 help: you can convert a `u16` to an `i64`: `x_u16.into()`
+   |                 ^^^^^ expected `i64`, found `u16`
+   |
+help: you can convert a `u16` to an `i64`
+   |
+LL |         x_i64 > x_u16.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:285:17
    |
 LL |         x_i64 > x_u32;
-   |                 ^^^^^
-   |                 |
-   |                 expected `i64`, found `u32`
-   |                 help: you can convert a `u32` to an `i64`: `x_u32.into()`
+   |                 ^^^^^ expected `i64`, found `u32`
+   |
+help: you can convert a `u32` to an `i64`
+   |
+LL |         x_i64 > x_u32.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:287:17
@@ -1234,7 +1294,7 @@ LL |         x_i64 > x_u64;
 help: you can convert a `u64` to an `i64` and panic if the converted value doesn't fit
    |
 LL |         x_i64 > x_u64.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:289:17
@@ -1245,7 +1305,7 @@ LL |         x_i64 > x_u128;
 help: you can convert a `u128` to an `i64` and panic if the converted value doesn't fit
    |
 LL |         x_i64 > x_u128.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:291:17
@@ -1256,43 +1316,51 @@ LL |         x_i64 > x_usize;
 help: you can convert a `usize` to an `i64` and panic if the converted value doesn't fit
    |
 LL |         x_i64 > x_usize.try_into().unwrap();
-   |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:294:18
    |
 LL |         x_i128 > x_u8;
-   |                  ^^^^
-   |                  |
-   |                  expected `i128`, found `u8`
-   |                  help: you can convert a `u8` to an `i128`: `x_u8.into()`
+   |                  ^^^^ expected `i128`, found `u8`
+   |
+help: you can convert a `u8` to an `i128`
+   |
+LL |         x_i128 > x_u8.into();
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:296:18
    |
 LL |         x_i128 > x_u16;
-   |                  ^^^^^
-   |                  |
-   |                  expected `i128`, found `u16`
-   |                  help: you can convert a `u16` to an `i128`: `x_u16.into()`
+   |                  ^^^^^ expected `i128`, found `u16`
+   |
+help: you can convert a `u16` to an `i128`
+   |
+LL |         x_i128 > x_u16.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:298:18
    |
 LL |         x_i128 > x_u32;
-   |                  ^^^^^
-   |                  |
-   |                  expected `i128`, found `u32`
-   |                  help: you can convert a `u32` to an `i128`: `x_u32.into()`
+   |                  ^^^^^ expected `i128`, found `u32`
+   |
+help: you can convert a `u32` to an `i128`
+   |
+LL |         x_i128 > x_u32.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:300:18
    |
 LL |         x_i128 > x_u64;
-   |                  ^^^^^
-   |                  |
-   |                  expected `i128`, found `u64`
-   |                  help: you can convert a `u64` to an `i128`: `x_u64.into()`
+   |                  ^^^^^ expected `i128`, found `u64`
+   |
+help: you can convert a `u64` to an `i128`
+   |
+LL |         x_i128 > x_u64.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:302:18
@@ -1303,7 +1371,7 @@ LL |         x_i128 > x_u128;
 help: you can convert a `u128` to an `i128` and panic if the converted value doesn't fit
    |
 LL |         x_i128 > x_u128.try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:304:18
@@ -1314,16 +1382,18 @@ LL |         x_i128 > x_usize;
 help: you can convert a `usize` to an `i128` and panic if the converted value doesn't fit
    |
 LL |         x_i128 > x_usize.try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:307:19
    |
 LL |         x_isize > x_u8;
-   |                   ^^^^
-   |                   |
-   |                   expected `isize`, found `u8`
-   |                   help: you can convert a `u8` to an `isize`: `x_u8.into()`
+   |                   ^^^^ expected `isize`, found `u8`
+   |
+help: you can convert a `u8` to an `isize`
+   |
+LL |         x_isize > x_u8.into();
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:309:19
@@ -1334,7 +1404,7 @@ LL |         x_isize > x_u16;
 help: you can convert a `u16` to an `isize` and panic if the converted value doesn't fit
    |
 LL |         x_isize > x_u16.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:311:19
@@ -1345,7 +1415,7 @@ LL |         x_isize > x_u32;
 help: you can convert a `u32` to an `isize` and panic if the converted value doesn't fit
    |
 LL |         x_isize > x_u32.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:313:19
@@ -1356,7 +1426,7 @@ LL |         x_isize > x_u64;
 help: you can convert a `u64` to an `isize` and panic if the converted value doesn't fit
    |
 LL |         x_isize > x_u64.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                        ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:315:19
@@ -1367,7 +1437,7 @@ LL |         x_isize > x_u128;
 help: you can convert a `u128` to an `isize` and panic if the converted value doesn't fit
    |
 LL |         x_isize > x_u128.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:317:19
@@ -1378,7 +1448,7 @@ LL |         x_isize > x_usize;
 help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit
    |
 LL |         x_isize > x_usize.try_into().unwrap();
-   |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                          ++++++++++++++++++++
 
 error: aborting due to 132 previous errors
 
diff --git a/src/test/ui/numeric/numeric-cast-no-fix.stderr b/src/test/ui/numeric/numeric-cast-no-fix.stderr
index 4510ce10b3d..e4843206de1 100644
--- a/src/test/ui/numeric/numeric-cast-no-fix.stderr
+++ b/src/test/ui/numeric/numeric-cast-no-fix.stderr
@@ -47,7 +47,7 @@ LL |     x_u8 > -1_isize;
 help: you can convert `x_u8` from `u8` to `isize`, matching the type of `-1_isize`
    |
 LL |     isize::from(x_u8) > -1_isize;
-   |     ~~~~~~~~~~~~~~~~~
+   |     ++++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:23:15
@@ -74,7 +74,7 @@ LL |     x_u64 > -1_i128;
 help: you can convert `x_u64` from `u64` to `i128`, matching the type of `-1_i128`
    |
 LL |     i128::from(x_u64) > -1_i128;
-   |     ~~~~~~~~~~~~~~~~~
+   |     +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:29:13
@@ -85,7 +85,7 @@ LL |     x_u32 > -1_i128;
 help: you can convert `x_u32` from `u32` to `i128`, matching the type of `-1_i128`
    |
 LL |     i128::from(x_u32) > -1_i128;
-   |     ~~~~~~~~~~~~~~~~~
+   |     +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:31:13
@@ -96,7 +96,7 @@ LL |     x_u16 > -1_i128;
 help: you can convert `x_u16` from `u16` to `i128`, matching the type of `-1_i128`
    |
 LL |     i128::from(x_u16) > -1_i128;
-   |     ~~~~~~~~~~~~~~~~~
+   |     +++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:33:12
@@ -107,7 +107,7 @@ LL |     x_u8 > -1_i128;
 help: you can convert `x_u8` from `u8` to `i128`, matching the type of `-1_i128`
    |
 LL |     i128::from(x_u8) > -1_i128;
-   |     ~~~~~~~~~~~~~~~~
+   |     +++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:36:15
@@ -142,7 +142,7 @@ LL |     x_u32 > -1_i64;
 help: you can convert `x_u32` from `u32` to `i64`, matching the type of `-1_i64`
    |
 LL |     i64::from(x_u32) > -1_i64;
-   |     ~~~~~~~~~~~~~~~~
+   |     ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:44:13
@@ -153,7 +153,7 @@ LL |     x_u16 > -1_i64;
 help: you can convert `x_u16` from `u16` to `i64`, matching the type of `-1_i64`
    |
 LL |     i64::from(x_u16) > -1_i64;
-   |     ~~~~~~~~~~~~~~~~
+   |     ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:46:12
@@ -164,7 +164,7 @@ LL |     x_u8 > -1_i64;
 help: you can convert `x_u8` from `u8` to `i64`, matching the type of `-1_i64`
    |
 LL |     i64::from(x_u8) > -1_i64;
-   |     ~~~~~~~~~~~~~~~
+   |     ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:49:15
@@ -207,7 +207,7 @@ LL |     x_u16 > -1_i32;
 help: you can convert `x_u16` from `u16` to `i32`, matching the type of `-1_i32`
    |
 LL |     i32::from(x_u16) > -1_i32;
-   |     ~~~~~~~~~~~~~~~~
+   |     ++++++++++     +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:59:12
@@ -218,7 +218,7 @@ LL |     x_u8 > -1_i32;
 help: you can convert `x_u8` from `u8` to `i32`, matching the type of `-1_i32`
    |
 LL |     i32::from(x_u8) > -1_i32;
-   |     ~~~~~~~~~~~~~~~
+   |     ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:62:15
@@ -269,7 +269,7 @@ LL |     x_u8 > -1_i16;
 help: you can convert `x_u8` from `u8` to `i16`, matching the type of `-1_i16`
    |
 LL |     i16::from(x_u8) > -1_i16;
-   |     ~~~~~~~~~~~~~~~
+   |     ++++++++++    +
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:75:15
diff --git a/src/test/ui/numeric/numeric-cast.stderr b/src/test/ui/numeric/numeric-cast.stderr
index 8bc617be573..3e2bc5bc82d 100644
--- a/src/test/ui/numeric/numeric-cast.stderr
+++ b/src/test/ui/numeric/numeric-cast.stderr
@@ -7,7 +7,7 @@ LL |     foo::<usize>(x_u64);
 help: you can convert a `u64` to a `usize` and panic if the converted value doesn't fit
    |
 LL |     foo::<usize>(x_u64.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:25:18
@@ -18,25 +18,29 @@ LL |     foo::<usize>(x_u32);
 help: you can convert a `u32` to a `usize` and panic if the converted value doesn't fit
    |
 LL |     foo::<usize>(x_u32.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:27:18
    |
 LL |     foo::<usize>(x_u16);
-   |                  ^^^^^
-   |                  |
-   |                  expected `usize`, found `u16`
-   |                  help: you can convert a `u16` to a `usize`: `x_u16.into()`
+   |                  ^^^^^ expected `usize`, found `u16`
+   |
+help: you can convert a `u16` to a `usize`
+   |
+LL |     foo::<usize>(x_u16.into());
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:29:18
    |
 LL |     foo::<usize>(x_u8);
-   |                  ^^^^
-   |                  |
-   |                  expected `usize`, found `u8`
-   |                  help: you can convert a `u8` to a `usize`: `x_u8.into()`
+   |                  ^^^^ expected `usize`, found `u8`
+   |
+help: you can convert a `u8` to a `usize`
+   |
+LL |     foo::<usize>(x_u8.into());
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:31:18
@@ -47,7 +51,7 @@ LL |     foo::<usize>(x_isize);
 help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
    |
 LL |     foo::<usize>(x_isize.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:33:18
@@ -58,7 +62,7 @@ LL |     foo::<usize>(x_i64);
 help: you can convert an `i64` to a `usize` and panic if the converted value doesn't fit
    |
 LL |     foo::<usize>(x_i64.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:35:18
@@ -69,7 +73,7 @@ LL |     foo::<usize>(x_i32);
 help: you can convert an `i32` to a `usize` and panic if the converted value doesn't fit
    |
 LL |     foo::<usize>(x_i32.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:37:18
@@ -80,7 +84,7 @@ LL |     foo::<usize>(x_i16);
 help: you can convert an `i16` to a `usize` and panic if the converted value doesn't fit
    |
 LL |     foo::<usize>(x_i16.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:39:18
@@ -91,7 +95,7 @@ LL |     foo::<usize>(x_i8);
 help: you can convert an `i8` to a `usize` and panic if the converted value doesn't fit
    |
 LL |     foo::<usize>(x_i8.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:44:18
@@ -102,7 +106,7 @@ LL |     foo::<isize>(x_usize);
 help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit
    |
 LL |     foo::<isize>(x_usize.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                         ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:46:18
@@ -113,7 +117,7 @@ LL |     foo::<isize>(x_u64);
 help: you can convert a `u64` to an `isize` and panic if the converted value doesn't fit
    |
 LL |     foo::<isize>(x_u64.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:48:18
@@ -124,7 +128,7 @@ LL |     foo::<isize>(x_u32);
 help: you can convert a `u32` to an `isize` and panic if the converted value doesn't fit
    |
 LL |     foo::<isize>(x_u32.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:50:18
@@ -135,16 +139,18 @@ LL |     foo::<isize>(x_u16);
 help: you can convert a `u16` to an `isize` and panic if the converted value doesn't fit
    |
 LL |     foo::<isize>(x_u16.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:52:18
    |
 LL |     foo::<isize>(x_u8);
-   |                  ^^^^
-   |                  |
-   |                  expected `isize`, found `u8`
-   |                  help: you can convert a `u8` to an `isize`: `x_u8.into()`
+   |                  ^^^^ expected `isize`, found `u8`
+   |
+help: you can convert a `u8` to an `isize`
+   |
+LL |     foo::<isize>(x_u8.into());
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:55:18
@@ -155,7 +161,7 @@ LL |     foo::<isize>(x_i64);
 help: you can convert an `i64` to an `isize` and panic if the converted value doesn't fit
    |
 LL |     foo::<isize>(x_i64.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:57:18
@@ -166,25 +172,29 @@ LL |     foo::<isize>(x_i32);
 help: you can convert an `i32` to an `isize` and panic if the converted value doesn't fit
    |
 LL |     foo::<isize>(x_i32.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:59:18
    |
 LL |     foo::<isize>(x_i16);
-   |                  ^^^^^
-   |                  |
-   |                  expected `isize`, found `i16`
-   |                  help: you can convert an `i16` to an `isize`: `x_i16.into()`
+   |                  ^^^^^ expected `isize`, found `i16`
+   |
+help: you can convert an `i16` to an `isize`
+   |
+LL |     foo::<isize>(x_i16.into());
+   |                       +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:61:18
    |
 LL |     foo::<isize>(x_i8);
-   |                  ^^^^
-   |                  |
-   |                  expected `isize`, found `i8`
-   |                  help: you can convert an `i8` to an `isize`: `x_i8.into()`
+   |                  ^^^^ expected `isize`, found `i8`
+   |
+help: you can convert an `i8` to an `isize`
+   |
+LL |     foo::<isize>(x_i8.into());
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:66:16
@@ -195,34 +205,40 @@ LL |     foo::<u64>(x_usize);
 help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit
    |
 LL |     foo::<u64>(x_usize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:69:16
    |
 LL |     foo::<u64>(x_u32);
-   |                ^^^^^
-   |                |
-   |                expected `u64`, found `u32`
-   |                help: you can convert a `u32` to a `u64`: `x_u32.into()`
+   |                ^^^^^ expected `u64`, found `u32`
+   |
+help: you can convert a `u32` to a `u64`
+   |
+LL |     foo::<u64>(x_u32.into());
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:71:16
    |
 LL |     foo::<u64>(x_u16);
-   |                ^^^^^
-   |                |
-   |                expected `u64`, found `u16`
-   |                help: you can convert a `u16` to a `u64`: `x_u16.into()`
+   |                ^^^^^ expected `u64`, found `u16`
+   |
+help: you can convert a `u16` to a `u64`
+   |
+LL |     foo::<u64>(x_u16.into());
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:73:16
    |
 LL |     foo::<u64>(x_u8);
-   |                ^^^^
-   |                |
-   |                expected `u64`, found `u8`
-   |                help: you can convert a `u8` to a `u64`: `x_u8.into()`
+   |                ^^^^ expected `u64`, found `u8`
+   |
+help: you can convert a `u8` to a `u64`
+   |
+LL |     foo::<u64>(x_u8.into());
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:75:16
@@ -233,7 +249,7 @@ LL |     foo::<u64>(x_isize);
 help: you can convert an `isize` to a `u64` and panic if the converted value doesn't fit
    |
 LL |     foo::<u64>(x_isize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:77:16
@@ -244,7 +260,7 @@ LL |     foo::<u64>(x_i64);
 help: you can convert an `i64` to a `u64` and panic if the converted value doesn't fit
    |
 LL |     foo::<u64>(x_i64.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:79:16
@@ -255,7 +271,7 @@ LL |     foo::<u64>(x_i32);
 help: you can convert an `i32` to a `u64` and panic if the converted value doesn't fit
    |
 LL |     foo::<u64>(x_i32.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:81:16
@@ -266,7 +282,7 @@ LL |     foo::<u64>(x_i16);
 help: you can convert an `i16` to a `u64` and panic if the converted value doesn't fit
    |
 LL |     foo::<u64>(x_i16.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:83:16
@@ -277,7 +293,7 @@ LL |     foo::<u64>(x_i8);
 help: you can convert an `i8` to a `u64` and panic if the converted value doesn't fit
    |
 LL |     foo::<u64>(x_i8.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:88:16
@@ -288,7 +304,7 @@ LL |     foo::<i64>(x_usize);
 help: you can convert a `usize` to an `i64` and panic if the converted value doesn't fit
    |
 LL |     foo::<i64>(x_usize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:90:16
@@ -299,34 +315,40 @@ LL |     foo::<i64>(x_u64);
 help: you can convert a `u64` to an `i64` and panic if the converted value doesn't fit
    |
 LL |     foo::<i64>(x_u64.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:92:16
    |
 LL |     foo::<i64>(x_u32);
-   |                ^^^^^
-   |                |
-   |                expected `i64`, found `u32`
-   |                help: you can convert a `u32` to an `i64`: `x_u32.into()`
+   |                ^^^^^ expected `i64`, found `u32`
+   |
+help: you can convert a `u32` to an `i64`
+   |
+LL |     foo::<i64>(x_u32.into());
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:94:16
    |
 LL |     foo::<i64>(x_u16);
-   |                ^^^^^
-   |                |
-   |                expected `i64`, found `u16`
-   |                help: you can convert a `u16` to an `i64`: `x_u16.into()`
+   |                ^^^^^ expected `i64`, found `u16`
+   |
+help: you can convert a `u16` to an `i64`
+   |
+LL |     foo::<i64>(x_u16.into());
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:96:16
    |
 LL |     foo::<i64>(x_u8);
-   |                ^^^^
-   |                |
-   |                expected `i64`, found `u8`
-   |                help: you can convert a `u8` to an `i64`: `x_u8.into()`
+   |                ^^^^ expected `i64`, found `u8`
+   |
+help: you can convert a `u8` to an `i64`
+   |
+LL |     foo::<i64>(x_u8.into());
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:98:16
@@ -337,34 +359,40 @@ LL |     foo::<i64>(x_isize);
 help: you can convert an `isize` to an `i64` and panic if the converted value doesn't fit
    |
 LL |     foo::<i64>(x_isize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:101:16
    |
 LL |     foo::<i64>(x_i32);
-   |                ^^^^^
-   |                |
-   |                expected `i64`, found `i32`
-   |                help: you can convert an `i32` to an `i64`: `x_i32.into()`
+   |                ^^^^^ expected `i64`, found `i32`
+   |
+help: you can convert an `i32` to an `i64`
+   |
+LL |     foo::<i64>(x_i32.into());
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:103:16
    |
 LL |     foo::<i64>(x_i16);
-   |                ^^^^^
-   |                |
-   |                expected `i64`, found `i16`
-   |                help: you can convert an `i16` to an `i64`: `x_i16.into()`
+   |                ^^^^^ expected `i64`, found `i16`
+   |
+help: you can convert an `i16` to an `i64`
+   |
+LL |     foo::<i64>(x_i16.into());
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:105:16
    |
 LL |     foo::<i64>(x_i8);
-   |                ^^^^
-   |                |
-   |                expected `i64`, found `i8`
-   |                help: you can convert an `i8` to an `i64`: `x_i8.into()`
+   |                ^^^^ expected `i64`, found `i8`
+   |
+help: you can convert an `i8` to an `i64`
+   |
+LL |     foo::<i64>(x_i8.into());
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:110:16
@@ -375,7 +403,7 @@ LL |     foo::<u32>(x_usize);
 help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     foo::<u32>(x_usize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:112:16
@@ -386,25 +414,29 @@ LL |     foo::<u32>(x_u64);
 help: you can convert a `u64` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     foo::<u32>(x_u64.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:115:16
    |
 LL |     foo::<u32>(x_u16);
-   |                ^^^^^
-   |                |
-   |                expected `u32`, found `u16`
-   |                help: you can convert a `u16` to a `u32`: `x_u16.into()`
+   |                ^^^^^ expected `u32`, found `u16`
+   |
+help: you can convert a `u16` to a `u32`
+   |
+LL |     foo::<u32>(x_u16.into());
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:117:16
    |
 LL |     foo::<u32>(x_u8);
-   |                ^^^^
-   |                |
-   |                expected `u32`, found `u8`
-   |                help: you can convert a `u8` to a `u32`: `x_u8.into()`
+   |                ^^^^ expected `u32`, found `u8`
+   |
+help: you can convert a `u8` to a `u32`
+   |
+LL |     foo::<u32>(x_u8.into());
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:119:16
@@ -415,7 +447,7 @@ LL |     foo::<u32>(x_isize);
 help: you can convert an `isize` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     foo::<u32>(x_isize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:121:16
@@ -426,7 +458,7 @@ LL |     foo::<u32>(x_i64);
 help: you can convert an `i64` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     foo::<u32>(x_i64.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:123:16
@@ -437,7 +469,7 @@ LL |     foo::<u32>(x_i32);
 help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     foo::<u32>(x_i32.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:125:16
@@ -448,7 +480,7 @@ LL |     foo::<u32>(x_i16);
 help: you can convert an `i16` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     foo::<u32>(x_i16.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:127:16
@@ -459,7 +491,7 @@ LL |     foo::<u32>(x_i8);
 help: you can convert an `i8` to a `u32` and panic if the converted value doesn't fit
    |
 LL |     foo::<u32>(x_i8.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:132:16
@@ -470,7 +502,7 @@ LL |     foo::<i32>(x_usize);
 help: you can convert a `usize` to an `i32` and panic if the converted value doesn't fit
    |
 LL |     foo::<i32>(x_usize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:134:16
@@ -481,7 +513,7 @@ LL |     foo::<i32>(x_u64);
 help: you can convert a `u64` to an `i32` and panic if the converted value doesn't fit
    |
 LL |     foo::<i32>(x_u64.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:136:16
@@ -492,25 +524,29 @@ LL |     foo::<i32>(x_u32);
 help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
    |
 LL |     foo::<i32>(x_u32.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:138:16
    |
 LL |     foo::<i32>(x_u16);
-   |                ^^^^^
-   |                |
-   |                expected `i32`, found `u16`
-   |                help: you can convert a `u16` to an `i32`: `x_u16.into()`
+   |                ^^^^^ expected `i32`, found `u16`
+   |
+help: you can convert a `u16` to an `i32`
+   |
+LL |     foo::<i32>(x_u16.into());
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:140:16
    |
 LL |     foo::<i32>(x_u8);
-   |                ^^^^
-   |                |
-   |                expected `i32`, found `u8`
-   |                help: you can convert a `u8` to an `i32`: `x_u8.into()`
+   |                ^^^^ expected `i32`, found `u8`
+   |
+help: you can convert a `u8` to an `i32`
+   |
+LL |     foo::<i32>(x_u8.into());
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:142:16
@@ -521,7 +557,7 @@ LL |     foo::<i32>(x_isize);
 help: you can convert an `isize` to an `i32` and panic if the converted value doesn't fit
    |
 LL |     foo::<i32>(x_isize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:144:16
@@ -532,25 +568,29 @@ LL |     foo::<i32>(x_i64);
 help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
    |
 LL |     foo::<i32>(x_i64.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:147:16
    |
 LL |     foo::<i32>(x_i16);
-   |                ^^^^^
-   |                |
-   |                expected `i32`, found `i16`
-   |                help: you can convert an `i16` to an `i32`: `x_i16.into()`
+   |                ^^^^^ expected `i32`, found `i16`
+   |
+help: you can convert an `i16` to an `i32`
+   |
+LL |     foo::<i32>(x_i16.into());
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:149:16
    |
 LL |     foo::<i32>(x_i8);
-   |                ^^^^
-   |                |
-   |                expected `i32`, found `i8`
-   |                help: you can convert an `i8` to an `i32`: `x_i8.into()`
+   |                ^^^^ expected `i32`, found `i8`
+   |
+help: you can convert an `i8` to an `i32`
+   |
+LL |     foo::<i32>(x_i8.into());
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:154:16
@@ -561,7 +601,7 @@ LL |     foo::<u16>(x_usize);
 help: you can convert a `usize` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     foo::<u16>(x_usize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:156:16
@@ -572,7 +612,7 @@ LL |     foo::<u16>(x_u64);
 help: you can convert a `u64` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     foo::<u16>(x_u64.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:158:16
@@ -583,16 +623,18 @@ LL |     foo::<u16>(x_u32);
 help: you can convert a `u32` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     foo::<u16>(x_u32.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:161:16
    |
 LL |     foo::<u16>(x_u8);
-   |                ^^^^
-   |                |
-   |                expected `u16`, found `u8`
-   |                help: you can convert a `u8` to a `u16`: `x_u8.into()`
+   |                ^^^^ expected `u16`, found `u8`
+   |
+help: you can convert a `u8` to a `u16`
+   |
+LL |     foo::<u16>(x_u8.into());
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:163:16
@@ -603,7 +645,7 @@ LL |     foo::<u16>(x_isize);
 help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     foo::<u16>(x_isize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:165:16
@@ -614,7 +656,7 @@ LL |     foo::<u16>(x_i64);
 help: you can convert an `i64` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     foo::<u16>(x_i64.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:167:16
@@ -625,7 +667,7 @@ LL |     foo::<u16>(x_i32);
 help: you can convert an `i32` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     foo::<u16>(x_i32.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:169:16
@@ -636,7 +678,7 @@ LL |     foo::<u16>(x_i16);
 help: you can convert an `i16` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     foo::<u16>(x_i16.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:171:16
@@ -647,7 +689,7 @@ LL |     foo::<u16>(x_i8);
 help: you can convert an `i8` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     foo::<u16>(x_i8.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:176:16
@@ -658,7 +700,7 @@ LL |     foo::<i16>(x_usize);
 help: you can convert a `usize` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     foo::<i16>(x_usize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:178:16
@@ -669,7 +711,7 @@ LL |     foo::<i16>(x_u64);
 help: you can convert a `u64` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     foo::<i16>(x_u64.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:180:16
@@ -680,7 +722,7 @@ LL |     foo::<i16>(x_u32);
 help: you can convert a `u32` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     foo::<i16>(x_u32.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:182:16
@@ -691,16 +733,18 @@ LL |     foo::<i16>(x_u16);
 help: you can convert a `u16` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     foo::<i16>(x_u16.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:184:16
    |
 LL |     foo::<i16>(x_u8);
-   |                ^^^^
-   |                |
-   |                expected `i16`, found `u8`
-   |                help: you can convert a `u8` to an `i16`: `x_u8.into()`
+   |                ^^^^ expected `i16`, found `u8`
+   |
+help: you can convert a `u8` to an `i16`
+   |
+LL |     foo::<i16>(x_u8.into());
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:186:16
@@ -711,7 +755,7 @@ LL |     foo::<i16>(x_isize);
 help: you can convert an `isize` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     foo::<i16>(x_isize.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                       ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:188:16
@@ -722,7 +766,7 @@ LL |     foo::<i16>(x_i64);
 help: you can convert an `i64` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     foo::<i16>(x_i64.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:190:16
@@ -733,16 +777,18 @@ LL |     foo::<i16>(x_i32);
 help: you can convert an `i32` to an `i16` and panic if the converted value doesn't fit
    |
 LL |     foo::<i16>(x_i32.try_into().unwrap());
-   |                ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                     ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:193:16
    |
 LL |     foo::<i16>(x_i8);
-   |                ^^^^
-   |                |
-   |                expected `i16`, found `i8`
-   |                help: you can convert an `i8` to an `i16`: `x_i8.into()`
+   |                ^^^^ expected `i16`, found `i8`
+   |
+help: you can convert an `i8` to an `i16`
+   |
+LL |     foo::<i16>(x_i8.into());
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:198:15
@@ -753,7 +799,7 @@ LL |     foo::<u8>(x_usize);
 help: you can convert a `usize` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     foo::<u8>(x_usize.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:200:15
@@ -764,7 +810,7 @@ LL |     foo::<u8>(x_u64);
 help: you can convert a `u64` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     foo::<u8>(x_u64.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:202:15
@@ -775,7 +821,7 @@ LL |     foo::<u8>(x_u32);
 help: you can convert a `u32` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     foo::<u8>(x_u32.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:204:15
@@ -786,7 +832,7 @@ LL |     foo::<u8>(x_u16);
 help: you can convert a `u16` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     foo::<u8>(x_u16.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:207:15
@@ -797,7 +843,7 @@ LL |     foo::<u8>(x_isize);
 help: you can convert an `isize` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     foo::<u8>(x_isize.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:209:15
@@ -808,7 +854,7 @@ LL |     foo::<u8>(x_i64);
 help: you can convert an `i64` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     foo::<u8>(x_i64.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:211:15
@@ -819,7 +865,7 @@ LL |     foo::<u8>(x_i32);
 help: you can convert an `i32` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     foo::<u8>(x_i32.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:213:15
@@ -830,7 +876,7 @@ LL |     foo::<u8>(x_i16);
 help: you can convert an `i16` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     foo::<u8>(x_i16.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:215:15
@@ -841,7 +887,7 @@ LL |     foo::<u8>(x_i8);
 help: you can convert an `i8` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     foo::<u8>(x_i8.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                   ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:220:15
@@ -852,7 +898,7 @@ LL |     foo::<i8>(x_usize);
 help: you can convert a `usize` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     foo::<i8>(x_usize.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:222:15
@@ -863,7 +909,7 @@ LL |     foo::<i8>(x_u64);
 help: you can convert a `u64` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     foo::<i8>(x_u64.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:224:15
@@ -874,7 +920,7 @@ LL |     foo::<i8>(x_u32);
 help: you can convert a `u32` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     foo::<i8>(x_u32.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:226:15
@@ -885,7 +931,7 @@ LL |     foo::<i8>(x_u16);
 help: you can convert a `u16` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     foo::<i8>(x_u16.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:228:15
@@ -896,7 +942,7 @@ LL |     foo::<i8>(x_u8);
 help: you can convert a `u8` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     foo::<i8>(x_u8.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~
+   |                   ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:230:15
@@ -907,7 +953,7 @@ LL |     foo::<i8>(x_isize);
 help: you can convert an `isize` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     foo::<i8>(x_isize.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                      ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:232:15
@@ -918,7 +964,7 @@ LL |     foo::<i8>(x_i64);
 help: you can convert an `i64` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     foo::<i8>(x_i64.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:234:15
@@ -929,7 +975,7 @@ LL |     foo::<i8>(x_i32);
 help: you can convert an `i32` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     foo::<i8>(x_i32.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:236:15
@@ -940,7 +986,7 @@ LL |     foo::<i8>(x_i16);
 help: you can convert an `i16` to an `i8` and panic if the converted value doesn't fit
    |
 LL |     foo::<i8>(x_i16.try_into().unwrap());
-   |               ~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                    ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:242:16
@@ -951,7 +997,7 @@ LL |     foo::<f64>(x_usize);
 help: you can cast a `usize` to an `f64`, producing the floating point representation of the integer,
    |                                              rounded if necessary
 LL |     foo::<f64>(x_usize as f64);
-   |                ~~~~~~~~~~~~~~
+   |                        ++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:244:16
@@ -962,7 +1008,7 @@ LL |     foo::<f64>(x_u64);
 help: you can cast a `u64` to an `f64`, producing the floating point representation of the integer,
    |                                              rounded if necessary
 LL |     foo::<f64>(x_u64 as f64);
-   |                ~~~~~~~~~~~~
+   |                      ++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:246:16
@@ -973,7 +1019,7 @@ LL |     foo::<f64>(x_u32);
 help: you can convert a `u32` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(x_u32.into());
-   |                ~~~~~~~~~~~~
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:248:16
@@ -984,7 +1030,7 @@ LL |     foo::<f64>(x_u16);
 help: you can convert a `u16` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(x_u16.into());
-   |                ~~~~~~~~~~~~
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:250:16
@@ -995,7 +1041,7 @@ LL |     foo::<f64>(x_u8);
 help: you can convert a `u8` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(x_u8.into());
-   |                ~~~~~~~~~~~
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:252:16
@@ -1006,7 +1052,7 @@ LL |     foo::<f64>(x_isize);
 help: you can convert an `isize` to an `f64`, producing the floating point representation of the integer, rounded if necessary
    |
 LL |     foo::<f64>(x_isize as f64);
-   |                ~~~~~~~~~~~~~~
+   |                        ++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:254:16
@@ -1017,7 +1063,7 @@ LL |     foo::<f64>(x_i64);
 help: you can convert an `i64` to an `f64`, producing the floating point representation of the integer, rounded if necessary
    |
 LL |     foo::<f64>(x_i64 as f64);
-   |                ~~~~~~~~~~~~
+   |                      ++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:256:16
@@ -1028,7 +1074,7 @@ LL |     foo::<f64>(x_i32);
 help: you can convert an `i32` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(x_i32.into());
-   |                ~~~~~~~~~~~~
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:258:16
@@ -1039,7 +1085,7 @@ LL |     foo::<f64>(x_i16);
 help: you can convert an `i16` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(x_i16.into());
-   |                ~~~~~~~~~~~~
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:260:16
@@ -1050,16 +1096,18 @@ LL |     foo::<f64>(x_i8);
 help: you can convert an `i8` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(x_i8.into());
-   |                ~~~~~~~~~~~
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:263:16
    |
 LL |     foo::<f64>(x_f32);
-   |                ^^^^^
-   |                |
-   |                expected `f64`, found `f32`
-   |                help: you can convert an `f32` to an `f64`: `x_f32.into()`
+   |                ^^^^^ expected `f64`, found `f32`
+   |
+help: you can convert an `f32` to an `f64`
+   |
+LL |     foo::<f64>(x_f32.into());
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:266:16
@@ -1070,7 +1118,7 @@ LL |     foo::<f32>(x_usize);
 help: you can cast a `usize` to an `f32`, producing the floating point representation of the integer,
    |                                              rounded if necessary
 LL |     foo::<f32>(x_usize as f32);
-   |                ~~~~~~~~~~~~~~
+   |                        ++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:268:16
@@ -1081,7 +1129,7 @@ LL |     foo::<f32>(x_u64);
 help: you can cast a `u64` to an `f32`, producing the floating point representation of the integer,
    |                                              rounded if necessary
 LL |     foo::<f32>(x_u64 as f32);
-   |                ~~~~~~~~~~~~
+   |                      ++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:270:16
@@ -1092,7 +1140,7 @@ LL |     foo::<f32>(x_u32);
 help: you can cast a `u32` to an `f32`, producing the floating point representation of the integer,
    |                                              rounded if necessary
 LL |     foo::<f32>(x_u32 as f32);
-   |                ~~~~~~~~~~~~
+   |                      ++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:272:16
@@ -1103,7 +1151,7 @@ LL |     foo::<f32>(x_u16);
 help: you can convert a `u16` to an `f32`, producing the floating point representation of the integer
    |
 LL |     foo::<f32>(x_u16.into());
-   |                ~~~~~~~~~~~~
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:274:16
@@ -1114,7 +1162,7 @@ LL |     foo::<f32>(x_u8);
 help: you can convert a `u8` to an `f32`, producing the floating point representation of the integer
    |
 LL |     foo::<f32>(x_u8.into());
-   |                ~~~~~~~~~~~
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:276:16
@@ -1125,7 +1173,7 @@ LL |     foo::<f32>(x_isize);
 help: you can convert an `isize` to an `f32`, producing the floating point representation of the integer, rounded if necessary
    |
 LL |     foo::<f32>(x_isize as f32);
-   |                ~~~~~~~~~~~~~~
+   |                        ++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:278:16
@@ -1136,7 +1184,7 @@ LL |     foo::<f32>(x_i64);
 help: you can convert an `i64` to an `f32`, producing the floating point representation of the integer, rounded if necessary
    |
 LL |     foo::<f32>(x_i64 as f32);
-   |                ~~~~~~~~~~~~
+   |                      ++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:280:16
@@ -1147,7 +1195,7 @@ LL |     foo::<f32>(x_i32);
 help: you can convert an `i32` to an `f32`, producing the floating point representation of the integer, rounded if necessary
    |
 LL |     foo::<f32>(x_i32 as f32);
-   |                ~~~~~~~~~~~~
+   |                      ++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:282:16
@@ -1158,7 +1206,7 @@ LL |     foo::<f32>(x_i16);
 help: you can convert an `i16` to an `f32`, producing the floating point representation of the integer
    |
 LL |     foo::<f32>(x_i16.into());
-   |                ~~~~~~~~~~~~
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:284:16
@@ -1169,25 +1217,29 @@ LL |     foo::<f32>(x_i8);
 help: you can convert an `i8` to an `f32`, producing the floating point representation of the integer
    |
 LL |     foo::<f32>(x_i8.into());
-   |                ~~~~~~~~~~~
+   |                    +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:289:16
    |
 LL |     foo::<u32>(x_u8 as u16);
-   |                ^^^^^^^^^^^
-   |                |
-   |                expected `u32`, found `u16`
-   |                help: you can convert a `u16` to a `u32`: `(x_u8 as u16).into()`
+   |                ^^^^^^^^^^^ expected `u32`, found `u16`
+   |
+help: you can convert a `u16` to a `u32`
+   |
+LL |     foo::<u32>((x_u8 as u16).into());
+   |                +           ++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-cast.rs:291:16
    |
 LL |     foo::<i32>(-x_i8);
-   |                ^^^^^
-   |                |
-   |                expected `i32`, found `i8`
-   |                help: you can convert an `i8` to an `i32`: `(-x_i8).into()`
+   |                ^^^^^ expected `i32`, found `i8`
+   |
+help: you can convert an `i8` to an `i32`
+   |
+LL |     foo::<i32>((-x_i8).into());
+   |                +     ++++++++
 
 error: aborting due to 113 previous errors
 
diff --git a/src/test/ui/numeric/numeric-suffix.stderr b/src/test/ui/numeric/numeric-suffix.stderr
index d3f02214e3b..b829946e522 100644
--- a/src/test/ui/numeric/numeric-suffix.stderr
+++ b/src/test/ui/numeric/numeric-suffix.stderr
@@ -7,7 +7,7 @@ LL |     foo::<usize>(42_u64);
 help: change the type of the numeric literal from `u64` to `usize`
    |
 LL |     foo::<usize>(42_usize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:9:18
@@ -18,7 +18,7 @@ LL |     foo::<usize>(42_u32);
 help: change the type of the numeric literal from `u32` to `usize`
    |
 LL |     foo::<usize>(42_usize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:11:18
@@ -29,7 +29,7 @@ LL |     foo::<usize>(42_u16);
 help: change the type of the numeric literal from `u16` to `usize`
    |
 LL |     foo::<usize>(42_usize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:13:18
@@ -40,7 +40,7 @@ LL |     foo::<usize>(42_u8);
 help: change the type of the numeric literal from `u8` to `usize`
    |
 LL |     foo::<usize>(42_usize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:15:18
@@ -51,7 +51,7 @@ LL |     foo::<usize>(42_isize);
 help: change the type of the numeric literal from `isize` to `usize`
    |
 LL |     foo::<usize>(42_usize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:17:18
@@ -62,7 +62,7 @@ LL |     foo::<usize>(42_i64);
 help: change the type of the numeric literal from `i64` to `usize`
    |
 LL |     foo::<usize>(42_usize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:19:18
@@ -73,7 +73,7 @@ LL |     foo::<usize>(42_i32);
 help: change the type of the numeric literal from `i32` to `usize`
    |
 LL |     foo::<usize>(42_usize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:21:18
@@ -84,7 +84,7 @@ LL |     foo::<usize>(42_i16);
 help: change the type of the numeric literal from `i16` to `usize`
    |
 LL |     foo::<usize>(42_usize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:23:18
@@ -95,7 +95,7 @@ LL |     foo::<usize>(42_i8);
 help: change the type of the numeric literal from `i8` to `usize`
    |
 LL |     foo::<usize>(42_usize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:25:18
@@ -106,7 +106,7 @@ LL |     foo::<usize>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `usize`
    |
 LL |     foo::<usize>(42usize);
-   |                  ~~~~~~~
+   |                    ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:27:18
@@ -117,7 +117,7 @@ LL |     foo::<usize>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `usize`
    |
 LL |     foo::<usize>(42usize);
-   |                  ~~~~~~~
+   |                    ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:30:18
@@ -128,7 +128,7 @@ LL |     foo::<isize>(42_usize);
 help: change the type of the numeric literal from `usize` to `isize`
    |
 LL |     foo::<isize>(42_isize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:32:18
@@ -139,7 +139,7 @@ LL |     foo::<isize>(42_u64);
 help: change the type of the numeric literal from `u64` to `isize`
    |
 LL |     foo::<isize>(42_isize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:34:18
@@ -150,7 +150,7 @@ LL |     foo::<isize>(42_u32);
 help: change the type of the numeric literal from `u32` to `isize`
    |
 LL |     foo::<isize>(42_isize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:36:18
@@ -161,7 +161,7 @@ LL |     foo::<isize>(42_u16);
 help: change the type of the numeric literal from `u16` to `isize`
    |
 LL |     foo::<isize>(42_isize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:38:18
@@ -172,7 +172,7 @@ LL |     foo::<isize>(42_u8);
 help: change the type of the numeric literal from `u8` to `isize`
    |
 LL |     foo::<isize>(42_isize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:41:18
@@ -183,7 +183,7 @@ LL |     foo::<isize>(42_i64);
 help: change the type of the numeric literal from `i64` to `isize`
    |
 LL |     foo::<isize>(42_isize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:43:18
@@ -194,7 +194,7 @@ LL |     foo::<isize>(42_i32);
 help: change the type of the numeric literal from `i32` to `isize`
    |
 LL |     foo::<isize>(42_isize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:45:18
@@ -205,7 +205,7 @@ LL |     foo::<isize>(42_i16);
 help: change the type of the numeric literal from `i16` to `isize`
    |
 LL |     foo::<isize>(42_isize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:47:18
@@ -216,7 +216,7 @@ LL |     foo::<isize>(42_i8);
 help: change the type of the numeric literal from `i8` to `isize`
    |
 LL |     foo::<isize>(42_isize);
-   |                  ~~~~~~~~
+   |                     ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:49:18
@@ -227,7 +227,7 @@ LL |     foo::<isize>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `isize`
    |
 LL |     foo::<isize>(42isize);
-   |                  ~~~~~~~
+   |                    ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:51:18
@@ -238,7 +238,7 @@ LL |     foo::<isize>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `isize`
    |
 LL |     foo::<isize>(42isize);
-   |                  ~~~~~~~
+   |                    ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:54:16
@@ -249,7 +249,7 @@ LL |     foo::<u64>(42_usize);
 help: change the type of the numeric literal from `usize` to `u64`
    |
 LL |     foo::<u64>(42_u64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:57:16
@@ -260,7 +260,7 @@ LL |     foo::<u64>(42_u32);
 help: change the type of the numeric literal from `u32` to `u64`
    |
 LL |     foo::<u64>(42_u64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:59:16
@@ -271,7 +271,7 @@ LL |     foo::<u64>(42_u16);
 help: change the type of the numeric literal from `u16` to `u64`
    |
 LL |     foo::<u64>(42_u64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:61:16
@@ -282,7 +282,7 @@ LL |     foo::<u64>(42_u8);
 help: change the type of the numeric literal from `u8` to `u64`
    |
 LL |     foo::<u64>(42_u64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:63:16
@@ -293,7 +293,7 @@ LL |     foo::<u64>(42_isize);
 help: change the type of the numeric literal from `isize` to `u64`
    |
 LL |     foo::<u64>(42_u64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:65:16
@@ -304,7 +304,7 @@ LL |     foo::<u64>(42_i64);
 help: change the type of the numeric literal from `i64` to `u64`
    |
 LL |     foo::<u64>(42_u64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:67:16
@@ -315,7 +315,7 @@ LL |     foo::<u64>(42_i32);
 help: change the type of the numeric literal from `i32` to `u64`
    |
 LL |     foo::<u64>(42_u64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:69:16
@@ -326,7 +326,7 @@ LL |     foo::<u64>(42_i16);
 help: change the type of the numeric literal from `i16` to `u64`
    |
 LL |     foo::<u64>(42_u64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:71:16
@@ -337,7 +337,7 @@ LL |     foo::<u64>(42_i8);
 help: change the type of the numeric literal from `i8` to `u64`
    |
 LL |     foo::<u64>(42_u64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:73:16
@@ -348,7 +348,7 @@ LL |     foo::<u64>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `u64`
    |
 LL |     foo::<u64>(42u64);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:75:16
@@ -359,7 +359,7 @@ LL |     foo::<u64>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `u64`
    |
 LL |     foo::<u64>(42u64);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:78:16
@@ -370,7 +370,7 @@ LL |     foo::<i64>(42_usize);
 help: change the type of the numeric literal from `usize` to `i64`
    |
 LL |     foo::<i64>(42_i64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:80:16
@@ -381,7 +381,7 @@ LL |     foo::<i64>(42_u64);
 help: change the type of the numeric literal from `u64` to `i64`
    |
 LL |     foo::<i64>(42_i64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:82:16
@@ -392,7 +392,7 @@ LL |     foo::<i64>(42_u32);
 help: change the type of the numeric literal from `u32` to `i64`
    |
 LL |     foo::<i64>(42_i64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:84:16
@@ -403,7 +403,7 @@ LL |     foo::<i64>(42_u16);
 help: change the type of the numeric literal from `u16` to `i64`
    |
 LL |     foo::<i64>(42_i64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:86:16
@@ -414,7 +414,7 @@ LL |     foo::<i64>(42_u8);
 help: change the type of the numeric literal from `u8` to `i64`
    |
 LL |     foo::<i64>(42_i64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:88:16
@@ -425,7 +425,7 @@ LL |     foo::<i64>(42_isize);
 help: change the type of the numeric literal from `isize` to `i64`
    |
 LL |     foo::<i64>(42_i64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:91:16
@@ -436,7 +436,7 @@ LL |     foo::<i64>(42_i32);
 help: change the type of the numeric literal from `i32` to `i64`
    |
 LL |     foo::<i64>(42_i64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:93:16
@@ -447,7 +447,7 @@ LL |     foo::<i64>(42_i16);
 help: change the type of the numeric literal from `i16` to `i64`
    |
 LL |     foo::<i64>(42_i64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:95:16
@@ -458,7 +458,7 @@ LL |     foo::<i64>(42_i8);
 help: change the type of the numeric literal from `i8` to `i64`
    |
 LL |     foo::<i64>(42_i64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:97:16
@@ -469,7 +469,7 @@ LL |     foo::<i64>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `i64`
    |
 LL |     foo::<i64>(42i64);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:99:16
@@ -480,7 +480,7 @@ LL |     foo::<i64>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `i64`
    |
 LL |     foo::<i64>(42i64);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:102:16
@@ -491,7 +491,7 @@ LL |     foo::<u32>(42_usize);
 help: change the type of the numeric literal from `usize` to `u32`
    |
 LL |     foo::<u32>(42_u32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:104:16
@@ -502,7 +502,7 @@ LL |     foo::<u32>(42_u64);
 help: change the type of the numeric literal from `u64` to `u32`
    |
 LL |     foo::<u32>(42_u32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:107:16
@@ -513,7 +513,7 @@ LL |     foo::<u32>(42_u16);
 help: change the type of the numeric literal from `u16` to `u32`
    |
 LL |     foo::<u32>(42_u32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:109:16
@@ -524,7 +524,7 @@ LL |     foo::<u32>(42_u8);
 help: change the type of the numeric literal from `u8` to `u32`
    |
 LL |     foo::<u32>(42_u32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:111:16
@@ -535,7 +535,7 @@ LL |     foo::<u32>(42_isize);
 help: change the type of the numeric literal from `isize` to `u32`
    |
 LL |     foo::<u32>(42_u32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:113:16
@@ -546,7 +546,7 @@ LL |     foo::<u32>(42_i64);
 help: change the type of the numeric literal from `i64` to `u32`
    |
 LL |     foo::<u32>(42_u32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:115:16
@@ -557,7 +557,7 @@ LL |     foo::<u32>(42_i32);
 help: change the type of the numeric literal from `i32` to `u32`
    |
 LL |     foo::<u32>(42_u32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:117:16
@@ -568,7 +568,7 @@ LL |     foo::<u32>(42_i16);
 help: change the type of the numeric literal from `i16` to `u32`
    |
 LL |     foo::<u32>(42_u32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:119:16
@@ -579,7 +579,7 @@ LL |     foo::<u32>(42_i8);
 help: change the type of the numeric literal from `i8` to `u32`
    |
 LL |     foo::<u32>(42_u32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:121:16
@@ -590,7 +590,7 @@ LL |     foo::<u32>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `u32`
    |
 LL |     foo::<u32>(42u32);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:123:16
@@ -601,7 +601,7 @@ LL |     foo::<u32>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `u32`
    |
 LL |     foo::<u32>(42u32);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:126:16
@@ -612,7 +612,7 @@ LL |     foo::<i32>(42_usize);
 help: change the type of the numeric literal from `usize` to `i32`
    |
 LL |     foo::<i32>(42_i32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:128:16
@@ -623,7 +623,7 @@ LL |     foo::<i32>(42_u64);
 help: change the type of the numeric literal from `u64` to `i32`
    |
 LL |     foo::<i32>(42_i32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:130:16
@@ -634,7 +634,7 @@ LL |     foo::<i32>(42_u32);
 help: change the type of the numeric literal from `u32` to `i32`
    |
 LL |     foo::<i32>(42_i32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:132:16
@@ -645,7 +645,7 @@ LL |     foo::<i32>(42_u16);
 help: change the type of the numeric literal from `u16` to `i32`
    |
 LL |     foo::<i32>(42_i32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:134:16
@@ -656,7 +656,7 @@ LL |     foo::<i32>(42_u8);
 help: change the type of the numeric literal from `u8` to `i32`
    |
 LL |     foo::<i32>(42_i32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:136:16
@@ -667,7 +667,7 @@ LL |     foo::<i32>(42_isize);
 help: change the type of the numeric literal from `isize` to `i32`
    |
 LL |     foo::<i32>(42_i32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:138:16
@@ -678,7 +678,7 @@ LL |     foo::<i32>(42_i64);
 help: change the type of the numeric literal from `i64` to `i32`
    |
 LL |     foo::<i32>(42_i32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:141:16
@@ -689,7 +689,7 @@ LL |     foo::<i32>(42_i16);
 help: change the type of the numeric literal from `i16` to `i32`
    |
 LL |     foo::<i32>(42_i32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:143:16
@@ -700,7 +700,7 @@ LL |     foo::<i32>(42_i8);
 help: change the type of the numeric literal from `i8` to `i32`
    |
 LL |     foo::<i32>(42_i32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:145:16
@@ -711,7 +711,7 @@ LL |     foo::<i32>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `i32`
    |
 LL |     foo::<i32>(42i32);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:147:16
@@ -722,7 +722,7 @@ LL |     foo::<i32>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `i32`
    |
 LL |     foo::<i32>(42i32);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:150:16
@@ -733,7 +733,7 @@ LL |     foo::<u16>(42_usize);
 help: change the type of the numeric literal from `usize` to `u16`
    |
 LL |     foo::<u16>(42_u16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:152:16
@@ -744,7 +744,7 @@ LL |     foo::<u16>(42_u64);
 help: change the type of the numeric literal from `u64` to `u16`
    |
 LL |     foo::<u16>(42_u16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:154:16
@@ -755,7 +755,7 @@ LL |     foo::<u16>(42_u32);
 help: change the type of the numeric literal from `u32` to `u16`
    |
 LL |     foo::<u16>(42_u16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:157:16
@@ -766,7 +766,7 @@ LL |     foo::<u16>(42_u8);
 help: change the type of the numeric literal from `u8` to `u16`
    |
 LL |     foo::<u16>(42_u16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:159:16
@@ -777,7 +777,7 @@ LL |     foo::<u16>(42_isize);
 help: change the type of the numeric literal from `isize` to `u16`
    |
 LL |     foo::<u16>(42_u16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:161:16
@@ -788,7 +788,7 @@ LL |     foo::<u16>(42_i64);
 help: change the type of the numeric literal from `i64` to `u16`
    |
 LL |     foo::<u16>(42_u16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:163:16
@@ -799,7 +799,7 @@ LL |     foo::<u16>(42_i32);
 help: change the type of the numeric literal from `i32` to `u16`
    |
 LL |     foo::<u16>(42_u16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:165:16
@@ -810,7 +810,7 @@ LL |     foo::<u16>(42_i16);
 help: change the type of the numeric literal from `i16` to `u16`
    |
 LL |     foo::<u16>(42_u16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:167:16
@@ -821,7 +821,7 @@ LL |     foo::<u16>(42_i8);
 help: change the type of the numeric literal from `i8` to `u16`
    |
 LL |     foo::<u16>(42_u16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:169:16
@@ -832,7 +832,7 @@ LL |     foo::<u16>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `u16`
    |
 LL |     foo::<u16>(42u16);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:171:16
@@ -843,7 +843,7 @@ LL |     foo::<u16>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `u16`
    |
 LL |     foo::<u16>(42u16);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:174:16
@@ -854,7 +854,7 @@ LL |     foo::<i16>(42_usize);
 help: change the type of the numeric literal from `usize` to `i16`
    |
 LL |     foo::<i16>(42_i16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:176:16
@@ -865,7 +865,7 @@ LL |     foo::<i16>(42_u64);
 help: change the type of the numeric literal from `u64` to `i16`
    |
 LL |     foo::<i16>(42_i16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:178:16
@@ -876,7 +876,7 @@ LL |     foo::<i16>(42_u32);
 help: change the type of the numeric literal from `u32` to `i16`
    |
 LL |     foo::<i16>(42_i16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:180:16
@@ -887,7 +887,7 @@ LL |     foo::<i16>(42_u16);
 help: change the type of the numeric literal from `u16` to `i16`
    |
 LL |     foo::<i16>(42_i16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:182:16
@@ -898,7 +898,7 @@ LL |     foo::<i16>(42_u8);
 help: change the type of the numeric literal from `u8` to `i16`
    |
 LL |     foo::<i16>(42_i16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:184:16
@@ -909,7 +909,7 @@ LL |     foo::<i16>(42_isize);
 help: change the type of the numeric literal from `isize` to `i16`
    |
 LL |     foo::<i16>(42_i16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:186:16
@@ -920,7 +920,7 @@ LL |     foo::<i16>(42_i64);
 help: change the type of the numeric literal from `i64` to `i16`
    |
 LL |     foo::<i16>(42_i16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:188:16
@@ -931,7 +931,7 @@ LL |     foo::<i16>(42_i32);
 help: change the type of the numeric literal from `i32` to `i16`
    |
 LL |     foo::<i16>(42_i16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:191:16
@@ -942,7 +942,7 @@ LL |     foo::<i16>(42_i8);
 help: change the type of the numeric literal from `i8` to `i16`
    |
 LL |     foo::<i16>(42_i16);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:193:16
@@ -953,7 +953,7 @@ LL |     foo::<i16>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `i16`
    |
 LL |     foo::<i16>(42i16);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:195:16
@@ -964,7 +964,7 @@ LL |     foo::<i16>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `i16`
    |
 LL |     foo::<i16>(42i16);
-   |                ~~~~~
+   |                  ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:198:15
@@ -975,7 +975,7 @@ LL |     foo::<u8>(42_usize);
 help: change the type of the numeric literal from `usize` to `u8`
    |
 LL |     foo::<u8>(42_u8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:200:15
@@ -986,7 +986,7 @@ LL |     foo::<u8>(42_u64);
 help: change the type of the numeric literal from `u64` to `u8`
    |
 LL |     foo::<u8>(42_u8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:202:15
@@ -997,7 +997,7 @@ LL |     foo::<u8>(42_u32);
 help: change the type of the numeric literal from `u32` to `u8`
    |
 LL |     foo::<u8>(42_u8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:204:15
@@ -1008,7 +1008,7 @@ LL |     foo::<u8>(42_u16);
 help: change the type of the numeric literal from `u16` to `u8`
    |
 LL |     foo::<u8>(42_u8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:207:15
@@ -1019,7 +1019,7 @@ LL |     foo::<u8>(42_isize);
 help: change the type of the numeric literal from `isize` to `u8`
    |
 LL |     foo::<u8>(42_u8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:209:15
@@ -1030,7 +1030,7 @@ LL |     foo::<u8>(42_i64);
 help: change the type of the numeric literal from `i64` to `u8`
    |
 LL |     foo::<u8>(42_u8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:211:15
@@ -1041,7 +1041,7 @@ LL |     foo::<u8>(42_i32);
 help: change the type of the numeric literal from `i32` to `u8`
    |
 LL |     foo::<u8>(42_u8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:213:15
@@ -1052,7 +1052,7 @@ LL |     foo::<u8>(42_i16);
 help: change the type of the numeric literal from `i16` to `u8`
    |
 LL |     foo::<u8>(42_u8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:215:15
@@ -1063,7 +1063,7 @@ LL |     foo::<u8>(42_i8);
 help: change the type of the numeric literal from `i8` to `u8`
    |
 LL |     foo::<u8>(42_u8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:217:15
@@ -1074,7 +1074,7 @@ LL |     foo::<u8>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `u8`
    |
 LL |     foo::<u8>(42u8);
-   |               ~~~~
+   |                 ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:219:15
@@ -1085,7 +1085,7 @@ LL |     foo::<u8>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `u8`
    |
 LL |     foo::<u8>(42u8);
-   |               ~~~~
+   |                 ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:222:15
@@ -1096,7 +1096,7 @@ LL |     foo::<i8>(42_usize);
 help: change the type of the numeric literal from `usize` to `i8`
    |
 LL |     foo::<i8>(42_i8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:224:15
@@ -1107,7 +1107,7 @@ LL |     foo::<i8>(42_u64);
 help: change the type of the numeric literal from `u64` to `i8`
    |
 LL |     foo::<i8>(42_i8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:226:15
@@ -1118,7 +1118,7 @@ LL |     foo::<i8>(42_u32);
 help: change the type of the numeric literal from `u32` to `i8`
    |
 LL |     foo::<i8>(42_i8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:228:15
@@ -1129,7 +1129,7 @@ LL |     foo::<i8>(42_u16);
 help: change the type of the numeric literal from `u16` to `i8`
    |
 LL |     foo::<i8>(42_i8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:230:15
@@ -1140,7 +1140,7 @@ LL |     foo::<i8>(42_u8);
 help: change the type of the numeric literal from `u8` to `i8`
    |
 LL |     foo::<i8>(42_i8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:232:15
@@ -1151,7 +1151,7 @@ LL |     foo::<i8>(42_isize);
 help: change the type of the numeric literal from `isize` to `i8`
    |
 LL |     foo::<i8>(42_i8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:234:15
@@ -1162,7 +1162,7 @@ LL |     foo::<i8>(42_i64);
 help: change the type of the numeric literal from `i64` to `i8`
    |
 LL |     foo::<i8>(42_i8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:236:15
@@ -1173,7 +1173,7 @@ LL |     foo::<i8>(42_i32);
 help: change the type of the numeric literal from `i32` to `i8`
    |
 LL |     foo::<i8>(42_i8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:238:15
@@ -1184,7 +1184,7 @@ LL |     foo::<i8>(42_i16);
 help: change the type of the numeric literal from `i16` to `i8`
    |
 LL |     foo::<i8>(42_i8);
-   |               ~~~~~
+   |                  ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:241:15
@@ -1195,7 +1195,7 @@ LL |     foo::<i8>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `i8`
    |
 LL |     foo::<i8>(42i8);
-   |               ~~~~
+   |                 ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:243:15
@@ -1206,7 +1206,7 @@ LL |     foo::<i8>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `i8`
    |
 LL |     foo::<i8>(42i8);
-   |               ~~~~
+   |                 ~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:246:16
@@ -1217,7 +1217,7 @@ LL |     foo::<f64>(42_usize);
 help: change the type of the numeric literal from `usize` to `f64`
    |
 LL |     foo::<f64>(42_f64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:248:16
@@ -1228,7 +1228,7 @@ LL |     foo::<f64>(42_u64);
 help: change the type of the numeric literal from `u64` to `f64`
    |
 LL |     foo::<f64>(42_f64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:250:16
@@ -1239,7 +1239,7 @@ LL |     foo::<f64>(42_u32);
 help: you can convert a `u32` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(42_u32.into());
-   |                ~~~~~~~~~~~~~
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:252:16
@@ -1250,7 +1250,7 @@ LL |     foo::<f64>(42_u16);
 help: you can convert a `u16` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(42_u16.into());
-   |                ~~~~~~~~~~~~~
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:254:16
@@ -1261,7 +1261,7 @@ LL |     foo::<f64>(42_u8);
 help: you can convert a `u8` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(42_u8.into());
-   |                ~~~~~~~~~~~~
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:256:16
@@ -1272,7 +1272,7 @@ LL |     foo::<f64>(42_isize);
 help: change the type of the numeric literal from `isize` to `f64`
    |
 LL |     foo::<f64>(42_f64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:258:16
@@ -1283,7 +1283,7 @@ LL |     foo::<f64>(42_i64);
 help: change the type of the numeric literal from `i64` to `f64`
    |
 LL |     foo::<f64>(42_f64);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:260:16
@@ -1294,7 +1294,7 @@ LL |     foo::<f64>(42_i32);
 help: you can convert an `i32` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(42_i32.into());
-   |                ~~~~~~~~~~~~~
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:262:16
@@ -1305,7 +1305,7 @@ LL |     foo::<f64>(42_i16);
 help: you can convert an `i16` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(42_i16.into());
-   |                ~~~~~~~~~~~~~
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:264:16
@@ -1316,7 +1316,7 @@ LL |     foo::<f64>(42_i8);
 help: you can convert an `i8` to an `f64`, producing the floating point representation of the integer
    |
 LL |     foo::<f64>(42_i8.into());
-   |                ~~~~~~~~~~~~
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:267:16
@@ -1327,7 +1327,7 @@ LL |     foo::<f64>(42.0_f32);
 help: change the type of the numeric literal from `f32` to `f64`
    |
 LL |     foo::<f64>(42.0_f64);
-   |                ~~~~~~~~
+   |                     ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:270:16
@@ -1338,7 +1338,7 @@ LL |     foo::<f32>(42_usize);
 help: change the type of the numeric literal from `usize` to `f32`
    |
 LL |     foo::<f32>(42_f32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:272:16
@@ -1349,7 +1349,7 @@ LL |     foo::<f32>(42_u64);
 help: change the type of the numeric literal from `u64` to `f32`
    |
 LL |     foo::<f32>(42_f32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:274:16
@@ -1360,7 +1360,7 @@ LL |     foo::<f32>(42_u32);
 help: change the type of the numeric literal from `u32` to `f32`
    |
 LL |     foo::<f32>(42_f32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:276:16
@@ -1371,7 +1371,7 @@ LL |     foo::<f32>(42_u16);
 help: you can convert a `u16` to an `f32`, producing the floating point representation of the integer
    |
 LL |     foo::<f32>(42_u16.into());
-   |                ~~~~~~~~~~~~~
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:278:16
@@ -1382,7 +1382,7 @@ LL |     foo::<f32>(42_u8);
 help: you can convert a `u8` to an `f32`, producing the floating point representation of the integer
    |
 LL |     foo::<f32>(42_u8.into());
-   |                ~~~~~~~~~~~~
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:280:16
@@ -1393,7 +1393,7 @@ LL |     foo::<f32>(42_isize);
 help: change the type of the numeric literal from `isize` to `f32`
    |
 LL |     foo::<f32>(42_f32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:282:16
@@ -1404,7 +1404,7 @@ LL |     foo::<f32>(42_i64);
 help: change the type of the numeric literal from `i64` to `f32`
    |
 LL |     foo::<f32>(42_f32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:284:16
@@ -1415,7 +1415,7 @@ LL |     foo::<f32>(42_i32);
 help: change the type of the numeric literal from `i32` to `f32`
    |
 LL |     foo::<f32>(42_f32);
-   |                ~~~~~~
+   |                   ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:286:16
@@ -1426,7 +1426,7 @@ LL |     foo::<f32>(42_i16);
 help: you can convert an `i16` to an `f32`, producing the floating point representation of the integer
    |
 LL |     foo::<f32>(42_i16.into());
-   |                ~~~~~~~~~~~~~
+   |                      +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:288:16
@@ -1437,7 +1437,7 @@ LL |     foo::<f32>(42_i8);
 help: you can convert an `i8` to an `f32`, producing the floating point representation of the integer
    |
 LL |     foo::<f32>(42_i8.into());
-   |                ~~~~~~~~~~~~
+   |                     +++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:290:16
@@ -1448,25 +1448,29 @@ LL |     foo::<f32>(42.0_f64);
 help: change the type of the numeric literal from `f64` to `f32`
    |
 LL |     foo::<f32>(42.0_f32);
-   |                ~~~~~~~~
+   |                     ~~~
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:294:16
    |
 LL |     foo::<u32>(42_u8 as u16);
-   |                ^^^^^^^^^^^^
-   |                |
-   |                expected `u32`, found `u16`
-   |                help: you can convert a `u16` to a `u32`: `(42_u8 as u16).into()`
+   |                ^^^^^^^^^^^^ expected `u32`, found `u16`
+   |
+help: you can convert a `u16` to a `u32`
+   |
+LL |     foo::<u32>((42_u8 as u16).into());
+   |                +            ++++++++
 
 error[E0308]: mismatched types
   --> $DIR/numeric-suffix.rs:296:16
    |
 LL |     foo::<i32>(-42_i8);
-   |                ^^^^^^
-   |                |
-   |                expected `i32`, found `i8`
-   |                help: you can convert an `i8` to an `i32`: `(-42_i8).into()`
+   |                ^^^^^^ expected `i32`, found `i8`
+   |
+help: you can convert an `i8` to an `i32`
+   |
+LL |     foo::<i32>((-42_i8).into());
+   |                +      ++++++++
 
 error: aborting due to 134 previous errors
 
diff --git a/src/test/ui/object-does-not-impl-trait.stderr b/src/test/ui/object-does-not-impl-trait.stderr
index bf1641167cf..f1dd508a467 100644
--- a/src/test/ui/object-does-not-impl-trait.stderr
+++ b/src/test/ui/object-does-not-impl-trait.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `Box<dyn Foo>: Foo` is not satisfied
   --> $DIR/object-does-not-impl-trait.rs:6:44
    |
 LL | fn take_object(f: Box<dyn Foo>) { take_foo(f); }
-   |                                            ^ the trait `Foo` is not implemented for `Box<dyn Foo>`
+   |                                   -------- ^ the trait `Foo` is not implemented for `Box<dyn Foo>`
+   |                                   |
+   |                                   required by a bound introduced by this call
    |
 note: required by a bound in `take_foo`
   --> $DIR/object-does-not-impl-trait.rs:5:15
diff --git a/src/test/ui/object-safety/object-safety-associated-consts.curr.stderr b/src/test/ui/object-safety/object-safety-associated-consts.curr.stderr
index 35ec586892c..9dd144fee24 100644
--- a/src/test/ui/object-safety/object-safety-associated-consts.curr.stderr
+++ b/src/test/ui/object-safety/object-safety-associated-consts.curr.stderr
@@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
    |                              ^^^^^^^^ `Bar` cannot be made into an object
    |
-   = help: consider moving `X` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/object-safety-associated-consts.rs:9:11
    |
@@ -12,6 +11,7 @@ LL | trait Bar {
    |       --- this trait cannot be made into an object...
 LL |     const X: usize;
    |           ^ ...because it contains this associated `const`
+   = help: consider moving `X` to another trait
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr
index d51734ed231..9ba3b251e66 100644
--- a/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr
+++ b/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr
@@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL |     t
    |     ^ `Bar` cannot be made into an object
    |
-   = help: consider moving `X` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/object-safety-associated-consts.rs:9:11
    |
@@ -12,6 +11,7 @@ LL | trait Bar {
    |       --- this trait cannot be made into an object...
 LL |     const X: usize;
    |           ^ ...because it contains this associated `const`
+   = help: consider moving `X` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T`
    = note: required by cast to type `&dyn Bar`
 
diff --git a/src/test/ui/object-safety/object-safety-generics.curr.stderr b/src/test/ui/object-safety/object-safety-generics.curr.stderr
index 8d6094c5144..345950f1ae6 100644
--- a/src/test/ui/object-safety/object-safety-generics.curr.stderr
+++ b/src/test/ui/object-safety/object-safety-generics.curr.stderr
@@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
    |                              ^^^^^^^^ `Bar` cannot be made into an object
    |
-   = help: consider moving `bar` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/object-safety-generics.rs:10:8
    |
@@ -12,6 +11,7 @@ LL | trait Bar {
    |       --- this trait cannot be made into an object...
 LL |     fn bar<T>(&self, t: T);
    |        ^^^ ...because method `bar` has generic type parameters
+   = help: consider moving `bar` to another trait
 
 error[E0038]: the trait `Bar` cannot be made into an object
   --> $DIR/object-safety-generics.rs:24:39
@@ -19,7 +19,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL | fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
    |                                       ^^^^^^^^ `Bar` cannot be made into an object
    |
-   = help: consider moving `bar` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/object-safety-generics.rs:10:8
    |
@@ -27,6 +26,7 @@ LL | trait Bar {
    |       --- this trait cannot be made into an object...
 LL |     fn bar<T>(&self, t: T);
    |        ^^^ ...because method `bar` has generic type parameters
+   = help: consider moving `bar` to another trait
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr
index 3d2b2bb228c..86355627c79 100644
--- a/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr
+++ b/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr
@@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL |     t
    |     ^ `Bar` cannot be made into an object
    |
-   = help: consider moving `bar` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/object-safety-generics.rs:10:8
    |
@@ -12,6 +11,7 @@ LL | trait Bar {
    |       --- this trait cannot be made into an object...
 LL |     fn bar<T>(&self, t: T);
    |        ^^^ ...because method `bar` has generic type parameters
+   = help: consider moving `bar` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T`
    = note: required by cast to type `&dyn Bar`
 
@@ -21,7 +21,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL |     t as &dyn Bar
    |     ^ `Bar` cannot be made into an object
    |
-   = help: consider moving `bar` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/object-safety-generics.rs:10:8
    |
@@ -29,6 +28,7 @@ LL | trait Bar {
    |       --- this trait cannot be made into an object...
 LL |     fn bar<T>(&self, t: T);
    |        ^^^ ...because method `bar` has generic type parameters
+   = help: consider moving `bar` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T`
    = note: required by cast to type `&dyn Bar`
 
diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr
index 336929702e6..f91c9b98560 100644
--- a/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr
+++ b/src/test/ui/object-safety/object-safety-mentions-Self.curr.stderr
@@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
    |                              ^^^^^^^^ `Bar` cannot be made into an object
    |
-   = help: consider moving `bar` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/object-safety-mentions-Self.rs:11:22
    |
@@ -12,6 +11,7 @@ LL | trait Bar {
    |       --- this trait cannot be made into an object...
 LL |     fn bar(&self, x: &Self);
    |                      ^^^^^ ...because method `bar` references the `Self` type in this parameter
+   = help: consider moving `bar` to another trait
 
 error[E0038]: the trait `Baz` cannot be made into an object
   --> $DIR/object-safety-mentions-Self.rs:28:30
@@ -19,7 +19,6 @@ error[E0038]: the trait `Baz` cannot be made into an object
 LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
    |                              ^^^^^^^^ `Baz` cannot be made into an object
    |
-   = help: consider moving `baz` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/object-safety-mentions-Self.rs:15:22
    |
@@ -27,6 +26,7 @@ LL | trait Baz {
    |       --- this trait cannot be made into an object...
 LL |     fn baz(&self) -> Self;
    |                      ^^^^ ...because method `baz` references the `Self` type in its return type
+   = help: consider moving `baz` to another trait
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr
index 6e7896e309c..f48628c9d11 100644
--- a/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr
+++ b/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr
@@ -4,7 +4,6 @@ error[E0038]: the trait `Bar` cannot be made into an object
 LL |     t
    |     ^ `Bar` cannot be made into an object
    |
-   = help: consider moving `bar` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/object-safety-mentions-Self.rs:11:22
    |
@@ -12,6 +11,7 @@ LL | trait Bar {
    |       --- this trait cannot be made into an object...
 LL |     fn bar(&self, x: &Self);
    |                      ^^^^^ ...because method `bar` references the `Self` type in this parameter
+   = help: consider moving `bar` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T`
    = note: required by cast to type `&dyn Bar`
 
@@ -21,7 +21,6 @@ error[E0038]: the trait `Baz` cannot be made into an object
 LL |     t
    |     ^ `Baz` cannot be made into an object
    |
-   = help: consider moving `baz` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/object-safety-mentions-Self.rs:15:22
    |
@@ -29,6 +28,7 @@ LL | trait Baz {
    |       --- this trait cannot be made into an object...
 LL |     fn baz(&self) -> Self;
    |                      ^^^^ ...because method `baz` references the `Self` type in its return type
+   = help: consider moving `baz` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Baz>` for `&T`
    = note: required by cast to type `&dyn Baz`
 
diff --git a/src/test/ui/on-unimplemented/enclosing-scope.stderr b/src/test/ui/on-unimplemented/enclosing-scope.stderr
index abd156dd5ac..67759d02a16 100644
--- a/src/test/ui/on-unimplemented/enclosing-scope.stderr
+++ b/src/test/ui/on-unimplemented/enclosing-scope.stderr
@@ -4,7 +4,9 @@ error[E0277]: the trait bound `Foo: Trait` is not satisfied
 LL |       let x = || {
    |  _____________-
 LL | |         f(Foo{});
-   | |           ^^^^^ the trait `Trait` is not implemented for `Foo`
+   | |         - ^^^^^ the trait `Trait` is not implemented for `Foo`
+   | |         |
+   | |         required by a bound introduced by this call
 LL | |         let y = || {
 LL | |             f(Foo{});
 LL | |         };
@@ -23,7 +25,9 @@ error[E0277]: the trait bound `Foo: Trait` is not satisfied
 LL |           let y = || {
    |  _________________-
 LL | |             f(Foo{});
-   | |               ^^^^^ the trait `Trait` is not implemented for `Foo`
+   | |             - ^^^^^ the trait `Trait` is not implemented for `Foo`
+   | |             |
+   | |             required by a bound introduced by this call
 LL | |         };
    | |_________- in this scope
    |
@@ -42,7 +46,9 @@ LL | |         f(Foo{});
 LL | |         let y = || {
 ...  |
 LL | |             f(Foo{});
-   | |               ^^^^^ the trait `Trait` is not implemented for `Foo`
+   | |             - ^^^^^ the trait `Trait` is not implemented for `Foo`
+   | |             |
+   | |             required by a bound introduced by this call
 ...  |
 LL | |     f(Foo{});
 LL | | }
@@ -63,7 +69,9 @@ LL | |         f(Foo{});
 LL | |         let y = || {
 ...  |
 LL | |     f(Foo{});
-   | |       ^^^^^ the trait `Trait` is not implemented for `Foo`
+   | |     - ^^^^^ the trait `Trait` is not implemented for `Foo`
+   | |     |
+   | |     required by a bound introduced by this call
 LL | | }
    | |_- in this scope
    |
diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr
index 804b6282202..a3658f22426 100644
--- a/src/test/ui/on-unimplemented/multiple-impls.stderr
+++ b/src/test/ui/on-unimplemented/multiple-impls.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
   --> $DIR/multiple-impls.rs:33:18
    |
 LL |     Index::index(&[] as &[i32], 2u32);
-   |                  ^^^^^^^^^^^^^ trait message
+   |     ------------ ^^^^^^^^^^^^^ trait message
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Index<u32>` is not implemented for `[i32]`
 note: required by `Index::index`
@@ -15,7 +17,9 @@ error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
   --> $DIR/multiple-impls.rs:36:18
    |
 LL |     Index::index(&[] as &[i32], Foo(2u32));
-   |                  ^^^^^^^^^^^^^ on impl for Foo
+   |     ------------ ^^^^^^^^^^^^^ on impl for Foo
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
 note: required by `Index::index`
@@ -28,7 +32,9 @@ error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
   --> $DIR/multiple-impls.rs:39:18
    |
 LL |     Index::index(&[] as &[i32], Bar(2u32));
-   |                  ^^^^^^^^^^^^^ on impl for Bar
+   |     ------------ ^^^^^^^^^^^^^ on impl for Bar
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
 note: required by `Index::index`
diff --git a/src/test/ui/on-unimplemented/on-impl.stderr b/src/test/ui/on-unimplemented/on-impl.stderr
index bfd438e5cc2..18eca06ba69 100644
--- a/src/test/ui/on-unimplemented/on-impl.stderr
+++ b/src/test/ui/on-unimplemented/on-impl.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
   --> $DIR/on-impl.rs:22:25
    |
 LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
-   |                         ^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
+   |     ------------------- ^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Index<u32>` is not implemented for `[i32]`
 note: required by `Index::index`
diff --git a/src/test/ui/overloaded/overloaded-autoderef-order.rs b/src/test/ui/overloaded/overloaded-autoderef-order.rs
index 1ae16d2a7fc..f48bae55f5f 100644
--- a/src/test/ui/overloaded/overloaded-autoderef-order.rs
+++ b/src/test/ui/overloaded/overloaded-autoderef-order.rs
@@ -1,5 +1,7 @@
 // run-pass
 
+#![allow(dead_code)]
+
 use std::rc::Rc;
 use std::ops::Deref;
 
diff --git a/src/test/ui/parser/expr-as-stmt.fixed b/src/test/ui/parser/expr-as-stmt.fixed
index c217ab9774f..101959d6da0 100644
--- a/src/test/ui/parser/expr-as-stmt.fixed
+++ b/src/test/ui/parser/expr-as-stmt.fixed
@@ -10,7 +10,7 @@ fn foo() -> i32 {
 }
 
 fn bar() -> i32 {
-    ({2}) + 2 //~ ERROR expected expression, found `+`
+    ({2}) + 2 //~ ERROR leading `+` is not supported
     //~^ ERROR mismatched types
 }
 
@@ -32,4 +32,9 @@ fn moo(x: u32) -> bool {
     }) > 0 //~ ERROR expected expression
 }
 
+fn qux() -> u32 {
+    ({2}) - 2 //~ ERROR cannot apply unary operator `-` to type `u32`
+    //~^ ERROR mismatched types
+}
+
 fn main() {}
diff --git a/src/test/ui/parser/expr-as-stmt.rs b/src/test/ui/parser/expr-as-stmt.rs
index b04025faaec..45c4f977502 100644
--- a/src/test/ui/parser/expr-as-stmt.rs
+++ b/src/test/ui/parser/expr-as-stmt.rs
@@ -10,7 +10,7 @@ fn foo() -> i32 {
 }
 
 fn bar() -> i32 {
-    {2} + 2 //~ ERROR expected expression, found `+`
+    {2} + 2 //~ ERROR leading `+` is not supported
     //~^ ERROR mismatched types
 }
 
@@ -32,4 +32,9 @@ fn moo(x: u32) -> bool {
     } > 0 //~ ERROR expected expression
 }
 
+fn qux() -> u32 {
+    {2} - 2 //~ ERROR cannot apply unary operator `-` to type `u32`
+    //~^ ERROR mismatched types
+}
+
 fn main() {}
diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr
index ba5cd01abfc..cae775099e0 100644
--- a/src/test/ui/parser/expr-as-stmt.stderr
+++ b/src/test/ui/parser/expr-as-stmt.stderr
@@ -9,11 +9,11 @@ help: parentheses are required to parse this as an expression
 LL |     ({2}) + {2}
    |     +   +
 
-error: expected expression, found `+`
+error: leading `+` is not supported
   --> $DIR/expr-as-stmt.rs:13:9
    |
 LL |     {2} + 2
-   |         ^ expected expression
+   |         ^ unexpected `+`
    |
 help: parentheses are required to parse this as an expression
    |
@@ -99,7 +99,29 @@ help: parentheses are required to parse this as an expression
 LL |     ({ 3 }) * 3
    |     +     +
 
-error: aborting due to 9 previous errors
+error[E0308]: mismatched types
+  --> $DIR/expr-as-stmt.rs:36:6
+   |
+LL |     {2} - 2
+   |      ^ expected `()`, found integer
+   |
+help: you might have meant to return this value
+   |
+LL |     {return 2;} - 2
+   |      ++++++  +
+
+error[E0600]: cannot apply unary operator `-` to type `u32`
+  --> $DIR/expr-as-stmt.rs:36:9
+   |
+LL |     {2} - 2
+   |         ^^^ cannot apply unary operator `-`
+   |
+help: parentheses are required to parse this as an expression
+   |
+LL |     ({2}) - 2
+   |     +   +
+
+error: aborting due to 11 previous errors
 
-Some errors have detailed explanations: E0308, E0614.
+Some errors have detailed explanations: E0308, E0600, E0614.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/inverted-parameters.stderr b/src/test/ui/parser/inverted-parameters.stderr
index d1a249389fe..86622778203 100644
--- a/src/test/ui/parser/inverted-parameters.stderr
+++ b/src/test/ui/parser/inverted-parameters.stderr
@@ -38,15 +38,15 @@ LL | fn fizz(i32) {}
 help: if this is a `self` type, give it a parameter name
    |
 LL | fn fizz(self: i32) {}
-   |         ~~~~~~~~~
+   |         +++++
 help: if this is a parameter name, give it a type
    |
 LL | fn fizz(i32: TypeName) {}
-   |         ~~~~~~~~~~~~~
+   |            ++++++++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL | fn fizz(_: i32) {}
-   |         ~~~~~~
+   |         ++
 
 error: expected one of `:`, `@`, or `|`, found `S`
   --> $DIR/inverted-parameters.rs:27:23
diff --git a/src/test/ui/parser/issue-44406.rs b/src/test/ui/parser/issue-44406.rs
index 83bbf884a4f..a5b7e83a016 100644
--- a/src/test/ui/parser/issue-44406.rs
+++ b/src/test/ui/parser/issue-44406.rs
@@ -1,10 +1,10 @@
 macro_rules! foo {
     ($rest: tt) => {
-        bar(baz: $rest)
+        bar(baz: $rest) //~ ERROR invalid `struct` delimiters or `fn` call arguments
     }
 }
 
 fn main() {
-    foo!(true); //~ ERROR expected type, found keyword
+    foo!(true);
     //~^ ERROR expected identifier, found keyword
 }
diff --git a/src/test/ui/parser/issue-44406.stderr b/src/test/ui/parser/issue-44406.stderr
index 372387131e5..862026408ef 100644
--- a/src/test/ui/parser/issue-44406.stderr
+++ b/src/test/ui/parser/issue-44406.stderr
@@ -9,17 +9,25 @@ help: you can escape reserved keywords to use them as identifiers
 LL |     foo!(r#true);
    |          ~~~~~~
 
-error: expected type, found keyword `true`
-  --> $DIR/issue-44406.rs:8:10
+error: invalid `struct` delimiters or `fn` call arguments
+  --> $DIR/issue-44406.rs:3:9
    |
 LL |         bar(baz: $rest)
-   |                - help: try using a semicolon: `;`
+   |         ^^^^^^^^^^^^^^^
 ...
 LL |     foo!(true);
-   |          ^^^^ expected type
+   |     ----------- in this macro invocation
+   |
+   = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: if `bar` is a struct, use braces as delimiters
+   |
+LL |         bar {  }
+   |             ~
+help: if `bar` is a function, use the arguments directly
    |
-   = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
-   = note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
+LL -         bar(baz: $rest)
+LL +         bar(true);
+   | 
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/parser/issue-88276-unary-plus.fixed b/src/test/ui/parser/issue-88276-unary-plus.fixed
new file mode 100644
index 00000000000..25b7c340f60
--- /dev/null
+++ b/src/test/ui/parser/issue-88276-unary-plus.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+#[allow(unused_parens)]
+fn main() {
+    let _ = 1; //~ ERROR leading `+` is not supported
+    let _ = (1.0 + 2.0) * 3.0; //~ ERROR leading `+` is not supported
+                           //~| ERROR leading `+` is not supported
+    let _ = [3, 4+6]; //~ ERROR leading `+` is not supported
+}
diff --git a/src/test/ui/parser/issue-88276-unary-plus.rs b/src/test/ui/parser/issue-88276-unary-plus.rs
new file mode 100644
index 00000000000..11b2e9d6016
--- /dev/null
+++ b/src/test/ui/parser/issue-88276-unary-plus.rs
@@ -0,0 +1,8 @@
+// run-rustfix
+#[allow(unused_parens)]
+fn main() {
+    let _ = +1; //~ ERROR leading `+` is not supported
+    let _ = (1.0 + +2.0) * +3.0; //~ ERROR leading `+` is not supported
+                           //~| ERROR leading `+` is not supported
+    let _ = [+3, 4+6]; //~ ERROR leading `+` is not supported
+}
diff --git a/src/test/ui/parser/issue-88276-unary-plus.stderr b/src/test/ui/parser/issue-88276-unary-plus.stderr
new file mode 100644
index 00000000000..b26761729a8
--- /dev/null
+++ b/src/test/ui/parser/issue-88276-unary-plus.stderr
@@ -0,0 +1,50 @@
+error: leading `+` is not supported
+  --> $DIR/issue-88276-unary-plus.rs:4:13
+   |
+LL |     let _ = +1;
+   |             ^ unexpected `+`
+   |
+help: try removing the `+`
+   |
+LL -     let _ = +1;
+LL +     let _ = 1;
+   | 
+
+error: leading `+` is not supported
+  --> $DIR/issue-88276-unary-plus.rs:5:20
+   |
+LL |     let _ = (1.0 + +2.0) * +3.0;
+   |                    ^ unexpected `+`
+   |
+help: try removing the `+`
+   |
+LL -     let _ = (1.0 + +2.0) * +3.0;
+LL +     let _ = (1.0 + 2.0) * +3.0;
+   | 
+
+error: leading `+` is not supported
+  --> $DIR/issue-88276-unary-plus.rs:5:28
+   |
+LL |     let _ = (1.0 + +2.0) * +3.0;
+   |                            ^ unexpected `+`
+   |
+help: try removing the `+`
+   |
+LL -     let _ = (1.0 + +2.0) * +3.0;
+LL +     let _ = (1.0 + +2.0) * 3.0;
+   | 
+
+error: leading `+` is not supported
+  --> $DIR/issue-88276-unary-plus.rs:7:14
+   |
+LL |     let _ = [+3, 4+6];
+   |              ^ unexpected `+`
+   |
+help: try removing the `+`
+   |
+LL -     let _ = [+3, 4+6];
+LL +     let _ = [3, 4+6];
+   | 
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/parser/issue-88583-union-as-ident.rs b/src/test/ui/parser/issue-88583-union-as-ident.rs
new file mode 100644
index 00000000000..b3d66d46b1d
--- /dev/null
+++ b/src/test/ui/parser/issue-88583-union-as-ident.rs
@@ -0,0 +1,15 @@
+// check-pass
+
+#![allow(non_camel_case_types)]
+
+struct union;
+
+impl union {
+    pub fn new() -> Self {
+        union { }
+    }
+}
+
+fn main() {
+    let _u = union::new();
+}
diff --git a/src/test/ui/parser/issue-88818.rs b/src/test/ui/parser/issue-88818.rs
new file mode 100644
index 00000000000..b9233ca8339
--- /dev/null
+++ b/src/test/ui/parser/issue-88818.rs
@@ -0,0 +1,10 @@
+// Regression test for #88818 (improve error message for missing trait
+// in `impl for X`).
+
+struct S { }
+impl for S { }
+//~^ ERROR: missing trait in a trait impl
+//~| HELP: add a trait here
+//~| HELP: for an inherent impl, drop this `for`
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-88818.stderr b/src/test/ui/parser/issue-88818.stderr
new file mode 100644
index 00000000000..d30990ae582
--- /dev/null
+++ b/src/test/ui/parser/issue-88818.stderr
@@ -0,0 +1,18 @@
+error: missing trait in a trait impl
+  --> $DIR/issue-88818.rs:5:5
+   |
+LL | impl for S { }
+   |     ^
+   |
+help: add a trait here
+   |
+LL | impl Trait for S { }
+   |      +++++
+help: for an inherent impl, drop this `for`
+   |
+LL - impl for S { }
+LL + impl S { }
+   | 
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/lifetime-in-pattern.stderr b/src/test/ui/parser/lifetime-in-pattern.stderr
index bf73595e5b0..a1d721e746a 100644
--- a/src/test/ui/parser/lifetime-in-pattern.stderr
+++ b/src/test/ui/parser/lifetime-in-pattern.stderr
@@ -13,16 +13,16 @@ LL | fn test(&'a str) {
    = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
 help: if this is a `self` type, give it a parameter name
    |
-LL | fn test(self: &str) {
-   |         ~~~~~~~~~~
+LL | fn test(self: &'a str) {
+   |         +++++
 help: if this is a parameter name, give it a type
    |
 LL | fn test(str: &TypeName) {
    |         ~~~~~~~~~~~~~~
 help: if this is a type, explicitly ignore the parameter name
    |
-LL | fn test(_: &str) {
-   |         ~~~~~~~
+LL | fn test(_: &'a str) {
+   |         ++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/parser/macro-braces-dot-question.rs b/src/test/ui/parser/macro-braces-dot-question.rs
new file mode 100644
index 00000000000..016b434a612
--- /dev/null
+++ b/src/test/ui/parser/macro-braces-dot-question.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+use std::io::Write;
+
+fn main() -> Result<(), std::io::Error> {
+    vec! { 1, 2, 3 }.len();
+    write! { vec![], "" }?;
+    println!{""}
+    [0]; // separate statement, not indexing into the result of println.
+    Ok(())
+}
diff --git a/src/test/ui/parser/omitted-arg-in-item-fn.stderr b/src/test/ui/parser/omitted-arg-in-item-fn.stderr
index 329fa8776f5..ce2eab051ad 100644
--- a/src/test/ui/parser/omitted-arg-in-item-fn.stderr
+++ b/src/test/ui/parser/omitted-arg-in-item-fn.stderr
@@ -8,15 +8,15 @@ LL | fn foo(x) {
 help: if this is a `self` type, give it a parameter name
    |
 LL | fn foo(self: x) {
-   |        ~~~~~~~
+   |        +++++
 help: if this is a parameter name, give it a type
    |
 LL | fn foo(x: TypeName) {
-   |        ~~~~~~~~~~~
+   |         ++++++++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL | fn foo(_: x) {
-   |        ~~~~
+   |        ++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/pat-lt-bracket-2.stderr b/src/test/ui/parser/pat-lt-bracket-2.stderr
index 762733cc97b..c78f96e1add 100644
--- a/src/test/ui/parser/pat-lt-bracket-2.stderr
+++ b/src/test/ui/parser/pat-lt-bracket-2.stderr
@@ -8,11 +8,11 @@ LL | fn a(B<) {}
 help: if this is a `self` type, give it a parameter name
    |
 LL | fn a(self: B<) {}
-   |      ~~~~~~~
+   |      +++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL | fn a(_: B<) {}
-   |      ~~~~
+   |      ++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/recover-from-bad-variant.rs b/src/test/ui/parser/recover-from-bad-variant.rs
index 1bcef450bb9..e8887147cbc 100644
--- a/src/test/ui/parser/recover-from-bad-variant.rs
+++ b/src/test/ui/parser/recover-from-bad-variant.rs
@@ -5,7 +5,7 @@ enum Enum {
 
 fn main() {
     let x = Enum::Foo(a: 3, b: 4);
-    //~^ ERROR expected type, found `3`
+    //~^ ERROR invalid `struct` delimiters or `fn` call arguments
     match x {
         Enum::Foo(a, b) => {}
         //~^ ERROR expected tuple struct or tuple variant, found struct variant `Enum::Foo`
diff --git a/src/test/ui/parser/recover-from-bad-variant.stderr b/src/test/ui/parser/recover-from-bad-variant.stderr
index 61ea3695eee..8cb71069bda 100644
--- a/src/test/ui/parser/recover-from-bad-variant.stderr
+++ b/src/test/ui/parser/recover-from-bad-variant.stderr
@@ -1,13 +1,18 @@
-error: expected type, found `3`
-  --> $DIR/recover-from-bad-variant.rs:7:26
+error: invalid `struct` delimiters or `fn` call arguments
+  --> $DIR/recover-from-bad-variant.rs:7:13
    |
 LL |     let x = Enum::Foo(a: 3, b: 4);
-   |                        - ^ expected type
-   |                        |
-   |                        tried to parse a type due to this type ascription
+   |             ^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `<expr>: <type>`
-   = note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
+help: if `Enum::Foo` is a struct, use braces as delimiters
+   |
+LL |     let x = Enum::Foo { a: 3, b: 4 };
+   |                       ~            ~
+help: if `Enum::Foo` is a function, use the arguments directly
+   |
+LL -     let x = Enum::Foo(a: 3, b: 4);
+LL +     let x = Enum::Foo(3, 4);
+   | 
 
 error[E0532]: expected tuple struct or tuple variant, found struct variant `Enum::Foo`
   --> $DIR/recover-from-bad-variant.rs:10:9
diff --git a/src/test/ui/path-lookahead.stderr b/src/test/ui/path-lookahead.stderr
index dcf235a9e27..8adf02b150b 100644
--- a/src/test/ui/path-lookahead.stderr
+++ b/src/test/ui/path-lookahead.stderr
@@ -2,13 +2,18 @@ warning: unnecessary parentheses around `return` value
   --> $DIR/path-lookahead.rs:10:12
    |
 LL |     return (<T as ToString>::to_string(&arg));
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
+   |            ^                                ^
    |
 note: the lint level is defined here
   --> $DIR/path-lookahead.rs:5:9
    |
 LL | #![warn(unused_parens)]
    |         ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -     return (<T as ToString>::to_string(&arg));
+LL +     return <T as ToString>::to_string(&arg);
+   | 
 
 warning: 1 warning emitted
 
diff --git a/src/test/ui/phantom-auto-trait.stderr b/src/test/ui/phantom-auto-trait.stderr
index e7b5528daee..1cc653c51cf 100644
--- a/src/test/ui/phantom-auto-trait.stderr
+++ b/src/test/ui/phantom-auto-trait.stderr
@@ -2,7 +2,9 @@ error[E0277]: `T` cannot be shared between threads safely
   --> $DIR/phantom-auto-trait.rs:21:12
    |
 LL |     is_zen(x)
-   |            ^ `T` cannot be shared between threads safely
+   |     ------ ^ `T` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required because of the requirements on the impl of `Zen` for `&T`
   --> $DIR/phantom-auto-trait.rs:10:24
@@ -29,7 +31,9 @@ error[E0277]: `T` cannot be shared between threads safely
   --> $DIR/phantom-auto-trait.rs:26:12
    |
 LL |     is_zen(x)
-   |            ^ `T` cannot be shared between threads safely
+   |     ------ ^ `T` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required because of the requirements on the impl of `Zen` for `&T`
   --> $DIR/phantom-auto-trait.rs:10:24
diff --git a/src/test/ui/pptypedef.stderr b/src/test/ui/pptypedef.stderr
index c42d9e6bbf0..49895f3db4d 100644
--- a/src/test/ui/pptypedef.stderr
+++ b/src/test/ui/pptypedef.stderr
@@ -7,7 +7,7 @@ LL |     let_in(3u32, |i| { assert!(i == 3i32); });
 help: change the type of the numeric literal from `i32` to `u32`
    |
 LL |     let_in(3u32, |i| { assert!(i == 3u32); });
-   |                                     ~~~~
+   |                                      ~~~
 
 error[E0308]: mismatched types
   --> $DIR/pptypedef.rs:8:37
@@ -18,7 +18,7 @@ LL |     let_in(3i32, |i| { assert!(i == 3u32); });
 help: change the type of the numeric literal from `u32` to `i32`
    |
 LL |     let_in(3i32, |i| { assert!(i == 3i32); });
-   |                                     ~~~~
+   |                                      ~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr
index 713560772ee..e9a44ccb12e 100644
--- a/src/test/ui/proc-macro/span-preservation.stderr
+++ b/src/test/ui/proc-macro/span-preservation.stderr
@@ -18,7 +18,7 @@ LL |         Some(x) => { return x },
 help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
    |
 LL |         Some(x) => { return x.try_into().unwrap() },
-   |                             ~~~~~~~~~~~~~~~~~~~~~
+   |                              ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/span-preservation.rs:33:22
diff --git a/src/test/ui/repeat_count.stderr b/src/test/ui/repeat_count.stderr
index c85f0572031..59bcd954a1f 100644
--- a/src/test/ui/repeat_count.stderr
+++ b/src/test/ui/repeat_count.stderr
@@ -55,7 +55,7 @@ LL |     let f = [0; 4u8];
 help: change the type of the numeric literal from `u8` to `usize`
    |
 LL |     let f = [0; 4usize];
-   |                 ~~~~~~
+   |                  ~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/repeat_count.rs:31:17
diff --git a/src/test/ui/repr/repr-transparent-issue-87496.rs b/src/test/ui/repr/repr-transparent-issue-87496.rs
new file mode 100644
index 00000000000..a4dd45c63f5
--- /dev/null
+++ b/src/test/ui/repr/repr-transparent-issue-87496.rs
@@ -0,0 +1,12 @@
+// Regression test for the ICE described in #87496.
+
+// check-pass
+
+#[repr(transparent)]
+struct TransparentCustomZst(());
+extern "C" {
+    fn good17(p: TransparentCustomZst);
+    //~^ WARNING: `extern` block uses type `TransparentCustomZst`, which is not FFI-safe
+}
+
+fn main() {}
diff --git a/src/test/ui/repr/repr-transparent-issue-87496.stderr b/src/test/ui/repr/repr-transparent-issue-87496.stderr
new file mode 100644
index 00000000000..c488755cc24
--- /dev/null
+++ b/src/test/ui/repr/repr-transparent-issue-87496.stderr
@@ -0,0 +1,16 @@
+warning: `extern` block uses type `TransparentCustomZst`, which is not FFI-safe
+  --> $DIR/repr-transparent-issue-87496.rs:8:18
+   |
+LL |     fn good17(p: TransparentCustomZst);
+   |                  ^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = note: `#[warn(improper_ctypes)]` on by default
+   = note: this struct contains only zero-sized fields
+note: the type is defined here
+  --> $DIR/repr-transparent-issue-87496.rs:6:1
+   |
+LL | struct TransparentCustomZst(());
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs
index 8516bafef9b..0098f087d10 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs
+++ b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/enums.rs
@@ -4,8 +4,29 @@
 pub enum NonExhaustiveEnum {
     Unit,
     Tuple(u32),
-    Struct { field: u32 }
+    Struct { field: u32 },
+}
+
+#[non_exhaustive]
+pub enum NestedNonExhaustive {
+    A(NonExhaustiveEnum),
+    B,
+    C,
 }
 
 #[non_exhaustive]
 pub enum EmptyNonExhaustiveEnum {}
+
+pub enum VariantNonExhaustive {
+    #[non_exhaustive]
+    Bar {
+        x: u32,
+        y: u64,
+    },
+    Baz(u32, u16),
+}
+
+#[non_exhaustive]
+pub enum NonExhaustiveSingleVariant {
+    A(bool),
+}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs
index 6bfe7bf923d..5b2181d2d83 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs
+++ b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/structs.rs
@@ -1,3 +1,4 @@
+#[derive(Default)]
 #[non_exhaustive]
 pub struct NormalStruct {
     pub first_field: u16,
@@ -15,7 +16,7 @@ pub struct TupleStruct(pub u16, pub u16);
 pub struct FunctionalRecord {
     pub first_field: u16,
     pub second_field: u16,
-    pub third_field: bool
+    pub third_field: bool,
 }
 
 impl Default for FunctionalRecord {
@@ -23,3 +24,10 @@ impl Default for FunctionalRecord {
         FunctionalRecord { first_field: 640, second_field: 480, third_field: false }
     }
 }
+
+#[derive(Default)]
+#[non_exhaustive]
+pub struct NestedStruct {
+    pub foo: u16,
+    pub bar: NormalStruct,
+}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/reachable-patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/reachable-patterns.rs
new file mode 100644
index 00000000000..115fd300fa5
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/reachable-patterns.rs
@@ -0,0 +1,160 @@
+// Test that the `non_exhaustive_omitted_patterns` lint is triggered correctly.
+
+// aux-build:enums.rs
+extern crate enums;
+
+// aux-build:structs.rs
+extern crate structs;
+
+use enums::{
+    EmptyNonExhaustiveEnum, NestedNonExhaustive, NonExhaustiveEnum, NonExhaustiveSingleVariant,
+    VariantNonExhaustive,
+};
+use structs::{FunctionalRecord, NestedStruct, NormalStruct};
+
+#[non_exhaustive]
+#[derive(Default)]
+pub struct Foo {
+    a: u8,
+    b: usize,
+    c: String,
+}
+
+#[non_exhaustive]
+pub enum Bar {
+    A,
+    B,
+    C,
+}
+
+fn main() {
+    let enumeration = Bar::A;
+
+    // Ok: this is a crate local non_exhaustive enum
+    match enumeration {
+        Bar::A => {}
+        Bar::B => {}
+        #[deny(non_exhaustive_omitted_patterns)]
+        _ => {}
+    }
+
+    let non_enum = NonExhaustiveEnum::Unit;
+
+    // Ok: without the attribute
+    match non_enum {
+        NonExhaustiveEnum::Unit => {}
+        NonExhaustiveEnum::Tuple(_) => {}
+        _ => {}
+    }
+
+    match non_enum {
+        NonExhaustiveEnum::Unit => {}
+        NonExhaustiveEnum::Tuple(_) => {}
+        #[deny(non_exhaustive_omitted_patterns)]
+        _ => {}
+    }
+    //~^^ some variants are not matched explicitly
+
+    match non_enum {
+        NonExhaustiveEnum::Unit | NonExhaustiveEnum::Struct { .. } => {}
+        #[deny(non_exhaustive_omitted_patterns)]
+        _ => {}
+    }
+    //~^^ some variants are not matched explicitly
+
+    let x = 5;
+    match non_enum {
+        NonExhaustiveEnum::Unit if x > 10 => {}
+        NonExhaustiveEnum::Tuple(_) => {}
+        NonExhaustiveEnum::Struct { .. } => {}
+        #[deny(non_exhaustive_omitted_patterns)]
+        _ => {}
+    }
+    //~^^ some variants are not matched explicitly
+
+    // Ok: all covered and not `unreachable-patterns`
+    #[deny(unreachable_patterns)]
+    match non_enum {
+        NonExhaustiveEnum::Unit => {}
+        NonExhaustiveEnum::Tuple(_) => {}
+        NonExhaustiveEnum::Struct { .. } => {}
+        #[deny(non_exhaustive_omitted_patterns)]
+        _ => {}
+    }
+
+    #[deny(non_exhaustive_omitted_patterns)]
+    match NestedNonExhaustive::B {
+        NestedNonExhaustive::A(NonExhaustiveEnum::Unit) => {}
+        NestedNonExhaustive::A(_) => {}
+        NestedNonExhaustive::B => {}
+        _ => {}
+    }
+    //~^^ some variants are not matched explicitly
+    //~^^^^^ some variants are not matched explicitly
+
+    // The io::ErrorKind has many `unstable` fields how do they interact with this
+    // lint
+    #[deny(non_exhaustive_omitted_patterns)]
+    match std::io::ErrorKind::Other {
+        std::io::ErrorKind::NotFound => {}
+        std::io::ErrorKind::PermissionDenied => {}
+        std::io::ErrorKind::ConnectionRefused => {}
+        std::io::ErrorKind::ConnectionReset => {}
+        std::io::ErrorKind::ConnectionAborted => {}
+        std::io::ErrorKind::NotConnected => {}
+        std::io::ErrorKind::AddrInUse => {}
+        std::io::ErrorKind::AddrNotAvailable => {}
+        std::io::ErrorKind::BrokenPipe => {}
+        std::io::ErrorKind::AlreadyExists => {}
+        std::io::ErrorKind::WouldBlock => {}
+        std::io::ErrorKind::InvalidInput => {}
+        std::io::ErrorKind::InvalidData => {}
+        std::io::ErrorKind::TimedOut => {}
+        std::io::ErrorKind::WriteZero => {}
+        std::io::ErrorKind::Interrupted => {}
+        std::io::ErrorKind::Other => {}
+        std::io::ErrorKind::UnexpectedEof => {}
+        std::io::ErrorKind::Unsupported => {}
+        std::io::ErrorKind::OutOfMemory => {}
+        // All stable variants are above and unstable in `_`
+        _ => {}
+    }
+    //~^^ some variants are not matched explicitly
+
+    #[warn(non_exhaustive_omitted_patterns)]
+    match VariantNonExhaustive::Baz(1, 2) {
+        VariantNonExhaustive::Baz(_, _) => {}
+        VariantNonExhaustive::Bar { x, .. } => {}
+    }
+    //~^^ some fields are not explicitly listed
+
+    #[warn(non_exhaustive_omitted_patterns)]
+    let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default();
+    //~^ some fields are not explicitly listed
+
+    // Ok: this is local
+    #[warn(non_exhaustive_omitted_patterns)]
+    let Foo { a, b, .. } = Foo::default();
+
+    #[warn(non_exhaustive_omitted_patterns)]
+    let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
+    //~^ some fields are not explicitly listed
+    //~^^ some fields are not explicitly listed
+
+    // Ok: because this only has 1 variant
+    #[deny(non_exhaustive_omitted_patterns)]
+    match NonExhaustiveSingleVariant::A(true) {
+        NonExhaustiveSingleVariant::A(true) => {}
+        _ => {}
+    }
+
+    #[deny(non_exhaustive_omitted_patterns)]
+    match NonExhaustiveSingleVariant::A(true) {
+        _ => {}
+    }
+    //~^^ some variants are not matched explicitly
+
+    // Ok: we don't lint on `if let` expressions
+    #[deny(non_exhaustive_omitted_patterns)]
+    if let NonExhaustiveEnum::Tuple(_) = non_enum {}
+}
diff --git a/src/test/ui/rfc-2008-non-exhaustive/reachable-patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/reachable-patterns.stderr
new file mode 100644
index 00000000000..aebe2acb6ad
--- /dev/null
+++ b/src/test/ui/rfc-2008-non-exhaustive/reachable-patterns.stderr
@@ -0,0 +1,146 @@
+warning: some fields are not explicitly listed
+  --> $DIR/reachable-patterns.rs:127:9
+   |
+LL |         VariantNonExhaustive::Bar { x, .. } => {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `y` not listed
+   |
+note: the lint level is defined here
+  --> $DIR/reachable-patterns.rs:124:12
+   |
+LL |     #[warn(non_exhaustive_omitted_patterns)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+   = note: the pattern is of type `VariantNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
+
+warning: some fields are not explicitly listed
+  --> $DIR/reachable-patterns.rs:132:9
+   |
+LL |     let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `third_field` not listed
+   |
+note: the lint level is defined here
+  --> $DIR/reachable-patterns.rs:131:12
+   |
+LL |     #[warn(non_exhaustive_omitted_patterns)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+   = note: the pattern is of type `FunctionalRecord` and the `non_exhaustive_omitted_patterns` attribute was found
+
+warning: some fields are not explicitly listed
+  --> $DIR/reachable-patterns.rs:140:29
+   |
+LL |     let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `second_field` not listed
+   |
+note: the lint level is defined here
+  --> $DIR/reachable-patterns.rs:139:12
+   |
+LL |     #[warn(non_exhaustive_omitted_patterns)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+   = note: the pattern is of type `NormalStruct` and the `non_exhaustive_omitted_patterns` attribute was found
+
+warning: some fields are not explicitly listed
+  --> $DIR/reachable-patterns.rs:140:9
+   |
+LL |     let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `foo` not listed
+   |
+   = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+   = note: the pattern is of type `NestedStruct` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+  --> $DIR/reachable-patterns.rs:54:9
+   |
+LL |         _ => {}
+   |         ^ pattern `Struct { .. }` not covered
+   |
+note: the lint level is defined here
+  --> $DIR/reachable-patterns.rs:53:16
+   |
+LL |         #[deny(non_exhaustive_omitted_patterns)]
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: ensure that all variants are matched explicitly by adding the suggested match arms
+   = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+  --> $DIR/reachable-patterns.rs:61:9
+   |
+LL |         _ => {}
+   |         ^ pattern `Tuple(_)` not covered
+   |
+note: the lint level is defined here
+  --> $DIR/reachable-patterns.rs:60:16
+   |
+LL |         #[deny(non_exhaustive_omitted_patterns)]
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: ensure that all variants are matched explicitly by adding the suggested match arms
+   = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+  --> $DIR/reachable-patterns.rs:71:9
+   |
+LL |         _ => {}
+   |         ^ pattern `Unit` not covered
+   |
+note: the lint level is defined here
+  --> $DIR/reachable-patterns.rs:70:16
+   |
+LL |         #[deny(non_exhaustive_omitted_patterns)]
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: ensure that all variants are matched explicitly by adding the suggested match arms
+   = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+  --> $DIR/reachable-patterns.rs:88:32
+   |
+LL |         NestedNonExhaustive::A(_) => {}
+   |                                ^ patterns `Tuple(_)` and `Struct { .. }` not covered
+   |
+note: the lint level is defined here
+  --> $DIR/reachable-patterns.rs:85:12
+   |
+LL |     #[deny(non_exhaustive_omitted_patterns)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: ensure that all variants are matched explicitly by adding the suggested match arms
+   = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+  --> $DIR/reachable-patterns.rs:90:9
+   |
+LL |         _ => {}
+   |         ^ pattern `C` not covered
+   |
+   = help: ensure that all variants are matched explicitly by adding the suggested match arms
+   = note: the matched value is of type `NestedNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+  --> $DIR/reachable-patterns.rs:120:9
+   |
+LL |         _ => {}
+   |         ^ patterns `HostUnreachable`, `NetworkUnreachable`, `NetworkDown` and 18 more not covered
+   |
+note: the lint level is defined here
+  --> $DIR/reachable-patterns.rs:97:12
+   |
+LL |     #[deny(non_exhaustive_omitted_patterns)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: ensure that all variants are matched explicitly by adding the suggested match arms
+   = note: the matched value is of type `ErrorKind` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: some variants are not matched explicitly
+  --> $DIR/reachable-patterns.rs:153:9
+   |
+LL |         _ => {}
+   |         ^ pattern `A(_)` not covered
+   |
+note: the lint level is defined here
+  --> $DIR/reachable-patterns.rs:151:12
+   |
+LL |     #[deny(non_exhaustive_omitted_patterns)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: ensure that all variants are matched explicitly by adding the suggested match arms
+   = note: the matched value is of type `NonExhaustiveSingleVariant` and the `non_exhaustive_omitted_patterns` attribute was found
+
+error: aborting due to 7 previous errors; 4 warnings emitted
+
diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr
index b0c319f2c7f..272b2ef6ee1 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr
@@ -16,13 +16,13 @@ error[E0603]: tuple struct constructor `TupleStruct` is private
 LL |     let ts_explicit = structs::TupleStruct(640, 480);
    |                                ^^^^^^^^^^^ private tuple struct constructor
    |
-  ::: $DIR/auxiliary/structs.rs:11:24
+  ::: $DIR/auxiliary/structs.rs:12:24
    |
 LL | pub struct TupleStruct(pub u16, pub u16);
    |                        ---------------- a constructor is private if any of the fields is private
    |
 note: the tuple struct constructor `TupleStruct` is defined here
-  --> $DIR/auxiliary/structs.rs:11:1
+  --> $DIR/auxiliary/structs.rs:12:1
    |
 LL | pub struct TupleStruct(pub u16, pub u16);
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -34,7 +34,7 @@ LL |     let us_explicit = structs::UnitStruct;
    |                                ^^^^^^^^^^ private unit struct
    |
 note: the unit struct `UnitStruct` is defined here
-  --> $DIR/auxiliary/structs.rs:8:1
+  --> $DIR/auxiliary/structs.rs:9:1
    |
 LL | pub struct UnitStruct;
    | ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr
index 4514fd96c2e..593821bf961 100644
--- a/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr
+++ b/src/test/ui/rfc-2565-param-attrs/param-attrs-2018.stderr
@@ -8,15 +8,15 @@ LL | trait Trait2015 { fn foo(#[allow(C)] i32); }
 help: if this is a `self` type, give it a parameter name
    |
 LL | trait Trait2015 { fn foo(#[allow(C)] self: i32); }
-   |                                      ~~~~~~~~~
+   |                                      +++++
 help: if this is a parameter name, give it a type
    |
 LL | trait Trait2015 { fn foo(#[allow(C)] i32: TypeName); }
-   |                                      ~~~~~~~~~~~~~
+   |                                         ++++++++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL | trait Trait2015 { fn foo(#[allow(C)] _: i32); }
-   |                                      ~~~~~~
+   |                                      ++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs
index 7185376b440..cc24dbd96d2 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs
@@ -16,12 +16,17 @@ impl const PartialEq for S {
 
 // This duplicate bound should not result in ambiguities. It should be equivalent to a single ~const
 // bound.
-// const fn equals_self<T: PartialEq + ~const PartialEq>(t: &T) -> bool {
-// FIXME(fee1-dead)^ why should the order matter here?
-const fn equals_self<T: ~const PartialEq + PartialEq>(t: &T) -> bool {
+const fn equals_self<T: PartialEq + ~const PartialEq>(t: &T) -> bool {
     *t == *t
 }
 
-pub const EQ: bool = equals_self(&S);
+trait A: PartialEq {}
+impl<T: PartialEq> A for T {}
+
+const fn equals_self2<T: A + ~const PartialEq>(t: &T) -> bool {
+    *t == *t
+}
+
+pub const EQ: bool = equals_self(&S) && equals_self2(&S);
 
 fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
index 9b9bda7c90e..0440f17a704 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
@@ -2,7 +2,9 @@ error[E0277]: can't compare `S` with `S`
   --> $DIR/call-generic-method-nonconst.rs:19:34
    |
 LL | pub const EQ: bool = equals_self(&S);
-   |                                  ^^ no implementation for `S == S`
+   |                      ----------- ^^ no implementation for `S == S`
+   |                      |
+   |                      required by a bound introduced by this call
    |
    = help: the trait `PartialEq` is not implemented for `S`
 note: required by a bound in `equals_self`
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
new file mode 100644
index 00000000000..34cd1d2b107
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
@@ -0,0 +1,68 @@
+error: `~const` is not allowed here
+  --> $DIR/const-drop-fail.rs:27:35
+   |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+   |                                   ^^^^^^^^
+   |
+   = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+
+error[E0277]: the trait bound `NonTrivialDrop: Drop` is not satisfied
+  --> $DIR/const-drop-fail.rs:45:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     NonTrivialDrop,
+   |     ^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `NonTrivialDrop`
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:36:19
+   |
+LL | const fn check<T: ~const Drop>(_: T) {}
+   |                   ^^^^^^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `ConstImplWithDropGlue: Drop` is not satisfied
+  --> $DIR/const-drop-fail.rs:47:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     ConstImplWithDropGlue(NonTrivialDrop),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `ConstImplWithDropGlue`
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:36:19
+   |
+LL | const fn check<T: ~const Drop>(_: T) {}
+   |                   ^^^^^^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied
+  --> $DIR/const-drop-fail.rs:49:5
+   |
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop`
+   |
+note: required by `ConstDropImplWithBounds`
+  --> $DIR/const-drop-fail.rs:27:1
+   |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied
+  --> $DIR/const-drop-fail.rs:49:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop`
+   |
+note: required by a bound in `ConstDropImplWithBounds`
+  --> $DIR/const-drop-fail.rs:27:35
+   |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+   |                                   ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
new file mode 100644
index 00000000000..3d4de088f55
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
@@ -0,0 +1,54 @@
+// revisions: stock precise
+#![feature(const_trait_impl)]
+#![feature(const_mut_refs)]
+#![feature(const_fn_trait_bound)]
+#![cfg_attr(precise, feature(const_precise_live_drops))]
+
+use std::marker::PhantomData;
+
+struct NonTrivialDrop;
+
+impl Drop for NonTrivialDrop {
+    fn drop(&mut self) {
+        println!("Non trivial drop");
+    }
+}
+
+struct ConstImplWithDropGlue(NonTrivialDrop);
+
+impl const Drop for ConstImplWithDropGlue {
+    fn drop(&mut self) {}
+}
+
+trait A { fn a() { println!("A"); } }
+
+impl A for NonTrivialDrop {}
+
+struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+//~^ ERROR `~const` is not allowed
+
+impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
+    fn drop(&mut self) {
+        T::a();
+    }
+}
+
+const fn check<T: ~const Drop>(_: T) {}
+
+macro_rules! check_all {
+    ($($exp:expr),*$(,)?) => {$(
+        const _: () = check($exp);
+    )*};
+}
+
+check_all! {
+    NonTrivialDrop,
+    //~^ ERROR the trait bound
+    ConstImplWithDropGlue(NonTrivialDrop),
+    //~^ ERROR the trait bound
+    ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+    //~^ ERROR the trait bound
+    //~| ERROR the trait bound
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
new file mode 100644
index 00000000000..34cd1d2b107
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
@@ -0,0 +1,68 @@
+error: `~const` is not allowed here
+  --> $DIR/const-drop-fail.rs:27:35
+   |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+   |                                   ^^^^^^^^
+   |
+   = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+
+error[E0277]: the trait bound `NonTrivialDrop: Drop` is not satisfied
+  --> $DIR/const-drop-fail.rs:45:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     NonTrivialDrop,
+   |     ^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `NonTrivialDrop`
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:36:19
+   |
+LL | const fn check<T: ~const Drop>(_: T) {}
+   |                   ^^^^^^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `ConstImplWithDropGlue: Drop` is not satisfied
+  --> $DIR/const-drop-fail.rs:47:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     ConstImplWithDropGlue(NonTrivialDrop),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Drop` is not implemented for `ConstImplWithDropGlue`
+   |
+note: required by a bound in `check`
+  --> $DIR/const-drop-fail.rs:36:19
+   |
+LL | const fn check<T: ~const Drop>(_: T) {}
+   |                   ^^^^^^^^^^^ required by this bound in `check`
+
+error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied
+  --> $DIR/const-drop-fail.rs:49:5
+   |
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop`
+   |
+note: required by `ConstDropImplWithBounds`
+  --> $DIR/const-drop-fail.rs:27:1
+   |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the trait bound `NonTrivialDrop: A` is not satisfied
+  --> $DIR/const-drop-fail.rs:49:5
+   |
+LL |         const _: () = check($exp);
+   |                       ----- required by a bound introduced by this call
+...
+LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `A` is not implemented for `NonTrivialDrop`
+   |
+note: required by a bound in `ConstDropImplWithBounds`
+  --> $DIR/const-drop-fail.rs:27:35
+   |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+   |                                   ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs
new file mode 100644
index 00000000000..9a1b554f45f
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs
@@ -0,0 +1,81 @@
+// run-pass
+// revisions: stock precise
+#![feature(const_trait_impl)]
+#![feature(const_fn_trait_bound)]
+#![feature(const_mut_refs)]
+#![feature(const_panic)]
+#![cfg_attr(precise, feature(const_precise_live_drops))]
+
+struct S<'a>(&'a mut u8);
+
+impl<'a> const Drop for S<'a> {
+    fn drop(&mut self) {
+        *self.0 += 1;
+    }
+}
+
+const fn a<T: ~const Drop>(_: T) {}
+
+const fn b() -> u8 {
+    let mut c = 0;
+    let _ = S(&mut c);
+    a(S(&mut c));
+    c
+}
+
+const C: u8 = b();
+
+macro_rules! implements_const_drop {
+    ($($exp:expr),*$(,)?) => {
+        $(
+            const _: () = a($exp);
+        )*
+    }
+}
+
+#[allow(dead_code)]
+mod t {
+    pub struct Foo;
+    pub enum Bar { A }
+    pub fn foo() {}
+    pub struct ConstDrop;
+
+    impl const Drop for ConstDrop {
+        fn drop(&mut self) {}
+    }
+
+    pub struct HasConstDrop(pub ConstDrop);
+    pub struct TrivialFields(pub u8, pub i8, pub usize, pub isize);
+}
+
+use t::*;
+
+implements_const_drop! {
+    1u8,
+    2,
+    3.0,
+    Foo,
+    Bar::A,
+    foo,
+    ConstDrop,
+    HasConstDrop(ConstDrop),
+    TrivialFields(1, 2, 3, 4),
+    &1,
+    &1 as *const i32,
+}
+
+fn main() {
+    struct HasDropGlue(Box<u8>);
+    struct HasDropImpl;
+    impl Drop for HasDropImpl {
+        fn drop(&mut self) {
+            println!("not trivial drop");
+        }
+    }
+
+    // These types should pass because ~const in a non-const context should have no effect.
+    a(HasDropGlue(Box::new(0)));
+    a(HasDropImpl);
+
+    assert_eq!(C, 2);
+}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs
new file mode 100644
index 00000000000..fe1015b3bf7
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs
@@ -0,0 +1,21 @@
+// check-pass
+#![feature(const_trait_impl)]
+#![feature(const_fn_trait_bound)]
+
+struct S;
+
+trait A {}
+trait B {}
+
+impl const A for S {}
+impl const B for S {}
+
+impl S {
+    const fn a<T: ~const A>() where T: ~const B {
+
+    }
+}
+
+const _: () = S::a::<S>();
+
+fn main() {}
diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr
index 81c0c4a7875..ea22d1c89b1 100644
--- a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr
+++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr
@@ -2,7 +2,9 @@ error[E0277]: expected a `Fn<()>` closure, found `fn() {foo}`
   --> $DIR/fn-traits.rs:24:10
    |
 LL |     call(foo);
-   |          ^^^ expected an `Fn<()>` closure, found `fn() {foo}`
+   |     ---- ^^^ expected an `Fn<()>` closure, found `fn() {foo}`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Fn<()>` is not implemented for `fn() {foo}`
    = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
@@ -17,7 +19,9 @@ error[E0277]: expected a `FnMut<()>` closure, found `fn() {foo}`
   --> $DIR/fn-traits.rs:25:14
    |
 LL |     call_mut(foo);
-   |              ^^^ expected an `FnMut<()>` closure, found `fn() {foo}`
+   |     -------- ^^^ expected an `FnMut<()>` closure, found `fn() {foo}`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `FnMut<()>` is not implemented for `fn() {foo}`
    = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
@@ -32,7 +36,9 @@ error[E0277]: expected a `FnOnce<()>` closure, found `fn() {foo}`
   --> $DIR/fn-traits.rs:26:15
    |
 LL |     call_once(foo);
-   |               ^^^ expected an `FnOnce<()>` closure, found `fn() {foo}`
+   |     --------- ^^^ expected an `FnOnce<()>` closure, found `fn() {foo}`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `FnOnce<()>` is not implemented for `fn() {foo}`
    = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
@@ -47,7 +53,9 @@ error[E0277]: expected a `Fn<()>` closure, found `unsafe fn() {foo_unsafe}`
   --> $DIR/fn-traits.rs:28:10
    |
 LL |     call(foo_unsafe);
-   |          ^^^^^^^^^^ expected an `Fn<()>` closure, found `unsafe fn() {foo_unsafe}`
+   |     ---- ^^^^^^^^^^ expected an `Fn<()>` closure, found `unsafe fn() {foo_unsafe}`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Fn<()>` is not implemented for `unsafe fn() {foo_unsafe}`
    = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
@@ -62,7 +70,9 @@ error[E0277]: expected a `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}`
   --> $DIR/fn-traits.rs:30:14
    |
 LL |     call_mut(foo_unsafe);
-   |              ^^^^^^^^^^ expected an `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}`
+   |     -------- ^^^^^^^^^^ expected an `FnMut<()>` closure, found `unsafe fn() {foo_unsafe}`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `FnMut<()>` is not implemented for `unsafe fn() {foo_unsafe}`
    = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
@@ -77,7 +87,9 @@ error[E0277]: expected a `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}`
   --> $DIR/fn-traits.rs:32:15
    |
 LL |     call_once(foo_unsafe);
-   |               ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}`
+   |     --------- ^^^^^^^^^^ expected an `FnOnce<()>` closure, found `unsafe fn() {foo_unsafe}`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {foo_unsafe}`
    = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
diff --git a/src/test/ui/self/ufcs-explicit-self.rs b/src/test/ui/self/ufcs-explicit-self.rs
index 4e2405504f0..0aaaa7d47c3 100644
--- a/src/test/ui/self/ufcs-explicit-self.rs
+++ b/src/test/ui/self/ufcs-explicit-self.rs
@@ -1,5 +1,6 @@
 // run-pass
 #![feature(box_syntax)]
+#![allow(dead_code)]
 
 #[derive(Copy, Clone)]
 struct Foo {
diff --git a/src/test/ui/shift-various-bad-types.stderr b/src/test/ui/shift-various-bad-types.stderr
index 7c16581686a..932a435143b 100644
--- a/src/test/ui/shift-various-bad-types.stderr
+++ b/src/test/ui/shift-various-bad-types.stderr
@@ -33,7 +33,7 @@ LL |     let _: i32 = 22_i64 >> 1_i32;
 help: you can convert an `i64` to an `i32` and panic if the converted value doesn't fit
    |
 LL |     let _: i32 = (22_i64 >> 1_i32).try_into().unwrap();
-   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |                  +               +++++++++++++++++++++
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr
index da0a3c8b476..8d26ca4ac7a 100644
--- a/src/test/ui/span/issue-34264.stderr
+++ b/src/test/ui/span/issue-34264.stderr
@@ -8,11 +8,11 @@ LL | fn foo(Option<i32>, String) {}
 help: if this is a `self` type, give it a parameter name
    |
 LL | fn foo(self: Option<i32>, String) {}
-   |        ~~~~~~~~~~~~
+   |        +++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL | fn foo(_: Option<i32>, String) {}
-   |        ~~~~~~~~~
+   |        ++
 
 error: expected one of `:`, `@`, or `|`, found `)`
   --> $DIR/issue-34264.rs:1:27
@@ -24,11 +24,11 @@ LL | fn foo(Option<i32>, String) {}
 help: if this is a parameter name, give it a type
    |
 LL | fn foo(Option<i32>, String: TypeName) {}
-   |                     ~~~~~~~~~~~~~~~~
+   |                           ++++++++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL | fn foo(Option<i32>, _: String) {}
-   |                     ~~~~~~~~~
+   |                     ++
 
 error: expected one of `:`, `@`, or `|`, found `,`
   --> $DIR/issue-34264.rs:3:9
@@ -40,15 +40,15 @@ LL | fn bar(x, y: usize) {}
 help: if this is a `self` type, give it a parameter name
    |
 LL | fn bar(self: x, y: usize) {}
-   |        ~~~~~~~
+   |        +++++
 help: if this is a parameter name, give it a type
    |
 LL | fn bar(x: TypeName, y: usize) {}
-   |        ~~~~~~~~~~~
+   |         ++++++++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL | fn bar(_: x, y: usize) {}
-   |        ~~~~
+   |        ++
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
   --> $DIR/issue-34264.rs:7:5
diff --git a/src/test/ui/str/str-idx.stderr b/src/test/ui/str/str-idx.stderr
index f323ba03c01..47bd6f6bfa7 100644
--- a/src/test/ui/str/str-idx.stderr
+++ b/src/test/ui/str/str-idx.stderr
@@ -13,7 +13,9 @@ error[E0277]: the type `str` cannot be indexed by `{integer}`
   --> $DIR/str-idx.rs:4:19
    |
 LL |     let _ = s.get(4);
-   |                   ^ string indices are ranges of `usize`
+   |               --- ^ string indices are ranges of `usize`
+   |               |
+   |               required by a bound introduced by this call
    |
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
@@ -23,7 +25,9 @@ error[E0277]: the type `str` cannot be indexed by `{integer}`
   --> $DIR/str-idx.rs:5:29
    |
 LL |     let _ = s.get_unchecked(4);
-   |                             ^ string indices are ranges of `usize`
+   |               ------------- ^ string indices are ranges of `usize`
+   |               |
+   |               required by a bound introduced by this call
    |
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr
index 3e49c8394ab..ab647c75cf1 100644
--- a/src/test/ui/str/str-mut-idx.stderr
+++ b/src/test/ui/str/str-mut-idx.stderr
@@ -37,7 +37,9 @@ error[E0277]: the type `str` cannot be indexed by `{integer}`
   --> $DIR/str-mut-idx.rs:9:15
    |
 LL |     s.get_mut(1);
-   |               ^ string indices are ranges of `usize`
+   |       ------- ^ string indices are ranges of `usize`
+   |       |
+   |       required by a bound introduced by this call
    |
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
@@ -47,7 +49,9 @@ error[E0277]: the type `str` cannot be indexed by `{integer}`
   --> $DIR/str-mut-idx.rs:11:25
    |
 LL |     s.get_unchecked_mut(1);
-   |                         ^ string indices are ranges of `usize`
+   |       ----------------- ^ string indices are ranges of `usize`
+   |       |
+   |       required by a bound introduced by this call
    |
    = help: the trait `SliceIndex<str>` is not implemented for `{integer}`
    = note: you can use `.chars().nth()` or `.bytes().nth()`
diff --git a/src/test/ui/structs-enums/class-cast-to-trait-multiple-types.rs b/src/test/ui/structs-enums/class-cast-to-trait-multiple-types.rs
index 55975cbdb53..ca35a615d21 100644
--- a/src/test/ui/structs-enums/class-cast-to-trait-multiple-types.rs
+++ b/src/test/ui/structs-enums/class-cast-to-trait-multiple-types.rs
@@ -1,5 +1,6 @@
 // run-pass
 #![allow(non_camel_case_types)]
+#![allow(dead_code)]
 
 trait noisy {
   fn speak(&mut self) -> isize;
diff --git a/src/test/ui/structs-enums/class-implement-traits.rs b/src/test/ui/structs-enums/class-implement-traits.rs
index c9e98e21b9e..732aa146ce4 100644
--- a/src/test/ui/structs-enums/class-implement-traits.rs
+++ b/src/test/ui/structs-enums/class-implement-traits.rs
@@ -1,5 +1,6 @@
 // run-pass
 #![allow(non_camel_case_types)]
+#![allow(dead_code)]
 
 trait noisy {
     fn speak(&mut self);
diff --git a/src/test/ui/structs-enums/functional-struct-upd.rs b/src/test/ui/structs-enums/functional-struct-upd.rs
index 51c6b6d7e4f..68ff73a0805 100644
--- a/src/test/ui/structs-enums/functional-struct-upd.rs
+++ b/src/test/ui/structs-enums/functional-struct-upd.rs
@@ -1,4 +1,7 @@
 // run-pass
+
+#![allow(dead_code)]
+
 #[derive(Debug)]
 struct Foo {
     x: isize,
diff --git a/src/test/ui/structs-enums/tag-align-shape.rs b/src/test/ui/structs-enums/tag-align-shape.rs
index 87282ddbcca..ce599582378 100644
--- a/src/test/ui/structs-enums/tag-align-shape.rs
+++ b/src/test/ui/structs-enums/tag-align-shape.rs
@@ -1,5 +1,6 @@
 // run-pass
 #![allow(non_camel_case_types)]
+#![allow(dead_code)]
 
 #[derive(Debug)]
 enum a_tag {
diff --git a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
index 300c2a66c29..78ebb3d6bfc 100644
--- a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
+++ b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
@@ -5,7 +5,9 @@ LL | async fn foo() {}
    |          --- consider calling this function
 ...
 LL |     bar(foo);
-   |         ^^^ `fn() -> impl Future {foo}` is not a future
+   |     --- ^^^ `fn() -> impl Future {foo}` is not a future
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Future` is not implemented for `fn() -> impl Future {foo}`
 note: required by a bound in `bar`
@@ -24,7 +26,9 @@ error[E0277]: `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-be
 LL |     let async_closure = async || ();
    |                         -------- consider calling this closure
 LL |     bar(async_closure);
-   |         ^^^^^^^^^^^^^ `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]` is not a future
+   |     --- ^^^^^^^^^^^^^ `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]` is not a future
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Future` is not implemented for `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:36]`
 note: required by a bound in `bar`
diff --git a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
index 93048107e59..b111df49f6e 100644
--- a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
+++ b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
@@ -5,7 +5,9 @@ LL | fn foo() -> impl T<O=()> { S }
    |    --- consider calling this function
 ...
 LL |     bar(foo);
-   |         ^^^ the trait `T` is not implemented for `fn() -> impl T {foo}`
+   |     --- ^^^ the trait `T` is not implemented for `fn() -> impl T {foo}`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `bar`
   --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:14:16
@@ -23,7 +25,9 @@ error[E0277]: the trait bound `[closure@$DIR/fn-ctor-passed-as-arg-where-it-shou
 LL |     let closure = || S;
    |                   -- consider calling this closure
 LL |     bar(closure);
-   |         ^^^^^^^ the trait `T` is not implemented for `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:23]`
+   |     --- ^^^^^^^ the trait `T` is not implemented for `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:23]`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `bar`
   --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:14:16
diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr
index 39bde52c55a..71779ecb729 100644
--- a/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr
+++ b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `&S: Trait` is not satisfied
   --> $DIR/imm-ref-trait-object-literal.rs:12:7
    |
 LL |   foo(&s);
-   |       ^^ the trait `Trait` is not implemented for `&S`
+   |   --- ^^ the trait `Trait` is not implemented for `&S`
+   |   |
+   |   required by a bound introduced by this call
    |
    = help: the following implementations were found:
              <&'a mut S as Trait>
@@ -20,10 +22,11 @@ error[E0277]: the trait bound `S: Trait` is not satisfied
   --> $DIR/imm-ref-trait-object-literal.rs:13:7
    |
 LL |   foo(s);
-   |       ^
-   |       |
-   |       expected an implementor of trait `Trait`
-   |       help: consider mutably borrowing here: `&mut s`
+   |   --- ^
+   |   |   |
+   |   |   expected an implementor of trait `Trait`
+   |   |   help: consider mutably borrowing here: `&mut s`
+   |   required by a bound introduced by this call
    |
 note: required by a bound in `foo`
   --> $DIR/imm-ref-trait-object-literal.rs:7:11
diff --git a/src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr b/src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr
index bb7919ebb79..229c4b824f2 100644
--- a/src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr
+++ b/src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr
@@ -2,7 +2,9 @@ error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
   --> $DIR/impl-trait-with-missing-bounds.rs:14:13
    |
 LL |         qux(constraint);
-   |             ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         |
+   |         required by a bound introduced by this call
    |
    = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
 note: required by a bound in `qux`
@@ -19,7 +21,9 @@ error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
   --> $DIR/impl-trait-with-missing-bounds.rs:22:13
    |
 LL |         qux(constraint);
-   |             ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         |
+   |         required by a bound introduced by this call
    |
    = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
 note: required by a bound in `qux`
@@ -36,7 +40,9 @@ error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
   --> $DIR/impl-trait-with-missing-bounds.rs:30:13
    |
 LL |         qux(constraint);
-   |             ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         |
+   |         required by a bound introduced by this call
    |
    = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
 note: required by a bound in `qux`
@@ -53,7 +59,9 @@ error[E0277]: `<impl Iterator + std::fmt::Debug as Iterator>::Item` doesn't impl
   --> $DIR/impl-trait-with-missing-bounds.rs:37:13
    |
 LL |         qux(constraint);
-   |             ^^^^^^^^^^ `<impl Iterator + std::fmt::Debug as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         --- ^^^^^^^^^^ `<impl Iterator + std::fmt::Debug as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         |
+   |         required by a bound introduced by this call
    |
    = help: the trait `Debug` is not implemented for `<impl Iterator + std::fmt::Debug as Iterator>::Item`
 note: required by a bound in `qux`
@@ -70,7 +78,9 @@ error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
   --> $DIR/impl-trait-with-missing-bounds.rs:6:13
    |
 LL |         qux(constraint);
-   |             ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         |
+   |         required by a bound introduced by this call
    |
    = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
 note: required by a bound in `qux`
@@ -87,7 +97,9 @@ error[E0277]: `<impl Iterator as Iterator>::Item` doesn't implement `Debug`
   --> $DIR/impl-trait-with-missing-bounds.rs:45:13
    |
 LL |         qux(constraint);
-   |             ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         --- ^^^^^^^^^^ `<impl Iterator as Iterator>::Item` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |         |
+   |         required by a bound introduced by this call
    |
    = help: the trait `Debug` is not implemented for `<impl Iterator as Iterator>::Item`
 note: required by a bound in `qux`
diff --git a/src/test/ui/suggestions/issue-62843.stderr b/src/test/ui/suggestions/issue-62843.stderr
index b2be09a4c7f..93251b2c8db 100644
--- a/src/test/ui/suggestions/issue-62843.stderr
+++ b/src/test/ui/suggestions/issue-62843.stderr
@@ -2,10 +2,11 @@ error[E0277]: expected a `FnMut<(char,)>` closure, found `String`
   --> $DIR/issue-62843.rs:4:32
    |
 LL |     println!("{:?}", line.find(pattern));
-   |                                ^^^^^^^
-   |                                |
-   |                                expected an implementor of trait `Pattern<'_>`
-   |                                help: consider borrowing here: `&pattern`
+   |                           ---- ^^^^^^^
+   |                           |    |
+   |                           |    expected an implementor of trait `Pattern<'_>`
+   |                           |    help: consider borrowing here: `&pattern`
+   |                           required by a bound introduced by this call
    |
    = note: the trait bound `String: Pattern<'_>` is not satisfied
    = note: required because of the requirements on the impl of `Pattern<'_>` for `String`
diff --git a/src/test/ui/suggestions/issue-64252-self-type.stderr b/src/test/ui/suggestions/issue-64252-self-type.stderr
index 009707a3a64..c3418dab0e8 100644
--- a/src/test/ui/suggestions/issue-64252-self-type.stderr
+++ b/src/test/ui/suggestions/issue-64252-self-type.stderr
@@ -8,11 +8,11 @@ LL | pub fn foo(Box<Self>) { }
 help: if this is a `self` type, give it a parameter name
    |
 LL | pub fn foo(self: Box<Self>) { }
-   |            ~~~~~~~~~
+   |            +++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL | pub fn foo(_: Box<Self>) { }
-   |            ~~~~~~
+   |            ++
 
 error: expected one of `:`, `@`, or `|`, found `<`
   --> $DIR/issue-64252-self-type.rs:10:15
@@ -24,11 +24,11 @@ LL |     fn bar(Box<Self>) { }
 help: if this is a `self` type, give it a parameter name
    |
 LL |     fn bar(self: Box<Self>) { }
-   |            ~~~~~~~~~
+   |            +++++
 help: if this is a type, explicitly ignore the parameter name
    |
 LL |     fn bar(_: Box<Self>) { }
-   |            ~~~~~~
+   |            ++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr b/src/test/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr
index cd1a8c4be8e..a3ab0b8efb0 100644
--- a/src/test/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr
+++ b/src/test/ui/suggestions/issue-79843-impl-trait-with-missing-bounds-on-async-fn.stderr
@@ -2,7 +2,9 @@ error[E0277]: `<impl Foo as Foo>::Bar` cannot be sent between threads safely
   --> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:14:20
    |
 LL |     assert_is_send(&bar);
-   |                    ^^^^ `<impl Foo as Foo>::Bar` cannot be sent between threads safely
+   |     -------------- ^^^^ `<impl Foo as Foo>::Bar` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Send` is not implemented for `<impl Foo as Foo>::Bar`
 note: required by a bound in `assert_is_send`
@@ -19,7 +21,9 @@ error[E0277]: `<impl Foo as Foo>::Bar` cannot be sent between threads safely
   --> $DIR/issue-79843-impl-trait-with-missing-bounds-on-async-fn.rs:24:20
    |
 LL |     assert_is_send(&bar);
-   |                    ^^^^ `<impl Foo as Foo>::Bar` cannot be sent between threads safely
+   |     -------------- ^^^^ `<impl Foo as Foo>::Bar` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Send` is not implemented for `<impl Foo as Foo>::Bar`
 note: required by a bound in `assert_is_send`
diff --git a/src/test/ui/suggestions/issue-84973-2.stderr b/src/test/ui/suggestions/issue-84973-2.stderr
index df1eeb7a2b8..c1a7a2e101d 100644
--- a/src/test/ui/suggestions/issue-84973-2.stderr
+++ b/src/test/ui/suggestions/issue-84973-2.stderr
@@ -2,10 +2,11 @@ error[E0277]: the trait bound `i32: Tr` is not satisfied
   --> $DIR/issue-84973-2.rs:11:9
    |
 LL |     foo(a);
-   |         ^
-   |         |
-   |         expected an implementor of trait `Tr`
-   |         help: consider mutably borrowing here: `&mut a`
+   |     --- ^
+   |     |   |
+   |     |   expected an implementor of trait `Tr`
+   |     |   help: consider mutably borrowing here: `&mut a`
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `foo`
   --> $DIR/issue-84973-2.rs:7:11
diff --git a/src/test/ui/suggestions/issue-84973-blacklist.rs b/src/test/ui/suggestions/issue-84973-blacklist.rs
index db954530b1b..6813b07a2ee 100644
--- a/src/test/ui/suggestions/issue-84973-blacklist.rs
+++ b/src/test/ui/suggestions/issue-84973-blacklist.rs
@@ -21,7 +21,6 @@ fn main() {
     let ref_cl: &dyn Fn() -> () = &cl;
     f_sized(*ref_cl);
     //~^ ERROR: the size for values of type `dyn Fn()` cannot be known at compilation time [E0277]
-    //~| ERROR: the size for values of type `dyn Fn()` cannot be known at compilation time [E0277]
 
     use std::rc::Rc;
     let rc = Rc::new(0);
diff --git a/src/test/ui/suggestions/issue-84973-blacklist.stderr b/src/test/ui/suggestions/issue-84973-blacklist.stderr
index 2ffe2f5a2b6..ae55c96702a 100644
--- a/src/test/ui/suggestions/issue-84973-blacklist.stderr
+++ b/src/test/ui/suggestions/issue-84973-blacklist.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
   --> $DIR/issue-84973-blacklist.rs:15:12
    |
 LL |     f_copy("".to_string());
-   |            ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+   |     ------ ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `f_copy`
   --> $DIR/issue-84973-blacklist.rs:6:14
@@ -14,7 +16,9 @@ error[E0277]: the trait bound `S: Clone` is not satisfied
   --> $DIR/issue-84973-blacklist.rs:16:13
    |
 LL |     f_clone(S);
-   |             ^ the trait `Clone` is not implemented for `S`
+   |     ------- ^ the trait `Clone` is not implemented for `S`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `f_clone`
   --> $DIR/issue-84973-blacklist.rs:7:15
@@ -39,7 +43,9 @@ error[E0277]: the size for values of type `dyn Fn()` cannot be known at compilat
   --> $DIR/issue-84973-blacklist.rs:22:13
    |
 LL |     f_sized(*ref_cl);
-   |             ^^^^^^^ doesn't have a size known at compile-time
+   |     ------- ^^^^^^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sized` is not implemented for `dyn Fn()`
 note: required by a bound in `f_sized`
@@ -49,10 +55,12 @@ LL | fn f_sized<T: Sized>(t: T) {}
    |            ^ required by this bound in `f_sized`
 
 error[E0277]: `Rc<{integer}>` cannot be sent between threads safely
-  --> $DIR/issue-84973-blacklist.rs:28:12
+  --> $DIR/issue-84973-blacklist.rs:27:12
    |
 LL |     f_send(rc);
-   |            ^^ `Rc<{integer}>` cannot be sent between threads safely
+   |     ------ ^^ `Rc<{integer}>` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Send` is not implemented for `Rc<{integer}>`
 note: required by a bound in `f_send`
@@ -61,16 +69,6 @@ note: required by a bound in `f_send`
 LL | fn f_send<T: Send>(t: T) {}
    |              ^^^^ required by this bound in `f_send`
 
-error[E0277]: the size for values of type `dyn Fn()` cannot be known at compilation time
-  --> $DIR/issue-84973-blacklist.rs:22:5
-   |
-LL |     f_sized(*ref_cl);
-   |     ^^^^^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `dyn Fn()`
-   = note: all function arguments must have a statically known size
-   = help: unsized fn params are gated as an unstable feature
-
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/issue-84973-negative.stderr b/src/test/ui/suggestions/issue-84973-negative.stderr
index bd1cf6ba614..14b32d8515c 100644
--- a/src/test/ui/suggestions/issue-84973-negative.stderr
+++ b/src/test/ui/suggestions/issue-84973-negative.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `i32: Tr` is not satisfied
   --> $DIR/issue-84973-negative.rs:10:9
    |
 LL |     bar(a);
-   |         ^ the trait `Tr` is not implemented for `i32`
+   |     --- ^ the trait `Tr` is not implemented for `i32`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `bar`
   --> $DIR/issue-84973-negative.rs:5:11
@@ -14,10 +16,11 @@ error[E0277]: the trait bound `f32: Tr` is not satisfied
   --> $DIR/issue-84973-negative.rs:11:9
    |
 LL |     bar(b);
-   |         ^
-   |         |
-   |         expected an implementor of trait `Tr`
-   |         help: consider borrowing here: `&b`
+   |     --- ^
+   |     |   |
+   |     |   expected an implementor of trait `Tr`
+   |     |   help: consider borrowing here: `&b`
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `bar`
   --> $DIR/issue-84973-negative.rs:5:11
diff --git a/src/test/ui/suggestions/issue-84973.stderr b/src/test/ui/suggestions/issue-84973.stderr
index 649517b7d99..169d0cccb43 100644
--- a/src/test/ui/suggestions/issue-84973.stderr
+++ b/src/test/ui/suggestions/issue-84973.stderr
@@ -2,10 +2,11 @@ error[E0277]: the trait bound `Fancy: SomeTrait` is not satisfied
   --> $DIR/issue-84973.rs:6:24
    |
 LL |     let o = Other::new(f);
-   |                        ^
-   |                        |
-   |                        expected an implementor of trait `SomeTrait`
-   |                        help: consider borrowing here: `&f`
+   |             ---------- ^
+   |             |          |
+   |             |          expected an implementor of trait `SomeTrait`
+   |             |          help: consider borrowing here: `&f`
+   |             required by a bound introduced by this call
    |
 note: required by `Other::<'a, G>::new`
   --> $DIR/issue-84973.rs:27:5
diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
index 3b71d5cee93..e6a22313900 100644
--- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
+++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satis
   --> $DIR/mut-borrow-needed-by-trait.rs:17:29
    |
 LL |     let fp = BufWriter::new(fp);
-   |                             ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write`
+   |              -------------- ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write`
+   |              |
+   |              required by a bound introduced by this call
    |
    = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write`
 note: required by `BufWriter::<W>::new`
diff --git a/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr b/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr
index f332b7213d8..54f19fe9da4 100644
--- a/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr
+++ b/src/test/ui/suggestions/object-unsafe-trait-references-self.stderr
@@ -4,8 +4,6 @@ error[E0038]: the trait `Trait` cannot be made into an object
 LL | fn bar(x: &dyn Trait) {}
    |            ^^^^^^^^^ `Trait` cannot be made into an object
    |
-   = help: consider moving `baz` to another trait
-   = help: consider moving `bat` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/object-unsafe-trait-references-self.rs:2:22
    |
@@ -15,6 +13,8 @@ LL |     fn baz(&self, _: Self) {}
    |                      ^^^^ ...because method `baz` references the `Self` type in this parameter
 LL |     fn bat(&self) -> Self {}
    |                      ^^^^ ...because method `bat` references the `Self` type in its return type
+   = help: consider moving `baz` to another trait
+   = help: consider moving `bat` to another trait
 
 error[E0038]: the trait `Other` cannot be made into an object
   --> $DIR/object-unsafe-trait-references-self.rs:10:12
diff --git a/src/test/ui/suggestions/restrict-type-argument.stderr b/src/test/ui/suggestions/restrict-type-argument.stderr
index b62502fb6a2..551a7c5060f 100644
--- a/src/test/ui/suggestions/restrict-type-argument.stderr
+++ b/src/test/ui/suggestions/restrict-type-argument.stderr
@@ -2,7 +2,9 @@ error[E0277]: `impl Sync` cannot be sent between threads safely
   --> $DIR/restrict-type-argument.rs:4:13
    |
 LL |     is_send(val);
-   |             ^^^ `impl Sync` cannot be sent between threads safely
+   |     ------- ^^^ `impl Sync` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `is_send`
   --> $DIR/restrict-type-argument.rs:1:15
@@ -18,7 +20,9 @@ error[E0277]: `S` cannot be sent between threads safely
   --> $DIR/restrict-type-argument.rs:8:13
    |
 LL |     is_send(val);
-   |             ^^^ `S` cannot be sent between threads safely
+   |     ------- ^^^ `S` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `is_send`
   --> $DIR/restrict-type-argument.rs:1:15
@@ -34,7 +38,9 @@ error[E0277]: `S` cannot be sent between threads safely
   --> $DIR/restrict-type-argument.rs:12:13
    |
 LL |     is_send(val);
-   |             ^^^ `S` cannot be sent between threads safely
+   |     ------- ^^^ `S` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `is_send`
   --> $DIR/restrict-type-argument.rs:1:15
@@ -50,7 +56,9 @@ error[E0277]: `S` cannot be sent between threads safely
   --> $DIR/restrict-type-argument.rs:20:13
    |
 LL |     is_send(val);
-   |             ^^^ `S` cannot be sent between threads safely
+   |     ------- ^^^ `S` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `is_send`
   --> $DIR/restrict-type-argument.rs:1:15
@@ -66,7 +74,9 @@ error[E0277]: `S` cannot be sent between threads safely
   --> $DIR/restrict-type-argument.rs:24:13
    |
 LL |     is_send(val);
-   |             ^^^ `S` cannot be sent between threads safely
+   |     ------- ^^^ `S` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `is_send`
   --> $DIR/restrict-type-argument.rs:1:15
@@ -82,7 +92,9 @@ error[E0277]: `S` cannot be sent between threads safely
   --> $DIR/restrict-type-argument.rs:28:13
    |
 LL |     is_send(val);
-   |             ^^^ `S` cannot be sent between threads safely
+   |     ------- ^^^ `S` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `is_send`
   --> $DIR/restrict-type-argument.rs:1:15
diff --git a/src/test/ui/suggestions/slice-issue-87994.rs b/src/test/ui/suggestions/slice-issue-87994.rs
new file mode 100644
index 00000000000..ecb7f54ea25
--- /dev/null
+++ b/src/test/ui/suggestions/slice-issue-87994.rs
@@ -0,0 +1,16 @@
+fn main() {
+  let v = vec![1i32, 2, 3];
+  for _ in v[1..] {
+    //~^ ERROR [i32]` is not an iterator [E0277]
+    //~^^ ERROR known at compilation time
+  }
+  struct K {
+    n: i32,
+  }
+  let mut v2 = vec![K { n: 1 }, K { n: 1 }, K { n: 1 }];
+  for i2 in v2[1..] {
+    //~^ ERROR [K]` is not an iterator [E0277]
+    //~^^ ERROR known at compilation time
+    i2.n = 2;
+  }
+}
diff --git a/src/test/ui/suggestions/slice-issue-87994.stderr b/src/test/ui/suggestions/slice-issue-87994.stderr
new file mode 100644
index 00000000000..018f62e783d
--- /dev/null
+++ b/src/test/ui/suggestions/slice-issue-87994.stderr
@@ -0,0 +1,71 @@
+error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
+  --> $DIR/slice-issue-87994.rs:3:12
+   |
+LL |   for _ in v[1..] {
+   |            ^^^^^^
+   |            |
+   |            expected an implementor of trait `IntoIterator`
+   |            help: consider borrowing here: `&v[1..]`
+   |
+   = note: the trait bound `[i32]: IntoIterator` is not satisfied
+   = note: required because of the requirements on the impl of `IntoIterator` for `[i32]`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `[i32]` is not an iterator
+  --> $DIR/slice-issue-87994.rs:3:12
+   |
+LL |   for _ in v[1..] {
+   |            ^^^^^^
+   |            |
+   |            expected an implementor of trait `IntoIterator`
+   |            help: consider borrowing here: `&v[1..]`
+   |
+   = note: the trait bound `[i32]: IntoIterator` is not satisfied
+   = note: required because of the requirements on the impl of `IntoIterator` for `[i32]`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: the size for values of type `[K]` cannot be known at compilation time
+  --> $DIR/slice-issue-87994.rs:11:13
+   |
+LL |   for i2 in v2[1..] {
+   |             ^^^^^^^
+   |             |
+   |             expected an implementor of trait `IntoIterator`
+   |             help: consider borrowing here: `&v2[1..]`
+   |
+   = note: the trait bound `[K]: IntoIterator` is not satisfied
+   = note: required because of the requirements on the impl of `IntoIterator` for `[K]`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `[K]` is not an iterator
+  --> $DIR/slice-issue-87994.rs:11:13
+   |
+LL |   for i2 in v2[1..] {
+   |             ^^^^^^^
+   |             |
+   |             expected an implementor of trait `IntoIterator`
+   |             help: consider borrowing here: `&v2[1..]`
+   |
+   = note: the trait bound `[K]: IntoIterator` is not satisfied
+   = note: required because of the requirements on the impl of `IntoIterator` for `[K]`
+note: required by `into_iter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+   |
+LL |     fn into_iter(self) -> Self::IntoIter;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/suggest-change-mut.stderr b/src/test/ui/suggestions/suggest-change-mut.stderr
index 1f14ebae841..8dfab8dfa17 100644
--- a/src/test/ui/suggestions/suggest-change-mut.stderr
+++ b/src/test/ui/suggestions/suggest-change-mut.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `&T: std::io::Read` is not satisfied
   --> $DIR/suggest-change-mut.rs:12:48
    |
 LL |         let mut stream_reader = BufReader::new(&stream);
-   |                                                ^^^^^^^ the trait `std::io::Read` is not implemented for `&T`
+   |                                 -------------- ^^^^^^^ the trait `std::io::Read` is not implemented for `&T`
+   |                                 |
+   |                                 required by a bound introduced by this call
    |
 note: required by `BufReader::<R>::new`
   --> $SRC_DIR/std/src/io/buffered/bufreader.rs:LL:COL
diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr
index b391cd4beb4..12466868f00 100644
--- a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr
+++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr
@@ -2,19 +2,23 @@ error[E0308]: mismatched types
   --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:19
    |
 LL |     let _ = RGB { r, g, c };
-   |                   ^
-   |                   |
-   |                   expected `f64`, found `f32`
-   |                   help: you can convert an `f32` to an `f64`: `r: r.into()`
+   |                   ^ expected `f64`, found `f32`
+   |
+help: you can convert an `f32` to an `f64`
+   |
+LL |     let _ = RGB { r: r.into(), g, c };
+   |                   ++  +++++++
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:22
    |
 LL |     let _ = RGB { r, g, c };
-   |                      ^
-   |                      |
-   |                      expected `f64`, found `f32`
-   |                      help: you can convert an `f32` to an `f64`: `g: g.into()`
+   |                      ^ expected `f64`, found `f32`
+   |
+help: you can convert an `f32` to an `f64`
+   |
+LL |     let _ = RGB { r, g: g.into(), c };
+   |                      ++  +++++++
 
 error[E0560]: struct `RGB` has no field named `c`
   --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:25
diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr
index 61ea852a8c4..72c84d16716 100644
--- a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr
+++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr
@@ -2,28 +2,34 @@ error[E0308]: mismatched types
   --> $DIR/type-mismatch-struct-field-shorthand.rs:8:19
    |
 LL |     let _ = RGB { r, g, b };
-   |                   ^
-   |                   |
-   |                   expected `f64`, found `f32`
-   |                   help: you can convert an `f32` to an `f64`: `r: r.into()`
+   |                   ^ expected `f64`, found `f32`
+   |
+help: you can convert an `f32` to an `f64`
+   |
+LL |     let _ = RGB { r: r.into(), g, b };
+   |                   ++  +++++++
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch-struct-field-shorthand.rs:8:22
    |
 LL |     let _ = RGB { r, g, b };
-   |                      ^
-   |                      |
-   |                      expected `f64`, found `f32`
-   |                      help: you can convert an `f32` to an `f64`: `g: g.into()`
+   |                      ^ expected `f64`, found `f32`
+   |
+help: you can convert an `f32` to an `f64`
+   |
+LL |     let _ = RGB { r, g: g.into(), b };
+   |                      ++  +++++++
 
 error[E0308]: mismatched types
   --> $DIR/type-mismatch-struct-field-shorthand.rs:8:25
    |
 LL |     let _ = RGB { r, g, b };
-   |                         ^
-   |                         |
-   |                         expected `f64`, found `f32`
-   |                         help: you can convert an `f32` to an `f64`: `b: b.into()`
+   |                         ^ expected `f64`, found `f32`
+   |
+help: you can convert an `f32` to an `f64`
+   |
+LL |     let _ = RGB { r, g, b: b.into() };
+   |                         ++  +++++++
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/tail-typeck.stderr b/src/test/ui/tail-typeck.stderr
index 422aa904e1d..10dfd2de744 100644
--- a/src/test/ui/tail-typeck.stderr
+++ b/src/test/ui/tail-typeck.stderr
@@ -9,7 +9,7 @@ LL | fn f() -> isize { return g(); }
 help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit
    |
 LL | fn f() -> isize { return g().try_into().unwrap(); }
-   |                          ~~~~~~~~~~~~~~~~~~~~~~~
+   |                             ++++++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/bound/same-crate-name.stderr b/src/test/ui/traits/bound/same-crate-name.stderr
index 15f5fe16bc7..81e5589d6eb 100644
--- a/src/test/ui/traits/bound/same-crate-name.stderr
+++ b/src/test/ui/traits/bound/same-crate-name.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `Foo: main::a::Bar` is not satisfied
   --> $DIR/same-crate-name.rs:31:20
    |
 LL |         a::try_foo(foo);
-   |                    ^^^ the trait `main::a::Bar` is not implemented for `Foo`
+   |         ---------- ^^^ the trait `main::a::Bar` is not implemented for `Foo`
+   |         |
+   |         required by a bound introduced by this call
    |
 help: trait impl with same name found
   --> $DIR/auxiliary/crate_a2.rs:5:1
@@ -20,7 +22,9 @@ error[E0277]: the trait bound `DoesNotImplementTrait: main::a::Bar` is not satis
   --> $DIR/same-crate-name.rs:38:20
    |
 LL |         a::try_foo(implements_no_traits);
-   |                    ^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `DoesNotImplementTrait`
+   |         ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `DoesNotImplementTrait`
+   |         |
+   |         required by a bound introduced by this call
    |
 note: required by a bound in `try_foo`
   --> $DIR/auxiliary/crate_a1.rs:3:24
@@ -32,7 +36,9 @@ error[E0277]: the trait bound `ImplementsWrongTraitConditionally<isize>: main::a
   --> $DIR/same-crate-name.rs:45:20
    |
 LL |         a::try_foo(other_variant_implements_mismatched_trait);
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsWrongTraitConditionally<isize>`
+   |         ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsWrongTraitConditionally<isize>`
+   |         |
+   |         required by a bound introduced by this call
    |
 help: trait impl with same name found
   --> $DIR/auxiliary/crate_a2.rs:13:1
@@ -50,7 +56,9 @@ error[E0277]: the trait bound `ImplementsTraitForUsize<isize>: main::a::Bar` is
   --> $DIR/same-crate-name.rs:51:20
    |
 LL |         a::try_foo(other_variant_implements_correct_trait);
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsTraitForUsize<isize>`
+   |         ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsTraitForUsize<isize>`
+   |         |
+   |         required by a bound introduced by this call
    |
    = help: the following implementations were found:
              <ImplementsTraitForUsize<usize> as main::a::Bar>
diff --git a/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr b/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
index 5206b572106..7895e50eef5 100644
--- a/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
+++ b/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
@@ -10,7 +10,9 @@ error[E0277]: the trait bound `NoClone: Copy` is not satisfied
   --> $DIR/supertrait-auto-trait.rs:16:23
    |
 LL |     let (a, b) = copy(NoClone);
-   |                       ^^^^^^^ the trait `Copy` is not implemented for `NoClone`
+   |                  ---- ^^^^^^^ the trait `Copy` is not implemented for `NoClone`
+   |                  |
+   |                  required by a bound introduced by this call
    |
    = note: required because of the requirements on the impl of `Magic` for `NoClone`
 note: required by a bound in `copy`
diff --git a/src/test/ui/traits/item-privacy.stderr b/src/test/ui/traits/item-privacy.stderr
index 2260dcfc70e..ef5d5cdff8f 100644
--- a/src/test/ui/traits/item-privacy.stderr
+++ b/src/test/ui/traits/item-privacy.stderr
@@ -127,9 +127,6 @@ error[E0038]: the trait `assoc_const::C` cannot be made into an object
 LL |     <dyn C>::A;
    |      ^^^^^ `assoc_const::C` cannot be made into an object
    |
-   = help: consider moving `C` to another trait
-   = help: consider moving `B` to another trait
-   = help: consider moving `A` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/item-privacy.rs:25:15
    |
@@ -143,6 +140,9 @@ LL |     pub trait C: A + B {
    |               - this trait cannot be made into an object...
 LL |         const C: u8 = 0;
    |               ^ ...because it contains this associated `const`
+   = help: consider moving `C` to another trait
+   = help: consider moving `A` to another trait
+   = help: consider moving `B` to another trait
 
 error[E0223]: ambiguous associated type
   --> $DIR/item-privacy.rs:115:12
diff --git a/src/test/ui/traits/multidispatch-bad.stderr b/src/test/ui/traits/multidispatch-bad.stderr
index ccdace1957d..6caa23d8f49 100644
--- a/src/test/ui/traits/multidispatch-bad.stderr
+++ b/src/test/ui/traits/multidispatch-bad.stderr
@@ -7,7 +7,7 @@ LL |     test(22i32, 44i32);
 help: change the type of the numeric literal from `i32` to `u32`
    |
 LL |     test(22i32, 44u32);
-   |                 ~~~~~
+   |                   ~~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr
index ad95e06eb4e..790e2a81c3a 100644
--- a/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr
+++ b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr
@@ -2,7 +2,9 @@ error[E0277]: `dummy::TestType` cannot be sent between threads safely
   --> $DIR/negated-auto-traits-error.rs:23:11
    |
 LL |     Outer(TestType);
-   |           ^^^^^^^^ `dummy::TestType` cannot be sent between threads safely
+   |     ----- ^^^^^^^^ `dummy::TestType` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Send` is not implemented for `dummy::TestType`
 note: required by `Outer`
@@ -28,7 +30,9 @@ error[E0277]: `dummy1b::TestType` cannot be sent between threads safely
   --> $DIR/negated-auto-traits-error.rs:32:13
    |
 LL |     is_send(TestType);
-   |             ^^^^^^^^ `dummy1b::TestType` cannot be sent between threads safely
+   |     ------- ^^^^^^^^ `dummy1b::TestType` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Send` is not implemented for `dummy1b::TestType`
 note: required by a bound in `is_send`
@@ -41,9 +45,11 @@ error[E0277]: `dummy1c::TestType` cannot be sent between threads safely
   --> $DIR/negated-auto-traits-error.rs:40:13
    |
 LL |     is_send((8, TestType));
-   |             ^^^^^^^^^^^^^ `dummy1c::TestType` cannot be sent between threads safely
+   |     ------- ^^^^^^^^^^^^^ `dummy1c::TestType` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
-   = help: within `({integer}, dummy1c::TestType)`, the trait `Send` is not implemented for `dummy1c::TestType`
+   = help: the trait `Send` is not implemented for `dummy1c::TestType`
    = note: required because it appears within the type `({integer}, dummy1c::TestType)`
 note: required by a bound in `is_send`
   --> $DIR/negated-auto-traits-error.rs:16:15
@@ -55,10 +61,11 @@ error[E0277]: `dummy2::TestType` cannot be sent between threads safely
   --> $DIR/negated-auto-traits-error.rs:48:13
    |
 LL |     is_send(Box::new(TestType));
-   |             ^^^^^^^^^^^^^^^^^^
-   |             |
-   |             expected an implementor of trait `Send`
-   |             help: consider borrowing here: `&Box::new(TestType)`
+   |     ------- ^^^^^^^^^^^^^^^^^^
+   |     |       |
+   |     |       expected an implementor of trait `Send`
+   |     |       help: consider borrowing here: `&Box::new(TestType)`
+   |     required by a bound introduced by this call
    |
    = note: the trait bound `dummy2::TestType: Send` is not satisfied
    = note: required because of the requirements on the impl of `Send` for `Unique<dummy2::TestType>`
@@ -73,9 +80,11 @@ error[E0277]: `dummy3::TestType` cannot be sent between threads safely
   --> $DIR/negated-auto-traits-error.rs:56:13
    |
 LL |     is_send(Box::new(Outer2(TestType)));
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ `dummy3::TestType` cannot be sent between threads safely
+   |     ------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ `dummy3::TestType` cannot be sent between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
-   = help: within `Outer2<dummy3::TestType>`, the trait `Send` is not implemented for `dummy3::TestType`
+   = help: the trait `Send` is not implemented for `dummy3::TestType`
 note: required because it appears within the type `Outer2<dummy3::TestType>`
   --> $DIR/negated-auto-traits-error.rs:12:8
    |
@@ -93,10 +102,11 @@ error[E0277]: `main::TestType` cannot be sent between threads safely
   --> $DIR/negated-auto-traits-error.rs:66:13
    |
 LL |     is_sync(Outer2(TestType));
-   |             ^^^^^^^^^^^^^^^^
-   |             |
-   |             expected an implementor of trait `Sync`
-   |             help: consider borrowing here: `&Outer2(TestType)`
+   |     ------- ^^^^^^^^^^^^^^^^
+   |     |       |
+   |     |       expected an implementor of trait `Sync`
+   |     |       help: consider borrowing here: `&Outer2(TestType)`
+   |     required by a bound introduced by this call
    |
    = note: the trait bound `main::TestType: Sync` is not satisfied
 note: required because of the requirements on the impl of `Sync` for `Outer2<main::TestType>`
diff --git a/src/test/ui/traits/reservation-impl/no-use.stderr b/src/test/ui/traits/reservation-impl/no-use.stderr
index 526c0e9ed54..e7d1ee616b3 100644
--- a/src/test/ui/traits/reservation-impl/no-use.stderr
+++ b/src/test/ui/traits/reservation-impl/no-use.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `(): MyTrait` is not satisfied
   --> $DIR/no-use.rs:10:26
    |
 LL |     <() as MyTrait>::foo(&());
-   |                          ^^^ the trait `MyTrait` is not implemented for `()`
+   |     -------------------- ^^^ the trait `MyTrait` is not implemented for `()`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the following implementations were found:
              <() as MyTrait>
diff --git a/src/test/ui/traits/suggest-deferences/issue-39029.stderr b/src/test/ui/traits/suggest-deferences/issue-39029.stderr
index 10eeec20d98..2c225f4311d 100644
--- a/src/test/ui/traits/suggest-deferences/issue-39029.stderr
+++ b/src/test/ui/traits/suggest-deferences/issue-39029.stderr
@@ -2,10 +2,11 @@ error[E0277]: the trait bound `NoToSocketAddrs: ToSocketAddrs` is not satisfied
   --> $DIR/issue-39029.rs:16:37
    |
 LL |     let _errors = TcpListener::bind(&bad);
-   |                                     ^^^^
-   |                                     |
-   |                                     the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs`
-   |                                     help: consider adding dereference here: `&*bad`
+   |                   ----------------- ^^^^
+   |                   |                 |
+   |                   |                 the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs`
+   |                   |                 help: consider adding dereference here: `&*bad`
+   |                   required by a bound introduced by this call
    |
    = note: required because of the requirements on the impl of `ToSocketAddrs` for `&NoToSocketAddrs`
 note: required by a bound in `TcpListener::bind`
diff --git a/src/test/ui/traits/suggest-deferences/issue-62530.stderr b/src/test/ui/traits/suggest-deferences/issue-62530.stderr
index 750c8a86c56..b77af7ddf47 100644
--- a/src/test/ui/traits/suggest-deferences/issue-62530.stderr
+++ b/src/test/ui/traits/suggest-deferences/issue-62530.stderr
@@ -2,10 +2,11 @@ error[E0277]: the trait bound `&String: SomeTrait` is not satisfied
   --> $DIR/issue-62530.rs:13:26
    |
 LL |     takes_type_parameter(&string);  // Error
-   |                          ^^^^^^^
-   |                          |
-   |                          the trait `SomeTrait` is not implemented for `&String`
-   |                          help: consider adding dereference here: `&*string`
+   |     -------------------- ^^^^^^^
+   |     |                    |
+   |     |                    the trait `SomeTrait` is not implemented for `&String`
+   |     |                    help: consider adding dereference here: `&*string`
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `takes_type_parameter`
   --> $DIR/issue-62530.rs:4:44
diff --git a/src/test/ui/traits/suggest-deferences/multiple-0.stderr b/src/test/ui/traits/suggest-deferences/multiple-0.stderr
index 6fcf8780d6e..bf9f85f1b45 100644
--- a/src/test/ui/traits/suggest-deferences/multiple-0.stderr
+++ b/src/test/ui/traits/suggest-deferences/multiple-0.stderr
@@ -2,10 +2,11 @@ error[E0277]: the trait bound `&Baz: Happy` is not satisfied
   --> $DIR/multiple-0.rs:34:9
    |
 LL |     foo(&baz);
-   |         ^^^^
-   |         |
-   |         the trait `Happy` is not implemented for `&Baz`
-   |         help: consider adding dereference here: `&***baz`
+   |     --- ^^^^
+   |     |   |
+   |     |   the trait `Happy` is not implemented for `&Baz`
+   |     |   help: consider adding dereference here: `&***baz`
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `foo`
   --> $DIR/multiple-0.rs:30:26
diff --git a/src/test/ui/traits/suggest-deferences/multiple-1.stderr b/src/test/ui/traits/suggest-deferences/multiple-1.stderr
index 268f375050a..040fbb3e3e6 100644
--- a/src/test/ui/traits/suggest-deferences/multiple-1.stderr
+++ b/src/test/ui/traits/suggest-deferences/multiple-1.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `&mut Baz: Happy` is not satisfied
   --> $DIR/multiple-1.rs:52:9
    |
 LL |     foo(&mut baz);
-   |         ^^^^^^^^ the trait `Happy` is not implemented for `&mut Baz`
+   |     --- ^^^^^^^^ the trait `Happy` is not implemented for `&mut Baz`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `foo`
   --> $DIR/multiple-1.rs:45:26
diff --git a/src/test/ui/traits/test-2.stderr b/src/test/ui/traits/test-2.stderr
index 0289424510f..d943b48fd00 100644
--- a/src/test/ui/traits/test-2.stderr
+++ b/src/test/ui/traits/test-2.stderr
@@ -32,8 +32,6 @@ error[E0038]: the trait `bar` cannot be made into an object
 LL |     (box 10 as Box<dyn bar>).dup();
    |                ^^^^^^^^^^^^ `bar` cannot be made into an object
    |
-   = help: consider moving `dup` to another trait
-   = help: consider moving `blah` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/test-2.rs:4:30
    |
@@ -42,6 +40,8 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
    |       |                      |
    |       |                      ...because method `dup` references the `Self` type in its return type
    |       this trait cannot be made into an object...
+   = help: consider moving `dup` to another trait
+   = help: consider moving `blah` to another trait
 
 error[E0038]: the trait `bar` cannot be made into an object
   --> $DIR/test-2.rs:13:6
@@ -49,8 +49,6 @@ error[E0038]: the trait `bar` cannot be made into an object
 LL |     (box 10 as Box<dyn bar>).dup();
    |      ^^^^^^ `bar` cannot be made into an object
    |
-   = help: consider moving `dup` to another trait
-   = help: consider moving `blah` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/test-2.rs:4:30
    |
@@ -59,6 +57,8 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
    |       |                      |
    |       |                      ...because method `dup` references the `Self` type in its return type
    |       this trait cannot be made into an object...
+   = help: consider moving `dup` to another trait
+   = help: consider moving `blah` to another trait
    = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn bar>>` for `Box<{integer}>`
    = note: required by cast to type `Box<dyn bar>`
 
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr
index 6508e6a6e76..26679e71380 100644
--- a/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr
+++ b/src/test/ui/trivial-bounds/trivial-bounds-inconsistent-projection-error.stderr
@@ -10,7 +10,7 @@ LL |     B::get_x()
 help: you can convert an `i32` to a `u8` and panic if the converted value doesn't fit
    |
 LL |     B::get_x().try_into().unwrap()
-   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+   |               ++++++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr
index 97ef2dd37f7..d9e0d21541e 100644
--- a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr
+++ b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr
@@ -24,7 +24,9 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied
   --> $DIR/trivial-bounds-leak.rs:25:15
    |
 LL |     Foo::test(&4i32);
-   |               ^^^^^ the trait `Foo` is not implemented for `i32`
+   |     --------- ^^^^^ the trait `Foo` is not implemented for `i32`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by `Foo::test`
   --> $DIR/trivial-bounds-leak.rs:5:5
@@ -36,7 +38,9 @@ error[E0277]: the trait bound `i32: Foo` is not satisfied
   --> $DIR/trivial-bounds-leak.rs:26:22
    |
 LL |     generic_function(5i32);
-   |                      ^^^^ the trait `Foo` is not implemented for `i32`
+   |     ---------------- ^^^^ the trait `Foo` is not implemented for `i32`
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `generic_function`
   --> $DIR/trivial-bounds-leak.rs:29:24
diff --git a/src/test/ui/try-block/try-block-unused-delims.stderr b/src/test/ui/try-block/try-block-unused-delims.stderr
index c5a24054629..d8dd31645e0 100644
--- a/src/test/ui/try-block/try-block-unused-delims.stderr
+++ b/src/test/ui/try-block/try-block-unused-delims.stderr
@@ -2,43 +2,71 @@ warning: unnecessary parentheses around function argument
   --> $DIR/try-block-unused-delims.rs:11:13
    |
 LL |     consume((try {}));
-   |             ^^^^^^^^ help: remove these parentheses
+   |             ^      ^
    |
 note: the lint level is defined here
   --> $DIR/try-block-unused-delims.rs:6:9
    |
 LL | #![warn(unused_parens, unused_braces)]
    |         ^^^^^^^^^^^^^
+help: remove these parentheses
+   |
+LL -     consume((try {}));
+LL +     consume(try {});
+   | 
 
 warning: unnecessary braces around function argument
   --> $DIR/try-block-unused-delims.rs:14:13
    |
 LL |     consume({ try {} });
-   |             ^^^^^^^^^^ help: remove these braces
+   |             ^^      ^^
    |
 note: the lint level is defined here
   --> $DIR/try-block-unused-delims.rs:6:24
    |
 LL | #![warn(unused_parens, unused_braces)]
    |                        ^^^^^^^^^^^^^
+help: remove these braces
+   |
+LL -     consume({ try {} });
+LL +     consume(try {});
+   | 
 
 warning: unnecessary parentheses around `match` scrutinee expression
   --> $DIR/try-block-unused-delims.rs:17:11
    |
 LL |     match (try {}) {
-   |           ^^^^^^^^ help: remove these parentheses
+   |           ^      ^
+   |
+help: remove these parentheses
+   |
+LL -     match (try {}) {
+LL +     match try {} {
+   | 
 
 warning: unnecessary parentheses around `let` scrutinee expression
   --> $DIR/try-block-unused-delims.rs:22:22
    |
 LL |     if let Err(()) = (try {}) {}
-   |                      ^^^^^^^^ help: remove these parentheses
+   |                      ^      ^
+   |
+help: remove these parentheses
+   |
+LL -     if let Err(()) = (try {}) {}
+LL +     if let Err(()) = try {} {}
+   | 
 
 warning: unnecessary parentheses around `match` scrutinee expression
   --> $DIR/try-block-unused-delims.rs:25:11
    |
 LL |     match (try {}) {
-   |           ^^^^^^^^ help: remove these parentheses
+   |           ^      ^
+   |
+help: remove these parentheses
+   |
+LL -     match (try {}) {
+LL +     match try {} {
+   | 
 
 warning: 5 warnings emitted
 
diff --git a/src/test/ui/tutorial-suffix-inference-test.stderr b/src/test/ui/tutorial-suffix-inference-test.stderr
index ac1027ff34a..fbfbffbd24e 100644
--- a/src/test/ui/tutorial-suffix-inference-test.stderr
+++ b/src/test/ui/tutorial-suffix-inference-test.stderr
@@ -2,10 +2,12 @@ error[E0308]: mismatched types
   --> $DIR/tutorial-suffix-inference-test.rs:9:18
    |
 LL |     identity_u16(x);
-   |                  ^
-   |                  |
-   |                  expected `u16`, found `u8`
-   |                  help: you can convert a `u8` to a `u16`: `x.into()`
+   |                  ^ expected `u16`, found `u8`
+   |
+help: you can convert a `u8` to a `u16`
+   |
+LL |     identity_u16(x.into());
+   |                   +++++++
 
 error[E0308]: mismatched types
   --> $DIR/tutorial-suffix-inference-test.rs:12:18
@@ -16,7 +18,7 @@ LL |     identity_u16(y);
 help: you can convert an `i32` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     identity_u16(y.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~
+   |                   ++++++++++++++++++++
 
 error[E0308]: mismatched types
   --> $DIR/tutorial-suffix-inference-test.rs:21:18
@@ -27,7 +29,7 @@ LL |     identity_u16(a);
 help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit
    |
 LL |     identity_u16(a.try_into().unwrap());
-   |                  ~~~~~~~~~~~~~~~~~~~~~
+   |                   ++++++++++++++++++++
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.rs b/src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.rs
new file mode 100644
index 00000000000..e50cc586515
--- /dev/null
+++ b/src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.rs
@@ -0,0 +1,12 @@
+macro_rules! many_args {
+    ([$($t:tt)*]#$($h:tt)*) => {
+        many_args!{[$($t)*$($t)*]$($h)*}
+    };
+    ([$($t:tt)*]) => {
+        fn _f($($t: ()),*) {} //~ ERROR function can not have more than 65535 arguments
+    }
+}
+
+many_args!{[_]########## ######}
+
+fn main() {}
diff --git a/src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr b/src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr
new file mode 100644
index 00000000000..615fd2ccb04
--- /dev/null
+++ b/src/test/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr
@@ -0,0 +1,13 @@
+error: function can not have more than 65535 arguments
+  --> $DIR/issue-88577-check-fn-with-more-than-65535-arguments.rs:6:24
+   |
+LL |           fn _f($($t: ()),*) {}
+   |  ________________________^
+LL | |     }
+LL | | }
+LL | |
+LL | | many_args!{[_]########## ######}
+   | |____________^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
index 2de5f6eb0f0..8a296dc7ee6 100644
--- a/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
+++ b/src/test/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr
@@ -16,7 +16,6 @@ error[E0038]: the trait `MyAdd` cannot be made into an object
 LL |     let y = x as dyn MyAdd<i32>;
    |                  ^^^^^^^^^^^^^^ `MyAdd` cannot be made into an object
    |
-   = help: consider moving `add` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:6:55
    |
@@ -24,6 +23,7 @@ LL | trait MyAdd<Rhs=Self> { fn add(&self, other: &Rhs) -> Self; }
    |       -----                                           ^^^^ ...because method `add` references the `Self` type in its return type
    |       |
    |       this trait cannot be made into an object...
+   = help: consider moving `add` to another trait
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/typeck/issue-88803-call-expr-method.fixed b/src/test/ui/typeck/issue-88803-call-expr-method.fixed
new file mode 100644
index 00000000000..19b96ecf3fc
--- /dev/null
+++ b/src/test/ui/typeck/issue-88803-call-expr-method.fixed
@@ -0,0 +1,9 @@
+// run-rustfix
+
+fn main() {
+    let a = Some(42);
+    println!(
+        "The value is {}.",
+        a.unwrap() //~ERROR [E0615]
+    );
+}
diff --git a/src/test/ui/typeck/issue-88803-call-expr-method.rs b/src/test/ui/typeck/issue-88803-call-expr-method.rs
new file mode 100644
index 00000000000..a0619946637
--- /dev/null
+++ b/src/test/ui/typeck/issue-88803-call-expr-method.rs
@@ -0,0 +1,9 @@
+// run-rustfix
+
+fn main() {
+    let a = Some(42);
+    println!(
+        "The value is {}.",
+        (a.unwrap)() //~ERROR [E0615]
+    );
+}
diff --git a/src/test/ui/typeck/issue-88803-call-expr-method.stderr b/src/test/ui/typeck/issue-88803-call-expr-method.stderr
new file mode 100644
index 00000000000..dd717ed9416
--- /dev/null
+++ b/src/test/ui/typeck/issue-88803-call-expr-method.stderr
@@ -0,0 +1,15 @@
+error[E0615]: attempted to take value of method `unwrap` on type `Option<{integer}>`
+  --> $DIR/issue-88803-call-expr-method.rs:7:12
+   |
+LL |         (a.unwrap)()
+   |            ^^^^^^ method, not a field
+   |
+help: remove wrapping parentheses to call the method
+   |
+LL -         (a.unwrap)()
+LL +         a.unwrap()
+   | 
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0615`.
diff --git a/src/test/ui/typeck/typeck-unsafe-always-share.stderr b/src/test/ui/typeck/typeck-unsafe-always-share.stderr
index c0f388bd15b..4b5804253b2 100644
--- a/src/test/ui/typeck/typeck-unsafe-always-share.stderr
+++ b/src/test/ui/typeck/typeck-unsafe-always-share.stderr
@@ -2,7 +2,9 @@ error[E0277]: `UnsafeCell<MySync<{integer}>>` cannot be shared between threads s
   --> $DIR/typeck-unsafe-always-share.rs:19:10
    |
 LL |     test(us);
-   |          ^^ `UnsafeCell<MySync<{integer}>>` cannot be shared between threads safely
+   |     ---- ^^ `UnsafeCell<MySync<{integer}>>` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sync` is not implemented for `UnsafeCell<MySync<{integer}>>`
 note: required by a bound in `test`
@@ -15,7 +17,9 @@ error[E0277]: `UnsafeCell<NoSync>` cannot be shared between threads safely
   --> $DIR/typeck-unsafe-always-share.rs:23:10
    |
 LL |     test(uns);
-   |          ^^^ `UnsafeCell<NoSync>` cannot be shared between threads safely
+   |     ---- ^^^ `UnsafeCell<NoSync>` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sync` is not implemented for `UnsafeCell<NoSync>`
 note: required by a bound in `test`
@@ -46,7 +50,9 @@ error[E0277]: `NoSync` cannot be shared between threads safely
   --> $DIR/typeck-unsafe-always-share.rs:30:10
    |
 LL |     test(NoSync);
-   |          ^^^^^^ `NoSync` cannot be shared between threads safely
+   |     ---- ^^^^^^ `NoSync` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sync` is not implemented for `NoSync`
 note: required by a bound in `test`
diff --git a/src/test/ui/typeof/type_mismatch.stderr b/src/test/ui/typeof/type_mismatch.stderr
index 5c58e29fa00..e82b5e44973 100644
--- a/src/test/ui/typeof/type_mismatch.stderr
+++ b/src/test/ui/typeof/type_mismatch.stderr
@@ -15,7 +15,7 @@ LL |     let b: typeof(a) = 1i8;
 help: change the type of the numeric literal from `i8` to `u8`
    |
 LL |     let b: typeof(a) = 1u8;
-   |                        ~~~
+   |                         ~~
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
index 8dc024697d7..23b91573756 100644
--- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
+++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
@@ -20,7 +20,7 @@ LL |     <i32 as Add<i32>>::add(1u32, 2);
 help: change the type of the numeric literal from `u32` to `i32`
    |
 LL |     <i32 as Add<i32>>::add(1i32, 2);
-   |                            ~~~~
+   |                             ~~~
 
 error[E0308]: mismatched types
   --> $DIR/ufcs-qpath-self-mismatch.rs:8:31
@@ -31,7 +31,7 @@ LL |     <i32 as Add<i32>>::add(1, 2u32);
 help: change the type of the numeric literal from `u32` to `i32`
    |
 LL |     <i32 as Add<i32>>::add(1, 2i32);
-   |                               ~~~~
+   |                                ~~~
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr
index f30bf40983e..c8ce3091cf6 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr
@@ -2,7 +2,9 @@ error[E0277]: expected a `Fn<(isize,)>` closure, found `S`
   --> $DIR/unboxed-closures-fnmut-as-fn.rs:28:21
    |
 LL |     let x = call_it(&S, 22);
-   |                     ^^ expected an `Fn<(isize,)>` closure, found `S`
+   |             ------- ^^ expected an `Fn<(isize,)>` closure, found `S`
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `Fn<(isize,)>` is not implemented for `S`
 note: required by a bound in `call_it`
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr b/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr
index 67bf4be54e6..f791ea62ceb 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-type-mismatch.stderr
@@ -7,7 +7,7 @@ LL |     let z = f(1_usize, 2);
 help: change the type of the numeric literal from `usize` to `isize`
    |
 LL |     let z = f(1_isize, 2);
-   |               ~~~~~~~
+   |                 ~~~~~
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
index 6b21b9246f7..c9a20232f35 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
@@ -2,7 +2,9 @@ error[E0277]: expected a `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r i
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:20:21
    |
 LL |     let x = call_it(&square, 22);
-   |                     ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   |             ------- ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
 note: required by a bound in `call_it`
@@ -15,7 +17,9 @@ error[E0277]: expected a `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:25:25
    |
 LL |     let y = call_it_mut(&mut square, 22);
-   |                         ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   |             ----------- ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
 note: required by a bound in `call_it_mut`
@@ -28,7 +32,9 @@ error[E0277]: expected a `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:30:26
    |
 LL |     let z = call_it_once(square, 22);
-   |                          ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   |             ------------ ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
 note: required by a bound in `call_it_once`
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr
index 936cb27759a..77c176de625 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr
@@ -2,7 +2,9 @@ error[E0277]: expected a `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&
   --> $DIR/unboxed-closures-wrong-abi.rs:20:21
    |
 LL |     let x = call_it(&square, 22);
-   |                     ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   |             ------- ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
 note: required by a bound in `call_it`
@@ -15,7 +17,9 @@ error[E0277]: expected a `FnMut<(&isize,)>` closure, found `for<'r> extern "C" f
   --> $DIR/unboxed-closures-wrong-abi.rs:25:25
    |
 LL |     let y = call_it_mut(&mut square, 22);
-   |                         ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   |             ----------- ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
 note: required by a bound in `call_it_mut`
@@ -28,7 +32,9 @@ error[E0277]: expected a `FnOnce<(&isize,)>` closure, found `for<'r> extern "C"
   --> $DIR/unboxed-closures-wrong-abi.rs:30:26
    |
 LL |     let z = call_it_once(square, 22);
-   |                          ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   |             ------------ ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
 note: required by a bound in `call_it_once`
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
index f9f1182e309..64d57773d70 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
@@ -2,7 +2,9 @@ error[E0277]: expected a `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isi
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:21:21
    |
 LL |     let x = call_it(&square, 22);
-   |                     ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+   |             ------- ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
 note: required by a bound in `call_it`
@@ -15,7 +17,9 @@ error[E0277]: expected a `FnMut<(&isize,)>` closure, found `unsafe fn(isize) ->
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:26:25
    |
 LL |     let y = call_it_mut(&mut square, 22);
-   |                         ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+   |             ----------- ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
 note: required by a bound in `call_it_mut`
@@ -28,7 +32,9 @@ error[E0277]: expected a `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) ->
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:31:26
    |
 LL |     let z = call_it_once(square, 22);
-   |                          ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+   |             ------------ ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `unsafe fn(isize) -> isize {square}`
+   |             |
+   |             required by a bound introduced by this call
    |
    = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
 note: required by a bound in `call_it_once`
diff --git a/src/test/ui/unnamed_fields/restrict_anonymous.rs b/src/test/ui/unnamed_fields/restrict_anonymous.rs
deleted file mode 100644
index 99637d11053..00000000000
--- a/src/test/ui/unnamed_fields/restrict_anonymous.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-#![allow(incomplete_features)]
-#![feature(unnamed_fields)]
-
-fn f() -> struct { field: u8 } {} //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-//~^ ERROR anonymous structs are unimplemented
-
-fn f2(a: struct { field: u8 } ) {} //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-//~^ ERROR anonymous structs are unimplemented
-
-union G {
-    field: struct { field: u8 } //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-    //~^ ERROR anonymous structs are unimplemented
-}
-//~| ERROR unions may not contain fields that need dropping [E0740]
-
-struct H { _: u8 } // Should error after hir checks
-
-struct I(struct { field: u8 }, u8); //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-//~^ ERROR anonymous structs are unimplemented
-
-enum J {
-    K(struct { field: u8 }), //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-    //~^ ERROR anonymous structs are unimplemented
-    L {
-        _ : struct { field: u8 } //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-        //~^ ERROR anonymous fields are not allowed outside of structs or unions
-        //~| ERROR anonymous structs are unimplemented
-    },
-    M {
-        _ : u8 //~ ERROR anonymous fields are not allowed outside of structs or unions
-    }
-}
-
-static M: union { field: u8 } = 0; //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields
-//~^ ERROR anonymous unions are unimplemented
-
-type N = union { field: u8 }; //~ ERROR anonymous unions are not allowed outside of unnamed struct or union fields
-//~^ ERROR anonymous unions are unimplemented
-
-fn main() {
-    const O: struct { field: u8 } = 0; //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-    //~^ ERROR anonymous structs are unimplemented
-
-    let p: [struct { field: u8 }; 1]; //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-    //~^ ERROR anonymous structs are unimplemented
-
-    let q: (struct { field: u8 }, u8); //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-    //~^ ERROR anonymous structs are unimplemented
-
-    let cl = || -> struct { field: u8 } {}; //~ ERROR anonymous structs are not allowed outside of unnamed struct or union fields
-    //~^ ERROR anonymous structs are unimplemented
-}
diff --git a/src/test/ui/unnamed_fields/restrict_anonymous.stderr b/src/test/ui/unnamed_fields/restrict_anonymous.stderr
deleted file mode 100644
index efcf544fde4..00000000000
--- a/src/test/ui/unnamed_fields/restrict_anonymous.stderr
+++ /dev/null
@@ -1,175 +0,0 @@
-error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:4:11
-   |
-LL | fn f() -> struct { field: u8 } {}
-   |           ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:7:10
-   |
-LL | fn f2(a: struct { field: u8 } ) {}
-   |          ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:11:12
-   |
-LL |     field: struct { field: u8 }
-   |            ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:18:10
-   |
-LL | struct I(struct { field: u8 }, u8);
-   |          ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:22:7
-   |
-LL |     K(struct { field: u8 }),
-   |       ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous fields are not allowed outside of structs or unions
-  --> $DIR/restrict_anonymous.rs:25:9
-   |
-LL |         _ : struct { field: u8 }
-   |         -^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         anonymous field declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:25:13
-   |
-LL |         _ : struct { field: u8 }
-   |             ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous fields are not allowed outside of structs or unions
-  --> $DIR/restrict_anonymous.rs:30:9
-   |
-LL |         _ : u8
-   |         -^^^^^
-   |         |
-   |         anonymous field declared here
-
-error: anonymous unions are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:34:11
-   |
-LL | static M: union { field: u8 } = 0;
-   |           ^^^^^^^^^^^^^^^^^^^ anonymous union declared here
-
-error: anonymous unions are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:37:10
-   |
-LL | type N = union { field: u8 };
-   |          ^^^^^^^^^^^^^^^^^^^ anonymous union declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:41:14
-   |
-LL |     const O: struct { field: u8 } = 0;
-   |              ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:44:13
-   |
-LL |     let p: [struct { field: u8 }; 1];
-   |             ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:47:13
-   |
-LL |     let q: (struct { field: u8 }, u8);
-   |             ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are not allowed outside of unnamed struct or union fields
-  --> $DIR/restrict_anonymous.rs:50:20
-   |
-LL |     let cl = || -> struct { field: u8 } {};
-   |                    ^^^^^^^^^^^^^^^^^^^^ anonymous struct declared here
-
-error: anonymous structs are unimplemented
-  --> $DIR/restrict_anonymous.rs:4:11
-   |
-LL | fn f() -> struct { field: u8 } {}
-   |           ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
-  --> $DIR/restrict_anonymous.rs:7:10
-   |
-LL | fn f2(a: struct { field: u8 } ) {}
-   |          ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
-  --> $DIR/restrict_anonymous.rs:11:12
-   |
-LL |     field: struct { field: u8 }
-   |            ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
-  --> $DIR/restrict_anonymous.rs:18:10
-   |
-LL | struct I(struct { field: u8 }, u8);
-   |          ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
-  --> $DIR/restrict_anonymous.rs:22:7
-   |
-LL |     K(struct { field: u8 }),
-   |       ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
-  --> $DIR/restrict_anonymous.rs:25:13
-   |
-LL |         _ : struct { field: u8 }
-   |             ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous unions are unimplemented
-  --> $DIR/restrict_anonymous.rs:34:11
-   |
-LL | static M: union { field: u8 } = 0;
-   |           ^^^^^^^^^^^^^^^^^^^
-
-error: anonymous unions are unimplemented
-  --> $DIR/restrict_anonymous.rs:37:10
-   |
-LL | type N = union { field: u8 };
-   |          ^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
-  --> $DIR/restrict_anonymous.rs:44:13
-   |
-LL |     let p: [struct { field: u8 }; 1];
-   |             ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
-  --> $DIR/restrict_anonymous.rs:47:13
-   |
-LL |     let q: (struct { field: u8 }, u8);
-   |             ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
-  --> $DIR/restrict_anonymous.rs:50:20
-   |
-LL |     let cl = || -> struct { field: u8 } {};
-   |                    ^^^^^^^^^^^^^^^^^^^^
-
-error: anonymous structs are unimplemented
-  --> $DIR/restrict_anonymous.rs:41:14
-   |
-LL |     const O: struct { field: u8 } = 0;
-   |              ^^^^^^^^^^^^^^^^^^^^
-
-error[E0740]: unions may not contain fields that need dropping
-  --> $DIR/restrict_anonymous.rs:11:5
-   |
-LL |     field: struct { field: u8 }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: `std::mem::ManuallyDrop` can be used to wrap the type
-  --> $DIR/restrict_anonymous.rs:11:5
-   |
-LL |     field: struct { field: u8 }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 27 previous errors
-
-For more information about this error, try `rustc --explain E0740`.
diff --git a/src/test/ui/unsized-locals/unsized-exprs.stderr b/src/test/ui/unsized-locals/unsized-exprs.stderr
index a7f57e3fd15..6686e55130f 100644
--- a/src/test/ui/unsized-locals/unsized-exprs.stderr
+++ b/src/test/ui/unsized-locals/unsized-exprs.stderr
@@ -12,9 +12,11 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
   --> $DIR/unsized-exprs.rs:24:22
    |
 LL |     udrop::<A<[u8]>>(A { 0: *foo() });
-   |                      ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |     ---------------- ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
    |
-   = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]`
+   = help: the trait `Sized` is not implemented for `[u8]`
 note: required because it appears within the type `A<[u8]>`
   --> $DIR/unsized-exprs.rs:3:8
    |
diff --git a/src/test/ui/unsized/unsized3.rs b/src/test/ui/unsized/unsized3.rs
index f5b5d025931..39b6583bc4e 100644
--- a/src/test/ui/unsized/unsized3.rs
+++ b/src/test/ui/unsized/unsized3.rs
@@ -44,8 +44,6 @@ fn f9<X: ?Sized>(x1: Box<S<X>>) {
 fn f10<X: ?Sized>(x1: Box<S<X>>) {
     f5(&(32, *x1));
     //~^ ERROR the size for values of type
-    //~| ERROR the size for values of type
 }
 
-pub fn main() {
-}
+pub fn main() {}
diff --git a/src/test/ui/unsized/unsized3.stderr b/src/test/ui/unsized/unsized3.stderr
index f7bb6c9c78c..ae89f2f9977 100644
--- a/src/test/ui/unsized/unsized3.stderr
+++ b/src/test/ui/unsized/unsized3.stderr
@@ -4,7 +4,9 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
 LL | fn f1<X: ?Sized>(x: &X) {
    |       - this type parameter needs to be `std::marker::Sized`
 LL |     f2::<X>(x);
-   |             ^ doesn't have a size known at compile-time
+   |     ------- ^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `f2`
   --> $DIR/unsized3.rs:10:7
@@ -27,7 +29,9 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
 LL | fn f3<X: ?Sized + T>(x: &X) {
    |       - this type parameter needs to be `std::marker::Sized`
 LL |     f4::<X>(x);
-   |             ^ doesn't have a size known at compile-time
+   |     ------- ^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `f4`
   --> $DIR/unsized3.rs:21:7
@@ -50,7 +54,9 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
 LL | fn f8<X: ?Sized>(x1: &S<X>, x2: &S<X>) {
    |       - this type parameter needs to be `std::marker::Sized`
 LL |     f5(x1);
-   |        ^^ doesn't have a size known at compile-time
+   |     -- ^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required because it appears within the type `S<X>`
   --> $DIR/unsized3.rs:28:8
@@ -78,7 +84,9 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
 LL | fn f9<X: ?Sized>(x1: Box<S<X>>) {
    |       - this type parameter needs to be `std::marker::Sized`
 LL |     f5(&(*x1, 34));
-   |        ^^^^^^^^^^ doesn't have a size known at compile-time
+   |     -- ^^^^^^^^^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required because it appears within the type `S<X>`
   --> $DIR/unsized3.rs:28:8
@@ -93,33 +101,14 @@ LL + fn f9<X>(x1: Box<S<X>>) {
    | 
 
 error[E0277]: the size for values of type `X` cannot be known at compilation time
-  --> $DIR/unsized3.rs:45:9
-   |
-LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
-   |        - this type parameter needs to be `std::marker::Sized`
-LL |     f5(&(32, *x1));
-   |         ^^^^^^^^^ doesn't have a size known at compile-time
-   |
-note: required because it appears within the type `S<X>`
-  --> $DIR/unsized3.rs:28:8
-   |
-LL | struct S<X: ?Sized> {
-   |        ^
-   = note: required because it appears within the type `({integer}, S<X>)`
-   = note: tuples must have a statically known size to be initialized
-help: consider removing the `?Sized` bound to make the type parameter `Sized`
-   |
-LL - fn f10<X: ?Sized>(x1: Box<S<X>>) {
-LL + fn f10<X>(x1: Box<S<X>>) {
-   | 
-
-error[E0277]: the size for values of type `X` cannot be known at compilation time
   --> $DIR/unsized3.rs:45:8
    |
 LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
    |        - this type parameter needs to be `std::marker::Sized`
 LL |     f5(&(32, *x1));
-   |        ^^^^^^^^^^ doesn't have a size known at compile-time
+   |     -- ^^^^^^^^^^ doesn't have a size known at compile-time
+   |     |
+   |     required by a bound introduced by this call
    |
 note: required because it appears within the type `S<X>`
   --> $DIR/unsized3.rs:28:8
@@ -127,21 +116,13 @@ note: required because it appears within the type `S<X>`
 LL | struct S<X: ?Sized> {
    |        ^
    = note: required because it appears within the type `({integer}, S<X>)`
-note: required by a bound in `f5`
-  --> $DIR/unsized3.rs:24:7
-   |
-LL | fn f5<Y>(x: &Y) {}
-   |       ^ required by this bound in `f5`
+   = note: tuples must have a statically known size to be initialized
 help: consider removing the `?Sized` bound to make the type parameter `Sized`
    |
 LL - fn f10<X: ?Sized>(x1: Box<S<X>>) {
 LL + fn f10<X>(x1: Box<S<X>>) {
    | 
-help: consider relaxing the implicit `Sized` restriction
-   |
-LL | fn f5<Y: ?Sized>(x: &Y) {}
-   |        ++++++++
 
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/vtable-res-trait-param.stderr b/src/test/ui/vtable-res-trait-param.stderr
index bff64813268..c5fff622b6b 100644
--- a/src/test/ui/vtable-res-trait-param.stderr
+++ b/src/test/ui/vtable-res-trait-param.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `{integer}: TraitA` is not satisfied
   --> $DIR/vtable-res-trait-param.rs:17:18
    |
 LL |     b.gimme_an_a(y)
-   |                  ^ the trait `TraitA` is not implemented for `{integer}`
+   |       ---------- ^ the trait `TraitA` is not implemented for `{integer}`
+   |       |
+   |       required by a bound introduced by this call
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/issue-87495.stderr b/src/test/ui/wf/issue-87495.stderr
index 010200b5ded..c924cd87997 100644
--- a/src/test/ui/wf/issue-87495.stderr
+++ b/src/test/ui/wf/issue-87495.stderr
@@ -4,7 +4,6 @@ error[E0038]: the trait `T` cannot be made into an object
 LL |     const CONST: (bool, dyn T);
    |                         ^^^^^ `T` cannot be made into an object
    |
-   = help: consider moving `CONST` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/issue-87495.rs:4:11
    |
@@ -12,6 +11,7 @@ LL | trait T {
    |       - this trait cannot be made into an object...
 LL |     const CONST: (bool, dyn T);
    |           ^^^^^ ...because it contains this associated `const`
+   = help: consider moving `CONST` to another trait
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-object-safe.stderr b/src/test/ui/wf/wf-object-safe.stderr
index 9b749f88fb8..64969fbe320 100644
--- a/src/test/ui/wf/wf-object-safe.stderr
+++ b/src/test/ui/wf/wf-object-safe.stderr
@@ -4,7 +4,6 @@ error[E0038]: the trait `A` cannot be made into an object
 LL |     let _x: &dyn A;
    |             ^^^^^^ `A` cannot be made into an object
    |
-   = help: consider moving `foo` to another trait
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
   --> $DIR/wf-object-safe.rs:5:23
    |
@@ -12,6 +11,7 @@ LL | trait A {
    |       - this trait cannot be made into an object...
 LL |     fn foo(&self, _x: &Self);
    |                       ^^^^^ ...because method `foo` references the `Self` type in this parameter
+   = help: consider moving `foo` to another trait
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr
index 0df5f91c8f3..43fbc0a9061 100644
--- a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr
+++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
   --> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:13:22
    |
 LL |         require_copy(self.x);
-   |                      ^^^^^^ the trait `Copy` is not implemented for `T`
+   |         ------------ ^^^^^^ the trait `Copy` is not implemented for `T`
+   |         |
+   |         required by a bound introduced by this call
    |
 note: required by a bound in `require_copy`
   --> $DIR/where-clause-constraints-are-local-for-inherent-impl.rs:1:20
diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr
index 97d651e0bec..f2db8fcc4a3 100644
--- a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr
+++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
   --> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:18:22
    |
 LL |         require_copy(self.x);
-   |                      ^^^^^^ the trait `Copy` is not implemented for `T`
+   |         ------------ ^^^^^^ the trait `Copy` is not implemented for `T`
+   |         |
+   |         required by a bound introduced by this call
    |
 note: required by a bound in `require_copy`
   --> $DIR/where-clause-constraints-are-local-for-trait-impl.rs:1:20
diff --git a/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr b/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr
index d7de83104c1..3223dca3cdd 100644
--- a/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr
+++ b/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `Bar: Eq` is not satisfied
   --> $DIR/where-clauses-method-unsatisfied.rs:18:14
    |
 LL |     x.equals(&x);
-   |              ^^ the trait `Eq` is not implemented for `Bar`
+   |       ------ ^^ the trait `Eq` is not implemented for `Bar`
+   |       |
+   |       required by a bound introduced by this call
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wrong-ret-type.stderr b/src/test/ui/wrong-ret-type.stderr
index 8e240a0e40d..c686a0b2f5a 100644
--- a/src/test/ui/wrong-ret-type.stderr
+++ b/src/test/ui/wrong-ret-type.stderr
@@ -9,7 +9,7 @@ LL | fn mk_int() -> usize { let i: isize = 3; return i; }
 help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
    |
 LL | fn mk_int() -> usize { let i: isize = 3; return i.try_into().unwrap(); }
-   |                                                 ~~~~~~~~~~~~~~~~~~~~~
+   |                                                  ++++++++++++++++++++
 
 error: aborting due to previous error
 
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 18751dd3f238d94d384a7fe967abfac06cbfe0b
+Subproject e515c3277bf0681bfc79a9e763861bfe26bb05d
diff --git a/src/tools/clippy/.cargo/config b/src/tools/clippy/.cargo/config
index e95ea224cb6..84ae36a46d7 100644
--- a/src/tools/clippy/.cargo/config
+++ b/src/tools/clippy/.cargo/config
@@ -5,4 +5,5 @@ lintcheck = "run --target-dir lintcheck/target --package lintcheck --bin lintche
 collect-metadata = "test --test dogfood --features metadata-collector-lint -- run_metadata_collection_lint --ignored"
 
 [build]
-rustflags = ["-Zunstable-options"]
+# -Zbinary-dep-depinfo allows us to track which rlib files to use for compiling UI tests
+rustflags = ["-Zunstable-options", "-Zbinary-dep-depinfo"]
diff --git a/src/tools/clippy/.github/ISSUE_TEMPLATE/blank_issue.md b/src/tools/clippy/.github/ISSUE_TEMPLATE/blank_issue.md
index 9aef3ebe637..2891d5e5da1 100644
--- a/src/tools/clippy/.github/ISSUE_TEMPLATE/blank_issue.md
+++ b/src/tools/clippy/.github/ISSUE_TEMPLATE/blank_issue.md
@@ -2,3 +2,17 @@
 name: Blank Issue
 about: Create a blank issue.
 ---
+
+
+<!--
+Additional labels can be added to this issue by including the following command
+(without the space after the @ symbol):
+
+`@rustbot label +<label>`
+
+Common labels for this issue type are:
+* C-an-interesting-project
+* C-enhancement
+* C-question
+* C-tracking-issue
+-->
diff --git a/src/tools/clippy/.github/ISSUE_TEMPLATE/bug_report.md b/src/tools/clippy/.github/ISSUE_TEMPLATE/bug_report.md
index 2bc87db123d..87c18cdee66 100644
--- a/src/tools/clippy/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/src/tools/clippy/.github/ISSUE_TEMPLATE/bug_report.md
@@ -20,28 +20,24 @@ Instead, this happened: *explanation*
 
 ### Meta
 
-- `cargo clippy -V`: e.g. clippy 0.0.212 (f455e46 2020-06-20)
-- `rustc -Vv`:
-  ```
-  rustc 1.46.0-nightly (f455e46ea 2020-06-20)
-  binary: rustc
-  commit-hash: f455e46eae1a227d735091091144601b467e1565
-  commit-date: 2020-06-20
-  host: x86_64-unknown-linux-gnu
-  release: 1.46.0-nightly
-  LLVM version: 10.0
-  ```
+**Rust version (`rustc -Vv`):**
+
+```
+rustc 1.46.0-nightly (f455e46ea 2020-06-20)
+binary: rustc
+commit-hash: f455e46eae1a227d735091091144601b467e1565
+commit-date: 2020-06-20
+host: x86_64-unknown-linux-gnu
+release: 1.46.0-nightly
+LLVM version: 10.0
+```
 
 <!--
-Include a backtrace in the code block by setting `RUST_BACKTRACE=1` in your
-environment. E.g. `RUST_BACKTRACE=1 cargo clippy`.
+Additional labels can be added to this issue by including the following command
+(without the space after the @ symbol):
+
+`@rustbot label +<label>`
+
+Common labels for this issue type are:
+* `I-suggestion-causes-error`
 -->
-<details><summary>Backtrace</summary>
-  <p>
-  
-  ```
-  <backtrace>
-  ```
-  
-  </p>
-</details>
diff --git a/src/tools/clippy/.github/ISSUE_TEMPLATE/false_negative.md b/src/tools/clippy/.github/ISSUE_TEMPLATE/false_negative.md
index 53341c7a928..d9ea2db34ed 100644
--- a/src/tools/clippy/.github/ISSUE_TEMPLATE/false_negative.md
+++ b/src/tools/clippy/.github/ISSUE_TEMPLATE/false_negative.md
@@ -22,14 +22,14 @@ Instead, this happened: *explanation*
 
 ### Meta
 
-- `cargo clippy -V`: e.g. clippy 0.0.212 (f455e46 2020-06-20)
-- `rustc -Vv`:
-  ```
-  rustc 1.46.0-nightly (f455e46ea 2020-06-20)
-  binary: rustc
-  commit-hash: f455e46eae1a227d735091091144601b467e1565
-  commit-date: 2020-06-20
-  host: x86_64-unknown-linux-gnu
-  release: 1.46.0-nightly
-  LLVM version: 10.0
-  ```
+**Rust version (`rustc -Vv`):**
+
+```
+rustc 1.46.0-nightly (f455e46ea 2020-06-20)
+binary: rustc
+commit-hash: f455e46eae1a227d735091091144601b467e1565
+commit-date: 2020-06-20
+host: x86_64-unknown-linux-gnu
+release: 1.46.0-nightly
+LLVM version: 10.0
+```
diff --git a/src/tools/clippy/.github/ISSUE_TEMPLATE/false_positive.md b/src/tools/clippy/.github/ISSUE_TEMPLATE/false_positive.md
index 34fd6f4bdb7..4170b9ff2db 100644
--- a/src/tools/clippy/.github/ISSUE_TEMPLATE/false_positive.md
+++ b/src/tools/clippy/.github/ISSUE_TEMPLATE/false_positive.md
@@ -22,14 +22,23 @@ Instead, this happened: *explanation*
 
 ### Meta
 
-- `cargo clippy -V`: e.g. clippy 0.0.212 (f455e46 2020-06-20)
-- `rustc -Vv`:
-  ```
-  rustc 1.46.0-nightly (f455e46ea 2020-06-20)
-  binary: rustc
-  commit-hash: f455e46eae1a227d735091091144601b467e1565
-  commit-date: 2020-06-20
-  host: x86_64-unknown-linux-gnu
-  release: 1.46.0-nightly
-  LLVM version: 10.0
-  ```
+**Rust version (`rustc -Vv`):**
+```
+rustc 1.46.0-nightly (f455e46ea 2020-06-20)
+binary: rustc
+commit-hash: f455e46eae1a227d735091091144601b467e1565
+commit-date: 2020-06-20
+host: x86_64-unknown-linux-gnu
+release: 1.46.0-nightly
+LLVM version: 10.0
+```
+
+<!--
+Additional labels can be added to this issue by including the following command
+(without the space after the @ symbol):
+
+`@rustbot label +<label>`
+
+Common labels for this issue type are:
+* I-suggestion-causes-error
+-->
diff --git a/src/tools/clippy/.github/ISSUE_TEMPLATE/ice.md b/src/tools/clippy/.github/ISSUE_TEMPLATE/ice.md
index 0b7cd1ed0fb..6c1bed663c6 100644
--- a/src/tools/clippy/.github/ISSUE_TEMPLATE/ice.md
+++ b/src/tools/clippy/.github/ISSUE_TEMPLATE/ice.md
@@ -20,17 +20,16 @@ http://blog.pnkfx.org/blog/2019/11/18/rust-bug-minimization-patterns/
 
 ### Meta
 
-- `cargo clippy -V`: e.g. clippy 0.0.212 (f455e46 2020-06-20)
-- `rustc -Vv`:
-  ```
-  rustc 1.46.0-nightly (f455e46ea 2020-06-20)
-  binary: rustc
-  commit-hash: f455e46eae1a227d735091091144601b467e1565
-  commit-date: 2020-06-20
-  host: x86_64-unknown-linux-gnu
-  release: 1.46.0-nightly
-  LLVM version: 10.0
-  ```
+**Rust version (`rustc -Vv`):**
+```
+rustc 1.46.0-nightly (f455e46ea 2020-06-20)
+binary: rustc
+commit-hash: f455e46eae1a227d735091091144601b467e1565
+commit-date: 2020-06-20
+host: x86_64-unknown-linux-gnu
+release: 1.46.0-nightly
+LLVM version: 10.0
+```
 
 ### Error output
 
diff --git a/src/tools/clippy/.github/workflows/clippy_dev.yml b/src/tools/clippy/.github/workflows/clippy_dev.yml
index 95da775b7bc..9a5416153ab 100644
--- a/src/tools/clippy/.github/workflows/clippy_dev.yml
+++ b/src/tools/clippy/.github/workflows/clippy_dev.yml
@@ -42,9 +42,6 @@ jobs:
       run: cargo build --features deny-warnings
       working-directory: clippy_dev
 
-    - name: Test limit_stderr_length
-      run: cargo dev limit_stderr_length
-
     - name: Test update_lints
       run: cargo dev update_lints --check
 
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 2b89170073b..f5ac2f7c9f8 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -964,7 +964,7 @@ Released 2020-11-19
   [#5907](https://github.com/rust-lang/rust-clippy/pull/5907)
 * [`suspicious_arithmetic_impl`]: extend to implementations of `BitAnd`, `BitOr`, `BitXor`, `Rem`, `Shl`, and `Shr`
   [#5884](https://github.com/rust-lang/rust-clippy/pull/5884)
-* [`invalid_atomic_ordering`]: detect misuse of `compare_exchange`, `compare_exchange_weak`, and `fetch_update`
+* `invalid_atomic_ordering`: detect misuse of `compare_exchange`, `compare_exchange_weak`, and `fetch_update`
   [#6025](https://github.com/rust-lang/rust-clippy/pull/6025)
 * Avoid [`redundant_pattern_matching`] triggering in macros
   [#6069](https://github.com/rust-lang/rust-clippy/pull/6069)
@@ -1451,7 +1451,7 @@ Released 2020-03-12
 * [`option_as_ref_deref`] [#4945](https://github.com/rust-lang/rust-clippy/pull/4945)
 * [`wildcard_in_or_patterns`] [#4960](https://github.com/rust-lang/rust-clippy/pull/4960)
 * [`iter_nth_zero`] [#4966](https://github.com/rust-lang/rust-clippy/pull/4966)
-* [`invalid_atomic_ordering`] [#4999](https://github.com/rust-lang/rust-clippy/pull/4999)
+* `invalid_atomic_ordering` [#4999](https://github.com/rust-lang/rust-clippy/pull/4999)
 * [`skip_while_next`] [#5067](https://github.com/rust-lang/rust-clippy/pull/5067)
 
 ### Moves and Deprecations
@@ -2613,6 +2613,7 @@ Released 2018-09-13
 [`deprecated_cfg_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr
 [`deprecated_semver`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_semver
 [`deref_addrof`]: https://rust-lang.github.io/rust-clippy/master/index.html#deref_addrof
+[`derivable_impls`]: https://rust-lang.github.io/rust-clippy/master/index.html#derivable_impls
 [`derive_hash_xor_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_hash_xor_eq
 [`derive_ord_xor_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_ord_xor_partial_ord
 [`disallowed_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_method
@@ -2712,7 +2713,6 @@ Released 2018-09-13
 [`integer_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_arithmetic
 [`integer_division`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division
 [`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref
-[`invalid_atomic_ordering`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_atomic_ordering
 [`invalid_null_ptr_usage`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_null_ptr_usage
 [`invalid_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_regex
 [`invalid_upcast_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons
@@ -2754,6 +2754,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_split_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once
 [`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
@@ -2795,6 +2796,7 @@ Released 2018-09-13
 [`missing_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc
 [`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes
 [`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals
+[`mod_module_files`]: https://rust-lang.github.io/rust-clippy/master/index.html#mod_module_files
 [`module_inception`]: https://rust-lang.github.io/rust-clippy/master/index.html#module_inception
 [`module_name_repetitions`]: https://rust-lang.github.io/rust-clippy/master/index.html#module_name_repetitions
 [`modulo_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#modulo_arithmetic
@@ -2821,6 +2823,7 @@ Released 2018-09-13
 [`needless_doctest_main`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_doctest_main
 [`needless_for_each`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_for_each
 [`needless_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_lifetimes
+[`needless_option_as_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_option_as_deref
 [`needless_pass_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value
 [`needless_question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_question_mark
 [`needless_range_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_range_loop
@@ -2828,6 +2831,7 @@ Released 2018-09-13
 [`needless_update`]: https://rust-lang.github.io/rust-clippy/master/index.html#needless_update
 [`neg_cmp_op_on_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#neg_cmp_op_on_partial_ord
 [`neg_multiply`]: https://rust-lang.github.io/rust-clippy/master/index.html#neg_multiply
+[`negative_feature_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#negative_feature_names
 [`never_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#never_loop
 [`new_ret_no_self`]: https://rust-lang.github.io/rust-clippy/master/index.html#new_ret_no_self
 [`new_without_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#new_without_default
@@ -2881,6 +2885,7 @@ Released 2018-09-13
 [`redundant_closure_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_call
 [`redundant_closure_for_method_calls`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_for_method_calls
 [`redundant_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_else
+[`redundant_feature_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_feature_names
 [`redundant_field_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_field_names
 [`redundant_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern
 [`redundant_pattern_matching`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_pattern_matching
@@ -2903,6 +2908,7 @@ Released 2018-09-13
 [`search_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#search_is_some
 [`self_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_assignment
 [`self_named_constructors`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_constructors
+[`self_named_module_files`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_module_files
 [`semicolon_if_nothing_returned`]: https://rust-lang.github.io/rust-clippy/master/index.html#semicolon_if_nothing_returned
 [`serde_api_misuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#serde_api_misuse
 [`shadow_reuse`]: https://rust-lang.github.io/rust-clippy/master/index.html#shadow_reuse
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index 16b6c207a5f..40aaa5924df 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy"
-version = "0.1.56"
+version = "0.1.57"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
@@ -21,32 +21,35 @@ name = "clippy-driver"
 path = "src/driver.rs"
 
 [dependencies]
-# begin automatic update
-clippy_lints = { version = "0.1.50", path = "clippy_lints" }
-# end automatic update
+clippy_lints = { version = "0.1", path = "clippy_lints" }
 semver = "0.11"
-rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util" }
-tempfile = { version = "3.1.0", optional = true }
+rustc_tools_util = { version = "0.2", path = "rustc_tools_util" }
+tempfile = { version = "3.2", optional = true }
 
 [dev-dependencies]
 cargo_metadata = "0.12"
-compiletest_rs = { version = "0.6.0", features = ["tmp"] }
+compiletest_rs = { version = "0.7", features = ["tmp"] }
 tester = "0.9"
-serde = { version = "1.0", features = ["derive"] }
-derive-new = "0.5"
-regex = "1.4"
-quote = "1"
-syn = { version = "1", features = ["full"] }
+regex = "1.5"
 # 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`
 # for more information.
-rustc-workspace-hack = "1.0.0"
+rustc-workspace-hack = "1.0"
+
+# UI test dependencies
+clippy_utils = { path = "clippy_utils" }
+derive-new = "0.5"
+if_chain = "1.0"
+itertools = "0.10"
+quote = "1.0"
+serde = { version = "1.0", features = ["derive"] }
+syn = { version = "1.0", features = ["full"] }
 
 [build-dependencies]
-rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util" }
+rustc_tools_util = { version = "0.2", path = "rustc_tools_util" }
 
 [features]
 deny-warnings = ["clippy_lints/deny-warnings"]
diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md
index e1c968273cd..aaf404eadea 100644
--- a/src/tools/clippy/README.md
+++ b/src/tools/clippy/README.md
@@ -45,13 +45,13 @@ or in Travis CI.
 One way to use Clippy is by installing Clippy through rustup as a cargo
 subcommand.
 
-#### Step 1: Install rustup
+#### Step 1: Install Rustup
 
-You can install [rustup](https://rustup.rs/) on supported platforms. This will help
+You can install [Rustup](https://rustup.rs/) on supported platforms. This will help
 us install Clippy and its dependencies.
 
-If you already have rustup installed, update to ensure you have the latest
-rustup and compiler:
+If you already have Rustup installed, update to ensure you have the latest
+Rustup and compiler:
 
 ```terminal
 rustup update
diff --git a/src/tools/clippy/clippy_dev/Cargo.toml b/src/tools/clippy/clippy_dev/Cargo.toml
index 0fae8c7b9af..d7d2655026b 100644
--- a/src/tools/clippy/clippy_dev/Cargo.toml
+++ b/src/tools/clippy/clippy_dev/Cargo.toml
@@ -6,11 +6,11 @@ edition = "2018"
 [dependencies]
 bytecount = "0.6"
 clap = "2.33"
-itertools = "0.9"
+itertools = "0.10"
 opener = "0.5"
-regex = "1"
+regex = "1.5"
 shell-escape = "0.1"
-walkdir = "2"
+walkdir = "2.3"
 
 [features]
 deny-warnings = []
diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs
index 72bdaf8d592..e05db7af586 100644
--- a/src/tools/clippy/clippy_dev/src/lib.rs
+++ b/src/tools/clippy/clippy_dev/src/lib.rs
@@ -17,7 +17,6 @@ pub mod fmt;
 pub mod new_lint;
 pub mod serve;
 pub mod setup;
-pub mod stderr_length_check;
 pub mod update_lints;
 
 static DEC_CLIPPY_LINT_RE: SyncLazy<Regex> = SyncLazy::new(|| {
diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs
index ff324ff6ee6..8fdeba9842a 100644
--- a/src/tools/clippy/clippy_dev/src/main.rs
+++ b/src/tools/clippy/clippy_dev/src/main.rs
@@ -3,7 +3,7 @@
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
 use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
-use clippy_dev::{bless, fmt, new_lint, serve, setup, stderr_length_check, update_lints};
+use clippy_dev::{bless, fmt, new_lint, serve, setup, update_lints};
 fn main() {
     let matches = get_clap_config();
 
@@ -33,9 +33,6 @@ fn main() {
                 Err(e) => eprintln!("Unable to create lint: {}", e),
             }
         },
-        ("limit_stderr_length", _) => {
-            stderr_length_check::check();
-        },
         ("setup", Some(sub_command)) => match sub_command.subcommand() {
             ("intellij", Some(matches)) => setup::intellij::setup_rustc_src(
                 matches
@@ -153,10 +150,6 @@ fn get_clap_config<'a>() -> ArgMatches<'a> {
                 ),
         )
         .subcommand(
-            SubCommand::with_name("limit_stderr_length")
-                .about("Ensures that stderr files do not grow longer than a certain amount of lines."),
-        )
-        .subcommand(
             SubCommand::with_name("setup")
                 .about("Support for setting up your personal development environment")
                 .setting(AppSettings::ArgRequiredElseHelp)
diff --git a/src/tools/clippy/clippy_dev/src/stderr_length_check.rs b/src/tools/clippy/clippy_dev/src/stderr_length_check.rs
deleted file mode 100644
index e02b6f7da5f..00000000000
--- a/src/tools/clippy/clippy_dev/src/stderr_length_check.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-use crate::clippy_project_root;
-use std::ffi::OsStr;
-use std::fs;
-use std::path::{Path, PathBuf};
-use walkdir::WalkDir;
-
-// The maximum length allowed for stderr files.
-//
-// We limit this because small files are easier to deal with than bigger files.
-const LENGTH_LIMIT: usize = 200;
-
-pub fn check() {
-    let exceeding_files: Vec<_> = exceeding_stderr_files();
-
-    if !exceeding_files.is_empty() {
-        eprintln!("Error: stderr files exceeding limit of {} lines:", LENGTH_LIMIT);
-        for (path, count) in exceeding_files {
-            println!("{}: {}", path.display(), count);
-        }
-        std::process::exit(1);
-    }
-}
-
-fn exceeding_stderr_files() -> Vec<(PathBuf, usize)> {
-    // We use `WalkDir` instead of `fs::read_dir` here in order to recurse into subdirectories.
-    WalkDir::new(clippy_project_root().join("tests/ui"))
-        .into_iter()
-        .filter_map(Result::ok)
-        .filter(|f| !f.file_type().is_dir())
-        .filter_map(|e| {
-            let p = e.into_path();
-            let count = count_linenumbers(&p);
-            if p.extension() == Some(OsStr::new("stderr")) && count > LENGTH_LIMIT {
-                Some((p, count))
-            } else {
-                None
-            }
-        })
-        .collect()
-}
-
-#[must_use]
-fn count_linenumbers(filepath: &Path) -> usize {
-    match fs::read(filepath) {
-        Ok(content) => bytecount::count(&content, b'\n'),
-        Err(e) => {
-            eprintln!("Failed to read file: {}", e);
-            0
-        },
-    }
-}
diff --git a/src/tools/clippy/clippy_dummy/Cargo.toml b/src/tools/clippy/clippy_dummy/Cargo.toml
index a1707bad5c2..c206a1eb07b 100644
--- a/src/tools/clippy/clippy_dummy/Cargo.toml
+++ b/src/tools/clippy/clippy_dummy/Cargo.toml
@@ -13,4 +13,4 @@ keywords = ["clippy", "lint", "plugin"]
 categories = ["development-tools", "development-tools::cargo-plugins"]
 
 [build-dependencies]
-term = "0.6"
+term = "0.7"
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index a3b92e1faa1..e59175a55e1 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -1,8 +1,6 @@
 [package]
 name = "clippy_lints"
-# begin automatic update
-version = "0.1.56"
-# end automatic update
+version = "0.1.57"
 description = "A bunch of helpful lints to avoid common pitfalls in Rust"
 repository = "https://github.com/rust-lang/rust-clippy"
 readme = "README.md"
@@ -13,21 +11,21 @@ edition = "2018"
 [dependencies]
 cargo_metadata = "0.12"
 clippy_utils = { path = "../clippy_utils" }
-if_chain = "1.0.0"
-itertools = "0.9"
+if_chain = "1.0"
+itertools = "0.10"
 pulldown-cmark = { version = "0.8", default-features = false }
-quine-mc_cluskey = "0.2.2"
+quine-mc_cluskey = "0.2"
 regex-syntax = "0.6"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = { version = "1.0", optional = true }
-toml = "0.5.3"
+toml = "0.5"
 unicode-normalization = "0.1"
-unicode-script = { version = "0.5.3", default-features = false }
+unicode-script = { version = "0.5", default-features = false }
 semver = "0.11"
-rustc-semver = "1.1.0"
+rustc-semver = "1.1"
 # NOTE: cargo requires serde feat in its url dep
 # see <https://github.com/rust-lang/rust/pull/63587#issuecomment-522343864>
-url = { version = "2.1.0", features = ["serde"] }
+url = { version = "2.2", features = ["serde"] }
 
 [features]
 deny-warnings = ["clippy_utils/deny-warnings"]
diff --git a/src/tools/clippy/clippy_lints/src/approx_const.rs b/src/tools/clippy/clippy_lints/src/approx_const.rs
index 6100f4e435a..fb54ac1ec51 100644
--- a/src/tools/clippy/clippy_lints/src/approx_const.rs
+++ b/src/tools/clippy/clippy_lints/src/approx_const.rs
@@ -1,8 +1,10 @@
-use clippy_utils::diagnostics::span_lint;
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::{meets_msrv, msrvs};
 use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
 use rustc_hir::{Expr, ExprKind};
-use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_semver::RustcVersion;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol;
 use std::f64::consts as f64;
 
@@ -36,68 +38,82 @@ declare_clippy_lint! {
     "the approximate of a known float constant (in `std::fXX::consts`)"
 }
 
-// Tuples are of the form (constant, name, min_digits)
-const KNOWN_CONSTS: [(f64, &str, usize); 18] = [
-    (f64::E, "E", 4),
-    (f64::FRAC_1_PI, "FRAC_1_PI", 4),
-    (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2", 5),
-    (f64::FRAC_2_PI, "FRAC_2_PI", 5),
-    (f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI", 5),
-    (f64::FRAC_PI_2, "FRAC_PI_2", 5),
-    (f64::FRAC_PI_3, "FRAC_PI_3", 5),
-    (f64::FRAC_PI_4, "FRAC_PI_4", 5),
-    (f64::FRAC_PI_6, "FRAC_PI_6", 5),
-    (f64::FRAC_PI_8, "FRAC_PI_8", 5),
-    (f64::LN_10, "LN_10", 5),
-    (f64::LN_2, "LN_2", 5),
-    (f64::LOG10_E, "LOG10_E", 5),
-    (f64::LOG2_E, "LOG2_E", 5),
-    (f64::LOG2_10, "LOG2_10", 5),
-    (f64::LOG10_2, "LOG10_2", 5),
-    (f64::PI, "PI", 3),
-    (f64::SQRT_2, "SQRT_2", 5),
+// Tuples are of the form (constant, name, min_digits, msrv)
+const KNOWN_CONSTS: [(f64, &str, usize, Option<RustcVersion>); 19] = [
+    (f64::E, "E", 4, None),
+    (f64::FRAC_1_PI, "FRAC_1_PI", 4, None),
+    (f64::FRAC_1_SQRT_2, "FRAC_1_SQRT_2", 5, None),
+    (f64::FRAC_2_PI, "FRAC_2_PI", 5, None),
+    (f64::FRAC_2_SQRT_PI, "FRAC_2_SQRT_PI", 5, None),
+    (f64::FRAC_PI_2, "FRAC_PI_2", 5, None),
+    (f64::FRAC_PI_3, "FRAC_PI_3", 5, None),
+    (f64::FRAC_PI_4, "FRAC_PI_4", 5, None),
+    (f64::FRAC_PI_6, "FRAC_PI_6", 5, None),
+    (f64::FRAC_PI_8, "FRAC_PI_8", 5, None),
+    (f64::LN_2, "LN_2", 5, None),
+    (f64::LN_10, "LN_10", 5, None),
+    (f64::LOG2_10, "LOG2_10", 5, Some(msrvs::LOG2_10)),
+    (f64::LOG2_E, "LOG2_E", 5, None),
+    (f64::LOG10_2, "LOG10_2", 5, Some(msrvs::LOG10_2)),
+    (f64::LOG10_E, "LOG10_E", 5, None),
+    (f64::PI, "PI", 3, None),
+    (f64::SQRT_2, "SQRT_2", 5, None),
+    (f64::TAU, "TAU", 3, Some(msrvs::TAU)),
 ];
 
-declare_lint_pass!(ApproxConstant => [APPROX_CONSTANT]);
+pub struct ApproxConstant {
+    msrv: Option<RustcVersion>,
+}
 
-impl<'tcx> LateLintPass<'tcx> for ApproxConstant {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
-        if let ExprKind::Lit(lit) = &e.kind {
-            check_lit(cx, &lit.node, e);
+impl ApproxConstant {
+    #[must_use]
+    pub fn new(msrv: Option<RustcVersion>) -> Self {
+        Self { msrv }
+    }
+
+    fn check_lit(&self, cx: &LateContext<'_>, lit: &LitKind, e: &Expr<'_>) {
+        match *lit {
+            LitKind::Float(s, LitFloatType::Suffixed(fty)) => match fty {
+                FloatTy::F32 => self.check_known_consts(cx, e, s, "f32"),
+                FloatTy::F64 => self.check_known_consts(cx, e, s, "f64"),
+            },
+            LitKind::Float(s, LitFloatType::Unsuffixed) => self.check_known_consts(cx, e, s, "f{32, 64}"),
+            _ => (),
         }
     }
-}
 
-fn check_lit(cx: &LateContext<'_>, lit: &LitKind, e: &Expr<'_>) {
-    match *lit {
-        LitKind::Float(s, LitFloatType::Suffixed(fty)) => match fty {
-            FloatTy::F32 => check_known_consts(cx, e, s, "f32"),
-            FloatTy::F64 => check_known_consts(cx, e, s, "f64"),
-        },
-        LitKind::Float(s, LitFloatType::Unsuffixed) => check_known_consts(cx, e, s, "f{32, 64}"),
-        _ => (),
+    fn check_known_consts(&self, cx: &LateContext<'_>, e: &Expr<'_>, s: symbol::Symbol, module: &str) {
+        let s = s.as_str();
+        if s.parse::<f64>().is_ok() {
+            for &(constant, name, min_digits, msrv) in &KNOWN_CONSTS {
+                if is_approx_const(constant, &s, min_digits)
+                    && msrv.as_ref().map_or(true, |msrv| meets_msrv(self.msrv.as_ref(), msrv))
+                {
+                    span_lint_and_help(
+                        cx,
+                        APPROX_CONSTANT,
+                        e.span,
+                        &format!("approximate value of `{}::consts::{}` found", module, &name),
+                        None,
+                        "consider using the constant directly",
+                    );
+                    return;
+                }
+            }
+        }
     }
 }
 
-fn check_known_consts(cx: &LateContext<'_>, e: &Expr<'_>, s: symbol::Symbol, module: &str) {
-    let s = s.as_str();
-    if s.parse::<f64>().is_ok() {
-        for &(constant, name, min_digits) in &KNOWN_CONSTS {
-            if is_approx_const(constant, &s, min_digits) {
-                span_lint(
-                    cx,
-                    APPROX_CONSTANT,
-                    e.span,
-                    &format!(
-                        "approximate value of `{}::consts::{}` found. \
-                         Consider using it directly",
-                        module, &name
-                    ),
-                );
-                return;
-            }
+impl_lint_pass!(ApproxConstant => [APPROX_CONSTANT]);
+
+impl<'tcx> LateLintPass<'tcx> for ApproxConstant {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
+        if let ExprKind::Lit(lit) = &e.kind {
+            self.check_lit(cx, &lit.node, e);
         }
     }
+
+    extract_msrv_attr!(LateContext);
 }
 
 /// Returns `false` if the number of significant figures in `value` are
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 891e865b245..d834a1d317a 100644
--- a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
+++ b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
@@ -118,7 +118,7 @@ enum AssertKind {
 fn match_assert_with_message<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<AssertKind> {
     if_chain! {
         if let Some(higher::If { cond, then, .. }) = higher::If::hir(expr);
-        if let ExprKind::Unary(UnOp::Not, ref expr) = cond.kind;
+        if let ExprKind::Unary(UnOp::Not, expr) = cond.kind;
         // bind the first argument of the `assert!` macro
         if let Some((Constant::Bool(is_true), _)) = constant(cx, cx.typeck_results(), expr);
         // block
diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs
index c9ff468874b..2ef7dcc1775 100644
--- a/src/tools/clippy/clippy_lints/src/attrs.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs.rs
@@ -527,8 +527,8 @@ fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::It
                 return;
             }
 
-            let begin_of_attr_to_item = Span::new(attr.span.lo(), item.span.lo(), item.span.ctxt());
-            let end_of_attr_to_item = Span::new(attr.span.hi(), item.span.lo(), item.span.ctxt());
+            let begin_of_attr_to_item = Span::new(attr.span.lo(), item.span.lo(), item.span.ctxt(), item.span.parent());
+            let end_of_attr_to_item = Span::new(attr.span.hi(), item.span.lo(), item.span.ctxt(), item.span.parent());
 
             if let Some(snippet) = snippet_opt(cx, end_of_attr_to_item) {
                 let lines = snippet.split('\n').collect::<Vec<_>>();
diff --git a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
index 51d95cc6f0b..47e5b0d583d 100644
--- a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
+++ b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
@@ -61,8 +61,8 @@ impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> {
             // do not lint if the closure is called using an iterator (see #1141)
             if_chain! {
                 if let Some(parent) = get_parent_expr(self.cx, expr);
-                if let ExprKind::MethodCall(_, _, args, _) = parent.kind;
-                let caller = self.cx.typeck_results().expr_ty(&args[0]);
+                if let ExprKind::MethodCall(_, _, [self_arg, ..], _) = &parent.kind;
+                let caller = self.cx.typeck_results().expr_ty(self_arg);
                 if let Some(iter_id) = self.cx.tcx.get_diagnostic_item(sym::Iterator);
                 if implements_trait(self.cx, caller, iter_id, &[]);
                 then {
diff --git a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
index 8d3f68565b2..cdc192a47e4 100644
--- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
+++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
@@ -1,9 +1,11 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::{ast_utils, is_direct_expn_of};
-use rustc_ast::ast::{Expr, ExprKind, Lit, LitKind};
+use clippy_utils::{diagnostics::span_lint_and_sugg, higher, is_direct_expn_of, ty::implements_trait};
+use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
-use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_hir::{Expr, ExprKind, Lit};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::symbol::Ident;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -28,45 +30,77 @@ declare_clippy_lint! {
 
 declare_lint_pass!(BoolAssertComparison => [BOOL_ASSERT_COMPARISON]);
 
-fn is_bool_lit(e: &Expr) -> bool {
+fn is_bool_lit(e: &Expr<'_>) -> bool {
     matches!(
         e.kind,
         ExprKind::Lit(Lit {
-            kind: LitKind::Bool(_),
+            node: LitKind::Bool(_),
             ..
         })
     ) && !e.span.from_expansion()
 }
 
-impl EarlyLintPass for BoolAssertComparison {
-    fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) {
+fn is_impl_not_trait_with_bool_out(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> bool {
+    let ty = cx.typeck_results().expr_ty(e);
+
+    cx.tcx
+        .lang_items()
+        .not_trait()
+        .filter(|trait_id| implements_trait(cx, ty, *trait_id, &[]))
+        .and_then(|trait_id| {
+            cx.tcx.associated_items(trait_id).find_by_name_and_kind(
+                cx.tcx,
+                Ident::from_str("Output"),
+                ty::AssocKind::Type,
+                trait_id,
+            )
+        })
+        .map_or(false, |assoc_item| {
+            let proj = cx.tcx.mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(ty, &[]));
+            let nty = cx.tcx.normalize_erasing_regions(cx.param_env, proj);
+
+            nty.is_bool()
+        })
+}
+
+impl<'tcx> LateLintPass<'tcx> for BoolAssertComparison {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         let macros = ["assert_eq", "debug_assert_eq"];
         let inverted_macros = ["assert_ne", "debug_assert_ne"];
 
         for mac in macros.iter().chain(inverted_macros.iter()) {
-            if let Some(span) = is_direct_expn_of(e.span, mac) {
-                if let Some([a, b]) = ast_utils::extract_assert_macro_args(e) {
-                    let nb_bool_args = is_bool_lit(a) as usize + is_bool_lit(b) as usize;
+            if let Some(span) = is_direct_expn_of(expr.span, mac) {
+                if let Some(args) = higher::extract_assert_macro_args(expr) {
+                    if let [a, b, ..] = args[..] {
+                        let nb_bool_args = is_bool_lit(a) as usize + is_bool_lit(b) as usize;
+
+                        if nb_bool_args != 1 {
+                            // If there are two boolean arguments, we definitely don't understand
+                            // what's going on, so better leave things as is...
+                            //
+                            // Or there is simply no boolean and then we can leave things as is!
+                            return;
+                        }
 
-                    if nb_bool_args != 1 {
-                        // If there are two boolean arguments, we definitely don't understand
-                        // what's going on, so better leave things as is...
-                        //
-                        // Or there is simply no boolean and then we can leave things as is!
+                        if !is_impl_not_trait_with_bool_out(cx, a) || !is_impl_not_trait_with_bool_out(cx, b) {
+                            // At this point the expression which is not a boolean
+                            // literal does not implement Not trait with a bool output,
+                            // so we cannot suggest to rewrite our code
+                            return;
+                        }
+
+                        let non_eq_mac = &mac[..mac.len() - 3];
+                        span_lint_and_sugg(
+                            cx,
+                            BOOL_ASSERT_COMPARISON,
+                            span,
+                            &format!("used `{}!` with a literal bool", mac),
+                            "replace it with",
+                            format!("{}!(..)", non_eq_mac),
+                            Applicability::MaybeIncorrect,
+                        );
                         return;
                     }
-
-                    let non_eq_mac = &mac[..mac.len() - 3];
-                    span_lint_and_sugg(
-                        cx,
-                        BOOL_ASSERT_COMPARISON,
-                        span,
-                        &format!("used `{}!` with a literal bool", mac),
-                        "replace it with",
-                        format!("{}!(..)", non_eq_mac),
-                        Applicability::MaybeIncorrect,
-                    );
-                    return;
                 }
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/bytecount.rs b/src/tools/clippy/clippy_lints/src/bytecount.rs
index c444984bc13..a07cd5e5f4e 100644
--- a/src/tools/clippy/clippy_lints/src/bytecount.rs
+++ b/src/tools/clippy/clippy_lints/src/bytecount.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::match_type;
-use clippy_utils::visitors::LocalUsedVisitor;
+use clippy_utils::visitors::is_local_used;
 use clippy_utils::{path_to_local_id, paths, peel_ref_operators, remove_blocks, strip_pat_refs};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
@@ -65,7 +65,7 @@ impl<'tcx> LateLintPass<'tcx> for ByteCount {
                 return;
             };
             if ty::Uint(UintTy::U8) == *cx.typeck_results().expr_ty(needle).peel_refs().kind();
-            if !LocalUsedVisitor::new(cx, arg_id).check_expr(needle);
+            if !is_local_used(cx, needle, arg_id);
             then {
                 let haystack = if let ExprKind::MethodCall(path, _, args, _) =
                         filter_recv.kind {
diff --git a/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs b/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs
index bd5426ba707..162911b77d6 100644
--- a/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs
+++ b/src/tools/clippy/clippy_lints/src/cargo_common_metadata.rs
@@ -1,7 +1,5 @@
 //! lint on missing cargo common metadata
 
-use std::path::PathBuf;
-
 use clippy_utils::{diagnostics::span_lint, is_lint_allowed};
 use rustc_hir::{hir_id::CRATE_HIR_ID, Crate};
 use rustc_lint::{LateContext, LateLintPass};
@@ -69,12 +67,8 @@ fn missing_warning(cx: &LateContext<'_>, package: &cargo_metadata::Package, fiel
     span_lint(cx, CARGO_COMMON_METADATA, DUMMY_SP, &message);
 }
 
-fn is_empty_str(value: &Option<String>) -> bool {
-    value.as_ref().map_or(true, String::is_empty)
-}
-
-fn is_empty_path(value: &Option<PathBuf>) -> bool {
-    value.as_ref().and_then(|x| x.to_str()).map_or(true, str::is_empty)
+fn is_empty_str<T: AsRef<std::ffi::OsStr>>(value: &Option<T>) -> bool {
+    value.as_ref().map_or(true, |s| s.as_ref().is_empty())
 }
 
 fn is_empty_vec(value: &[String]) -> bool {
@@ -98,7 +92,7 @@ impl LateLintPass<'_> for CargoCommonMetadata {
                     missing_warning(cx, &package, "package.description");
                 }
 
-                if is_empty_str(&package.license) && is_empty_path(&package.license_file) {
+                if is_empty_str(&package.license) && is_empty_str(&package.license_file) {
                     missing_warning(cx, &package, "either package.license or package.license_file");
                 }
 
@@ -106,7 +100,7 @@ impl LateLintPass<'_> for CargoCommonMetadata {
                     missing_warning(cx, &package, "package.repository");
                 }
 
-                if is_empty_path(&package.readme) {
+                if is_empty_str(&package.readme) {
                     missing_warning(cx, &package, "package.readme");
                 }
 
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
index 5dcf1824ef0..248b35b024e 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs
@@ -19,7 +19,7 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
             cx.typeck_results().expr_ty(expr),
         );
         lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
-    } else if let ExprKind::MethodCall(method_path, _, args, _) = expr.kind {
+    } else if let ExprKind::MethodCall(method_path, _, [self_arg, ..], _) = &expr.kind {
         if_chain! {
             if method_path.ident.name == sym!(cast);
             if let Some(generic_args) = method_path.args;
@@ -28,7 +28,7 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
             if !is_hir_ty_cfg_dependant(cx, cast_to);
             then {
                 let (cast_from, cast_to) =
-                    (cx.typeck_results().expr_ty(&args[0]), cx.typeck_results().expr_ty(expr));
+                    (cx.typeck_results().expr_ty(self_arg), cx.typeck_results().expr_ty(expr));
                 lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
index 96c30d57ee1..2203d1c39f1 100644
--- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
+++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
@@ -95,7 +95,7 @@ impl CognitiveComplexity {
                     });
 
                     if let Some((low, high)) = pos {
-                        Span::new(low, high, header_span.ctxt())
+                        Span::new(low, high, header_span.ctxt(), header_span.parent())
                     } else {
                         return;
                     }
diff --git a/src/tools/clippy/clippy_lints/src/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/collapsible_match.rs
index a42eee53459..a4693fa213b 100644
--- a/src/tools/clippy/clippy_lints/src/collapsible_match.rs
+++ b/src/tools/clippy/clippy_lints/src/collapsible_match.rs
@@ -1,9 +1,10 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::visitors::LocalUsedVisitor;
-use clippy_utils::{higher, is_lang_ctor, is_unit_expr, path_to_local, peel_ref_operators, SpanlessEq};
+use clippy_utils::higher::IfLetOrMatch;
+use clippy_utils::visitors::is_local_used;
+use clippy_utils::{is_lang_ctor, is_unit_expr, path_to_local, peel_ref_operators, SpanlessEq};
 use if_chain::if_chain;
 use rustc_hir::LangItem::OptionNone;
-use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, MatchSource, Pat, PatKind, StmtKind};
+use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{MultiSpan, Span};
@@ -56,11 +57,11 @@ impl<'tcx> LateLintPass<'tcx> for CollapsibleMatch {
                         check_arm(cx, true, arm.pat, arm.body, arm.guard.as_ref(), Some(els_arm.body));
                     }
                 }
-            }
+            },
             Some(IfLetOrMatch::IfLet(_, pat, body, els)) => {
                 check_arm(cx, false, pat, body, None, els);
-            }
-            None => {}
+            },
+            None => {},
         }
     }
 }
@@ -71,7 +72,7 @@ fn check_arm<'tcx>(
     outer_pat: &'tcx Pat<'tcx>,
     outer_then_body: &'tcx Expr<'tcx>,
     outer_guard: Option<&'tcx Guard<'tcx>>,
-    outer_else_body: Option<&'tcx Expr<'tcx>>
+    outer_else_body: Option<&'tcx Expr<'tcx>>,
 ) {
     let inner_expr = strip_singleton_blocks(outer_then_body);
     if_chain! {
@@ -106,14 +107,13 @@ fn check_arm<'tcx>(
             (Some(a), Some(b)) => SpanlessEq::new(cx).eq_expr(a, b),
         };
         // the binding must not be used in the if guard
-        let mut used_visitor = LocalUsedVisitor::new(cx, binding_id);
-        if outer_guard.map_or(true, |(Guard::If(e) | Guard::IfLet(_, e))| !used_visitor.check_expr(e));
+        if outer_guard.map_or(true, |(Guard::If(e) | Guard::IfLet(_, e))| !is_local_used(cx, *e, binding_id));
         // ...or anywhere in the inner expression
         if match inner {
             IfLetOrMatch::IfLet(_, _, body, els) => {
-                !used_visitor.check_expr(body) && els.map_or(true, |e| !used_visitor.check_expr(e))
+                !is_local_used(cx, body, binding_id) && els.map_or(true, |e| !is_local_used(cx, e, binding_id))
             },
-            IfLetOrMatch::Match(_, arms, ..) => !arms.iter().any(|arm| used_visitor.check_arm(arm)),
+            IfLetOrMatch::Match(_, arms, ..) => !arms.iter().any(|arm| is_local_used(cx, arm, binding_id)),
         };
         then {
             let msg = format!(
@@ -151,23 +151,6 @@ fn strip_singleton_blocks<'hir>(mut expr: &'hir Expr<'hir>) -> &'hir Expr<'hir>
     expr
 }
 
-enum IfLetOrMatch<'hir> {
-    Match(&'hir Expr<'hir>, &'hir [Arm<'hir>], MatchSource),
-    /// scrutinee, pattern, then block, else block
-    IfLet(&'hir Expr<'hir>, &'hir Pat<'hir>, &'hir Expr<'hir>, Option<&'hir Expr<'hir>>),
-}
-
-impl<'hir> IfLetOrMatch<'hir> {
-    fn parse(cx: &LateContext<'_>, expr: &Expr<'hir>) -> Option<Self> {
-        match expr.kind {
-            ExprKind::Match(expr, arms, source) => Some(Self::Match(expr, arms, source)),
-            _ => higher::IfLet::hir(cx, expr).map(|higher::IfLet { let_expr, let_pat, if_then, if_else }| {
-                Self::IfLet(let_expr, let_pat, if_then, if_else)
-            })
-        }
-    }
-}
-
 /// A "wild-like" arm has a wild (`_`) or `None` pattern and no guard. Such arms can be "collapsed"
 /// into a single wild arm without any significant loss in semantics or readability.
 fn arm_is_wild_like(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs
index 5eb99cfe24f..6ded2f233ef 100644
--- a/src/tools/clippy/clippy_lints/src/copies.rs
+++ b/src/tools/clippy/clippy_lints/src/copies.rs
@@ -148,7 +148,7 @@ declare_clippy_lint! {
     /// };
     /// ```
     pub BRANCHES_SHARING_CODE,
-    complexity,
+    nursery,
     "`if` statement with shared code in all blocks"
 }
 
@@ -472,7 +472,7 @@ fn emit_branches_sharing_code_lint(
 
         let mut span = moved_start.to(span_end);
         // Improve formatting if the inner block has indention (i.e. normal Rust formatting)
-        let test_span = Span::new(span.lo() - BytePos(4), span.lo(), span.ctxt());
+        let test_span = Span::new(span.lo() - BytePos(4), span.lo(), span.ctxt(), span.parent());
         if snippet_opt(cx, test_span)
             .map(|snip| snip == "    ")
             .unwrap_or_default()
diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
new file mode 100644
index 00000000000..b4c4ca016aa
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
@@ -0,0 +1,108 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::{in_macro, is_automatically_derived, is_default_equivalent, remove_blocks};
+use rustc_hir::{
+    def::{DefKind, Res},
+    Body, Expr, ExprKind, Impl, ImplItemKind, Item, ItemKind, Node, QPath,
+};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::TypeFoldable;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Detects manual `std::default::Default` implementations that are identical to a derived implementation.
+    ///
+    /// ### Why is this bad?
+    /// It is less concise.
+    ///
+    /// ### Example
+    /// ```rust
+    /// struct Foo {
+    ///     bar: bool
+    /// }
+    ///
+    /// impl std::default::Default for Foo {
+    ///     fn default() -> Self {
+    ///         Self {
+    ///             bar: false
+    ///         }
+    ///     }
+    /// }
+    /// ```
+    ///
+    /// Could be written as:
+    ///
+    /// ```rust
+    /// #[derive(Default)]
+    /// struct Foo {
+    ///     bar: bool
+    /// }
+    /// ```
+    ///
+    /// ### Known problems
+    /// Derive macros [sometimes use incorrect bounds](https://github.com/rust-lang/rust/issues/26925)
+    /// in generic types and the user defined `impl` maybe is more generalized or
+    /// specialized than what derive will produce. This lint can't detect the manual `impl`
+    /// has exactly equal bounds, and therefore this lint is disabled for types with
+    /// generic parameters.
+    ///
+    pub DERIVABLE_IMPLS,
+    complexity,
+    "manual implementation of the `Default` trait which is equal to a derive"
+}
+
+declare_lint_pass!(DerivableImpls => [DERIVABLE_IMPLS]);
+
+fn is_path_self(e: &Expr<'_>) -> bool {
+    if let ExprKind::Path(QPath::Resolved(_, p)) = e.kind {
+        matches!(p.res, Res::SelfCtor(..) | Res::Def(DefKind::Ctor(..), _))
+    } else {
+        false
+    }
+}
+
+impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
+        if_chain! {
+            if let ItemKind::Impl(Impl {
+                of_trait: Some(ref trait_ref),
+                items: [child],
+                ..
+            }) = item.kind;
+            if let attrs = cx.tcx.hir().attrs(item.hir_id());
+            if !is_automatically_derived(attrs);
+            if !in_macro(item.span);
+            if let Some(def_id) = trait_ref.trait_def_id();
+            if cx.tcx.is_diagnostic_item(sym::Default, def_id);
+            if let impl_item_hir = child.id.hir_id();
+            if let Some(Node::ImplItem(impl_item)) = cx.tcx.hir().find(impl_item_hir);
+            if let ImplItemKind::Fn(_, b) = &impl_item.kind;
+            if let Body { value: func_expr, .. } = cx.tcx.hir().body(*b);
+            if let Some(adt_def) = cx.tcx.type_of(item.def_id).ty_adt_def();
+            then {
+                if cx.tcx.type_of(item.def_id).definitely_has_param_types_or_consts(cx.tcx) {
+                    return;
+                }
+                let should_emit = match remove_blocks(func_expr).kind {
+                    ExprKind::Tup(fields) => fields.iter().all(|e| is_default_equivalent(cx, e)),
+                    ExprKind::Call(callee, args)
+                        if is_path_self(callee) => args.iter().all(|e| is_default_equivalent(cx, e)),
+                    ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_equivalent(cx, ef.expr)),
+                    _ => false,
+                };
+                if should_emit {
+                    let path_string = cx.tcx.def_path_str(adt_def.did);
+                    span_lint_and_help(
+                        cx,
+                        DERIVABLE_IMPLS,
+                        item.span,
+                        "this `impl` can be derived",
+                        None,
+                        &format!("try annotating `{}` with `#[derive(Default)]`", path_string),
+                    );
+                }
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index dcfa5253f83..8416b8440df 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -105,9 +105,6 @@ declare_clippy_lint! {
     /// nothing more than copy the object, which is what `#[derive(Copy, Clone)]`
     /// gets you.
     ///
-    /// ### Known problems
-    /// Bounds of generic types are sometimes wrong: https://github.com/rust-lang/rust/issues/26925
-    ///
     /// ### Example
     /// ```rust,ignore
     /// #[derive(Copy)]
diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs
index cb2b7f5be70..0b61909ddd8 100644
--- a/src/tools/clippy/clippy_lints/src/doc.rs
+++ b/src/tools/clippy/clippy_lints/src/doc.rs
@@ -665,6 +665,7 @@ fn check_text(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, text: &str
             span.lo() + BytePos::from_usize(offset),
             span.lo() + BytePos::from_usize(offset + word.len()),
             span.ctxt(),
+            span.parent(),
         );
 
         check_word(cx, word, span);
diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs
index 627f746ec99..ac6824672f6 100644
--- a/src/tools/clippy/clippy_lints/src/entry.rs
+++ b/src/tools/clippy/clippy_lints/src/entry.rs
@@ -9,8 +9,9 @@ use clippy_utils::{
 use core::fmt::Write;
 use rustc_errors::Applicability;
 use rustc_hir::{
+    hir_id::HirIdSet,
     intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor},
-    Block, Expr, ExprKind, Guard, HirId, Local, Stmt, StmtKind, UnOp,
+    Block, Expr, ExprKind, Guard, HirId, Pat, Stmt, StmtKind, UnOp,
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -338,6 +339,8 @@ struct InsertSearcher<'cx, 'tcx> {
     edits: Vec<Edit<'tcx>>,
     /// A stack of loops the visitor is currently in.
     loops: Vec<HirId>,
+    /// Local variables created in the expression. These don't need to be captured.
+    locals: HirIdSet,
 }
 impl<'tcx> InsertSearcher<'_, 'tcx> {
     /// Visit the expression as a branch in control flow. Multiple insert calls can be used, but
@@ -385,13 +388,16 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
                 }
             },
             StmtKind::Expr(e) => self.visit_expr(e),
-            StmtKind::Local(Local { init: Some(e), .. }) => {
-                self.allow_insert_closure &= !self.in_tail_pos;
-                self.in_tail_pos = false;
-                self.is_single_insert = false;
-                self.visit_expr(e);
+            StmtKind::Local(l) => {
+                self.visit_pat(l.pat);
+                if let Some(e) = l.init {
+                    self.allow_insert_closure &= !self.in_tail_pos;
+                    self.in_tail_pos = false;
+                    self.is_single_insert = false;
+                    self.visit_expr(e);
+                }
             },
-            _ => {
+            StmtKind::Item(_) => {
                 self.allow_insert_closure &= !self.in_tail_pos;
                 self.is_single_insert = false;
             },
@@ -473,6 +479,7 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
                     // Each branch may contain it's own insert expression.
                     let mut is_map_used = self.is_map_used;
                     for arm in arms {
+                        self.visit_pat(arm.pat);
                         if let Some(Guard::If(guard) | Guard::IfLet(_, guard)) = arm.guard {
                             self.visit_non_tail_expr(guard);
                         }
@@ -498,7 +505,8 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
                 },
                 _ => {
                     self.allow_insert_closure &= !self.in_tail_pos;
-                    self.allow_insert_closure &= can_move_expr_to_closure_no_visit(self.cx, expr, &self.loops);
+                    self.allow_insert_closure &=
+                        can_move_expr_to_closure_no_visit(self.cx, expr, &self.loops, &self.locals);
                     // Sub expressions are no longer in the tail position.
                     self.is_single_insert = false;
                     self.in_tail_pos = false;
@@ -507,6 +515,12 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
             },
         }
     }
+
+    fn visit_pat(&mut self, p: &'tcx Pat<'tcx>) {
+        p.each_binding_or_first(&mut |_, id, _, _| {
+            self.locals.insert(id);
+        });
+    }
 }
 
 struct InsertSearchResults<'tcx> {
@@ -632,6 +646,7 @@ fn find_insert_calls(
         in_tail_pos: true,
         is_single_insert: true,
         loops: Vec::new(),
+        locals: HirIdSet::default(),
     };
     s.visit_expr(expr);
     let allow_insert_closure = s.allow_insert_closure;
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 f72a1e446d5..8714ce90164 100644
--- a/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs
+++ b/src/tools/clippy/clippy_lints/src/eval_order_dependence.rs
@@ -15,8 +15,8 @@ declare_clippy_lint! {
     /// order of sub-expressions.
     ///
     /// ### Why is this bad?
-    /// It is often confusing to read. In addition, the
-    /// sub-expression evaluation order for Rust is not well documented.
+    /// It is often confusing to read. As described [here](https://doc.rust-lang.org/reference/expressions.html?highlight=subexpression#evaluation-order-of-operands),
+    /// the operands of these expressions are evaluated before applying the effects of the expression.
     ///
     /// ### Known problems
     /// Code which intentionally depends on the evaluation
diff --git a/src/tools/clippy/clippy_lints/src/feature_name.rs b/src/tools/clippy/clippy_lints/src/feature_name.rs
new file mode 100644
index 00000000000..eef1407a80c
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/feature_name.rs
@@ -0,0 +1,164 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::{diagnostics::span_lint, is_lint_allowed};
+use rustc_hir::{Crate, CRATE_HIR_ID};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::source_map::DUMMY_SP;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for feature names with prefix `use-`, `with-` or suffix `-support`
+    ///
+    /// ### Why is this bad?
+    /// These prefixes and suffixes have no significant meaning.
+    ///
+    /// ### Example
+    /// ```toml
+    /// # The `Cargo.toml` with feature name redundancy
+    /// [features]
+    /// default = ["use-abc", "with-def", "ghi-support"]
+    /// use-abc = []  // redundant
+    /// with-def = []   // redundant
+    /// ghi-support = []   // redundant
+    /// ```
+    ///
+    /// Use instead:
+    /// ```toml
+    /// [features]
+    /// default = ["abc", "def", "ghi"]
+    /// abc = []
+    /// def = []
+    /// ghi = []
+    /// ```
+    ///
+    pub REDUNDANT_FEATURE_NAMES,
+    cargo,
+    "usage of a redundant feature name"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for negative feature names with prefix `no-` or `not-`
+    ///
+    /// ### Why is this bad?
+    /// Features are supposed to be additive, and negatively-named features violate it.
+    ///
+    /// ### Example
+    /// ```toml
+    /// # The `Cargo.toml` with negative feature names
+    /// [features]
+    /// default = []
+    /// no-abc = []
+    /// not-def = []
+    ///
+    /// ```
+    /// Use instead:
+    /// ```toml
+    /// [features]
+    /// default = ["abc", "def"]
+    /// abc = []
+    /// def = []
+    ///
+    /// ```
+    pub NEGATIVE_FEATURE_NAMES,
+    cargo,
+    "usage of a negative feature name"
+}
+
+declare_lint_pass!(FeatureName => [REDUNDANT_FEATURE_NAMES, NEGATIVE_FEATURE_NAMES]);
+
+static PREFIXES: [&str; 8] = ["no-", "no_", "not-", "not_", "use-", "use_", "with-", "with_"];
+static SUFFIXES: [&str; 2] = ["-support", "_support"];
+
+fn is_negative_prefix(s: &str) -> bool {
+    s.starts_with("no")
+}
+
+fn lint(cx: &LateContext<'_>, feature: &str, substring: &str, is_prefix: bool) {
+    let is_negative = is_prefix && is_negative_prefix(substring);
+    span_lint_and_help(
+        cx,
+        if is_negative {
+            NEGATIVE_FEATURE_NAMES
+        } else {
+            REDUNDANT_FEATURE_NAMES
+        },
+        DUMMY_SP,
+        &format!(
+            "the \"{}\" {} in the feature name \"{}\" is {}",
+            substring,
+            if is_prefix { "prefix" } else { "suffix" },
+            feature,
+            if is_negative { "negative" } else { "redundant" }
+        ),
+        None,
+        &format!(
+            "consider renaming the feature to \"{}\"{}",
+            if is_prefix {
+                feature.strip_prefix(substring)
+            } else {
+                feature.strip_suffix(substring)
+            }
+            .unwrap(),
+            if is_negative {
+                ", but make sure the feature adds functionality"
+            } else {
+                ""
+            }
+        ),
+    );
+}
+
+impl LateLintPass<'_> for FeatureName {
+    fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) {
+        if is_lint_allowed(cx, REDUNDANT_FEATURE_NAMES, CRATE_HIR_ID)
+            && is_lint_allowed(cx, NEGATIVE_FEATURE_NAMES, CRATE_HIR_ID)
+        {
+            return;
+        }
+
+        let metadata = unwrap_cargo_metadata!(cx, REDUNDANT_FEATURE_NAMES, false);
+
+        for package in metadata.packages {
+            let mut features: Vec<&String> = package.features.keys().collect();
+            features.sort();
+            for feature in features {
+                let prefix_opt = {
+                    let i = PREFIXES.partition_point(|prefix| prefix < &feature.as_str());
+                    if i > 0 && feature.starts_with(PREFIXES[i - 1]) {
+                        Some(PREFIXES[i - 1])
+                    } else {
+                        None
+                    }
+                };
+                if let Some(prefix) = prefix_opt {
+                    lint(cx, feature, prefix, true);
+                }
+
+                let suffix_opt: Option<&str> = {
+                    let i = SUFFIXES.partition_point(|suffix| {
+                        suffix.bytes().rev().cmp(feature.bytes().rev()) == std::cmp::Ordering::Less
+                    });
+                    if i > 0 && feature.ends_with(SUFFIXES[i - 1]) {
+                        Some(SUFFIXES[i - 1])
+                    } else {
+                        None
+                    }
+                };
+                if let Some(suffix) = suffix_opt {
+                    lint(cx, feature, suffix, false);
+                }
+            }
+        }
+    }
+}
+
+#[test]
+fn test_prefixes_sorted() {
+    let mut sorted_prefixes = PREFIXES;
+    sorted_prefixes.sort_unstable();
+    assert_eq!(PREFIXES, sorted_prefixes);
+    let mut sorted_suffixes = SUFFIXES;
+    sorted_suffixes.sort_by(|a, b| a.bytes().rev().cmp(b.bytes().rev()));
+    assert_eq!(SUFFIXES, sorted_suffixes);
+}
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 d12482e7b7b..eda611117ba 100644
--- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
@@ -332,8 +332,6 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
                         ),
                         Applicability::MachineApplicable,
                     );
-
-                    return;
                 }
             }
         }
@@ -364,22 +362,22 @@ fn detect_hypot(cx: &LateContext<'_>, args: &[Expr<'_>]) -> Option<String> {
         if_chain! {
             if let ExprKind::MethodCall(
                 PathSegment { ident: lmethod_name, .. },
-                ref _lspan,
-                largs,
+                _lspan,
+                [largs_0, largs_1, ..],
                 _
-            ) = add_lhs.kind;
+            ) = &add_lhs.kind;
             if let ExprKind::MethodCall(
                 PathSegment { ident: rmethod_name, .. },
-                ref _rspan,
-                rargs,
+                _rspan,
+                [rargs_0, rargs_1, ..],
                 _
-            ) = add_rhs.kind;
+            ) = &add_rhs.kind;
             if lmethod_name.as_str() == "powi" && rmethod_name.as_str() == "powi";
-            if let Some((lvalue, _)) = constant(cx, cx.typeck_results(), &largs[1]);
-            if let Some((rvalue, _)) = constant(cx, cx.typeck_results(), &rargs[1]);
+            if let Some((lvalue, _)) = constant(cx, cx.typeck_results(), largs_1);
+            if let Some((rvalue, _)) = constant(cx, cx.typeck_results(), rargs_1);
             if Int(2) == lvalue && Int(2) == rvalue;
             then {
-                return Some(format!("{}.hypot({})", Sugg::hir(cx, &largs[0], ".."), Sugg::hir(cx, &rargs[0], "..")));
+                return Some(format!("{}.hypot({})", Sugg::hir(cx, largs_0, ".."), Sugg::hir(cx, rargs_0, "..")));
             }
         }
     }
@@ -409,8 +407,8 @@ fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) {
         if cx.typeck_results().expr_ty(lhs).is_floating_point();
         if let Some((value, _)) = constant(cx, cx.typeck_results(), rhs);
         if F32(1.0) == value || F64(1.0) == value;
-        if let ExprKind::MethodCall(path, _, method_args, _) = lhs.kind;
-        if cx.typeck_results().expr_ty(&method_args[0]).is_floating_point();
+        if let ExprKind::MethodCall(path, _, [self_arg, ..], _) = &lhs.kind;
+        if cx.typeck_results().expr_ty(self_arg).is_floating_point();
         if path.ident.name.as_str() == "exp";
         then {
             span_lint_and_sugg(
@@ -421,7 +419,7 @@ fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) {
                 "consider using",
                 format!(
                     "{}.exp_m1()",
-                    Sugg::hir(cx, &method_args[0], "..")
+                    Sugg::hir(cx, self_arg, "..")
                 ),
                 Applicability::MachineApplicable,
             );
@@ -619,8 +617,8 @@ fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) {
             rhs,
         ) = &expr.kind;
         if are_same_base_logs(cx, lhs, rhs);
-        if let ExprKind::MethodCall(_, _, largs, _) = lhs.kind;
-        if let ExprKind::MethodCall(_, _, rargs, _) = rhs.kind;
+        if let ExprKind::MethodCall(_, _, [largs_self, ..], _) = &lhs.kind;
+        if let ExprKind::MethodCall(_, _, [rargs_self, ..], _) = &rhs.kind;
         then {
             span_lint_and_sugg(
                 cx,
@@ -628,7 +626,7 @@ fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) {
                 expr.span,
                 "log base can be expressed more clearly",
                 "consider using",
-                format!("{}.log({})", Sugg::hir(cx, &largs[0], ".."), Sugg::hir(cx, &rargs[0], ".."),),
+                format!("{}.log({})", Sugg::hir(cx, largs_self, ".."), Sugg::hir(cx, rargs_self, ".."),),
                 Applicability::MachineApplicable,
             );
         }
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 ea6193acbe8..77d08081c07 100644
--- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
@@ -26,7 +26,6 @@ pub(super) fn check_item(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
         if let Some(attr) = attr {
             check_needless_must_use(cx, sig.decl, item.hir_id(), item.span, fn_header_span, attr);
-            return;
         } else if is_public && !is_proc_macro(cx.sess(), attrs) && !attrs.iter().any(|a| a.has_name(sym::no_mangle)) {
             check_must_use_candidate(
                 cx,
diff --git a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs
index 7dad1c31150..ef72b88b3c7 100644
--- a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs
+++ b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs
@@ -138,12 +138,12 @@ impl<'tcx, 'l> ArmVisitor<'tcx, 'l> {
 
 fn is_mutex_lock_call<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
     if_chain! {
-        if let ExprKind::MethodCall(path, _span, args, _) = &expr.kind;
+        if let ExprKind::MethodCall(path, _span, [self_arg, ..], _) = &expr.kind;
         if path.ident.as_str() == "lock";
-        let ty = cx.typeck_results().expr_ty(&args[0]);
+        let ty = cx.typeck_results().expr_ty(self_arg);
         if is_type_diagnostic_item(cx, ty, sym!(mutex_type));
         then {
-            Some(&args[0])
+            Some(self_arg)
         } else {
             None
         }
diff --git a/src/tools/clippy/clippy_lints/src/if_let_some_result.rs b/src/tools/clippy/clippy_lints/src/if_let_some_result.rs
index fb5637fcec1..adcd78ed0d4 100644
--- a/src/tools/clippy/clippy_lints/src/if_let_some_result.rs
+++ b/src/tools/clippy/clippy_lints/src/if_let_some_result.rs
@@ -46,10 +46,10 @@ impl<'tcx> LateLintPass<'tcx> for OkIfLet {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! { //begin checking variables
             if let Some(higher::IfLet { let_pat, let_expr, .. }) = higher::IfLet::hir(cx, expr);
-            if let ExprKind::MethodCall(_, ok_span, ref result_types, _) = let_expr.kind; //check is expr.ok() has type Result<T,E>.ok(, _)
-            if let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _)  = let_pat.kind; //get operation
+            if let ExprKind::MethodCall(_, ok_span, [ref result_types_0, ..], _) = let_expr.kind; //check is expr.ok() has type Result<T,E>.ok(, _)
+            if let PatKind::TupleStruct(QPath::Resolved(_, x), y, _)  = let_pat.kind; //get operation
             if method_chain_args(let_expr, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized;
-            if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&result_types[0]), sym::result_type);
+            if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(result_types_0), sym::result_type);
             if rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(x, false)) == "Some";
 
             then {
diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
index 6b407c7bb67..2fe32fcf665 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
@@ -130,7 +130,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
                         let pos = snippet_opt(cx, item.span.until(target.span()))
                             .and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4)));
                         if let Some(pos) = pos {
-                            Span::new(pos, pos, item.span.data().ctxt)
+                            Span::new(pos, pos, item.span.ctxt(), item.span.parent())
                         } else {
                             return;
                         }
@@ -173,7 +173,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
                                     Some(item.span.lo() + BytePos((i + (&snip[i..]).find('(')?) as u32))
                                 })
                                 .expect("failed to create span for type parameters");
-                            Span::new(pos, pos, item.span.data().ctxt)
+                            Span::new(pos, pos, item.span.ctxt(), item.span.parent())
                         });
 
                         let mut ctr_vis = ImplicitHasherConstructorVisitor::new(cx, target);
diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
index 10281496c11..fe6814e35d0 100644
--- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
@@ -63,6 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
                     hi_pos - BytePos::from_usize("const".len()),
                     hi_pos,
                     item.span.ctxt(),
+                    item.span.parent(),
                 );
                 span_lint_and_then(
                     cx,
diff --git a/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs
index 0594b73dd38..7f2c7b707f0 100644
--- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs
+++ b/src/tools/clippy/clippy_lints/src/let_if_seq.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
-use clippy_utils::{path_to_local_id, visitors::LocalUsedVisitor};
+use clippy_utils::{path_to_local_id, visitors::is_local_used};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -65,11 +65,10 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq {
                 if let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.kind;
                 if let hir::StmtKind::Expr(if_) = expr.kind;
                 if let hir::ExprKind::If(hir::Expr { kind: hir::ExprKind::DropTemps(cond), ..}, then, else_) = if_.kind;
-                let mut used_visitor = LocalUsedVisitor::new(cx, canonical_id);
-                if !used_visitor.check_expr(cond);
+                if !is_local_used(cx, *cond, canonical_id);
                 if let hir::ExprKind::Block(then, _) = then.kind;
                 if let Some(value) = check_assign(cx, canonical_id, &*then);
-                if !used_visitor.check_expr(value);
+                if !is_local_used(cx, value, canonical_id);
                 then {
                     let span = stmt.span.to(if_.span);
 
@@ -148,15 +147,13 @@ fn check_assign<'tcx>(
         if let hir::ExprKind::Assign(var, value, _) = expr.kind;
         if path_to_local_id(var, decl);
         then {
-            let mut v = LocalUsedVisitor::new(cx, decl);
-
-            if block.stmts.iter().take(block.stmts.len()-1).any(|stmt| v.check_stmt(stmt)) {
-                return None;
+            if block.stmts.iter().take(block.stmts.len()-1).any(|stmt| is_local_used(cx, stmt, decl)) {
+                None
+            } else {
+                Some(value)
             }
-
-            return Some(value);
+        } else {
+            None
         }
     }
-
-    None
 }
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 19719502870..acc78840bb9 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -31,7 +31,7 @@ extern crate rustc_infer;
 extern crate rustc_lexer;
 extern crate rustc_lint;
 extern crate rustc_middle;
-extern crate rustc_mir;
+extern crate rustc_mir_dataflow;
 extern crate rustc_parse;
 extern crate rustc_parse_format;
 extern crate rustc_session;
@@ -187,6 +187,7 @@ mod dbg_macro;
 mod default;
 mod default_numeric_fallback;
 mod dereference;
+mod derivable_impls;
 mod derive;
 mod disallowed_method;
 mod disallowed_script_idents;
@@ -211,6 +212,7 @@ mod exhaustive_items;
 mod exit;
 mod explicit_write;
 mod fallible_impl_from;
+mod feature_name;
 mod float_equality_without_abs;
 mod float_literal;
 mod floating_point_arithmetic;
@@ -272,6 +274,7 @@ mod missing_const_for_fn;
 mod missing_doc;
 mod missing_enforced_import_rename;
 mod missing_inline;
+mod module_style;
 mod modulo_arithmetic;
 mod multiple_crate_versions;
 mod mut_key;
@@ -287,6 +290,7 @@ mod needless_borrow;
 mod needless_borrowed_ref;
 mod needless_continue;
 mod needless_for_each;
+mod needless_option_as_deref;
 mod needless_pass_by_value;
 mod needless_question_mark;
 mod needless_update;
@@ -584,6 +588,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         default::FIELD_REASSIGN_WITH_DEFAULT,
         default_numeric_fallback::DEFAULT_NUMERIC_FALLBACK,
         dereference::EXPLICIT_DEREF_METHODS,
+        derivable_impls::DERIVABLE_IMPLS,
         derive::DERIVE_HASH_XOR_EQ,
         derive::DERIVE_ORD_XOR_PARTIAL_ORD,
         derive::EXPL_IMPL_CLONE_ON_COPY,
@@ -625,6 +630,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         exit::EXIT,
         explicit_write::EXPLICIT_WRITE,
         fallible_impl_from::FALLIBLE_IMPL_FROM,
+        feature_name::NEGATIVE_FEATURE_NAMES,
+        feature_name::REDUNDANT_FEATURE_NAMES,
         float_equality_without_abs::FLOAT_EQUALITY_WITHOUT_ABS,
         float_literal::EXCESSIVE_PRECISION,
         float_literal::LOSSY_FLOAT_LITERAL,
@@ -770,6 +777,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_SPLIT_ONCE,
         methods::MANUAL_STR_REPEAT,
         methods::MAP_COLLECT_RESULT_UNIT,
         methods::MAP_FLATTEN,
@@ -822,6 +830,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS,
         missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES,
         missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS,
+        module_style::MOD_MODULE_FILES,
+        module_style::SELF_NAMED_MODULE_FILES,
         modulo_arithmetic::MODULO_ARITHMETIC,
         multiple_crate_versions::MULTIPLE_CRATE_VERSIONS,
         mut_key::MUTABLE_KEY_TYPE,
@@ -840,6 +850,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE,
         needless_continue::NEEDLESS_CONTINUE,
         needless_for_each::NEEDLESS_FOR_EACH,
+        needless_option_as_deref::NEEDLESS_OPTION_AS_DEREF,
         needless_pass_by_value::NEEDLESS_PASS_BY_VALUE,
         needless_question_mark::NEEDLESS_QUESTION_MARK,
         needless_update::NEEDLESS_UPDATE,
@@ -1031,6 +1042,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS),
         LintId::of(missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES),
         LintId::of(missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS),
+        LintId::of(module_style::MOD_MODULE_FILES),
+        LintId::of(module_style::SELF_NAMED_MODULE_FILES),
         LintId::of(modulo_arithmetic::MODULO_ARITHMETIC),
         LintId::of(panic_in_result_fn::PANIC_IN_RESULT_FN),
         LintId::of(panic_unimplemented::PANIC),
@@ -1122,7 +1135,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(needless_for_each::NEEDLESS_FOR_EACH),
         LintId::of(needless_pass_by_value::NEEDLESS_PASS_BY_VALUE),
         LintId::of(non_expressive_names::SIMILAR_NAMES),
-        LintId::of(option_if_let_else::OPTION_IF_LET_ELSE),
         LintId::of(pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE),
         LintId::of(pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF),
         LintId::of(ranges::RANGE_MINUS_ONE),
@@ -1193,10 +1205,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(collapsible_if::COLLAPSIBLE_IF),
         LintId::of(collapsible_match::COLLAPSIBLE_MATCH),
         LintId::of(comparison_chain::COMPARISON_CHAIN),
-        LintId::of(copies::BRANCHES_SHARING_CODE),
         LintId::of(copies::IFS_SAME_COND),
         LintId::of(copies::IF_SAME_THEN_ELSE),
         LintId::of(default::FIELD_REASSIGN_WITH_DEFAULT),
+        LintId::of(derivable_impls::DERIVABLE_IMPLS),
         LintId::of(derive::DERIVE_HASH_XOR_EQ),
         LintId::of(derive::DERIVE_ORD_XOR_PARTIAL_ORD),
         LintId::of(doc::MISSING_SAFETY_DOC),
@@ -1316,6 +1328,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_SPLIT_ONCE),
         LintId::of(methods::MANUAL_STR_REPEAT),
         LintId::of(methods::MAP_COLLECT_RESULT_UNIT),
         LintId::of(methods::MAP_IDENTITY),
@@ -1366,6 +1379,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(needless_bool::NEEDLESS_BOOL),
         LintId::of(needless_borrow::NEEDLESS_BORROW),
         LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE),
+        LintId::of(needless_option_as_deref::NEEDLESS_OPTION_AS_DEREF),
         LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK),
         LintId::of(needless_update::NEEDLESS_UPDATE),
         LintId::of(neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD),
@@ -1581,7 +1595,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(booleans::NONMINIMAL_BOOL),
         LintId::of(casts::CHAR_LIT_AS_U8),
         LintId::of(casts::UNNECESSARY_CAST),
-        LintId::of(copies::BRANCHES_SHARING_CODE),
+        LintId::of(derivable_impls::DERIVABLE_IMPLS),
         LintId::of(double_comparison::DOUBLE_COMPARISONS),
         LintId::of(double_parens::DOUBLE_PARENS),
         LintId::of(duration_subsec::DURATION_SUBSEC),
@@ -1614,6 +1628,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(methods::ITER_COUNT),
         LintId::of(methods::MANUAL_FILTER_MAP),
         LintId::of(methods::MANUAL_FIND_MAP),
+        LintId::of(methods::MANUAL_SPLIT_ONCE),
         LintId::of(methods::MAP_IDENTITY),
         LintId::of(methods::OPTION_AS_REF_DEREF),
         LintId::of(methods::OPTION_FILTER_MAP),
@@ -1628,6 +1643,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(needless_bool::BOOL_COMPARISON),
         LintId::of(needless_bool::NEEDLESS_BOOL),
         LintId::of(needless_borrowed_ref::NEEDLESS_BORROWED_REFERENCE),
+        LintId::of(needless_option_as_deref::NEEDLESS_OPTION_AS_DEREF),
         LintId::of(needless_question_mark::NEEDLESS_QUESTION_MARK),
         LintId::of(needless_update::NEEDLESS_UPDATE),
         LintId::of(neg_cmp_op_on_partial_ord::NEG_CMP_OP_ON_PARTIAL_ORD),
@@ -1779,6 +1795,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
 
     store.register_group(true, "clippy::cargo", Some("clippy_cargo"), vec![
         LintId::of(cargo_common_metadata::CARGO_COMMON_METADATA),
+        LintId::of(feature_name::NEGATIVE_FEATURE_NAMES),
+        LintId::of(feature_name::REDUNDANT_FEATURE_NAMES),
         LintId::of(multiple_crate_versions::MULTIPLE_CRATE_VERSIONS),
         LintId::of(wildcard_dependencies::WILDCARD_DEPENDENCIES),
     ]);
@@ -1786,6 +1804,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
         LintId::of(attrs::EMPTY_LINE_AFTER_OUTER_ATTR),
         LintId::of(cognitive_complexity::COGNITIVE_COMPLEXITY),
+        LintId::of(copies::BRANCHES_SHARING_CODE),
         LintId::of(disallowed_method::DISALLOWED_METHOD),
         LintId::of(disallowed_type::DISALLOWED_TYPE),
         LintId::of(fallible_impl_from::FALLIBLE_IMPL_FROM),
@@ -1797,6 +1816,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL),
         LintId::of(mutex_atomic::MUTEX_INTEGER),
         LintId::of(nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES),
+        LintId::of(option_if_let_else::OPTION_IF_LET_ELSE),
         LintId::of(path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE),
         LintId::of(redundant_pub_crate::REDUNDANT_PUB_CRATE),
         LintId::of(regex::TRIVIAL_REGEX),
@@ -1835,7 +1855,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| Box::new(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::new(types::Types::new(vec_box_size_threshold, type_complexity_threshold)));
+    let avoid_breaking_exported_api = conf.avoid_breaking_exported_api;
+    store.register_late_pass(move || Box::new(types::Types::new(
+        vec_box_size_threshold,
+        type_complexity_threshold,
+        avoid_breaking_exported_api,
+    )));
     store.register_late_pass(|| Box::new(booleans::NonminimalBool));
     store.register_late_pass(|| Box::new(needless_bitwise_bool::NeedlessBitwiseBool));
     store.register_late_pass(|| Box::new(eq_op::EqOp));
@@ -1846,9 +1871,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| Box::new(ptr::Ptr));
     store.register_late_pass(|| Box::new(ptr_eq::PtrEq));
     store.register_late_pass(|| Box::new(needless_bool::NeedlessBool));
+    store.register_late_pass(|| Box::new(needless_option_as_deref::OptionNeedlessDeref));
     store.register_late_pass(|| Box::new(needless_bool::BoolComparison));
     store.register_late_pass(|| Box::new(needless_for_each::NeedlessForEach));
-    store.register_late_pass(|| Box::new(approx_const::ApproxConstant));
     store.register_late_pass(|| Box::new(misc::MiscLints));
     store.register_late_pass(|| Box::new(eta_reduction::EtaReduction));
     store.register_late_pass(|| Box::new(identity_op::IdentityOp));
@@ -1877,6 +1902,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     });
 
     let avoid_breaking_exported_api = conf.avoid_breaking_exported_api;
+    store.register_late_pass(move || Box::new(approx_const::ApproxConstant::new(msrv)));
     store.register_late_pass(move || Box::new(methods::Methods::new(avoid_breaking_exported_api, msrv)));
     store.register_late_pass(move || Box::new(matches::Matches::new(msrv)));
     store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustive::new(msrv)));
@@ -1920,6 +1946,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| Box::new(panic_unimplemented::PanicUnimplemented));
     store.register_late_pass(|| Box::new(strings::StringLitAsBytes));
     store.register_late_pass(|| Box::new(derive::Derive));
+    store.register_late_pass(|| Box::new(derivable_impls::DerivableImpls));
     store.register_late_pass(|| Box::new(get_last_with_len::GetLastWithLen));
     store.register_late_pass(|| Box::new(drop_forget_ref::DropForgetRef));
     store.register_late_pass(|| Box::new(empty_enum::EmptyEnum));
@@ -2092,7 +2119,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| Box::new(from_str_radix_10::FromStrRadix10));
     store.register_late_pass(|| Box::new(manual_map::ManualMap));
     store.register_late_pass(move || Box::new(if_then_some_else_none::IfThenSomeElseNone::new(msrv)));
-    store.register_early_pass(|| Box::new(bool_assert_comparison::BoolAssertComparison));
+    store.register_late_pass(|| Box::new(bool_assert_comparison::BoolAssertComparison));
+    store.register_early_pass(move || Box::new(module_style::ModStyle));
     store.register_late_pass(|| Box::new(unused_async::UnusedAsync));
     let disallowed_types = conf.disallowed_types.iter().cloned().collect::<FxHashSet<_>>();
     store.register_late_pass(move || Box::new(disallowed_type::DisallowedType::new(&disallowed_types)));
@@ -2102,6 +2130,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_early_pass(move || Box::new(disallowed_script_idents::DisallowedScriptIdents::new(&scripts)));
     store.register_late_pass(|| Box::new(strlen_on_c_strings::StrlenOnCStrings));
     store.register_late_pass(move || Box::new(self_named_constructors::SelfNamedConstructors));
+    store.register_late_pass(move || Box::new(feature_name::FeatureName));
 }
 
 #[rustfmt::skip]
diff --git a/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs b/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs
index 82bf49f5b49..12ffe7a1364 100644
--- a/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
 use clippy_utils::source::snippet;
 use clippy_utils::sugg;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::visitors::LocalUsedVisitor;
+use clippy_utils::visitors::is_local_used;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, Pat, PatKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
@@ -15,7 +15,6 @@ pub(super) fn check<'tcx>(
     pat: &'tcx Pat<'_>,
     arg: &'tcx Expr<'_>,
     body: &'tcx Expr<'_>,
-    expr: &'tcx Expr<'_>,
 ) {
     let pat_span = pat.span;
 
@@ -43,7 +42,7 @@ pub(super) fn check<'tcx>(
                 span_lint_and_then(
                     cx,
                     FOR_KV_MAP,
-                    expr.span,
+                    arg_span,
                     &format!("you seem to want to iterate on a map's {}s", kind),
                     |diag| {
                         let map = sugg::Sugg::hir(cx, arg, "map");
@@ -66,9 +65,7 @@ pub(super) fn check<'tcx>(
 fn pat_is_wild<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx PatKind<'_>, body: &'tcx Expr<'_>) -> bool {
     match *pat {
         PatKind::Wild => true,
-        PatKind::Binding(_, id, ident, None) if ident.as_str().starts_with('_') => {
-            !LocalUsedVisitor::new(cx, id).check_expr(body)
-        },
+        PatKind::Binding(_, id, ident, None) if ident.as_str().starts_with('_') => !is_local_used(cx, body, id),
         _ => false,
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs b/src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs
index 9148fbfd497..e640c62ebda 100644
--- a/src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs
@@ -5,12 +5,12 @@ use rustc_hir::Expr;
 use rustc_lint::LateContext;
 use rustc_span::sym;
 
-pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, expr: &Expr<'_>) -> bool {
+pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>) -> bool {
     if is_trait_method(cx, arg, sym::Iterator) {
         span_lint(
             cx,
             ITER_NEXT_LOOP,
-            expr.span,
+            arg.span,
             "you are iterating over `Iterator::next()` which is an Option; this will compile but is \
             probably not what you want",
         );
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
index 5852674da57..5b6e27085d5 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
@@ -2,6 +2,7 @@ use super::utils::make_iterator_snippet;
 use super::MANUAL_FLATTEN;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher;
+use clippy_utils::visitors::is_local_used;
 use clippy_utils::{is_lang_ctor, path_to_local_id};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
@@ -37,7 +38,8 @@ pub(super) fn check<'tcx>(
 
         if_chain! {
             if let Some(inner_expr) = inner_expr;
-            if let Some(higher::IfLet { let_pat, let_expr, if_else: None, .. }) = higher::IfLet::hir(cx, inner_expr);
+            if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else: None })
+                = higher::IfLet::hir(cx, inner_expr);
             // Ensure match_expr in `if let` statement is the same as the pat from the for-loop
             if let PatKind::Binding(_, pat_hir_id, _, _) = pat.kind;
             if path_to_local_id(let_expr, pat_hir_id);
@@ -46,6 +48,8 @@ pub(super) fn check<'tcx>(
             let some_ctor = is_lang_ctor(cx, qpath, OptionSome);
             let ok_ctor = is_lang_ctor(cx, qpath, ResultOk);
             if some_ctor || ok_ctor;
+            // Ensure epxr in `if let` is not used afterwards
+            if !is_local_used(cx, if_then, pat_hir_id);
             then {
                 let if_let_type = if some_ctor { "Some" } else { "Ok" };
                 // Prepare the error message
diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs
index bd9de5e08d7..5df1b796401 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs
@@ -397,6 +397,21 @@ declare_clippy_lint! {
     /// ### Why is this bad?
     /// One might think that modifying the mutable variable changes the loop bounds
     ///
+    /// ### Known problems
+    /// False positive when mutation is followed by a `break`, but the `break` is not immediately
+    /// after the mutation:
+    ///
+    /// ```rust
+    /// let mut x = 5;
+    /// for _ in 0..x {
+    ///     x += 1; // x is a range bound that is mutated
+    ///     ..; // some other expression
+    ///     break; // leaves the loop, so mutation is not an issue
+    /// }
+    /// ```
+    ///
+    /// False positive on nested loops ([#6072](https://github.com/rust-lang/rust-clippy/issues/6072))
+    ///
     /// ### Example
     /// ```rust
     /// let mut foo = 42;
@@ -580,8 +595,8 @@ impl<'tcx> LateLintPass<'tcx> for Loops {
 
         while_let_on_iterator::check(cx, expr);
 
-        if let Some(higher::While { if_cond, if_then, .. }) = higher::While::hir(&expr) {
-            while_immutable_condition::check(cx, if_cond, if_then);
+        if let Some(higher::While { condition, body }) = higher::While::hir(expr) {
+            while_immutable_condition::check(cx, condition, body);
         }
 
         needless_collect::check(expr, cx);
@@ -601,15 +616,15 @@ fn check_for_loop<'tcx>(
         needless_range_loop::check(cx, pat, arg, body, expr);
         explicit_counter_loop::check(cx, pat, arg, body, expr);
     }
-    check_for_loop_arg(cx, pat, arg, expr);
-    for_kv_map::check(cx, pat, arg, body, expr);
+    check_for_loop_arg(cx, pat, arg);
+    for_kv_map::check(cx, pat, arg, body);
     mut_range_bound::check(cx, arg, body);
     single_element_loop::check(cx, pat, arg, body, expr);
     same_item_push::check(cx, pat, arg, body, expr);
     manual_flatten::check(cx, pat, arg, body, span);
 }
 
-fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>, expr: &Expr<'_>) {
+fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>) {
     let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used
 
     if let ExprKind::MethodCall(method, _, [self_arg], _) = arg.kind {
@@ -622,7 +637,7 @@ fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>, expr:
                 explicit_into_iter_loop::check(cx, self_arg, arg);
             },
             "next" => {
-                next_loop_linted = iter_next_loop::check(cx, arg, expr);
+                next_loop_linted = iter_next_loop::check(cx, arg);
             },
             _ => {},
         }
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 344dc5074d3..358d53e8859 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
@@ -1,24 +1,27 @@
 use super::MUT_RANGE_BOUND;
-use clippy_utils::diagnostics::span_lint;
-use clippy_utils::{higher, path_to_local};
+use clippy_utils::diagnostics::span_lint_and_note;
+use clippy_utils::{get_enclosing_block, higher, path_to_local};
 use if_chain::if_chain;
-use rustc_hir::{BindingAnnotation, Expr, HirId, Node, PatKind};
+use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, Node, PatKind};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
+use rustc_middle::hir::map::Map;
 use rustc_middle::{mir::FakeReadCause, ty};
 use rustc_span::source_map::Span;
 use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 
 pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<'_>) {
-    if let Some(higher::Range {
-        start: Some(start),
-        end: Some(end),
-        ..
-    }) = higher::Range::hir(arg)
-    {
-        let mut_ids = vec![check_for_mutability(cx, start), check_for_mutability(cx, end)];
-        if mut_ids[0].is_some() || mut_ids[1].is_some() {
-            let (span_low, span_high) = check_for_mutation(cx, body, &mut_ids);
+    if_chain! {
+        if let Some(higher::Range {
+            start: Some(start),
+            end: Some(end),
+            ..
+        }) = higher::Range::hir(arg);
+        let (mut_id_start, mut_id_end) = (check_for_mutability(cx, start), check_for_mutability(cx, end));
+        if mut_id_start.is_some() || mut_id_end.is_some();
+        then {
+            let (span_low, span_high) = check_for_mutation(cx, body, mut_id_start, mut_id_end);
             mut_warn_with_span(cx, span_low);
             mut_warn_with_span(cx, span_high);
         }
@@ -27,11 +30,13 @@ pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<'_>) {
 
 fn mut_warn_with_span(cx: &LateContext<'_>, span: Option<Span>) {
     if let Some(sp) = span {
-        span_lint(
+        span_lint_and_note(
             cx,
             MUT_RANGE_BOUND,
             sp,
-            "attempt to mutate range bound within loop; note that the range of the loop is unchanged",
+            "attempt to mutate range bound within loop",
+            None,
+            "the range of the loop is unchanged",
         );
     }
 }
@@ -51,12 +56,13 @@ fn check_for_mutability(cx: &LateContext<'_>, bound: &Expr<'_>) -> Option<HirId>
 fn check_for_mutation<'tcx>(
     cx: &LateContext<'tcx>,
     body: &Expr<'_>,
-    bound_ids: &[Option<HirId>],
+    bound_id_start: Option<HirId>,
+    bound_id_end: Option<HirId>,
 ) -> (Option<Span>, Option<Span>) {
     let mut delegate = MutatePairDelegate {
         cx,
-        hir_id_low: bound_ids[0],
-        hir_id_high: bound_ids[1],
+        hir_id_low: bound_id_start,
+        hir_id_high: bound_id_end,
         span_low: None,
         span_high: None,
     };
@@ -70,6 +76,7 @@ fn check_for_mutation<'tcx>(
         )
         .walk_expr(body);
     });
+
     delegate.mutation_span()
 }
 
@@ -87,10 +94,10 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
     fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, bk: ty::BorrowKind) {
         if let ty::BorrowKind::MutBorrow = bk {
             if let PlaceBase::Local(id) = cmt.place.base {
-                if Some(id) == self.hir_id_low {
+                if Some(id) == self.hir_id_low && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) {
                     self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id));
                 }
-                if Some(id) == self.hir_id_high {
+                if Some(id) == self.hir_id_high && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) {
                     self.span_high = Some(self.cx.tcx.hir().span(diag_expr_id));
                 }
             }
@@ -99,10 +106,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 {
+            if Some(id) == self.hir_id_low && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) {
                 self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id));
             }
-            if Some(id) == self.hir_id_high {
+            if Some(id) == self.hir_id_high && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) {
                 self.span_high = Some(self.cx.tcx.hir().span(diag_expr_id));
             }
         }
@@ -116,3 +123,52 @@ impl MutatePairDelegate<'_, '_> {
         (self.span_low, self.span_high)
     }
 }
+
+struct BreakAfterExprVisitor {
+    hir_id: HirId,
+    past_expr: bool,
+    past_candidate: bool,
+    break_after_expr: bool,
+}
+
+impl BreakAfterExprVisitor {
+    pub fn is_found(cx: &LateContext<'_>, hir_id: HirId) -> bool {
+        let mut visitor = BreakAfterExprVisitor {
+            hir_id,
+            past_expr: false,
+            past_candidate: false,
+            break_after_expr: false,
+        };
+
+        get_enclosing_block(cx, hir_id).map_or(false, |block| {
+            visitor.visit_block(block);
+            visitor.break_after_expr
+        })
+    }
+}
+
+impl intravisit::Visitor<'tcx> for BreakAfterExprVisitor {
+    type Map = Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::None
+    }
+
+    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
+        if self.past_candidate {
+            return;
+        }
+
+        if expr.hir_id == self.hir_id {
+            self.past_expr = true;
+        } else if self.past_expr {
+            if matches!(&expr.kind, ExprKind::Break(..)) {
+                self.break_after_expr = true;
+            }
+
+            self.past_candidate = true;
+        } else {
+            intravisit::walk_expr(self, expr);
+        }
+    }
+}
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 51d7def137e..f90ed7397e1 100644
--- a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
@@ -26,7 +26,7 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont
         if chain_method.ident.name == sym!(collect) && is_trait_method(cx, &args[0], sym::Iterator);
         then {
             let ty = cx.typeck_results().expr_ty(&args[0]);
-            let mut applicability = Applicability::MachineApplicable;
+            let mut applicability = Applicability::MaybeIncorrect;
             let is_empty_sugg = "next().is_none()".to_string();
             let method_name = &*method.ident.name.as_str();
             let sugg = if is_type_diagnostic_item(cx, ty, sym::vec_type) ||
@@ -113,7 +113,7 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
                                     (stmt.span, String::new()),
                                     (iter_call.span, iter_replacement)
                                 ],
-                                Applicability::MachineApplicable,// MaybeIncorrect,
+                                Applicability::MaybeIncorrect,
                             );
                         },
                     );
diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
index 3f77e7af927..7157b801185 100644
--- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
@@ -2,10 +2,8 @@ use super::NEEDLESS_RANGE_LOOP;
 use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
 use clippy_utils::source::snippet;
 use clippy_utils::ty::has_iter_method;
-use clippy_utils::visitors::LocalUsedVisitor;
-use clippy_utils::{
-    contains_name, higher, is_integer_const, match_trait_method, path_to_local_id, paths, sugg, SpanlessEq,
-};
+use clippy_utils::visitors::is_local_used;
+use clippy_utils::{contains_name, higher, is_integer_const, match_trait_method, paths, sugg, SpanlessEq};
 use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -146,7 +144,7 @@ pub(super) fn check<'tcx>(
                     span_lint_and_then(
                         cx,
                         NEEDLESS_RANGE_LOOP,
-                        expr.span,
+                        arg.span,
                         &format!("the loop variable `{}` is used to index `{}`", ident.name, indexed),
                         |diag| {
                             multispan_sugg(
@@ -172,7 +170,7 @@ pub(super) fn check<'tcx>(
                     span_lint_and_then(
                         cx,
                         NEEDLESS_RANGE_LOOP,
-                        expr.span,
+                        arg.span,
                         &format!("the loop variable `{}` is only used to index `{}`", ident.name, indexed),
                         |diag| {
                             multispan_sugg(
@@ -256,43 +254,36 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
             if let ExprKind::Path(ref seqpath) = seqexpr.kind;
             if let QPath::Resolved(None, seqvar) = *seqpath;
             if seqvar.segments.len() == 1;
-            let index_used_directly = path_to_local_id(idx, self.var);
-            let indexed_indirectly = {
-                let mut used_visitor = LocalUsedVisitor::new(self.cx, self.var);
-                walk_expr(&mut used_visitor, idx);
-                used_visitor.used
-            };
-            if indexed_indirectly || index_used_directly;
+            if is_local_used(self.cx, idx, self.var);
             then {
                 if self.prefer_mutable {
                     self.indexed_mut.insert(seqvar.segments[0].ident.name);
                 }
+                let index_used_directly = matches!(idx.kind, ExprKind::Path(_));
                 let res = self.cx.qpath_res(seqpath, seqexpr.hir_id);
                 match res {
                     Res::Local(hir_id) => {
                         let parent_id = self.cx.tcx.hir().get_parent_item(expr.hir_id);
                         let parent_def_id = self.cx.tcx.hir().local_def_id(parent_id);
                         let extent = self.cx.tcx.region_scope_tree(parent_def_id).var_scope(hir_id.local_id);
-                        if indexed_indirectly {
-                            self.indexed_indirectly.insert(seqvar.segments[0].ident.name, Some(extent));
-                        }
                         if index_used_directly {
                             self.indexed_directly.insert(
                                 seqvar.segments[0].ident.name,
                                 (Some(extent), self.cx.typeck_results().node_type(seqexpr.hir_id)),
                             );
+                        } else {
+                            self.indexed_indirectly.insert(seqvar.segments[0].ident.name, Some(extent));
                         }
                         return false;  // no need to walk further *on the variable*
                     }
                     Res::Def(DefKind::Static | DefKind::Const, ..) => {
-                        if indexed_indirectly {
-                            self.indexed_indirectly.insert(seqvar.segments[0].ident.name, None);
-                        }
                         if index_used_directly {
                             self.indexed_directly.insert(
                                 seqvar.segments[0].ident.name,
                                 (None, self.cx.typeck_results().node_type(seqexpr.hir_id)),
                             );
+                        } else {
+                            self.indexed_indirectly.insert(seqvar.segments[0].ident.name, None);
                         }
                         return false;  // no need to walk further *on the variable*
                     }
@@ -310,10 +301,10 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         if_chain! {
             // a range index op
-            if let ExprKind::MethodCall(meth, _, args, _) = expr.kind;
+            if let ExprKind::MethodCall(meth, _, [args_0, args_1, ..], _) = &expr.kind;
             if (meth.ident.name == sym::index && match_trait_method(self.cx, expr, &paths::INDEX))
                 || (meth.ident.name == sym::index_mut && match_trait_method(self.cx, expr, &paths::INDEX_MUT));
-            if !self.check(&args[1], &args[0], expr);
+            if !self.check(args_1, args_0, expr);
             then { return }
         }
 
diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
index 2c46971d5f7..41956650c9f 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -87,7 +87,7 @@ fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult) -> NeverLoopResult
 
 fn never_loop_block(block: &Block<'_>, main_loop_id: HirId) -> NeverLoopResult {
     let stmts = block.stmts.iter().map(stmt_to_expr);
-    let expr = once(block.expr.as_deref());
+    let expr = once(block.expr);
     let mut iter = stmts.chain(expr).flatten();
     never_loop_expr_seq(&mut iter, main_loop_id)
 }
@@ -100,7 +100,7 @@ fn never_loop_expr_seq<'a, T: Iterator<Item = &'a Expr<'a>>>(es: &mut T, main_lo
 fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<&'tcx Expr<'tcx>> {
     match stmt.kind {
         StmtKind::Semi(e, ..) | StmtKind::Expr(e, ..) => Some(e),
-        StmtKind::Local(local) => local.init.as_deref(),
+        StmtKind::Local(local) => local.init,
         StmtKind::Item(..) => None,
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs
index d6d3315e0a8..1848f5b5de2 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs
@@ -24,13 +24,13 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_block: &'
             }
         }
 
-        if let ExprKind::Match(ref matchexpr, ref arms, MatchSource::Normal) = inner.kind {
+        if let ExprKind::Match(matchexpr, arms, MatchSource::Normal) = inner.kind {
             if arms.len() == 2
                 && arms[0].guard.is_none()
                 && arms[1].guard.is_none()
-                && is_simple_break_expr(&arms[1].body)
+                && is_simple_break_expr(arms[1].body)
             {
-                could_be_while_let(cx, expr, &arms[0].pat, matchexpr);
+                could_be_while_let(cx, expr, arms[0].pat, matchexpr);
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
index 0757d329125..79527e3bfa9 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
@@ -14,12 +14,7 @@ use rustc_span::{symbol::sym, Span, Symbol};
 
 pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
     let (scrutinee_expr, iter_expr, some_pat, loop_expr) = if_chain! {
-        if let Some(higher::WhileLet {
-            if_then,
-            let_pat,
-            let_expr,
-            ..
-        }) = higher::WhileLet::hir(expr);
+        if let Some(higher::WhileLet { if_then, let_pat, let_expr }) = higher::WhileLet::hir(expr);
         // check for `Some(..)` pattern
         if let PatKind::TupleStruct(QPath::Resolved(None, pat_path), some_pat, _) = let_pat.kind;
         if let Res::Def(_, pat_did) = pat_path.res;
diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs
index 39f7ade3f81..41e6ad12d05 100644
--- a/src/tools/clippy/clippy_lints/src/macro_use.rs
+++ b/src/tools/clippy/clippy_lints/src/macro_use.rs
@@ -29,37 +29,21 @@ declare_clippy_lint! {
     "#[macro_use] is no longer needed"
 }
 
-const BRACKETS: &[char] = &['<', '>'];
-
 #[derive(Clone, Debug, PartialEq, Eq)]
 struct PathAndSpan {
     path: String,
     span: Span,
 }
 
-/// `MacroRefData` includes the name of the macro
-/// and the path from `SourceMap::span_to_filename`.
+/// `MacroRefData` includes the name of the macro.
 #[derive(Debug, Clone)]
 pub struct MacroRefData {
     name: String,
-    path: String,
 }
 
 impl MacroRefData {
-    pub fn new(name: String, callee: Span, cx: &LateContext<'_>) -> Self {
-        let sm = cx.sess().source_map();
-        let mut path = sm.filename_for_diagnostics(&sm.span_to_filename(callee))
-            .to_string();
-
-        // std lib paths are <::std::module::file type>
-        // so remove brackets, space and type.
-        if path.contains('<') {
-            path = path.replace(BRACKETS, "");
-        }
-        if path.contains(' ') {
-            path = path.split(' ').next().unwrap().to_string();
-        }
-        Self { name, path }
+    pub fn new(name: String) -> Self {
+        Self { name }
     }
 }
 
@@ -79,7 +63,7 @@ impl MacroUseImports {
     fn push_unique_macro(&mut self, cx: &LateContext<'_>, span: Span) {
         let call_site = span.source_callsite();
         let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_");
-        if let Some(callee) = span.source_callee() {
+        if let Some(_callee) = span.source_callee() {
             if !self.collected.contains(&call_site) {
                 let name = if name.contains("::") {
                     name.split("::").last().unwrap().to_string()
@@ -87,7 +71,7 @@ impl MacroUseImports {
                     name.to_string()
                 };
 
-                self.mac_refs.push(MacroRefData::new(name, callee.def_site, cx));
+                self.mac_refs.push(MacroRefData::new(name));
                 self.collected.insert(call_site);
             }
         }
@@ -96,10 +80,10 @@ impl MacroUseImports {
     fn push_unique_macro_pat_ty(&mut self, cx: &LateContext<'_>, span: Span) {
         let call_site = span.source_callsite();
         let name = snippet(cx, cx.sess().source_map().span_until_char(call_site, '!'), "_");
-        if let Some(callee) = span.source_callee() {
+        if let Some(_callee) = span.source_callee() {
             if !self.collected.contains(&call_site) {
                 self.mac_refs
-                    .push(MacroRefData::new(name.to_string(), callee.def_site, cx));
+                    .push(MacroRefData::new(name.to_string()));
                 self.collected.insert(call_site);
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/manual_map.rs b/src/tools/clippy/clippy_lints/src/manual_map.rs
index 161d8841490..b5f573cb104 100644
--- a/src/tools/clippy/clippy_lints/src/manual_map.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_map.rs
@@ -1,16 +1,18 @@
 use crate::{map_unit_fn::OPTION_MAP_UNIT_FN, matches::MATCH_AS_REF};
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::higher;
+use clippy_utils::higher::IfLetOrMatch;
 use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
 use clippy_utils::ty::{is_type_diagnostic_item, peel_mid_ty_refs_is_mutable};
 use clippy_utils::{
     can_move_expr_to_closure, in_constant, is_else_clause, is_lang_ctor, is_lint_allowed, path_to_local_id,
-    peel_hir_expr_refs,
+    peel_hir_expr_refs, peel_hir_expr_while, CaptureKind,
 };
 use rustc_ast::util::parser::PREC_POSTFIX;
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{OptionNone, OptionSome};
-use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, HirId, Mutability, Pat, PatKind};
+use rustc_hir::{
+    def::Res, Arm, BindingAnnotation, Block, Expr, ExprKind, HirId, Mutability, Pat, PatKind, Path, QPath,
+};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -44,168 +46,169 @@ declare_lint_pass!(ManualMap => [MANUAL_MAP]);
 impl LateLintPass<'_> for ManualMap {
     #[allow(clippy::too_many_lines)]
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if let Some(higher::IfLet {
-            let_pat,
-            let_expr,
-            if_then,
-            if_else: Some(if_else),
-        }) = higher::IfLet::hir(cx, expr)
-        {
-            manage_lint(cx, expr, (&let_pat.kind, if_then), (&PatKind::Wild, if_else), let_expr);
+        let (scrutinee, then_pat, then_body, else_pat, else_body) = match IfLetOrMatch::parse(cx, expr) {
+            Some(IfLetOrMatch::IfLet(scrutinee, pat, body, Some(r#else))) => (scrutinee, pat, body, None, r#else),
+            Some(IfLetOrMatch::Match(
+                scrutinee,
+                [arm1 @ Arm { guard: None, .. }, arm2 @ Arm { guard: None, .. }],
+                _,
+            )) => (scrutinee, arm1.pat, arm1.body, Some(arm2.pat), arm2.body),
+            _ => return,
+        };
+        if in_external_macro(cx.sess(), expr.span) || in_constant(cx, expr.hir_id) {
+            return;
         }
 
-        if let ExprKind::Match(scrutinee, [then @ Arm { guard: None, .. }, r#else @ Arm { guard: None, .. }], _) =
-            expr.kind
+        let (scrutinee_ty, ty_ref_count, ty_mutability) =
+            peel_mid_ty_refs_is_mutable(cx.typeck_results().expr_ty(scrutinee));
+        if !(is_type_diagnostic_item(cx, scrutinee_ty, sym::option_type)
+            && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::option_type))
         {
-            manage_lint(
-                cx,
-                expr,
-                (&then.pat.kind, then.body),
-                (&r#else.pat.kind, r#else.body),
-                scrutinee,
-            );
+            return;
         }
-    }
-}
-
-fn manage_lint<'tcx>(
-    cx: &LateContext<'tcx>,
-    expr: &'tcx Expr<'_>,
-    then: (&'tcx PatKind<'_>, &'tcx Expr<'_>),
-    r#else: (&'tcx PatKind<'_>, &'tcx Expr<'_>),
-    scrut: &'tcx Expr<'_>,
-) {
-    if in_external_macro(cx.sess(), expr.span) || in_constant(cx, expr.hir_id) {
-        return;
-    }
 
-    let (scrutinee_ty, ty_ref_count, ty_mutability) = peel_mid_ty_refs_is_mutable(cx.typeck_results().expr_ty(scrut));
-    if !(is_type_diagnostic_item(cx, scrutinee_ty, sym::option_type)
-        && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::option_type))
-    {
-        return;
-    }
+        let expr_ctxt = expr.span.ctxt();
+        let (some_expr, some_pat, pat_ref_count, is_wild_none) = match (
+            try_parse_pattern(cx, then_pat, expr_ctxt),
+            else_pat.map_or(Some(OptionPat::Wild), |p| try_parse_pattern(cx, p, expr_ctxt)),
+        ) {
+            (Some(OptionPat::Wild), Some(OptionPat::Some { pattern, ref_count })) if is_none_expr(cx, then_body) => {
+                (else_body, pattern, ref_count, true)
+            },
+            (Some(OptionPat::None), Some(OptionPat::Some { pattern, ref_count })) if is_none_expr(cx, then_body) => {
+                (else_body, pattern, ref_count, false)
+            },
+            (Some(OptionPat::Some { pattern, ref_count }), Some(OptionPat::Wild)) if is_none_expr(cx, else_body) => {
+                (then_body, pattern, ref_count, true)
+            },
+            (Some(OptionPat::Some { pattern, ref_count }), Some(OptionPat::None)) if is_none_expr(cx, else_body) => {
+                (then_body, pattern, ref_count, false)
+            },
+            _ => return,
+        };
 
-    let (then_pat, then_expr) = then;
-    let (else_pat, else_expr) = r#else;
+        // Top level or patterns aren't allowed in closures.
+        if matches!(some_pat.kind, PatKind::Or(_)) {
+            return;
+        }
 
-    let expr_ctxt = expr.span.ctxt();
-    let (some_expr, some_pat, pat_ref_count, is_wild_none) = match (
-        try_parse_pattern(cx, then_pat, expr_ctxt),
-        try_parse_pattern(cx, else_pat, expr_ctxt),
-    ) {
-        (Some(OptionPat::Wild), Some(OptionPat::Some { pattern, ref_count })) if is_none_expr(cx, then_expr) => {
-            (else_expr, pattern, ref_count, true)
-        },
-        (Some(OptionPat::None), Some(OptionPat::Some { pattern, ref_count })) if is_none_expr(cx, then_expr) => {
-            (else_expr, pattern, ref_count, false)
-        },
-        (Some(OptionPat::Some { pattern, ref_count }), Some(OptionPat::Wild)) if is_none_expr(cx, else_expr) => {
-            (then_expr, pattern, ref_count, true)
-        },
-        (Some(OptionPat::Some { pattern, ref_count }), Some(OptionPat::None)) if is_none_expr(cx, else_expr) => {
-            (then_expr, pattern, ref_count, false)
-        },
-        _ => return,
-    };
+        let some_expr = match get_some_expr(cx, some_expr, expr_ctxt) {
+            Some(expr) => expr,
+            None => return,
+        };
 
-    // Top level or patterns aren't allowed in closures.
-    if matches!(some_pat.kind, PatKind::Or(_)) {
-        return;
-    }
+        // These two lints will go back and forth with each other.
+        if cx.typeck_results().expr_ty(some_expr) == cx.tcx.types.unit
+            && !is_lint_allowed(cx, OPTION_MAP_UNIT_FN, expr.hir_id)
+        {
+            return;
+        }
 
-    let some_expr = match get_some_expr(cx, some_expr, expr_ctxt) {
-        Some(expr) => expr,
-        None => return,
-    };
+        // `map` won't perform any adjustments.
+        if !cx.typeck_results().expr_adjustments(some_expr).is_empty() {
+            return;
+        }
 
-    if cx.typeck_results().expr_ty(some_expr) == cx.tcx.types.unit && !is_lint_allowed(cx, OPTION_MAP_UNIT_FN, expr.hir_id) {
-        return;
-    }
+        // Determine which binding mode to use.
+        let explicit_ref = some_pat.contains_explicit_ref_binding();
+        let binding_ref = explicit_ref.or_else(|| (ty_ref_count != pat_ref_count).then(|| ty_mutability));
 
-    // `map` won't perform any adjustments.
-    if !cx.typeck_results().expr_adjustments(some_expr).is_empty() {
-        return;
-    }
+        let as_ref_str = match binding_ref {
+            Some(Mutability::Mut) => ".as_mut()",
+            Some(Mutability::Not) => ".as_ref()",
+            None => "",
+        };
 
-    if !can_move_expr_to_closure(cx, some_expr) {
-        return;
-    }
-
-    // Determine which binding mode to use.
-    let explicit_ref = some_pat.contains_explicit_ref_binding();
-    let binding_ref = explicit_ref.or_else(|| (ty_ref_count != pat_ref_count).then(|| ty_mutability));
+        match can_move_expr_to_closure(cx, some_expr) {
+            Some(captures) => {
+                // Check if captures the closure will need conflict with borrows made in the scrutinee.
+                // TODO: check all the references made in the scrutinee expression. This will require interacting
+                // with the borrow checker. Currently only `<local>[.<field>]*` is checked for.
+                if let Some(binding_ref_mutability) = binding_ref {
+                    let e = peel_hir_expr_while(scrutinee, |e| match e.kind {
+                        ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) => Some(e),
+                        _ => None,
+                    });
+                    if let ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(l), .. })) = e.kind {
+                        match captures.get(l) {
+                            Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return,
+                            Some(CaptureKind::Ref(Mutability::Not)) if binding_ref_mutability == Mutability::Mut => {
+                                return;
+                            },
+                            Some(CaptureKind::Ref(Mutability::Not)) | None => (),
+                        }
+                    }
+                }
+            },
+            None => return,
+        };
 
-    let as_ref_str = match binding_ref {
-        Some(Mutability::Mut) => ".as_mut()",
-        Some(Mutability::Not) => ".as_ref()",
-        None => "",
-    };
+        let mut app = Applicability::MachineApplicable;
 
-    let mut app = Applicability::MachineApplicable;
+        // Remove address-of expressions from the scrutinee. Either `as_ref` will be called, or
+        // it's being passed by value.
+        let scrutinee = peel_hir_expr_refs(scrutinee).0;
+        let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app);
+        let scrutinee_str =
+            if scrutinee.span.ctxt() == expr.span.ctxt() && scrutinee.precedence().order() < PREC_POSTFIX {
+                format!("({})", scrutinee_str)
+            } else {
+                scrutinee_str.into()
+            };
 
-    // Remove address-of expressions from the scrutinee. Either `as_ref` will be called, or
-    // it's being passed by value.
-    let scrutinee = peel_hir_expr_refs(scrut).0;
-    let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app);
-    let scrutinee_str = if scrutinee.span.ctxt() == expr.span.ctxt() && scrutinee.precedence().order() < PREC_POSTFIX {
-        format!("({})", scrutinee_str)
-    } else {
-        scrutinee_str.into()
-    };
+        let body_str = if let PatKind::Binding(annotation, id, some_binding, None) = some_pat.kind {
+            match can_pass_as_func(cx, id, some_expr) {
+                Some(func) if func.span.ctxt() == some_expr.span.ctxt() => {
+                    snippet_with_applicability(cx, func.span, "..", &mut app).into_owned()
+                },
+                _ => {
+                    if path_to_local_id(some_expr, id)
+                        && !is_lint_allowed(cx, MATCH_AS_REF, expr.hir_id)
+                        && binding_ref.is_some()
+                    {
+                        return;
+                    }
 
-    let body_str = if let PatKind::Binding(annotation, id, some_binding, None) = some_pat.kind {
-        match can_pass_as_func(cx, id, some_expr) {
-            Some(func) if func.span.ctxt() == some_expr.span.ctxt() => {
-                snippet_with_applicability(cx, func.span, "..", &mut app).into_owned()
-            },
-            _ => {
-                if path_to_local_id(some_expr, id)
-                    && !is_lint_allowed(cx, MATCH_AS_REF, expr.hir_id)
-                    && binding_ref.is_some()
-                {
-                    return;
-                }
+                    // `ref` and `ref mut` annotations were handled earlier.
+                    let annotation = if matches!(annotation, BindingAnnotation::Mutable) {
+                        "mut "
+                    } else {
+                        ""
+                    };
+                    format!(
+                        "|{}{}| {}",
+                        annotation,
+                        some_binding,
+                        snippet_with_context(cx, some_expr.span, expr_ctxt, "..", &mut app).0
+                    )
+                },
+            }
+        } else if !is_wild_none && explicit_ref.is_none() {
+            // TODO: handle explicit reference annotations.
+            format!(
+                "|{}| {}",
+                snippet_with_context(cx, some_pat.span, expr_ctxt, "..", &mut app).0,
+                snippet_with_context(cx, some_expr.span, expr_ctxt, "..", &mut app).0
+            )
+        } else {
+            // Refutable bindings and mixed reference annotations can't be handled by `map`.
+            return;
+        };
 
-                // `ref` and `ref mut` annotations were handled earlier.
-                let annotation = if matches!(annotation, BindingAnnotation::Mutable) {
-                    "mut "
-                } else {
-                    ""
-                };
-                format!(
-                    "|{}{}| {}",
-                    annotation,
-                    some_binding,
-                    snippet_with_context(cx, some_expr.span, expr_ctxt, "..", &mut app).0
-                )
+        span_lint_and_sugg(
+            cx,
+            MANUAL_MAP,
+            expr.span,
+            "manual implementation of `Option::map`",
+            "try this",
+            if else_pat.is_none() && is_else_clause(cx.tcx, expr) {
+                format!("{{ {}{}.map({}) }}", scrutinee_str, as_ref_str, body_str)
+            } else {
+                format!("{}{}.map({})", scrutinee_str, as_ref_str, body_str)
             },
-        }
-    } else if !is_wild_none && explicit_ref.is_none() {
-        // TODO: handle explicit reference annotations.
-        format!(
-            "|{}| {}",
-            snippet_with_context(cx, some_pat.span, expr_ctxt, "..", &mut app).0,
-            snippet_with_context(cx, some_expr.span, expr_ctxt, "..", &mut app).0
-        )
-    } else {
-        // Refutable bindings and mixed reference annotations can't be handled by `map`.
-        return;
-    };
-
-    span_lint_and_sugg(
-        cx,
-        MANUAL_MAP,
-        expr.span,
-        "manual implementation of `Option::map`",
-        "try this",
-        if is_else_clause(cx.tcx, expr) {
-            format!("{{ {}{}.map({}) }}", scrutinee_str, as_ref_str, body_str)
-        } else {
-            format!("{}{}.map({})", scrutinee_str, as_ref_str, body_str)
-        },
-        app,
-    );
+            app,
+        );
+    }
 }
 
 // Checks whether the expression could be passed as a function, or whether a closure is needed.
@@ -213,7 +216,7 @@ fn manage_lint<'tcx>(
 fn can_pass_as_func(cx: &LateContext<'tcx>, binding: HirId, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
     match expr.kind {
         ExprKind::Call(func, [arg])
-            if path_to_local_id (arg, binding) && cx.typeck_results().expr_adjustments(arg).is_empty() =>
+            if path_to_local_id(arg, binding) && cx.typeck_results().expr_adjustments(arg).is_empty() =>
         {
             Some(func)
         },
@@ -235,28 +238,21 @@ enum OptionPat<'a> {
 
 // Try to parse into a recognized `Option` pattern.
 // i.e. `_`, `None`, `Some(..)`, or a reference to any of those.
-fn try_parse_pattern(
-    cx: &LateContext<'tcx>,
-    pat_kind: &'tcx PatKind<'_>,
-    ctxt: SyntaxContext,
-) -> Option<OptionPat<'tcx>> {
-    fn f(
-        cx: &LateContext<'tcx>,
-        pat_kind: &'tcx PatKind<'_>,
-        ref_count: usize,
-        ctxt: SyntaxContext,
-    ) -> Option<OptionPat<'tcx>> {
-        match pat_kind {
+fn try_parse_pattern(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, ctxt: SyntaxContext) -> Option<OptionPat<'tcx>> {
+    fn f(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, ref_count: usize, ctxt: SyntaxContext) -> Option<OptionPat<'tcx>> {
+        match pat.kind {
             PatKind::Wild => Some(OptionPat::Wild),
-            PatKind::Ref(ref_pat, _) => f(cx, &ref_pat.kind, ref_count + 1, ctxt),
+            PatKind::Ref(pat, _) => f(cx, pat, ref_count + 1, ctxt),
             PatKind::Path(ref qpath) if is_lang_ctor(cx, qpath, OptionNone) => Some(OptionPat::None),
-            PatKind::TupleStruct(ref qpath, [pattern], _) if is_lang_ctor(cx, qpath, OptionSome) => {
+            PatKind::TupleStruct(ref qpath, [pattern], _)
+                if is_lang_ctor(cx, qpath, OptionSome) && pat.span.ctxt() == ctxt =>
+            {
                 Some(OptionPat::Some { pattern, ref_count })
             },
             _ => None,
         }
     }
-    f(cx, pat_kind, 0, ctxt)
+    f(cx, pat, 0, ctxt)
 }
 
 // Checks for an expression wrapped by the `Some` constructor. Returns the contained expression.
diff --git a/src/tools/clippy/clippy_lints/src/matches.rs b/src/tools/clippy/clippy_lints/src/matches.rs
index 3d0da472ddc..2f1ff567e84 100644
--- a/src/tools/clippy/clippy_lints/src/matches.rs
+++ b/src/tools/clippy/clippy_lints/src/matches.rs
@@ -6,7 +6,7 @@ use clippy_utils::higher;
 use clippy_utils::source::{expr_block, indent_of, snippet, snippet_block, snippet_opt, snippet_with_applicability};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, match_type, peel_mid_ty_refs};
-use clippy_utils::visitors::LocalUsedVisitor;
+use clippy_utils::visitors::is_local_used;
 use clippy_utils::{
     get_parent_expr, in_macro, is_expn_of, is_lang_ctor, is_lint_allowed, is_refutable, is_unit_expr, is_wild,
     meets_msrv, msrvs, path_to_local, path_to_local_id, peel_hir_pat_refs, peel_n_hir_expr_refs, recurse_or_patterns,
@@ -631,7 +631,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
                 check_match_single_binding(cx, ex, arms, expr);
             }
         }
-        if let ExprKind::Match(ref ex, ref arms, _) = expr.kind {
+        if let ExprKind::Match(ex, arms, _) = expr.kind {
             check_match_ref_pats(cx, ex, arms.iter().map(|el| el.pat), expr);
         }
         if let Some(higher::IfLet { let_pat, let_expr, .. }) = higher::IfLet::hir(cx, expr) {
@@ -959,9 +959,7 @@ fn check_wild_err_arm<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm
                         // Looking for unused bindings (i.e.: `_e`)
                         for pat in inner.iter() {
                             if let PatKind::Binding(_, id, ident, None) = pat.kind {
-                                if ident.as_str().starts_with('_')
-                                    && !LocalUsedVisitor::new(cx, id).check_expr(arm.body)
-                                {
+                                if ident.as_str().starts_with('_') && !is_local_used(cx, arm.body, id) {
                                     ident_bind_name = (&ident.name.as_str()).to_string();
                                     matching_wild = true;
                                 }
@@ -1196,7 +1194,7 @@ where
 
     let (first_sugg, msg, title);
     let span = ex.span.source_callsite();
-    if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, ref inner) = ex.kind {
+    if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = ex.kind {
         first_sugg = once((span, Sugg::hir_with_macro_callsite(cx, inner, "..").to_string()));
         msg = "try";
         title = "you don't need to add `&` to both the expression and the patterns";
@@ -1207,7 +1205,7 @@ where
     }
 
     let remaining_suggs = pats.filter_map(|pat| {
-        if let PatKind::Ref(ref refp, _) = pat.kind {
+        if let PatKind::Ref(refp, _) = pat.kind {
             Some((pat.span, snippet(cx, refp.span, "..").to_string()))
         } else {
             None
@@ -1367,7 +1365,7 @@ where
                 find_bool_lit(&arm.2.kind, is_if_let).map_or(false, |b| b == b0) && arm.3.is_none() && arm.0.is_empty()
             });
         then {
-            if let Some(ref last_pat) = last_pat_opt {
+            if let Some(last_pat) = last_pat_opt {
                 if !is_wild(last_pat) {
                     return false;
                 }
@@ -1829,13 +1827,13 @@ mod redundant_pattern_match {
             ..
         }) = higher::IfLet::hir(cx, expr)
         {
-            find_sugg_for_if_let(cx, expr, let_pat, let_expr, "if", if_else.is_some())
+            find_sugg_for_if_let(cx, expr, let_pat, let_expr, "if", if_else.is_some());
         }
         if let ExprKind::Match(op, arms, MatchSource::Normal) = &expr.kind {
-            find_sugg_for_match(cx, expr, op, arms)
+            find_sugg_for_match(cx, expr, op, arms);
         }
         if let Some(higher::WhileLet { let_pat, let_expr, .. }) = higher::WhileLet::hir(expr) {
-            find_sugg_for_if_let(cx, expr, let_pat, let_expr, "while", false)
+            find_sugg_for_if_let(cx, expr, let_pat, let_expr, "while", false);
         }
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/mem_forget.rs b/src/tools/clippy/clippy_lints/src/mem_forget.rs
index 07202a59c4b..eb437dc47af 100644
--- a/src/tools/clippy/clippy_lints/src/mem_forget.rs
+++ b/src/tools/clippy/clippy_lints/src/mem_forget.rs
@@ -28,11 +28,11 @@ declare_lint_pass!(MemForget => [MEM_FORGET]);
 
 impl<'tcx> LateLintPass<'tcx> for MemForget {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
-        if let ExprKind::Call(path_expr, args) = e.kind {
+        if let ExprKind::Call(path_expr, [ref first_arg, ..]) = e.kind {
             if let ExprKind::Path(ref qpath) = path_expr.kind {
                 if let Some(def_id) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id() {
                     if match_def_path(cx, def_id, &paths::MEM_FORGET) {
-                        let forgot_ty = cx.typeck_results().expr_ty(&args[0]);
+                        let forgot_ty = cx.typeck_results().expr_ty(first_arg);
 
                         if forgot_ty.ty_adt_def().map_or(false, |def| def.has_dtor(cx.tcx)) {
                             span_lint(cx, MEM_FORGET, e.span, "usage of `mem::forget` on `Drop` type");
diff --git a/src/tools/clippy/clippy_lints/src/mem_replace.rs b/src/tools/clippy/clippy_lints/src/mem_replace.rs
index 3d071c9081b..1e6057a8fe9 100644
--- a/src/tools/clippy/clippy_lints/src/mem_replace.rs
+++ b/src/tools/clippy/clippy_lints/src/mem_replace.rs
@@ -1,9 +1,9 @@
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::{snippet, snippet_with_applicability};
-use clippy_utils::{in_macro, is_diag_trait_item, is_lang_ctor, match_def_path, meets_msrv, msrvs, paths};
+use clippy_utils::ty::is_non_aggregate_primitive_type;
+use clippy_utils::{in_macro, is_default_equivalent, is_lang_ctor, match_def_path, meets_msrv, msrvs, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::def_id::DefId;
 use rustc_hir::LangItem::OptionNone;
 use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, QPath};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -194,64 +194,37 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'
     }
 }
 
-/// Returns true if the `def_id` associated with the `path` is recognized as a "default-equivalent"
-/// constructor from the std library
-fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath<'_>) -> bool {
-    let std_types_symbols = &[
-        sym::string_type,
-        sym::vec_type,
-        sym::vecdeque_type,
-        sym::LinkedList,
-        sym::hashmap_type,
-        sym::BTreeMap,
-        sym::hashset_type,
-        sym::BTreeSet,
-        sym::BinaryHeap,
-    ];
-
-    if let QPath::TypeRelative(_, method) = path {
-        if method.ident.name == sym::new {
-            if let Some(impl_did) = cx.tcx.impl_of_method(def_id) {
-                if let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def() {
-                    return std_types_symbols
-                        .iter()
-                        .any(|&symbol| cx.tcx.is_diagnostic_item(symbol, adt.did));
-                }
-            }
+fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) {
+    // disable lint for primitives
+    let expr_type = cx.typeck_results().expr_ty_adjusted(src);
+    if is_non_aggregate_primitive_type(expr_type) {
+        return;
+    }
+    // disable lint for Option since it is covered in another lint
+    if let ExprKind::Path(q) = &src.kind {
+        if is_lang_ctor(cx, q, OptionNone) {
+            return;
         }
     }
-    false
-}
+    if is_default_equivalent(cx, src) && !in_external_macro(cx.tcx.sess, expr_span) {
+        span_lint_and_then(
+            cx,
+            MEM_REPLACE_WITH_DEFAULT,
+            expr_span,
+            "replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`",
+            |diag| {
+                if !in_macro(expr_span) {
+                    let suggestion = format!("std::mem::take({})", snippet(cx, dest.span, ""));
 
-fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) {
-    if_chain! {
-        if let ExprKind::Call(repl_func, _) = src.kind;
-        if !in_external_macro(cx.tcx.sess, expr_span);
-        if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
-        if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
-        if is_diag_trait_item(cx, repl_def_id, sym::Default)
-            || is_default_equivalent_ctor(cx, repl_def_id, repl_func_qpath);
-
-        then {
-            span_lint_and_then(
-                cx,
-                MEM_REPLACE_WITH_DEFAULT,
-                expr_span,
-                "replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`",
-                |diag| {
-                    if !in_macro(expr_span) {
-                        let suggestion = format!("std::mem::take({})", snippet(cx, dest.span, ""));
-
-                        diag.span_suggestion(
-                            expr_span,
-                            "consider using",
-                            suggestion,
-                            Applicability::MachineApplicable
-                        );
-                    }
+                    diag.span_suggestion(
+                        expr_span,
+                        "consider using",
+                        suggestion,
+                        Applicability::MachineApplicable,
+                    );
                 }
-            );
-        }
+            },
+        );
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs
index 172714f6b01..bcf8d93b602 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
-use clippy_utils::is_trait_method;
 use clippy_utils::source::snippet;
+use clippy_utils::ty::implements_trait;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -16,7 +16,10 @@ pub(super) fn check<'tcx>(
     filter_arg: &'tcx hir::Expr<'_>,
 ) {
     // lint if caller of `.filter().next()` is an Iterator
-    if is_trait_method(cx, expr, sym::Iterator) {
+    let recv_impls_iterator = cx.tcx.get_diagnostic_item(sym::Iterator).map_or(false, |id| {
+        implements_trait(cx, cx.typeck_results().expr_ty(recv), id, &[])
+    });
+    if recv_impls_iterator {
         let msg = "called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling \
                    `.find(..)` instead";
         let filter_snippet = snippet(cx, filter_arg.span, "..");
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_split_once.rs b/src/tools/clippy/clippy_lints/src/methods/manual_split_once.rs
new file mode 100644
index 00000000000..00167650324
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_split_once.rs
@@ -0,0 +1,213 @@
+use clippy_utils::consts::{constant, Constant};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_context;
+use clippy_utils::{is_diag_item_method, match_def_path, paths};
+use if_chain::if_chain;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind, HirId, LangItem, Node, QPath};
+use rustc_lint::LateContext;
+use rustc_middle::ty::{self, adjustment::Adjust};
+use rustc_span::{symbol::sym, Span, SyntaxContext};
+
+use super::MANUAL_SPLIT_ONCE;
+
+pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, self_arg: &Expr<'_>, pat_arg: &Expr<'_>) {
+    if !cx.typeck_results().expr_ty_adjusted(self_arg).peel_refs().is_str() {
+        return;
+    }
+
+    let ctxt = expr.span.ctxt();
+    let usage = match parse_iter_usage(cx, ctxt, cx.tcx.hir().parent_iter(expr.hir_id)) {
+        Some(x) => x,
+        None => return,
+    };
+    let (method_name, msg) = if method_name == "splitn" {
+        ("split_once", "manual implementation of `split_once`")
+    } else {
+        ("rsplit_once", "manual implementation of `rsplit_once`")
+    };
+
+    let mut app = Applicability::MachineApplicable;
+    let self_snip = snippet_with_context(cx, self_arg.span, ctxt, "..", &mut app).0;
+    let pat_snip = snippet_with_context(cx, pat_arg.span, ctxt, "..", &mut app).0;
+
+    match usage.kind {
+        IterUsageKind::NextTuple => {
+            span_lint_and_sugg(
+                cx,
+                MANUAL_SPLIT_ONCE,
+                usage.span,
+                msg,
+                "try this",
+                format!("{}.{}({})", self_snip, method_name, pat_snip),
+                app,
+            );
+        },
+        IterUsageKind::Next => {
+            let self_deref = {
+                let adjust = cx.typeck_results().expr_adjustments(self_arg);
+                if adjust.is_empty() {
+                    String::new()
+                } else if cx.typeck_results().expr_ty(self_arg).is_box()
+                    || adjust
+                        .iter()
+                        .any(|a| matches!(a.kind, Adjust::Deref(Some(_))) || a.target.is_box())
+                {
+                    format!("&{}", "*".repeat(adjust.len() - 1))
+                } else {
+                    "*".repeat(adjust.len() - 2)
+                }
+            };
+            let sugg = if usage.unwrap_kind.is_some() {
+                format!(
+                    "{}.{}({}).map_or({}{}, |x| x.0)",
+                    &self_snip, method_name, pat_snip, self_deref, &self_snip
+                )
+            } else {
+                format!(
+                    "Some({}.{}({}).map_or({}{}, |x| x.0))",
+                    &self_snip, method_name, pat_snip, self_deref, &self_snip
+                )
+            };
+
+            span_lint_and_sugg(cx, MANUAL_SPLIT_ONCE, usage.span, msg, "try this", sugg, app);
+        },
+        IterUsageKind::Second => {
+            let access_str = match usage.unwrap_kind {
+                Some(UnwrapKind::Unwrap) => ".unwrap().1",
+                Some(UnwrapKind::QuestionMark) => "?.1",
+                None => ".map(|x| x.1)",
+            };
+            span_lint_and_sugg(
+                cx,
+                MANUAL_SPLIT_ONCE,
+                usage.span,
+                msg,
+                "try this",
+                format!("{}.{}({}){}", self_snip, method_name, pat_snip, access_str),
+                app,
+            );
+        },
+    }
+}
+
+enum IterUsageKind {
+    Next,
+    Second,
+    NextTuple,
+}
+
+enum UnwrapKind {
+    Unwrap,
+    QuestionMark,
+}
+
+struct IterUsage {
+    kind: IterUsageKind,
+    unwrap_kind: Option<UnwrapKind>,
+    span: Span,
+}
+
+fn parse_iter_usage(
+    cx: &LateContext<'tcx>,
+    ctxt: SyntaxContext,
+    mut iter: impl Iterator<Item = (HirId, Node<'tcx>)>,
+) -> Option<IterUsage> {
+    let (kind, span) = match iter.next() {
+        Some((_, Node::Expr(e))) if e.span.ctxt() == ctxt => {
+            let (name, args) = if let ExprKind::MethodCall(name, _, [_, args @ ..], _) = e.kind {
+                (name, args)
+            } else {
+                return None;
+            };
+            let did = cx.typeck_results().type_dependent_def_id(e.hir_id)?;
+            let iter_id = cx.tcx.get_diagnostic_item(sym::Iterator)?;
+
+            match (&*name.ident.as_str(), args) {
+                ("next", []) if cx.tcx.trait_of_item(did) == Some(iter_id) => (IterUsageKind::Next, e.span),
+                ("next_tuple", []) => {
+                    if_chain! {
+                        if match_def_path(cx, did, &paths::ITERTOOLS_NEXT_TUPLE);
+                        if let ty::Adt(adt_def, subs) = cx.typeck_results().expr_ty(e).kind();
+                        if cx.tcx.is_diagnostic_item(sym::option_type, adt_def.did);
+                        if let ty::Tuple(subs) = subs.type_at(0).kind();
+                        if subs.len() == 2;
+                        then {
+                            return Some(IterUsage { kind: IterUsageKind::NextTuple, span: e.span, unwrap_kind: None });
+                        } else {
+                            return None;
+                        }
+                    }
+                },
+                ("nth" | "skip", [idx_expr]) if cx.tcx.trait_of_item(did) == Some(iter_id) => {
+                    if let Some((Constant::Int(idx), _)) = constant(cx, cx.typeck_results(), idx_expr) {
+                        let span = if name.ident.as_str() == "nth" {
+                            e.span
+                        } else {
+                            if_chain! {
+                                if let Some((_, Node::Expr(next_expr))) = iter.next();
+                                if let ExprKind::MethodCall(next_name, _, [_], _) = next_expr.kind;
+                                if next_name.ident.name == sym::next;
+                                if next_expr.span.ctxt() == ctxt;
+                                if let Some(next_id) = cx.typeck_results().type_dependent_def_id(next_expr.hir_id);
+                                if cx.tcx.trait_of_item(next_id) == Some(iter_id);
+                                then {
+                                    next_expr.span
+                                } else {
+                                    return None;
+                                }
+                            }
+                        };
+                        match idx {
+                            0 => (IterUsageKind::Next, span),
+                            1 => (IterUsageKind::Second, span),
+                            _ => return None,
+                        }
+                    } else {
+                        return None;
+                    }
+                },
+                _ => return None,
+            }
+        },
+        _ => return None,
+    };
+
+    let (unwrap_kind, span) = if let Some((_, Node::Expr(e))) = iter.next() {
+        match e.kind {
+            ExprKind::Call(
+                Expr {
+                    kind: ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, _)),
+                    ..
+                },
+                _,
+            ) => {
+                let parent_span = e.span.parent_callsite().unwrap();
+                if parent_span.ctxt() == ctxt {
+                    (Some(UnwrapKind::QuestionMark), parent_span)
+                } else {
+                    (None, span)
+                }
+            },
+            _ if e.span.ctxt() != ctxt => (None, span),
+            ExprKind::MethodCall(name, _, [_], _)
+                if name.ident.name == sym::unwrap
+                    && cx
+                        .typeck_results()
+                        .type_dependent_def_id(e.hir_id)
+                        .map_or(false, |id| is_diag_item_method(cx, id, sym::option_type)) =>
+            {
+                (Some(UnwrapKind::Unwrap), e.span)
+            },
+            _ => (None, span),
+        }
+    } else {
+        (None, span)
+    };
+
+    Some(IterUsage {
+        kind,
+        unwrap_kind,
+        span,
+    })
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 9626cf79dc1..e89b2d295b9 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -33,6 +33,7 @@ mod iter_nth_zero;
 mod iter_skip_next;
 mod iterator_step_by_zero;
 mod manual_saturating_arithmetic;
+mod manual_split_once;
 mod manual_str_repeat;
 mod map_collect_result_unit;
 mod map_flatten;
@@ -64,6 +65,7 @@ mod wrong_self_convention;
 mod zst_offset;
 
 use bind_instead_of_map::BindInsteadOfMap;
+use clippy_utils::consts::{constant, Constant};
 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, meets_msrv, msrvs, paths, return_ty};
@@ -1771,6 +1773,29 @@ declare_clippy_lint! {
     "manual implementation of `str::repeat`"
 }
 
+declare_clippy_lint! {
+    /// **What it does:** Checks for usages of `str::splitn(2, _)`
+    ///
+    /// **Why is this bad?** `split_once` is both clearer in intent and slightly more efficient.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust,ignore
+    /// // Bad
+    ///  let (key, value) = _.splitn(2, '=').next_tuple()?;
+    ///  let value = _.splitn(2, '=').nth(1)?;
+    ///
+    /// // Good
+    /// let (key, value) = _.split_once('=')?;
+    /// let value = _.split_once('=')?.1;
+    /// ```
+    pub MANUAL_SPLIT_ONCE,
+    complexity,
+    "replace `.splitn(2, pat)` with `.split_once(pat)`"
+}
+
 pub struct Methods {
     avoid_breaking_exported_api: bool,
     msrv: Option<RustcVersion>,
@@ -1848,7 +1873,8 @@ impl_lint_pass!(Methods => [
     IMPLICIT_CLONE,
     SUSPICIOUS_SPLITN,
     MANUAL_STR_REPEAT,
-    EXTEND_WITH_DRAIN
+    EXTEND_WITH_DRAIN,
+    MANUAL_SPLIT_ONCE
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
@@ -2176,8 +2202,18 @@ 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);
+            ("splitn" | "rsplitn", [count_arg, pat_arg]) => {
+                if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) {
+                    suspicious_splitn::check(cx, name, expr, recv, count);
+                    if count == 2 && meets_msrv(msrv, &msrvs::STR_SPLIT_ONCE) {
+                        manual_split_once::check(cx, name, expr, recv, pat_arg);
+                    }
+                }
+            },
+            ("splitn_mut" | "rsplitn_mut", [count_arg, _]) => {
+                if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) {
+                    suspicious_splitn::check(cx, name, expr, recv, count);
+                }
             },
             ("step_by", [arg]) => iterator_step_by_zero::check(cx, expr, arg),
             ("to_os_string" | "to_owned" | "to_path_buf" | "to_vec", []) => {
diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
index c1d22e5d72c..30ed1d665a9 100644
--- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
@@ -96,9 +96,9 @@ pub(super) fn check<'tcx>(
             (&paths::RESULT, true, &["or", "unwrap_or"], "else"),
         ];
 
-        if let hir::ExprKind::MethodCall(path, _, args, _) = &arg.kind {
+        if let hir::ExprKind::MethodCall(path, _, [self_arg, ..], _) = &arg.kind {
             if path.ident.name == sym::len {
-                let ty = cx.typeck_results().expr_ty(&args[0]).peel_refs();
+                let ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
 
                 match ty.kind() {
                     ty::Slice(_) | ty::Array(_, _) | ty::Str => return,
diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs
index a271df60572..1c546a15bf6 100644
--- a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs
@@ -1,4 +1,3 @@
-use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint_and_note;
 use if_chain::if_chain;
 use rustc_ast::LitKind;
@@ -8,15 +7,8 @@ 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<'_>,
-) {
+pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, self_arg: &Expr<'_>, count: u128) {
     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);
@@ -24,9 +16,9 @@ pub(super) fn check(
         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([]))
+            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;
             }
diff --git a/src/tools/clippy/clippy_lints/src/methods/utils.rs b/src/tools/clippy/clippy_lints/src/methods/utils.rs
index 0daea47816a..30d6665a920 100644
--- a/src/tools/clippy/clippy_lints/src/methods/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/utils.rs
@@ -24,9 +24,9 @@ pub(super) fn derefs_to_slice<'tcx>(
         }
     }
 
-    if let hir::ExprKind::MethodCall(path, _, args, _) = expr.kind {
-        if path.ident.name == sym::iter && may_slice(cx, cx.typeck_results().expr_ty(&args[0])) {
-            Some(&args[0])
+    if let hir::ExprKind::MethodCall(path, _, [self_arg, ..], _) = &expr.kind {
+        if path.ident.name == sym::iter && may_slice(cx, cx.typeck_results().expr_ty(self_arg)) {
+            Some(self_arg)
         } else {
             None
         }
diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs
index c796abe9815..538fa4e1678 100644
--- a/src/tools/clippy/clippy_lints/src/misc.rs
+++ b/src/tools/clippy/clippy_lints/src/misc.rs
@@ -513,12 +513,12 @@ fn is_signum(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     }
 
     if_chain! {
-        if let ExprKind::MethodCall(method_name, _, expressions, _) = expr.kind;
+        if let ExprKind::MethodCall(method_name, _, [ref self_arg, ..], _) = expr.kind;
         if sym!(signum) == method_name.ident.name;
         // Check that the receiver of the signum() is a float (expressions[0] is the receiver of
         // the method call)
         then {
-            return is_float(cx, &expressions[0]);
+            return is_float(cx, self_arg);
         }
     }
     false
diff --git a/src/tools/clippy/clippy_lints/src/module_style.rs b/src/tools/clippy/clippy_lints/src/module_style.rs
new file mode 100644
index 00000000000..f351d0098b7
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/module_style.rs
@@ -0,0 +1,178 @@
+use std::{
+    ffi::OsString,
+    path::{Component, Path},
+};
+
+use rustc_ast::ast;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::{FileName, RealFileName, SourceFile, Span, SyntaxContext};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks that module layout uses only self named module files, bans mod.rs files.
+    ///
+    /// ### Why is this bad?
+    /// Having multiple module layout styles in a project can be confusing.
+    ///
+    /// ### Example
+    /// ```text
+    /// src/
+    ///   stuff/
+    ///     stuff_files.rs
+    ///     mod.rs
+    ///   lib.rs
+    /// ```
+    /// Use instead:
+    /// ```text
+    /// src/
+    ///   stuff/
+    ///     stuff_files.rs
+    ///   stuff.rs
+    ///   lib.rs
+    /// ```
+    pub MOD_MODULE_FILES,
+    restriction,
+    "checks that module layout is consistent"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks that module layout uses only mod.rs files.
+    ///
+    /// ### Why is this bad?
+    /// Having multiple module layout styles in a project can be confusing.
+    ///
+    /// ### Example
+    /// ```text
+    /// src/
+    ///   stuff/
+    ///     stuff_files.rs
+    ///   stuff.rs
+    ///   lib.rs
+    /// ```
+    /// Use instead:
+    /// ```text
+    /// src/
+    ///   stuff/
+    ///     stuff_files.rs
+    ///     mod.rs
+    ///   lib.rs
+    /// ```
+
+    pub SELF_NAMED_MODULE_FILES,
+    restriction,
+    "checks that module layout is consistent"
+}
+
+pub struct ModStyle;
+
+impl_lint_pass!(ModStyle => [MOD_MODULE_FILES, SELF_NAMED_MODULE_FILES]);
+
+impl EarlyLintPass for ModStyle {
+    fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
+        if cx.builder.lint_level(MOD_MODULE_FILES).0 == Level::Allow
+            && cx.builder.lint_level(SELF_NAMED_MODULE_FILES).0 == Level::Allow
+        {
+            return;
+        }
+
+        let files = cx.sess.source_map().files();
+
+        let trim_to_src = if let RealFileName::LocalPath(p) = &cx.sess.opts.working_dir {
+            p.to_string_lossy()
+        } else {
+            return;
+        };
+
+        // `folder_segments` is all unique folder path segments `path/to/foo.rs` gives
+        // `[path, to]` but not foo
+        let mut folder_segments = FxHashSet::default();
+        // `mod_folders` is all the unique folder names that contain a mod.rs file
+        let mut mod_folders = FxHashSet::default();
+        // `file_map` maps file names to the full path including the file name
+        // `{ foo => path/to/foo.rs, .. }
+        let mut file_map = FxHashMap::default();
+        for file in files.iter() {
+            match &file.name {
+                FileName::Real(RealFileName::LocalPath(lp))
+                    if lp.to_string_lossy().starts_with(trim_to_src.as_ref()) =>
+                {
+                    let p = lp.to_string_lossy();
+                    let path = Path::new(p.trim_start_matches(trim_to_src.as_ref()));
+                    if let Some(stem) = path.file_stem() {
+                        file_map.insert(stem.to_os_string(), (file, path.to_owned()));
+                    }
+                    process_paths_for_mod_files(path, &mut folder_segments, &mut mod_folders);
+                    check_self_named_mod_exists(cx, path, file);
+                }
+                _ => {},
+            }
+        }
+
+        for folder in &folder_segments {
+            if !mod_folders.contains(folder) {
+                if let Some((file, path)) = file_map.get(folder) {
+                    let mut correct = path.clone();
+                    correct.pop();
+                    correct.push(folder);
+                    correct.push("mod.rs");
+                    cx.struct_span_lint(
+                        SELF_NAMED_MODULE_FILES,
+                        Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None),
+                        |build| {
+                            let mut lint =
+                                build.build(&format!("`mod.rs` files are required, found `{}`", path.display()));
+                            lint.help(&format!("move `{}` to `{}`", path.display(), correct.display(),));
+                            lint.emit();
+                        },
+                    );
+                }
+            }
+        }
+    }
+}
+
+/// For each `path` we add each folder component to `folder_segments` and if the file name
+/// is `mod.rs` we add it's parent folder to `mod_folders`.
+fn process_paths_for_mod_files(
+    path: &Path,
+    folder_segments: &mut FxHashSet<OsString>,
+    mod_folders: &mut FxHashSet<OsString>,
+) {
+    let mut comp = path.components().rev().peekable();
+    let _ = comp.next();
+    if path.ends_with("mod.rs") {
+        mod_folders.insert(comp.peek().map(|c| c.as_os_str().to_owned()).unwrap_or_default());
+    }
+    let folders = comp
+        .filter_map(|c| {
+            if let Component::Normal(s) = c {
+                Some(s.to_os_string())
+            } else {
+                None
+            }
+        })
+        .collect::<Vec<_>>();
+    folder_segments.extend(folders);
+}
+
+/// Checks every path for the presence of `mod.rs` files and emits the lint if found.
+fn check_self_named_mod_exists(cx: &EarlyContext<'_>, path: &Path, file: &SourceFile) {
+    if path.ends_with("mod.rs") {
+        let mut mod_file = path.to_path_buf();
+        mod_file.pop();
+        mod_file.set_extension("rs");
+
+        cx.struct_span_lint(
+            MOD_MODULE_FILES,
+            Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None),
+            |build| {
+                let mut lint = build.build(&format!("`mod.rs` files are not allowed, found `{}`", path.display()));
+                lint.help(&format!("move `{}` to `{}`", path.display(), mod_file.display(),));
+                lint.emit();
+            },
+        );
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/mut_mutex_lock.rs b/src/tools/clippy/clippy_lints/src/mut_mutex_lock.rs
index 85e870632a5..e9dcc7b227d 100644
--- a/src/tools/clippy/clippy_lints/src/mut_mutex_lock.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_mutex_lock.rs
@@ -47,9 +47,9 @@ declare_lint_pass!(MutMutexLock => [MUT_MUTEX_LOCK]);
 impl<'tcx> LateLintPass<'tcx> for MutMutexLock {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, ex: &'tcx Expr<'tcx>) {
         if_chain! {
-            if let ExprKind::MethodCall(path, method_span, args, _) = &ex.kind;
+            if let ExprKind::MethodCall(path, method_span, [self_arg, ..], _) = &ex.kind;
             if path.ident.name == sym!(lock);
-            let ty = cx.typeck_results().expr_ty(&args[0]);
+            let ty = cx.typeck_results().expr_ty(self_arg);
             if let ty::Ref(_, inner_ty, Mutability::Mut) = ty.kind();
             if is_type_diagnostic_item(cx, inner_ty, sym!(mutex_type));
             then {
diff --git a/src/tools/clippy/clippy_lints/src/needless_option_as_deref.rs b/src/tools/clippy/clippy_lints/src/needless_option_as_deref.rs
new file mode 100644
index 00000000000..5024a881d2a
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/needless_option_as_deref.rs
@@ -0,0 +1,66 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::in_macro;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::ty::is_type_diagnostic_item;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::TyS;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::symbol::sym;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for no-op uses of Option::{as_deref,as_deref_mut},
+    /// for example, `Option<&T>::as_deref()` returns the same type.
+    ///
+    /// ### Why is this bad?
+    /// Redundant code and improving readability.
+    ///
+    /// ### Example
+    /// ```rust
+    /// let a = Some(&1);
+    /// let b = a.as_deref(); // goes from Option<&i32> to Option<&i32>
+    /// ```
+    /// Could be written as:
+    /// ```rust
+    /// let a = Some(&1);
+    /// let b = a;
+    /// ```
+    pub NEEDLESS_OPTION_AS_DEREF,
+    complexity,
+    "no-op use of `deref` or `deref_mut` method to `Option`."
+}
+
+declare_lint_pass!(OptionNeedlessDeref=> [
+    NEEDLESS_OPTION_AS_DEREF,
+]);
+
+impl<'tcx> LateLintPass<'tcx> for OptionNeedlessDeref {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+        if expr.span.from_expansion() || in_macro(expr.span) {
+            return;
+        }
+        let typeck = cx.typeck_results();
+        let outer_ty = typeck.expr_ty(expr);
+
+        if_chain! {
+            if is_type_diagnostic_item(cx,outer_ty,sym::option_type);
+            if let ExprKind::MethodCall(path, _, [sub_expr], _) = expr.kind;
+            let symbol = path.ident.as_str();
+            if symbol=="as_deref" || symbol=="as_deref_mut";
+            if TyS::same_type( outer_ty, typeck.expr_ty(sub_expr) );
+            then{
+                span_lint_and_sugg(
+                    cx,
+                    NEEDLESS_OPTION_AS_DEREF,
+                    expr.span,
+                    "derefed type is same as origin",
+                    "try this",
+                    snippet_opt(cx,sub_expr.span).unwrap(),
+                    Applicability::MachineApplicable
+                );
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs
index 28e9e6f438e..c5a5cde4b11 100644
--- a/src/tools/clippy/clippy_lints/src/no_effect.rs
+++ b/src/tools/clippy/clippy_lints/src/no_effect.rs
@@ -96,28 +96,63 @@ impl<'tcx> LateLintPass<'tcx> for NoEffect {
             if has_no_effect(cx, expr) {
                 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 {
+                for e in &reduced {
                     if e.span.from_expansion() {
                         return;
                     }
-                    if let Some(snip) = snippet_opt(cx, e.span) {
-                        snippet.push_str(&snip);
-                        snippet.push(';');
-                    } else {
-                        return;
+                }
+                if let ExprKind::Index(..) = &expr.kind {
+                    let snippet;
+                    if_chain! {
+                        if let Some(arr) = snippet_opt(cx, reduced[0].span);
+                        if let Some(func) = snippet_opt(cx, reduced[1].span);
+                        then {
+                            snippet = format!("assert!({}.len() > {});", &arr, &func);
+                        } else {
+                            return;
+                        }
+                    }
+                    span_lint_hir_and_then(
+                        cx,
+                        UNNECESSARY_OPERATION,
+                        expr.hir_id,
+                        stmt.span,
+                        "unnecessary operation",
+                        |diag| {
+                            diag.span_suggestion(
+                                stmt.span,
+                                "statement can be written as",
+                                snippet,
+                                Applicability::MaybeIncorrect,
+                            );
+                        },
+                    );
+                } else {
+                    let mut snippet = String::new();
+                    for e in reduced {
+                        if let Some(snip) = snippet_opt(cx, e.span) {
+                            snippet.push_str(&snip);
+                            snippet.push(';');
+                        } else {
+                            return;
+                        }
                     }
+                    span_lint_hir_and_then(
+                        cx,
+                        UNNECESSARY_OPERATION,
+                        expr.hir_id,
+                        stmt.span,
+                        "unnecessary operation",
+                        |diag| {
+                            diag.span_suggestion(
+                                stmt.span,
+                                "statement can be reduced to",
+                                snippet,
+                                Applicability::MachineApplicable,
+                            );
+                        },
+                    );
                 }
-                span_lint_hir_and_then(
-                    cx,
-                    UNNECESSARY_OPERATION,
-                    expr.hir_id,
-                    stmt.span,
-                    "statement can be reduced",
-                    |diag| {
-                        diag.span_suggestion(stmt.span, "replace it with", snippet, Applicability::MachineApplicable);
-                    },
-                );
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/open_options.rs b/src/tools/clippy/clippy_lints/src/open_options.rs
index 4064d94da2a..5752342cf62 100644
--- a/src/tools/clippy/clippy_lints/src/open_options.rs
+++ b/src/tools/clippy/clippy_lints/src/open_options.rs
@@ -31,11 +31,11 @@ declare_lint_pass!(OpenOptions => [NONSENSICAL_OPEN_OPTIONS]);
 
 impl<'tcx> LateLintPass<'tcx> for OpenOptions {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
-        if let ExprKind::MethodCall(path, _, arguments, _) = e.kind {
-            let obj_ty = cx.typeck_results().expr_ty(&arguments[0]).peel_refs();
+        if let ExprKind::MethodCall(path, _, [self_arg, ..], _) = &e.kind {
+            let obj_ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
             if path.ident.name == sym!(open) && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) {
                 let mut options = Vec::new();
-                get_open_options(cx, &arguments[0], &mut options);
+                get_open_options(cx, self_arg, &mut options);
                 check_open_options(cx, &options, e.span);
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
index eff3d3abff8..15f6dcae887 100644
--- a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
@@ -2,12 +2,14 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::higher;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::usage::contains_return_break_continue_macro;
-use clippy_utils::{eager_or_lazy, in_macro, is_else_clause, is_lang_ctor};
+use clippy_utils::{
+    can_move_expr_to_closure, eager_or_lazy, in_constant, in_macro, is_else_clause, is_lang_ctor, peel_hir_expr_while,
+    CaptureKind,
+};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::OptionSome;
-use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, Mutability, PatKind, UnOp};
+use rustc_hir::{def::Res, BindingAnnotation, Block, Expr, ExprKind, Mutability, PatKind, Path, QPath, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
@@ -58,7 +60,7 @@ declare_clippy_lint! {
     /// }, |foo| foo);
     /// ```
     pub OPTION_IF_LET_ELSE,
-    pedantic,
+    nursery,
     "reimplementation of Option::map_or"
 }
 
@@ -125,20 +127,30 @@ fn format_option_in_sugg(cx: &LateContext<'_>, cond_expr: &Expr<'_>, as_ref: boo
 fn detect_option_if_let_else<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<OptionIfLetElseOccurence> {
     if_chain! {
         if !in_macro(expr.span); // Don't lint macros, because it behaves weirdly
-        if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else: Some(if_else) }) = higher::IfLet::hir(cx, expr);
+        if !in_constant(cx, expr.hir_id);
+        if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else: Some(if_else) })
+            = higher::IfLet::hir(cx, expr);
         if !is_else_clause(cx.tcx, expr);
         if !is_result_ok(cx, let_expr); // Don't lint on Result::ok because a different lint does it already
         if let PatKind::TupleStruct(struct_qpath, [inner_pat], _) = &let_pat.kind;
         if is_lang_ctor(cx, struct_qpath, OptionSome);
         if let PatKind::Binding(bind_annotation, _, id, _) = &inner_pat.kind;
-        if !contains_return_break_continue_macro(if_then);
-        if !contains_return_break_continue_macro(if_else);
+        if let Some(some_captures) = can_move_expr_to_closure(cx, if_then);
+        if let Some(none_captures) = can_move_expr_to_closure(cx, if_else);
+        if some_captures
+            .iter()
+            .filter_map(|(id, &c)| none_captures.get(id).map(|&c2| (c, c2)))
+            .all(|(x, y)| x.is_imm_ref() && y.is_imm_ref());
 
         then {
             let capture_mut = if bind_annotation == &BindingAnnotation::Mutable { "mut " } else { "" };
             let some_body = extract_body_from_expr(if_then)?;
             let none_body = extract_body_from_expr(if_else)?;
-            let method_sugg = if eager_or_lazy::is_eagerness_candidate(cx, none_body) { "map_or" } else { "map_or_else" };
+            let method_sugg = if eager_or_lazy::is_eagerness_candidate(cx, none_body) {
+                "map_or"
+            } else {
+                "map_or_else"
+            };
             let capture_name = id.name.to_ident_string();
             let (as_ref, as_mut) = match &let_expr.kind {
                 ExprKind::AddrOf(_, Mutability::Not, _) => (true, false),
@@ -150,6 +162,24 @@ fn detect_option_if_let_else<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) ->
                 ExprKind::Unary(UnOp::Deref, expr) | ExprKind::AddrOf(_, _, expr) => expr,
                 _ => let_expr,
             };
+            // Check if captures the closure will need conflict with borrows made in the scrutinee.
+            // TODO: check all the references made in the scrutinee expression. This will require interacting
+            // with the borrow checker. Currently only `<local>[.<field>]*` is checked for.
+            if as_ref || as_mut {
+                let e = peel_hir_expr_while(cond_expr, |e| match e.kind {
+                    ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) => Some(e),
+                    _ => None,
+                });
+                if let ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(local_id), .. })) = e.kind {
+                    match some_captures.get(local_id)
+                        .or_else(|| (method_sugg == "map_or_else").then(|| ()).and_then(|_| none_captures.get(local_id)))
+                    {
+                        Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return None,
+                        Some(CaptureKind::Ref(Mutability::Not)) if as_mut => return None,
+                        Some(CaptureKind::Ref(Mutability::Not)) | None => (),
+                    }
+                }
+            }
             Some(OptionIfLetElseOccurence {
                 option: format_option_in_sugg(cx, cond_expr, as_ref, as_mut),
                 method_sugg: method_sugg.to_string(),
diff --git a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
index 35cff4141a9..e7bc2446590 100644
--- a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
+++ b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs
@@ -118,7 +118,7 @@ impl<'tcx> LateLintPass<'tcx> for PatternTypeMismatch {
             }
         }
         if let ExprKind::Let(let_pat, let_expr, _) = expr.kind {
-            if let Some(ref expr_ty) = cx.typeck_results().node_type_opt(let_expr.hir_id) {
+            if let Some(expr_ty) = cx.typeck_results().node_type_opt(let_expr.hir_id) {
                 if in_external_macro(cx.sess(), let_pat.span) {
                     return;
                 }
diff --git a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs
index f1975056ddc..cfb5287c667 100644
--- a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs
@@ -92,13 +92,13 @@ fn expr_as_ptr_offset_call<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &'tcx Expr<'_>,
 ) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>, Method)> {
-    if let ExprKind::MethodCall(path_segment, _, args, _) = expr.kind {
-        if is_expr_ty_raw_ptr(cx, &args[0]) {
+    if let ExprKind::MethodCall(path_segment, _, [arg_0, arg_1, ..], _) = &expr.kind {
+        if is_expr_ty_raw_ptr(cx, arg_0) {
             if path_segment.ident.name == sym::offset {
-                return Some((&args[0], &args[1], Method::Offset));
+                return Some((arg_0, arg_1, Method::Offset));
             }
             if path_segment.ident.name == sym!(wrapping_offset) {
-                return Some((&args[0], &args[1], Method::WrappingOffset));
+                return Some((arg_0, arg_1, Method::WrappingOffset));
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index 7b6a0894e6d..e79cd7ed4ec 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -97,7 +97,8 @@ impl QuestionMark {
 
     fn check_if_let_some_and_early_return_none(cx: &LateContext<'_>, expr: &Expr<'_>) {
         if_chain! {
-            if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else: Some(if_else) }) = higher::IfLet::hir(cx, expr);
+            if let Some(higher::IfLet { let_pat, let_expr, if_then, if_else: Some(if_else) })
+                = higher::IfLet::hir(cx, expr);
             if Self::is_option(cx, let_expr);
 
             if let PatKind::TupleStruct(ref path1, fields, None) = let_pat.kind;
@@ -105,7 +106,7 @@ impl QuestionMark {
             if let PatKind::Binding(annot, bind_id, _, _) = fields[0].kind;
             let by_ref = matches!(annot, BindingAnnotation::Ref | BindingAnnotation::RefMut);
 
-            if let ExprKind::Block(ref block, None) = if_then.kind;
+            if let ExprKind::Block(block, None) = if_then.kind;
             if block.stmts.is_empty();
             if let Some(trailing_expr) = &block.expr;
             if path_to_local_id(trailing_expr, bind_id);
diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
index f5e43264a5c..7041e4f980e 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
@@ -15,7 +15,7 @@ use rustc_middle::mir::{
     Mutability,
 };
 use rustc_middle::ty::{self, fold::TypeVisitor, Ty, TyCtxt};
-use rustc_mir::dataflow::{Analysis, AnalysisDomain, GenKill, GenKillAnalysis, ResultsCursor};
+use rustc_mir_dataflow::{Analysis, AnalysisDomain, GenKill, GenKillAnalysis, ResultsCursor};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::{BytePos, Span};
 use rustc_span::sym;
@@ -625,7 +625,10 @@ impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'tcx> {
                 .flat_map(HybridBitSet::iter)
                 .collect();
 
-            if ContainsRegion(self.cx.tcx).visit_ty(self.body.local_decls[*dest].ty).is_break() {
+            if ContainsRegion(self.cx.tcx)
+                .visit_ty(self.body.local_decls[*dest].ty)
+                .is_break()
+            {
                 mutable_variables.push(*dest);
             }
 
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 7314bce83e0..90e3c3f4b3e 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
@@ -51,9 +51,7 @@ impl ReturnVisitor {
 
 impl<'ast> ast_visit::Visitor<'ast> for ReturnVisitor {
     fn visit_expr(&mut self, ex: &'ast ast::Expr) {
-        if let ast::ExprKind::Ret(_) = ex.kind {
-            self.found_return = true;
-        } else if let ast::ExprKind::Try(_) = ex.kind {
+        if let ast::ExprKind::Ret(_) | ast::ExprKind::Try(_) = ex.kind {
             self.found_return = true;
         }
 
diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs
index eab09733730..947c25ac880 100644
--- a/src/tools/clippy/clippy_lints/src/regex.rs
+++ b/src/tools/clippy/clippy_lints/src/regex.rs
@@ -3,8 +3,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
 use clippy_utils::{match_def_path, paths};
 use if_chain::if_chain;
 use rustc_ast::ast::{LitKind, StrStyle};
-use rustc_data_structures::fx::FxHashSet;
-use rustc_hir::{BorrowKind, Expr, ExprKind, HirId};
+use rustc_hir::{BorrowKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::{BytePos, Span};
@@ -53,10 +52,7 @@ declare_clippy_lint! {
 }
 
 #[derive(Clone, Default)]
-pub struct Regex {
-    spans: FxHashSet<Span>,
-    last: Option<HirId>,
-}
+pub struct Regex {}
 
 impl_lint_pass!(Regex => [INVALID_REGEX, TRIVIAL_REGEX]);
 
@@ -91,7 +87,7 @@ fn str_span(base: Span, c: regex_syntax::ast::Span, offset: u16) -> Span {
     let end = base.lo() + BytePos(u32::try_from(c.end.offset).expect("offset too large") + offset);
     let start = base.lo() + BytePos(u32::try_from(c.start.offset).expect("offset too large") + offset);
     assert!(start <= end);
-    Span::new(start, end, base.ctxt())
+    Span::new(start, end, base.ctxt(), base.parent())
 }
 
 fn const_str<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option<String> {
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index 681baed8c36..341b5a61631 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -206,13 +206,10 @@ fn check_final_expr<'tcx>(
         // an if/if let expr, check both exprs
         // note, if without else is going to be a type checking error anyways
         // (except for unit type functions) so we don't match it
-        ExprKind::Match(_, arms, source) => match source {
-            MatchSource::Normal => {
-                for arm in arms.iter() {
-                    check_final_expr(cx, arm.body, Some(arm.body.span), RetReplacement::Block);
-                }
-            },
-            _ => (),
+        ExprKind::Match(_, arms, MatchSource::Normal) => {
+            for arm in arms.iter() {
+                check_final_expr(cx, arm.body, Some(arm.body.span), RetReplacement::Block);
+            }
         },
         ExprKind::DropTemps(expr) => check_final_expr(cx, expr, None, RetReplacement::Empty),
         _ => (),
diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs
index 1a78a4968e5..13d8f954c44 100644
--- a/src/tools/clippy/clippy_lints/src/strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strings.rs
@@ -345,9 +345,9 @@ declare_lint_pass!(StrToString => [STR_TO_STRING]);
 impl LateLintPass<'_> for StrToString {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
         if_chain! {
-            if let ExprKind::MethodCall(path, _, args, _) = &expr.kind;
+            if let ExprKind::MethodCall(path, _, [self_arg, ..], _) = &expr.kind;
             if path.ident.name == sym!(to_string);
-            let ty = cx.typeck_results().expr_ty(&args[0]);
+            let ty = cx.typeck_results().expr_ty(self_arg);
             if let ty::Ref(_, ty, ..) = ty.kind();
             if *ty.kind() == ty::Str;
             then {
@@ -394,9 +394,9 @@ declare_lint_pass!(StringToString => [STRING_TO_STRING]);
 impl LateLintPass<'_> for StringToString {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
         if_chain! {
-            if let ExprKind::MethodCall(path, _, args, _) = &expr.kind;
+            if let ExprKind::MethodCall(path, _, [self_arg, ..], _) = &expr.kind;
             if path.ident.name == sym!(to_string);
-            let ty = cx.typeck_results().expr_ty(&args[0]);
+            let ty = cx.typeck_results().expr_ty(self_arg);
             if is_type_diagnostic_item(cx, ty, sym::string_type);
             then {
                 span_lint_and_help(
diff --git a/src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs b/src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs
index 6a73b94d87e..4a67cabf323 100644
--- a/src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs
+++ b/src/tools/clippy/clippy_lints/src/tabs_in_doc_comments.rs
@@ -69,6 +69,7 @@ impl TabsInDocComments {
                     attr.span.lo() + BytePos(3 + lo),
                     attr.span.lo() + BytePos(3 + hi),
                     attr.span.ctxt(),
+                    attr.span.parent(),
                 );
                 span_lint_and_sugg(
                     cx,
diff --git a/src/tools/clippy/clippy_lints/src/to_string_in_display.rs b/src/tools/clippy/clippy_lints/src/to_string_in_display.rs
index b036ed9a3d2..b7414cec87c 100644
--- a/src/tools/clippy/clippy_lints/src/to_string_in_display.rs
+++ b/src/tools/clippy/clippy_lints/src/to_string_in_display.rs
@@ -92,11 +92,11 @@ impl LateLintPass<'_> for ToStringInDisplay {
         if_chain! {
             if self.in_display_impl;
             if let Some(self_hir_id) = self.self_hir_id;
-            if let ExprKind::MethodCall(path, _, args, _) = expr.kind;
+            if let ExprKind::MethodCall(path, _, [ref self_arg, ..], _) = expr.kind;
             if path.ident.name == sym!(to_string);
             if let Some(expr_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
             if is_diag_trait_item(cx, expr_def_id, sym::ToString);
-            if path_to_local_id(&args[0], self_hir_id);
+            if path_to_local_id(self_arg, self_hir_id);
             then {
                 span_lint(
                     cx,
diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs
index 371bb8b445a..9588de8459c 100644
--- a/src/tools/clippy/clippy_lints/src/types/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/types/mod.rs
@@ -295,6 +295,7 @@ declare_clippy_lint! {
 pub struct Types {
     vec_box_size_threshold: u64,
     type_complexity_threshold: u64,
+    avoid_breaking_exported_api: bool,
 }
 
 impl_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION, RC_BUFFER, RC_MUTEX, TYPE_COMPLEXITY]);
@@ -308,19 +309,31 @@ impl<'tcx> LateLintPass<'tcx> for Types {
             false
         };
 
+        let is_exported = cx.access_levels.is_exported(cx.tcx.hir().local_def_id(id));
+
         self.check_fn_decl(
             cx,
             decl,
             CheckTyContext {
                 is_in_trait_impl,
+                is_exported,
                 ..CheckTyContext::default()
             },
         );
     }
 
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
+        let is_exported = cx.access_levels.is_exported(item.def_id);
+
         match item.kind {
-            ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => self.check_ty(cx, ty, CheckTyContext::default()),
+            ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => self.check_ty(
+                cx,
+                ty,
+                CheckTyContext {
+                    is_exported,
+                    ..CheckTyContext::default()
+                },
+            ),
             // functions, enums, structs, impls and traits are covered
             _ => (),
         }
@@ -342,15 +355,31 @@ impl<'tcx> LateLintPass<'tcx> for Types {
     }
 
     fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
-        self.check_ty(cx, field.ty, CheckTyContext::default());
+        let is_exported = cx.access_levels.is_exported(cx.tcx.hir().local_def_id(field.hir_id));
+
+        self.check_ty(
+            cx,
+            field.ty,
+            CheckTyContext {
+                is_exported,
+                ..CheckTyContext::default()
+            },
+        );
     }
 
-    fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &TraitItem<'_>) {
+    fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'_>) {
+        let is_exported = cx.access_levels.is_exported(item.def_id);
+
+        let context = CheckTyContext {
+            is_exported,
+            ..CheckTyContext::default()
+        };
+
         match item.kind {
             TraitItemKind::Const(ty, _) | TraitItemKind::Type(_, Some(ty)) => {
-                self.check_ty(cx, ty, CheckTyContext::default());
+                self.check_ty(cx, ty, context);
             },
-            TraitItemKind::Fn(ref sig, _) => self.check_fn_decl(cx, sig.decl, CheckTyContext::default()),
+            TraitItemKind::Fn(ref sig, _) => self.check_fn_decl(cx, sig.decl, context),
             TraitItemKind::Type(..) => (),
         }
     }
@@ -370,10 +399,11 @@ impl<'tcx> LateLintPass<'tcx> for Types {
 }
 
 impl Types {
-    pub fn new(vec_box_size_threshold: u64, type_complexity_threshold: u64) -> Self {
+    pub fn new(vec_box_size_threshold: u64, type_complexity_threshold: u64, avoid_breaking_exported_api: bool) -> Self {
         Self {
             vec_box_size_threshold,
             type_complexity_threshold,
+            avoid_breaking_exported_api,
         }
     }
 
@@ -410,17 +440,24 @@ impl Types {
                 let hir_id = hir_ty.hir_id;
                 let res = cx.qpath_res(qpath, hir_id);
                 if let Some(def_id) = res.opt_def_id() {
-                    let mut triggered = false;
-                    triggered |= box_vec::check(cx, hir_ty, qpath, def_id);
-                    triggered |= redundant_allocation::check(cx, hir_ty, qpath, def_id);
-                    triggered |= rc_buffer::check(cx, hir_ty, qpath, def_id);
-                    triggered |= vec_box::check(cx, hir_ty, qpath, def_id, self.vec_box_size_threshold);
-                    triggered |= option_option::check(cx, hir_ty, qpath, def_id);
-                    triggered |= linked_list::check(cx, hir_ty, def_id);
-                    triggered |= rc_mutex::check(cx, hir_ty, qpath, def_id);
-
-                    if triggered {
-                        return;
+                    if self.is_type_change_allowed(context) {
+                        // All lints that are being checked in this block are guarded by
+                        // the `avoid_breaking_exported_api` configuration. When adding a
+                        // new lint, please also add the name to the configuration documentation
+                        // in `clippy_lints::utils::conf.rs`
+
+                        let mut triggered = false;
+                        triggered |= box_vec::check(cx, hir_ty, qpath, def_id);
+                        triggered |= redundant_allocation::check(cx, hir_ty, qpath, def_id);
+                        triggered |= rc_buffer::check(cx, hir_ty, qpath, def_id);
+                        triggered |= vec_box::check(cx, hir_ty, qpath, def_id, self.vec_box_size_threshold);
+                        triggered |= option_option::check(cx, hir_ty, qpath, def_id);
+                        triggered |= linked_list::check(cx, hir_ty, def_id);
+                        triggered |= rc_mutex::check(cx, hir_ty, qpath, def_id);
+
+                        if triggered {
+                            return;
+                        }
                     }
                 }
                 match *qpath {
@@ -487,11 +524,21 @@ impl Types {
             _ => {},
         }
     }
+
+    /// This function checks if the type is allowed to change in the current context
+    /// based on the `avoid_breaking_exported_api` configuration
+    fn is_type_change_allowed(&self, context: CheckTyContext) -> bool {
+        !(context.is_exported && self.avoid_breaking_exported_api)
+    }
 }
 
+#[allow(clippy::struct_excessive_bools)]
 #[derive(Clone, Copy, Default)]
 struct CheckTyContext {
     is_in_trait_impl: bool,
+    /// `true` for types on local variables.
     is_local: bool,
+    /// `true` for types that are part of the public API.
+    is_exported: bool,
     is_nested_call: bool,
 }
diff --git a/src/tools/clippy/clippy_lints/src/types/rc_mutex.rs b/src/tools/clippy/clippy_lints/src/types/rc_mutex.rs
index bd7a0ee6408..12db7afb81c 100644
--- a/src/tools/clippy/clippy_lints/src/types/rc_mutex.rs
+++ b/src/tools/clippy/clippy_lints/src/types/rc_mutex.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint;
+use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::is_ty_param_diagnostic_item;
 use if_chain::if_chain;
 use rustc_hir::{self as hir, def_id::DefId, QPath};
@@ -11,13 +11,14 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
     if_chain! {
         if cx.tcx.is_diagnostic_item(sym::Rc, def_id) ;
         if let Some(_) = is_ty_param_diagnostic_item(cx, qpath, sym!(mutex_type)) ;
-
-        then{
-            span_lint(
+        then {
+            span_lint_and_help(
                 cx,
                 RC_MUTEX,
                 hir_ty.span,
-                "found `Rc<Mutex<_>>`. Consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead",
+                "usage of `Rc<Mutex<_>>`",
+                None,
+                "consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead",
             );
             return true;
         }
diff --git a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
index 8e83dcbf704..ac7bdd6a1eb 100644
--- a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
+++ b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
@@ -54,7 +54,13 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
         _ => return false,
     };
     let inner_span = match get_qpath_generic_tys(inner_qpath).next() {
-        Some(ty) => ty.span,
+        Some(ty) => {
+            // Box<Box<dyn T>> is smaller than Box<dyn T> because of wide pointers
+            if matches!(ty.kind, TyKind::TraitObject(..)) {
+                return false;
+            }
+            ty.span
+        },
         None => return false,
     };
     if inner_sym == outer_sym {
diff --git a/src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs b/src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs
index 47571e608c7..09570616593 100644
--- a/src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs
+++ b/src/tools/clippy/clippy_lints/src/undropped_manually_drops.rs
@@ -37,8 +37,8 @@ declare_lint_pass!(UndroppedManuallyDrops => [UNDROPPED_MANUALLY_DROPS]);
 
 impl LateLintPass<'tcx> for UndroppedManuallyDrops {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if let Some(args) = match_function_call(cx, expr, &paths::DROP) {
-            let ty = cx.typeck_results().expr_ty(&args[0]);
+        if let Some([arg_0, ..]) = match_function_call(cx, expr, &paths::DROP) {
+            let ty = cx.typeck_results().expr_ty(arg_0);
             if is_type_lang_item(cx, ty, lang_items::LangItem::ManuallyDrop) {
                 span_lint_and_help(
                     cx,
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs b/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs
index 97b1b2dae3c..61670fe124e 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_sort_by.rs
@@ -218,7 +218,10 @@ fn detect_lint(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<LintTrigger> {
 
 fn expr_borrows(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     let ty = cx.typeck_results().expr_ty(expr);
-    matches!(ty.kind(), ty::Ref(..)) || ty.walk(cx.tcx).any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_)))
+    matches!(ty.kind(), ty::Ref(..))
+        || ty
+            .walk(cx.tcx)
+            .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_)))
 }
 
 impl LateLintPass<'_> for UnnecessarySortBy {
diff --git a/src/tools/clippy/clippy_lints/src/unused_async.rs b/src/tools/clippy/clippy_lints/src/unused_async.rs
index 3a6a07c5226..f4808682b69 100644
--- a/src/tools/clippy/clippy_lints/src/unused_async.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_async.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor};
-use rustc_hir::{Body, Expr, ExprKind, FnDecl, FnHeader, HirId, IsAsync, Item, ItemKind, YieldSource};
+use rustc_hir::{Body, Expr, ExprKind, FnDecl, FnHeader, HirId, IsAsync, YieldSource};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::map::Map;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -57,11 +57,6 @@ impl<'a, 'tcx> Visitor<'tcx> for AsyncFnVisitor<'a, 'tcx> {
 }
 
 impl<'tcx> LateLintPass<'tcx> for UnusedAsync {
-    fn check_item(&mut self, _: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
-        if let ItemKind::Trait(..) = item.kind {
-            return;
-        }
-    }
     fn check_fn(
         &mut self,
         cx: &LateContext<'tcx>,
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 82bc4a6d153..031b182bd2f 100644
--- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
@@ -45,20 +45,20 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount {
 
         match expr.kind {
             hir::ExprKind::Match(res, _, _) if is_try(cx, expr).is_some() => {
-                if let hir::ExprKind::Call(func, args) = res.kind {
+                if let hir::ExprKind::Call(func, [ref arg_0, ..]) = res.kind {
                     if matches!(
                         func.kind,
                         hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, _))
                     ) {
-                        check_map_error(cx, &args[0], expr);
+                        check_map_error(cx, arg_0, expr);
                     }
                 } else {
                     check_map_error(cx, res, expr);
                 }
             },
-            hir::ExprKind::MethodCall(path, _, args, _) => match &*path.ident.as_str() {
+            hir::ExprKind::MethodCall(path, _, [ref arg_0, ..], _) => match &*path.ident.as_str() {
                 "expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" => {
-                    check_map_error(cx, &args[0], expr);
+                    check_map_error(cx, arg_0, expr);
                 },
                 _ => (),
             },
diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs
index 658ac81f6ea..e7e249c79a2 100644
--- a/src/tools/clippy/clippy_lints/src/unused_self.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_self.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::visitors::LocalUsedVisitor;
+use clippy_utils::visitors::is_local_used;
 use if_chain::if_chain;
 use rustc_hir::{Impl, ImplItem, ImplItemKind, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -50,8 +50,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
             if let ImplItemKind::Fn(.., body_id) = &impl_item.kind;
             let body = cx.tcx.hir().body(*body_id);
             if let [self_param, ..] = body.params;
-            let self_hir_id = self_param.pat.hir_id;
-            if !LocalUsedVisitor::new(cx, self_hir_id).check_body(body);
+            if !is_local_used(cx, body, self_param.pat.hir_id);
             then {
                 span_lint_and_help(
                     cx,
diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs
index bffd9f3612b..b2ab300c2e9 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap.rs
@@ -1,10 +1,11 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{differing_macro_contexts, usage::is_potentially_mutated};
+use clippy_utils::{differing_macro_contexts, path_to_local, usage::is_potentially_mutated};
 use if_chain::if_chain;
+use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor};
-use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, Path, QPath, UnOp};
+use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, PathSegment, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::map::Map;
 use rustc_middle::lint::in_external_macro;
@@ -74,26 +75,61 @@ struct UnwrappableVariablesVisitor<'a, 'tcx> {
     unwrappables: Vec<UnwrapInfo<'tcx>>,
     cx: &'a LateContext<'tcx>,
 }
+
+/// What kind of unwrappable this is.
+#[derive(Copy, Clone, Debug)]
+enum UnwrappableKind {
+    Option,
+    Result,
+}
+
+impl UnwrappableKind {
+    fn success_variant_pattern(self) -> &'static str {
+        match self {
+            UnwrappableKind::Option => "Some(..)",
+            UnwrappableKind::Result => "Ok(..)",
+        }
+    }
+
+    fn error_variant_pattern(self) -> &'static str {
+        match self {
+            UnwrappableKind::Option => "None",
+            UnwrappableKind::Result => "Err(..)",
+        }
+    }
+}
+
 /// Contains information about whether a variable can be unwrapped.
 #[derive(Copy, Clone, Debug)]
 struct UnwrapInfo<'tcx> {
     /// The variable that is checked
-    ident: &'tcx Path<'tcx>,
+    local_id: HirId,
+    /// The if itself
+    if_expr: &'tcx Expr<'tcx>,
     /// The check, like `x.is_ok()`
     check: &'tcx Expr<'tcx>,
+    /// The check's name, like `is_ok`
+    check_name: &'tcx PathSegment<'tcx>,
     /// The branch where the check takes place, like `if x.is_ok() { .. }`
     branch: &'tcx Expr<'tcx>,
     /// Whether `is_some()` or `is_ok()` was called (as opposed to `is_err()` or `is_none()`).
     safe_to_unwrap: bool,
+    /// What kind of unwrappable this is.
+    kind: UnwrappableKind,
+    /// If the check is the entire condition (`if x.is_ok()`) or only a part of it (`foo() &&
+    /// x.is_ok()`)
+    is_entire_condition: bool,
 }
 
 /// Collects the information about unwrappable variables from an if condition
 /// The `invert` argument tells us whether the condition is negated.
 fn collect_unwrap_info<'tcx>(
     cx: &LateContext<'tcx>,
+    if_expr: &'tcx Expr<'_>,
     expr: &'tcx Expr<'_>,
     branch: &'tcx Expr<'_>,
     invert: bool,
+    is_entire_condition: bool,
 ) -> Vec<UnwrapInfo<'tcx>> {
     fn is_relevant_option_call(cx: &LateContext<'_>, ty: Ty<'_>, method_name: &str) -> bool {
         is_type_diagnostic_item(cx, ty, sym::option_type) && ["is_some", "is_none"].contains(&method_name)
@@ -106,18 +142,18 @@ fn collect_unwrap_info<'tcx>(
     if let ExprKind::Binary(op, left, right) = &expr.kind {
         match (invert, op.node) {
             (false, BinOpKind::And | BinOpKind::BitAnd) | (true, BinOpKind::Or | BinOpKind::BitOr) => {
-                let mut unwrap_info = collect_unwrap_info(cx, left, branch, invert);
-                unwrap_info.append(&mut collect_unwrap_info(cx, right, branch, invert));
+                let mut unwrap_info = collect_unwrap_info(cx, if_expr, left, branch, invert, false);
+                unwrap_info.append(&mut collect_unwrap_info(cx, if_expr, right, branch, invert, false));
                 return unwrap_info;
             },
             _ => (),
         }
     } else if let ExprKind::Unary(UnOp::Not, expr) = &expr.kind {
-        return collect_unwrap_info(cx, expr, branch, !invert);
+        return collect_unwrap_info(cx, if_expr, expr, branch, !invert, false);
     } else {
         if_chain! {
             if let ExprKind::MethodCall(method_name, _, args, _) = &expr.kind;
-            if let ExprKind::Path(QPath::Resolved(None, path)) = &args[0].kind;
+            if let Some(local_id) = path_to_local(&args[0]);
             let ty = cx.typeck_results().expr_ty(&args[0]);
             let name = method_name.ident.as_str();
             if is_relevant_option_call(cx, ty, &name) || is_relevant_result_call(cx, ty, &name);
@@ -129,7 +165,24 @@ fn collect_unwrap_info<'tcx>(
                     _ => unreachable!(),
                 };
                 let safe_to_unwrap = unwrappable != invert;
-                return vec![UnwrapInfo { ident: path, check: expr, branch, safe_to_unwrap }];
+                let kind = if is_type_diagnostic_item(cx, ty, sym::option_type) {
+                    UnwrappableKind::Option
+                } else {
+                    UnwrappableKind::Result
+                };
+
+                return vec![
+                    UnwrapInfo {
+                        local_id,
+                        if_expr,
+                        check: expr,
+                        check_name: method_name,
+                        branch,
+                        safe_to_unwrap,
+                        kind,
+                        is_entire_condition,
+                    }
+                ]
             }
         }
     }
@@ -137,11 +190,17 @@ fn collect_unwrap_info<'tcx>(
 }
 
 impl<'a, 'tcx> UnwrappableVariablesVisitor<'a, 'tcx> {
-    fn visit_branch(&mut self, cond: &'tcx Expr<'_>, branch: &'tcx Expr<'_>, else_branch: bool) {
+    fn visit_branch(
+        &mut self,
+        if_expr: &'tcx Expr<'_>,
+        cond: &'tcx Expr<'_>,
+        branch: &'tcx Expr<'_>,
+        else_branch: bool,
+    ) {
         let prev_len = self.unwrappables.len();
-        for unwrap_info in collect_unwrap_info(self.cx, cond, branch, else_branch) {
-            if is_potentially_mutated(unwrap_info.ident, cond, self.cx)
-                || is_potentially_mutated(unwrap_info.ident, branch, self.cx)
+        for unwrap_info in collect_unwrap_info(self.cx, if_expr, cond, branch, else_branch, true) {
+            if is_potentially_mutated(unwrap_info.local_id, cond, self.cx)
+                || is_potentially_mutated(unwrap_info.local_id, branch, self.cx)
             {
                 // if the variable is mutated, we don't know whether it can be unwrapped:
                 continue;
@@ -163,32 +222,62 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
         }
         if let Some(higher::If { cond, then, r#else }) = higher::If::hir(expr) {
             walk_expr(self, cond);
-            self.visit_branch(cond, then, false);
+            self.visit_branch(expr, cond, then, false);
             if let Some(else_inner) = r#else {
-                self.visit_branch(cond, else_inner, true);
+                self.visit_branch(expr, cond, else_inner, true);
             }
         } else {
             // find `unwrap[_err]()` calls:
             if_chain! {
                 if let ExprKind::MethodCall(method_name, _, args, _) = expr.kind;
-                if let ExprKind::Path(QPath::Resolved(None, path)) = args[0].kind;
-                if [sym::unwrap, sym!(unwrap_err)].contains(&method_name.ident.name);
-                let call_to_unwrap = method_name.ident.name == sym::unwrap;
+                if let Some(id) = path_to_local(&args[0]);
+                if [sym::unwrap, sym::expect, sym!(unwrap_err)].contains(&method_name.ident.name);
+                let call_to_unwrap = [sym::unwrap, sym::expect].contains(&method_name.ident.name);
                 if let Some(unwrappable) = self.unwrappables.iter()
-                    .find(|u| u.ident.res == path.res);
+                    .find(|u| u.local_id == id);
                 // Span contexts should not differ with the conditional branch
                 if !differing_macro_contexts(unwrappable.branch.span, expr.span);
                 if !differing_macro_contexts(unwrappable.branch.span, unwrappable.check.span);
                 then {
                     if call_to_unwrap == unwrappable.safe_to_unwrap {
+                        let is_entire_condition = unwrappable.is_entire_condition;
+                        let unwrappable_variable_name = self.cx.tcx.hir().name(unwrappable.local_id);
+                        let suggested_pattern = if call_to_unwrap {
+                            unwrappable.kind.success_variant_pattern()
+                        } else {
+                            unwrappable.kind.error_variant_pattern()
+                        };
+
                         span_lint_and_then(
                             self.cx,
                             UNNECESSARY_UNWRAP,
                             expr.span,
-                            &format!("you checked before that `{}()` cannot fail, \
-                            instead of checking and unwrapping, it's better to use `if let` or `match`",
-                            method_name.ident.name),
-                            |diag| { diag.span_label(unwrappable.check.span, "the check is happening here"); },
+                            &format!(
+                                "called `{}` on `{}` after checking its variant with `{}`",
+                                method_name.ident.name,
+                                unwrappable_variable_name,
+                                unwrappable.check_name.ident.as_str(),
+                            ),
+                            |diag| {
+                                if is_entire_condition {
+                                    diag.span_suggestion(
+                                        unwrappable.check.span.with_lo(unwrappable.if_expr.span.lo()),
+                                        "try",
+                                        format!(
+                                            "if let {} = {}",
+                                            suggested_pattern,
+                                            unwrappable_variable_name,
+                                        ),
+                                        // We don't track how the unwrapped value is used inside the
+                                        // block or suggest deleting the unwrap, so we can't offer a
+                                        // fixable solution.
+                                        Applicability::Unspecified,
+                                    );
+                                } else {
+                                    diag.span_label(unwrappable.check.span, "the check is happening here");
+                                    diag.help("try using `if let` or `match`");
+                                }
+                            },
                         );
                     } else {
                         span_lint_and_then(
diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs
index c192f9094a8..8651fa6fcf9 100644
--- a/src/tools/clippy/clippy_lints/src/utils/conf.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs
@@ -31,9 +31,6 @@ impl TryConf {
     }
 }
 
-/// Note that the configuration parsing currently doesn't support documentation that will
-/// that spans over several lines. This will be possible with the new implementation
-/// See (rust-clippy#7172)
 macro_rules! define_Conf {
     ($(
         $(#[doc = $doc:literal])+
@@ -130,13 +127,12 @@ macro_rules! define_Conf {
     };
 }
 
-// N.B., this macro is parsed by util/lintlib.py
 define_Conf! {
-    /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION.
+    /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_VEC, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX.
     ///
     /// 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.
+    /// Lint: MANUAL_SPLIT_ONCE, 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, APPROX_CONSTANT.
     ///
     /// The minimum rust version that the project supports
     (msrv: Option<String> = None),
diff --git a/src/tools/clippy/clippy_lints/src/utils/inspector.rs b/src/tools/clippy/clippy_lints/src/utils/inspector.rs
index e97983a2e14..43590cc7862 100644
--- a/src/tools/clippy/clippy_lints/src/utils/inspector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/inspector.rs
@@ -142,7 +142,7 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
                 print_expr(cx, arg, indent + 1);
             }
         },
-        hir::ExprKind::Let(ref pat, ref expr, _) => {
+        hir::ExprKind::Let(pat, expr, _) => {
             print_pat(cx, pat, indent + 1);
             print_expr(cx, expr, indent + 1);
         },
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 d660008e7d1..756c33d70c2 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
@@ -1,5 +1,6 @@
 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::higher;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::match_type;
 use clippy_utils::{
@@ -17,8 +18,8 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::hir_id::CRATE_HIR_ID;
 use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
 use rustc_hir::{
-    BinOpKind, Block, Crate, Expr, ExprKind, HirId, Item, Local, MatchSource, MutTy, Mutability, Node, Path, Stmt,
-    StmtKind, Ty, TyKind, UnOp,
+    BinOpKind, Block, Crate, Expr, ExprKind, HirId, Item, Local, MutTy, Mutability, Node, Path, Stmt, StmtKind, Ty,
+    TyKind, UnOp,
 };
 use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
 use rustc_middle::hir::map::Map;
@@ -503,10 +504,10 @@ impl<'tcx> LateLintPass<'tcx> for CompilerLintFunctions {
         }
 
         if_chain! {
-            if let ExprKind::MethodCall(path, _, args, _) = expr.kind;
+            if let ExprKind::MethodCall(path, _, [self_arg, ..], _) = &expr.kind;
             let fn_name = path.ident;
             if let Some(sugg) = self.map.get(&*fn_name.as_str());
-            let ty = cx.typeck_results().expr_ty(&args[0]).peel_refs();
+            let ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
             if match_type(cx, ty, &paths::EARLY_CONTEXT)
                 || match_type(cx, ty, &paths::LATE_CONTEXT);
             then {
@@ -1106,16 +1107,10 @@ impl<'tcx> LateLintPass<'tcx> for IfChainStyle {
     }
 
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
-        let (cond, then, els) = match expr.kind {
-            ExprKind::If(cond, then, els) => (Some(cond), then, els.is_some()),
-            ExprKind::Match(
-                _,
-                [arm, ..],
-                MatchSource::IfLetDesugar {
-                    contains_else_clause: els,
-                },
-            ) => (None, arm.body, els),
-            _ => return,
+        let (cond, then, els) = if let Some(higher::IfOrIfLet { cond, r#else, then }) = higher::IfOrIfLet::hir(expr) {
+            (cond, then, r#else.is_some())
+        } else {
+            return;
         };
         let then_block = match then.kind {
             ExprKind::Block(block, _) => block,
@@ -1131,7 +1126,6 @@ impl<'tcx> LateLintPass<'tcx> for IfChainStyle {
         };
         // check for `if a && b;`
         if_chain! {
-            if let Some(cond) = cond;
             if let ExprKind::Binary(op, _, _) = cond.kind;
             if op.node == BinOpKind::And;
             if cx.sess().source_map().is_multiline(cond.span);
@@ -1166,9 +1160,7 @@ fn check_nested_if_chains(
         _ => return,
     };
     if_chain! {
-        if matches!(tail.kind,
-            ExprKind::If(_, _, None)
-            | ExprKind::Match(.., MatchSource::IfLetDesugar { contains_else_clause: false }));
+        if let Some(higher::IfOrIfLet { r#else: None, .. }) = higher::IfOrIfLet::hir(tail);
         let sm = cx.sess().source_map();
         if head
             .iter()
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 a48a5385083..188d0419c39 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
@@ -82,7 +82,7 @@ This lint has the following configuration variables:
 /// `default`
 macro_rules! CONFIGURATION_VALUE_TEMPLATE {
     () => {
-        "* {name}: `{ty}`: {doc} (defaults to `{default}`)\n"
+        "* `{name}`: `{ty}`: {doc} (defaults to `{default}`)\n"
     };
 }
 
@@ -786,8 +786,6 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for ApplicabilityResolver<'a, 'hir> {
             }
         };
 
-        // TODO xFrednet 2021-03-01: support function arguments?
-
         intravisit::walk_expr(self, expr);
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs
index e76d5f81c96..d124d948b5e 100644
--- a/src/tools/clippy/clippy_lints/src/vec.rs
+++ b/src/tools/clippy/clippy_lints/src/vec.rs
@@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
         if_chain! {
             if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty_adjusted(expr).kind();
             if let ty::Slice(..) = ty.kind();
-            if let ExprKind::AddrOf(BorrowKind::Ref, mutability, ref addressee) = expr.kind;
+            if let ExprKind::AddrOf(BorrowKind::Ref, mutability, addressee) = expr.kind;
             if let Some(vec_args) = higher::VecArgs::hir(cx, addressee);
             then {
                 self.check_vec_macro(cx, &vec_args, mutability, expr.span);
diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml
index c65b2958ec5..7c24e830e71 100644
--- a/src/tools/clippy/clippy_utils/Cargo.toml
+++ b/src/tools/clippy/clippy_utils/Cargo.toml
@@ -1,16 +1,12 @@
 [package]
 name = "clippy_utils"
-version = "0.1.56"
+version = "0.1.57"
 edition = "2018"
 publish = false
 
 [dependencies]
-if_chain = "1.0.0"
-itertools = "0.9"
-regex-syntax = "0.6"
-serde = { version = "1.0", features = ["derive"] }
-unicode-normalization = "0.1"
-rustc-semver="1.1.0"
+if_chain = "1.0"
+rustc-semver = "1.1"
 
 [features]
 deny-warnings = []
diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs
index 71cfa196fc3..9302e5c21fa 100644
--- a/src/tools/clippy/clippy_utils/src/diagnostics.rs
+++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs
@@ -21,7 +21,7 @@ fn docs_link(diag: &mut DiagnosticBuilder<'_>, lint: &'static Lint) {
                 "for further information visit https://rust-lang.github.io/rust-clippy/{}/index.html#{}",
                 &option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| {
                     // extract just major + minor version and ignore patch versions
-                    format!("rust-{}", n.rsplitn(2, '.').nth(1).unwrap())
+                    format!("rust-{}", n.rsplit_once('.').unwrap().1)
                 }),
                 lint
             ));
diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs
index c06b894a738..05a4a014319 100644
--- a/src/tools/clippy/clippy_utils/src/higher.rs
+++ b/src/tools/clippy/clippy_utils/src/higher.rs
@@ -6,33 +6,38 @@ use crate::{is_expn_of, match_def_path, paths};
 use if_chain::if_chain;
 use rustc_ast::ast::{self, LitKind};
 use rustc_hir as hir;
-use rustc_hir::{Block, BorrowKind, Expr, ExprKind, LoopSource, Node, Pat, StmtKind, UnOp};
+use rustc_hir::{Arm, Block, BorrowKind, Expr, ExprKind, LoopSource, MatchSource, Node, Pat, StmtKind, UnOp};
 use rustc_lint::LateContext;
 use rustc_span::{sym, ExpnKind, Span, Symbol};
 
 /// The essential nodes of a desugared for loop as well as the entire span:
 /// `for pat in arg { body }` becomes `(pat, arg, body)`. Return `(pat, arg, body, span)`.
 pub struct ForLoop<'tcx> {
+    /// `for` loop item
     pub pat: &'tcx hir::Pat<'tcx>,
+    /// `IntoIterator` argument
     pub arg: &'tcx hir::Expr<'tcx>,
+    /// `for` loop body
     pub body: &'tcx hir::Expr<'tcx>,
+    /// entire `for` loop span
     pub span: Span,
 }
 
 impl<'tcx> ForLoop<'tcx> {
     #[inline]
+    /// Parses a desugared `for` loop
     pub fn hir(expr: &Expr<'tcx>) -> Option<Self> {
         if_chain! {
-            if let hir::ExprKind::Match(ref iterexpr, ref arms, hir::MatchSource::ForLoopDesugar) = expr.kind;
+            if let hir::ExprKind::Match(iterexpr, arms, hir::MatchSource::ForLoopDesugar) = expr.kind;
             if let Some(first_arm) = arms.get(0);
-            if let hir::ExprKind::Call(_, ref iterargs) = iterexpr.kind;
+            if let hir::ExprKind::Call(_, iterargs) = iterexpr.kind;
             if let Some(first_arg) = iterargs.get(0);
             if iterargs.len() == 1 && arms.len() == 1 && first_arm.guard.is_none();
-            if let hir::ExprKind::Loop(ref block, ..) = first_arm.body.kind;
+            if let hir::ExprKind::Loop(block, ..) = first_arm.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 body_expr) = body.kind;
+            if let hir::StmtKind::Local(local) = let_stmt.kind;
+            if let hir::StmtKind::Expr(body_expr) = body.kind;
             then {
                 return Some(Self {
                     pat: &*local.pat,
@@ -46,14 +51,19 @@ impl<'tcx> ForLoop<'tcx> {
     }
 }
 
+/// An `if` expression without `DropTemps`
 pub struct If<'hir> {
+    /// `if` condition
     pub cond: &'hir Expr<'hir>,
-    pub r#else: Option<&'hir Expr<'hir>>,
+    /// `if` then expression
     pub then: &'hir Expr<'hir>,
+    /// `else` expression
+    pub r#else: Option<&'hir Expr<'hir>>,
 }
 
 impl<'hir> If<'hir> {
     #[inline]
+    /// Parses an `if` expression
     pub const fn hir(expr: &Expr<'hir>) -> Option<Self> {
         if let ExprKind::If(
             Expr {
@@ -64,21 +74,27 @@ impl<'hir> If<'hir> {
             r#else,
         ) = expr.kind
         {
-            Some(Self { cond, r#else, then })
+            Some(Self { cond, then, r#else })
         } else {
             None
         }
     }
 }
 
+/// An `if let` expression
 pub struct IfLet<'hir> {
+    /// `if let` pattern
     pub let_pat: &'hir Pat<'hir>,
+    /// `if let` scrutinee
     pub let_expr: &'hir Expr<'hir>,
+    /// `if let` then expression
     pub if_then: &'hir Expr<'hir>,
+    /// `if let` else expression
     pub if_else: Option<&'hir Expr<'hir>>,
 }
 
 impl<'hir> IfLet<'hir> {
+    /// Parses an `if let` expression
     pub fn hir(cx: &LateContext<'_>, expr: &Expr<'hir>) -> Option<Self> {
         if let ExprKind::If(
             Expr {
@@ -92,7 +108,14 @@ impl<'hir> IfLet<'hir> {
             let hir = cx.tcx.hir();
             let mut iter = hir.parent_iter(expr.hir_id);
             if let Some((_, Node::Block(Block { stmts: [], .. }))) = iter.next() {
-                if let Some((_, Node::Expr(Expr { kind: ExprKind::Loop(_, _, LoopSource::While, _), .. }))) = iter.next() {
+                if let Some((
+                    _,
+                    Node::Expr(Expr {
+                        kind: ExprKind::Loop(_, _, LoopSource::While, _),
+                        ..
+                    }),
+                )) = iter.next()
+                {
                     // while loop desugar
                     return None;
                 }
@@ -108,14 +131,49 @@ impl<'hir> IfLet<'hir> {
     }
 }
 
+/// An `if let` or `match` expression. Useful for lints that trigger on one or the other.
+pub enum IfLetOrMatch<'hir> {
+    /// Any `match` expression
+    Match(&'hir Expr<'hir>, &'hir [Arm<'hir>], MatchSource),
+    /// scrutinee, pattern, then block, else block
+    IfLet(
+        &'hir Expr<'hir>,
+        &'hir Pat<'hir>,
+        &'hir Expr<'hir>,
+        Option<&'hir Expr<'hir>>,
+    ),
+}
+
+impl<'hir> IfLetOrMatch<'hir> {
+    /// Parses an `if let` or `match` expression
+    pub fn parse(cx: &LateContext<'_>, expr: &Expr<'hir>) -> Option<Self> {
+        match expr.kind {
+            ExprKind::Match(expr, arms, source) => Some(Self::Match(expr, arms, source)),
+            _ => IfLet::hir(cx, expr).map(
+                |IfLet {
+                     let_expr,
+                     let_pat,
+                     if_then,
+                     if_else,
+                 }| { Self::IfLet(let_expr, let_pat, if_then, if_else) },
+            ),
+        }
+    }
+}
+
+/// An `if` or `if let` expression
 pub struct IfOrIfLet<'hir> {
+    /// `if` condition that is maybe a `let` expression
     pub cond: &'hir Expr<'hir>,
-    pub r#else: Option<&'hir Expr<'hir>>,
+    /// `if` then expression
     pub then: &'hir Expr<'hir>,
+    /// `else` expression
+    pub r#else: Option<&'hir Expr<'hir>>,
 }
 
 impl<'hir> IfOrIfLet<'hir> {
     #[inline]
+    /// Parses an `if` or `if let` expression
     pub const fn hir(expr: &Expr<'hir>) -> Option<Self> {
         if let ExprKind::If(cond, then, r#else) = expr.kind {
             if let ExprKind::DropTemps(new_cond) = cond.kind {
@@ -126,7 +184,7 @@ impl<'hir> IfOrIfLet<'hir> {
                 });
             }
             if let ExprKind::Let(..) = cond.kind {
-                return Some(Self { cond, r#else, then });
+                return Some(Self { cond, then, r#else });
             }
         }
         None
@@ -155,7 +213,7 @@ impl<'a> 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, _))
@@ -167,7 +225,7 @@ impl<'a> 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,
@@ -213,7 +271,7 @@ impl<'a> VecArgs<'a> {
     /// from `vec!`.
     pub fn hir(cx: &LateContext<'_>, expr: &'a hir::Expr<'_>) -> Option<VecArgs<'a>> {
         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();
@@ -225,10 +283,10 @@ impl<'a> VecArgs<'a> {
                 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));
+                            return Some(VecArgs::Vec(args));
                         }
                     }
 
@@ -247,14 +305,17 @@ impl<'a> VecArgs<'a> {
     }
 }
 
+/// A desugared `while` loop
 pub struct While<'hir> {
-    pub if_cond: &'hir Expr<'hir>,
-    pub if_then: &'hir Expr<'hir>,
-    pub if_else: Option<&'hir Expr<'hir>>,
+    /// `while` loop condition
+    pub condition: &'hir Expr<'hir>,
+    /// `while` loop body
+    pub body: &'hir Expr<'hir>,
 }
 
 impl<'hir> While<'hir> {
     #[inline]
+    /// Parses a desugared `while` loop
     pub const fn hir(expr: &Expr<'hir>) -> Option<Self> {
         if let ExprKind::Loop(
             Block {
@@ -263,11 +324,11 @@ impl<'hir> While<'hir> {
                         kind:
                             ExprKind::If(
                                 Expr {
-                                    kind: ExprKind::DropTemps(if_cond),
+                                    kind: ExprKind::DropTemps(condition),
                                     ..
                                 },
-                                if_then,
-                                if_else_ref,
+                                body,
+                                _,
                             ),
                         ..
                     }),
@@ -278,59 +339,53 @@ impl<'hir> While<'hir> {
             _,
         ) = expr.kind
         {
-            let if_else = *if_else_ref;
-            return Some(Self {
-                if_cond,
-                if_then,
-                if_else,
-            });
+            return Some(Self { condition, body });
         }
         None
     }
 }
 
+/// A desugared `while let` loop
 pub struct WhileLet<'hir> {
-    pub if_expr: &'hir Expr<'hir>,
+    /// `while let` loop item pattern
     pub let_pat: &'hir Pat<'hir>,
+    /// `while let` loop scrutinee
     pub let_expr: &'hir Expr<'hir>,
+    /// `while let` loop body
     pub if_then: &'hir Expr<'hir>,
-    pub if_else: Option<&'hir Expr<'hir>>,
 }
 
 impl<'hir> WhileLet<'hir> {
     #[inline]
+    /// Parses a desugared `while let` loop
     pub const fn hir(expr: &Expr<'hir>) -> Option<Self> {
         if let ExprKind::Loop(
             Block {
-                expr: Some(if_expr), ..
+                expr:
+                    Some(Expr {
+                        kind:
+                            ExprKind::If(
+                                Expr {
+                                    kind: ExprKind::Let(let_pat, let_expr, _),
+                                    ..
+                                },
+                                if_then,
+                                _,
+                            ),
+                        ..
+                    }),
+                ..
             },
             _,
             LoopSource::While,
             _,
         ) = expr.kind
         {
-            if let Expr {
-                kind:
-                    ExprKind::If(
-                        Expr {
-                            kind: ExprKind::Let(let_pat, let_expr, _),
-                            ..
-                        },
-                        if_then,
-                        if_else_ref,
-                    ),
-                ..
-            } = if_expr
-            {
-                let if_else = *if_else_ref;
-                return Some(Self {
-                    if_expr,
-                    let_pat,
-                    let_expr,
-                    if_then,
-                    if_else,
-                });
-            }
+            return Some(Self {
+                let_pat,
+                let_expr,
+                if_then,
+            });
         }
         None
     }
@@ -532,7 +587,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;
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index a44f2df2fd6..6e9a1de21ee 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -232,9 +232,7 @@ impl HirEqInterExpr<'_, '_, '_> {
             (&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::Let(ref lp, ref le, _), &ExprKind::Let(ref rp, ref re, _)) => {
-                self.eq_pat(lp, rp) && self.eq_expr(le, re)
-            },
+            (&ExprKind::Let(lp, le, _), &ExprKind::Let(rp, re, _)) => self.eq_pat(lp, rp) && self.eq_expr(le, re),
             (&ExprKind::Lit(ref l), &ExprKind::Lit(ref r)) => l.node == r.node,
             (&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)
@@ -668,7 +666,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     }
                 }
             },
-            ExprKind::Let(ref pat, ref expr, _) => {
+            ExprKind::Let(pat, expr, _) => {
                 self.hash_expr(expr);
                 self.hash_pat(pat);
             },
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index ddff1686ba2..3a94f472983 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -2,6 +2,7 @@
 #![feature(in_band_lifetimes)]
 #![feature(iter_zip)]
 #![feature(rustc_private)]
+#![feature(control_flow_enum)]
 #![recursion_limit = "512"]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 #![allow(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)]
@@ -17,6 +18,7 @@
 extern crate rustc_ast;
 extern crate rustc_ast_pretty;
 extern crate rustc_attr;
+extern crate rustc_const_eval;
 extern crate rustc_data_structures;
 extern crate rustc_errors;
 extern crate rustc_hir;
@@ -24,7 +26,6 @@ extern crate rustc_infer;
 extern crate rustc_lexer;
 extern crate rustc_lint;
 extern crate rustc_middle;
-extern crate rustc_mir;
 extern crate rustc_session;
 extern crate rustc_span;
 extern crate rustc_target;
@@ -62,23 +63,27 @@ use std::collections::hash_map::Entry;
 use std::hash::BuildHasherDefault;
 
 use if_chain::if_chain;
-use rustc_ast::ast::{self, Attribute, BorrowKind, LitKind};
+use rustc_ast::ast::{self, Attribute, LitKind};
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
+use rustc_hir::hir_id::{HirIdMap, HirIdSet};
 use rustc_hir::intravisit::{self, walk_expr, ErasedMap, FnKind, NestedVisitorMap, Visitor};
-use rustc_hir::LangItem::{ResultErr, ResultOk};
+use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk};
 use rustc_hir::{
     def, Arm, BindingAnnotation, Block, Body, Constness, Destination, Expr, ExprKind, FnDecl, GenericArgs, HirId, Impl,
-    ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, MatchSource, Node, Param, Pat, PatKind, Path,
-    PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitRef, TyKind, UnOp,
+    ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, MatchSource, Mutability, Node, Param, Pat,
+    PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitRef, TyKind, UnOp,
 };
 use rustc_lint::{LateContext, Level, Lint, LintContext};
 use rustc_middle::hir::exports::Export;
 use rustc_middle::hir::map::Map;
+use rustc_middle::hir::place::PlaceBase;
 use rustc_middle::ty as rustc_ty;
-use rustc_middle::ty::{layout::IntegerExt, DefIdTree, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
+use rustc_middle::ty::binding::BindingMode;
+use rustc_middle::ty::{layout::IntegerExt, BorrowKind, DefIdTree, Ty, TyCtxt, TypeAndMut, TypeFoldable, UpvarCapture};
 use rustc_semver::RustcVersion;
 use rustc_session::Session;
 use rustc_span::hygiene::{ExpnKind, MacroKind};
@@ -89,7 +94,7 @@ use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::Integer;
 
 use crate::consts::{constant, Constant};
-use crate::ty::{can_partially_move_ty, is_recursively_primitive_type};
+use crate::ty::{can_partially_move_ty, is_copy, is_recursively_primitive_type};
 
 pub fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Option<RustcVersion> {
     if let Ok(version) = RustcVersion::parse(msrv) {
@@ -255,7 +260,17 @@ pub fn in_macro(span: Span) -> bool {
 }
 
 pub fn is_unit_expr(expr: &Expr<'_>) -> bool {
-    matches!(expr.kind, ExprKind::Block(Block { stmts: [], expr: None, .. }, _) | ExprKind::Tup([]))
+    matches!(
+        expr.kind,
+        ExprKind::Block(
+            Block {
+                stmts: [],
+                expr: None,
+                ..
+            },
+            _
+        ) | ExprKind::Tup([])
+    )
 }
 
 /// Checks if given pattern is a wildcard (`_`)
@@ -505,7 +520,7 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
             }
         };
     }
-    fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<&'tcx Export<HirId>> {
+    fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<&'tcx Export> {
         tcx.item_children(def_id)
             .iter()
             .find(|item| item.ident.name.as_str() == name)
@@ -542,7 +557,7 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
                 None
             }
         });
-    try_res!(last).res
+    try_res!(last).res.expect_non_local()
 }
 
 /// Convenience function to get the `DefId` of a trait by path.
@@ -629,12 +644,106 @@ pub fn can_mut_borrow_both(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>) -
     false
 }
 
+/// Returns true if the `def_id` associated with the `path` is recognized as a "default-equivalent"
+/// constructor from the std library
+fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath<'_>) -> bool {
+    let std_types_symbols = &[
+        sym::string_type,
+        sym::vec_type,
+        sym::vecdeque_type,
+        sym::LinkedList,
+        sym::hashmap_type,
+        sym::BTreeMap,
+        sym::hashset_type,
+        sym::BTreeSet,
+        sym::BinaryHeap,
+    ];
+
+    if let QPath::TypeRelative(_, method) = path {
+        if method.ident.name == sym::new {
+            if let Some(impl_did) = cx.tcx.impl_of_method(def_id) {
+                if let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def() {
+                    return std_types_symbols
+                        .iter()
+                        .any(|&symbol| cx.tcx.is_diagnostic_item(symbol, adt.did));
+                }
+            }
+        }
+    }
+    false
+}
+
+/// Returns true if the expr is equal to `Default::default()` of it's type when evaluated.
+/// It doesn't cover all cases, for example indirect function calls (some of std
+/// functions are supported) but it is the best we have.
+pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
+    match &e.kind {
+        ExprKind::Lit(lit) => match lit.node {
+            LitKind::Bool(false) | LitKind::Int(0, _) => true,
+            LitKind::Str(s, _) => s.is_empty(),
+            _ => false,
+        },
+        ExprKind::Tup(items) | ExprKind::Array(items) => items.iter().all(|x| is_default_equivalent(cx, x)),
+        ExprKind::Repeat(x, _) => is_default_equivalent(cx, x),
+        ExprKind::Call(repl_func, _) => if_chain! {
+            if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind;
+            if let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id();
+            if is_diag_trait_item(cx, repl_def_id, sym::Default)
+                || is_default_equivalent_ctor(cx, repl_def_id, repl_func_qpath);
+            then {
+                true
+            }
+            else {
+                false
+            }
+        },
+        ExprKind::Path(qpath) => is_lang_ctor(cx, qpath, OptionNone),
+        ExprKind::AddrOf(rustc_hir::BorrowKind::Ref, _, expr) => matches!(expr.kind, ExprKind::Array([])),
+        _ => false,
+    }
+}
+
 /// Checks if the top level expression can be moved into a closure as is.
-pub fn can_move_expr_to_closure_no_visit(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, jump_targets: &[HirId]) -> bool {
+/// Currently checks for:
+/// * Break/Continue outside the given loop HIR ids.
+/// * Yield/Return statments.
+/// * Inline assembly.
+/// * Usages of a field of a local where the type of the local can be partially moved.
+///
+/// For example, given the following function:
+///
+/// ```
+/// fn f<'a>(iter: &mut impl Iterator<Item = (usize, &'a mut String)>) {
+///     for item in iter {
+///         let s = item.1;
+///         if item.0 > 10 {
+///             continue;
+///         } else {
+///             s.clear();
+///         }
+///     }
+/// }
+/// ```
+///
+/// When called on the expression `item.0` this will return false unless the local `item` is in the
+/// `ignore_locals` set. The type `(usize, &mut String)` can have the second element moved, so it
+/// isn't always safe to move into a closure when only a single field is needed.
+///
+/// When called on the `continue` expression this will return false unless the outer loop expression
+/// is in the `loop_ids` set.
+///
+/// Note that this check is not recursive, so passing the `if` expression will always return true
+/// even though sub-expressions might return false.
+pub fn can_move_expr_to_closure_no_visit(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx Expr<'_>,
+    loop_ids: &[HirId],
+    ignore_locals: &HirIdSet,
+) -> bool {
     match expr.kind {
         ExprKind::Break(Destination { target_id: Ok(id), .. }, _)
         | ExprKind::Continue(Destination { target_id: Ok(id), .. })
-            if jump_targets.contains(&id) =>
+            if loop_ids.contains(&id) =>
         {
             true
         },
@@ -646,25 +755,170 @@ pub fn can_move_expr_to_closure_no_visit(cx: &LateContext<'tcx>, expr: &'tcx Exp
         | ExprKind::LlvmInlineAsm(_) => false,
         // Accessing a field of a local value can only be done if the type isn't
         // partially moved.
-        ExprKind::Field(base_expr, _)
-            if matches!(
-                base_expr.kind,
-                ExprKind::Path(QPath::Resolved(_, Path { res: Res::Local(_), .. }))
-            ) && can_partially_move_ty(cx, cx.typeck_results().expr_ty(base_expr)) =>
-        {
+        ExprKind::Field(
+            &Expr {
+                hir_id,
+                kind:
+                    ExprKind::Path(QPath::Resolved(
+                        _,
+                        Path {
+                            res: Res::Local(local_id),
+                            ..
+                        },
+                    )),
+                ..
+            },
+            _,
+        ) if !ignore_locals.contains(local_id) && can_partially_move_ty(cx, cx.typeck_results().node_type(hir_id)) => {
             // TODO: check if the local has been partially moved. Assume it has for now.
             false
-        }
+        },
         _ => true,
     }
 }
 
-/// Checks if the expression can be moved into a closure as is.
-pub fn can_move_expr_to_closure(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
+/// How a local is captured by a closure
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum CaptureKind {
+    Value,
+    Ref(Mutability),
+}
+impl CaptureKind {
+    pub fn is_imm_ref(self) -> bool {
+        self == Self::Ref(Mutability::Not)
+    }
+}
+impl std::ops::BitOr for CaptureKind {
+    type Output = Self;
+    fn bitor(self, rhs: Self) -> Self::Output {
+        match (self, rhs) {
+            (CaptureKind::Value, _) | (_, CaptureKind::Value) => CaptureKind::Value,
+            (CaptureKind::Ref(Mutability::Mut), CaptureKind::Ref(_))
+            | (CaptureKind::Ref(_), CaptureKind::Ref(Mutability::Mut)) => CaptureKind::Ref(Mutability::Mut),
+            (CaptureKind::Ref(Mutability::Not), CaptureKind::Ref(Mutability::Not)) => CaptureKind::Ref(Mutability::Not),
+        }
+    }
+}
+impl std::ops::BitOrAssign for CaptureKind {
+    fn bitor_assign(&mut self, rhs: Self) {
+        *self = *self | rhs;
+    }
+}
+
+/// Given an expression referencing a local, determines how it would be captured in a closure.
+/// Note as this will walk up to parent expressions until the capture can be determined it should
+/// only be used while making a closure somewhere a value is consumed. e.g. a block, match arm, or
+/// function argument (other than a receiver).
+pub fn capture_local_usage(cx: &LateContext<'tcx>, e: &Expr<'_>) -> CaptureKind {
+    fn pat_capture_kind(cx: &LateContext<'_>, pat: &Pat<'_>) -> CaptureKind {
+        let mut capture = CaptureKind::Ref(Mutability::Not);
+        pat.each_binding_or_first(&mut |_, id, span, _| match cx
+            .typeck_results()
+            .extract_binding_mode(cx.sess(), id, span)
+            .unwrap()
+        {
+            BindingMode::BindByValue(_) if !is_copy(cx, cx.typeck_results().node_type(id)) => {
+                capture = CaptureKind::Value;
+            },
+            BindingMode::BindByReference(Mutability::Mut) if capture != CaptureKind::Value => {
+                capture = CaptureKind::Ref(Mutability::Mut);
+            },
+            _ => (),
+        });
+        capture
+    }
+
+    debug_assert!(matches!(
+        e.kind,
+        ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(_), .. }))
+    ));
+
+    let map = cx.tcx.hir();
+    let mut child_id = e.hir_id;
+    let mut capture = CaptureKind::Value;
+    let mut capture_expr_ty = e;
+
+    for (parent_id, parent) in map.parent_iter(e.hir_id) {
+        if let [Adjustment {
+            kind: Adjust::Deref(_) | Adjust::Borrow(AutoBorrow::Ref(..)),
+            target,
+        }, ref adjust @ ..] = *cx
+            .typeck_results()
+            .adjustments()
+            .get(child_id)
+            .map_or(&[][..], |x| &**x)
+        {
+            if let rustc_ty::RawPtr(TypeAndMut { mutbl: mutability, .. }) | rustc_ty::Ref(_, _, mutability) =
+                *adjust.last().map_or(target, |a| a.target).kind()
+            {
+                return CaptureKind::Ref(mutability);
+            }
+        }
+
+        match parent {
+            Node::Expr(e) => match e.kind {
+                ExprKind::AddrOf(_, mutability, _) => return CaptureKind::Ref(mutability),
+                ExprKind::Index(..) | ExprKind::Unary(UnOp::Deref, _) => capture = CaptureKind::Ref(Mutability::Not),
+                ExprKind::Assign(lhs, ..) | ExprKind::Assign(_, lhs, _) if lhs.hir_id == child_id => {
+                    return CaptureKind::Ref(Mutability::Mut);
+                },
+                ExprKind::Field(..) => {
+                    if capture == CaptureKind::Value {
+                        capture_expr_ty = e;
+                    }
+                },
+                ExprKind::Let(pat, ..) => {
+                    let mutability = match pat_capture_kind(cx, pat) {
+                        CaptureKind::Value => Mutability::Not,
+                        CaptureKind::Ref(m) => m,
+                    };
+                    return CaptureKind::Ref(mutability);
+                },
+                ExprKind::Match(_, arms, _) => {
+                    let mut mutability = Mutability::Not;
+                    for capture in arms.iter().map(|arm| pat_capture_kind(cx, arm.pat)) {
+                        match capture {
+                            CaptureKind::Value => break,
+                            CaptureKind::Ref(Mutability::Mut) => mutability = Mutability::Mut,
+                            CaptureKind::Ref(Mutability::Not) => (),
+                        }
+                    }
+                    return CaptureKind::Ref(mutability);
+                },
+                _ => break,
+            },
+            Node::Local(l) => match pat_capture_kind(cx, l.pat) {
+                CaptureKind::Value => break,
+                capture @ CaptureKind::Ref(_) => return capture,
+            },
+            _ => break,
+        }
+
+        child_id = parent_id;
+    }
+
+    if capture == CaptureKind::Value && is_copy(cx, cx.typeck_results().expr_ty(capture_expr_ty)) {
+        // Copy types are never automatically captured by value.
+        CaptureKind::Ref(Mutability::Not)
+    } else {
+        capture
+    }
+}
+
+/// Checks if the expression can be moved into a closure as is. This will return a list of captures
+/// if so, otherwise, `None`.
+pub fn can_move_expr_to_closure(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<HirIdMap<CaptureKind>> {
     struct V<'cx, 'tcx> {
         cx: &'cx LateContext<'tcx>,
+        // Stack of potential break targets contained in the expression.
         loops: Vec<HirId>,
+        /// Local variables created in the expression. These don't need to be captured.
+        locals: HirIdSet,
+        /// Whether this expression can be turned into a closure.
         allow_closure: bool,
+        /// Locals which need to be captured, and whether they need to be by value, reference, or
+        /// mutable reference.
+        captures: HirIdMap<CaptureKind>,
     }
     impl Visitor<'tcx> for V<'_, 'tcx> {
         type Map = ErasedMap<'tcx>;
@@ -676,24 +930,67 @@ pub fn can_move_expr_to_closure(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) ->
             if !self.allow_closure {
                 return;
             }
-            if let ExprKind::Loop(b, ..) = e.kind {
-                self.loops.push(e.hir_id);
-                self.visit_block(b);
-                self.loops.pop();
-            } else {
-                self.allow_closure &= can_move_expr_to_closure_no_visit(self.cx, e, &self.loops);
-                walk_expr(self, e);
+
+            match e.kind {
+                ExprKind::Path(QPath::Resolved(None, &Path { res: Res::Local(l), .. })) => {
+                    if !self.locals.contains(&l) {
+                        let cap = capture_local_usage(self.cx, e);
+                        self.captures.entry(l).and_modify(|e| *e |= cap).or_insert(cap);
+                    }
+                },
+                ExprKind::Closure(..) => {
+                    let closure_id = self.cx.tcx.hir().local_def_id(e.hir_id).to_def_id();
+                    for capture in self.cx.typeck_results().closure_min_captures_flattened(closure_id) {
+                        let local_id = match capture.place.base {
+                            PlaceBase::Local(id) => id,
+                            PlaceBase::Upvar(var) => var.var_path.hir_id,
+                            _ => continue,
+                        };
+                        if !self.locals.contains(&local_id) {
+                            let capture = match capture.info.capture_kind {
+                                UpvarCapture::ByValue(_) => CaptureKind::Value,
+                                UpvarCapture::ByRef(borrow) => match borrow.kind {
+                                    BorrowKind::ImmBorrow => CaptureKind::Ref(Mutability::Not),
+                                    BorrowKind::UniqueImmBorrow | BorrowKind::MutBorrow => {
+                                        CaptureKind::Ref(Mutability::Mut)
+                                    },
+                                },
+                            };
+                            self.captures
+                                .entry(local_id)
+                                .and_modify(|e| *e |= capture)
+                                .or_insert(capture);
+                        }
+                    }
+                },
+                ExprKind::Loop(b, ..) => {
+                    self.loops.push(e.hir_id);
+                    self.visit_block(b);
+                    self.loops.pop();
+                },
+                _ => {
+                    self.allow_closure &= can_move_expr_to_closure_no_visit(self.cx, e, &self.loops, &self.locals);
+                    walk_expr(self, e);
+                },
             }
         }
+
+        fn visit_pat(&mut self, p: &'tcx Pat<'tcx>) {
+            p.each_binding_or_first(&mut |_, id, _, _| {
+                self.locals.insert(id);
+            });
+        }
     }
 
     let mut v = V {
         cx,
         allow_closure: true,
         loops: Vec::new(),
+        locals: HirIdSet::default(),
+        captures: HirIdMap::default(),
     };
     v.visit_expr(expr);
-    v.allow_closure
+    v.allow_closure.then(|| v.captures)
 }
 
 /// Returns the method names and argument list of nested method call expressions that make up
@@ -1365,13 +1662,13 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>,
 
     while let Some(higher::IfOrIfLet { cond, then, r#else }) = higher::IfOrIfLet::hir(expr) {
         conds.push(&*cond);
-        if let ExprKind::Block(ref block, _) = then.kind {
+        if let ExprKind::Block(block, _) = then.kind {
             blocks.push(block);
         } else {
             panic!("ExprKind::If node is not an ExprKind::Block");
         }
 
-        if let Some(ref else_expr) = r#else {
+        if let Some(else_expr) = r#else {
             expr = else_expr;
         } else {
             break;
@@ -1708,7 +2005,7 @@ pub fn peel_hir_expr_while<'tcx>(
 pub fn peel_n_hir_expr_refs(expr: &'a Expr<'a>, count: usize) -> (&'a Expr<'a>, usize) {
     let mut remaining = count;
     let e = peel_hir_expr_while(expr, |e| match e.kind {
-        ExprKind::AddrOf(BorrowKind::Ref, _, e) if remaining != 0 => {
+        ExprKind::AddrOf(ast::BorrowKind::Ref, _, e) if remaining != 0 => {
             remaining -= 1;
             Some(e)
         },
@@ -1722,7 +2019,7 @@ pub fn peel_n_hir_expr_refs(expr: &'a Expr<'a>, count: usize) -> (&'a Expr<'a>,
 pub fn peel_hir_expr_refs(expr: &'a Expr<'a>) -> (&'a Expr<'a>, usize) {
     let mut count = 0;
     let e = peel_hir_expr_while(expr, |e| match e.kind {
-        ExprKind::AddrOf(BorrowKind::Ref, _, e) => {
+        ExprKind::AddrOf(ast::BorrowKind::Ref, _, e) => {
             count += 1;
             Some(e)
         },
diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs
index 4a9c4fd0276..fa57dfbb57e 100644
--- a/src/tools/clippy/clippy_utils/src/msrvs.rs
+++ b/src/tools/clippy/clippy_utils/src/msrvs.rs
@@ -13,9 +13,12 @@ macro_rules! msrv_aliases {
 // names may refer to stabilized feature flags or library items
 msrv_aliases! {
     1,53,0 { OR_PATTERNS }
+    1,52,0 { STR_SPLIT_ONCE }
     1,50,0 { BOOL_THEN }
+    1,47,0 { TAU }
     1,46,0 { CONST_IF_MATCH }
     1,45,0 { STR_STRIP_PREFIX }
+    1,43,0 { LOG2_10, LOG10_2 }
     1,42,0 { MATCHES_MACRO }
     1,41,0 { RE_REBALANCING_COHERENCE, RESULT_MAP_OR_ELSE }
     1,40,0 { MEM_TAKE, NON_EXHAUSTIVE, OPTION_AS_DEREF }
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index b0c3fe1e5a7..80be4350c3c 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -68,6 +68,7 @@ pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"];
 pub const IPADDR_V4: [&str; 5] = ["std", "net", "ip", "IpAddr", "V4"];
 pub const IPADDR_V6: [&str; 5] = ["std", "net", "ip", "IpAddr", "V6"];
 pub const ITER_REPEAT: [&str; 5] = ["core", "iter", "sources", "repeat", "repeat"];
+pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"];
 #[cfg(feature = "internal-lints")]
 pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"];
 #[cfg(feature = "internal-lints")]
@@ -103,7 +104,7 @@ pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 2] = ["parking_lot", "RwLockWri
 pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"];
 pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"];
 pub const PERMISSIONS: [&str; 3] = ["std", "fs", "Permissions"];
-pub const PERMISSIONS_FROM_MODE: [&str; 7] = ["std", "os", "imp", "unix", "fs", "PermissionsExt", "from_mode"];
+pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"];
 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"];
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 e5bbf75c3b0..e9a9895cb74 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
@@ -36,9 +36,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv: Option<&Ru
                 ty::PredicateKind::ObjectSafe(_) => panic!("object safe predicate on function: {:#?}", predicate),
                 ty::PredicateKind::ClosureKind(..) => panic!("closure kind predicate on function: {:#?}", predicate),
                 ty::PredicateKind::Subtype(_) => panic!("subtype predicate on function: {:#?}", predicate),
-                ty::PredicateKind::Coerce(_) => {
-                    panic!("coerce predicate on function: {:#?}", predicate)
-                },
+                ty::PredicateKind::Coerce(_) => panic!("coerce predicate on function: {:#?}", predicate),
                 ty::PredicateKind::Trait(pred) => {
                     if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
                         continue;
@@ -194,7 +192,7 @@ fn check_rvalue(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId, rvalue: &Rv
                 ))
             }
         },
-        Rvalue::NullaryOp(NullOp::SizeOf, _) => Ok(()),
+        Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => Ok(()),
         Rvalue::NullaryOp(NullOp::Box, _) => Err((span, "heap allocations are not allowed in const fn".into())),
         Rvalue::UnaryOp(_, operand) => {
             let ty = operand.ty(body, tcx);
@@ -366,7 +364,7 @@ fn check_terminator(
 }
 
 fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: Option<&RustcVersion>) -> bool {
-    rustc_mir::const_eval::is_const_fn(tcx, def_id)
+    rustc_const_eval::const_eval::is_const_fn(tcx, def_id)
         && tcx.lookup_const_stability(def_id).map_or(true, |const_stab| {
             if let rustc_attr::StabilityLevel::Stable { since } = const_stab.level {
                 // Checking MSRV is manually necessary because `rustc` has no such concept. This entire
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 65d93e8f86e..ab05a0b4238 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -329,7 +329,7 @@ fn has_enclosing_paren(sugg: impl AsRef<str>) -> bool {
     }
 }
 
-// Copied from the rust standart library, and then edited
+/// Copied from the rust standard library, and then edited
 macro_rules! forward_binop_impls_to_ref {
     (impl $imp:ident, $method:ident for $t:ty, type Output = $o:ty) => {
         impl $imp<$t> for &$t {
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 3cd8ed5aa2c..d6f9ebe89bc 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -10,7 +10,7 @@ use rustc_hir::{TyKind, Unsafety};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
-use rustc_middle::ty::{self, TyCtxt, AdtDef, IntTy, Ty, TypeFoldable, UintTy};
+use rustc_middle::ty::{self, AdtDef, IntTy, Ty, TyCtxt, TypeFoldable, UintTy};
 use rustc_span::sym;
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::DUMMY_SP;
@@ -224,6 +224,13 @@ fn is_normalizable_helper<'tcx>(
     result
 }
 
+/// Returns true iff the given type is a non aggregate primitive (a bool or char, any integer or
+/// floating-point number type). For checking aggregation of primitive types (e.g. tuples and slices
+/// of primitive type) see `is_recursively_primitive_type`
+pub fn is_non_aggregate_primitive_type(ty: Ty<'_>) -> bool {
+    matches!(ty.kind(), ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_))
+}
+
 /// Returns true iff the given type is a primitive (a bool or char, any integer or floating-point
 /// number type, a str, or an array, slice, or tuple of those types).
 pub fn is_recursively_primitive_type(ty: Ty<'_>) -> bool {
diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs
index ac885e99944..098ec175fe2 100644
--- a/src/tools/clippy/clippy_utils/src/usage.rs
+++ b/src/tools/clippy/clippy_utils/src/usage.rs
@@ -1,10 +1,9 @@
 use crate as utils;
 use rustc_hir as hir;
-use rustc_hir::def::Res;
 use rustc_hir::intravisit;
 use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
 use rustc_hir::HirIdSet;
-use rustc_hir::{Expr, ExprKind, HirId, Path};
+use rustc_hir::{Expr, ExprKind, HirId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
 use rustc_middle::hir::map::Map;
@@ -35,12 +34,8 @@ pub fn mutated_variables<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) ->
     Some(delegate.used_mutably)
 }
 
-pub fn is_potentially_mutated<'tcx>(variable: &'tcx Path<'_>, expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> bool {
-    if let Res::Local(id) = variable.res {
-        mutated_variables(expr, cx).map_or(true, |mutated| mutated.contains(&id))
-    } else {
-        true
-    }
+pub fn is_potentially_mutated<'tcx>(variable: HirId, expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> bool {
+    mutated_variables(expr, cx).map_or(true, |mutated| mutated.contains(&variable))
 }
 
 struct MutVarsDelegate {
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index ce00106dd4d..503effbdad5 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -4,6 +4,7 @@ use rustc_hir::intravisit::{self, walk_expr, ErasedMap, NestedVisitorMap, Visito
 use rustc_hir::{def::Res, Arm, Block, Body, BodyId, Destination, Expr, ExprKind, HirId, Stmt};
 use rustc_lint::LateContext;
 use rustc_middle::hir::map::Map;
+use std::ops::ControlFlow;
 
 /// returns `true` if expr contains match expr desugared from try
 fn contains_try(expr: &hir::Expr<'_>) -> bool {
@@ -133,62 +134,6 @@ where
     }
 }
 
-pub struct LocalUsedVisitor<'hir> {
-    hir: Map<'hir>,
-    pub local_hir_id: HirId,
-    pub used: bool,
-}
-
-impl<'hir> LocalUsedVisitor<'hir> {
-    pub fn new(cx: &LateContext<'hir>, local_hir_id: HirId) -> Self {
-        Self {
-            hir: cx.tcx.hir(),
-            local_hir_id,
-            used: false,
-        }
-    }
-
-    fn check<T>(&mut self, t: T, visit: fn(&mut Self, T)) -> bool {
-        visit(self, t);
-        std::mem::replace(&mut self.used, false)
-    }
-
-    pub fn check_arm(&mut self, arm: &'hir Arm<'_>) -> bool {
-        self.check(arm, Self::visit_arm)
-    }
-
-    pub fn check_body(&mut self, body: &'hir Body<'_>) -> bool {
-        self.check(body, Self::visit_body)
-    }
-
-    pub fn check_expr(&mut self, expr: &'hir Expr<'_>) -> bool {
-        self.check(expr, Self::visit_expr)
-    }
-
-    pub fn check_stmt(&mut self, stmt: &'hir Stmt<'_>) -> bool {
-        self.check(stmt, Self::visit_stmt)
-    }
-}
-
-impl<'v> Visitor<'v> for LocalUsedVisitor<'v> {
-    type Map = Map<'v>;
-
-    fn visit_expr(&mut self, expr: &'v Expr<'v>) {
-        if self.used {
-            return;
-        }
-        if path_to_local_id(expr, self.local_hir_id) {
-            self.used = true;
-        } else {
-            walk_expr(self, expr);
-        }
-    }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::OnlyBodies(self.hir)
-    }
-}
-
 /// A type which can be visited.
 pub trait Visitable<'tcx> {
     /// Calls the corresponding `visit_*` function on the visitor.
@@ -203,7 +148,22 @@ macro_rules! visitable_ref {
         }
     };
 }
+visitable_ref!(Arm, visit_arm);
 visitable_ref!(Block, visit_block);
+visitable_ref!(Body, visit_body);
+visitable_ref!(Expr, visit_expr);
+visitable_ref!(Stmt, visit_stmt);
+
+// impl<'tcx, I: IntoIterator> Visitable<'tcx> for I
+// where
+//     I::Item: Visitable<'tcx>,
+// {
+//     fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) {
+//         for x in self {
+//             x.visit(visitor);
+//         }
+//     }
+// }
 
 /// Calls the given function for each break expression.
 pub fn visit_break_exprs<'tcx>(
@@ -260,3 +220,48 @@ pub fn is_res_used(cx: &LateContext<'_>, res: Res, body: BodyId) -> bool {
     v.visit_expr(&cx.tcx.hir().body(body).value);
     v.found
 }
+
+/// Calls the given function for each usage of the given local.
+pub fn for_each_local_usage<'tcx, B>(
+    cx: &LateContext<'tcx>,
+    visitable: impl Visitable<'tcx>,
+    id: HirId,
+    f: impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B>,
+) -> ControlFlow<B> {
+    struct V<'tcx, B, F> {
+        map: Map<'tcx>,
+        id: HirId,
+        f: F,
+        res: ControlFlow<B>,
+    }
+    impl<'tcx, B, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B>> Visitor<'tcx> for V<'tcx, B, F> {
+        type Map = Map<'tcx>;
+        fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+            NestedVisitorMap::OnlyBodies(self.map)
+        }
+
+        fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
+            if self.res.is_continue() {
+                if path_to_local_id(e, self.id) {
+                    self.res = (self.f)(e);
+                } else {
+                    walk_expr(self, e);
+                }
+            }
+        }
+    }
+
+    let mut v = V {
+        map: cx.tcx.hir(),
+        id,
+        f,
+        res: ControlFlow::CONTINUE,
+    };
+    visitable.visit(&mut v);
+    v.res
+}
+
+/// Checks if the given local is used.
+pub fn is_local_used(cx: &LateContext<'tcx>, visitable: impl Visitable<'tcx>, id: HirId) -> bool {
+    for_each_local_usage(cx, visitable, id, |_| ControlFlow::BREAK).is_break()
+}
diff --git a/src/tools/clippy/doc/adding_lints.md b/src/tools/clippy/doc/adding_lints.md
index f2260c3d1a2..004eb28b446 100644
--- a/src/tools/clippy/doc/adding_lints.md
+++ b/src/tools/clippy/doc/adding_lints.md
@@ -556,14 +556,15 @@ directory. Adding a configuration to a lint can be useful for thresholds or to c
 behavior that can be seen as a false positive for some users. Adding a configuration is done
 in the following steps:
 
-1. Adding a new configuration entry to [clippy_utils::conf](/clippy_utils/src/conf.rs)
+1. Adding a new configuration entry to [clippy_lints::utils::conf](/clippy_lints/src/utils/conf.rs)
     like this:
     ```rust
-    /// Lint: LINT_NAME. <The configuration field doc comment>
+    /// Lint: LINT_NAME.
+    ///
+    /// <The configuration field doc comment>
     (configuration_ident: Type = DefaultValue),
     ```
-    The configuration value and identifier should usually be the same. The doc comment will be
-    automatically added to the lint documentation.
+    The doc comment will be automatically added to the lint documentation.
 2. Adding the configuration value to the lint impl struct:
     1. This first requires the definition of a lint impl struct. Lint impl structs are usually
         generated with the `declare_lint_pass!` macro. This struct needs to be defined manually
diff --git a/src/tools/clippy/doc/common_tools_writing_lints.md b/src/tools/clippy/doc/common_tools_writing_lints.md
index 0a85f650011..1a6b7c8cb47 100644
--- a/src/tools/clippy/doc/common_tools_writing_lints.md
+++ b/src/tools/clippy/doc/common_tools_writing_lints.md
@@ -11,6 +11,7 @@ You may need following tooltips to catch up with common operations.
 
 Useful Rustc dev guide links:
 - [Stages of compilation](https://rustc-dev-guide.rust-lang.org/compiler-src.html#the-main-stages-of-compilation)
+- [Diagnostic items](https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-items.html)
 - [Type checking](https://rustc-dev-guide.rust-lang.org/type-checking.html)
 - [Ty module](https://rustc-dev-guide.rust-lang.org/ty.html)
 
@@ -75,20 +76,21 @@ impl LateLintPass<'_> for MyStructLint {
 
 # Checking if a type implements a specific trait
 
-There are two ways to do this, depending if the target trait is part of lang items.
+There are three ways to do this, depending on if the target trait has a diagnostic item, lang item or neither.
 
 ```rust
-use clippy_utils::{implements_trait, match_trait_method, paths};
+use clippy_utils::{implements_trait, is_trait_method, match_trait_method, paths};
+use rustc_span::symbol::sym;
 
 impl LateLintPass<'_> for MyStructLint {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        // 1. Using expression and Clippy's convenient method
-        // we use `match_trait_method` function from Clippy's toolbox
-        if match_trait_method(cx, expr, &paths::INTO) {
-            // `expr` implements `Into` trait
+        // 1. Using diagnostic items with the expression
+        // we use `is_trait_method` function from Clippy's utils
+        if is_trait_method(cx, expr, sym::Iterator) {
+            // method call in `expr` belongs to `Iterator` trait
         }
 
-        // 2. Using type context `TyCtxt`
+        // 2. Using lang items with the expression type
         let ty = cx.typeck_results().expr_ty(expr);
         if cx.tcx.lang_items()
             // we are looking for the `DefId` of `Drop` trait in lang items
@@ -97,15 +99,20 @@ impl LateLintPass<'_> for MyStructLint {
             .map_or(false, |id| implements_trait(cx, ty, id, &[])) {
                 // `expr` implements `Drop` trait
             }
+
+        // 3. Using the type path with the expression
+        // we use `match_trait_method` function from Clippy's utils
+        if match_trait_method(cx, expr, &paths::INTO) {
+            // `expr` implements `Into` trait
+        }
     }
 }
 ```
 
-> Prefer using lang items, if the target trait is available there.
-
-A list of defined paths for Clippy can be found in [paths.rs][paths]
+> Prefer using diagnostic and lang items, if the target trait has one.
 
 We access lang items through the type context `tcx`. `tcx` is of type [`TyCtxt`][TyCtxt] and is defined in the `rustc_middle` crate.
+A list of defined paths for Clippy can be found in [paths.rs][paths]
 
 # Checking if a type defines a specific method
 
diff --git a/src/tools/clippy/lintcheck/Cargo.toml b/src/tools/clippy/lintcheck/Cargo.toml
index 8c33fa372ec..f33f1b65eab 100644
--- a/src/tools/clippy/lintcheck/Cargo.toml
+++ b/src/tools/clippy/lintcheck/Cargo.toml
@@ -11,14 +11,15 @@ publish = false
 
 [dependencies]
 clap = "2.33"
-flate2 = {version = "1.0.19"}
-fs_extra = {version = "1.2.0"}
-rayon = {version = "1.5.0"}
-serde = {version = "1.0", features = ["derive"]}
-serde_json = {version = "1.0"}
-tar = {version = "0.4.30"}
-toml = {version = "0.5"}
-ureq = {version = "2.0.0-rc3"}
+flate2 = "1.0"
+fs_extra = "1.2"
+rayon = "1.5"
+serde = { version = "1.0", features = ["derive"] }
+serde_json = "1.0"
+tar = "0.4"
+toml = "0.5"
+ureq = "2.2"
+walkdir = "2.3"
 
 [features]
 deny-warnings = []
diff --git a/src/tools/clippy/lintcheck/src/main.rs b/src/tools/clippy/lintcheck/src/main.rs
index 7d2f3173fb0..f1e03ba4296 100644
--- a/src/tools/clippy/lintcheck/src/main.rs
+++ b/src/tools/clippy/lintcheck/src/main.rs
@@ -21,6 +21,7 @@ use clap::{App, Arg, ArgMatches};
 use rayon::prelude::*;
 use serde::{Deserialize, Serialize};
 use serde_json::Value;
+use walkdir::{DirEntry, WalkDir};
 
 #[cfg(not(windows))]
 const CLIPPY_DRIVER_PATH: &str = "target/debug/clippy-driver";
@@ -193,32 +194,41 @@ impl CrateSource {
                 }
             },
             CrateSource::Path { name, path, options } => {
-                use fs_extra::dir;
-
-                // simply copy the entire directory into our target dir
-                let copy_dest = PathBuf::from(format!("{}/", LINTCHECK_SOURCES));
+                // copy path into the dest_crate_root but skip directories that contain a CACHEDIR.TAG file.
+                // The target/ directory contains a CACHEDIR.TAG file so it is the most commonly skipped directory
+                // as a result of this filter.
+                let dest_crate_root = PathBuf::from(LINTCHECK_SOURCES).join(name);
+                if dest_crate_root.exists() {
+                    println!("Deleting existing directory at {:?}", dest_crate_root);
+                    std::fs::remove_dir_all(&dest_crate_root).unwrap();
+                }
 
-                // the source path of the crate we copied,  ${copy_dest}/crate_name
-                let crate_root = copy_dest.join(name); // .../crates/local_crate
+                println!("Copying {:?} to {:?}", path, dest_crate_root);
 
-                if crate_root.exists() {
-                    println!(
-                        "Not copying {} to {}, destination already exists",
-                        path.display(),
-                        crate_root.display()
-                    );
-                } else {
-                    println!("Copying {} to {}", path.display(), copy_dest.display());
+                fn is_cache_dir(entry: &DirEntry) -> bool {
+                    std::fs::read(entry.path().join("CACHEDIR.TAG"))
+                        .map(|x| x.starts_with(b"Signature: 8a477f597d28d172789f06886806bc55"))
+                        .unwrap_or(false)
+                }
 
-                    dir::copy(path, &copy_dest, &dir::CopyOptions::new()).unwrap_or_else(|_| {
-                        panic!("Failed to copy from {}, to  {}", path.display(), crate_root.display())
-                    });
+                for entry in WalkDir::new(path).into_iter().filter_entry(|e| !is_cache_dir(e)) {
+                    let entry = entry.unwrap();
+                    let entry_path = entry.path();
+                    let relative_entry_path = entry_path.strip_prefix(path).unwrap();
+                    let dest_path = dest_crate_root.join(relative_entry_path);
+                    let metadata = entry_path.symlink_metadata().unwrap();
+
+                    if metadata.is_dir() {
+                        std::fs::create_dir(dest_path).unwrap();
+                    } else if metadata.is_file() {
+                        std::fs::copy(entry_path, dest_path).unwrap();
+                    }
                 }
 
                 Crate {
                     version: String::from("local"),
                     name: name.clone(),
-                    path: crate_root,
+                    path: dest_crate_root,
                     options: options.clone(),
                 }
             },
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 23887f17845..92bde3423a2 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2021-08-12"
+channel = "nightly-2021-09-08"
 components = ["llvm-tools-preview", "rustc-dev", "rust-src"]
diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs
index 0a82377a10e..c63c47690d5 100644
--- a/src/tools/clippy/tests/compile-test.rs
+++ b/src/tools/clippy/tests/compile-test.rs
@@ -1,10 +1,12 @@
 #![feature(test)] // compiletest_rs requires this attribute
 #![feature(once_cell)]
-#![feature(try_blocks)]
+#![cfg_attr(feature = "deny-warnings", deny(warnings))]
+#![warn(rust_2018_idioms, unused_lifetimes)]
 
 use compiletest_rs as compiletest;
 use compiletest_rs::common::Mode as TestMode;
 
+use std::collections::HashMap;
 use std::env::{self, remove_var, set_var, var_os};
 use std::ffi::{OsStr, OsString};
 use std::fs;
@@ -16,6 +18,34 @@ mod cargo;
 // whether to run internal tests or not
 const RUN_INTERNAL_TESTS: bool = cfg!(feature = "internal-lints");
 
+/// All crates used in UI tests are listed here
+static TEST_DEPENDENCIES: &[&str] = &[
+    "clippy_utils",
+    "derive_new",
+    "if_chain",
+    "itertools",
+    "quote",
+    "regex",
+    "serde",
+    "serde_derive",
+    "syn",
+];
+
+// Test dependencies may need an `extern crate` here to ensure that they show up
+// in the depinfo file (otherwise cargo thinks they are unused)
+#[allow(unused_extern_crates)]
+extern crate clippy_utils;
+#[allow(unused_extern_crates)]
+extern crate derive_new;
+#[allow(unused_extern_crates)]
+extern crate if_chain;
+#[allow(unused_extern_crates)]
+extern crate itertools;
+#[allow(unused_extern_crates)]
+extern crate quote;
+#[allow(unused_extern_crates)]
+extern crate syn;
+
 fn host_lib() -> PathBuf {
     option_env!("HOST_LIBS").map_or(cargo::CARGO_TARGET_DIR.join(env!("PROFILE")), PathBuf::from)
 }
@@ -24,71 +54,58 @@ fn clippy_driver_path() -> PathBuf {
     option_env!("CLIPPY_DRIVER_PATH").map_or(cargo::TARGET_LIB.join("clippy-driver"), PathBuf::from)
 }
 
-// When we'll want to use `extern crate ..` for a dependency that is used
-// both by the crate and the compiler itself, we can't simply pass -L flags
-// as we'll get a duplicate matching versions. Instead, disambiguate with
-// `--extern dep=path`.
-// See https://github.com/rust-lang/rust-clippy/issues/4015.
-//
-// FIXME: We cannot use `cargo build --message-format=json` to resolve to dependency files.
-//        Because it would force-rebuild if the options passed to `build` command is not the same
-//        as what we manually pass to `cargo` invocation
-fn third_party_crates() -> String {
-    use std::collections::HashMap;
-    static CRATES: &[&str] = &[
-        "clippy_lints",
-        "clippy_utils",
-        "if_chain",
-        "quote",
-        "regex",
-        "serde",
-        "serde_derive",
-        "syn",
-    ];
-    let dep_dir = cargo::TARGET_LIB.join("deps");
-    let mut crates: HashMap<&str, Vec<PathBuf>> = HashMap::with_capacity(CRATES.len());
-    let mut flags = String::new();
-    for entry in fs::read_dir(dep_dir).unwrap().flatten() {
-        let path = entry.path();
-        if let Some(name) = try {
-            let name = path.file_name()?.to_str()?;
-            let (name, _) = name.strip_suffix(".rlib")?.strip_prefix("lib")?.split_once('-')?;
-            CRATES.iter().copied().find(|&c| c == name)?
-        } {
-            flags += &format!(" --extern {}={}", name, path.display());
-            crates.entry(name).or_default().push(path.clone());
+/// Produces a string with an `--extern` flag for all UI test crate
+/// dependencies.
+///
+/// The dependency files are located by parsing the depinfo file for this test
+/// module. This assumes the `-Z binary-dep-depinfo` flag is enabled. All test
+/// dependencies must be added to Cargo.toml at the project root. Test
+/// dependencies that are not *directly* used by this test module require an
+/// `extern crate` declaration.
+fn extern_flags() -> String {
+    let current_exe_depinfo = {
+        let mut path = env::current_exe().unwrap();
+        path.set_extension("d");
+        std::fs::read_to_string(path).unwrap()
+    };
+    let mut crates: HashMap<&str, &str> = HashMap::with_capacity(TEST_DEPENDENCIES.len());
+    for line in current_exe_depinfo.lines() {
+        // each dependency is expected to have a Makefile rule like `/path/to/crate-hash.rlib:`
+        let parse_name_path = || {
+            if line.starts_with(char::is_whitespace) {
+                return None;
+            }
+            let path_str = line.strip_suffix(':')?;
+            let path = Path::new(path_str);
+            if !matches!(path.extension()?.to_str()?, "rlib" | "so" | "dylib" | "dll") {
+                return None;
+            }
+            let (name, _hash) = path.file_stem()?.to_str()?.rsplit_once('-')?;
+            // the "lib" prefix is not present for dll files
+            let name = name.strip_prefix("lib").unwrap_or(name);
+            Some((name, path_str))
+        };
+        if let Some((name, path)) = parse_name_path() {
+            if TEST_DEPENDENCIES.contains(&name) {
+                // A dependency may be listed twice if it is available in sysroot,
+                // and the sysroot dependencies are listed first. As of the writing,
+                // this only seems to apply to if_chain.
+                crates.insert(name, path);
+            }
         }
     }
-    crates.retain(|_, paths| paths.len() > 1);
-    if !crates.is_empty() {
-        let crate_names = crates.keys().map(|s| format!("`{}`", s)).collect::<Vec<_>>().join(", ");
-        // add backslashes for an easy copy-paste `rm` command
-        let paths = crates
-            .into_values()
-            .flatten()
-            .map(|p| strip_current_dir(&p).display().to_string())
-            .collect::<Vec<_>>()
-            .join(" \\\n");
-        // Check which action should be done in order to remove compiled deps.
-        // If pre-installed version of compiler is used, `cargo clean` will do.
-        // Otherwise (for bootstrapped compiler), the dependencies directory
-        // must be removed manually.
-        let suggested_action = if std::env::var_os("RUSTC_BOOTSTRAP").is_some() {
-            "removing the stageN-tools directory"
-        } else {
-            "running `cargo clean`"
-        };
-
-        panic!(
-            "\n----------------------------------------------------------------------\n\
-            ERROR: Found multiple rlibs for crates: {}\n\
-            Try {} or remove the following files:\n\n{}\n\n\
-            For details on this error see https://github.com/rust-lang/rust-clippy/issues/7343\n\
-            ----------------------------------------------------------------------\n",
-            crate_names, suggested_action, paths
-        );
+    let not_found: Vec<&str> = TEST_DEPENDENCIES
+        .iter()
+        .copied()
+        .filter(|n| !crates.contains_key(n))
+        .collect();
+    if !not_found.is_empty() {
+        panic!("dependencies not found in depinfo: {:?}", not_found);
     }
-    flags
+    crates
+        .into_iter()
+        .map(|(name, path)| format!("--extern {}={} ", name, path))
+        .collect()
 }
 
 fn default_config() -> compiletest::Config {
@@ -104,11 +121,14 @@ fn default_config() -> compiletest::Config {
         config.compile_lib_path = path;
     }
 
+    // Using `-L dependency={}` enforces that external dependencies are added with `--extern`.
+    // This is valuable because a) it allows us to monitor what external dependencies are used
+    // and b) it ensures that conflicting rlibs are resolved properly.
     config.target_rustcflags = Some(format!(
-        "--emit=metadata -L {0} -L {1} -Dwarnings -Zui-testing {2}",
+        "--emit=metadata -L dependency={} -L dependency={} -Dwarnings -Zui-testing {}",
         host_lib().join("deps").display(),
         cargo::TARGET_LIB.join("deps").display(),
-        third_party_crates(),
+        extern_flags(),
     ));
 
     config.build_base = host_lib().join("test_build_base");
@@ -315,12 +335,3 @@ impl Drop for VarGuard {
         }
     }
 }
-
-fn strip_current_dir(path: &Path) -> &Path {
-    if let Ok(curr) = env::current_dir() {
-        if let Ok(stripped) = path.strip_prefix(curr) {
-            return stripped;
-        }
-    }
-    path
-}
diff --git a/src/tools/clippy/tests/dogfood.rs b/src/tools/clippy/tests/dogfood.rs
index 4ede20c5258..54f452172de 100644
--- a/src/tools/clippy/tests/dogfood.rs
+++ b/src/tools/clippy/tests/dogfood.rs
@@ -6,6 +6,8 @@
 // Dogfood cannot run on Windows
 #![cfg(not(windows))]
 #![feature(once_cell)]
+#![cfg_attr(feature = "deny-warnings", deny(warnings))]
+#![warn(rust_2018_idioms, unused_lifetimes)]
 
 use std::lazy::SyncLazy;
 use std::path::PathBuf;
diff --git a/src/tools/clippy/tests/fmt.rs b/src/tools/clippy/tests/fmt.rs
index 7616d8001e8..be42f1fbb20 100644
--- a/src/tools/clippy/tests/fmt.rs
+++ b/src/tools/clippy/tests/fmt.rs
@@ -1,3 +1,6 @@
+#![cfg_attr(feature = "deny-warnings", deny(warnings))]
+#![warn(rust_2018_idioms, unused_lifetimes)]
+
 use std::path::PathBuf;
 use std::process::Command;
 
diff --git a/src/tools/clippy/tests/integration.rs b/src/tools/clippy/tests/integration.rs
index 1718089e8bd..7e3eff3c732 100644
--- a/src/tools/clippy/tests/integration.rs
+++ b/src/tools/clippy/tests/integration.rs
@@ -1,4 +1,6 @@
 #![cfg(feature = "integration")]
+#![cfg_attr(feature = "deny-warnings", deny(warnings))]
+#![warn(rust_2018_idioms, unused_lifetimes)]
 
 use std::env;
 use std::ffi::OsStr;
diff --git a/src/tools/clippy/tests/lint_message_convention.rs b/src/tools/clippy/tests/lint_message_convention.rs
index 2f8989c8e11..b4d94dc983f 100644
--- a/src/tools/clippy/tests/lint_message_convention.rs
+++ b/src/tools/clippy/tests/lint_message_convention.rs
@@ -1,3 +1,6 @@
+#![cfg_attr(feature = "deny-warnings", deny(warnings))]
+#![warn(rust_2018_idioms, unused_lifetimes)]
+
 use std::ffi::OsStr;
 use std::path::PathBuf;
 
diff --git a/src/tools/clippy/tests/missing-test-files.rs b/src/tools/clippy/tests/missing-test-files.rs
index 9cef7438d22..bd342e390f5 100644
--- a/src/tools/clippy/tests/missing-test-files.rs
+++ b/src/tools/clippy/tests/missing-test-files.rs
@@ -1,3 +1,5 @@
+#![cfg_attr(feature = "deny-warnings", deny(warnings))]
+#![warn(rust_2018_idioms, unused_lifetimes)]
 #![allow(clippy::assertions_on_constants)]
 
 use std::fs::{self, DirEntry};
diff --git a/src/tools/clippy/tests/ui-cargo/feature_name/fail/Cargo.toml b/src/tools/clippy/tests/ui-cargo/feature_name/fail/Cargo.toml
new file mode 100644
index 00000000000..97d51462a94
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/feature_name/fail/Cargo.toml
@@ -0,0 +1,21 @@
+
+# Content that triggers the lint goes here
+
+[package]
+name = "feature_name"
+version = "0.1.0"
+publish = false
+
+[workspace]
+
+[features]
+use-qwq = []
+use_qwq = []
+with-owo = []
+with_owo = []
+qvq-support = []
+qvq_support = []
+no-qaq = []
+no_qaq = []
+not-orz = []
+not_orz = []
diff --git a/src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.rs b/src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.rs
new file mode 100644
index 00000000000..64f01a98c90
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.rs
@@ -0,0 +1,7 @@
+// compile-flags: --crate-name=feature_name
+#![warn(clippy::redundant_feature_names)]
+#![warn(clippy::negative_feature_names)]
+
+fn main() {
+    // test code goes here
+}
diff --git a/src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.stderr b/src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.stderr
new file mode 100644
index 00000000000..b9e6cb49bc9
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.stderr
@@ -0,0 +1,44 @@
+error: the "no-" prefix in the feature name "no-qaq" is negative
+   |
+   = note: `-D clippy::negative-feature-names` implied by `-D warnings`
+   = help: consider renaming the feature to "qaq", but make sure the feature adds functionality
+
+error: the "no_" prefix in the feature name "no_qaq" is negative
+   |
+   = help: consider renaming the feature to "qaq", but make sure the feature adds functionality
+
+error: the "not-" prefix in the feature name "not-orz" is negative
+   |
+   = help: consider renaming the feature to "orz", but make sure the feature adds functionality
+
+error: the "not_" prefix in the feature name "not_orz" is negative
+   |
+   = help: consider renaming the feature to "orz", but make sure the feature adds functionality
+
+error: the "-support" suffix in the feature name "qvq-support" is redundant
+   |
+   = note: `-D clippy::redundant-feature-names` implied by `-D warnings`
+   = help: consider renaming the feature to "qvq"
+
+error: the "_support" suffix in the feature name "qvq_support" is redundant
+   |
+   = help: consider renaming the feature to "qvq"
+
+error: the "use-" prefix in the feature name "use-qwq" is redundant
+   |
+   = help: consider renaming the feature to "qwq"
+
+error: the "use_" prefix in the feature name "use_qwq" is redundant
+   |
+   = help: consider renaming the feature to "qwq"
+
+error: the "with-" prefix in the feature name "with-owo" is redundant
+   |
+   = help: consider renaming the feature to "owo"
+
+error: the "with_" prefix in the feature name "with_owo" is redundant
+   |
+   = help: consider renaming the feature to "owo"
+
+error: aborting due to 10 previous errors
+
diff --git a/src/tools/clippy/tests/ui-cargo/feature_name/pass/Cargo.toml b/src/tools/clippy/tests/ui-cargo/feature_name/pass/Cargo.toml
new file mode 100644
index 00000000000..cf947312bd4
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/feature_name/pass/Cargo.toml
@@ -0,0 +1,9 @@
+
+# This file should not trigger the lint
+
+[package]
+name = "feature_name"
+version = "0.1.0"
+publish = false
+
+[workspace]
diff --git a/src/tools/clippy/tests/ui-cargo/feature_name/pass/src/main.rs b/src/tools/clippy/tests/ui-cargo/feature_name/pass/src/main.rs
new file mode 100644
index 00000000000..64f01a98c90
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/feature_name/pass/src/main.rs
@@ -0,0 +1,7 @@
+// compile-flags: --crate-name=feature_name
+#![warn(clippy::redundant_feature_names)]
+#![warn(clippy::negative_feature_names)]
+
+fn main() {
+    // test code goes here
+}
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/Cargo.toml b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/Cargo.toml
new file mode 100644
index 00000000000..27b61c09fb4
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "fail"
+version = "0.1.0"
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/bad/inner.rs b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/bad/inner.rs
new file mode 100644
index 00000000000..91cd540a28f
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/bad/inner.rs
@@ -0,0 +1 @@
+pub mod stuff;
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/bad/inner/stuff.rs b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/bad/inner/stuff.rs
new file mode 100644
index 00000000000..7713fa9d35c
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/bad/inner/stuff.rs
@@ -0,0 +1,3 @@
+pub mod most;
+
+pub struct Inner;
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/bad/inner/stuff/most.rs b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/bad/inner/stuff/most.rs
new file mode 100644
index 00000000000..5a5eaf9670f
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/bad/inner/stuff/most.rs
@@ -0,0 +1 @@
+pub struct Snarks;
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/bad/mod.rs b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/bad/mod.rs
new file mode 100644
index 00000000000..a12734db7cb
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/bad/mod.rs
@@ -0,0 +1,3 @@
+pub mod inner;
+
+pub struct Thing;
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.rs b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.rs
new file mode 100644
index 00000000000..3e985d4e904
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.rs
@@ -0,0 +1,9 @@
+#![warn(clippy::self_named_module_files)]
+
+mod bad;
+
+fn main() {
+    let _ = bad::Thing;
+    let _ = bad::inner::stuff::Inner;
+    let _ = bad::inner::stuff::most::Snarks;
+}
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.stderr b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.stderr
new file mode 100644
index 00000000000..af4c298b310
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.stderr
@@ -0,0 +1,19 @@
+error: `mod.rs` files are required, found `/bad/inner.rs`
+  --> $DIR/bad/inner.rs:1:1
+   |
+LL | pub mod stuff;
+   | ^
+   |
+   = note: `-D clippy::self-named-module-files` implied by `-D warnings`
+   = help: move `/bad/inner.rs` to `/bad/inner/mod.rs`
+
+error: `mod.rs` files are required, found `/bad/inner/stuff.rs`
+  --> $DIR/bad/inner/stuff.rs:1:1
+   |
+LL | pub mod most;
+   | ^
+   |
+   = help: move `/bad/inner/stuff.rs` to `/bad/inner/stuff/mod.rs`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/Cargo.toml b/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/Cargo.toml
new file mode 100644
index 00000000000..27b61c09fb4
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "fail"
+version = "0.1.0"
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/bad/mod.rs b/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/bad/mod.rs
new file mode 100644
index 00000000000..f19ab10d5fb
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/bad/mod.rs
@@ -0,0 +1 @@
+pub struct Thing;
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.rs b/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.rs
new file mode 100644
index 00000000000..c6e9045b8dc
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.rs
@@ -0,0 +1,7 @@
+#![warn(clippy::mod_module_files)]
+
+mod bad;
+
+fn main() {
+    let _ = bad::Thing;
+}
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr b/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr
new file mode 100644
index 00000000000..11e15db7fb9
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr
@@ -0,0 +1,11 @@
+error: `mod.rs` files are not allowed, found `/bad/mod.rs`
+  --> $DIR/bad/mod.rs:1:1
+   |
+LL | pub struct Thing;
+   | ^
+   |
+   = note: `-D clippy::mod-module-files` implied by `-D warnings`
+   = help: move `/bad/mod.rs` to `/bad.rs`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/pass_mod/Cargo.toml b/src/tools/clippy/tests/ui-cargo/module_style/pass_mod/Cargo.toml
new file mode 100644
index 00000000000..27b61c09fb4
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/pass_mod/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "fail"
+version = "0.1.0"
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/bad/mod.rs b/src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/bad/mod.rs
new file mode 100644
index 00000000000..f19ab10d5fb
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/bad/mod.rs
@@ -0,0 +1 @@
+pub struct Thing;
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/main.rs b/src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/main.rs
new file mode 100644
index 00000000000..9e08715fc05
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/main.rs
@@ -0,0 +1,10 @@
+#![warn(clippy::self_named_module_files)]
+
+mod bad;
+mod more;
+
+fn main() {
+    let _ = bad::Thing;
+    let _ = more::foo::Foo;
+    let _ = more::inner::Inner;
+}
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/more/foo.rs b/src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/more/foo.rs
new file mode 100644
index 00000000000..4a835673a59
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/more/foo.rs
@@ -0,0 +1 @@
+pub struct Foo;
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/more/inner/mod.rs b/src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/more/inner/mod.rs
new file mode 100644
index 00000000000..aa84f78cc2c
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/more/inner/mod.rs
@@ -0,0 +1 @@
+pub struct Inner;
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/more/mod.rs b/src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/more/mod.rs
new file mode 100644
index 00000000000..d79569f78ff
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/pass_mod/src/more/mod.rs
@@ -0,0 +1,2 @@
+pub mod foo;
+pub mod inner;
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/pass_no_mod/Cargo.toml b/src/tools/clippy/tests/ui-cargo/module_style/pass_no_mod/Cargo.toml
new file mode 100644
index 00000000000..3c0896dd2cd
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/pass_no_mod/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "pass"
+version = "0.1.0"
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/pass_no_mod/src/good.rs b/src/tools/clippy/tests/ui-cargo/module_style/pass_no_mod/src/good.rs
new file mode 100644
index 00000000000..f19ab10d5fb
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/pass_no_mod/src/good.rs
@@ -0,0 +1 @@
+pub struct Thing;
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/pass_no_mod/src/main.rs b/src/tools/clippy/tests/ui-cargo/module_style/pass_no_mod/src/main.rs
new file mode 100644
index 00000000000..50211a340b9
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/pass_no_mod/src/main.rs
@@ -0,0 +1,7 @@
+#![warn(clippy::mod_module_files)]
+
+mod good;
+
+fn main() {
+    let _ = good::Thing;
+}
diff --git a/src/tools/clippy/tests/ui/approx_const.rs b/src/tools/clippy/tests/ui/approx_const.rs
index fb57a0becbb..2ae4d613507 100644
--- a/src/tools/clippy/tests/ui/approx_const.rs
+++ b/src/tools/clippy/tests/ui/approx_const.rs
@@ -57,4 +57,8 @@ fn main() {
 
     let my_sq2 = 1.4142;
     let no_sq2 = 1.414;
+
+    let my_tau = 6.2832;
+    let almost_tau = 6.28;
+    let no_tau = 6.3;
 }
diff --git a/src/tools/clippy/tests/ui/approx_const.stderr b/src/tools/clippy/tests/ui/approx_const.stderr
index 98b85443f0b..4da1b8215ae 100644
--- a/src/tools/clippy/tests/ui/approx_const.stderr
+++ b/src/tools/clippy/tests/ui/approx_const.stderr
@@ -1,130 +1,187 @@
-error: approximate value of `f{32, 64}::consts::E` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::E` found
   --> $DIR/approx_const.rs:4:16
    |
 LL |     let my_e = 2.7182;
    |                ^^^^^^
    |
    = note: `-D clippy::approx-constant` implied by `-D warnings`
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::E` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::E` found
   --> $DIR/approx_const.rs:5:20
    |
 LL |     let almost_e = 2.718;
    |                    ^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::FRAC_1_PI` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::FRAC_1_PI` found
   --> $DIR/approx_const.rs:8:24
    |
 LL |     let my_1_frac_pi = 0.3183;
    |                        ^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found
   --> $DIR/approx_const.rs:11:28
    |
 LL |     let my_frac_1_sqrt_2 = 0.70710678;
    |                            ^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found
   --> $DIR/approx_const.rs:12:32
    |
 LL |     let almost_frac_1_sqrt_2 = 0.70711;
    |                                ^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::FRAC_2_PI` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::FRAC_2_PI` found
   --> $DIR/approx_const.rs:15:24
    |
 LL |     let my_frac_2_pi = 0.63661977;
    |                        ^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::FRAC_2_SQRT_PI` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::FRAC_2_SQRT_PI` found
   --> $DIR/approx_const.rs:18:27
    |
 LL |     let my_frac_2_sq_pi = 1.128379;
    |                           ^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::FRAC_PI_2` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::FRAC_PI_2` found
   --> $DIR/approx_const.rs:21:24
    |
 LL |     let my_frac_pi_2 = 1.57079632679;
    |                        ^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::FRAC_PI_3` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::FRAC_PI_3` found
   --> $DIR/approx_const.rs:24:24
    |
 LL |     let my_frac_pi_3 = 1.04719755119;
    |                        ^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::FRAC_PI_4` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::FRAC_PI_4` found
   --> $DIR/approx_const.rs:27:24
    |
 LL |     let my_frac_pi_4 = 0.785398163397;
    |                        ^^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::FRAC_PI_6` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::FRAC_PI_6` found
   --> $DIR/approx_const.rs:30:24
    |
 LL |     let my_frac_pi_6 = 0.523598775598;
    |                        ^^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::FRAC_PI_8` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::FRAC_PI_8` found
   --> $DIR/approx_const.rs:33:24
    |
 LL |     let my_frac_pi_8 = 0.3926990816987;
    |                        ^^^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::LN_10` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::LN_10` found
   --> $DIR/approx_const.rs:36:20
    |
 LL |     let my_ln_10 = 2.302585092994046;
    |                    ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::LN_2` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::LN_2` found
   --> $DIR/approx_const.rs:39:19
    |
 LL |     let my_ln_2 = 0.6931471805599453;
    |                   ^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::LOG10_E` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::LOG10_E` found
   --> $DIR/approx_const.rs:42:22
    |
 LL |     let my_log10_e = 0.4342944819032518;
    |                      ^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::LOG2_E` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::LOG2_E` found
   --> $DIR/approx_const.rs:45:21
    |
 LL |     let my_log2_e = 1.4426950408889634;
    |                     ^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::LOG2_10` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::LOG2_10` found
   --> $DIR/approx_const.rs:48:19
    |
 LL |     let log2_10 = 3.321928094887362;
    |                   ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::LOG10_2` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::LOG10_2` found
   --> $DIR/approx_const.rs:51:19
    |
 LL |     let log10_2 = 0.301029995663981;
    |                   ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::PI` found
   --> $DIR/approx_const.rs:54:17
    |
 LL |     let my_pi = 3.1415;
    |                 ^^^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::PI` found
   --> $DIR/approx_const.rs:55:21
    |
 LL |     let almost_pi = 3.14;
    |                     ^^^^
+   |
+   = help: consider using the constant directly
 
-error: approximate value of `f{32, 64}::consts::SQRT_2` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::SQRT_2` found
   --> $DIR/approx_const.rs:58:18
    |
 LL |     let my_sq2 = 1.4142;
    |                  ^^^^^^
+   |
+   = help: consider using the constant directly
+
+error: approximate value of `f{32, 64}::consts::TAU` found
+  --> $DIR/approx_const.rs:61:18
+   |
+LL |     let my_tau = 6.2832;
+   |                  ^^^^^^
+   |
+   = help: consider using the constant directly
+
+error: approximate value of `f{32, 64}::consts::TAU` found
+  --> $DIR/approx_const.rs:62:22
+   |
+LL |     let almost_tau = 6.28;
+   |                      ^^^^
+   |
+   = help: consider using the constant directly
 
-error: aborting due to 21 previous errors
+error: aborting due to 23 previous errors
 
diff --git a/src/tools/clippy/tests/ui/auxiliary/option_helpers.rs b/src/tools/clippy/tests/ui/auxiliary/option_helpers.rs
index 7dc3f4ebd4d..86a637ce309 100644
--- a/src/tools/clippy/tests/ui/auxiliary/option_helpers.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/option_helpers.rs
@@ -53,3 +53,12 @@ impl IteratorFalsePositives {
         self.foo as usize
     }
 }
+
+#[derive(Copy, Clone)]
+pub struct IteratorMethodFalsePositives;
+
+impl IteratorMethodFalsePositives {
+    pub fn filter(&self, _s: i32) -> std::vec::IntoIter<i32> {
+        unimplemented!();
+    }
+}
diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.rs b/src/tools/clippy/tests/ui/bool_assert_comparison.rs
index 2de402fae8c..ec4d6f3ff84 100644
--- a/src/tools/clippy/tests/ui/bool_assert_comparison.rs
+++ b/src/tools/clippy/tests/ui/bool_assert_comparison.rs
@@ -1,5 +1,7 @@
 #![warn(clippy::bool_assert_comparison)]
 
+use std::ops::Not;
+
 macro_rules! a {
     () => {
         true
@@ -11,7 +13,58 @@ macro_rules! b {
     };
 }
 
+// Implements the Not trait but with an output type
+// that's not bool. Should not suggest a rewrite
+#[derive(Debug)]
+enum ImplNotTraitWithoutBool {
+    VariantX(bool),
+    VariantY(u32),
+}
+
+impl PartialEq<bool> for ImplNotTraitWithoutBool {
+    fn eq(&self, other: &bool) -> bool {
+        match *self {
+            ImplNotTraitWithoutBool::VariantX(b) => b == *other,
+            _ => false,
+        }
+    }
+}
+
+impl Not for ImplNotTraitWithoutBool {
+    type Output = Self;
+
+    fn not(self) -> Self::Output {
+        match self {
+            ImplNotTraitWithoutBool::VariantX(b) => ImplNotTraitWithoutBool::VariantX(!b),
+            ImplNotTraitWithoutBool::VariantY(0) => ImplNotTraitWithoutBool::VariantY(1),
+            ImplNotTraitWithoutBool::VariantY(_) => ImplNotTraitWithoutBool::VariantY(0),
+        }
+    }
+}
+
+// This type implements the Not trait with an Output of
+// type bool. Using assert!(..) must be suggested
+#[derive(Debug)]
+struct ImplNotTraitWithBool;
+
+impl PartialEq<bool> for ImplNotTraitWithBool {
+    fn eq(&self, other: &bool) -> bool {
+        false
+    }
+}
+
+impl Not for ImplNotTraitWithBool {
+    type Output = bool;
+
+    fn not(self) -> Self::Output {
+        true
+    }
+}
+
 fn main() {
+    let a = ImplNotTraitWithoutBool::VariantX(true);
+    let b = ImplNotTraitWithBool;
+
     assert_eq!("a".len(), 1);
     assert_eq!("a".is_empty(), false);
     assert_eq!("".is_empty(), true);
@@ -19,6 +72,8 @@ fn main() {
     assert_eq!(a!(), b!());
     assert_eq!(a!(), "".is_empty());
     assert_eq!("".is_empty(), b!());
+    assert_eq!(a, true);
+    assert_eq!(b, true);
 
     assert_ne!("a".len(), 1);
     assert_ne!("a".is_empty(), false);
@@ -27,6 +82,8 @@ fn main() {
     assert_ne!(a!(), b!());
     assert_ne!(a!(), "".is_empty());
     assert_ne!("".is_empty(), b!());
+    assert_ne!(a, true);
+    assert_ne!(b, true);
 
     debug_assert_eq!("a".len(), 1);
     debug_assert_eq!("a".is_empty(), false);
@@ -35,6 +92,8 @@ fn main() {
     debug_assert_eq!(a!(), b!());
     debug_assert_eq!(a!(), "".is_empty());
     debug_assert_eq!("".is_empty(), b!());
+    debug_assert_eq!(a, true);
+    debug_assert_eq!(b, true);
 
     debug_assert_ne!("a".len(), 1);
     debug_assert_ne!("a".is_empty(), false);
@@ -43,6 +102,8 @@ fn main() {
     debug_assert_ne!(a!(), b!());
     debug_assert_ne!(a!(), "".is_empty());
     debug_assert_ne!("".is_empty(), b!());
+    debug_assert_ne!(a, true);
+    debug_assert_ne!(b, true);
 
     // assert with error messages
     assert_eq!("a".len(), 1, "tadam {}", 1);
@@ -50,10 +111,12 @@ fn main() {
     assert_eq!("a".is_empty(), false, "tadam {}", 1);
     assert_eq!("a".is_empty(), false, "tadam {}", true);
     assert_eq!(false, "a".is_empty(), "tadam {}", true);
+    assert_eq!(a, true, "tadam {}", false);
 
     debug_assert_eq!("a".len(), 1, "tadam {}", 1);
     debug_assert_eq!("a".len(), 1, "tadam {}", true);
     debug_assert_eq!("a".is_empty(), false, "tadam {}", 1);
     debug_assert_eq!("a".is_empty(), false, "tadam {}", true);
     debug_assert_eq!(false, "a".is_empty(), "tadam {}", true);
+    debug_assert_eq!(a, true, "tadam {}", false);
 }
diff --git a/src/tools/clippy/tests/ui/bool_assert_comparison.stderr b/src/tools/clippy/tests/ui/bool_assert_comparison.stderr
index f57acf520d5..da9b56aa779 100644
--- a/src/tools/clippy/tests/ui/bool_assert_comparison.stderr
+++ b/src/tools/clippy/tests/ui/bool_assert_comparison.stderr
@@ -1,5 +1,5 @@
 error: used `assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:16:5
+  --> $DIR/bool_assert_comparison.rs:69:5
    |
 LL |     assert_eq!("a".is_empty(), false);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
@@ -7,106 +7,130 @@ LL |     assert_eq!("a".is_empty(), false);
    = note: `-D clippy::bool-assert-comparison` implied by `-D warnings`
 
 error: used `assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:17:5
+  --> $DIR/bool_assert_comparison.rs:70:5
    |
 LL |     assert_eq!("".is_empty(), true);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
 
 error: used `assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:18:5
+  --> $DIR/bool_assert_comparison.rs:71:5
    |
 LL |     assert_eq!(true, "".is_empty());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
 
+error: used `assert_eq!` with a literal bool
+  --> $DIR/bool_assert_comparison.rs:76:5
+   |
+LL |     assert_eq!(b, true);
+   |     ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
+
 error: used `assert_ne!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:24:5
+  --> $DIR/bool_assert_comparison.rs:79:5
    |
 LL |     assert_ne!("a".is_empty(), false);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
 
 error: used `assert_ne!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:25:5
+  --> $DIR/bool_assert_comparison.rs:80:5
    |
 LL |     assert_ne!("".is_empty(), true);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
 
 error: used `assert_ne!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:26:5
+  --> $DIR/bool_assert_comparison.rs:81:5
    |
 LL |     assert_ne!(true, "".is_empty());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
 
+error: used `assert_ne!` with a literal bool
+  --> $DIR/bool_assert_comparison.rs:86:5
+   |
+LL |     assert_ne!(b, true);
+   |     ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
+
 error: used `debug_assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:32:5
+  --> $DIR/bool_assert_comparison.rs:89:5
    |
 LL |     debug_assert_eq!("a".is_empty(), false);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
 
 error: used `debug_assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:33:5
+  --> $DIR/bool_assert_comparison.rs:90:5
    |
 LL |     debug_assert_eq!("".is_empty(), true);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
 
 error: used `debug_assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:34:5
+  --> $DIR/bool_assert_comparison.rs:91:5
    |
 LL |     debug_assert_eq!(true, "".is_empty());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
 
+error: used `debug_assert_eq!` with a literal bool
+  --> $DIR/bool_assert_comparison.rs:96:5
+   |
+LL |     debug_assert_eq!(b, true);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
+
 error: used `debug_assert_ne!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:40:5
+  --> $DIR/bool_assert_comparison.rs:99:5
    |
 LL |     debug_assert_ne!("a".is_empty(), false);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
 
 error: used `debug_assert_ne!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:41:5
+  --> $DIR/bool_assert_comparison.rs:100:5
    |
 LL |     debug_assert_ne!("".is_empty(), true);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
 
 error: used `debug_assert_ne!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:42:5
+  --> $DIR/bool_assert_comparison.rs:101:5
    |
 LL |     debug_assert_ne!(true, "".is_empty());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
 
+error: used `debug_assert_ne!` with a literal bool
+  --> $DIR/bool_assert_comparison.rs:106:5
+   |
+LL |     debug_assert_ne!(b, true);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
+
 error: used `assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:50:5
+  --> $DIR/bool_assert_comparison.rs:111:5
    |
 LL |     assert_eq!("a".is_empty(), false, "tadam {}", 1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
 
 error: used `assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:51:5
+  --> $DIR/bool_assert_comparison.rs:112:5
    |
 LL |     assert_eq!("a".is_empty(), false, "tadam {}", true);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
 
 error: used `assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:52:5
+  --> $DIR/bool_assert_comparison.rs:113:5
    |
 LL |     assert_eq!(false, "a".is_empty(), "tadam {}", true);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `assert!(..)`
 
 error: used `debug_assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:56:5
+  --> $DIR/bool_assert_comparison.rs:118:5
    |
 LL |     debug_assert_eq!("a".is_empty(), false, "tadam {}", 1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
 
 error: used `debug_assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:57:5
+  --> $DIR/bool_assert_comparison.rs:119:5
    |
 LL |     debug_assert_eq!("a".is_empty(), false, "tadam {}", true);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
 
 error: used `debug_assert_eq!` with a literal bool
-  --> $DIR/bool_assert_comparison.rs:58:5
+  --> $DIR/bool_assert_comparison.rs:120:5
    |
 LL |     debug_assert_eq!(false, "a".is_empty(), "tadam {}", true);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `debug_assert!(..)`
 
-error: aborting due to 18 previous errors
+error: aborting due to 22 previous errors
 
diff --git a/src/tools/clippy/tests/ui/box_vec.rs b/src/tools/clippy/tests/ui/box_vec.rs
index 87b67c23704..1d6366972da 100644
--- a/src/tools/clippy/tests/ui/box_vec.rs
+++ b/src/tools/clippy/tests/ui/box_vec.rs
@@ -1,6 +1,10 @@
 #![warn(clippy::all)]
-#![allow(clippy::boxed_local, clippy::needless_pass_by_value)]
-#![allow(clippy::blacklisted_name)]
+#![allow(
+    clippy::boxed_local,
+    clippy::needless_pass_by_value,
+    clippy::blacklisted_name,
+    unused
+)]
 
 macro_rules! boxit {
     ($init:expr, $x:ty) => {
@@ -11,22 +15,22 @@ macro_rules! boxit {
 fn test_macro() {
     boxit!(Vec::new(), Vec<u8>);
 }
-pub fn test(foo: Box<Vec<bool>>) {
-    println!("{:?}", foo.get(0))
-}
+fn test(foo: Box<Vec<bool>>) {}
 
-pub fn test2(foo: Box<dyn Fn(Vec<u32>)>) {
+fn test2(foo: Box<dyn Fn(Vec<u32>)>) {
     // pass if #31 is fixed
     foo(vec![1, 2, 3])
 }
 
-pub fn test_local_not_linted() {
+fn test_local_not_linted() {
     let _: Box<Vec<bool>>;
 }
 
-fn main() {
-    test(Box::new(Vec::new()));
-    test2(Box::new(|v| println!("{:?}", v)));
-    test_macro();
-    test_local_not_linted();
+// All of these test should be allowed because they are part of the
+// public api and `avoid_breaking_exported_api` is `false` by default.
+pub fn pub_test(foo: Box<Vec<bool>>) {}
+pub fn pub_test_ret() -> Box<Vec<bool>> {
+    Box::new(Vec::new())
 }
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/box_vec.stderr b/src/tools/clippy/tests/ui/box_vec.stderr
index 9b789334bae..58c1f13fb87 100644
--- a/src/tools/clippy/tests/ui/box_vec.stderr
+++ b/src/tools/clippy/tests/ui/box_vec.stderr
@@ -1,8 +1,8 @@
 error: you seem to be trying to use `Box<Vec<T>>`. Consider using just `Vec<T>`
-  --> $DIR/box_vec.rs:14:18
+  --> $DIR/box_vec.rs:18:14
    |
-LL | pub fn test(foo: Box<Vec<bool>>) {
-   |                  ^^^^^^^^^^^^^^
+LL | fn test(foo: Box<Vec<bool>>) {}
+   |              ^^^^^^^^^^^^^^
    |
    = note: `-D clippy::box-vec` implied by `-D warnings`
    = help: `Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation
diff --git a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.stderr b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.stderr
index 33bb5136ef8..46c6f69708e 100644
--- a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.stderr
+++ b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.stderr
@@ -1,4 +1,4 @@
-error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap` on `x` after checking its variant with `is_ok`
   --> $DIR/complex_conditionals.rs:8:9
    |
 LL |     if x.is_ok() && y.is_err() {
@@ -11,6 +11,7 @@ note: the lint level is defined here
    |
 LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: try using `if let` or `match`
 
 error: this call to `unwrap_err()` will always panic
   --> $DIR/complex_conditionals.rs:9:9
@@ -36,7 +37,7 @@ LL |     if x.is_ok() && y.is_err() {
 LL |         y.unwrap(); // will panic
    |         ^^^^^^^^^^
 
-error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap_err` on `y` after checking its variant with `is_err`
   --> $DIR/complex_conditionals.rs:11:9
    |
 LL |     if x.is_ok() && y.is_err() {
@@ -44,6 +45,8 @@ LL |     if x.is_ok() && y.is_err() {
 ...
 LL |         y.unwrap_err(); // unnecessary
    |         ^^^^^^^^^^^^^^
+   |
+   = help: try using `if let` or `match`
 
 error: this call to `unwrap()` will always panic
   --> $DIR/complex_conditionals.rs:25:9
@@ -54,7 +57,7 @@ LL |     if x.is_ok() || y.is_ok() {
 LL |         x.unwrap(); // will panic
    |         ^^^^^^^^^^
 
-error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap_err` on `x` after checking its variant with `is_ok`
   --> $DIR/complex_conditionals.rs:26:9
    |
 LL |     if x.is_ok() || y.is_ok() {
@@ -62,6 +65,8 @@ LL |     if x.is_ok() || y.is_ok() {
 ...
 LL |         x.unwrap_err(); // unnecessary
    |         ^^^^^^^^^^^^^^
+   |
+   = help: try using `if let` or `match`
 
 error: this call to `unwrap()` will always panic
   --> $DIR/complex_conditionals.rs:27:9
@@ -72,7 +77,7 @@ LL |     if x.is_ok() || y.is_ok() {
 LL |         y.unwrap(); // will panic
    |         ^^^^^^^^^^
 
-error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap_err` on `y` after checking its variant with `is_ok`
   --> $DIR/complex_conditionals.rs:28:9
    |
 LL |     if x.is_ok() || y.is_ok() {
@@ -80,14 +85,18 @@ LL |     if x.is_ok() || y.is_ok() {
 ...
 LL |         y.unwrap_err(); // unnecessary
    |         ^^^^^^^^^^^^^^
+   |
+   = help: try using `if let` or `match`
 
-error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap` on `x` after checking its variant with `is_ok`
   --> $DIR/complex_conditionals.rs:32:9
    |
 LL |     if x.is_ok() && !(y.is_ok() || z.is_err()) {
    |        --------- the check is happening here
 LL |         x.unwrap(); // unnecessary
    |         ^^^^^^^^^^
+   |
+   = help: try using `if let` or `match`
 
 error: this call to `unwrap_err()` will always panic
   --> $DIR/complex_conditionals.rs:33:9
@@ -107,7 +116,7 @@ LL |     if x.is_ok() && !(y.is_ok() || z.is_err()) {
 LL |         y.unwrap(); // will panic
    |         ^^^^^^^^^^
 
-error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap_err` on `y` after checking its variant with `is_ok`
   --> $DIR/complex_conditionals.rs:35:9
    |
 LL |     if x.is_ok() && !(y.is_ok() || z.is_err()) {
@@ -115,8 +124,10 @@ LL |     if x.is_ok() && !(y.is_ok() || z.is_err()) {
 ...
 LL |         y.unwrap_err(); // unnecessary
    |         ^^^^^^^^^^^^^^
+   |
+   = help: try using `if let` or `match`
 
-error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap` on `z` after checking its variant with `is_err`
   --> $DIR/complex_conditionals.rs:36:9
    |
 LL |     if x.is_ok() && !(y.is_ok() || z.is_err()) {
@@ -124,6 +135,8 @@ LL |     if x.is_ok() && !(y.is_ok() || z.is_err()) {
 ...
 LL |         z.unwrap(); // unnecessary
    |         ^^^^^^^^^^
+   |
+   = help: try using `if let` or `match`
 
 error: this call to `unwrap_err()` will always panic
   --> $DIR/complex_conditionals.rs:37:9
@@ -143,7 +156,7 @@ LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
 LL |         x.unwrap(); // will panic
    |         ^^^^^^^^^^
 
-error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap_err` on `x` after checking its variant with `is_ok`
   --> $DIR/complex_conditionals.rs:46:9
    |
 LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
@@ -151,8 +164,10 @@ LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
 ...
 LL |         x.unwrap_err(); // unnecessary
    |         ^^^^^^^^^^^^^^
+   |
+   = help: try using `if let` or `match`
 
-error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap` on `y` after checking its variant with `is_ok`
   --> $DIR/complex_conditionals.rs:47:9
    |
 LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
@@ -160,6 +175,8 @@ LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
 ...
 LL |         y.unwrap(); // unnecessary
    |         ^^^^^^^^^^
+   |
+   = help: try using `if let` or `match`
 
 error: this call to `unwrap_err()` will always panic
   --> $DIR/complex_conditionals.rs:48:9
@@ -179,7 +196,7 @@ LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
 LL |         z.unwrap(); // will panic
    |         ^^^^^^^^^^
 
-error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap_err` on `z` after checking its variant with `is_err`
   --> $DIR/complex_conditionals.rs:50:9
    |
 LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
@@ -187,6 +204,8 @@ LL |     if x.is_ok() || !(y.is_ok() && z.is_err()) {
 ...
 LL |         z.unwrap_err(); // unnecessary
    |         ^^^^^^^^^^^^^^
+   |
+   = help: try using `if let` or `match`
 
 error: aborting due to 20 previous errors
 
diff --git a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.stderr b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.stderr
index a01f7f956f6..542ab53300c 100644
--- a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.stderr
+++ b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals_nested.stderr
@@ -1,8 +1,8 @@
-error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap` on `x` after checking its variant with `is_some`
   --> $DIR/complex_conditionals_nested.rs:8:13
    |
 LL |         if x.is_some() {
-   |            ----------- the check is happening here
+   |         -------------- help: try: `if let Some(..) = x`
 LL |             x.unwrap(); // unnecessary
    |             ^^^^^^^^^^
    |
diff --git a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs
index 8f23fb28827..ee3fdfabe9d 100644
--- a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs
+++ b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.rs
@@ -37,8 +37,10 @@ fn main() {
     let x = Some(());
     if x.is_some() {
         x.unwrap(); // unnecessary
+        x.expect("an error message"); // unnecessary
     } else {
         x.unwrap(); // will panic
+        x.expect("an error message"); // will panic
     }
     if x.is_none() {
         x.unwrap(); // will panic
@@ -52,9 +54,11 @@ fn main() {
     let mut x: Result<(), ()> = Ok(());
     if x.is_ok() {
         x.unwrap(); // unnecessary
+        x.expect("an error message"); // unnecessary
         x.unwrap_err(); // will panic
     } else {
         x.unwrap(); // will panic
+        x.expect("an error message"); // will panic
         x.unwrap_err(); // unnecessary
     }
     if x.is_err() {
diff --git a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr
index a4bc058fe20..82f26954380 100644
--- a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr
+++ b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr
@@ -1,8 +1,8 @@
-error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap` on `x` after checking its variant with `is_some`
   --> $DIR/simple_conditionals.rs:39:9
    |
 LL |     if x.is_some() {
-   |        ----------- the check is happening here
+   |     -------------- help: try: `if let Some(..) = x`
 LL |         x.unwrap(); // unnecessary
    |         ^^^^^^^^^^
    |
@@ -12,8 +12,17 @@ note: the lint level is defined here
 LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: called `expect` on `x` after checking its variant with `is_some`
+  --> $DIR/simple_conditionals.rs:40:9
+   |
+LL |     if x.is_some() {
+   |     -------------- help: try: `if let Some(..) = x`
+LL |         x.unwrap(); // unnecessary
+LL |         x.expect("an error message"); // unnecessary
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: this call to `unwrap()` will always panic
-  --> $DIR/simple_conditionals.rs:41:9
+  --> $DIR/simple_conditionals.rs:42:9
    |
 LL |     if x.is_some() {
    |        ----------- because of this check
@@ -27,28 +36,37 @@ note: the lint level is defined here
 LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: this call to `expect()` will always panic
+  --> $DIR/simple_conditionals.rs:43:9
+   |
+LL |     if x.is_some() {
+   |        ----------- because of this check
+...
+LL |         x.expect("an error message"); // will panic
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: this call to `unwrap()` will always panic
-  --> $DIR/simple_conditionals.rs:44:9
+  --> $DIR/simple_conditionals.rs:46:9
    |
 LL |     if x.is_none() {
    |        ----------- because of this check
 LL |         x.unwrap(); // will panic
    |         ^^^^^^^^^^
 
-error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
-  --> $DIR/simple_conditionals.rs:46:9
+error: called `unwrap` on `x` after checking its variant with `is_none`
+  --> $DIR/simple_conditionals.rs:48:9
    |
 LL |     if x.is_none() {
-   |        ----------- the check is happening here
+   |     -------------- help: try: `if let Some(..) = x`
 ...
 LL |         x.unwrap(); // unnecessary
    |         ^^^^^^^^^^
 
-error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
+error: called `unwrap` on `x` after checking its variant with `is_some`
   --> $DIR/simple_conditionals.rs:7:13
    |
 LL |         if $a.is_some() {
-   |            ------------ the check is happening here
+   |         --------------- help: try: `if let Some(..) = x`
 LL |             $a.unwrap(); // unnecessary
    |             ^^^^^^^^^^^
 ...
@@ -57,25 +75,34 @@ LL |     m!(x);
    |
    = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
-  --> $DIR/simple_conditionals.rs:54:9
+error: called `unwrap` on `x` after checking its variant with `is_ok`
+  --> $DIR/simple_conditionals.rs:56:9
    |
 LL |     if x.is_ok() {
-   |        --------- the check is happening here
+   |     ------------ help: try: `if let Ok(..) = x`
 LL |         x.unwrap(); // unnecessary
    |         ^^^^^^^^^^
 
+error: called `expect` on `x` after checking its variant with `is_ok`
+  --> $DIR/simple_conditionals.rs:57:9
+   |
+LL |     if x.is_ok() {
+   |     ------------ help: try: `if let Ok(..) = x`
+LL |         x.unwrap(); // unnecessary
+LL |         x.expect("an error message"); // unnecessary
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: this call to `unwrap_err()` will always panic
-  --> $DIR/simple_conditionals.rs:55:9
+  --> $DIR/simple_conditionals.rs:58:9
    |
 LL |     if x.is_ok() {
    |        --------- because of this check
-LL |         x.unwrap(); // unnecessary
+...
 LL |         x.unwrap_err(); // will panic
    |         ^^^^^^^^^^^^^^
 
 error: this call to `unwrap()` will always panic
-  --> $DIR/simple_conditionals.rs:57:9
+  --> $DIR/simple_conditionals.rs:60:9
    |
 LL |     if x.is_ok() {
    |        --------- because of this check
@@ -83,43 +110,52 @@ LL |     if x.is_ok() {
 LL |         x.unwrap(); // will panic
    |         ^^^^^^^^^^
 
-error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
-  --> $DIR/simple_conditionals.rs:58:9
+error: this call to `expect()` will always panic
+  --> $DIR/simple_conditionals.rs:61:9
+   |
+LL |     if x.is_ok() {
+   |        --------- because of this check
+...
+LL |         x.expect("an error message"); // will panic
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: called `unwrap_err` on `x` after checking its variant with `is_ok`
+  --> $DIR/simple_conditionals.rs:62:9
    |
 LL |     if x.is_ok() {
-   |        --------- the check is happening here
+   |     ------------ help: try: `if let Err(..) = x`
 ...
 LL |         x.unwrap_err(); // unnecessary
    |         ^^^^^^^^^^^^^^
 
 error: this call to `unwrap()` will always panic
-  --> $DIR/simple_conditionals.rs:61:9
+  --> $DIR/simple_conditionals.rs:65:9
    |
 LL |     if x.is_err() {
    |        ---------- because of this check
 LL |         x.unwrap(); // will panic
    |         ^^^^^^^^^^
 
-error: you checked before that `unwrap_err()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
-  --> $DIR/simple_conditionals.rs:62:9
+error: called `unwrap_err` on `x` after checking its variant with `is_err`
+  --> $DIR/simple_conditionals.rs:66:9
    |
 LL |     if x.is_err() {
-   |        ---------- the check is happening here
+   |     ------------- help: try: `if let Err(..) = x`
 LL |         x.unwrap(); // will panic
 LL |         x.unwrap_err(); // unnecessary
    |         ^^^^^^^^^^^^^^
 
-error: you checked before that `unwrap()` cannot fail, instead of checking and unwrapping, it's better to use `if let` or `match`
-  --> $DIR/simple_conditionals.rs:64:9
+error: called `unwrap` on `x` after checking its variant with `is_err`
+  --> $DIR/simple_conditionals.rs:68:9
    |
 LL |     if x.is_err() {
-   |        ---------- the check is happening here
+   |     ------------- help: try: `if let Ok(..) = x`
 ...
 LL |         x.unwrap(); // unnecessary
    |         ^^^^^^^^^^
 
 error: this call to `unwrap_err()` will always panic
-  --> $DIR/simple_conditionals.rs:65:9
+  --> $DIR/simple_conditionals.rs:69:9
    |
 LL |     if x.is_err() {
    |        ---------- because of this check
@@ -127,5 +163,5 @@ LL |     if x.is_err() {
 LL |         x.unwrap_err(); // will panic
    |         ^^^^^^^^^^^^^^
 
-error: aborting due to 13 previous errors
+error: aborting due to 17 previous errors
 
diff --git a/src/tools/clippy/tests/ui/default_trait_access.fixed b/src/tools/clippy/tests/ui/default_trait_access.fixed
index 4c80cabc723..f1f9c123dc8 100644
--- a/src/tools/clippy/tests/ui/default_trait_access.fixed
+++ b/src/tools/clippy/tests/ui/default_trait_access.fixed
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![allow(unused_imports)]
+#![allow(unused_imports,dead_code)]
 #![deny(clippy::default_trait_access)]
 
 use std::default;
diff --git a/src/tools/clippy/tests/ui/default_trait_access.rs b/src/tools/clippy/tests/ui/default_trait_access.rs
index a68b6455c04..7f3dfc7f013 100644
--- a/src/tools/clippy/tests/ui/default_trait_access.rs
+++ b/src/tools/clippy/tests/ui/default_trait_access.rs
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![allow(unused_imports)]
+#![allow(unused_imports,dead_code)]
 #![deny(clippy::default_trait_access)]
 
 use std::default;
diff --git a/src/tools/clippy/tests/ui/derivable_impls.rs b/src/tools/clippy/tests/ui/derivable_impls.rs
new file mode 100644
index 00000000000..336a743de72
--- /dev/null
+++ b/src/tools/clippy/tests/ui/derivable_impls.rs
@@ -0,0 +1,170 @@
+use std::collections::HashMap;
+
+struct FooDefault<'a> {
+    a: bool,
+    b: i32,
+    c: u64,
+    d: Vec<i32>,
+    e: FooND1,
+    f: FooND2,
+    g: HashMap<i32, i32>,
+    h: (i32, Vec<i32>),
+    i: [Vec<i32>; 3],
+    j: [i32; 5],
+    k: Option<i32>,
+    l: &'a [i32],
+}
+
+impl std::default::Default for FooDefault<'_> {
+    fn default() -> Self {
+        Self {
+            a: false,
+            b: 0,
+            c: 0u64,
+            d: vec![],
+            e: Default::default(),
+            f: FooND2::default(),
+            g: HashMap::new(),
+            h: (0, vec![]),
+            i: [vec![], vec![], vec![]],
+            j: [0; 5],
+            k: None,
+            l: &[],
+        }
+    }
+}
+
+struct TupleDefault(bool, i32, u64);
+
+impl std::default::Default for TupleDefault {
+    fn default() -> Self {
+        Self(false, 0, 0u64)
+    }
+}
+
+struct FooND1 {
+    a: bool,
+}
+
+impl std::default::Default for FooND1 {
+    fn default() -> Self {
+        Self { a: true }
+    }
+}
+
+struct FooND2 {
+    a: i32,
+}
+
+impl std::default::Default for FooND2 {
+    fn default() -> Self {
+        Self { a: 5 }
+    }
+}
+
+struct FooNDNew {
+    a: bool,
+}
+
+impl FooNDNew {
+    fn new() -> Self {
+        Self { a: true }
+    }
+}
+
+impl Default for FooNDNew {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+struct FooNDVec(Vec<i32>);
+
+impl Default for FooNDVec {
+    fn default() -> Self {
+        Self(vec![5, 12])
+    }
+}
+
+struct StrDefault<'a>(&'a str);
+
+impl Default for StrDefault<'_> {
+    fn default() -> Self {
+        Self("")
+    }
+}
+
+#[derive(Default)]
+struct AlreadyDerived(i32, bool);
+
+macro_rules! mac {
+    () => {
+        0
+    };
+    ($e:expr) => {
+        struct X(u32);
+        impl Default for X {
+            fn default() -> Self {
+                Self($e)
+            }
+        }
+    };
+}
+
+mac!(0);
+
+struct Y(u32);
+impl Default for Y {
+    fn default() -> Self {
+        Self(mac!())
+    }
+}
+
+struct RustIssue26925<T> {
+    a: Option<T>,
+}
+
+// We should watch out for cases where a manual impl is needed because a
+// derive adds different type bounds (https://github.com/rust-lang/rust/issues/26925).
+// For example, a struct with Option<T> does not require T: Default, but a derive adds
+// that type bound anyways. So until #26925 get fixed we should disable lint
+// for the following case
+impl<T> Default for RustIssue26925<T> {
+    fn default() -> Self {
+        Self { a: None }
+    }
+}
+
+struct SpecializedImpl<A, B> {
+    a: A,
+    b: B,
+}
+
+impl<T: Default> Default for SpecializedImpl<T, T> {
+    fn default() -> Self {
+        Self {
+            a: T::default(),
+            b: T::default(),
+        }
+    }
+}
+
+struct WithoutSelfCurly {
+    a: bool,
+}
+
+impl Default for WithoutSelfCurly {
+    fn default() -> Self {
+        WithoutSelfCurly { a: false }
+    }
+}
+
+struct WithoutSelfParan(bool);
+
+impl Default for WithoutSelfParan {
+    fn default() -> Self {
+        WithoutSelfParan(false)
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/derivable_impls.stderr b/src/tools/clippy/tests/ui/derivable_impls.stderr
new file mode 100644
index 00000000000..4ed64fade02
--- /dev/null
+++ b/src/tools/clippy/tests/ui/derivable_impls.stderr
@@ -0,0 +1,77 @@
+error: this `impl` can be derived
+  --> $DIR/derivable_impls.rs:18:1
+   |
+LL | / impl std::default::Default for FooDefault<'_> {
+LL | |     fn default() -> Self {
+LL | |         Self {
+LL | |             a: false,
+...  |
+LL | |     }
+LL | | }
+   | |_^
+   |
+   = note: `-D clippy::derivable-impls` implied by `-D warnings`
+   = help: try annotating `FooDefault` with `#[derive(Default)]`
+
+error: this `impl` can be derived
+  --> $DIR/derivable_impls.rs:39:1
+   |
+LL | / impl std::default::Default for TupleDefault {
+LL | |     fn default() -> Self {
+LL | |         Self(false, 0, 0u64)
+LL | |     }
+LL | | }
+   | |_^
+   |
+   = help: try annotating `TupleDefault` with `#[derive(Default)]`
+
+error: this `impl` can be derived
+  --> $DIR/derivable_impls.rs:91:1
+   |
+LL | / impl Default for StrDefault<'_> {
+LL | |     fn default() -> Self {
+LL | |         Self("")
+LL | |     }
+LL | | }
+   | |_^
+   |
+   = help: try annotating `StrDefault` with `#[derive(Default)]`
+
+error: this `impl` can be derived
+  --> $DIR/derivable_impls.rs:117:1
+   |
+LL | / impl Default for Y {
+LL | |     fn default() -> Self {
+LL | |         Self(mac!())
+LL | |     }
+LL | | }
+   | |_^
+   |
+   = help: try annotating `Y` with `#[derive(Default)]`
+
+error: this `impl` can be derived
+  --> $DIR/derivable_impls.rs:156:1
+   |
+LL | / impl Default for WithoutSelfCurly {
+LL | |     fn default() -> Self {
+LL | |         WithoutSelfCurly { a: false }
+LL | |     }
+LL | | }
+   | |_^
+   |
+   = help: try annotating `WithoutSelfCurly` with `#[derive(Default)]`
+
+error: this `impl` can be derived
+  --> $DIR/derivable_impls.rs:164:1
+   |
+LL | / impl Default for WithoutSelfParan {
+LL | |     fn default() -> Self {
+LL | |         WithoutSelfParan(false)
+LL | |     }
+LL | | }
+   | |_^
+   |
+   = help: try annotating `WithoutSelfParan` with `#[derive(Default)]`
+
+error: aborting due to 6 previous errors
+
diff --git a/src/tools/clippy/tests/ui/entry.fixed b/src/tools/clippy/tests/ui/entry.fixed
index cfad3090ba3..8a36ec833d7 100644
--- a/src/tools/clippy/tests/ui/entry.fixed
+++ b/src/tools/clippy/tests/ui/entry.fixed
@@ -4,7 +4,7 @@
 #![warn(clippy::map_entry)]
 #![feature(asm)]
 
-use std::collections::{BTreeMap, HashMap};
+use std::collections::HashMap;
 use std::hash::Hash;
 
 macro_rules! m {
@@ -142,14 +142,13 @@ fn hash_map<K: Eq + Hash + Copy, V: Copy>(m: &mut HashMap<K, V>, m2: &mut HashMa
     if !m.contains_key(&k) {
         insert!(m, k, v);
     }
-}
 
-fn btree_map<K: Eq + Ord + Copy, V: Copy>(m: &mut BTreeMap<K, V>, k: K, v: V, v2: V) {
-    // insert then do something, use if let
-    if let std::collections::btree_map::Entry::Vacant(e) = m.entry(k) {
-        e.insert(v);
-        foo();
-    }
+    // or_insert_with. Partial move of a local declared in the closure is ok.
+    m.entry(k).or_insert_with(|| {
+        let x = (String::new(), String::new());
+        let _ = x.0;
+        v
+    });
 }
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/entry.rs b/src/tools/clippy/tests/ui/entry.rs
index fa9280b58de..d972a201ad7 100644
--- a/src/tools/clippy/tests/ui/entry.rs
+++ b/src/tools/clippy/tests/ui/entry.rs
@@ -4,7 +4,7 @@
 #![warn(clippy::map_entry)]
 #![feature(asm)]
 
-use std::collections::{BTreeMap, HashMap};
+use std::collections::HashMap;
 use std::hash::Hash;
 
 macro_rules! m {
@@ -146,13 +146,12 @@ fn hash_map<K: Eq + Hash + Copy, V: Copy>(m: &mut HashMap<K, V>, m2: &mut HashMa
     if !m.contains_key(&k) {
         insert!(m, k, v);
     }
-}
 
-fn btree_map<K: Eq + Ord + Copy, V: Copy>(m: &mut BTreeMap<K, V>, k: K, v: V, v2: V) {
-    // insert then do something, use if let
+    // or_insert_with. Partial move of a local declared in the closure is ok.
     if !m.contains_key(&k) {
+        let x = (String::new(), String::new());
+        let _ = x.0;
         m.insert(k, v);
-        foo();
     }
 }
 
diff --git a/src/tools/clippy/tests/ui/entry.stderr b/src/tools/clippy/tests/ui/entry.stderr
index 8f2e383d675..1076500498d 100644
--- a/src/tools/clippy/tests/ui/entry.stderr
+++ b/src/tools/clippy/tests/ui/entry.stderr
@@ -165,21 +165,23 @@ LL | |         m.insert(m!(k), m!(v));
 LL | |     }
    | |_____^ help: try this: `m.entry(m!(k)).or_insert_with(|| m!(v));`
 
-error: usage of `contains_key` followed by `insert` on a `BTreeMap`
-  --> $DIR/entry.rs:153:5
+error: usage of `contains_key` followed by `insert` on a `HashMap`
+  --> $DIR/entry.rs:151:5
    |
 LL | /     if !m.contains_key(&k) {
+LL | |         let x = (String::new(), String::new());
+LL | |         let _ = x.0;
 LL | |         m.insert(k, v);
-LL | |         foo();
 LL | |     }
    | |_____^
    |
 help: try this
    |
-LL ~     if let std::collections::btree_map::Entry::Vacant(e) = m.entry(k) {
-LL +         e.insert(v);
-LL +         foo();
-LL +     }
+LL ~     m.entry(k).or_insert_with(|| {
+LL +         let x = (String::new(), String::new());
+LL +         let _ = x.0;
+LL +         v
+LL +     });
    |
 
 error: aborting due to 10 previous errors
diff --git a/src/tools/clippy/tests/ui/entry_btree.fixed b/src/tools/clippy/tests/ui/entry_btree.fixed
new file mode 100644
index 00000000000..94979104556
--- /dev/null
+++ b/src/tools/clippy/tests/ui/entry_btree.fixed
@@ -0,0 +1,18 @@
+// run-rustfix
+
+#![warn(clippy::map_entry)]
+#![allow(dead_code)]
+
+use std::collections::BTreeMap;
+
+fn foo() {}
+
+fn btree_map<K: Eq + Ord + Copy, V: Copy>(m: &mut BTreeMap<K, V>, k: K, v: V) {
+    // insert then do something, use if let
+    if let std::collections::btree_map::Entry::Vacant(e) = m.entry(k) {
+        e.insert(v);
+        foo();
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/entry_btree.rs b/src/tools/clippy/tests/ui/entry_btree.rs
new file mode 100644
index 00000000000..080c1d959e8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/entry_btree.rs
@@ -0,0 +1,18 @@
+// run-rustfix
+
+#![warn(clippy::map_entry)]
+#![allow(dead_code)]
+
+use std::collections::BTreeMap;
+
+fn foo() {}
+
+fn btree_map<K: Eq + Ord + Copy, V: Copy>(m: &mut BTreeMap<K, V>, k: K, v: V) {
+    // insert then do something, use if let
+    if !m.contains_key(&k) {
+        m.insert(k, v);
+        foo();
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/entry_btree.stderr b/src/tools/clippy/tests/ui/entry_btree.stderr
new file mode 100644
index 00000000000..5c6fcdf1a28
--- /dev/null
+++ b/src/tools/clippy/tests/ui/entry_btree.stderr
@@ -0,0 +1,20 @@
+error: usage of `contains_key` followed by `insert` on a `BTreeMap`
+  --> $DIR/entry_btree.rs:12:5
+   |
+LL | /     if !m.contains_key(&k) {
+LL | |         m.insert(k, v);
+LL | |         foo();
+LL | |     }
+   | |_____^
+   |
+   = note: `-D clippy::map-entry` implied by `-D warnings`
+help: try this
+   |
+LL ~     if let std::collections::btree_map::Entry::Vacant(e) = m.entry(k) {
+LL +         e.insert(v);
+LL +         foo();
+LL +     }
+   |
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/linkedlist.rs b/src/tools/clippy/tests/ui/linkedlist.rs
index 2c3b25cd45e..690ea810a62 100644
--- a/src/tools/clippy/tests/ui/linkedlist.rs
+++ b/src/tools/clippy/tests/ui/linkedlist.rs
@@ -1,6 +1,6 @@
 #![feature(associated_type_defaults)]
 #![warn(clippy::linkedlist)]
-#![allow(dead_code, clippy::needless_pass_by_value)]
+#![allow(unused, dead_code, clippy::needless_pass_by_value)]
 
 extern crate alloc;
 use alloc::collections::linked_list::LinkedList;
@@ -20,24 +20,29 @@ impl Foo for LinkedList<u8> {
     const BAR: Option<LinkedList<u8>> = None;
 }
 
-struct Bar;
+pub struct Bar {
+    priv_linked_list_field: LinkedList<u8>,
+    pub pub_linked_list_field: LinkedList<u8>,
+}
 impl Bar {
     fn foo(_: LinkedList<u8>) {}
 }
 
-pub fn test(my_favourite_linked_list: LinkedList<u8>) {
-    println!("{:?}", my_favourite_linked_list)
-}
-
-pub fn test_ret() -> Option<LinkedList<u8>> {
-    unimplemented!();
+// All of these test should be trigger the lint because they are not
+// part of the public api
+fn test(my_favorite_linked_list: LinkedList<u8>) {}
+fn test_ret() -> Option<LinkedList<u8>> {
+    None
 }
-
-pub fn test_local_not_linted() {
+fn test_local_not_linted() {
     let _: LinkedList<u8>;
 }
 
-fn main() {
-    test(LinkedList::new());
-    test_local_not_linted();
+// All of these test should be allowed because they are part of the
+// public api and `avoid_breaking_exported_api` is `false` by default.
+pub fn pub_test(the_most_awesome_linked_list: LinkedList<u8>) {}
+pub fn pub_test_ret() -> Option<LinkedList<u8>> {
+    None
 }
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/linkedlist.stderr b/src/tools/clippy/tests/ui/linkedlist.stderr
index 38ae71714d6..51327df1321 100644
--- a/src/tools/clippy/tests/ui/linkedlist.stderr
+++ b/src/tools/clippy/tests/ui/linkedlist.stderr
@@ -40,7 +40,15 @@ LL |     const BAR: Option<LinkedList<u8>>;
    = help: a `VecDeque` might work
 
 error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure?
-  --> $DIR/linkedlist.rs:25:15
+  --> $DIR/linkedlist.rs:24:29
+   |
+LL |     priv_linked_list_field: LinkedList<u8>,
+   |                             ^^^^^^^^^^^^^^
+   |
+   = help: a `VecDeque` might work
+
+error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure?
+  --> $DIR/linkedlist.rs:28:15
    |
 LL |     fn foo(_: LinkedList<u8>) {}
    |               ^^^^^^^^^^^^^^
@@ -48,20 +56,20 @@ LL |     fn foo(_: LinkedList<u8>) {}
    = help: a `VecDeque` might work
 
 error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure?
-  --> $DIR/linkedlist.rs:28:39
+  --> $DIR/linkedlist.rs:33:34
    |
-LL | pub fn test(my_favourite_linked_list: LinkedList<u8>) {
-   |                                       ^^^^^^^^^^^^^^
+LL | fn test(my_favorite_linked_list: LinkedList<u8>) {}
+   |                                  ^^^^^^^^^^^^^^
    |
    = help: a `VecDeque` might work
 
 error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure?
-  --> $DIR/linkedlist.rs:32:29
+  --> $DIR/linkedlist.rs:34:25
    |
-LL | pub fn test_ret() -> Option<LinkedList<u8>> {
-   |                             ^^^^^^^^^^^^^^
+LL | fn test_ret() -> Option<LinkedList<u8>> {
+   |                         ^^^^^^^^^^^^^^
    |
    = help: a `VecDeque` might work
 
-error: aborting due to 8 previous errors
+error: aborting due to 9 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_flatten.rs b/src/tools/clippy/tests/ui/manual_flatten.rs
index b5bd35a6878..7db6b730963 100644
--- a/src/tools/clippy/tests/ui/manual_flatten.rs
+++ b/src/tools/clippy/tests/ui/manual_flatten.rs
@@ -91,6 +91,19 @@ fn main() {
         }
     }
 
+    struct Test {
+        a: usize,
+    }
+
+    let mut vec_of_struct = [Some(Test { a: 1 }), None];
+
+    // Usage of `if let` expression should not trigger lint
+    for n in vec_of_struct.iter_mut() {
+        if let Some(z) = n {
+            *n = None;
+        }
+    }
+
     // Using manual flatten should not trigger the lint
     for n in vec![Some(1), Some(2), Some(3)].iter().flatten() {
         println!("{}", n);
diff --git a/src/tools/clippy/tests/ui/manual_map_option_2.fixed b/src/tools/clippy/tests/ui/manual_map_option_2.fixed
new file mode 100644
index 00000000000..8cc12149403
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_map_option_2.fixed
@@ -0,0 +1,50 @@
+// run-rustfix
+
+#![warn(clippy::manual_map)]
+#![allow(clippy::toplevel_ref_arg)]
+
+fn main() {
+    // Lint. `y` is declared within the arm, so it isn't captured by the map closure
+    let _ = Some(0).map(|x| {
+            let y = (String::new(), String::new());
+            (x, y.0)
+        });
+
+    // Don't lint. `s` is borrowed until partway through the arm, but needs to be captured by the map
+    // closure
+    let s = Some(String::new());
+    let _ = match &s {
+        Some(x) => Some((x.clone(), s)),
+        None => None,
+    };
+
+    // Don't lint. `s` is borrowed until partway through the arm, but needs to be captured by the map
+    // closure
+    let s = Some(String::new());
+    let _ = match &s {
+        Some(x) => Some({
+            let clone = x.clone();
+            let s = || s;
+            (clone, s())
+        }),
+        None => None,
+    };
+
+    // Don't lint. `s` is borrowed until partway through the arm, but needs to be captured as a mutable
+    // reference by the map closure
+    let mut s = Some(String::new());
+    let _ = match &s {
+        Some(x) => Some({
+            let clone = x.clone();
+            let ref mut s = s;
+            (clone, s)
+        }),
+        None => None,
+    };
+
+    // Lint. `s` is captured by reference, so no lifetime issues.
+    let s = Some(String::new());
+    let _ = s.as_ref().map(|x| {
+            if let Some(ref s) = s { (x.clone(), s) } else { panic!() }
+        });
+}
diff --git a/src/tools/clippy/tests/ui/manual_map_option_2.rs b/src/tools/clippy/tests/ui/manual_map_option_2.rs
new file mode 100644
index 00000000000..0862b201ead
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_map_option_2.rs
@@ -0,0 +1,56 @@
+// run-rustfix
+
+#![warn(clippy::manual_map)]
+#![allow(clippy::toplevel_ref_arg)]
+
+fn main() {
+    // Lint. `y` is declared within the arm, so it isn't captured by the map closure
+    let _ = match Some(0) {
+        Some(x) => Some({
+            let y = (String::new(), String::new());
+            (x, y.0)
+        }),
+        None => None,
+    };
+
+    // Don't lint. `s` is borrowed until partway through the arm, but needs to be captured by the map
+    // closure
+    let s = Some(String::new());
+    let _ = match &s {
+        Some(x) => Some((x.clone(), s)),
+        None => None,
+    };
+
+    // Don't lint. `s` is borrowed until partway through the arm, but needs to be captured by the map
+    // closure
+    let s = Some(String::new());
+    let _ = match &s {
+        Some(x) => Some({
+            let clone = x.clone();
+            let s = || s;
+            (clone, s())
+        }),
+        None => None,
+    };
+
+    // Don't lint. `s` is borrowed until partway through the arm, but needs to be captured as a mutable
+    // reference by the map closure
+    let mut s = Some(String::new());
+    let _ = match &s {
+        Some(x) => Some({
+            let clone = x.clone();
+            let ref mut s = s;
+            (clone, s)
+        }),
+        None => None,
+    };
+
+    // Lint. `s` is captured by reference, so no lifetime issues.
+    let s = Some(String::new());
+    let _ = match &s {
+        Some(x) => Some({
+            if let Some(ref s) = s { (x.clone(), s) } else { panic!() }
+        }),
+        None => None,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/manual_map_option_2.stderr b/src/tools/clippy/tests/ui/manual_map_option_2.stderr
new file mode 100644
index 00000000000..711ff6c4a4b
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_map_option_2.stderr
@@ -0,0 +1,43 @@
+error: manual implementation of `Option::map`
+  --> $DIR/manual_map_option_2.rs:8:13
+   |
+LL |       let _ = match Some(0) {
+   |  _____________^
+LL | |         Some(x) => Some({
+LL | |             let y = (String::new(), String::new());
+LL | |             (x, y.0)
+LL | |         }),
+LL | |         None => None,
+LL | |     };
+   | |_____^
+   |
+   = note: `-D clippy::manual-map` implied by `-D warnings`
+help: try this
+   |
+LL ~     let _ = Some(0).map(|x| {
+LL +             let y = (String::new(), String::new());
+LL +             (x, y.0)
+LL ~         });
+   |
+
+error: manual implementation of `Option::map`
+  --> $DIR/manual_map_option_2.rs:50:13
+   |
+LL |       let _ = match &s {
+   |  _____________^
+LL | |         Some(x) => Some({
+LL | |             if let Some(ref s) = s { (x.clone(), s) } else { panic!() }
+LL | |         }),
+LL | |         None => None,
+LL | |     };
+   | |_____^
+   |
+help: try this
+   |
+LL ~     let _ = s.as_ref().map(|x| {
+LL +             if let Some(ref s) = s { (x.clone(), s) } else { panic!() }
+LL ~         });
+   |
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_split_once.fixed b/src/tools/clippy/tests/ui/manual_split_once.fixed
new file mode 100644
index 00000000000..3a0332939d4
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_split_once.fixed
@@ -0,0 +1,50 @@
+// run-rustfix
+
+#![feature(custom_inner_attributes)]
+#![warn(clippy::manual_split_once)]
+#![allow(clippy::iter_skip_next, clippy::iter_nth_zero)]
+
+extern crate itertools;
+
+#[allow(unused_imports)]
+use itertools::Itertools;
+
+fn main() {
+    let _ = Some("key=value".split_once('=').map_or("key=value", |x| x.0));
+    let _ = "key=value".splitn(2, '=').nth(2);
+    let _ = "key=value".split_once('=').map_or("key=value", |x| x.0);
+    let _ = "key=value".split_once('=').map_or("key=value", |x| x.0);
+    let _ = "key=value".split_once('=').unwrap().1;
+    let _ = "key=value".split_once('=').unwrap().1;
+    let (_, _) = "key=value".split_once('=').unwrap();
+
+    let s = String::from("key=value");
+    let _ = s.split_once('=').map_or(&*s, |x| x.0);
+
+    let s = Box::<str>::from("key=value");
+    let _ = s.split_once('=').map_or(&*s, |x| x.0);
+
+    let s = &"key=value";
+    let _ = s.split_once('=').map_or(*s, |x| x.0);
+
+    fn _f(s: &str) -> Option<&str> {
+        let _ = s.split_once("key=value").map_or(s, |x| x.0);
+        let _ = s.split_once("key=value")?.1;
+        let _ = s.split_once("key=value")?.1;
+        None
+    }
+
+    // Don't lint, slices don't have `split_once`
+    let _ = [0, 1, 2].splitn(2, |&x| x == 1).nth(1).unwrap();
+}
+
+fn _msrv_1_51() {
+    #![clippy::msrv = "1.51"]
+    // `str::split_once` was stabilized in 1.16. Do not lint this
+    let _ = "key=value".splitn(2, '=').nth(1).unwrap();
+}
+
+fn _msrv_1_52() {
+    #![clippy::msrv = "1.52"]
+    let _ = "key=value".split_once('=').unwrap().1;
+}
diff --git a/src/tools/clippy/tests/ui/manual_split_once.rs b/src/tools/clippy/tests/ui/manual_split_once.rs
new file mode 100644
index 00000000000..e6093b63fe8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_split_once.rs
@@ -0,0 +1,50 @@
+// run-rustfix
+
+#![feature(custom_inner_attributes)]
+#![warn(clippy::manual_split_once)]
+#![allow(clippy::iter_skip_next, clippy::iter_nth_zero)]
+
+extern crate itertools;
+
+#[allow(unused_imports)]
+use itertools::Itertools;
+
+fn main() {
+    let _ = "key=value".splitn(2, '=').next();
+    let _ = "key=value".splitn(2, '=').nth(2);
+    let _ = "key=value".splitn(2, '=').next().unwrap();
+    let _ = "key=value".splitn(2, '=').nth(0).unwrap();
+    let _ = "key=value".splitn(2, '=').nth(1).unwrap();
+    let _ = "key=value".splitn(2, '=').skip(1).next().unwrap();
+    let (_, _) = "key=value".splitn(2, '=').next_tuple().unwrap();
+
+    let s = String::from("key=value");
+    let _ = s.splitn(2, '=').next().unwrap();
+
+    let s = Box::<str>::from("key=value");
+    let _ = s.splitn(2, '=').nth(0).unwrap();
+
+    let s = &"key=value";
+    let _ = s.splitn(2, '=').skip(0).next().unwrap();
+
+    fn _f(s: &str) -> Option<&str> {
+        let _ = s.splitn(2, "key=value").next()?;
+        let _ = s.splitn(2, "key=value").nth(1)?;
+        let _ = s.splitn(2, "key=value").skip(1).next()?;
+        None
+    }
+
+    // Don't lint, slices don't have `split_once`
+    let _ = [0, 1, 2].splitn(2, |&x| x == 1).nth(1).unwrap();
+}
+
+fn _msrv_1_51() {
+    #![clippy::msrv = "1.51"]
+    // `str::split_once` was stabilized in 1.16. Do not lint this
+    let _ = "key=value".splitn(2, '=').nth(1).unwrap();
+}
+
+fn _msrv_1_52() {
+    #![clippy::msrv = "1.52"]
+    let _ = "key=value".splitn(2, '=').nth(1).unwrap();
+}
diff --git a/src/tools/clippy/tests/ui/manual_split_once.stderr b/src/tools/clippy/tests/ui/manual_split_once.stderr
new file mode 100644
index 00000000000..4f15196b469
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_split_once.stderr
@@ -0,0 +1,82 @@
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:13:13
+   |
+LL |     let _ = "key=value".splitn(2, '=').next();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Some("key=value".split_once('=').map_or("key=value", |x| x.0))`
+   |
+   = note: `-D clippy::manual-split-once` implied by `-D warnings`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:15:13
+   |
+LL |     let _ = "key=value".splitn(2, '=').next().unwrap();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').map_or("key=value", |x| x.0)`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:16:13
+   |
+LL |     let _ = "key=value".splitn(2, '=').nth(0).unwrap();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').map_or("key=value", |x| x.0)`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:17:13
+   |
+LL |     let _ = "key=value".splitn(2, '=').nth(1).unwrap();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').unwrap().1`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:18:13
+   |
+LL |     let _ = "key=value".splitn(2, '=').skip(1).next().unwrap();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').unwrap().1`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:19:18
+   |
+LL |     let (_, _) = "key=value".splitn(2, '=').next_tuple().unwrap();
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=')`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:22:13
+   |
+LL |     let _ = s.splitn(2, '=').next().unwrap();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=').map_or(&*s, |x| x.0)`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:25:13
+   |
+LL |     let _ = s.splitn(2, '=').nth(0).unwrap();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=').map_or(&*s, |x| x.0)`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:28:13
+   |
+LL |     let _ = s.splitn(2, '=').skip(0).next().unwrap();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once('=').map_or(*s, |x| x.0)`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:31:17
+   |
+LL |         let _ = s.splitn(2, "key=value").next()?;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once("key=value").map_or(s, |x| x.0)`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:32:17
+   |
+LL |         let _ = s.splitn(2, "key=value").nth(1)?;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once("key=value")?.1`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:33:17
+   |
+LL |         let _ = s.splitn(2, "key=value").skip(1).next()?;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.split_once("key=value")?.1`
+
+error: manual implementation of `split_once`
+  --> $DIR/manual_split_once.rs:49:13
+   |
+LL |     let _ = "key=value".splitn(2, '=').nth(1).unwrap();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `"key=value".split_once('=').unwrap().1`
+
+error: aborting due to 13 previous errors
+
diff --git a/src/tools/clippy/tests/ui/mem_replace.fixed b/src/tools/clippy/tests/ui/mem_replace.fixed
index 3b6224254a0..b609ba65946 100644
--- a/src/tools/clippy/tests/ui/mem_replace.fixed
+++ b/src/tools/clippy/tests/ui/mem_replace.fixed
@@ -51,9 +51,29 @@ fn replace_with_default() {
 
     let mut binary_heap: BinaryHeap<i32> = BinaryHeap::new();
     let _ = std::mem::take(&mut binary_heap);
+
+    let mut tuple = (vec![1, 2], BinaryHeap::<i32>::new());
+    let _ = std::mem::take(&mut tuple);
+
+    let mut refstr = "hello";
+    let _ = std::mem::take(&mut refstr);
+
+    let mut slice: &[i32] = &[1, 2, 3];
+    let _ = std::mem::take(&mut slice);
+}
+
+// lint is disabled for primitives because in this case `take`
+// has no clear benefit over `replace` and sometimes is harder to read
+fn dont_lint_primitive() {
+    let mut pbool = true;
+    let _ = std::mem::replace(&mut pbool, false);
+
+    let mut pint = 5;
+    let _ = std::mem::replace(&mut pint, 0);
 }
 
 fn main() {
     replace_option_with_none();
     replace_with_default();
+    dont_lint_primitive();
 }
diff --git a/src/tools/clippy/tests/ui/mem_replace.rs b/src/tools/clippy/tests/ui/mem_replace.rs
index 0a36db9e921..93f6dcdec83 100644
--- a/src/tools/clippy/tests/ui/mem_replace.rs
+++ b/src/tools/clippy/tests/ui/mem_replace.rs
@@ -51,9 +51,29 @@ fn replace_with_default() {
 
     let mut binary_heap: BinaryHeap<i32> = BinaryHeap::new();
     let _ = std::mem::replace(&mut binary_heap, BinaryHeap::new());
+
+    let mut tuple = (vec![1, 2], BinaryHeap::<i32>::new());
+    let _ = std::mem::replace(&mut tuple, (vec![], BinaryHeap::new()));
+
+    let mut refstr = "hello";
+    let _ = std::mem::replace(&mut refstr, "");
+
+    let mut slice: &[i32] = &[1, 2, 3];
+    let _ = std::mem::replace(&mut slice, &[]);
+}
+
+// lint is disabled for primitives because in this case `take`
+// has no clear benefit over `replace` and sometimes is harder to read
+fn dont_lint_primitive() {
+    let mut pbool = true;
+    let _ = std::mem::replace(&mut pbool, false);
+
+    let mut pint = 5;
+    let _ = std::mem::replace(&mut pint, 0);
 }
 
 fn main() {
     replace_option_with_none();
     replace_with_default();
+    dont_lint_primitive();
 }
diff --git a/src/tools/clippy/tests/ui/mem_replace.stderr b/src/tools/clippy/tests/ui/mem_replace.stderr
index f8aa1538bff..90dc6c95f85 100644
--- a/src/tools/clippy/tests/ui/mem_replace.stderr
+++ b/src/tools/clippy/tests/ui/mem_replace.stderr
@@ -98,5 +98,23 @@ error: replacing a value of type `T` with `T::default()` is better expressed usi
 LL |     let _ = std::mem::replace(&mut binary_heap, BinaryHeap::new());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut binary_heap)`
 
-error: aborting due to 16 previous errors
+error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
+  --> $DIR/mem_replace.rs:56:13
+   |
+LL |     let _ = std::mem::replace(&mut tuple, (vec![], BinaryHeap::new()));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut tuple)`
+
+error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
+  --> $DIR/mem_replace.rs:59:13
+   |
+LL |     let _ = std::mem::replace(&mut refstr, "");
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut refstr)`
+
+error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
+  --> $DIR/mem_replace.rs:62:13
+   |
+LL |     let _ = std::mem::replace(&mut slice, &[]);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut slice)`
+
+error: aborting due to 19 previous errors
 
diff --git a/src/tools/clippy/tests/ui/methods.rs b/src/tools/clippy/tests/ui/methods.rs
index 513d930e056..c441b35b992 100644
--- a/src/tools/clippy/tests/ui/methods.rs
+++ b/src/tools/clippy/tests/ui/methods.rs
@@ -32,7 +32,7 @@ use std::ops::Mul;
 use std::rc::{self, Rc};
 use std::sync::{self, Arc};
 
-use option_helpers::IteratorFalsePositives;
+use option_helpers::{IteratorFalsePositives, IteratorMethodFalsePositives};
 
 struct Lt<'a> {
     foo: &'a u32,
@@ -131,6 +131,9 @@ fn filter_next() {
     // Check that we don't lint if the caller is not an `Iterator`.
     let foo = IteratorFalsePositives { foo: 0 };
     let _ = foo.filter().next();
+
+    let foo = IteratorMethodFalsePositives {};
+    let _ = foo.filter(42).next();
 }
 
 fn main() {
diff --git a/src/tools/clippy/tests/ui/min_rust_version_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_attr.rs
index 7f9f7ddc535..8d9fc5a864d 100644
--- a/src/tools/clippy/tests/ui/min_rust_version_attr.rs
+++ b/src/tools/clippy/tests/ui/min_rust_version_attr.rs
@@ -4,6 +4,11 @@
 
 use std::ops::{Deref, RangeFrom};
 
+fn approx_const() {
+    let log2_10 = 3.321928094887362;
+    let log10_2 = 0.301029995663981;
+}
+
 fn cloned_instead_of_copied() {
     let _ = [1].iter().cloned();
 }
diff --git a/src/tools/clippy/tests/ui/min_rust_version_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_attr.stderr
index a2e4e86ed6b..360dcfb230c 100644
--- a/src/tools/clippy/tests/ui/min_rust_version_attr.stderr
+++ b/src/tools/clippy/tests/ui/min_rust_version_attr.stderr
@@ -1,12 +1,12 @@
 error: stripping a prefix manually
-  --> $DIR/min_rust_version_attr.rs:160:24
+  --> $DIR/min_rust_version_attr.rs:165:24
    |
 LL |             assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
    |                        ^^^^^^^^^^^^^^^^^^^^
    |
    = note: `-D clippy::manual-strip` implied by `-D warnings`
 note: the prefix was tested here
-  --> $DIR/min_rust_version_attr.rs:159:9
+  --> $DIR/min_rust_version_attr.rs:164:9
    |
 LL |         if s.starts_with("hello, ") {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -17,13 +17,13 @@ LL ~             assert_eq!(<stripped>.to_uppercase(), "WORLD!");
    |
 
 error: stripping a prefix manually
-  --> $DIR/min_rust_version_attr.rs:172:24
+  --> $DIR/min_rust_version_attr.rs:177:24
    |
 LL |             assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
    |                        ^^^^^^^^^^^^^^^^^^^^
    |
 note: the prefix was tested here
-  --> $DIR/min_rust_version_attr.rs:171:9
+  --> $DIR/min_rust_version_attr.rs:176:9
    |
 LL |         if s.starts_with("hello, ") {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/missing-doc-crate.stderr b/src/tools/clippy/tests/ui/missing-doc-crate.stderr
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/src/tools/clippy/tests/ui/missing-doc-crate.stderr
+++ /dev/null
diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.stderr b/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.stderr
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.stderr
+++ /dev/null
diff --git a/src/tools/clippy/tests/ui/mut_range_bound.rs b/src/tools/clippy/tests/ui/mut_range_bound.rs
index 1348dd2a3d8..e1ae1ef9282 100644
--- a/src/tools/clippy/tests/ui/mut_range_bound.rs
+++ b/src/tools/clippy/tests/ui/mut_range_bound.rs
@@ -1,14 +1,6 @@
 #![allow(unused)]
 
-fn main() {
-    mut_range_bound_upper();
-    mut_range_bound_lower();
-    mut_range_bound_both();
-    mut_range_bound_no_mutation();
-    immut_range_bound();
-    mut_borrow_range_bound();
-    immut_borrow_range_bound();
-}
+fn main() {}
 
 fn mut_range_bound_upper() {
     let mut m = 4;
@@ -61,3 +53,32 @@ fn immut_range_bound() {
         continue;
     } // no warning
 }
+
+fn mut_range_bound_break() {
+    let mut m = 4;
+    for i in 0..m {
+        if m == 4 {
+            m = 5; // no warning because of immediate break
+            break;
+        }
+    }
+}
+
+fn mut_range_bound_no_immediate_break() {
+    let mut m = 4;
+    for i in 0..m {
+        m = 2; // warning because it is not immediately followed by break
+        if m == 4 {
+            break;
+        }
+    }
+
+    let mut n = 3;
+    for i in n..10 {
+        if n == 4 {
+            n = 1; // FIXME: warning because is is not immediately followed by break
+            let _ = 2;
+            break;
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/mut_range_bound.stderr b/src/tools/clippy/tests/ui/mut_range_bound.stderr
index 0eeb76e0ec5..4b5a3fc1e41 100644
--- a/src/tools/clippy/tests/ui/mut_range_bound.stderr
+++ b/src/tools/clippy/tests/ui/mut_range_bound.stderr
@@ -1,34 +1,59 @@
-error: attempt to mutate range bound within loop; note that the range of the loop is unchanged
-  --> $DIR/mut_range_bound.rs:16:9
+error: attempt to mutate range bound within loop
+  --> $DIR/mut_range_bound.rs:8:9
    |
 LL |         m = 5;
    |         ^
    |
    = note: `-D clippy::mut-range-bound` implied by `-D warnings`
+   = note: the range of the loop is unchanged
 
-error: attempt to mutate range bound within loop; note that the range of the loop is unchanged
-  --> $DIR/mut_range_bound.rs:23:9
+error: attempt to mutate range bound within loop
+  --> $DIR/mut_range_bound.rs:15:9
    |
 LL |         m *= 2;
    |         ^
+   |
+   = note: the range of the loop is unchanged
 
-error: attempt to mutate range bound within loop; note that the range of the loop is unchanged
-  --> $DIR/mut_range_bound.rs:31:9
+error: attempt to mutate range bound within loop
+  --> $DIR/mut_range_bound.rs:23:9
    |
 LL |         m = 5;
    |         ^
+   |
+   = note: the range of the loop is unchanged
 
-error: attempt to mutate range bound within loop; note that the range of the loop is unchanged
-  --> $DIR/mut_range_bound.rs:32:9
+error: attempt to mutate range bound within loop
+  --> $DIR/mut_range_bound.rs:24:9
    |
 LL |         n = 7;
    |         ^
+   |
+   = note: the range of the loop is unchanged
 
-error: attempt to mutate range bound within loop; note that the range of the loop is unchanged
-  --> $DIR/mut_range_bound.rs:46:22
+error: attempt to mutate range bound within loop
+  --> $DIR/mut_range_bound.rs:38:22
    |
 LL |         let n = &mut m; // warning
    |                      ^
+   |
+   = note: the range of the loop is unchanged
+
+error: attempt to mutate range bound within loop
+  --> $DIR/mut_range_bound.rs:70:9
+   |
+LL |         m = 2; // warning because it is not immediately followed by break
+   |         ^
+   |
+   = note: the range of the loop is unchanged
+
+error: attempt to mutate range bound within loop
+  --> $DIR/mut_range_bound.rs:79:13
+   |
+LL |             n = 1; // FIXME: warning because is is not immediately followed by break
+   |             ^
+   |
+   = note: the range of the loop is unchanged
 
-error: aborting due to 5 previous errors
+error: aborting due to 7 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_option_as_deref.fixed b/src/tools/clippy/tests/ui/needless_option_as_deref.fixed
new file mode 100644
index 00000000000..d721452ae88
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_option_as_deref.fixed
@@ -0,0 +1,13 @@
+// run-rustfix
+
+#[warn(clippy::needless_option_as_deref)]
+
+fn main() {
+    // should lint
+    let _: Option<&usize> = Some(&1);
+    let _: Option<&mut usize> = Some(&mut 1);
+
+    // should not lint
+    let _ = Some(Box::new(1)).as_deref();
+    let _ = Some(Box::new(1)).as_deref_mut();
+}
diff --git a/src/tools/clippy/tests/ui/needless_option_as_deref.rs b/src/tools/clippy/tests/ui/needless_option_as_deref.rs
new file mode 100644
index 00000000000..bb15512adf6
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_option_as_deref.rs
@@ -0,0 +1,13 @@
+// run-rustfix
+
+#[warn(clippy::needless_option_as_deref)]
+
+fn main() {
+    // should lint
+    let _: Option<&usize> = Some(&1).as_deref();
+    let _: Option<&mut usize> = Some(&mut 1).as_deref_mut();
+
+    // should not lint
+    let _ = Some(Box::new(1)).as_deref();
+    let _ = Some(Box::new(1)).as_deref_mut();
+}
diff --git a/src/tools/clippy/tests/ui/needless_option_as_deref.stderr b/src/tools/clippy/tests/ui/needless_option_as_deref.stderr
new file mode 100644
index 00000000000..5dd507b4a71
--- /dev/null
+++ b/src/tools/clippy/tests/ui/needless_option_as_deref.stderr
@@ -0,0 +1,16 @@
+error: derefed type is same as origin
+  --> $DIR/needless_option_as_deref.rs:7:29
+   |
+LL |     let _: Option<&usize> = Some(&1).as_deref();
+   |                             ^^^^^^^^^^^^^^^^^^^ help: try this: `Some(&1)`
+   |
+   = note: `-D clippy::needless-option-as-deref` implied by `-D warnings`
+
+error: derefed type is same as origin
+  --> $DIR/needless_option_as_deref.rs:8:33
+   |
+LL |     let _: Option<&mut usize> = Some(&mut 1).as_deref_mut();
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Some(&mut 1)`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.fixed b/src/tools/clippy/tests/ui/option_if_let_else.fixed
index 769ccc14bc1..d1815d0aec3 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.fixed
+++ b/src/tools/clippy/tests/ui/option_if_let_else.fixed
@@ -1,3 +1,4 @@
+// edition:2018
 // run-rustfix
 #![warn(clippy::option_if_let_else)]
 #![allow(clippy::redundant_closure)]
@@ -86,4 +87,65 @@ fn main() {
     test_map_or_else(None);
     let _ = negative_tests(None);
     let _ = impure_else(None);
+
+    let _ = Some(0).map_or(0, |x| loop {
+            if x == 0 {
+                break x;
+            }
+        });
+
+    // #7576
+    const fn _f(x: Option<u32>) -> u32 {
+        // Don't lint, `map_or` isn't const
+        if let Some(x) = x { x } else { 10 }
+    }
+
+    // #5822
+    let s = String::new();
+    // Don't lint, `Some` branch consumes `s`, but else branch uses `s`
+    let _ = if let Some(x) = Some(0) {
+        let s = s;
+        s.len() + x
+    } else {
+        s.len()
+    };
+
+    let s = String::new();
+    // Lint, both branches immutably borrow `s`.
+    let _ = Some(0).map_or_else(|| s.len(), |x| s.len() + x);
+
+    let s = String::new();
+    // Lint, `Some` branch consumes `s`, but else branch doesn't use `s`.
+    let _ = Some(0).map_or(1, |x| {
+        let s = s;
+        s.len() + x
+    });
+
+    let s = Some(String::new());
+    // Don't lint, `Some` branch borrows `s`, but else branch consumes `s`
+    let _ = if let Some(x) = &s {
+        x.len()
+    } else {
+        let _s = s;
+        10
+    };
+
+    let mut s = Some(String::new());
+    // Don't lint, `Some` branch mutably borrows `s`, but else branch also borrows  `s`
+    let _ = if let Some(x) = &mut s {
+        x.push_str("test");
+        x.len()
+    } else {
+        let _s = &s;
+        10
+    };
+
+    async fn _f1(x: u32) -> u32 {
+        x
+    }
+
+    async fn _f2() {
+        // Don't lint. `await` can't be moved into a closure.
+        let _ = if let Some(x) = Some(0) { _f1(x).await } else { 0 };
+    }
 }
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.rs b/src/tools/clippy/tests/ui/option_if_let_else.rs
index e2f8dec3b93..a15627338cb 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.rs
+++ b/src/tools/clippy/tests/ui/option_if_let_else.rs
@@ -1,3 +1,4 @@
+// edition:2018
 // run-rustfix
 #![warn(clippy::option_if_let_else)]
 #![allow(clippy::redundant_closure)]
@@ -105,4 +106,71 @@ fn main() {
     test_map_or_else(None);
     let _ = negative_tests(None);
     let _ = impure_else(None);
+
+    let _ = if let Some(x) = Some(0) {
+        loop {
+            if x == 0 {
+                break x;
+            }
+        }
+    } else {
+        0
+    };
+
+    // #7576
+    const fn _f(x: Option<u32>) -> u32 {
+        // Don't lint, `map_or` isn't const
+        if let Some(x) = x { x } else { 10 }
+    }
+
+    // #5822
+    let s = String::new();
+    // Don't lint, `Some` branch consumes `s`, but else branch uses `s`
+    let _ = if let Some(x) = Some(0) {
+        let s = s;
+        s.len() + x
+    } else {
+        s.len()
+    };
+
+    let s = String::new();
+    // Lint, both branches immutably borrow `s`.
+    let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() };
+
+    let s = String::new();
+    // Lint, `Some` branch consumes `s`, but else branch doesn't use `s`.
+    let _ = if let Some(x) = Some(0) {
+        let s = s;
+        s.len() + x
+    } else {
+        1
+    };
+
+    let s = Some(String::new());
+    // Don't lint, `Some` branch borrows `s`, but else branch consumes `s`
+    let _ = if let Some(x) = &s {
+        x.len()
+    } else {
+        let _s = s;
+        10
+    };
+
+    let mut s = Some(String::new());
+    // Don't lint, `Some` branch mutably borrows `s`, but else branch also borrows  `s`
+    let _ = if let Some(x) = &mut s {
+        x.push_str("test");
+        x.len()
+    } else {
+        let _s = &s;
+        10
+    };
+
+    async fn _f1(x: u32) -> u32 {
+        x
+    }
+
+    async fn _f2() {
+        // Don't lint. `await` can't be moved into a closure.
+        let _ = if let Some(x) = Some(0) { _f1(x).await } else { 0 };
+    }
 }
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.stderr b/src/tools/clippy/tests/ui/option_if_let_else.stderr
index 099e49ef8e3..ed748ee8b39 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.stderr
+++ b/src/tools/clippy/tests/ui/option_if_let_else.stderr
@@ -1,5 +1,5 @@
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:7:5
+  --> $DIR/option_if_let_else.rs:8:5
    |
 LL | /     if let Some(x) = string {
 LL | |         (true, x)
@@ -11,19 +11,19 @@ LL | |     }
    = note: `-D clippy::option-if-let-else` implied by `-D warnings`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:25:13
+  --> $DIR/option_if_let_else.rs:26:13
    |
 LL |     let _ = if let Some(s) = *string { s.len() } else { 0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.map_or(0, |s| s.len())`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:26:13
+  --> $DIR/option_if_let_else.rs:27:13
    |
 LL |     let _ = if let Some(s) = &num { s } else { &0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:27:13
+  --> $DIR/option_if_let_else.rs:28:13
    |
 LL |       let _ = if let Some(s) = &mut num {
    |  _____________^
@@ -43,13 +43,13 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:33:13
+  --> $DIR/option_if_let_else.rs:34:13
    |
 LL |     let _ = if let Some(ref s) = num { s } else { &0 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:34:13
+  --> $DIR/option_if_let_else.rs:35:13
    |
 LL |       let _ = if let Some(mut s) = num {
    |  _____________^
@@ -69,7 +69,7 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:40:13
+  --> $DIR/option_if_let_else.rs:41:13
    |
 LL |       let _ = if let Some(ref mut s) = num {
    |  _____________^
@@ -89,7 +89,7 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:49:5
+  --> $DIR/option_if_let_else.rs:50:5
    |
 LL | /     if let Some(x) = arg {
 LL | |         let y = x * x;
@@ -108,7 +108,7 @@ LL +     })
    |
 
 error: use Option::map_or_else instead of an if let/else
-  --> $DIR/option_if_let_else.rs:62:13
+  --> $DIR/option_if_let_else.rs:63:13
    |
 LL |       let _ = if let Some(x) = arg {
    |  _____________^
@@ -120,7 +120,7 @@ LL | |     };
    | |_____^ help: try: `arg.map_or_else(|| side_effect(), |x| x)`
 
 error: use Option::map_or_else instead of an if let/else
-  --> $DIR/option_if_let_else.rs:71:13
+  --> $DIR/option_if_let_else.rs:72:13
    |
 LL |       let _ = if let Some(x) = arg {
    |  _____________^
@@ -143,10 +143,58 @@ LL ~     }, |x| x * x * x * x);
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:100:13
+  --> $DIR/option_if_let_else.rs:101:13
    |
 LL |     let _ = if let Some(x) = optional { x + 2 } else { 5 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)`
 
-error: aborting due to 11 previous errors
+error: use Option::map_or instead of an if let/else
+  --> $DIR/option_if_let_else.rs:110:13
+   |
+LL |       let _ = if let Some(x) = Some(0) {
+   |  _____________^
+LL | |         loop {
+LL | |             if x == 0 {
+LL | |                 break x;
+...  |
+LL | |         0
+LL | |     };
+   | |_____^
+   |
+help: try
+   |
+LL ~     let _ = Some(0).map_or(0, |x| loop {
+LL +             if x == 0 {
+LL +                 break x;
+LL +             }
+LL ~         });
+   |
+
+error: use Option::map_or_else instead of an if let/else
+  --> $DIR/option_if_let_else.rs:138:13
+   |
+LL |     let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() };
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or_else(|| s.len(), |x| s.len() + x)`
+
+error: use Option::map_or instead of an if let/else
+  --> $DIR/option_if_let_else.rs:142:13
+   |
+LL |       let _ = if let Some(x) = Some(0) {
+   |  _____________^
+LL | |         let s = s;
+LL | |         s.len() + x
+LL | |     } else {
+LL | |         1
+LL | |     };
+   | |_____^
+   |
+help: try
+   |
+LL ~     let _ = Some(0).map_or(1, |x| {
+LL +         let s = s;
+LL +         s.len() + x
+LL ~     });
+   |
+
+error: aborting due to 14 previous errors
 
diff --git a/src/tools/clippy/tests/ui/proc_macro.stderr b/src/tools/clippy/tests/ui/proc_macro.stderr
index 872cbc66af6..48fd58c9a49 100644
--- a/src/tools/clippy/tests/ui/proc_macro.stderr
+++ b/src/tools/clippy/tests/ui/proc_macro.stderr
@@ -1,10 +1,11 @@
-error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::PI` found
   --> $DIR/proc_macro.rs:10:14
    |
 LL |     let _x = 3.14;
    |              ^^^^
    |
    = note: `#[deny(clippy::approx_constant)]` on by default
+   = help: consider using the constant directly
 
 error: aborting due to previous error
 
diff --git a/src/tools/clippy/tests/ui/rc_buffer_redefined_string.stderr b/src/tools/clippy/tests/ui/rc_buffer_redefined_string.stderr
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/src/tools/clippy/tests/ui/rc_buffer_redefined_string.stderr
+++ /dev/null
diff --git a/src/tools/clippy/tests/ui/rc_mutex.rs b/src/tools/clippy/tests/ui/rc_mutex.rs
index 657a3ecf6a0..18e8a2e01e0 100644
--- a/src/tools/clippy/tests/ui/rc_mutex.rs
+++ b/src/tools/clippy/tests/ui/rc_mutex.rs
@@ -1,13 +1,17 @@
 #![warn(clippy::rc_mutex)]
-#![allow(clippy::blacklisted_name)]
+#![allow(unused, clippy::blacklisted_name)]
 
 use std::rc::Rc;
 use std::sync::Mutex;
 
-pub struct MyStruct {
+pub struct MyStructWithPrivItem {
     foo: Rc<Mutex<i32>>,
 }
 
+pub struct MyStructWithPubItem {
+    pub foo: Rc<Mutex<i32>>,
+}
+
 pub struct SubT<T> {
     foo: T,
 }
@@ -17,18 +21,16 @@ pub enum MyEnum {
     Two,
 }
 
-pub fn test1<T>(foo: Rc<Mutex<T>>) {}
-
-pub fn test2(foo: Rc<Mutex<MyEnum>>) {}
+// All of these test should be trigger the lint because they are not
+// part of the public api
+fn test1<T>(foo: Rc<Mutex<T>>) {}
+fn test2(foo: Rc<Mutex<MyEnum>>) {}
+fn test3(foo: Rc<Mutex<SubT<usize>>>) {}
 
-pub fn test3(foo: Rc<Mutex<SubT<usize>>>) {}
+// All of these test should be allowed because they are part of the
+// public api and `avoid_breaking_exported_api` is `false` by default.
+pub fn pub_test1<T>(foo: Rc<Mutex<T>>) {}
+pub fn pub_test2(foo: Rc<Mutex<MyEnum>>) {}
+pub fn pub_test3(foo: Rc<Mutex<SubT<usize>>>) {}
 
-fn main() {
-    test1(Rc::new(Mutex::new(1)));
-    test2(Rc::new(Mutex::new(MyEnum::One)));
-    test3(Rc::new(Mutex::new(SubT { foo: 1 })));
-
-    let _my_struct = MyStruct {
-        foo: Rc::new(Mutex::new(1)),
-    };
-}
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/rc_mutex.stderr b/src/tools/clippy/tests/ui/rc_mutex.stderr
index 8e58e2bc2d0..fe84361d781 100644
--- a/src/tools/clippy/tests/ui/rc_mutex.stderr
+++ b/src/tools/clippy/tests/ui/rc_mutex.stderr
@@ -1,28 +1,35 @@
-error: found `Rc<Mutex<_>>`. Consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
+error: usage of `Rc<Mutex<_>>`
   --> $DIR/rc_mutex.rs:8:10
    |
 LL |     foo: Rc<Mutex<i32>>,
    |          ^^^^^^^^^^^^^^
    |
    = note: `-D clippy::rc-mutex` implied by `-D warnings`
+   = help: consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
 
-error: found `Rc<Mutex<_>>`. Consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
-  --> $DIR/rc_mutex.rs:20:22
+error: usage of `Rc<Mutex<_>>`
+  --> $DIR/rc_mutex.rs:26:18
    |
-LL | pub fn test1<T>(foo: Rc<Mutex<T>>) {}
-   |                      ^^^^^^^^^^^^
+LL | fn test1<T>(foo: Rc<Mutex<T>>) {}
+   |                  ^^^^^^^^^^^^
+   |
+   = help: consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
 
-error: found `Rc<Mutex<_>>`. Consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
-  --> $DIR/rc_mutex.rs:22:19
+error: usage of `Rc<Mutex<_>>`
+  --> $DIR/rc_mutex.rs:27:15
+   |
+LL | fn test2(foo: Rc<Mutex<MyEnum>>) {}
+   |               ^^^^^^^^^^^^^^^^^
    |
-LL | pub fn test2(foo: Rc<Mutex<MyEnum>>) {}
-   |                   ^^^^^^^^^^^^^^^^^
+   = help: consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
 
-error: found `Rc<Mutex<_>>`. Consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
-  --> $DIR/rc_mutex.rs:24:19
+error: usage of `Rc<Mutex<_>>`
+  --> $DIR/rc_mutex.rs:28:15
+   |
+LL | fn test3(foo: Rc<Mutex<SubT<usize>>>) {}
+   |               ^^^^^^^^^^^^^^^^^^^^^^
    |
-LL | pub fn test3(foo: Rc<Mutex<SubT<usize>>>) {}
-   |                   ^^^^^^^^^^^^^^^^^^^^^^
+   = help: consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
 
 error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui/redundant_allocation.rs b/src/tools/clippy/tests/ui/redundant_allocation.rs
index 1b4f2a66c70..52fbc91e325 100644
--- a/src/tools/clippy/tests/ui/redundant_allocation.rs
+++ b/src/tools/clippy/tests/ui/redundant_allocation.rs
@@ -77,4 +77,24 @@ mod outer_arc {
     }
 }
 
+// https://github.com/rust-lang/rust-clippy/issues/7487
+mod box_dyn {
+    use std::boxed::Box;
+    use std::rc::Rc;
+    use std::sync::Arc;
+
+    pub trait T {}
+
+    struct S {
+        a: Box<Box<dyn T>>,
+        b: Rc<Box<dyn T>>,
+        c: Arc<Box<dyn T>>,
+    }
+
+    pub fn test_box(_: Box<Box<dyn T>>) {}
+    pub fn test_rc(_: Rc<Box<dyn T>>) {}
+    pub fn test_arc(_: Arc<Box<dyn T>>) {}
+    pub fn test_rc_box(_: Rc<Box<Box<dyn T>>>) {}
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/redundant_allocation.stderr b/src/tools/clippy/tests/ui/redundant_allocation.stderr
index fdab74eb538..c3b10e5f5e6 100644
--- a/src/tools/clippy/tests/ui/redundant_allocation.stderr
+++ b/src/tools/clippy/tests/ui/redundant_allocation.stderr
@@ -134,5 +134,14 @@ LL |     pub fn arc_test9<T>(foo: Arc<Rc<T>>) -> Arc<Rc<SubT<T>>> {
    = note: `Rc<SubT<T>>` is already on the heap, `Arc<Rc<SubT<T>>>` makes an extra allocation
    = help: consider using just `Arc<SubT<T>>` or `Rc<SubT<T>>`
 
-error: aborting due to 15 previous errors
+error: usage of `Rc<Box<Box<dyn T>>>`
+  --> $DIR/redundant_allocation.rs:97:27
+   |
+LL |     pub fn test_rc_box(_: Rc<Box<Box<dyn T>>>) {}
+   |                           ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Box<Box<dyn T>>` is already on the heap, `Rc<Box<Box<dyn T>>>` makes an extra allocation
+   = help: consider using just `Rc<Box<dyn T>>` or `Box<Box<dyn T>>`
+
+error: aborting due to 16 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_operation.fixed b/src/tools/clippy/tests/ui/unnecessary_operation.fixed
index 2fca96c4cd5..bf0ec8deb34 100644
--- a/src/tools/clippy/tests/ui/unnecessary_operation.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_operation.fixed
@@ -62,10 +62,10 @@ fn main() {
     get_number();
     5;get_number();
     42;get_number();
-    [42, 55];get_usize();
+    assert!([42, 55].len() > get_usize());
     42;get_number();
     get_number();
-    [42; 55];get_usize();
+    assert!([42; 55].len() > get_usize());
     get_number();
     String::from("blah");
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_operation.stderr b/src/tools/clippy/tests/ui/unnecessary_operation.stderr
index f88c9f9908b..f66d08ecb82 100644
--- a/src/tools/clippy/tests/ui/unnecessary_operation.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_operation.stderr
@@ -1,128 +1,128 @@
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:51:5
    |
 LL |     Tuple(get_number());
-   |     ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();`
+   |     ^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
    |
    = note: `-D clippy::unnecessary-operation` implied by `-D warnings`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:52:5
    |
 LL |     Struct { field: get_number() };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:53:5
    |
 LL |     Struct { ..get_struct() };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_struct();`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_struct();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:54:5
    |
 LL |     Enum::Tuple(get_number());
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:55:5
    |
 LL |     Enum::Struct { field: get_number() };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:56:5
    |
 LL |     5 + get_number();
-   |     ^^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();`
+   |     ^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:57:5
    |
 LL |     *&get_number();
-   |     ^^^^^^^^^^^^^^^ help: replace it with: `get_number();`
+   |     ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:58:5
    |
 LL |     &get_number();
-   |     ^^^^^^^^^^^^^^ help: replace it with: `get_number();`
+   |     ^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:59:5
    |
 LL |     (5, 6, get_number());
-   |     ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `5;6;get_number();`
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;6;get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:60:5
    |
 LL |     box get_number();
-   |     ^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();`
+   |     ^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:61:5
    |
 LL |     get_number()..;
-   |     ^^^^^^^^^^^^^^^ help: replace it with: `get_number();`
+   |     ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:62:5
    |
 LL |     ..get_number();
-   |     ^^^^^^^^^^^^^^^ help: replace it with: `get_number();`
+   |     ^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:63:5
    |
 LL |     5..get_number();
-   |     ^^^^^^^^^^^^^^^^ help: replace it with: `5;get_number();`
+   |     ^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:64:5
    |
 LL |     [42, get_number()];
-   |     ^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();`
+   |     ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:65:5
    |
 LL |     [42, 55][get_usize()];
-   |     ^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42, 55];get_usize();`
+   |     ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42, 55].len() > get_usize());`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:66:5
    |
 LL |     (42, get_number()).1;
-   |     ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `42;get_number();`
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:67:5
    |
 LL |     [get_number(); 55];
-   |     ^^^^^^^^^^^^^^^^^^^ help: replace it with: `get_number();`
+   |     ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:68:5
    |
 LL |     [42; 55][get_usize()];
-   |     ^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `[42; 55];get_usize();`
+   |     ^^^^^^^^^^^^^^^^^^^^^^ help: statement can be written as: `assert!([42; 55].len() > get_usize());`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:69:5
    |
 LL | /     {
 LL | |         get_number()
 LL | |     };
-   | |______^ help: replace it with: `get_number();`
+   | |______^ help: statement can be reduced to: `get_number();`
 
-error: statement can be reduced
+error: unnecessary operation
   --> $DIR/unnecessary_operation.rs:72:5
    |
 LL | /     FooString {
 LL | |         s: String::from("blah"),
 LL | |     };
-   | |______^ help: replace it with: `String::from("blah");`
+   | |______^ help: statement can be reduced to: `String::from("blah");`
 
 error: aborting due to 20 previous errors
 
diff --git a/src/tools/clippy/tests/versioncheck.rs b/src/tools/clippy/tests/versioncheck.rs
index 1eaec4a50a6..77102b8cac0 100644
--- a/src/tools/clippy/tests/versioncheck.rs
+++ b/src/tools/clippy/tests/versioncheck.rs
@@ -1,4 +1,7 @@
+#![cfg_attr(feature = "deny-warnings", deny(warnings))]
+#![warn(rust_2018_idioms, unused_lifetimes)]
 #![allow(clippy::single_match_else)]
+
 use rustc_tools_util::VersionInfo;
 
 #[test]
diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs
index 8cbe0a0c2e8..94ebbb33e8d 100644
--- a/src/tools/linkchecker/main.rs
+++ b/src/tools/linkchecker/main.rs
@@ -30,6 +30,7 @@ use regex::Regex;
 // If at all possible you should use intra-doc links to avoid linkcheck issues. These
 // are cases where that does not work
 // [(generated_documentation_page, &[broken_links])]
+#[rustfmt::skip]
 const LINKCHECK_EXCEPTIONS: &[(&str, &[&str])] = &[
     // These try to link to std::collections, but are defined in alloc
     // https://github.com/rust-lang/rust/issues/74481
@@ -37,6 +38,19 @@ const LINKCHECK_EXCEPTIONS: &[(&str, &[&str])] = &[
     ("std/collections/btree_set/struct.BTreeSet.html", &["#insert-and-complex-keys"]),
     ("alloc/collections/btree_map/struct.BTreeMap.html", &["#insert-and-complex-keys"]),
     ("alloc/collections/btree_set/struct.BTreeSet.html", &["#insert-and-complex-keys"]),
+
+    // These try to link to various things in std, but are defined in core.
+    // The docs in std::primitive use proper intra-doc links, so these seem fine to special-case.
+    // Most these are broken because liballoc uses `#[lang_item]` magic to define things on
+    // primitives that aren't available in core.
+    ("alloc/slice/trait.Join.html", &["#method.join"]),
+    ("alloc/slice/trait.Concat.html", &["#method.concat"]),
+    ("alloc/slice/index.html", &["#method.concat", "#method.join"]),
+    ("alloc/vec/struct.Vec.html", &["#method.sort_by_key", "#method.sort_by_cached_key"]),
+    ("core/primitive.str.html", &["#method.to_ascii_uppercase", "#method.to_ascii_lowercase"]),
+    ("core/primitive.slice.html", &["#method.to_ascii_uppercase", "#method.to_ascii_lowercase",
+                                    "core/slice::sort_by_key", "core\\slice::sort_by_key",
+                                    "#method.sort_by_cached_key"]),
 ];
 
 #[rustfmt::skip]
@@ -376,6 +390,10 @@ impl Checker {
 
     /// Load a file from disk, or from the cache if available.
     fn load_file(&mut self, file: &Path, report: &mut Report) -> (String, &FileEntry) {
+        // https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
+        #[cfg(windows)]
+        const ERROR_INVALID_NAME: i32 = 123;
+
         let pretty_path =
             file.strip_prefix(&self.root).unwrap_or(&file).to_str().unwrap().to_string();
 
@@ -392,6 +410,14 @@ impl Checker {
                 }
                 Err(e) if e.kind() == ErrorKind::NotFound => FileEntry::Missing,
                 Err(e) => {
+                    // If a broken intra-doc link contains `::`, on windows, it will cause `ERROR_INVALID_NAME` rather than `NotFound`.
+                    // Explicitly check for that so that the broken link can be allowed in `LINKCHECK_EXCEPTIONS`.
+                    #[cfg(windows)]
+                    if e.raw_os_error() == Some(ERROR_INVALID_NAME)
+                        && file.as_os_str().to_str().map_or(false, |s| s.contains("::"))
+                    {
+                        return FileEntry::Missing;
+                    }
                     panic!("unexpected read error for {}: {}", file.display(), e);
                 }
             });
diff --git a/src/tools/miri b/src/tools/miri
-Subproject 7a2f1cadcd5120c44eda3596053de767cd8173a
+Subproject 035933186957cf81c488261fb48a98bf523e800
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index f97914b1e97..04a1d257bc0 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -299,7 +299,13 @@ try:
     if repo:
         github_token = os.environ.get('TOOLSTATE_REPO_ACCESS_TOKEN')
         if github_token:
-            validate_maintainers(repo, github_token)
+            # FIXME: This is currently broken. Starting on 2021-09-15, GitHub
+            # seems to have changed it so that to list the collaborators
+            # requires admin permissions. I think this will probably just need
+            # to be removed since we are probably not going to use an admin
+            # token, and I don't see another way to do this.
+            print('maintainer validation disabled')
+            # validate_maintainers(repo, github_token)
         else:
             print('skipping toolstate maintainers validation since no GitHub token is present')
         # When validating maintainers don't run the full script.
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index 2483d0570d9..14041539b9d 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -6,7 +6,7 @@ use std::cmp::{max, min, Ordering};
 use regex::Regex;
 use rustc_ast::visit;
 use rustc_ast::{ast, ptr};
-use rustc_span::{symbol, BytePos, Span};
+use rustc_span::{symbol, BytePos, Span, DUMMY_SP};
 
 use crate::attr::filter_inline_attrs;
 use crate::comment::{
@@ -31,7 +31,12 @@ use crate::stmt::Stmt;
 use crate::utils::*;
 use crate::vertical::rewrite_with_alignment;
 use crate::visitor::FmtVisitor;
-use crate::DEFAULT_VISIBILITY;
+
+const DEFAULT_VISIBILITY: ast::Visibility = ast::Visibility {
+    kind: ast::VisibilityKind::Inherited,
+    span: DUMMY_SP,
+    tokens: None,
+};
 
 fn type_annotation_separator(config: &Config) -> &str {
     colon_spaces(config)
@@ -972,7 +977,7 @@ impl<'a> StructParts<'a> {
         format_header(context, self.prefix, self.ident, self.vis, offset)
     }
 
-    pub(crate) fn from_variant(variant: &'a ast::Variant) -> Self {
+    fn from_variant(variant: &'a ast::Variant) -> Self {
         StructParts {
             prefix: "",
             ident: variant.ident,
diff --git a/src/tools/rustfmt/src/lib.rs b/src/tools/rustfmt/src/lib.rs
index 206d2f78290..47a7b9d4dbe 100644
--- a/src/tools/rustfmt/src/lib.rs
+++ b/src/tools/rustfmt/src/lib.rs
@@ -32,7 +32,7 @@ use std::path::PathBuf;
 use std::rc::Rc;
 
 use rustc_ast::ast;
-use rustc_span::{symbol, DUMMY_SP};
+use rustc_span::symbol;
 use thiserror::Error;
 
 use crate::comment::LineClasses;
@@ -96,11 +96,6 @@ mod types;
 mod vertical;
 pub(crate) mod visitor;
 
-const DEFAULT_VISIBILITY: ast::Visibility = ast::Visibility {
-    kind: ast::VisibilityKind::Inherited,
-    span: DUMMY_SP,
-    tokens: None,
-};
 /// The various errors that can occur during formatting. Note that not all of
 /// these can currently be propagated to clients.
 #[derive(Error, Debug)]
diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index a9bc89544d8..927187dfd8a 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/src/macros.rs
@@ -762,7 +762,6 @@ impl MacroArgKind {
 #[derive(Debug, Clone)]
 struct ParsedMacroArg {
     kind: MacroArgKind,
-    span: Span,
 }
 
 impl ParsedMacroArg {
@@ -780,14 +779,10 @@ impl ParsedMacroArg {
 struct MacroArgParser {
     /// Either a name of the next metavariable, a separator, or junk.
     buf: String,
-    /// The start position on the current buffer.
-    lo: BytePos,
     /// The first token of the current buffer.
     start_tok: Token,
     /// `true` if we are parsing a metavariable or a repeat.
     is_meta_var: bool,
-    /// The position of the last token.
-    hi: BytePos,
     /// The last token parsed.
     last_tok: Token,
     /// Holds the parsed arguments.
@@ -807,8 +802,6 @@ fn last_tok(tt: &TokenTree) -> Token {
 impl MacroArgParser {
     fn new() -> MacroArgParser {
         MacroArgParser {
-            lo: BytePos(0),
-            hi: BytePos(0),
             buf: String::new(),
             is_meta_var: false,
             last_tok: Token {
@@ -824,7 +817,6 @@ impl MacroArgParser {
     }
 
     fn set_last_tok(&mut self, tok: &TokenTree) {
-        self.hi = tok.span().hi();
         self.last_tok = last_tok(tok);
     }
 
@@ -836,7 +828,6 @@ impl MacroArgParser {
         };
         self.result.push(ParsedMacroArg {
             kind: MacroArgKind::Separator(self.buf.clone(), prefix),
-            span: mk_sp(self.lo, self.hi),
         });
         self.buf.clear();
     }
@@ -849,7 +840,6 @@ impl MacroArgParser {
         };
         self.result.push(ParsedMacroArg {
             kind: MacroArgKind::Other(self.buf.clone(), prefix),
-            span: mk_sp(self.lo, self.hi),
         });
         self.buf.clear();
     }
@@ -858,11 +848,10 @@ impl MacroArgParser {
         match iter.next() {
             Some(TokenTree::Token(Token {
                 kind: TokenKind::Ident(name, _),
-                span,
+                ..
             })) => {
                 self.result.push(ParsedMacroArg {
                     kind: MacroArgKind::MetaVariable(name, self.buf.clone()),
-                    span: mk_sp(self.lo, span.hi()),
                 });
 
                 self.buf.clear();
@@ -873,10 +862,9 @@ impl MacroArgParser {
         }
     }
 
-    fn add_delimited(&mut self, inner: Vec<ParsedMacroArg>, delim: DelimToken, span: Span) {
+    fn add_delimited(&mut self, inner: Vec<ParsedMacroArg>, delim: DelimToken) {
         self.result.push(ParsedMacroArg {
             kind: MacroArgKind::Delimited(delim, inner),
-            span,
         });
     }
 
@@ -886,19 +874,15 @@ impl MacroArgParser {
         inner: Vec<ParsedMacroArg>,
         delim: DelimToken,
         iter: &mut Cursor,
-        span: Span,
     ) -> Option<()> {
         let mut buffer = String::new();
         let mut first = true;
-        let mut lo = span.lo();
-        let mut hi = span.hi();
 
         // Parse '*', '+' or '?.
         for tok in iter {
             self.set_last_tok(&tok);
             if first {
                 first = false;
-                lo = tok.span().lo();
             }
 
             match tok {
@@ -918,7 +902,6 @@ impl MacroArgParser {
                 }
                 TokenTree::Token(ref t) => {
                     buffer.push_str(&pprust::token_to_string(&t));
-                    hi = t.span.hi();
                 }
                 _ => return None,
             }
@@ -930,20 +913,17 @@ impl MacroArgParser {
         } else {
             Some(Box::new(ParsedMacroArg {
                 kind: MacroArgKind::Other(buffer, "".to_owned()),
-                span: mk_sp(lo, hi),
             }))
         };
 
         self.result.push(ParsedMacroArg {
             kind: MacroArgKind::Repeat(delim, inner, another, self.last_tok.clone()),
-            span: mk_sp(self.lo, self.hi),
         });
         Some(())
     }
 
     fn update_buffer(&mut self, t: &Token) {
         if self.buf.is_empty() {
-            self.lo = t.span.lo();
             self.start_tok = t.clone();
         } else {
             let needs_space = match next_space(&self.last_tok.kind) {
@@ -999,7 +979,6 @@ impl MacroArgParser {
 
                     // Start keeping the name of this metavariable in the buffer.
                     self.is_meta_var = true;
-                    self.lo = span.lo();
                     self.start_tok = Token {
                         kind: TokenKind::Dollar,
                         span,
@@ -1012,7 +991,7 @@ impl MacroArgParser {
                     self.add_meta_variable(&mut iter)?;
                 }
                 TokenTree::Token(ref t) => self.update_buffer(t),
-                TokenTree::Delimited(delimited_span, delimited, ref tts) => {
+                TokenTree::Delimited(_delimited_span, delimited, ref tts) => {
                     if !self.buf.is_empty() {
                         if next_space(&self.last_tok.kind) == SpaceState::Always {
                             self.add_separator();
@@ -1022,16 +1001,14 @@ impl MacroArgParser {
                     }
 
                     // Parse the stuff inside delimiters.
-                    let mut parser = MacroArgParser::new();
-                    parser.lo = delimited_span.open.lo();
+                    let parser = MacroArgParser::new();
                     let delimited_arg = parser.parse(tts.clone())?;
 
-                    let span = delimited_span.entire();
                     if self.is_meta_var {
-                        self.add_repeat(delimited_arg, delimited, &mut iter, span)?;
+                        self.add_repeat(delimited_arg, delimited, &mut iter)?;
                         self.is_meta_var = false;
                     } else {
-                        self.add_delimited(delimited_arg, delimited, span);
+                        self.add_delimited(delimited_arg, delimited);
                     }
                 }
             }
@@ -1270,7 +1247,12 @@ impl MacroParser {
                 let data = delimited_span.entire().data();
                 (
                     data.hi,
-                    Span::new(data.lo + BytePos(1), data.hi - BytePos(1), data.ctxt),
+                    Span::new(
+                        data.lo + BytePos(1),
+                        data.hi - BytePos(1),
+                        data.ctxt,
+                        data.parent,
+                    ),
                     delimited_span.entire(),
                 )
             }
diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs
index 5de0575b5cd..ded34d9032f 100644
--- a/src/tools/rustfmt/src/modules.rs
+++ b/src/tools/rustfmt/src/modules.rs
@@ -27,7 +27,6 @@ type FileModMap<'ast> = BTreeMap<FileName, Module<'ast>>;
 pub(crate) struct Module<'a> {
     ast_mod_kind: Option<Cow<'a, ast::ModKind>>,
     pub(crate) items: Cow<'a, Vec<rustc_ast::ptr::P<ast::Item>>>,
-    attrs: Cow<'a, Vec<ast::Attribute>>,
     inner_attr: Vec<ast::Attribute>,
     pub(crate) span: Span,
 }
@@ -46,7 +45,6 @@ impl<'a> Module<'a> {
             .collect();
         Module {
             items: mod_items,
-            attrs: mod_attrs,
             inner_attr,
             span: mod_span,
             ast_mod_kind,
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index 640d127e860..76bf58e875b 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -1,15 +1,15 @@
 use std::iter::ExactSizeIterator;
 use std::ops::Deref;
 
-use rustc_ast::ast::{self, AttrVec, FnRetTy, Mutability};
-use rustc_span::{symbol::kw, symbol::Ident, BytePos, Pos, Span};
+use rustc_ast::ast::{self, FnRetTy, Mutability};
+use rustc_span::{symbol::kw, BytePos, Pos, Span};
 
+use crate::comment::{combine_strs_with_missing_comments, contains_comment};
 use crate::config::lists::*;
 use crate::config::{IndentStyle, TypeDensity, Version};
 use crate::expr::{
     format_expr, rewrite_assign_rhs, rewrite_call, rewrite_tuple, rewrite_unary_prefix, ExprType,
 };
-use crate::items::StructParts;
 use crate::lists::{
     definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator,
 };
@@ -24,11 +24,6 @@ use crate::utils::{
     colon_spaces, extra_offset, first_line_width, format_extern, format_mutability,
     last_line_extendable, last_line_width, mk_sp, rewrite_ident,
 };
-use crate::DEFAULT_VISIBILITY;
-use crate::{
-    comment::{combine_strs_with_missing_comments, contains_comment},
-    items::format_struct_struct,
-};
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub(crate) enum PathContext {
@@ -769,54 +764,6 @@ impl Rewrite for ast::Ty {
             ast::TyKind::Tup(ref items) => {
                 rewrite_tuple(context, items.iter(), self.span, shape, items.len() == 1)
             }
-            ast::TyKind::AnonymousStruct(ref fields, recovered) => {
-                let ident = Ident::new(
-                    kw::Struct,
-                    mk_sp(self.span.lo(), self.span.lo() + BytePos(6)),
-                );
-                let data = ast::VariantData::Struct(fields.clone(), recovered);
-                let variant = ast::Variant {
-                    attrs: AttrVec::new(),
-                    id: self.id,
-                    span: self.span,
-                    vis: DEFAULT_VISIBILITY,
-                    ident,
-                    data,
-                    disr_expr: None,
-                    is_placeholder: false,
-                };
-                format_struct_struct(
-                    &context,
-                    &StructParts::from_variant(&variant),
-                    fields,
-                    shape.indent,
-                    None,
-                )
-            }
-            ast::TyKind::AnonymousUnion(ref fields, recovered) => {
-                let ident = Ident::new(
-                    kw::Union,
-                    mk_sp(self.span.lo(), self.span.lo() + BytePos(5)),
-                );
-                let data = ast::VariantData::Struct(fields.clone(), recovered);
-                let variant = ast::Variant {
-                    attrs: AttrVec::new(),
-                    id: self.id,
-                    span: self.span,
-                    vis: DEFAULT_VISIBILITY,
-                    ident,
-                    data,
-                    disr_expr: None,
-                    is_placeholder: false,
-                };
-                format_struct_struct(
-                    &context,
-                    &StructParts::from_variant(&variant),
-                    fields,
-                    shape.indent,
-                    None,
-                )
-            }
             ast::TyKind::Path(ref q_self, ref path) => {
                 rewrite_path(context, PathContext::Type, q_self.as_ref(), path, shape)
             }
diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs
index 06159a1b26e..29e1e070d41 100644
--- a/src/tools/rustfmt/src/utils.rs
+++ b/src/tools/rustfmt/src/utils.rs
@@ -356,11 +356,11 @@ macro_rules! source {
 }
 
 pub(crate) fn mk_sp(lo: BytePos, hi: BytePos) -> Span {
-    Span::new(lo, hi, SyntaxContext::root())
+    Span::new(lo, hi, SyntaxContext::root(), None)
 }
 
 pub(crate) fn mk_sp_lo_plus_one(lo: BytePos) -> Span {
-    Span::new(lo, lo + BytePos(1), SyntaxContext::root())
+    Span::new(lo, lo + BytePos(1), SyntaxContext::root(), None)
 }
 
 // Returns `true` if the given span does not intersect with file lines.
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index a1c41eb9981..35809e59926 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -46,6 +46,7 @@ pub mod errors;
 pub mod extdeps;
 pub mod features;
 pub mod pal;
+pub mod primitive_docs;
 pub mod style;
 pub mod target_specific_tests;
 pub mod ui_tests;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index 440c352ea53..d555f7c8e34 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -71,6 +71,7 @@ fn main() {
 
         // Checks that only make sense for the std libs.
         check!(pal, &library_path);
+        check!(primitive_docs, &library_path);
 
         // Checks that need to be done for both the compiler and std libraries.
         check!(unit_tests, &src_path);
diff --git a/src/tools/tidy/src/primitive_docs.rs b/src/tools/tidy/src/primitive_docs.rs
new file mode 100644
index 00000000000..8476650d9b5
--- /dev/null
+++ b/src/tools/tidy/src/primitive_docs.rs
@@ -0,0 +1,17 @@
+//! Tidy check to make sure `library/{std,core}/src/primitive_docs.rs` are the same file.  These are
+//! different files so that relative links work properly without having to have `CARGO_PKG_NAME`
+//! set, but conceptually they should always be the same.
+
+use std::path::Path;
+
+pub fn check(library_path: &Path, bad: &mut bool) {
+    let std_name = "std/src/primitive_docs.rs";
+    let core_name = "core/src/primitive_docs.rs";
+    let std_contents = std::fs::read_to_string(library_path.join(std_name))
+        .unwrap_or_else(|e| panic!("failed to read library/{}: {}", std_name, e));
+    let core_contents = std::fs::read_to_string(library_path.join(core_name))
+        .unwrap_or_else(|e| panic!("failed to read library/{}: {}", core_name, e));
+    if std_contents != core_contents {
+        tidy_error!(bad, "library/{} and library/{} have different contents", core_name, std_name);
+    }
+}