about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/tool.rs2
-rw-r--r--src/doc/unstable-book/src/compiler-flags/sanitizer.md3
-rw-r--r--src/libcore/iter/traits/iterator.rs29
-rw-r--r--src/libcore/tests/lib.rs2
-rw-r--r--src/librustc_arena/lib.rs39
-rw-r--r--src/librustc_codegen_llvm/attributes.rs45
-rw-r--r--src/librustc_codegen_llvm/back/write.rs44
-rw-r--r--src/librustc_codegen_llvm/base.rs6
-rw-r--r--src/librustc_codegen_llvm/common.rs2
-rw-r--r--src/librustc_codegen_llvm/llvm/ffi.rs7
-rw-r--r--src/librustc_codegen_ssa/back/link.rs40
-rw-r--r--src/librustc_codegen_ssa/back/symbol_export.rs4
-rw-r--r--src/librustc_codegen_ssa/back/write.rs12
-rw-r--r--src/librustc_error_codes/error_codes.rs1
-rw-r--r--src/librustc_error_codes/error_codes/E0668.md13
-rw-r--r--src/librustc_error_codes/error_codes/E0670.md2
-rw-r--r--src/librustc_error_codes/error_codes/E0764.md39
-rw-r--r--src/librustc_feature/active.rs1
-rw-r--r--src/librustc_infer/infer/canonical/canonicalizer.rs5
-rw-r--r--src/librustc_infer/infer/error_reporting/need_type_info.rs17
-rw-r--r--src/librustc_infer/infer/region_constraints/mod.rs17
-rw-r--r--src/librustc_infer/infer/resolve.rs43
-rw-r--r--src/librustc_interface/tests.rs8
-rw-r--r--src/librustc_middle/middle/codegen_fn_attrs.rs17
-rw-r--r--src/librustc_middle/mir/query.rs2
-rw-r--r--src/librustc_middle/ty/context.rs16
-rw-r--r--src/librustc_middle/ty/fold.rs3
-rw-r--r--src/librustc_middle/ty/instance.rs52
-rw-r--r--src/librustc_middle/ty/layout.rs2
-rw-r--r--src/librustc_middle/ty/list.rs17
-rw-r--r--src/librustc_middle/ty/mod.rs1
-rw-r--r--src/librustc_middle/ty/print/pretty.rs7
-rw-r--r--src/librustc_middle/ty/sty.rs3
-rw-r--r--src/librustc_mir/const_eval/mod.rs24
-rw-r--r--src/librustc_mir/shim.rs64
-rw-r--r--src/librustc_mir/transform/check_consts/ops.rs34
-rw-r--r--src/librustc_mir/transform/inline.rs21
-rw-r--r--src/librustc_mir/transform/validate.rs10
-rw-r--r--src/librustc_mir_build/hair/pattern/_match.rs6
-rw-r--r--src/librustc_mir_build/hair/pattern/const_to_pat.rs4
-rw-r--r--src/librustc_session/Cargo.toml1
-rw-r--r--src/librustc_session/config.rs75
-rw-r--r--src/librustc_session/lib.rs3
-rw-r--r--src/librustc_session/options.rs32
-rw-r--r--src/librustc_session/session.rs70
-rw-r--r--src/librustc_trait_selection/traits/project.rs12
-rw-r--r--src/librustc_trait_selection/traits/util.rs2
-rw-r--r--src/librustc_typeck/astconv.rs2
-rw-r--r--src/librustc_typeck/check/coercion.rs49
-rw-r--r--src/librustc_typeck/collect.rs9
-rw-r--r--src/libstd/prelude/mod.rs16
-rw-r--r--src/rustllvm/PassWrapper.cpp13
-rw-r--r--src/test/compile-fail/issue-52443.rs2
-rw-r--r--src/test/compile-fail/specialization/issue-50452.rs2
-rw-r--r--src/test/mir-opt/fn-ptr-shim.rs15
-rw-r--r--src/test/mir-opt/fn-ptr-shim/rustc.ops-function-Fn-call.AddMovesForPackedDrops.before.mir13
-rw-r--r--src/test/mir-opt/issue-72181-1.rs21
-rw-r--r--src/test/mir-opt/issue-72181-1/rustc.f.mir_map.0.mir37
-rw-r--r--src/test/mir-opt/issue-72181-1/rustc.main.mir_map.0.mir67
-rw-r--r--src/test/mir-opt/issue-72181.rs28
-rw-r--r--src/test/mir-opt/issue-72181/32bit/rustc.bar.mir_map.0.mir25
-rw-r--r--src/test/mir-opt/issue-72181/32bit/rustc.foo.mir_map.0.mir37
-rw-r--r--src/test/mir-opt/issue-72181/32bit/rustc.main.mir_map.0.mir93
-rw-r--r--src/test/mir-opt/issue-72181/64bit/rustc.bar.mir_map.0.mir25
-rw-r--r--src/test/mir-opt/issue-72181/64bit/rustc.foo.mir_map.0.mir37
-rw-r--r--src/test/mir-opt/issue-72181/64bit/rustc.main.mir_map.0.mir93
-rw-r--r--src/test/mir-opt/issue-72181/rustc.bar.mir_map.0.mir25
-rw-r--r--src/test/mir-opt/issue-72181/rustc.foo.mir_map.0.mir37
-rw-r--r--src/test/mir-opt/issue-72181/rustc.main.mir_map.0.mir93
-rw-r--r--src/test/rustdoc/synthetic_auto/overflow.rs35
-rw-r--r--src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr4
-rw-r--r--src/test/ui/associated-types/defaults-specialization.rs1
-rw-r--r--src/test/ui/associated-types/defaults-specialization.stderr37
-rw-r--r--src/test/ui/auto-traits/auto-is-contextual.rs (renamed from src/test/ui/auto-is-contextual.rs)0
-rw-r--r--src/test/ui/auto-traits/auto-trait-projection-recursion.rs34
-rw-r--r--src/test/ui/auto-traits/auto-trait-validation.rs (renamed from src/test/ui/auto-trait-validation.rs)0
-rw-r--r--src/test/ui/auto-traits/auto-trait-validation.stderr (renamed from src/test/ui/auto-trait-validation.stderr)0
-rw-r--r--src/test/ui/auto-traits/auto-traits.rs (renamed from src/test/ui/traits/auto-traits.rs)0
-rw-r--r--src/test/ui/auto-traits/issue-23080-2.rs (renamed from src/test/ui/issues/issue-23080-2.rs)0
-rw-r--r--src/test/ui/auto-traits/issue-23080-2.stderr (renamed from src/test/ui/issues/issue-23080-2.stderr)0
-rw-r--r--src/test/ui/auto-traits/issue-23080.rs (renamed from src/test/ui/issues/issue-23080.rs)0
-rw-r--r--src/test/ui/auto-traits/issue-23080.stderr (renamed from src/test/ui/issues/issue-23080.stderr)0
-rw-r--r--src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs (renamed from src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.rs)0
-rw-r--r--src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr (renamed from src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr)0
-rw-r--r--src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.rs (renamed from src/test/ui/typeck/typeck-auto-trait-no-supertraits.rs)0
-rw-r--r--src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr (renamed from src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr)0
-rw-r--r--src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.rs (renamed from src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.rs)0
-rw-r--r--src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr (renamed from src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr)0
-rw-r--r--src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.rs (renamed from src/test/ui/typeck/typeck-default-trait-impl-constituent-types.rs)0
-rw-r--r--src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.stderr (renamed from src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr)0
-rw-r--r--src/test/ui/auto-traits/typeck-default-trait-impl-negation.rs (renamed from src/test/ui/typeck/typeck-default-trait-impl-negation.rs)0
-rw-r--r--src/test/ui/auto-traits/typeck-default-trait-impl-negation.stderr (renamed from src/test/ui/typeck/typeck-default-trait-impl-negation.stderr)0
-rw-r--r--src/test/ui/auto-traits/typeck-default-trait-impl-precedence.rs (renamed from src/test/ui/typeck/typeck-default-trait-impl-precedence.rs)0
-rw-r--r--src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr (renamed from src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr)0
-rw-r--r--src/test/ui/check-static-immutable-mut-slices.rs2
-rw-r--r--src/test/ui/check-static-immutable-mut-slices.stderr9
-rw-r--r--src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr4
-rw-r--r--src/test/ui/coerce/coerce-overloaded-autoderef.rs68
-rw-r--r--src/test/ui/coercion/coerce-expect-unsized.rs (renamed from src/test/ui/coerce/coerce-expect-unsized.rs)0
-rw-r--r--src/test/ui/coercion/coerce-overloaded-autoderef-fail.rs32
-rw-r--r--src/test/ui/coercion/coerce-overloaded-autoderef-fail.stderr (renamed from src/test/ui/coercion/coerce-overloaded-autoderef.stderr)8
-rw-r--r--src/test/ui/coercion/coerce-overloaded-autoderef.rs78
-rw-r--r--src/test/ui/coercion/coerce-reborrow-imm-ptr-arg.rs (renamed from src/test/ui/coerce/coerce-reborrow-imm-ptr-arg.rs)0
-rw-r--r--src/test/ui/coercion/coerce-reborrow-imm-ptr-rcvr.rs (renamed from src/test/ui/coerce/coerce-reborrow-imm-ptr-rcvr.rs)0
-rw-r--r--src/test/ui/coercion/coerce-reborrow-imm-vec-arg.rs (renamed from src/test/ui/coerce/coerce-reborrow-imm-vec-arg.rs)0
-rw-r--r--src/test/ui/coercion/coerce-reborrow-imm-vec-rcvr.rs (renamed from src/test/ui/coerce/coerce-reborrow-imm-vec-rcvr.rs)0
-rw-r--r--src/test/ui/coercion/coerce-reborrow-multi-arg-fail.rs6
-rw-r--r--src/test/ui/coercion/coerce-reborrow-multi-arg-fail.stderr12
-rw-r--r--src/test/ui/coercion/coerce-reborrow-multi-arg.rs9
-rw-r--r--src/test/ui/coercion/coerce-reborrow-mut-ptr-arg.rs (renamed from src/test/ui/coerce/coerce-reborrow-mut-ptr-arg.rs)0
-rw-r--r--src/test/ui/coercion/coerce-reborrow-mut-ptr-rcvr.rs (renamed from src/test/ui/coerce/coerce-reborrow-mut-ptr-rcvr.rs)0
-rw-r--r--src/test/ui/coercion/coerce-reborrow-mut-vec-arg.rs (renamed from src/test/ui/coerce/coerce-reborrow-mut-vec-arg.rs)0
-rw-r--r--src/test/ui/coercion/coerce-reborrow-mut-vec-rcvr.rs (renamed from src/test/ui/coerce/coerce-reborrow-mut-vec-rcvr.rs)0
-rw-r--r--src/test/ui/coercion/coerce-to-bang-cast.rs2
-rw-r--r--src/test/ui/coercion/coerce-to-bang-cast.stderr4
-rw-r--r--src/test/ui/coercion/coerce-unify-return.rs (renamed from src/test/ui/coerce/coerce-unify-return.rs)0
-rw-r--r--src/test/ui/coercion/coerce-unify.rs (renamed from src/test/ui/coerce/coerce-unify.rs)0
-rw-r--r--src/test/ui/coercion/coerce-unsize-subtype.rs (renamed from src/test/ui/coerce/coerce-unsize-subtype.rs)0
-rw-r--r--src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs1
-rw-r--r--src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr15
-rw-r--r--src/test/ui/consts/const-eval/issue-65394.rs2
-rw-r--r--src/test/ui/consts/const-eval/issue-65394.stderr9
-rw-r--r--src/test/ui/consts/const-multi-ref.rs2
-rw-r--r--src/test/ui/consts/const-multi-ref.stderr9
-rw-r--r--src/test/ui/consts/const-mut-refs/const_mut_address_of.rs4
-rw-r--r--src/test/ui/consts/const-mut-refs/const_mut_address_of.stderr15
-rw-r--r--src/test/ui/consts/const-mut-refs/const_mut_refs.rs5
-rw-r--r--src/test/ui/consts/const-mut-refs/const_mut_refs.stderr21
-rw-r--r--src/test/ui/consts/const_let_assign3.rs4
-rw-r--r--src/test/ui/consts/const_let_assign3.stderr16
-rw-r--r--src/test/ui/consts/projection_qualif.mut_refs.stderr11
-rw-r--r--src/test/ui/consts/projection_qualif.rs2
-rw-r--r--src/test/ui/consts/projection_qualif.stock.stderr9
-rw-r--r--src/test/ui/consts/read_from_static_mut_ref.rs9
-rw-r--r--src/test/ui/consts/read_from_static_mut_ref.stderr9
-rw-r--r--src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr8
-rw-r--r--src/test/ui/consts/static_mut_containing_mut_ref2.rs3
-rw-r--r--src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr9
-rw-r--r--src/test/ui/consts/trait_specialization.rs2
-rw-r--r--src/test/ui/consts/trait_specialization.stderr11
-rw-r--r--src/test/ui/error-codes/E0017.rs8
-rw-r--r--src/test/ui/error-codes/E0017.stderr30
-rw-r--r--src/test/ui/error-codes/E0388.rs8
-rw-r--r--src/test/ui/error-codes/E0388.stderr23
-rw-r--r--src/test/ui/error-codes/E0520.rs1
-rw-r--r--src/test/ui/error-codes/E0520.stderr13
-rw-r--r--src/test/ui/impl-trait/equality-rpass.rs2
-rw-r--r--src/test/ui/impl-trait/equality-rpass.stderr11
-rw-r--r--src/test/ui/impl-trait/equality.rs2
-rw-r--r--src/test/ui/impl-trait/equality.stderr11
-rw-r--r--src/test/ui/impl-trait/equality2.rs2
-rw-r--r--src/test/ui/impl-trait/equality2.stderr11
-rw-r--r--src/test/ui/issues/issue-17718-const-bad-values.rs4
-rw-r--r--src/test/ui/issues/issue-17718-const-bad-values.stderr16
-rw-r--r--src/test/ui/issues/issue-23046.rs4
-rw-r--r--src/test/ui/issues/issue-23046.stderr13
-rw-r--r--src/test/ui/issues/issue-35376.rs1
-rw-r--r--src/test/ui/issues/issue-35376.stderr11
-rw-r--r--src/test/ui/issues/issue-38091.rs1
-rw-r--r--src/test/ui/issues/issue-38091.stderr11
-rw-r--r--src/test/ui/issues/issue-46604.rs2
-rw-r--r--src/test/ui/issues/issue-46604.stderr9
-rw-r--r--src/test/ui/issues/issue-55380.rs2
-rw-r--r--src/test/ui/issues/issue-55380.stderr11
-rw-r--r--src/test/ui/issues/issue-72690.rs62
-rw-r--r--src/test/ui/issues/issue-72690.stderr88
-rw-r--r--src/test/ui/overlap-doesnt-conflict-with-specialization.rs2
-rw-r--r--src/test/ui/overlap-doesnt-conflict-with-specialization.stderr11
-rw-r--r--src/test/ui/parser/assoc-static-semantic-fail.rs1
-rw-r--r--src/test/ui/parser/assoc-static-semantic-fail.stderr59
-rw-r--r--src/test/ui/parser/default.rs1
-rw-r--r--src/test/ui/parser/default.stderr19
-rw-r--r--src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs2
-rw-r--r--src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr11
-rw-r--r--src/test/ui/sanitize/incompatible.rs6
-rw-r--r--src/test/ui/sanitize/incompatible.stderr4
-rw-r--r--src/test/ui/sanitize/unsupported-target.rs3
-rw-r--r--src/test/ui/sanitize/unsupported-target.stderr2
-rw-r--r--src/test/ui/specialization/assoc-ty-graph-cycle.rs2
-rw-r--r--src/test/ui/specialization/assoc-ty-graph-cycle.stderr11
-rw-r--r--src/test/ui/specialization/cross-crate-defaults.rs2
-rw-r--r--src/test/ui/specialization/cross-crate-defaults.stderr11
-rw-r--r--src/test/ui/specialization/defaultimpl/allowed-cross-crate.rs2
-rw-r--r--src/test/ui/specialization/defaultimpl/allowed-cross-crate.stderr11
-rw-r--r--src/test/ui/specialization/defaultimpl/out-of-order.rs2
-rw-r--r--src/test/ui/specialization/defaultimpl/out-of-order.stderr11
-rw-r--r--src/test/ui/specialization/defaultimpl/overlap-projection.rs2
-rw-r--r--src/test/ui/specialization/defaultimpl/overlap-projection.stderr11
-rw-r--r--src/test/ui/specialization/defaultimpl/projection.rs2
-rw-r--r--src/test/ui/specialization/defaultimpl/projection.stderr11
-rw-r--r--src/test/ui/specialization/defaultimpl/specialization-no-default.rs2
-rw-r--r--src/test/ui/specialization/defaultimpl/specialization-no-default.stderr11
-rw-r--r--src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs2
-rw-r--r--src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr11
-rw-r--r--src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs2
-rw-r--r--src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr11
-rw-r--r--src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs2
-rw-r--r--src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr11
-rw-r--r--src/test/ui/specialization/defaultimpl/specialization-wfcheck.rs2
-rw-r--r--src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr11
-rw-r--r--src/test/ui/specialization/defaultimpl/validation.rs2
-rw-r--r--src/test/ui/specialization/defaultimpl/validation.stderr11
-rw-r--r--src/test/ui/specialization/issue-36804.rs2
-rw-r--r--src/test/ui/specialization/issue-36804.stderr11
-rw-r--r--src/test/ui/specialization/issue-39448.rs2
-rw-r--r--src/test/ui/specialization/issue-39448.stderr11
-rw-r--r--src/test/ui/specialization/issue-39618.rs2
-rw-r--r--src/test/ui/specialization/issue-39618.stderr11
-rw-r--r--src/test/ui/specialization/issue-50452.rs2
-rw-r--r--src/test/ui/specialization/issue-50452.stderr11
-rw-r--r--src/test/ui/specialization/issue-52050.rs2
-rw-r--r--src/test/ui/specialization/issue-52050.stderr11
-rw-r--r--src/test/ui/specialization/issue-63716-parse-async.rs2
-rw-r--r--src/test/ui/specialization/issue-63716-parse-async.stderr11
-rw-r--r--src/test/ui/specialization/issue-70442.rs2
-rw-r--r--src/test/ui/specialization/issue-70442.stderr11
-rw-r--r--src/test/ui/specialization/non-defaulted-item-fail.rs1
-rw-r--r--src/test/ui/specialization/non-defaulted-item-fail.stderr23
-rw-r--r--src/test/ui/specialization/specialization-allowed-cross-crate.rs2
-rw-r--r--src/test/ui/specialization/specialization-allowed-cross-crate.stderr11
-rw-r--r--src/test/ui/specialization/specialization-assoc-fns.rs2
-rw-r--r--src/test/ui/specialization/specialization-assoc-fns.stderr11
-rw-r--r--src/test/ui/specialization/specialization-basics.rs2
-rw-r--r--src/test/ui/specialization/specialization-basics.stderr11
-rw-r--r--src/test/ui/specialization/specialization-cross-crate.rs2
-rw-r--r--src/test/ui/specialization/specialization-cross-crate.stderr11
-rw-r--r--src/test/ui/specialization/specialization-default-methods.rs2
-rw-r--r--src/test/ui/specialization/specialization-default-methods.stderr11
-rw-r--r--src/test/ui/specialization/specialization-default-projection.rs2
-rw-r--r--src/test/ui/specialization/specialization-default-projection.stderr11
-rw-r--r--src/test/ui/specialization/specialization-default-types.rs2
-rw-r--r--src/test/ui/specialization/specialization-default-types.stderr11
-rw-r--r--src/test/ui/specialization/specialization-no-default.rs2
-rw-r--r--src/test/ui/specialization/specialization-no-default.stderr11
-rw-r--r--src/test/ui/specialization/specialization-on-projection.rs2
-rw-r--r--src/test/ui/specialization/specialization-on-projection.stderr11
-rw-r--r--src/test/ui/specialization/specialization-out-of-order.rs2
-rw-r--r--src/test/ui/specialization/specialization-out-of-order.stderr11
-rw-r--r--src/test/ui/specialization/specialization-overlap-negative.rs2
-rw-r--r--src/test/ui/specialization/specialization-overlap-negative.stderr11
-rw-r--r--src/test/ui/specialization/specialization-overlap-projection.rs2
-rw-r--r--src/test/ui/specialization/specialization-overlap-projection.stderr11
-rw-r--r--src/test/ui/specialization/specialization-overlap.rs2
-rw-r--r--src/test/ui/specialization/specialization-overlap.stderr11
-rw-r--r--src/test/ui/specialization/specialization-polarity.rs2
-rw-r--r--src/test/ui/specialization/specialization-polarity.stderr11
-rw-r--r--src/test/ui/specialization/specialization-projection-alias.rs2
-rw-r--r--src/test/ui/specialization/specialization-projection-alias.stderr11
-rw-r--r--src/test/ui/specialization/specialization-projection.rs2
-rw-r--r--src/test/ui/specialization/specialization-projection.stderr11
-rw-r--r--src/test/ui/specialization/specialization-super-traits.rs2
-rw-r--r--src/test/ui/specialization/specialization-super-traits.stderr11
-rw-r--r--src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs2
-rw-r--r--src/test/ui/specialization/specialization-translate-projections-with-lifetimes.stderr11
-rw-r--r--src/test/ui/specialization/specialization-translate-projections-with-params.rs2
-rw-r--r--src/test/ui/specialization/specialization-translate-projections-with-params.stderr11
-rw-r--r--src/test/ui/specialization/specialization-translate-projections.rs2
-rw-r--r--src/test/ui/specialization/specialization-translate-projections.stderr11
-rw-r--r--src/test/ui/traits/negative-impls/negative-default-impls.rs1
-rw-r--r--src/test/ui/traits/negative-impls/negative-default-impls.stderr13
-rw-r--r--src/test/ui/traits/negative-impls/negative-specializes-negative.rs2
-rw-r--r--src/test/ui/traits/negative-impls/negative-specializes-negative.stderr11
-rw-r--r--src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs2
-rw-r--r--src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr11
-rw-r--r--src/test/ui/traits/negative-impls/negative-specializes-positive.rs2
-rw-r--r--src/test/ui/traits/negative-impls/negative-specializes-positive.stderr11
-rw-r--r--src/test/ui/traits/negative-impls/positive-specializes-negative.rs2
-rw-r--r--src/test/ui/traits/negative-impls/positive-specializes-negative.stderr11
-rw-r--r--src/test/ui/traits/traits-inductive-overflow-lifetime.rs30
-rw-r--r--src/test/ui/traits/traits-inductive-overflow-lifetime.stderr14
-rw-r--r--src/test/ui/transmute-specialization.rs2
-rw-r--r--src/test/ui/transmute-specialization.stderr11
m---------src/tools/rls0
m---------src/tools/rustfmt36
274 files changed, 2491 insertions, 796 deletions
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 9c95de0a81e..c92082a9423 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -481,7 +481,7 @@ impl Step for Rustdoc {
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("src/tools/rustdoc")
+        run.path("src/tools/rustdoc").path("src/librustdoc")
     }
 
     fn make_run(run: RunConfig<'_>) {
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
index 7ebd8054ba0..5e2e04c063b 100644
--- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -12,8 +12,7 @@ This feature allows for use of one of following sanitizers:
 * [ThreadSanitizer][clang-tsan] a fast data race detector.
 
 To enable a sanitizer compile with `-Zsanitizer=address`, `-Zsanitizer=leak`,
-`-Zsanitizer=memory` or `-Zsanitizer=thread`. Only a single sanitizer can be
-enabled at a time.
+`-Zsanitizer=memory` or `-Zsanitizer=thread`.
 
 # AddressSanitizer
 
diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs
index fbfcdc3c1a9..530cf881f29 100644
--- a/src/libcore/iter/traits/iterator.rs
+++ b/src/libcore/iter/traits/iterator.rs
@@ -2265,7 +2265,7 @@ pub trait Iterator {
     }
 
     /// Applies function to the elements of iterator and returns
-    /// the first non-none result or the first error.
+    /// the first true result or the first error.
     ///
     /// # Examples
     ///
@@ -2286,19 +2286,26 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[unstable(feature = "try_find", reason = "new API", issue = "63178")]
-    fn try_find<F, E, R>(&mut self, mut f: F) -> Result<Option<Self::Item>, E>
+    fn try_find<F, R>(&mut self, f: F) -> Result<Option<Self::Item>, R::Error>
     where
         Self: Sized,
         F: FnMut(&Self::Item) -> R,
-        R: Try<Ok = bool, Error = E>,
-    {
-        self.try_fold((), move |(), x| match f(&x).into_result() {
-            Ok(false) => LoopState::Continue(()),
-            Ok(true) => LoopState::Break(Ok(x)),
-            Err(x) => LoopState::Break(Err(x)),
-        })
-        .break_value()
-        .transpose()
+        R: Try<Ok = bool>,
+    {
+        #[inline]
+        fn check<F, T, R>(mut f: F) -> impl FnMut((), T) -> LoopState<(), Result<T, R::Error>>
+        where
+            F: FnMut(&T) -> R,
+            R: Try<Ok = bool>,
+        {
+            move |(), x| match f(&x).into_result() {
+                Ok(false) => LoopState::Continue(()),
+                Ok(true) => LoopState::Break(Ok(x)),
+                Err(x) => LoopState::Break(Err(x)),
+            }
+        }
+
+        self.try_fold((), check(f)).break_value().transpose()
     }
 
     /// Searches for an element in an iterator, returning its index.
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 37ebf411280..4e55452a4c3 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -19,7 +19,7 @@
 #![feature(raw)]
 #![feature(sort_internals)]
 #![feature(slice_partition_at_index)]
-#![feature(specialization)]
+#![feature(min_specialization)]
 #![feature(step_trait)]
 #![feature(step_trait_ext)]
 #![feature(str_internals)]
diff --git a/src/librustc_arena/lib.rs b/src/librustc_arena/lib.rs
index 66c31cbebcc..6cf2db3e2da 100644
--- a/src/librustc_arena/lib.rs
+++ b/src/librustc_arena/lib.rs
@@ -22,6 +22,7 @@ extern crate alloc;
 use rustc_data_structures::cold_path;
 use smallvec::SmallVec;
 
+use std::alloc::Layout;
 use std::cell::{Cell, RefCell};
 use std::cmp;
 use std::intrinsics;
@@ -363,13 +364,15 @@ impl DroplessArena {
         }
     }
 
-    /// Allocates a byte slice with specified size and alignment from the
-    /// current memory chunk. Returns `None` if there is no free space left to
-    /// satisfy the request.
+    /// Allocates a byte slice with specified layout from the current memory
+    /// chunk. Returns `None` if there is no free space left to satisfy the
+    /// request.
     #[inline]
-    fn alloc_raw_without_grow(&self, bytes: usize, align: usize) -> Option<*mut u8> {
+    fn alloc_raw_without_grow(&self, layout: Layout) -> Option<*mut u8> {
         let ptr = self.ptr.get() as usize;
         let end = self.end.get() as usize;
+        let align = layout.align();
+        let bytes = layout.size();
         // The allocation request fits into the current chunk iff:
         //
         // let aligned = align_to(ptr, align);
@@ -390,15 +393,15 @@ impl DroplessArena {
     }
 
     #[inline]
-    pub fn alloc_raw(&self, bytes: usize, align: usize) -> *mut u8 {
-        assert!(bytes != 0);
+    pub fn alloc_raw(&self, layout: Layout) -> *mut u8 {
+        assert!(layout.size() != 0);
         loop {
-            if let Some(a) = self.alloc_raw_without_grow(bytes, align) {
+            if let Some(a) = self.alloc_raw_without_grow(layout) {
                 break a;
             }
             // No free space left. Allocate a new chunk to satisfy the request.
             // On failure the grow will panic or abort.
-            self.grow(bytes);
+            self.grow(layout.size());
         }
     }
 
@@ -406,7 +409,7 @@ impl DroplessArena {
     pub fn alloc<T>(&self, object: T) -> &mut T {
         assert!(!mem::needs_drop::<T>());
 
-        let mem = self.alloc_raw(mem::size_of::<T>(), mem::align_of::<T>()) as *mut T;
+        let mem = self.alloc_raw(Layout::for_value::<T>(&object)) as *mut T;
 
         unsafe {
             // Write into uninitialized memory.
@@ -431,7 +434,7 @@ impl DroplessArena {
         assert!(mem::size_of::<T>() != 0);
         assert!(!slice.is_empty());
 
-        let mem = self.alloc_raw(slice.len() * mem::size_of::<T>(), mem::align_of::<T>()) as *mut T;
+        let mem = self.alloc_raw(Layout::for_value::<[T]>(slice)) as *mut T;
 
         unsafe {
             mem.copy_from_nonoverlapping(slice.as_ptr(), slice.len());
@@ -477,8 +480,8 @@ impl DroplessArena {
                 if len == 0 {
                     return &mut [];
                 }
-                let size = len.checked_mul(mem::size_of::<T>()).unwrap();
-                let mem = self.alloc_raw(size, mem::align_of::<T>()) as *mut T;
+
+                let mem = self.alloc_raw(Layout::array::<T>(len).unwrap()) as *mut T;
                 unsafe { self.write_from_iter(iter, len, mem) }
             }
             (_, _) => {
@@ -491,9 +494,8 @@ impl DroplessArena {
                     // the content of the SmallVec
                     unsafe {
                         let len = vec.len();
-                        let start_ptr = self
-                            .alloc_raw(len * mem::size_of::<T>(), mem::align_of::<T>())
-                            as *mut T;
+                        let start_ptr =
+                            self.alloc_raw(Layout::for_value::<[T]>(vec.as_slice())) as *mut T;
                         vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
                         vec.set_len(0);
                         slice::from_raw_parts_mut(start_ptr, len)
@@ -537,7 +539,7 @@ pub struct DropArena {
 impl DropArena {
     #[inline]
     pub unsafe fn alloc<T>(&self, object: T) -> &mut T {
-        let mem = self.arena.alloc_raw(mem::size_of::<T>(), mem::align_of::<T>()) as *mut T;
+        let mem = self.arena.alloc_raw(Layout::new::<T>()) as *mut T;
         // Write into uninitialized memory.
         ptr::write(mem, object);
         let result = &mut *mem;
@@ -557,10 +559,7 @@ impl DropArena {
         }
         let len = vec.len();
 
-        let start_ptr = self
-            .arena
-            .alloc_raw(len.checked_mul(mem::size_of::<T>()).unwrap(), mem::align_of::<T>())
-            as *mut T;
+        let start_ptr = self.arena.alloc_raw(Layout::array::<T>(len).unwrap()) as *mut T;
 
         let mut destructors = self.destructors.borrow_mut();
         // Reserve space for the destructors so we can't panic while adding them
diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs
index a4e17a5f675..6234ade8a16 100644
--- a/src/librustc_codegen_llvm/attributes.rs
+++ b/src/librustc_codegen_llvm/attributes.rs
@@ -11,7 +11,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::ty::layout::HasTyCtxt;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_session::config::{OptLevel, Sanitizer};
+use rustc_session::config::{OptLevel, SanitizerSet};
 use rustc_session::Session;
 
 use crate::attributes;
@@ -45,26 +45,16 @@ fn inline(cx: &CodegenCx<'ll, '_>, val: &'ll Value, inline: InlineAttr) {
 
 /// Apply LLVM sanitize attributes.
 #[inline]
-pub fn sanitize(cx: &CodegenCx<'ll, '_>, codegen_fn_flags: CodegenFnAttrFlags, llfn: &'ll Value) {
-    if let Some(ref sanitizer) = cx.tcx.sess.opts.debugging_opts.sanitizer {
-        match *sanitizer {
-            Sanitizer::Address => {
-                if !codegen_fn_flags.contains(CodegenFnAttrFlags::NO_SANITIZE_ADDRESS) {
-                    llvm::Attribute::SanitizeAddress.apply_llfn(Function, llfn);
-                }
-            }
-            Sanitizer::Memory => {
-                if !codegen_fn_flags.contains(CodegenFnAttrFlags::NO_SANITIZE_MEMORY) {
-                    llvm::Attribute::SanitizeMemory.apply_llfn(Function, llfn);
-                }
-            }
-            Sanitizer::Thread => {
-                if !codegen_fn_flags.contains(CodegenFnAttrFlags::NO_SANITIZE_THREAD) {
-                    llvm::Attribute::SanitizeThread.apply_llfn(Function, llfn);
-                }
-            }
-            Sanitizer::Leak => {}
-        }
+pub fn sanitize(cx: &CodegenCx<'ll, '_>, no_sanitize: SanitizerSet, llfn: &'ll Value) {
+    let enabled = cx.tcx.sess.opts.debugging_opts.sanitizer - no_sanitize;
+    if enabled.contains(SanitizerSet::ADDRESS) {
+        llvm::Attribute::SanitizeAddress.apply_llfn(Function, llfn);
+    }
+    if enabled.contains(SanitizerSet::MEMORY) {
+        llvm::Attribute::SanitizeMemory.apply_llfn(Function, llfn);
+    }
+    if enabled.contains(SanitizerSet::THREAD) {
+        llvm::Attribute::SanitizeThread.apply_llfn(Function, llfn);
     }
 }
 
@@ -123,9 +113,14 @@ fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
     // Currently stack probes seem somewhat incompatible with the address
     // sanitizer and thread sanitizer. With asan we're already protected from
     // stack overflow anyway so we don't really need stack probes regardless.
-    match cx.sess().opts.debugging_opts.sanitizer {
-        Some(Sanitizer::Address | Sanitizer::Thread) => return,
-        _ => {}
+    if cx
+        .sess()
+        .opts
+        .debugging_opts
+        .sanitizer
+        .intersects(SanitizerSet::ADDRESS | SanitizerSet::THREAD)
+    {
+        return;
     }
 
     // probestack doesn't play nice either with `-C profile-generate`.
@@ -296,7 +291,7 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
     if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR) {
         Attribute::NoAlias.apply_llfn(llvm::AttributePlace::ReturnValue, llfn);
     }
-    sanitize(cx, codegen_fn_attrs.flags, llfn);
+    sanitize(cx, codegen_fn_attrs.no_sanitize, llfn);
 
     // Always annotate functions with the target-cpu they are compiled for.
     // Without this, ThinLTO won't inline Rust functions into Clang generated
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index 26f5334668b..868ce876a81 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -21,7 +21,7 @@ use rustc_fs_util::{link_or_copy, path_to_c_string};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::bug;
 use rustc_middle::ty::TyCtxt;
-use rustc_session::config::{self, Lto, OutputType, Passes, Sanitizer, SwitchWithOptPath};
+use rustc_session::config::{self, Lto, OutputType, Passes, SanitizerSet, SwitchWithOptPath};
 use rustc_session::Session;
 use rustc_span::InnerSpan;
 use rustc_target::spec::{CodeModel, RelocModel};
@@ -394,12 +394,13 @@ pub(crate) unsafe fn optimize_with_new_llvm_pass_manager(
     let is_lto = opt_stage == llvm::OptStage::ThinLTO || opt_stage == llvm::OptStage::FatLTO;
     // Sanitizer instrumentation is only inserted during the pre-link optimization stage.
     let sanitizer_options = if !is_lto {
-        config.sanitizer.as_ref().map(|s| llvm::SanitizerOptions {
-            sanitize_memory: *s == Sanitizer::Memory,
-            sanitize_thread: *s == Sanitizer::Thread,
-            sanitize_address: *s == Sanitizer::Address,
-            sanitize_recover: config.sanitizer_recover.contains(s),
+        Some(llvm::SanitizerOptions {
+            sanitize_address: config.sanitizer.contains(SanitizerSet::ADDRESS),
+            sanitize_address_recover: config.sanitizer_recover.contains(SanitizerSet::ADDRESS),
+            sanitize_memory: config.sanitizer.contains(SanitizerSet::MEMORY),
+            sanitize_memory_recover: config.sanitizer_recover.contains(SanitizerSet::MEMORY),
             sanitize_memory_track_origins: config.sanitizer_memory_track_origins as c_int,
+            sanitize_thread: config.sanitizer.contains(SanitizerSet::THREAD),
         })
     } else {
         None
@@ -600,25 +601,18 @@ pub(crate) unsafe fn optimize(
 }
 
 unsafe fn add_sanitizer_passes(config: &ModuleConfig, passes: &mut Vec<&'static mut llvm::Pass>) {
-    let sanitizer = match &config.sanitizer {
-        None => return,
-        Some(s) => s,
-    };
-
-    let recover = config.sanitizer_recover.contains(sanitizer);
-    match sanitizer {
-        Sanitizer::Address => {
-            passes.push(llvm::LLVMRustCreateAddressSanitizerFunctionPass(recover));
-            passes.push(llvm::LLVMRustCreateModuleAddressSanitizerPass(recover));
-        }
-        Sanitizer::Memory => {
-            let track_origins = config.sanitizer_memory_track_origins as c_int;
-            passes.push(llvm::LLVMRustCreateMemorySanitizerPass(track_origins, recover));
-        }
-        Sanitizer::Thread => {
-            passes.push(llvm::LLVMRustCreateThreadSanitizerPass());
-        }
-        Sanitizer::Leak => {}
+    if config.sanitizer.contains(SanitizerSet::ADDRESS) {
+        let recover = config.sanitizer_recover.contains(SanitizerSet::ADDRESS);
+        passes.push(llvm::LLVMRustCreateAddressSanitizerFunctionPass(recover));
+        passes.push(llvm::LLVMRustCreateModuleAddressSanitizerPass(recover));
+    }
+    if config.sanitizer.contains(SanitizerSet::MEMORY) {
+        let track_origins = config.sanitizer_memory_track_origins as c_int;
+        let recover = config.sanitizer_recover.contains(SanitizerSet::MEMORY);
+        passes.push(llvm::LLVMRustCreateMemorySanitizerPass(track_origins, recover));
+    }
+    if config.sanitizer.contains(SanitizerSet::THREAD) {
+        passes.push(llvm::LLVMRustCreateThreadSanitizerPass());
     }
 }
 
diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs
index 3e17a51528e..e99fb8dcae1 100644
--- a/src/librustc_codegen_llvm/base.rs
+++ b/src/librustc_codegen_llvm/base.rs
@@ -29,12 +29,12 @@ use rustc_codegen_ssa::traits::*;
 use rustc_codegen_ssa::{ModuleCodegen, ModuleKind};
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_middle::dep_graph;
-use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
+use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
 use rustc_middle::middle::cstore::EncodedMetadata;
 use rustc_middle::middle::exported_symbols;
 use rustc_middle::mir::mono::{Linkage, Visibility};
 use rustc_middle::ty::TyCtxt;
-use rustc_session::config::DebugInfo;
+use rustc_session::config::{DebugInfo, SanitizerSet};
 use rustc_span::symbol::Symbol;
 
 use std::ffi::CString;
@@ -132,7 +132,7 @@ pub fn compile_codegen_unit(
             // If this codegen unit contains the main function, also create the
             // wrapper here
             if let Some(entry) = maybe_create_entry_wrapper::<Builder<'_, '_, '_>>(&cx) {
-                attributes::sanitize(&cx, CodegenFnAttrFlags::empty(), entry);
+                attributes::sanitize(&cx, SanitizerSet::empty(), entry);
             }
 
             // Run replace-all-uses-with for statics that need it
diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs
index a5cda5949ee..64140747871 100644
--- a/src/librustc_codegen_llvm/common.rs
+++ b/src/librustc_codegen_llvm/common.rs
@@ -206,7 +206,7 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         let len = s.as_str().len();
         let cs = consts::ptrcast(
             self.const_cstr(s, false),
-            self.type_ptr_to(self.layout_of(self.tcx.mk_str()).llvm_type(self)),
+            self.type_ptr_to(self.layout_of(self.tcx.types.str_).llvm_type(self)),
         );
         (cs, self.const_usize(len as u64))
     }
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index 372fb17573a..8063d97aa73 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -439,11 +439,12 @@ pub enum OptStage {
 /// LLVMRustSanitizerOptions
 #[repr(C)]
 pub struct SanitizerOptions {
-    pub sanitize_memory: bool,
-    pub sanitize_thread: bool,
     pub sanitize_address: bool,
-    pub sanitize_recover: bool,
+    pub sanitize_address_recover: bool,
+    pub sanitize_memory: bool,
+    pub sanitize_memory_recover: bool,
     pub sanitize_memory_track_origins: c_int,
+    pub sanitize_thread: bool,
 }
 
 /// LLVMRelocMode
diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index 1eef86f6c93..c7a58d9f2a2 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -4,7 +4,7 @@ use rustc_hir::def_id::CrateNum;
 use rustc_middle::middle::cstore::{EncodedMetadata, LibSource, NativeLib};
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_session::config::{self, CFGuard, CrateType, DebugInfo};
-use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, Sanitizer};
+use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SanitizerSet};
 use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
 use rustc_session::search_paths::PathKind;
 use rustc_session::utils::NativeLibKind;
@@ -766,23 +766,26 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
     }
 }
 
-fn link_sanitizer_runtime(sess: &Session, crate_type: CrateType, linker: &mut dyn Linker) {
-    let sanitizer = match &sess.opts.debugging_opts.sanitizer {
-        Some(s) => s,
-        None => return,
-    };
-
+fn link_sanitizers(sess: &Session, crate_type: CrateType, linker: &mut dyn Linker) {
     if crate_type != CrateType::Executable {
         return;
     }
+    let sanitizer = sess.opts.debugging_opts.sanitizer;
+    if sanitizer.contains(SanitizerSet::ADDRESS) {
+        link_sanitizer_runtime(sess, linker, "asan");
+    }
+    if sanitizer.contains(SanitizerSet::LEAK) {
+        link_sanitizer_runtime(sess, linker, "lsan");
+    }
+    if sanitizer.contains(SanitizerSet::MEMORY) {
+        link_sanitizer_runtime(sess, linker, "msan");
+    }
+    if sanitizer.contains(SanitizerSet::THREAD) {
+        link_sanitizer_runtime(sess, linker, "tsan");
+    }
+}
 
-    let name = match sanitizer {
-        Sanitizer::Address => "asan",
-        Sanitizer::Leak => "lsan",
-        Sanitizer::Memory => "msan",
-        Sanitizer::Thread => "tsan",
-    };
-
+fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) {
     let default_sysroot = filesearch::get_or_default_sysroot();
     let default_tlib =
         filesearch::make_target_lib_path(&default_sysroot, sess.opts.target_triple.triple());
@@ -1555,9 +1558,10 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
 
     // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
     if sess.target.target.options.is_like_fuchsia && crate_type == CrateType::Executable {
-        let prefix = match sess.opts.debugging_opts.sanitizer {
-            Some(Sanitizer::Address) => "asan/",
-            _ => "",
+        let prefix = if sess.opts.debugging_opts.sanitizer.contains(SanitizerSet::ADDRESS) {
+            "asan/"
+        } else {
+            ""
         };
         cmd.arg(format!("--dynamic-linker={}ld.so.1", prefix));
     }
@@ -1581,7 +1585,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
     }
 
     // OBJECT-FILES-YES, AUDIT-ORDER
-    link_sanitizer_runtime(sess, crate_type, cmd);
+    link_sanitizers(sess, crate_type, cmd);
 
     // OBJECT-FILES-NO, AUDIT-ORDER
     // Linker plugins should be specified early in the list of arguments
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index 98f7da8361c..217ad57ddc9 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -15,7 +15,7 @@ use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
 use rustc_middle::ty::Instance;
 use rustc_middle::ty::{SymbolName, TyCtxt};
-use rustc_session::config::{CrateType, Sanitizer};
+use rustc_session::config::{CrateType, SanitizerSet};
 
 pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
     crates_export_threshold(&tcx.sess.crate_types())
@@ -204,7 +204,7 @@ fn exported_symbols_provider_local(
         }));
     }
 
-    if let Some(Sanitizer::Memory) = tcx.sess.opts.debugging_opts.sanitizer {
+    if tcx.sess.opts.debugging_opts.sanitizer.contains(SanitizerSet::MEMORY) {
         // Similar to profiling, preserve weak msan symbol during LTO.
         const MSAN_WEAK_SYMBOLS: [&str; 2] = ["__msan_track_origins", "__msan_keep_going"];
 
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index 49054765b9d..23e0b9344ec 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -29,7 +29,7 @@ use rustc_middle::middle::exported_symbols::SymbolExportLevel;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::cgu_reuse_tracker::CguReuseTracker;
 use rustc_session::config::{self, CrateType, Lto, OutputFilenames, OutputType};
-use rustc_session::config::{Passes, Sanitizer, SwitchWithOptPath};
+use rustc_session::config::{Passes, SanitizerSet, SwitchWithOptPath};
 use rustc_session::Session;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{sym, Symbol};
@@ -86,8 +86,8 @@ pub struct ModuleConfig {
     pub pgo_gen: SwitchWithOptPath,
     pub pgo_use: Option<PathBuf>,
 
-    pub sanitizer: Option<Sanitizer>,
-    pub sanitizer_recover: Vec<Sanitizer>,
+    pub sanitizer: SanitizerSet,
+    pub sanitizer_recover: SanitizerSet,
     pub sanitizer_memory_track_origins: usize,
 
     // Flags indicating which outputs to produce.
@@ -195,10 +195,10 @@ impl ModuleConfig {
             ),
             pgo_use: if_regular!(sess.opts.cg.profile_use.clone(), None),
 
-            sanitizer: if_regular!(sess.opts.debugging_opts.sanitizer.clone(), None),
+            sanitizer: if_regular!(sess.opts.debugging_opts.sanitizer, SanitizerSet::empty()),
             sanitizer_recover: if_regular!(
-                sess.opts.debugging_opts.sanitizer_recover.clone(),
-                vec![]
+                sess.opts.debugging_opts.sanitizer_recover,
+                SanitizerSet::empty()
             ),
             sanitizer_memory_track_origins: if_regular!(
                 sess.opts.debugging_opts.sanitizer_memory_track_origins,
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index 997762efcb3..738b3bc7539 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -444,6 +444,7 @@ E0760: include_str!("./error_codes/E0760.md"),
 E0761: include_str!("./error_codes/E0761.md"),
 E0762: include_str!("./error_codes/E0762.md"),
 E0763: include_str!("./error_codes/E0763.md"),
+E0764: include_str!("./error_codes/E0764.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
diff --git a/src/librustc_error_codes/error_codes/E0668.md b/src/librustc_error_codes/error_codes/E0668.md
index 3b43a1bcae9..b6fedfe53fc 100644
--- a/src/librustc_error_codes/error_codes/E0668.md
+++ b/src/librustc_error_codes/error_codes/E0668.md
@@ -1,11 +1,7 @@
 Malformed inline assembly rejected by LLVM.
 
-LLVM checks the validity of the constraints and the assembly string passed to
-it. This error implies that LLVM seems something wrong with the inline
-assembly call.
+Erroneous code example:
 
-In particular, it can happen if you forgot the closing bracket of a register
-constraint (see issue #51430):
 ```compile_fail,E0668
 #![feature(llvm_asm)]
 
@@ -17,3 +13,10 @@ fn main() {
     }
 }
 ```
+
+LLVM checks the validity of the constraints and the assembly string passed to
+it. This error implies that LLVM seems something wrong with the inline
+assembly call.
+
+In particular, it can happen if you forgot the closing bracket of a register
+constraint (see issue #51430), like in the previous code example.
diff --git a/src/librustc_error_codes/error_codes/E0670.md b/src/librustc_error_codes/error_codes/E0670.md
index 2026370bec3..74c1af06cf4 100644
--- a/src/librustc_error_codes/error_codes/E0670.md
+++ b/src/librustc_error_codes/error_codes/E0670.md
@@ -1,6 +1,6 @@
 Rust 2015 does not permit the use of `async fn`.
 
-Example of erroneous code:
+Erroneous code example:
 
 ```compile_fail,E0670
 async fn foo() {}
diff --git a/src/librustc_error_codes/error_codes/E0764.md b/src/librustc_error_codes/error_codes/E0764.md
new file mode 100644
index 00000000000..e9061f988ac
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0764.md
@@ -0,0 +1,39 @@
+Mutable references (`&mut`) can only be used in constant functions, not statics
+or constants. This limitation exists to prevent the creation of constants that
+have a mutable reference in their final value. If you had a constant of `&mut
+i32` type, you could modify the value through that reference, making the
+constant essentially mutable. While there could be a more fine-grained scheme
+in the future that allows mutable references if they are not "leaked" to the
+final value, a more conservative approach was chosen for now. `const fn` do not
+have this problem, as the borrow checker will prevent the `const fn` from
+returning new mutable references.
+
+Erroneous code example:
+
+```compile_fail,E0764
+#![feature(const_fn)]
+#![feature(const_mut_refs)]
+
+fn main() {
+    const OH_NO: &'static mut usize = &mut 1; // error!
+}
+```
+
+Remember: you cannot use a function call inside a constant or static. However,
+you can totally use it in constant functions:
+
+```
+#![feature(const_fn)]
+#![feature(const_mut_refs)]
+
+const fn foo(x: usize) -> usize {
+    let mut y = 1;
+    let z = &mut y;
+    *z += x;
+    y
+}
+
+fn main() {
+    const FOO: usize = foo(10); // ok!
+}
+```
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index d186f35a12b..7aadf58243f 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -596,4 +596,5 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
     sym::raw_dylib,
     sym::const_trait_impl,
     sym::const_trait_bound_opt_out,
+    sym::specialization,
 ];
diff --git a/src/librustc_infer/infer/canonical/canonicalizer.rs b/src/librustc_infer/infer/canonical/canonicalizer.rs
index 427cc55a428..2dc803b9595 100644
--- a/src/librustc_infer/infer/canonical/canonicalizer.rs
+++ b/src/librustc_infer/infer/canonical/canonicalizer.rs
@@ -314,18 +314,19 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> {
             }
 
             ty::ReVar(vid) => {
-                let r = self
+                let resolved_vid = self
                     .infcx
                     .unwrap()
                     .inner
                     .borrow_mut()
                     .unwrap_region_constraints()
-                    .opportunistic_resolve_var(self.tcx, vid);
+                    .opportunistic_resolve_var(vid);
                 debug!(
                     "canonical: region var found with vid {:?}, \
                      opportunistically resolved to {:?}",
                     vid, r
                 );
+                let r = self.tcx.reuse_or_mk_region(r, ty::ReVar(resolved_vid));
                 self.canonicalize_region_mode.canonicalize_free_region(self, r)
             }
 
diff --git a/src/librustc_infer/infer/error_reporting/need_type_info.rs b/src/librustc_infer/infer/error_reporting/need_type_info.rs
index 1361d5bede6..1687bcc1556 100644
--- a/src/librustc_infer/infer/error_reporting/need_type_info.rs
+++ b/src/librustc_infer/infer/error_reporting/need_type_info.rs
@@ -88,6 +88,17 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
         if let (None, Some(ty)) =
             (self.found_local_pattern, self.node_ty_contains_target(local.hir_id))
         {
+            // FIXME: There's a trade-off here - we can either check that our target span
+            // is contained in `local.span` or not. If we choose to check containment
+            // we can avoid some spurious suggestions (see #72690), but we lose
+            // the ability to report on things like:
+            //
+            // ```
+            // let x = vec![];
+            // ```
+            //
+            // because the target span will be in the macro expansion of `vec![]`.
+            // At present we choose not to check containment.
             self.found_local_pattern = Some(&*local.pat);
             self.found_node_ty = Some(ty);
         }
@@ -99,8 +110,10 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
             if let (None, Some(ty)) =
                 (self.found_arg_pattern, self.node_ty_contains_target(param.hir_id))
             {
-                self.found_arg_pattern = Some(&*param.pat);
-                self.found_node_ty = Some(ty);
+                if self.target_span.contains(param.pat.span) {
+                    self.found_arg_pattern = Some(&*param.pat);
+                    self.found_node_ty = Some(ty);
+                }
             }
         }
         intravisit::walk_body(self, body);
diff --git a/src/librustc_infer/infer/region_constraints/mod.rs b/src/librustc_infer/infer/region_constraints/mod.rs
index 626774617a6..90d61a78f9b 100644
--- a/src/librustc_infer/infer/region_constraints/mod.rs
+++ b/src/librustc_infer/infer/region_constraints/mod.rs
@@ -50,10 +50,10 @@ pub struct RegionConstraintStorage<'tcx> {
     /// R1 <= R2 and R2 <= R1 and (b) we unify the two regions in this
     /// table. You can then call `opportunistic_resolve_var` early
     /// which will map R1 and R2 to some common region (i.e., either
-    /// R1 or R2). This is important when dropck and other such code
-    /// is iterating to a fixed point, because otherwise we sometimes
-    /// would wind up with a fresh stream of region variables that
-    /// have been equated but appear distinct.
+    /// R1 or R2). This is important when fulfillment, dropck and other such
+    /// code is iterating to a fixed point, because otherwise we sometimes
+    /// would wind up with a fresh stream of region variables that have been
+    /// equated but appear distinct.
     pub(super) unification_table: ut::UnificationTableStorage<ty::RegionVid>,
 
     /// a flag set to true when we perform any unifications; this is used
@@ -714,13 +714,8 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
         }
     }
 
-    pub fn opportunistic_resolve_var(
-        &mut self,
-        tcx: TyCtxt<'tcx>,
-        rid: RegionVid,
-    ) -> ty::Region<'tcx> {
-        let vid = self.unification_table().probe_value(rid).min_vid;
-        tcx.mk_region(ty::ReVar(vid))
+    pub fn opportunistic_resolve_var(&mut self, rid: RegionVid) -> ty::RegionVid {
+        self.unification_table().probe_value(rid).min_vid
     }
 
     fn combine_map(&mut self, t: CombineMapType) -> &mut CombineMap<'tcx> {
diff --git a/src/librustc_infer/infer/resolve.rs b/src/librustc_infer/infer/resolve.rs
index df166d21a36..74f365ced23 100644
--- a/src/librustc_infer/infer/resolve.rs
+++ b/src/librustc_infer/infer/resolve.rs
@@ -46,51 +46,56 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> {
     }
 }
 
-/// The opportunistic type and region resolver is similar to the
-/// opportunistic type resolver, but also opportunistically resolves
-/// regions. It is useful for canonicalization.
-pub struct OpportunisticTypeAndRegionResolver<'a, 'tcx> {
+/// The opportunistic region resolver opportunistically resolves regions
+/// variables to the variable with the least variable id. It is used when
+/// normlizing projections to avoid hitting the recursion limit by creating
+/// many versions of a predicate for types that in the end have to unify.
+///
+/// If you want to resolve type and const variables as well, call
+/// [InferCtxt::resolve_vars_if_possible] first.
+pub struct OpportunisticRegionResolver<'a, 'tcx> {
     infcx: &'a InferCtxt<'a, 'tcx>,
 }
 
-impl<'a, 'tcx> OpportunisticTypeAndRegionResolver<'a, 'tcx> {
+impl<'a, 'tcx> OpportunisticRegionResolver<'a, 'tcx> {
     pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self {
-        OpportunisticTypeAndRegionResolver { infcx }
+        OpportunisticRegionResolver { infcx }
     }
 }
 
-impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticTypeAndRegionResolver<'a, 'tcx> {
+impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> {
     fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
         self.infcx.tcx
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if !t.needs_infer() {
+        if !t.has_infer_regions() {
             t // micro-optimize -- if there is nothing in this type that this fold affects...
         } else {
-            let t0 = self.infcx.shallow_resolve(t);
-            t0.super_fold_with(self)
+            t.super_fold_with(self)
         }
     }
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         match *r {
-            ty::ReVar(rid) => self
-                .infcx
-                .inner
-                .borrow_mut()
-                .unwrap_region_constraints()
-                .opportunistic_resolve_var(self.tcx(), rid),
+            ty::ReVar(rid) => {
+                let resolved = self
+                    .infcx
+                    .inner
+                    .borrow_mut()
+                    .unwrap_region_constraints()
+                    .opportunistic_resolve_var(rid);
+                self.tcx().reuse_or_mk_region(r, ty::ReVar(resolved))
+            }
             _ => r,
         }
     }
 
     fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
-        if !ct.needs_infer() {
+        if !ct.has_infer_regions() {
             ct // micro-optimize -- if there is nothing in this const that this fold affects...
         } else {
-            let c0 = self.infcx.shallow_resolve(ct);
-            c0.super_fold_with(self)
+            ct.super_fold_with(self)
         }
     }
 }
diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs
index c2a7d1a4a61..a832c2decaa 100644
--- a/src/librustc_interface/tests.rs
+++ b/src/librustc_interface/tests.rs
@@ -6,7 +6,9 @@ use rustc_session::config::Strip;
 use rustc_session::config::{build_configuration, build_session_options, to_crate_config};
 use rustc_session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes};
 use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath};
-use rustc_session::config::{Externs, OutputType, OutputTypes, Sanitizer, SymbolManglingVersion};
+use rustc_session::config::{
+    Externs, OutputType, OutputTypes, SanitizerSet, SymbolManglingVersion,
+};
 use rustc_session::lint::Level;
 use rustc_session::search_paths::SearchPath;
 use rustc_session::utils::NativeLibKind;
@@ -569,9 +571,9 @@ fn test_debugging_options_tracking_hash() {
     tracked!(relro_level, Some(RelroLevel::Full));
     tracked!(report_delayed_bugs, true);
     tracked!(run_dsymutil, false);
-    tracked!(sanitizer, Some(Sanitizer::Address));
+    tracked!(sanitizer, SanitizerSet::ADDRESS);
     tracked!(sanitizer_memory_track_origins, 2);
-    tracked!(sanitizer_recover, vec![Sanitizer::Address]);
+    tracked!(sanitizer_recover, SanitizerSet::ADDRESS);
     tracked!(saturating_float_casts, Some(true));
     tracked!(share_generics, Some(true));
     tracked!(show_span, Some(String::from("abc")));
diff --git a/src/librustc_middle/middle/codegen_fn_attrs.rs b/src/librustc_middle/middle/codegen_fn_attrs.rs
index c480944069e..d2749f8529b 100644
--- a/src/librustc_middle/middle/codegen_fn_attrs.rs
+++ b/src/librustc_middle/middle/codegen_fn_attrs.rs
@@ -1,5 +1,6 @@
 use crate::mir::mono::Linkage;
 use rustc_attr::{InlineAttr, OptimizeAttr};
+use rustc_session::config::SanitizerSet;
 use rustc_span::symbol::Symbol;
 
 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
@@ -30,6 +31,9 @@ pub struct CodegenFnAttrs {
     /// The `#[link_section = "..."]` attribute, or what executable section this
     /// should be placed in.
     pub link_section: Option<Symbol>,
+    /// The `#[no_sanitize(...)]` attribute. Indicates sanitizers for which
+    /// instrumentation should be disabled inside the annotated function.
+    pub no_sanitize: SanitizerSet,
 }
 
 bitflags! {
@@ -69,20 +73,12 @@ bitflags! {
         const FFI_RETURNS_TWICE         = 1 << 10;
         /// `#[track_caller]`: allow access to the caller location
         const TRACK_CALLER              = 1 << 11;
-        /// `#[no_sanitize(address)]`: disables address sanitizer instrumentation
-        const NO_SANITIZE_ADDRESS = 1 << 12;
-        /// `#[no_sanitize(memory)]`: disables memory sanitizer instrumentation
-        const NO_SANITIZE_MEMORY  = 1 << 13;
-        /// `#[no_sanitize(thread)]`: disables thread sanitizer instrumentation
-        const NO_SANITIZE_THREAD  = 1 << 14;
-        /// All `#[no_sanitize(...)]` attributes.
-        const NO_SANITIZE_ANY = Self::NO_SANITIZE_ADDRESS.bits | Self::NO_SANITIZE_MEMORY.bits | Self::NO_SANITIZE_THREAD.bits;
         /// #[ffi_pure]: applies clang's `pure` attribute to a foreign function
         /// declaration.
-        const FFI_PURE = 1 << 15;
+        const FFI_PURE                  = 1 << 12;
         /// #[ffi_const]: applies clang's `const` attribute to a foreign function
         /// declaration.
-        const FFI_CONST = 1 << 16;
+        const FFI_CONST                 = 1 << 13;
     }
 }
 
@@ -98,6 +94,7 @@ impl CodegenFnAttrs {
             target_features: vec![],
             linkage: None,
             link_section: None,
+            no_sanitize: SanitizerSet::empty(),
         }
     }
 
diff --git a/src/librustc_middle/mir/query.rs b/src/librustc_middle/mir/query.rs
index d82faf3e5fb..1aae97cc2a8 100644
--- a/src/librustc_middle/mir/query.rs
+++ b/src/librustc_middle/mir/query.rs
@@ -244,6 +244,6 @@ pub enum ClosureOutlivesSubject<'tcx> {
 /// The constituent parts of an ADT or array.
 #[derive(Copy, Clone, Debug, HashStable)]
 pub struct DestructuredConst<'tcx> {
-    pub variant: VariantIdx,
+    pub variant: Option<VariantIdx>,
     pub fields: &'tcx [&'tcx ty::Const<'tcx>],
 }
diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs
index c77c7b95bc0..6380f8be98d 100644
--- a/src/librustc_middle/ty/context.rs
+++ b/src/librustc_middle/ty/context.rs
@@ -143,6 +143,7 @@ pub struct CommonTypes<'tcx> {
     pub u128: Ty<'tcx>,
     pub f32: Ty<'tcx>,
     pub f64: Ty<'tcx>,
+    pub str_: Ty<'tcx>,
     pub never: Ty<'tcx>,
     pub self_param: Ty<'tcx>,
 
@@ -816,6 +817,7 @@ impl<'tcx> CommonTypes<'tcx> {
             u128: mk(Uint(ast::UintTy::U128)),
             f32: mk(Float(ast::FloatTy::F32)),
             f64: mk(Float(ast::FloatTy::F64)),
+            str_: mk(Str),
             self_param: mk(ty::Param(ty::ParamTy { index: 0, name: kw::SelfUpper })),
 
             trait_object_dummy_self: mk(Infer(ty::FreshTy(0))),
@@ -2108,6 +2110,13 @@ impl<'tcx> TyCtxt<'tcx> {
         })
     }
 
+    /// Same a `self.mk_region(kind)`, but avoids accessing the interners if
+    /// `*r == kind`.
+    #[inline]
+    pub fn reuse_or_mk_region(self, r: Region<'tcx>, kind: RegionKind) -> Region<'tcx> {
+        if *r == kind { r } else { self.mk_region(kind) }
+    }
+
     #[allow(rustc::usage_of_ty_tykind)]
     #[inline]
     pub fn mk_ty(&self, st: TyKind<'tcx>) -> Ty<'tcx> {
@@ -2150,13 +2159,8 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     #[inline]
-    pub fn mk_str(self) -> Ty<'tcx> {
-        self.mk_ty(Str)
-    }
-
-    #[inline]
     pub fn mk_static_str(self) -> Ty<'tcx> {
-        self.mk_imm_ref(self.lifetimes.re_static, self.mk_str())
+        self.mk_imm_ref(self.lifetimes.re_static, self.types.str_)
     }
 
     #[inline]
diff --git a/src/librustc_middle/ty/fold.rs b/src/librustc_middle/ty/fold.rs
index 248dd00ef47..24dbf7b8c46 100644
--- a/src/librustc_middle/ty/fold.rs
+++ b/src/librustc_middle/ty/fold.rs
@@ -87,6 +87,9 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
     fn has_param_types_or_consts(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM)
     }
+    fn has_infer_regions(&self) -> bool {
+        self.has_type_flags(TypeFlags::HAS_RE_INFER)
+    }
     fn has_infer_types(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_TY_INFER)
     }
diff --git a/src/librustc_middle/ty/instance.rs b/src/librustc_middle/ty/instance.rs
index 1ce079821a2..d628d6783d5 100644
--- a/src/librustc_middle/ty/instance.rs
+++ b/src/librustc_middle/ty/instance.rs
@@ -9,6 +9,11 @@ use rustc_macros::HashStable;
 
 use std::fmt;
 
+/// A monomorphized `InstanceDef`.
+///
+/// Monomorphization happens on-the-fly and no monomorphized MIR is ever created. Instead, this type
+/// simply couples a potentially generic `InstanceDef` with some substs, and codegen and const eval
+/// will do all required substitution as they run.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
 #[derive(HashStable, Lift)]
 pub struct Instance<'tcx> {
@@ -18,10 +23,26 @@ pub struct Instance<'tcx> {
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable, HashStable)]
 pub enum InstanceDef<'tcx> {
+    /// A user-defined callable item.
+    ///
+    /// This includes:
+    /// - `fn` items
+    /// - closures
+    /// - generators
     Item(DefId),
+
+    /// An intrinsic `fn` item (with `"rust-intrinsic"` or `"platform-intrinsic"` ABI).
+    ///
+    /// Alongside `Virtual`, this is the only `InstanceDef` that does not have its own callable MIR.
+    /// Instead, codegen and const eval "magically" evaluate calls to intrinsics purely in the
+    /// caller.
     Intrinsic(DefId),
 
-    /// `<T as Trait>::method` where `method` receives unsizeable `self: Self`.
+    /// `<T as Trait>::method` where `method` receives unsizeable `self: Self` (part of the
+    /// `unsized_locals` feature).
+    ///
+    /// The generated shim will take `Self` via `*mut Self` - conceptually this is `&owned Self` -
+    /// and dereference the argument to call the original function.
     VtableShim(DefId),
 
     /// `fn()` pointer where the function itself cannot be turned into a pointer.
@@ -37,7 +58,8 @@ pub enum InstanceDef<'tcx> {
     /// (the definition of the function itself).
     ReifyShim(DefId),
 
-    /// `<fn() as FnTrait>::call_*`
+    /// `<fn() as FnTrait>::call_*` (generated `FnTrait` implementation for `fn()` pointers).
+    ///
     /// `DefId` is `FnTrait::call_*`.
     ///
     /// NB: the (`fn` pointer) type must currently be monomorphic to avoid double substitution
@@ -45,19 +67,22 @@ pub enum InstanceDef<'tcx> {
     // FIXME(#69925) support polymorphic MIR shim bodies properly instead.
     FnPtrShim(DefId, Ty<'tcx>),
 
-    /// `<dyn Trait as Trait>::fn`, "direct calls" of which are implicitly
-    /// codegen'd as virtual calls.
+    /// Dynamic dispatch to `<dyn Trait as Trait>::fn`.
     ///
-    /// NB: if this is reified to a `fn` pointer, a `ReifyShim` is used
-    /// (see `ReifyShim` above for more details on that).
+    /// This `InstanceDef` does not have callable MIR. Calls to `Virtual` instances must be
+    /// codegen'd as virtual calls through the vtable.
+    ///
+    /// If this is reified to a `fn` pointer, a `ReifyShim` is used (see `ReifyShim` above for more
+    /// details on that).
     Virtual(DefId, usize),
 
-    /// `<[mut closure] as FnOnce>::call_once`
-    ClosureOnceShim {
-        call_once: DefId,
-    },
+    /// `<[FnMut closure] as FnOnce>::call_once`.
+    ///
+    /// The `DefId` is the ID of the `call_once` method in `FnOnce`.
+    ClosureOnceShim { call_once: DefId },
 
     /// `core::ptr::drop_in_place::<T>`.
+    ///
     /// The `DefId` is for `core::ptr::drop_in_place`.
     /// The `Option<Ty<'tcx>>` is either `Some(T)`, or `None` for empty drop
     /// glue.
@@ -67,7 +92,12 @@ pub enum InstanceDef<'tcx> {
     // FIXME(#69925) support polymorphic MIR shim bodies properly instead.
     DropGlue(DefId, Option<Ty<'tcx>>),
 
-    ///`<T as Clone>::clone` shim.
+    /// Compiler-generated `<T as Clone>::clone` implementation.
+    ///
+    /// For all types that automatically implement `Copy`, a trivial `Clone` impl is provided too.
+    /// Additionally, arrays, tuples, and closures get a `Clone` shim even if they aren't `Copy`.
+    ///
+    /// The `DefId` is for `Clone::clone`, the `Ty` is the type `T` with the builtin `Clone` impl.
     ///
     /// NB: the type must currently be monomorphic to avoid double substitution
     /// problems with the MIR shim bodies. `Instance::resolve` enforces this.
diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs
index 80f919d0c03..68af22569e3 100644
--- a/src/librustc_middle/ty/layout.rs
+++ b/src/librustc_middle/ty/layout.rs
@@ -2001,6 +2001,8 @@ where
                 }
 
                 let fields = match this.ty.kind {
+                    ty::Adt(def, _) if def.variants.is_empty() =>
+                        bug!("for_variant called on zero-variant enum"),
                     ty::Adt(def, _) => def.variants[variant_index].fields.len(),
                     _ => bug!(),
                 };
diff --git a/src/librustc_middle/ty/list.rs b/src/librustc_middle/ty/list.rs
index 76c72e4c260..92d6dbb5f90 100644
--- a/src/librustc_middle/ty/list.rs
+++ b/src/librustc_middle/ty/list.rs
@@ -2,7 +2,8 @@ use crate::arena::Arena;
 
 use rustc_serialize::{Encodable, Encoder};
 
-use std::cmp::{self, Ordering};
+use std::alloc::Layout;
+use std::cmp::Ordering;
 use std::fmt;
 use std::hash::{Hash, Hasher};
 use std::iter;
@@ -43,17 +44,9 @@ impl<T: Copy> List<T> {
         assert!(mem::size_of::<T>() != 0);
         assert!(!slice.is_empty());
 
-        // Align up the size of the len (usize) field
-        let align = mem::align_of::<T>();
-        let align_mask = align - 1;
-        let offset = mem::size_of::<usize>();
-        let offset = (offset + align_mask) & !align_mask;
-
-        let size = offset + slice.len() * mem::size_of::<T>();
-
-        let mem = arena
-            .dropless
-            .alloc_raw(size, cmp::max(mem::align_of::<T>(), mem::align_of::<usize>()));
+        let (layout, _offset) =
+            Layout::new::<usize>().extend(Layout::for_value::<[T]>(slice)).unwrap();
+        let mem = arena.dropless.alloc_raw(layout);
         unsafe {
             let result = &mut *(mem as *mut List<T>);
             // Write the length
diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs
index e26e09ae6a9..ca0a1ac71c6 100644
--- a/src/librustc_middle/ty/mod.rs
+++ b/src/librustc_middle/ty/mod.rs
@@ -2352,6 +2352,7 @@ impl<'tcx> AdtDef {
     /// Alternatively, if there is no explicit discriminant, returns the
     /// inferred discriminant directly.
     pub fn discriminant_def_for_variant(&self, variant_index: VariantIdx) -> (Option<DefId>, u32) {
+        assert!(!self.variants.is_empty());
         let mut explicit_index = variant_index.as_u32();
         let expr_did;
         loop {
diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs
index 17203fcce5e..1a08639a533 100644
--- a/src/librustc_middle/ty/print/pretty.rs
+++ b/src/librustc_middle/ty/print/pretty.rs
@@ -1177,8 +1177,13 @@ pub trait PrettyPrinter<'tcx>:
                         }
                         p!(write(")"));
                     }
+                    ty::Adt(def, substs) if def.variants.is_empty() => {
+                        p!(print_value_path(def.did, substs));
+                    }
                     ty::Adt(def, substs) => {
-                        let variant_def = &def.variants[contents.variant];
+                        let variant_id =
+                            contents.variant.expect("destructed const of adt without variant id");
+                        let variant_def = &def.variants[variant_id];
                         p!(print_value_path(variant_def.def_id, substs));
 
                         match variant_def.ctor_kind {
diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs
index cf11adb0285..b0addcb2bb6 100644
--- a/src/librustc_middle/ty/sty.rs
+++ b/src/librustc_middle/ty/sty.rs
@@ -2099,6 +2099,9 @@ impl<'tcx> TyS<'tcx> {
         variant_index: VariantIdx,
     ) -> Option<Discr<'tcx>> {
         match self.kind {
+            TyKind::Adt(adt, _) if adt.variants.is_empty() => {
+                bug!("discriminant_for_variant called on zero variant enum");
+            }
             TyKind::Adt(adt, _) if adt.is_enum() => {
                 Some(adt.discriminant_for_variant(tcx, variant_index))
             }
diff --git a/src/librustc_mir/const_eval/mod.rs b/src/librustc_mir/const_eval/mod.rs
index 3539ccf5de0..ed992a59839 100644
--- a/src/librustc_mir/const_eval/mod.rs
+++ b/src/librustc_mir/const_eval/mod.rs
@@ -30,8 +30,10 @@ pub(crate) fn const_caller_location(
     ConstValue::Scalar(loc_place.ptr)
 }
 
-// this function uses `unwrap` copiously, because an already validated constant
-// must have valid fields and can thus never fail outside of compiler bugs
+/// This function uses `unwrap` copiously, because an already validated constant
+/// must have valid fields and can thus never fail outside of compiler bugs. However, it is
+/// invoked from the pretty printer, where it can receive enums with no variants and e.g.
+/// `read_discriminant` needs to be able to handle that.
 pub(crate) fn destructure_const<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
@@ -41,17 +43,21 @@ pub(crate) fn destructure_const<'tcx>(
     let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
     let op = ecx.eval_const_to_op(val, None).unwrap();
 
-    let variant = ecx.read_discriminant(op).unwrap().1;
-
     // We go to `usize` as we cannot allocate anything bigger anyway.
-    let field_count = match val.ty.kind {
-        ty::Array(_, len) => usize::try_from(len.eval_usize(tcx, param_env)).unwrap(),
-        ty::Adt(def, _) => def.variants[variant].fields.len(),
-        ty::Tuple(substs) => substs.len(),
+    let (field_count, variant, down) = match val.ty.kind {
+        ty::Array(_, len) => (usize::try_from(len.eval_usize(tcx, param_env)).unwrap(), None, op),
+        ty::Adt(def, _) if def.variants.is_empty() => {
+            return mir::DestructuredConst { variant: None, fields: tcx.arena.alloc_slice(&[]) };
+        }
+        ty::Adt(def, _) => {
+            let variant = ecx.read_discriminant(op).unwrap().1;
+            let down = ecx.operand_downcast(op, variant).unwrap();
+            (def.variants[variant].fields.len(), Some(variant), down)
+        }
+        ty::Tuple(substs) => (substs.len(), None, op),
         _ => bug!("cannot destructure constant {:?}", val),
     };
 
-    let down = ecx.operand_downcast(op, variant).unwrap();
     let fields_iter = (0..field_count).map(|i| {
         let field_op = ecx.operand_field(down, i).unwrap();
         let val = op_to_const(&ecx, field_op);
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 71fff851531..15a2e9130a3 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -32,13 +32,9 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
 
     let mut result = match instance {
         ty::InstanceDef::Item(..) => bug!("item {:?} passed to make_shim", instance),
-        ty::InstanceDef::VtableShim(def_id) => build_call_shim(
-            tcx,
-            instance,
-            Some(Adjustment::DerefMove),
-            CallKind::Direct(def_id),
-            None,
-        ),
+        ty::InstanceDef::VtableShim(def_id) => {
+            build_call_shim(tcx, instance, Some(Adjustment::Deref), CallKind::Direct(def_id), None)
+        }
         ty::InstanceDef::FnPtrShim(def_id, ty) => {
             // FIXME(eddyb) support generating shims for a "shallow type",
             // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic
@@ -60,7 +56,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
             let sig = tcx.erase_late_bound_regions(&ty.fn_sig(tcx));
             let arg_tys = sig.inputs();
 
-            build_call_shim(tcx, instance, Some(adjustment), CallKind::Indirect, Some(arg_tys))
+            build_call_shim(tcx, instance, Some(adjustment), CallKind::Indirect(ty), Some(arg_tys))
         }
         // We are generating a call back to our def-id, which the
         // codegen backend knows to turn to an actual call, be it
@@ -134,15 +130,28 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
 
 #[derive(Copy, Clone, Debug, PartialEq)]
 enum Adjustment {
+    /// Pass the receiver as-is.
     Identity,
+
+    /// We get passed `&[mut] self` and call the target with `*self`.
+    ///
+    /// This either copies `self` (if `Self: Copy`, eg. for function items), or moves out of it
+    /// (for `VtableShim`, which effectively is passed `&own Self`).
     Deref,
-    DerefMove,
+
+    /// We get passed `self: Self` and call the target with `&mut self`.
+    ///
+    /// In this case we need to ensure that the `Self` is dropped after the call, as the callee
+    /// won't do it for us.
     RefMut,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
-enum CallKind {
-    Indirect,
+enum CallKind<'tcx> {
+    /// Call the `FnPtr` that was passed as the receiver.
+    Indirect(Ty<'tcx>),
+
+    /// Call a known `FnDef`.
     Direct(DefId),
 }
 
@@ -662,7 +671,7 @@ fn build_call_shim<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance: ty::InstanceDef<'tcx>,
     rcvr_adjustment: Option<Adjustment>,
-    call_kind: CallKind,
+    call_kind: CallKind<'tcx>,
     untuple_args: Option<&[Ty<'tcx>]>,
 ) -> Body<'tcx> {
     debug!(
@@ -675,6 +684,29 @@ fn build_call_shim<'tcx>(
     let sig = tcx.fn_sig(def_id);
     let mut sig = tcx.erase_late_bound_regions(&sig);
 
+    if let CallKind::Indirect(fnty) = call_kind {
+        // `sig` determines our local decls, and thus the callee type in the `Call` terminator. This
+        // can only be an `FnDef` or `FnPtr`, but currently will be `Self` since the types come from
+        // the implemented `FnX` trait.
+
+        // Apply the opposite adjustment to the MIR input.
+        let mut inputs_and_output = sig.inputs_and_output.to_vec();
+
+        // Initial signature is `fn(&? Self, Args) -> Self::Output` where `Args` is a tuple of the
+        // fn arguments. `Self` may be passed via (im)mutable reference or by-value.
+        assert_eq!(inputs_and_output.len(), 3);
+
+        // `Self` is always the original fn type `ty`. The MIR call terminator is only defined for
+        // `FnDef` and `FnPtr` callees, not the `Self` type param.
+        let self_arg = &mut inputs_and_output[0];
+        *self_arg = match rcvr_adjustment.unwrap() {
+            Adjustment::Identity => fnty,
+            Adjustment::Deref => tcx.mk_imm_ptr(fnty),
+            Adjustment::RefMut => tcx.mk_mut_ptr(fnty),
+        };
+        sig.inputs_and_output = tcx.intern_type_list(&inputs_and_output);
+    }
+
     // FIXME(eddyb) avoid having this snippet both here and in
     // `Instance::fn_sig` (introduce `InstanceDef::fn_sig`?).
     if let ty::InstanceDef::VtableShim(..) = instance {
@@ -701,8 +733,7 @@ fn build_call_shim<'tcx>(
 
     let rcvr = rcvr_adjustment.map(|rcvr_adjustment| match rcvr_adjustment {
         Adjustment::Identity => Operand::Move(rcvr_place()),
-        Adjustment::Deref => Operand::Move(tcx.mk_place_deref(rcvr_place())), // Can't copy `&mut`
-        Adjustment::DerefMove => Operand::Move(tcx.mk_place_deref(rcvr_place())),
+        Adjustment::Deref => Operand::Move(tcx.mk_place_deref(rcvr_place())),
         Adjustment::RefMut => {
             // let rcvr = &mut rcvr;
             let ref_rcvr = local_decls.push(
@@ -728,7 +759,10 @@ fn build_call_shim<'tcx>(
     });
 
     let (callee, mut args) = match call_kind {
-        CallKind::Indirect => (rcvr.unwrap(), vec![]),
+        // `FnPtr` call has no receiver. Args are untupled below.
+        CallKind::Indirect(_) => (rcvr.unwrap(), vec![]),
+
+        // `FnDef` call with optional receiver.
         CallKind::Direct(def_id) => {
             let ty = tcx.type_of(def_id);
             (
diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs
index d5059c98c95..733ae908451 100644
--- a/src/librustc_mir/transform/check_consts/ops.rs
+++ b/src/librustc_mir/transform/check_consts/ops.rs
@@ -205,22 +205,34 @@ impl NonConstOp for CellBorrow {
 #[derive(Debug)]
 pub struct MutBorrow;
 impl NonConstOp for MutBorrow {
+    fn is_allowed_in_item(&self, ccx: &ConstCx<'_, '_>) -> bool {
+        // Forbid everywhere except in const fn
+        ccx.const_kind() == hir::ConstContext::ConstFn
+            && ccx.tcx.features().enabled(Self::feature_gate().unwrap())
+    }
+
     fn feature_gate() -> Option<Symbol> {
         Some(sym::const_mut_refs)
     }
 
     fn emit_error(&self, ccx: &ConstCx<'_, '_>, span: Span) {
-        let mut err = feature_err(
-            &ccx.tcx.sess.parse_sess,
-            sym::const_mut_refs,
-            span,
-            &format!(
-                "references in {}s may only refer \
-                      to immutable values",
-                ccx.const_kind()
-            ),
-        );
-        err.span_label(span, format!("{}s require immutable values", ccx.const_kind()));
+        let mut err = if ccx.const_kind() == hir::ConstContext::ConstFn {
+            feature_err(
+                &ccx.tcx.sess.parse_sess,
+                sym::const_mut_refs,
+                span,
+                &format!("mutable references are not allowed in {}s", ccx.const_kind()),
+            )
+        } else {
+            struct_span_err!(
+                ccx.tcx.sess,
+                span,
+                E0764,
+                "mutable references are not allowed in {}s",
+                ccx.const_kind(),
+            )
+        };
+        err.span_label(span, "`&mut` is only allowed in `const fn`".to_string());
         if ccx.tcx.sess.teach(&err.get_code().unwrap()) {
             err.note(
                 "References in statics and constants may only refer \
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index db909494aed..068d055fa78 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -9,7 +9,6 @@ use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
 use rustc_middle::ty::subst::{Subst, SubstsRef};
 use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
-use rustc_session::config::Sanitizer;
 use rustc_target::spec::abi::Abi;
 
 use super::simplify::{remove_dead_blocks, CfgSimplifier};
@@ -232,24 +231,8 @@ impl Inliner<'tcx> {
 
         // Avoid inlining functions marked as no_sanitize if sanitizer is enabled,
         // since instrumentation might be enabled and performed on the caller.
-        match self.tcx.sess.opts.debugging_opts.sanitizer {
-            Some(Sanitizer::Address) => {
-                if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_SANITIZE_ADDRESS) {
-                    return false;
-                }
-            }
-            Some(Sanitizer::Memory) => {
-                if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_SANITIZE_MEMORY) {
-                    return false;
-                }
-            }
-            Some(Sanitizer::Thread) => {
-                if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_SANITIZE_THREAD) {
-                    return false;
-                }
-            }
-            Some(Sanitizer::Leak) => {}
-            None => {}
+        if self.tcx.sess.opts.debugging_opts.sanitizer.intersects(codegen_fn_attrs.no_sanitize) {
+            return false;
         }
 
         let hinted = match codegen_fn_attrs.inline {
diff --git a/src/librustc_mir/transform/validate.rs b/src/librustc_mir/transform/validate.rs
index 8150c328316..625f40cd792 100644
--- a/src/librustc_mir/transform/validate.rs
+++ b/src/librustc_mir/transform/validate.rs
@@ -9,7 +9,6 @@ use rustc_middle::{
     },
     ty::{self, ParamEnv, TyCtxt},
 };
-use rustc_span::def_id::DefId;
 
 #[derive(Copy, Clone, Debug)]
 enum EdgeKind {
@@ -24,15 +23,14 @@ pub struct Validator {
 
 impl<'tcx> MirPass<'tcx> for Validator {
     fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
-        let def_id = source.def_id();
-        let param_env = tcx.param_env(def_id);
-        TypeChecker { when: &self.when, def_id, body, tcx, param_env }.visit_body(body);
+        let param_env = tcx.param_env(source.def_id());
+        TypeChecker { when: &self.when, source, body, tcx, param_env }.visit_body(body);
     }
 }
 
 struct TypeChecker<'a, 'tcx> {
     when: &'a str,
-    def_id: DefId,
+    source: MirSource<'tcx>,
     body: &'a Body<'tcx>,
     tcx: TyCtxt<'tcx>,
     param_env: ParamEnv<'tcx>,
@@ -47,7 +45,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             span,
             &format!(
                 "broken MIR in {:?} ({}) at {:?}:\n{}",
-                self.def_id,
+                self.source.instance,
                 self.when,
                 location,
                 msg.as_ref()
diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs
index 4a4de6c420b..6ac5d41ec61 100644
--- a/src/librustc_mir_build/hair/pattern/_match.rs
+++ b/src/librustc_mir_build/hair/pattern/_match.rs
@@ -800,7 +800,11 @@ impl<'tcx> Constructor<'tcx> {
                 assert!(!adt.is_enum());
                 VariantIdx::new(0)
             }
-            ConstantValue(c) => cx.tcx.destructure_const(cx.param_env.and(c)).variant,
+            ConstantValue(c) => cx
+                .tcx
+                .destructure_const(cx.param_env.and(c))
+                .variant
+                .expect("destructed const of adt without variant id"),
             _ => bug!("bad constructor {:?} for adt {:?}", self, adt),
         }
     }
diff --git a/src/librustc_mir_build/hair/pattern/const_to_pat.rs b/src/librustc_mir_build/hair/pattern/const_to_pat.rs
index 1aed8e844b6..6dd7e0871b4 100644
--- a/src/librustc_mir_build/hair/pattern/const_to_pat.rs
+++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs
@@ -275,7 +275,9 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
                 PatKind::Variant {
                     adt_def,
                     substs,
-                    variant_index: destructured.variant,
+                    variant_index: destructured
+                        .variant
+                        .expect("destructed const of adt without variant id"),
                     subpatterns: field_pats(destructured.fields),
                 }
             }
diff --git a/src/librustc_session/Cargo.toml b/src/librustc_session/Cargo.toml
index 4d57c6384dd..abce7359c0e 100644
--- a/src/librustc_session/Cargo.toml
+++ b/src/librustc_session/Cargo.toml
@@ -9,6 +9,7 @@ name = "rustc_session"
 path = "lib.rs"
 
 [dependencies]
+bitflags = "1.2.1"
 getopts = "0.2"
 log = "0.4"
 rustc_errors = { path = "../librustc_errors" }
diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs
index 411a6eecbba..53cec040836 100644
--- a/src/librustc_session/config.rs
+++ b/src/librustc_session/config.rs
@@ -10,6 +10,7 @@ use crate::{early_error, early_warn, Session};
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::impl_stable_hash_via_hash;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 
 use rustc_target::spec::{Target, TargetTriple};
 
@@ -37,35 +38,55 @@ pub struct Config {
     pub ptr_width: u32,
 }
 
-#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
-pub enum Sanitizer {
-    Address,
-    Leak,
-    Memory,
-    Thread,
+bitflags! {
+    #[derive(Default, RustcEncodable, RustcDecodable)]
+    pub struct SanitizerSet: u8 {
+        const ADDRESS = 1 << 0;
+        const LEAK    = 1 << 1;
+        const MEMORY  = 1 << 2;
+        const THREAD  = 1 << 3;
+    }
 }
 
-impl fmt::Display for Sanitizer {
+/// Formats a sanitizer set as a comma separated list of sanitizers' names.
+impl fmt::Display for SanitizerSet {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            Sanitizer::Address => "address".fmt(f),
-            Sanitizer::Leak => "leak".fmt(f),
-            Sanitizer::Memory => "memory".fmt(f),
-            Sanitizer::Thread => "thread".fmt(f),
+        let mut first = true;
+        for s in *self {
+            let name = match s {
+                SanitizerSet::ADDRESS => "address",
+                SanitizerSet::LEAK => "leak",
+                SanitizerSet::MEMORY => "memory",
+                SanitizerSet::THREAD => "thread",
+                _ => panic!("unrecognized sanitizer {:?}", s),
+            };
+            if !first {
+                f.write_str(",")?;
+            }
+            f.write_str(name)?;
+            first = false;
         }
+        Ok(())
     }
 }
 
-impl FromStr for Sanitizer {
-    type Err = ();
-    fn from_str(s: &str) -> Result<Sanitizer, ()> {
-        match s {
-            "address" => Ok(Sanitizer::Address),
-            "leak" => Ok(Sanitizer::Leak),
-            "memory" => Ok(Sanitizer::Memory),
-            "thread" => Ok(Sanitizer::Thread),
-            _ => Err(()),
-        }
+impl IntoIterator for SanitizerSet {
+    type Item = SanitizerSet;
+    type IntoIter = std::vec::IntoIter<SanitizerSet>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        [SanitizerSet::ADDRESS, SanitizerSet::LEAK, SanitizerSet::MEMORY, SanitizerSet::THREAD]
+            .iter()
+            .copied()
+            .filter(|&s| self.contains(s))
+            .collect::<Vec<_>>()
+            .into_iter()
+    }
+}
+
+impl<CTX> HashStable<CTX> for SanitizerSet {
+    fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
+        self.bits().hash_stable(ctx, hasher);
     }
 }
 
@@ -726,10 +747,12 @@ pub fn default_configuration(sess: &Session) -> CrateConfig {
             }
         }
     }
-    if let Some(s) = &sess.opts.debugging_opts.sanitizer {
+
+    for s in sess.opts.debugging_opts.sanitizer {
         let symbol = Symbol::intern(&s.to_string());
         ret.insert((sym::sanitize, Some(symbol)));
     }
+
     if sess.opts.debug_assertions {
         ret.insert((Symbol::intern("debug_assertions"), None));
     }
@@ -1995,7 +2018,7 @@ impl PpMode {
 crate mod dep_tracking {
     use super::{
         CFGuard, CrateType, DebugInfo, ErrorOutputType, LinkerPluginLto, LtoCli, OptLevel,
-        OutputTypes, Passes, Sanitizer, SourceFileHashAlgorithm, SwitchWithOptPath,
+        OutputTypes, Passes, SanitizerSet, SourceFileHashAlgorithm, SwitchWithOptPath,
         SymbolManglingVersion,
     };
     use crate::lint;
@@ -2069,8 +2092,7 @@ crate mod dep_tracking {
     impl_dep_tracking_hash_via_hash!(UnstableFeatures);
     impl_dep_tracking_hash_via_hash!(OutputTypes);
     impl_dep_tracking_hash_via_hash!(NativeLibKind);
-    impl_dep_tracking_hash_via_hash!(Sanitizer);
-    impl_dep_tracking_hash_via_hash!(Option<Sanitizer>);
+    impl_dep_tracking_hash_via_hash!(SanitizerSet);
     impl_dep_tracking_hash_via_hash!(CFGuard);
     impl_dep_tracking_hash_via_hash!(TargetTriple);
     impl_dep_tracking_hash_via_hash!(Edition);
@@ -2085,7 +2107,6 @@ crate mod dep_tracking {
     impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level));
     impl_dep_tracking_hash_for_sortable_vec_of!((String, Option<String>, NativeLibKind));
     impl_dep_tracking_hash_for_sortable_vec_of!((String, u64));
-    impl_dep_tracking_hash_for_sortable_vec_of!(Sanitizer);
 
     impl<T1, T2> DepTrackingHash for (T1, T2)
     where
diff --git a/src/librustc_session/lib.rs b/src/librustc_session/lib.rs
index 80b693fe1ab..be9d2e7be27 100644
--- a/src/librustc_session/lib.rs
+++ b/src/librustc_session/lib.rs
@@ -1,6 +1,9 @@
 #![feature(crate_visibility_modifier)]
 #![feature(or_patterns)]
 
+#[macro_use]
+extern crate bitflags;
+
 pub mod cgu_reuse_tracker;
 pub mod utils;
 #[macro_use]
diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs
index 2d231359057..8032909bbcd 100644
--- a/src/librustc_session/options.rs
+++ b/src/librustc_session/options.rs
@@ -248,8 +248,7 @@ macro_rules! options {
         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_relro_level: &str = "one of: `full`, `partial`, or `off`";
-        pub const parse_sanitizer: &str = "one of: `address`, `leak`, `memory` or `thread`";
-        pub const parse_sanitizer_list: &str = "comma separated list of sanitizers";
+        pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `leak`, `memory` or `thread`";
         pub const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2";
         pub const parse_cfguard: &str = "either `disabled`, `nochecks`, or `checks`";
         pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`";
@@ -459,24 +458,15 @@ macro_rules! options {
             true
         }
 
-        fn parse_sanitizer(slot: &mut Option<Sanitizer>, v: Option<&str>) -> bool {
-            if let Some(Ok(s)) =  v.map(str::parse) {
-                *slot = Some(s);
-                true
-            } else {
-                false
-            }
-        }
-
-        fn parse_sanitizer_list(slot: &mut Vec<Sanitizer>, v: Option<&str>) -> bool {
+        fn parse_sanitizers(slot: &mut SanitizerSet, v: Option<&str>) -> bool {
             if let Some(v) = v {
-                for s in v.split(',').map(str::parse) {
-                    if let Ok(s) = s {
-                        if !slot.contains(&s) {
-                            slot.push(s);
-                        }
-                    } else {
-                        return false;
+                for s in v.split(',') {
+                    *slot |= match s {
+                        "address" => SanitizerSet::ADDRESS,
+                        "leak" => SanitizerSet::LEAK,
+                        "memory" => SanitizerSet::MEMORY,
+                        "thread" => SanitizerSet::THREAD,
+                        _ => return false,
                     }
                 }
                 true
@@ -974,11 +964,11 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
     // soon.
     run_dsymutil: bool = (true, parse_bool, [TRACKED],
         "if on Mac, run `dsymutil` and delete intermediate object files (default: yes)"),
-    sanitizer: Option<Sanitizer> = (None, parse_sanitizer, [TRACKED],
+    sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED],
         "use a sanitizer"),
     sanitizer_memory_track_origins: usize = (0, parse_sanitizer_memory_track_origins, [TRACKED],
         "enable origins tracking in MemorySanitizer"),
-    sanitizer_recover: Vec<Sanitizer> = (vec![], parse_sanitizer_list, [TRACKED],
+    sanitizer_recover: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED],
         "enable recovery for selected sanitizers"),
     saturating_float_casts: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "make float->int casts UB-free: numbers outside the integer type's range are clipped to \
diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs
index 06d7d4f14d8..90cd6ae5bf9 100644
--- a/src/librustc_session/session.rs
+++ b/src/librustc_session/session.rs
@@ -1,7 +1,7 @@
 use crate::cgu_reuse_tracker::CguReuseTracker;
 use crate::code_stats::CodeStats;
 pub use crate::code_stats::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
-use crate::config::{self, CrateType, OutputType, PrintRequest, Sanitizer, SwitchWithOptPath};
+use crate::config::{self, CrateType, OutputType, PrintRequest, SanitizerSet, SwitchWithOptPath};
 use crate::filesearch;
 use crate::lint;
 use crate::parse::ParseSess;
@@ -650,14 +650,9 @@ impl Session {
     }
     pub fn fewer_names(&self) -> bool {
         let more_names = self.opts.output_types.contains_key(&OutputType::LlvmAssembly)
-            || self.opts.output_types.contains_key(&OutputType::Bitcode);
-
-        // Address sanitizer and memory sanitizer use alloca name when reporting an issue.
-        let more_names = match self.opts.debugging_opts.sanitizer {
-            Some(Sanitizer::Address) => true,
-            Some(Sanitizer::Memory) => true,
-            _ => more_names,
-        };
+            || self.opts.output_types.contains_key(&OutputType::Bitcode)
+            // AddressSanitizer and MemorySanitizer use alloca name when reporting an issue.
+            || self.opts.debugging_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY);
 
         self.opts.debugging_opts.fewer_names || !more_names
     }
@@ -1020,12 +1015,10 @@ impl Session {
 
     /// Checks if LLVM lifetime markers should be emitted.
     pub fn emit_lifetime_markers(&self) -> bool {
-        match self.opts.debugging_opts.sanitizer {
-            // AddressSanitizer uses lifetimes to detect use after scope bugs.
-            // MemorySanitizer uses lifetimes to detect use of uninitialized stack variables.
-            Some(Sanitizer::Address | Sanitizer::Memory) => true,
-            _ => self.opts.optimize != config::OptLevel::No,
-        }
+        self.opts.optimize != config::OptLevel::No
+        // AddressSanitizer uses lifetimes to detect use after scope bugs.
+        // MemorySanitizer uses lifetimes to detect use of uninitialized stack variables.
+        || self.opts.debugging_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY)
     }
 }
 
@@ -1356,33 +1349,36 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
         );
     }
 
+    const ASAN_SUPPORTED_TARGETS: &[&str] =
+        &["aarch64-fuchsia", "x86_64-apple-darwin", "x86_64-fuchsia", "x86_64-unknown-linux-gnu"];
+    const LSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
+    const MSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"];
+    const TSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-apple-darwin", "x86_64-unknown-linux-gnu"];
+
     // Sanitizers can only be used on some tested platforms.
-    if let Some(ref sanitizer) = sess.opts.debugging_opts.sanitizer {
-        const ASAN_SUPPORTED_TARGETS: &[&str] = &[
-            "x86_64-unknown-linux-gnu",
-            "x86_64-apple-darwin",
-            "x86_64-fuchsia",
-            "aarch64-fuchsia",
-        ];
-        const TSAN_SUPPORTED_TARGETS: &[&str] =
-            &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"];
-        const LSAN_SUPPORTED_TARGETS: &[&str] =
-            &["x86_64-unknown-linux-gnu", "x86_64-apple-darwin"];
-        const MSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"];
-
-        let supported_targets = match *sanitizer {
-            Sanitizer::Address => ASAN_SUPPORTED_TARGETS,
-            Sanitizer::Thread => TSAN_SUPPORTED_TARGETS,
-            Sanitizer::Leak => LSAN_SUPPORTED_TARGETS,
-            Sanitizer::Memory => MSAN_SUPPORTED_TARGETS,
+    for s in sess.opts.debugging_opts.sanitizer {
+        let supported_targets = match s {
+            SanitizerSet::ADDRESS => ASAN_SUPPORTED_TARGETS,
+            SanitizerSet::LEAK => LSAN_SUPPORTED_TARGETS,
+            SanitizerSet::MEMORY => MSAN_SUPPORTED_TARGETS,
+            SanitizerSet::THREAD => TSAN_SUPPORTED_TARGETS,
+            _ => panic!("unrecognized sanitizer {}", s),
         };
-
         if !supported_targets.contains(&&*sess.opts.target_triple.triple()) {
             sess.err(&format!(
-                "{:?}Sanitizer only works with the `{}` target",
-                sanitizer,
-                supported_targets.join("` or `")
+                "`-Zsanitizer={}` only works with targets: {}",
+                s,
+                supported_targets.join(", ")
+            ));
+        }
+        let conflicting = sess.opts.debugging_opts.sanitizer - s;
+        if !conflicting.is_empty() {
+            sess.err(&format!(
+                "`-Zsanitizer={}` is incompatible with `-Zsanitizer={}`",
+                s, conflicting,
             ));
+            // Don't report additional errors.
+            break;
         }
     }
 }
diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs
index ed108613bfa..706e68698eb 100644
--- a/src/librustc_trait_selection/traits/project.rs
+++ b/src/librustc_trait_selection/traits/project.rs
@@ -24,6 +24,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::ErrorReported;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::{FnOnceTraitLangItem, GeneratorTraitLangItem};
+use rustc_infer::infer::resolve::OpportunisticRegionResolver;
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::util::IntTypeExt;
@@ -1146,7 +1147,7 @@ fn confirm_candidate<'cx, 'tcx>(
 ) -> Progress<'tcx> {
     debug!("confirm_candidate(candidate={:?}, obligation={:?})", candidate, obligation);
 
-    match candidate {
+    let mut progress = match candidate {
         ProjectionTyCandidate::ParamEnv(poly_projection)
         | ProjectionTyCandidate::TraitDef(poly_projection) => {
             confirm_param_env_candidate(selcx, obligation, poly_projection)
@@ -1155,7 +1156,16 @@ fn confirm_candidate<'cx, 'tcx>(
         ProjectionTyCandidate::Select(impl_source) => {
             confirm_select_candidate(selcx, obligation, obligation_trait_ref, impl_source)
         }
+    };
+    // When checking for cycle during evaluation, we compare predicates with
+    // "syntactic" equality. Since normalization generally introduces a type
+    // with new region variables, we need to resolve them to existing variables
+    // when possible for this to work. See `auto-trait-projection-recursion.rs`
+    // for a case where this matters.
+    if progress.ty.has_infer_regions() {
+        progress.ty = OpportunisticRegionResolver::new(selcx.infcx()).fold_ty(progress.ty);
     }
+    progress
 }
 
 fn confirm_select_candidate<'cx, 'tcx>(
diff --git a/src/librustc_trait_selection/traits/util.rs b/src/librustc_trait_selection/traits/util.rs
index 8b5b4128e66..d3484b8af89 100644
--- a/src/librustc_trait_selection/traits/util.rs
+++ b/src/librustc_trait_selection/traits/util.rs
@@ -302,7 +302,7 @@ pub fn get_vtable_index_of_object_method<N>(
 ) -> usize {
     // Count number of methods preceding the one we are selecting and
     // add them to the total offset.
-    // Skip over associated types and constants.
+    // Skip over associated types and constants, as those aren't stored in the vtable.
     let mut entries = object.vtable_base;
     for trait_item in tcx.associated_items(object.upcast_trait_ref.def_id()).in_definition_order() {
         if trait_item.def_id == method_def_id {
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 7cdcb2face8..b592d30c37d 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -2787,7 +2787,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     hir::PrimTy::Int(it) => tcx.mk_mach_int(it),
                     hir::PrimTy::Uint(uit) => tcx.mk_mach_uint(uit),
                     hir::PrimTy::Float(ft) => tcx.mk_mach_float(ft),
-                    hir::PrimTy::Str => tcx.mk_str(),
+                    hir::PrimTy::Str => tcx.types.str_,
                 }
             }
             Res::Err => {
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 1c34d71ee31..15d210b89b6 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -10,45 +10,30 @@
 //!
 //! Note that if we are expecting a reference, we will *reborrow*
 //! even if the argument provided was already a reference. This is
-//! useful for freezing mut/const things (that is, when the expected is &T
-//! but you have &const T or &mut T) and also for avoiding the linearity
+//! useful for freezing mut things (that is, when the expected type is &T
+//! but you have &mut T) and also for avoiding the linearity
 //! of mut things (when the expected is &mut T and you have &mut T). See
-//! the various `src/test/ui/coerce-reborrow-*.rs` tests for
+//! the various `src/test/ui/coerce/*.rs` tests for
 //! examples of where this is useful.
 //!
 //! ## Subtle note
 //!
-//! When deciding what type coercions to consider, we do not attempt to
-//! resolve any type variables we may encounter. This is because `b`
-//! represents the expected type "as the user wrote it", meaning that if
-//! the user defined a generic function like
+//! When infering the generic arguments of functions, the argument
+//! order is relevant, which can lead to the following edge case:
 //!
-//!    fn foo<A>(a: A, b: A) { ... }
+//! ```rust
+//! fn foo<T>(a: T, b: T) {
+//!     // ...
+//! }
 //!
-//! and then we wrote `foo(&1, @2)`, we will not auto-borrow
-//! either argument. In older code we went to some lengths to
-//! resolve the `b` variable, which could mean that we'd
-//! auto-borrow later arguments but not earlier ones, which
-//! seems very confusing.
+//! foo(&7i32, &mut 7i32);
+//! // This compiles, as we first infer `T` to be `&i32`,
+//! // and then coerce `&mut 7i32` to `&7i32`.
 //!
-//! ## Subtler note
-//!
-//! However, right now, if the user manually specifies the
-//! values for the type variables, as so:
-//!
-//!    foo::<&int>(@1, @2)
-//!
-//! then we *will* auto-borrow, because we can't distinguish this from a
-//! function that declared `&int`. This is inconsistent but it's easiest
-//! at the moment. The right thing to do, I think, is to consider the
-//! *unsubstituted* type when deciding whether to auto-borrow, but the
-//! *substituted* type when considering the bounds and so forth. But most
-//! of our methods don't give access to the unsubstituted type, and
-//! rightly so because they'd be error-prone. So maybe the thing to do is
-//! to actually determine the kind of coercions that should occur
-//! separately and pass them in. Or maybe it's ok as is. Anyway, it's
-//! sort of a minor point so I've opted to leave it for later -- after all,
-//! we may want to adjust precisely when coercions occur.
+//! foo(&mut 7i32, &7i32);
+//! // This does not compile, as we first infer `T` to be `&mut i32`
+//! // and are then unable to coerce `&7i32` to `&mut i32`.
+//! ```
 
 use crate::astconv::AstConv;
 use crate::check::FnCtxt;
@@ -96,6 +81,8 @@ impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> {
 
 type CoerceResult<'tcx> = InferResult<'tcx, (Vec<Adjustment<'tcx>>, Ty<'tcx>)>;
 
+/// Coercing a mutable reference to an immutable works, while
+/// coercing `&T` to `&mut T` should be forbidden.
 fn coerce_mutbls<'tcx>(
     from_mutbl: hir::Mutability,
     to_mutbl: hir::Mutability,
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 3bd75095bb6..91266eeb9ba 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -40,6 +40,7 @@ use rustc_middle::ty::util::Discr;
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, AdtKind, Const, ToPolyTraitRef, Ty, TyCtxt};
 use rustc_middle::ty::{ReprOptions, ToPredicate, WithConstness};
+use rustc_session::config::SanitizerSet;
 use rustc_session::lint;
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -2450,11 +2451,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
             if let Some(list) = attr.meta_item_list() {
                 for item in list.iter() {
                     if item.check_name(sym::address) {
-                        codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_SANITIZE_ADDRESS;
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::ADDRESS;
                     } else if item.check_name(sym::memory) {
-                        codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_SANITIZE_MEMORY;
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY;
                     } else if item.check_name(sym::thread) {
-                        codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_SANITIZE_THREAD;
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::THREAD;
                     } else {
                         tcx.sess
                             .struct_span_err(item.span(), "invalid argument for `no_sanitize`")
@@ -2554,7 +2555,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
         }
     }
 
-    if codegen_fn_attrs.flags.intersects(CodegenFnAttrFlags::NO_SANITIZE_ANY) {
+    if !codegen_fn_attrs.no_sanitize.is_empty() {
         if codegen_fn_attrs.inline == InlineAttr::Always {
             if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) {
                 let hir_id = tcx.hir().as_local_hir_id(id.expect_local());
diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs
index 3085c3d8296..48f7cf16988 100644
--- a/src/libstd/prelude/mod.rs
+++ b/src/libstd/prelude/mod.rs
@@ -10,22 +10,6 @@
 //! things, particularly traits, which are used in almost every single Rust
 //! program.
 //!
-//! On a technical level, Rust inserts
-//!
-//! ```
-//! # #[allow(unused_extern_crates)]
-//! extern crate std;
-//! ```
-//!
-//! into the crate root of every crate, and
-//!
-//! ```
-//! # #[allow(unused_imports)]
-//! use std::prelude::v1::*;
-//! ```
-//!
-//! into every module.
-//!
 //! # Other preludes
 //!
 //! Preludes can be seen as a pattern to make using multiple types more
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 323bd26c698..9bc111c26ba 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -717,11 +717,12 @@ enum class LLVMRustOptStage {
 };
 
 struct LLVMRustSanitizerOptions {
+  bool SanitizeAddress;
+  bool SanitizeAddressRecover;
   bool SanitizeMemory;
+  bool SanitizeMemoryRecover;
+  int  SanitizeMemoryTrackOrigins;
   bool SanitizeThread;
-  bool SanitizeAddress;
-  bool SanitizeRecover;
-  int SanitizeMemoryTrackOrigins;
 };
 
 extern "C" void
@@ -808,7 +809,7 @@ LLVMRustOptimizeWithNewPassManager(
     if (SanitizerOptions->SanitizeMemory) {
       MemorySanitizerOptions Options(
           SanitizerOptions->SanitizeMemoryTrackOrigins,
-          SanitizerOptions->SanitizeRecover,
+          SanitizerOptions->SanitizeMemoryRecover,
           /*CompileKernel=*/false);
 #if LLVM_VERSION_GE(10, 0)
       PipelineStartEPCallbacks.push_back([Options](ModulePassManager &MPM) {
@@ -842,14 +843,14 @@ LLVMRustOptimizeWithNewPassManager(
       OptimizerLastEPCallbacks.push_back(
         [SanitizerOptions](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) {
           FPM.addPass(AddressSanitizerPass(
-              /*CompileKernel=*/false, SanitizerOptions->SanitizeRecover,
+              /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover,
               /*UseAfterScope=*/true));
         }
       );
       PipelineStartEPCallbacks.push_back(
         [SanitizerOptions](ModulePassManager &MPM) {
           MPM.addPass(ModuleAddressSanitizerPass(
-              /*CompileKernel=*/false, SanitizerOptions->SanitizeRecover));
+              /*CompileKernel=*/false, SanitizerOptions->SanitizeAddressRecover));
         }
       );
     }
diff --git a/src/test/compile-fail/issue-52443.rs b/src/test/compile-fail/issue-52443.rs
index 97619593352..00aca1d14ba 100644
--- a/src/test/compile-fail/issue-52443.rs
+++ b/src/test/compile-fail/issue-52443.rs
@@ -9,7 +9,7 @@ fn main() {
     [(); { for _ in 0usize.. {}; 0}];
     //~^ ERROR `for` is not allowed in a `const`
     //~| ERROR calls in constants are limited to constant functions
-    //~| ERROR references in constants may only refer to immutable values
+    //~| ERROR mutable references are not allowed in constants
     //~| ERROR calls in constants are limited to constant functions
     //~| ERROR evaluation of constant value failed
 }
diff --git a/src/test/compile-fail/specialization/issue-50452.rs b/src/test/compile-fail/specialization/issue-50452.rs
index d9e5280c7e1..958f0eb2668 100644
--- a/src/test/compile-fail/specialization/issue-50452.rs
+++ b/src/test/compile-fail/specialization/issue-50452.rs
@@ -1,6 +1,6 @@
 // compile-fail
-
 #![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
 
 pub trait Foo {
     fn foo();
diff --git a/src/test/mir-opt/fn-ptr-shim.rs b/src/test/mir-opt/fn-ptr-shim.rs
new file mode 100644
index 00000000000..08413c9f6fc
--- /dev/null
+++ b/src/test/mir-opt/fn-ptr-shim.rs
@@ -0,0 +1,15 @@
+// compile-flags: -Zmir-opt-level=0 -Zvalidate-mir
+
+// Tests that the `<fn() as Fn>` shim does not create a `Call` terminator with a `Self` callee
+// (as only `FnDef` and `FnPtr` callees are allowed in MIR).
+
+// EMIT_MIR rustc.ops-function-Fn-call.AddMovesForPackedDrops.before.mir
+fn main() {
+    call(noop as fn());
+}
+
+fn noop() {}
+
+fn call<F: Fn()>(f: F) {
+    f();
+}
diff --git a/src/test/mir-opt/fn-ptr-shim/rustc.ops-function-Fn-call.AddMovesForPackedDrops.before.mir b/src/test/mir-opt/fn-ptr-shim/rustc.ops-function-Fn-call.AddMovesForPackedDrops.before.mir
new file mode 100644
index 00000000000..4ecc331afae
--- /dev/null
+++ b/src/test/mir-opt/fn-ptr-shim/rustc.ops-function-Fn-call.AddMovesForPackedDrops.before.mir
@@ -0,0 +1,13 @@
+// MIR for `std::ops::Fn::call` before AddMovesForPackedDrops
+
+fn std::ops::Fn::call(_1: *const fn(), _2: Args) -> <Self as std::ops::FnOnce<Args>>::Output {
+    let mut _0: <Self as std::ops::FnOnce<Args>>::Output; // return place in scope 0 at $SRC_DIR/libcore/ops/function.rs:LL:COL
+
+    bb0: {
+        _0 = move (*_1)() -> bb1;        // scope 0 at $SRC_DIR/libcore/ops/function.rs:LL:COL
+    }
+
+    bb1: {
+        return;                          // scope 0 at $SRC_DIR/libcore/ops/function.rs:LL:COL
+    }
+}
diff --git a/src/test/mir-opt/issue-72181-1.rs b/src/test/mir-opt/issue-72181-1.rs
new file mode 100644
index 00000000000..6d65f847a2c
--- /dev/null
+++ b/src/test/mir-opt/issue-72181-1.rs
@@ -0,0 +1,21 @@
+// compile-flags: -Z mir-opt-level=1
+// Regression test for #72181, this ICE requires `-Z mir-opt-level=1` flags.
+
+#![feature(never_type)]
+#![allow(unused, invalid_value)]
+
+enum Void {}
+
+// EMIT_MIR rustc.f.mir_map.0.mir
+fn f(v: Void) -> ! {
+    match v {}
+}
+
+// EMIT_MIR rustc.main.mir_map.0.mir
+fn main() {
+    let v: Void = unsafe {
+        std::mem::transmute::<(), Void>(())
+    };
+
+    f(v);
+}
diff --git a/src/test/mir-opt/issue-72181-1/rustc.f.mir_map.0.mir b/src/test/mir-opt/issue-72181-1/rustc.f.mir_map.0.mir
new file mode 100644
index 00000000000..1821365898e
--- /dev/null
+++ b/src/test/mir-opt/issue-72181-1/rustc.f.mir_map.0.mir
@@ -0,0 +1,37 @@
+// MIR for `f` 0 mir_map
+
+fn f(_1: Void) -> ! {
+    debug v => _1;                       // in scope 0 at $DIR/issue-72181-1.rs:10:6: 10:7
+    let mut _0: !;                       // return place in scope 0 at $DIR/issue-72181-1.rs:10:18: 10:19
+    let mut _2: !;                       // in scope 0 at $DIR/issue-72181-1.rs:10:20: 12:2
+    let mut _3: !;                       // in scope 0 at $DIR/issue-72181-1.rs:11:5: 11:15
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/issue-72181-1.rs:10:20: 12:2
+        StorageLive(_3);                 // scope 0 at $DIR/issue-72181-1.rs:11:5: 11:15
+        FakeRead(ForMatchedPlace, _1);   // scope 0 at $DIR/issue-72181-1.rs:11:11: 11:12
+        unreachable;                     // scope 0 at $DIR/issue-72181-1.rs:11:11: 11:12
+    }
+
+    bb1 (cleanup): {
+        resume;                          // scope 0 at $DIR/issue-72181-1.rs:10:1: 12:2
+    }
+
+    bb2: {
+        unreachable;                     // scope 0 at $DIR/issue-72181-1.rs:11:5: 11:15
+    }
+
+    bb3: {
+        StorageDead(_3);                 // scope 0 at $DIR/issue-72181-1.rs:11:14: 11:15
+        unreachable;                     // scope 0 at $DIR/issue-72181-1.rs:10:20: 12:2
+    }
+
+    bb4: {
+        StorageDead(_2);                 // scope 0 at $DIR/issue-72181-1.rs:12:1: 12:2
+        goto -> bb5;                     // scope 0 at $DIR/issue-72181-1.rs:12:2: 12:2
+    }
+
+    bb5: {
+        return;                          // scope 0 at $DIR/issue-72181-1.rs:12:2: 12:2
+    }
+}
diff --git a/src/test/mir-opt/issue-72181-1/rustc.main.mir_map.0.mir b/src/test/mir-opt/issue-72181-1/rustc.main.mir_map.0.mir
new file mode 100644
index 00000000000..b87d0294fb8
--- /dev/null
+++ b/src/test/mir-opt/issue-72181-1/rustc.main.mir_map.0.mir
@@ -0,0 +1,67 @@
+// MIR for `main` 0 mir_map
+
+| User Type Annotations
+| 0: Canonical { max_universe: U0, variables: [], value: Ty(Void) } at $DIR/issue-72181-1.rs:16:12: 16:16
+| 1: Canonical { max_universe: U0, variables: [], value: Ty(Void) } at $DIR/issue-72181-1.rs:16:12: 16:16
+|
+fn main() -> () {
+    let mut _0: ();                      // return place in scope 0 at $DIR/issue-72181-1.rs:15:11: 15:11
+    let mut _1: !;                       // in scope 0 at $DIR/issue-72181-1.rs:15:11: 21:2
+    let _2: Void as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/issue-72181-1.rs:16:9: 16:10
+    let mut _3: ();                      // in scope 0 at $DIR/issue-72181-1.rs:17:41: 17:43
+    let _4: !;                           // in scope 0 at $DIR/issue-72181-1.rs:20:5: 20:9
+    let mut _5: Void;                    // in scope 0 at $DIR/issue-72181-1.rs:20:7: 20:8
+    scope 1 {
+        debug v => _2;                   // in scope 1 at $DIR/issue-72181-1.rs:16:9: 16:10
+    }
+    scope 2 {
+    }
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/issue-72181-1.rs:16:9: 16:10
+        StorageLive(_3);                 // scope 2 at $DIR/issue-72181-1.rs:17:41: 17:43
+        _3 = ();                         // scope 2 at $DIR/issue-72181-1.rs:17:41: 17:43
+        _2 = const std::intrinsics::transmute::<(), Void>(move _3) -> [return: bb2, unwind: bb1]; // scope 2 at $DIR/issue-72181-1.rs:17:9: 17:44
+                                         // ty::Const
+                                         // + ty: unsafe extern "rust-intrinsic" fn(()) -> Void {std::intrinsics::transmute::<(), Void>}
+                                         // + val: Value(Scalar(<ZST>))
+                                         // mir::Constant
+                                         // + span: $DIR/issue-72181-1.rs:17:9: 17:40
+                                         // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(()) -> Void {std::intrinsics::transmute::<(), Void>}, val: Value(Scalar(<ZST>)) }
+    }
+
+    bb1 (cleanup): {
+        resume;                          // scope 0 at $DIR/issue-72181-1.rs:15:1: 21:2
+    }
+
+    bb2: {
+        StorageDead(_3);                 // scope 2 at $DIR/issue-72181-1.rs:17:43: 17:44
+        FakeRead(ForLet, _2);            // scope 0 at $DIR/issue-72181-1.rs:16:9: 16:10
+        AscribeUserType(_2, o, UserTypeProjection { base: UserType(1), projs: [] }); // scope 0 at $DIR/issue-72181-1.rs:16:12: 16:16
+        StorageLive(_4);                 // scope 1 at $DIR/issue-72181-1.rs:20:5: 20:9
+        StorageLive(_5);                 // scope 1 at $DIR/issue-72181-1.rs:20:7: 20:8
+        _5 = move _2;                    // scope 1 at $DIR/issue-72181-1.rs:20:7: 20:8
+        const f(move _5) -> bb1;         // scope 1 at $DIR/issue-72181-1.rs:20:5: 20:9
+                                         // ty::Const
+                                         // + ty: fn(Void) -> ! {f}
+                                         // + val: Value(Scalar(<ZST>))
+                                         // mir::Constant
+                                         // + span: $DIR/issue-72181-1.rs:20:5: 20:6
+                                         // + literal: Const { ty: fn(Void) -> ! {f}, val: Value(Scalar(<ZST>)) }
+    }
+
+    bb3: {
+        StorageDead(_5);                 // scope 1 at $DIR/issue-72181-1.rs:20:8: 20:9
+        StorageDead(_4);                 // scope 1 at $DIR/issue-72181-1.rs:20:9: 20:10
+        StorageDead(_2);                 // scope 0 at $DIR/issue-72181-1.rs:21:1: 21:2
+        unreachable;                     // scope 0 at $DIR/issue-72181-1.rs:15:11: 21:2
+    }
+
+    bb4: {
+        goto -> bb5;                     // scope 0 at $DIR/issue-72181-1.rs:21:2: 21:2
+    }
+
+    bb5: {
+        return;                          // scope 0 at $DIR/issue-72181-1.rs:21:2: 21:2
+    }
+}
diff --git a/src/test/mir-opt/issue-72181.rs b/src/test/mir-opt/issue-72181.rs
new file mode 100644
index 00000000000..9373ce12032
--- /dev/null
+++ b/src/test/mir-opt/issue-72181.rs
@@ -0,0 +1,28 @@
+// compile-flags: -Z mir-opt-level=1
+// Regression test for #72181, this ICE requires `-Z mir-opt-level=1` flags.
+
+use std::mem;
+
+#[derive(Copy, Clone)]
+enum Never {}
+
+union Foo {
+    a: u64,
+    b: Never
+}
+
+// EMIT_MIR_FOR_EACH_BIT_WIDTH
+// EMIT_MIR rustc.foo.mir_map.0.mir
+fn foo(xs: [(Never, u32); 1]) -> u32 { xs[0].1 }
+
+// EMIT_MIR rustc.bar.mir_map.0.mir
+fn bar([(_, x)]: [(Never, u32); 1]) -> u32 { x }
+
+// EMIT_MIR_FOR_EACH_BIT_WIDTH
+// EMIT_MIR rustc.main.mir_map.0.mir
+fn main() {
+    let _ = mem::size_of::<Foo>();
+
+    let f = [Foo { a: 42 }, Foo { a: 10 }];
+    let _ = unsafe { f[0].a };
+}
diff --git a/src/test/mir-opt/issue-72181/32bit/rustc.bar.mir_map.0.mir b/src/test/mir-opt/issue-72181/32bit/rustc.bar.mir_map.0.mir
new file mode 100644
index 00000000000..29654c2b1f8
--- /dev/null
+++ b/src/test/mir-opt/issue-72181/32bit/rustc.bar.mir_map.0.mir
@@ -0,0 +1,25 @@
+// MIR for `bar` 0 mir_map
+
+fn bar(_1: [(Never, u32); 1]) -> u32 {
+    let mut _0: u32;                     // return place in scope 0 at $DIR/issue-72181.rs:19:40: 19:43
+    let _2: u32;                         // in scope 0 at $DIR/issue-72181.rs:19:13: 19:14
+    scope 1 {
+        debug x => _2;                   // in scope 1 at $DIR/issue-72181.rs:19:13: 19:14
+    }
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/issue-72181.rs:19:13: 19:14
+        _2 = (_1[0 of 1].1: u32);        // scope 0 at $DIR/issue-72181.rs:19:13: 19:14
+        _0 = _2;                         // scope 1 at $DIR/issue-72181.rs:19:46: 19:47
+        StorageDead(_2);                 // scope 0 at $DIR/issue-72181.rs:19:48: 19:49
+        goto -> bb2;                     // scope 0 at $DIR/issue-72181.rs:19:49: 19:49
+    }
+
+    bb1 (cleanup): {
+        resume;                          // scope 0 at $DIR/issue-72181.rs:19:1: 19:49
+    }
+
+    bb2: {
+        return;                          // scope 0 at $DIR/issue-72181.rs:19:49: 19:49
+    }
+}
diff --git a/src/test/mir-opt/issue-72181/32bit/rustc.foo.mir_map.0.mir b/src/test/mir-opt/issue-72181/32bit/rustc.foo.mir_map.0.mir
new file mode 100644
index 00000000000..776eb61a526
--- /dev/null
+++ b/src/test/mir-opt/issue-72181/32bit/rustc.foo.mir_map.0.mir
@@ -0,0 +1,37 @@
+// MIR for `foo` 0 mir_map
+
+fn foo(_1: [(Never, u32); 1]) -> u32 {
+    debug xs => _1;                      // in scope 0 at $DIR/issue-72181.rs:16:8: 16:10
+    let mut _0: u32;                     // return place in scope 0 at $DIR/issue-72181.rs:16:34: 16:37
+    let _2: usize;                       // in scope 0 at $DIR/issue-72181.rs:16:43: 16:44
+    let mut _3: usize;                   // in scope 0 at $DIR/issue-72181.rs:16:40: 16:45
+    let mut _4: bool;                    // in scope 0 at $DIR/issue-72181.rs:16:40: 16:45
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/issue-72181.rs:16:43: 16:44
+        _2 = const 0usize;               // scope 0 at $DIR/issue-72181.rs:16:43: 16:44
+                                         // ty::Const
+                                         // + ty: usize
+                                         // + val: Value(Scalar(0x00000000))
+                                         // mir::Constant
+                                         // + span: $DIR/issue-72181.rs:16:43: 16:44
+                                         // + literal: Const { ty: usize, val: Value(Scalar(0x00000000)) }
+        _3 = Len(_1);                    // scope 0 at $DIR/issue-72181.rs:16:40: 16:45
+        _4 = Lt(_2, _3);                 // scope 0 at $DIR/issue-72181.rs:16:40: 16:45
+        assert(move _4, "index out of bounds: the len is {} but the index is {}", move _3, _2) -> [success: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:16:40: 16:45
+    }
+
+    bb1 (cleanup): {
+        resume;                          // scope 0 at $DIR/issue-72181.rs:16:1: 16:49
+    }
+
+    bb2: {
+        _0 = (_1[_2].1: u32);            // scope 0 at $DIR/issue-72181.rs:16:40: 16:47
+        StorageDead(_2);                 // scope 0 at $DIR/issue-72181.rs:16:48: 16:49
+        goto -> bb3;                     // scope 0 at $DIR/issue-72181.rs:16:49: 16:49
+    }
+
+    bb3: {
+        return;                          // scope 0 at $DIR/issue-72181.rs:16:49: 16:49
+    }
+}
diff --git a/src/test/mir-opt/issue-72181/32bit/rustc.main.mir_map.0.mir b/src/test/mir-opt/issue-72181/32bit/rustc.main.mir_map.0.mir
new file mode 100644
index 00000000000..aa44dcd8eae
--- /dev/null
+++ b/src/test/mir-opt/issue-72181/32bit/rustc.main.mir_map.0.mir
@@ -0,0 +1,93 @@
+// MIR for `main` 0 mir_map
+
+fn main() -> () {
+    let mut _0: ();                      // return place in scope 0 at $DIR/issue-72181.rs:23:11: 23:11
+    let mut _1: usize;                   // in scope 0 at $DIR/issue-72181.rs:24:13: 24:34
+    let mut _3: Foo;                     // in scope 0 at $DIR/issue-72181.rs:26:14: 26:27
+    let mut _4: Foo;                     // in scope 0 at $DIR/issue-72181.rs:26:29: 26:42
+    let mut _5: u64;                     // in scope 0 at $DIR/issue-72181.rs:27:13: 27:30
+    let _6: usize;                       // in scope 0 at $DIR/issue-72181.rs:27:24: 27:25
+    let mut _7: usize;                   // in scope 0 at $DIR/issue-72181.rs:27:22: 27:26
+    let mut _8: bool;                    // in scope 0 at $DIR/issue-72181.rs:27:22: 27:26
+    scope 1 {
+        let _2: [Foo; 2];                // in scope 1 at $DIR/issue-72181.rs:26:9: 26:10
+        scope 2 {
+            debug f => _2;               // in scope 2 at $DIR/issue-72181.rs:26:9: 26:10
+            scope 3 {
+            }
+            scope 4 {
+            }
+        }
+    }
+
+    bb0: {
+        StorageLive(_1);                 // scope 0 at $DIR/issue-72181.rs:24:13: 24:34
+        _1 = const std::mem::size_of::<Foo>() -> [return: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:24:13: 24:34
+                                         // ty::Const
+                                         // + ty: fn() -> usize {std::mem::size_of::<Foo>}
+                                         // + val: Value(Scalar(<ZST>))
+                                         // mir::Constant
+                                         // + span: $DIR/issue-72181.rs:24:13: 24:32
+                                         // + literal: Const { ty: fn() -> usize {std::mem::size_of::<Foo>}, val: Value(Scalar(<ZST>)) }
+    }
+
+    bb1 (cleanup): {
+        resume;                          // scope 0 at $DIR/issue-72181.rs:23:1: 28:2
+    }
+
+    bb2: {
+        StorageDead(_1);                 // scope 0 at $DIR/issue-72181.rs:24:34: 24:35
+        StorageLive(_2);                 // scope 1 at $DIR/issue-72181.rs:26:9: 26:10
+        StorageLive(_3);                 // scope 1 at $DIR/issue-72181.rs:26:14: 26:27
+        _3 = Foo { a: const 42u64 };     // scope 1 at $DIR/issue-72181.rs:26:14: 26:27
+                                         // ty::Const
+                                         // + ty: u64
+                                         // + val: Value(Scalar(0x000000000000002a))
+                                         // mir::Constant
+                                         // + span: $DIR/issue-72181.rs:26:23: 26:25
+                                         // + literal: Const { ty: u64, val: Value(Scalar(0x000000000000002a)) }
+        StorageLive(_4);                 // scope 1 at $DIR/issue-72181.rs:26:29: 26:42
+        _4 = Foo { a: const 10u64 };     // scope 1 at $DIR/issue-72181.rs:26:29: 26:42
+                                         // ty::Const
+                                         // + ty: u64
+                                         // + val: Value(Scalar(0x000000000000000a))
+                                         // mir::Constant
+                                         // + span: $DIR/issue-72181.rs:26:38: 26:40
+                                         // + literal: Const { ty: u64, val: Value(Scalar(0x000000000000000a)) }
+        _2 = [move _3, move _4];         // scope 1 at $DIR/issue-72181.rs:26:13: 26:43
+        StorageDead(_4);                 // scope 1 at $DIR/issue-72181.rs:26:42: 26:43
+        StorageDead(_3);                 // scope 1 at $DIR/issue-72181.rs:26:42: 26:43
+        FakeRead(ForLet, _2);            // scope 1 at $DIR/issue-72181.rs:26:9: 26:10
+        StorageLive(_5);                 // scope 2 at $DIR/issue-72181.rs:27:13: 27:30
+        StorageLive(_6);                 // scope 4 at $DIR/issue-72181.rs:27:24: 27:25
+        _6 = const 0usize;               // scope 4 at $DIR/issue-72181.rs:27:24: 27:25
+                                         // ty::Const
+                                         // + ty: usize
+                                         // + val: Value(Scalar(0x00000000))
+                                         // mir::Constant
+                                         // + span: $DIR/issue-72181.rs:27:24: 27:25
+                                         // + literal: Const { ty: usize, val: Value(Scalar(0x00000000)) }
+        _7 = Len(_2);                    // scope 4 at $DIR/issue-72181.rs:27:22: 27:26
+        _8 = Lt(_6, _7);                 // scope 4 at $DIR/issue-72181.rs:27:22: 27:26
+        assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> [success: bb3, unwind: bb1]; // scope 4 at $DIR/issue-72181.rs:27:22: 27:26
+    }
+
+    bb3: {
+        _5 = (_2[_6].0: u64);            // scope 4 at $DIR/issue-72181.rs:27:22: 27:28
+        StorageDead(_6);                 // scope 2 at $DIR/issue-72181.rs:27:30: 27:31
+        StorageDead(_5);                 // scope 2 at $DIR/issue-72181.rs:27:30: 27:31
+        _0 = const ();                   // scope 0 at $DIR/issue-72181.rs:23:11: 28:2
+                                         // ty::Const
+                                         // + ty: ()
+                                         // + val: Value(Scalar(<ZST>))
+                                         // mir::Constant
+                                         // + span: $DIR/issue-72181.rs:23:11: 28:2
+                                         // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
+        StorageDead(_2);                 // scope 1 at $DIR/issue-72181.rs:28:1: 28:2
+        goto -> bb4;                     // scope 0 at $DIR/issue-72181.rs:28:2: 28:2
+    }
+
+    bb4: {
+        return;                          // scope 0 at $DIR/issue-72181.rs:28:2: 28:2
+    }
+}
diff --git a/src/test/mir-opt/issue-72181/64bit/rustc.bar.mir_map.0.mir b/src/test/mir-opt/issue-72181/64bit/rustc.bar.mir_map.0.mir
new file mode 100644
index 00000000000..29654c2b1f8
--- /dev/null
+++ b/src/test/mir-opt/issue-72181/64bit/rustc.bar.mir_map.0.mir
@@ -0,0 +1,25 @@
+// MIR for `bar` 0 mir_map
+
+fn bar(_1: [(Never, u32); 1]) -> u32 {
+    let mut _0: u32;                     // return place in scope 0 at $DIR/issue-72181.rs:19:40: 19:43
+    let _2: u32;                         // in scope 0 at $DIR/issue-72181.rs:19:13: 19:14
+    scope 1 {
+        debug x => _2;                   // in scope 1 at $DIR/issue-72181.rs:19:13: 19:14
+    }
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/issue-72181.rs:19:13: 19:14
+        _2 = (_1[0 of 1].1: u32);        // scope 0 at $DIR/issue-72181.rs:19:13: 19:14
+        _0 = _2;                         // scope 1 at $DIR/issue-72181.rs:19:46: 19:47
+        StorageDead(_2);                 // scope 0 at $DIR/issue-72181.rs:19:48: 19:49
+        goto -> bb2;                     // scope 0 at $DIR/issue-72181.rs:19:49: 19:49
+    }
+
+    bb1 (cleanup): {
+        resume;                          // scope 0 at $DIR/issue-72181.rs:19:1: 19:49
+    }
+
+    bb2: {
+        return;                          // scope 0 at $DIR/issue-72181.rs:19:49: 19:49
+    }
+}
diff --git a/src/test/mir-opt/issue-72181/64bit/rustc.foo.mir_map.0.mir b/src/test/mir-opt/issue-72181/64bit/rustc.foo.mir_map.0.mir
new file mode 100644
index 00000000000..639019eaf9c
--- /dev/null
+++ b/src/test/mir-opt/issue-72181/64bit/rustc.foo.mir_map.0.mir
@@ -0,0 +1,37 @@
+// MIR for `foo` 0 mir_map
+
+fn foo(_1: [(Never, u32); 1]) -> u32 {
+    debug xs => _1;                      // in scope 0 at $DIR/issue-72181.rs:16:8: 16:10
+    let mut _0: u32;                     // return place in scope 0 at $DIR/issue-72181.rs:16:34: 16:37
+    let _2: usize;                       // in scope 0 at $DIR/issue-72181.rs:16:43: 16:44
+    let mut _3: usize;                   // in scope 0 at $DIR/issue-72181.rs:16:40: 16:45
+    let mut _4: bool;                    // in scope 0 at $DIR/issue-72181.rs:16:40: 16:45
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/issue-72181.rs:16:43: 16:44
+        _2 = const 0usize;               // scope 0 at $DIR/issue-72181.rs:16:43: 16:44
+                                         // ty::Const
+                                         // + ty: usize
+                                         // + val: Value(Scalar(0x0000000000000000))
+                                         // mir::Constant
+                                         // + span: $DIR/issue-72181.rs:16:43: 16:44
+                                         // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) }
+        _3 = Len(_1);                    // scope 0 at $DIR/issue-72181.rs:16:40: 16:45
+        _4 = Lt(_2, _3);                 // scope 0 at $DIR/issue-72181.rs:16:40: 16:45
+        assert(move _4, "index out of bounds: the len is {} but the index is {}", move _3, _2) -> [success: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:16:40: 16:45
+    }
+
+    bb1 (cleanup): {
+        resume;                          // scope 0 at $DIR/issue-72181.rs:16:1: 16:49
+    }
+
+    bb2: {
+        _0 = (_1[_2].1: u32);            // scope 0 at $DIR/issue-72181.rs:16:40: 16:47
+        StorageDead(_2);                 // scope 0 at $DIR/issue-72181.rs:16:48: 16:49
+        goto -> bb3;                     // scope 0 at $DIR/issue-72181.rs:16:49: 16:49
+    }
+
+    bb3: {
+        return;                          // scope 0 at $DIR/issue-72181.rs:16:49: 16:49
+    }
+}
diff --git a/src/test/mir-opt/issue-72181/64bit/rustc.main.mir_map.0.mir b/src/test/mir-opt/issue-72181/64bit/rustc.main.mir_map.0.mir
new file mode 100644
index 00000000000..4098e0e295c
--- /dev/null
+++ b/src/test/mir-opt/issue-72181/64bit/rustc.main.mir_map.0.mir
@@ -0,0 +1,93 @@
+// MIR for `main` 0 mir_map
+
+fn main() -> () {
+    let mut _0: ();                      // return place in scope 0 at $DIR/issue-72181.rs:23:11: 23:11
+    let mut _1: usize;                   // in scope 0 at $DIR/issue-72181.rs:24:13: 24:34
+    let mut _3: Foo;                     // in scope 0 at $DIR/issue-72181.rs:26:14: 26:27
+    let mut _4: Foo;                     // in scope 0 at $DIR/issue-72181.rs:26:29: 26:42
+    let mut _5: u64;                     // in scope 0 at $DIR/issue-72181.rs:27:13: 27:30
+    let _6: usize;                       // in scope 0 at $DIR/issue-72181.rs:27:24: 27:25
+    let mut _7: usize;                   // in scope 0 at $DIR/issue-72181.rs:27:22: 27:26
+    let mut _8: bool;                    // in scope 0 at $DIR/issue-72181.rs:27:22: 27:26
+    scope 1 {
+        let _2: [Foo; 2];                // in scope 1 at $DIR/issue-72181.rs:26:9: 26:10
+        scope 2 {
+            debug f => _2;               // in scope 2 at $DIR/issue-72181.rs:26:9: 26:10
+            scope 3 {
+            }
+            scope 4 {
+            }
+        }
+    }
+
+    bb0: {
+        StorageLive(_1);                 // scope 0 at $DIR/issue-72181.rs:24:13: 24:34
+        _1 = const std::mem::size_of::<Foo>() -> [return: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:24:13: 24:34
+                                         // ty::Const
+                                         // + ty: fn() -> usize {std::mem::size_of::<Foo>}
+                                         // + val: Value(Scalar(<ZST>))
+                                         // mir::Constant
+                                         // + span: $DIR/issue-72181.rs:24:13: 24:32
+                                         // + literal: Const { ty: fn() -> usize {std::mem::size_of::<Foo>}, val: Value(Scalar(<ZST>)) }
+    }
+
+    bb1 (cleanup): {
+        resume;                          // scope 0 at $DIR/issue-72181.rs:23:1: 28:2
+    }
+
+    bb2: {
+        StorageDead(_1);                 // scope 0 at $DIR/issue-72181.rs:24:34: 24:35
+        StorageLive(_2);                 // scope 1 at $DIR/issue-72181.rs:26:9: 26:10
+        StorageLive(_3);                 // scope 1 at $DIR/issue-72181.rs:26:14: 26:27
+        _3 = Foo { a: const 42u64 };     // scope 1 at $DIR/issue-72181.rs:26:14: 26:27
+                                         // ty::Const
+                                         // + ty: u64
+                                         // + val: Value(Scalar(0x000000000000002a))
+                                         // mir::Constant
+                                         // + span: $DIR/issue-72181.rs:26:23: 26:25
+                                         // + literal: Const { ty: u64, val: Value(Scalar(0x000000000000002a)) }
+        StorageLive(_4);                 // scope 1 at $DIR/issue-72181.rs:26:29: 26:42
+        _4 = Foo { a: const 10u64 };     // scope 1 at $DIR/issue-72181.rs:26:29: 26:42
+                                         // ty::Const
+                                         // + ty: u64
+                                         // + val: Value(Scalar(0x000000000000000a))
+                                         // mir::Constant
+                                         // + span: $DIR/issue-72181.rs:26:38: 26:40
+                                         // + literal: Const { ty: u64, val: Value(Scalar(0x000000000000000a)) }
+        _2 = [move _3, move _4];         // scope 1 at $DIR/issue-72181.rs:26:13: 26:43
+        StorageDead(_4);                 // scope 1 at $DIR/issue-72181.rs:26:42: 26:43
+        StorageDead(_3);                 // scope 1 at $DIR/issue-72181.rs:26:42: 26:43
+        FakeRead(ForLet, _2);            // scope 1 at $DIR/issue-72181.rs:26:9: 26:10
+        StorageLive(_5);                 // scope 2 at $DIR/issue-72181.rs:27:13: 27:30
+        StorageLive(_6);                 // scope 4 at $DIR/issue-72181.rs:27:24: 27:25
+        _6 = const 0usize;               // scope 4 at $DIR/issue-72181.rs:27:24: 27:25
+                                         // ty::Const
+                                         // + ty: usize
+                                         // + val: Value(Scalar(0x0000000000000000))
+                                         // mir::Constant
+                                         // + span: $DIR/issue-72181.rs:27:24: 27:25
+                                         // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) }
+        _7 = Len(_2);                    // scope 4 at $DIR/issue-72181.rs:27:22: 27:26
+        _8 = Lt(_6, _7);                 // scope 4 at $DIR/issue-72181.rs:27:22: 27:26
+        assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> [success: bb3, unwind: bb1]; // scope 4 at $DIR/issue-72181.rs:27:22: 27:26
+    }
+
+    bb3: {
+        _5 = (_2[_6].0: u64);            // scope 4 at $DIR/issue-72181.rs:27:22: 27:28
+        StorageDead(_6);                 // scope 2 at $DIR/issue-72181.rs:27:30: 27:31
+        StorageDead(_5);                 // scope 2 at $DIR/issue-72181.rs:27:30: 27:31
+        _0 = const ();                   // scope 0 at $DIR/issue-72181.rs:23:11: 28:2
+                                         // ty::Const
+                                         // + ty: ()
+                                         // + val: Value(Scalar(<ZST>))
+                                         // mir::Constant
+                                         // + span: $DIR/issue-72181.rs:23:11: 28:2
+                                         // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
+        StorageDead(_2);                 // scope 1 at $DIR/issue-72181.rs:28:1: 28:2
+        goto -> bb4;                     // scope 0 at $DIR/issue-72181.rs:28:2: 28:2
+    }
+
+    bb4: {
+        return;                          // scope 0 at $DIR/issue-72181.rs:28:2: 28:2
+    }
+}
diff --git a/src/test/mir-opt/issue-72181/rustc.bar.mir_map.0.mir b/src/test/mir-opt/issue-72181/rustc.bar.mir_map.0.mir
new file mode 100644
index 00000000000..3b6dc46d055
--- /dev/null
+++ b/src/test/mir-opt/issue-72181/rustc.bar.mir_map.0.mir
@@ -0,0 +1,25 @@
+// MIR for `bar` 0 mir_map
+
+fn bar(_1: [(Never, u32); 1]) -> u32 {
+    let mut _0: u32;                     // return place in scope 0 at $DIR/issue-72181.rs:18:40: 18:43
+    let _2: u32;                         // in scope 0 at $DIR/issue-72181.rs:18:13: 18:14
+    scope 1 {
+        debug x => _2;                   // in scope 1 at $DIR/issue-72181.rs:18:13: 18:14
+    }
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/issue-72181.rs:18:13: 18:14
+        _2 = (_1[0 of 1].1: u32);        // scope 0 at $DIR/issue-72181.rs:18:13: 18:14
+        _0 = _2;                         // scope 1 at $DIR/issue-72181.rs:18:46: 18:47
+        StorageDead(_2);                 // scope 0 at $DIR/issue-72181.rs:18:48: 18:49
+        goto -> bb2;                     // scope 0 at $DIR/issue-72181.rs:18:49: 18:49
+    }
+
+    bb1 (cleanup): {
+        resume;                          // scope 0 at $DIR/issue-72181.rs:18:1: 18:49
+    }
+
+    bb2: {
+        return;                          // scope 0 at $DIR/issue-72181.rs:18:49: 18:49
+    }
+}
diff --git a/src/test/mir-opt/issue-72181/rustc.foo.mir_map.0.mir b/src/test/mir-opt/issue-72181/rustc.foo.mir_map.0.mir
new file mode 100644
index 00000000000..2941e282cf4
--- /dev/null
+++ b/src/test/mir-opt/issue-72181/rustc.foo.mir_map.0.mir
@@ -0,0 +1,37 @@
+// MIR for `foo` 0 mir_map
+
+fn foo(_1: [(Never, u32); 1]) -> u32 {
+    debug xs => _1;                      // in scope 0 at $DIR/issue-72181.rs:15:8: 15:10
+    let mut _0: u32;                     // return place in scope 0 at $DIR/issue-72181.rs:15:34: 15:37
+    let _2: usize;                       // in scope 0 at $DIR/issue-72181.rs:15:43: 15:44
+    let mut _3: usize;                   // in scope 0 at $DIR/issue-72181.rs:15:40: 15:45
+    let mut _4: bool;                    // in scope 0 at $DIR/issue-72181.rs:15:40: 15:45
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/issue-72181.rs:15:43: 15:44
+        _2 = const 0usize;               // scope 0 at $DIR/issue-72181.rs:15:43: 15:44
+                                         // ty::Const
+                                         // + ty: usize
+                                         // + val: Value(Scalar(0x0000000000000000))
+                                         // mir::Constant
+                                         // + span: $DIR/issue-72181.rs:15:43: 15:44
+                                         // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) }
+        _3 = Len(_1);                    // scope 0 at $DIR/issue-72181.rs:15:40: 15:45
+        _4 = Lt(_2, _3);                 // scope 0 at $DIR/issue-72181.rs:15:40: 15:45
+        assert(move _4, "index out of bounds: the len is {} but the index is {}", move _3, _2) -> [success: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:15:40: 15:45
+    }
+
+    bb1 (cleanup): {
+        resume;                          // scope 0 at $DIR/issue-72181.rs:15:1: 15:49
+    }
+
+    bb2: {
+        _0 = (_1[_2].1: u32);            // scope 0 at $DIR/issue-72181.rs:15:40: 15:47
+        StorageDead(_2);                 // scope 0 at $DIR/issue-72181.rs:15:48: 15:49
+        goto -> bb3;                     // scope 0 at $DIR/issue-72181.rs:15:49: 15:49
+    }
+
+    bb3: {
+        return;                          // scope 0 at $DIR/issue-72181.rs:15:49: 15:49
+    }
+}
diff --git a/src/test/mir-opt/issue-72181/rustc.main.mir_map.0.mir b/src/test/mir-opt/issue-72181/rustc.main.mir_map.0.mir
new file mode 100644
index 00000000000..65f4de0e235
--- /dev/null
+++ b/src/test/mir-opt/issue-72181/rustc.main.mir_map.0.mir
@@ -0,0 +1,93 @@
+// MIR for `main` 0 mir_map
+
+fn main() -> () {
+    let mut _0: ();                      // return place in scope 0 at $DIR/issue-72181.rs:21:11: 21:11
+    let mut _1: usize;                   // in scope 0 at $DIR/issue-72181.rs:22:13: 22:34
+    let mut _3: Foo;                     // in scope 0 at $DIR/issue-72181.rs:24:14: 24:27
+    let mut _4: Foo;                     // in scope 0 at $DIR/issue-72181.rs:24:29: 24:42
+    let mut _5: u64;                     // in scope 0 at $DIR/issue-72181.rs:25:13: 25:30
+    let _6: usize;                       // in scope 0 at $DIR/issue-72181.rs:25:24: 25:25
+    let mut _7: usize;                   // in scope 0 at $DIR/issue-72181.rs:25:22: 25:26
+    let mut _8: bool;                    // in scope 0 at $DIR/issue-72181.rs:25:22: 25:26
+    scope 1 {
+        let _2: [Foo; 2];                // in scope 1 at $DIR/issue-72181.rs:24:9: 24:10
+        scope 2 {
+            debug f => _2;               // in scope 2 at $DIR/issue-72181.rs:24:9: 24:10
+            scope 3 {
+            }
+            scope 4 {
+            }
+        }
+    }
+
+    bb0: {
+        StorageLive(_1);                 // scope 0 at $DIR/issue-72181.rs:22:13: 22:34
+        _1 = const std::mem::size_of::<Foo>() -> [return: bb2, unwind: bb1]; // scope 0 at $DIR/issue-72181.rs:22:13: 22:34
+                                         // ty::Const
+                                         // + ty: fn() -> usize {std::mem::size_of::<Foo>}
+                                         // + val: Value(Scalar(<ZST>))
+                                         // mir::Constant
+                                         // + span: $DIR/issue-72181.rs:22:13: 22:32
+                                         // + literal: Const { ty: fn() -> usize {std::mem::size_of::<Foo>}, val: Value(Scalar(<ZST>)) }
+    }
+
+    bb1 (cleanup): {
+        resume;                          // scope 0 at $DIR/issue-72181.rs:21:1: 26:2
+    }
+
+    bb2: {
+        StorageDead(_1);                 // scope 0 at $DIR/issue-72181.rs:22:34: 22:35
+        StorageLive(_2);                 // scope 1 at $DIR/issue-72181.rs:24:9: 24:10
+        StorageLive(_3);                 // scope 1 at $DIR/issue-72181.rs:24:14: 24:27
+        _3 = Foo { a: const 42u64 };     // scope 1 at $DIR/issue-72181.rs:24:14: 24:27
+                                         // ty::Const
+                                         // + ty: u64
+                                         // + val: Value(Scalar(0x000000000000002a))
+                                         // mir::Constant
+                                         // + span: $DIR/issue-72181.rs:24:23: 24:25
+                                         // + literal: Const { ty: u64, val: Value(Scalar(0x000000000000002a)) }
+        StorageLive(_4);                 // scope 1 at $DIR/issue-72181.rs:24:29: 24:42
+        _4 = Foo { a: const 10u64 };     // scope 1 at $DIR/issue-72181.rs:24:29: 24:42
+                                         // ty::Const
+                                         // + ty: u64
+                                         // + val: Value(Scalar(0x000000000000000a))
+                                         // mir::Constant
+                                         // + span: $DIR/issue-72181.rs:24:38: 24:40
+                                         // + literal: Const { ty: u64, val: Value(Scalar(0x000000000000000a)) }
+        _2 = [move _3, move _4];         // scope 1 at $DIR/issue-72181.rs:24:13: 24:43
+        StorageDead(_4);                 // scope 1 at $DIR/issue-72181.rs:24:42: 24:43
+        StorageDead(_3);                 // scope 1 at $DIR/issue-72181.rs:24:42: 24:43
+        FakeRead(ForLet, _2);            // scope 1 at $DIR/issue-72181.rs:24:9: 24:10
+        StorageLive(_5);                 // scope 2 at $DIR/issue-72181.rs:25:13: 25:30
+        StorageLive(_6);                 // scope 4 at $DIR/issue-72181.rs:25:24: 25:25
+        _6 = const 0usize;               // scope 4 at $DIR/issue-72181.rs:25:24: 25:25
+                                         // ty::Const
+                                         // + ty: usize
+                                         // + val: Value(Scalar(0x0000000000000000))
+                                         // mir::Constant
+                                         // + span: $DIR/issue-72181.rs:25:24: 25:25
+                                         // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000000)) }
+        _7 = Len(_2);                    // scope 4 at $DIR/issue-72181.rs:25:22: 25:26
+        _8 = Lt(_6, _7);                 // scope 4 at $DIR/issue-72181.rs:25:22: 25:26
+        assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> [success: bb3, unwind: bb1]; // scope 4 at $DIR/issue-72181.rs:25:22: 25:26
+    }
+
+    bb3: {
+        _5 = (_2[_6].0: u64);            // scope 4 at $DIR/issue-72181.rs:25:22: 25:28
+        StorageDead(_6);                 // scope 2 at $DIR/issue-72181.rs:25:30: 25:31
+        StorageDead(_5);                 // scope 2 at $DIR/issue-72181.rs:25:30: 25:31
+        _0 = const ();                   // scope 0 at $DIR/issue-72181.rs:21:11: 26:2
+                                         // ty::Const
+                                         // + ty: ()
+                                         // + val: Value(Scalar(<ZST>))
+                                         // mir::Constant
+                                         // + span: $DIR/issue-72181.rs:21:11: 26:2
+                                         // + literal: Const { ty: (), val: Value(Scalar(<ZST>)) }
+        StorageDead(_2);                 // scope 1 at $DIR/issue-72181.rs:26:1: 26:2
+        goto -> bb4;                     // scope 0 at $DIR/issue-72181.rs:26:2: 26:2
+    }
+
+    bb4: {
+        return;                          // scope 0 at $DIR/issue-72181.rs:26:2: 26:2
+    }
+}
diff --git a/src/test/rustdoc/synthetic_auto/overflow.rs b/src/test/rustdoc/synthetic_auto/overflow.rs
new file mode 100644
index 00000000000..546b3e07793
--- /dev/null
+++ b/src/test/rustdoc/synthetic_auto/overflow.rs
@@ -0,0 +1,35 @@
+// Tests that we don't fail with an overflow error for certain
+// strange types
+// See https://github.com/rust-lang/rust/pull/72936#issuecomment-643676915
+
+pub trait Interner {
+    type InternedType;
+}
+
+struct RustInterner<'tcx> {
+    foo: &'tcx ()
+}
+
+impl<'tcx> Interner for RustInterner<'tcx> {
+    type InternedType = Box<TyData<Self>>;
+}
+
+enum TyData<I: Interner> {
+    FnDef(I::InternedType)
+}
+
+struct VariableKind<I: Interner>(I::InternedType);
+
+// @has overflow/struct.BoundVarsCollector.html
+// @has - '//code' "impl<'tcx> Send for BoundVarsCollector<'tcx>"
+pub struct BoundVarsCollector<'tcx> {
+    val: VariableKind<RustInterner<'tcx>>
+}
+
+fn is_send<T: Send>() {}
+
+struct MyInterner<'tcx> {
+    val: &'tcx ()
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
index 137cb83ccd3..0a05fc6bb82 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
@@ -1,8 +1,8 @@
 error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
-  --> $DIR/project-fn-ret-invariant.rs:48:8
+  --> $DIR/project-fn-ret-invariant.rs:48:4
    |
 LL |    bar(foo, x)
-   |        ^^^
+   |    ^^^^^^^^^^^
    |
 note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 44:8...
   --> $DIR/project-fn-ret-invariant.rs:44:8
diff --git a/src/test/ui/associated-types/defaults-specialization.rs b/src/test/ui/associated-types/defaults-specialization.rs
index d0ed718b839..553705b2a4f 100644
--- a/src/test/ui/associated-types/defaults-specialization.rs
+++ b/src/test/ui/associated-types/defaults-specialization.rs
@@ -1,6 +1,7 @@
 //! Tests the interaction of associated type defaults and specialization.
 
 #![feature(associated_type_defaults, specialization)]
+//~^ WARN the feature `specialization` is incomplete
 
 trait Tr {
     type Ty = u8;
diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr
index 37a4d9b60fd..09a8c8f8a88 100644
--- a/src/test/ui/associated-types/defaults-specialization.stderr
+++ b/src/test/ui/associated-types/defaults-specialization.stderr
@@ -1,5 +1,14 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/defaults-specialization.rs:3:38
+   |
+LL | #![feature(associated_type_defaults, specialization)]
+   |                                      ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0053]: method `make` has an incompatible type for trait
-  --> $DIR/defaults-specialization.rs:18:18
+  --> $DIR/defaults-specialization.rs:19:18
    |
 LL |     fn make() -> Self::Ty {
    |                  -------- type in trait
@@ -11,7 +20,7 @@ LL |     fn make() -> u8 { 0 }
               found fn pointer `fn() -> u8`
 
 error[E0053]: method `make` has an incompatible type for trait
-  --> $DIR/defaults-specialization.rs:34:18
+  --> $DIR/defaults-specialization.rs:35:18
    |
 LL |     fn make() -> Self::Ty {
    |                  -------- type in trait
@@ -26,7 +35,7 @@ LL |     fn make() -> bool { true }
               found fn pointer `fn() -> bool`
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:9:9
+  --> $DIR/defaults-specialization.rs:10:9
    |
 LL |     type Ty = u8;
    |     ------------- associated type defaults can't be assumed inside the trait defining them
@@ -40,7 +49,7 @@ LL |         0u8
                          found type `u8`
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:25:29
+  --> $DIR/defaults-specialization.rs:26:29
    |
 LL |     fn make() -> Self::Ty { 0u8 }
    |                  --------   ^^^ expected associated type, found `u8`
@@ -53,7 +62,7 @@ LL |     fn make() -> Self::Ty { 0u8 }
    = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:43:29
+  --> $DIR/defaults-specialization.rs:44:29
    |
 LL |     default type Ty = bool;
    |     ----------------------- expected this associated type
@@ -67,7 +76,7 @@ LL |     fn make() -> Self::Ty { true }
                          found type `bool`
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:86:32
+  --> $DIR/defaults-specialization.rs:87:32
    |
 LL |     let _: <B<()> as Tr>::Ty = 0u8;
    |            -----------------   ^^^ expected associated type, found `u8`
@@ -77,13 +86,13 @@ LL |     let _: <B<()> as Tr>::Ty = 0u8;
    = note: expected associated type `<B<()> as Tr>::Ty`
                          found type `u8`
 help: a method is available that returns `<B<()> as Tr>::Ty`
-  --> $DIR/defaults-specialization.rs:8:5
+  --> $DIR/defaults-specialization.rs:9:5
    |
 LL |     fn make() -> Self::Ty {
    |     ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make`
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:87:32
+  --> $DIR/defaults-specialization.rs:88:32
    |
 LL |     let _: <B<()> as Tr>::Ty = true;
    |            -----------------   ^^^^ expected associated type, found `bool`
@@ -93,13 +102,13 @@ LL |     let _: <B<()> as Tr>::Ty = true;
    = note: expected associated type `<B<()> as Tr>::Ty`
                          found type `bool`
 help: a method is available that returns `<B<()> as Tr>::Ty`
-  --> $DIR/defaults-specialization.rs:8:5
+  --> $DIR/defaults-specialization.rs:9:5
    |
 LL |     fn make() -> Self::Ty {
    |     ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make`
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:88:33
+  --> $DIR/defaults-specialization.rs:89:33
    |
 LL |     let _: <B2<()> as Tr>::Ty = 0u8;
    |            ------------------   ^^^ expected associated type, found `u8`
@@ -109,13 +118,13 @@ LL |     let _: <B2<()> as Tr>::Ty = 0u8;
    = note: expected associated type `<B2<()> as Tr>::Ty`
                          found type `u8`
 help: a method is available that returns `<B2<()> as Tr>::Ty`
-  --> $DIR/defaults-specialization.rs:8:5
+  --> $DIR/defaults-specialization.rs:9:5
    |
 LL |     fn make() -> Self::Ty {
    |     ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make`
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:89:33
+  --> $DIR/defaults-specialization.rs:90:33
    |
 LL |     let _: <B2<()> as Tr>::Ty = true;
    |            ------------------   ^^^^ expected associated type, found `bool`
@@ -125,12 +134,12 @@ LL |     let _: <B2<()> as Tr>::Ty = true;
    = note: expected associated type `<B2<()> as Tr>::Ty`
                          found type `bool`
 help: a method is available that returns `<B2<()> as Tr>::Ty`
-  --> $DIR/defaults-specialization.rs:8:5
+  --> $DIR/defaults-specialization.rs:9:5
    |
 LL |     fn make() -> Self::Ty {
    |     ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make`
 
-error: aborting due to 9 previous errors
+error: aborting due to 9 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0053, E0308.
 For more information about an error, try `rustc --explain E0053`.
diff --git a/src/test/ui/auto-is-contextual.rs b/src/test/ui/auto-traits/auto-is-contextual.rs
index a2ddd5374c0..a2ddd5374c0 100644
--- a/src/test/ui/auto-is-contextual.rs
+++ b/src/test/ui/auto-traits/auto-is-contextual.rs
diff --git a/src/test/ui/auto-traits/auto-trait-projection-recursion.rs b/src/test/ui/auto-traits/auto-trait-projection-recursion.rs
new file mode 100644
index 00000000000..a36f26f02e9
--- /dev/null
+++ b/src/test/ui/auto-traits/auto-trait-projection-recursion.rs
@@ -0,0 +1,34 @@
+// Checking the `Send` bound in `main` requires:
+//
+// checking             <C<'static> as Y>::P: Send
+// which normalizes to  Box<X<C<'?1>>>: Send
+// which needs          X<C<'?1>>: Send
+// which needs          <C<'?1> as Y>::P: Send
+//
+// At this point we used to normalize the predicate to `Box<X<C<'?2>>>: Send`
+// and continue in a loop where we created new region variables to the
+// recursion limit. To avoid this we now "canonicalize" region variables to
+// lowest unified region vid. This means we instead have to prove
+// `Box<X<C<'?1>>>: Send`, which we can because auto traits are coinductive.
+
+// check-pass
+
+// Avoid a really long error message if this regresses.
+#![recursion_limit="20"]
+
+trait Y {
+    type P;
+}
+
+impl<'a> Y for C<'a> {
+    type P = Box<X<C<'a>>>;
+}
+
+struct C<'a>(&'a ());
+struct X<T: Y>(T::P);
+
+fn is_send<S: Send>() {}
+
+fn main() {
+    is_send::<X<C<'static>>>();
+}
diff --git a/src/test/ui/auto-trait-validation.rs b/src/test/ui/auto-traits/auto-trait-validation.rs
index 34d6c3da00e..34d6c3da00e 100644
--- a/src/test/ui/auto-trait-validation.rs
+++ b/src/test/ui/auto-traits/auto-trait-validation.rs
diff --git a/src/test/ui/auto-trait-validation.stderr b/src/test/ui/auto-traits/auto-trait-validation.stderr
index 4040e66c6af..4040e66c6af 100644
--- a/src/test/ui/auto-trait-validation.stderr
+++ b/src/test/ui/auto-traits/auto-trait-validation.stderr
diff --git a/src/test/ui/traits/auto-traits.rs b/src/test/ui/auto-traits/auto-traits.rs
index 15fdddc5f3f..15fdddc5f3f 100644
--- a/src/test/ui/traits/auto-traits.rs
+++ b/src/test/ui/auto-traits/auto-traits.rs
diff --git a/src/test/ui/issues/issue-23080-2.rs b/src/test/ui/auto-traits/issue-23080-2.rs
index 7f6b9e3fba7..7f6b9e3fba7 100644
--- a/src/test/ui/issues/issue-23080-2.rs
+++ b/src/test/ui/auto-traits/issue-23080-2.rs
diff --git a/src/test/ui/issues/issue-23080-2.stderr b/src/test/ui/auto-traits/issue-23080-2.stderr
index 48ce09aaa34..48ce09aaa34 100644
--- a/src/test/ui/issues/issue-23080-2.stderr
+++ b/src/test/ui/auto-traits/issue-23080-2.stderr
diff --git a/src/test/ui/issues/issue-23080.rs b/src/test/ui/auto-traits/issue-23080.rs
index 035db82ba5d..035db82ba5d 100644
--- a/src/test/ui/issues/issue-23080.rs
+++ b/src/test/ui/auto-traits/issue-23080.rs
diff --git a/src/test/ui/issues/issue-23080.stderr b/src/test/ui/auto-traits/issue-23080.stderr
index 73ecb1c362e..73ecb1c362e 100644
--- a/src/test/ui/issues/issue-23080.stderr
+++ b/src/test/ui/auto-traits/issue-23080.stderr
diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.rs b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs
index 8824a6d2767..8824a6d2767 100644
--- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.rs
+++ b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.rs
diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr
index 63b3300f6db..63b3300f6db 100644
--- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr
+++ b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits-2.stderr
diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.rs b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.rs
index edbca915124..edbca915124 100644
--- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.rs
+++ b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.rs
diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr
index 796638fc54d..796638fc54d 100644
--- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr
+++ b/src/test/ui/auto-traits/typeck-auto-trait-no-supertraits.stderr
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.rs b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.rs
index 71ac2b466c1..71ac2b466c1 100644
--- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.rs
+++ b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.rs
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr
index 53ba9b8a3f6..53ba9b8a3f6 100644
--- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types-2.stderr
+++ b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.rs b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.rs
index 6483b9213dc..6483b9213dc 100644
--- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.rs
+++ b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.rs
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.stderr
index bc500004984..bc500004984 100644
--- a/src/test/ui/typeck/typeck-default-trait-impl-constituent-types.stderr
+++ b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types.stderr
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation.rs b/src/test/ui/auto-traits/typeck-default-trait-impl-negation.rs
index 47cab60625d..47cab60625d 100644
--- a/src/test/ui/typeck/typeck-default-trait-impl-negation.rs
+++ b/src/test/ui/auto-traits/typeck-default-trait-impl-negation.rs
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr b/src/test/ui/auto-traits/typeck-default-trait-impl-negation.stderr
index 76a6994cb00..76a6994cb00 100644
--- a/src/test/ui/typeck/typeck-default-trait-impl-negation.stderr
+++ b/src/test/ui/auto-traits/typeck-default-trait-impl-negation.stderr
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-precedence.rs b/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.rs
index 614a5ff55b1..614a5ff55b1 100644
--- a/src/test/ui/typeck/typeck-default-trait-impl-precedence.rs
+++ b/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.rs
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr b/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr
index 5962d191292..5962d191292 100644
--- a/src/test/ui/typeck/typeck-default-trait-impl-precedence.stderr
+++ b/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr
diff --git a/src/test/ui/check-static-immutable-mut-slices.rs b/src/test/ui/check-static-immutable-mut-slices.rs
index d5e9fb2dede..3be02f6a0f6 100644
--- a/src/test/ui/check-static-immutable-mut-slices.rs
+++ b/src/test/ui/check-static-immutable-mut-slices.rs
@@ -1,6 +1,6 @@
 // Checks that immutable static items can't have mutable slices
 
 static TEST: &'static mut [isize] = &mut [];
-//~^ ERROR references in statics may only refer to immutable values
+//~^ ERROR mutable references are not allowed in statics
 
 pub fn main() { }
diff --git a/src/test/ui/check-static-immutable-mut-slices.stderr b/src/test/ui/check-static-immutable-mut-slices.stderr
index 66fe8646e10..9ffbb483d13 100644
--- a/src/test/ui/check-static-immutable-mut-slices.stderr
+++ b/src/test/ui/check-static-immutable-mut-slices.stderr
@@ -1,12 +1,9 @@
-error[E0658]: references in statics may only refer to immutable values
+error[E0764]: mutable references are not allowed in statics
   --> $DIR/check-static-immutable-mut-slices.rs:3:37
    |
 LL | static TEST: &'static mut [isize] = &mut [];
-   |                                     ^^^^^^^ statics require immutable values
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+   |                                     ^^^^^^^ `&mut` is only allowed in `const fn`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.
+For more information about this error, try `rustc --explain E0764`.
diff --git a/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr b/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr
index 2005bd4dd5c..0c6d11cd321 100644
--- a/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr
+++ b/src/test/ui/closure-expected-type/expect-two-infer-vars-supply-ty-with-bound-region.stderr
@@ -1,8 +1,8 @@
 error[E0282]: type annotations needed
-  --> $DIR/expect-two-infer-vars-supply-ty-with-bound-region.rs:8:27
+  --> $DIR/expect-two-infer-vars-supply-ty-with-bound-region.rs:8:5
    |
 LL |     with_closure(|x: u32, y| {});
-   |                           ^ consider giving this closure parameter a type
+   |     ^^^^^^^^^^^^ cannot infer type for type parameter `B` declared on the function `with_closure`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/coerce/coerce-overloaded-autoderef.rs b/src/test/ui/coerce/coerce-overloaded-autoderef.rs
deleted file mode 100644
index d5484607c8b..00000000000
--- a/src/test/ui/coerce/coerce-overloaded-autoderef.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-// run-pass
-#![allow(unused_braces)]
-#![allow(dead_code)]
-// pretty-expanded FIXME #23616
-
-use std::rc::Rc;
-
-// Examples from the "deref coercions" RFC, at rust-lang/rfcs#241.
-
-fn use_ref<T>(_: &T) {}
-fn use_mut<T>(_: &mut T) {}
-
-fn use_rc<T>(t: Rc<T>) {
-    use_ref(&*t);  // what you have to write today
-    use_ref(&t);   // what you'd be able to write
-    use_ref(&&&&&&t);
-    use_ref(&mut &&&&&t);
-    use_ref(&&&mut &&&t);
-}
-
-fn use_mut_box<T>(mut t: &mut Box<T>) {
-    use_mut(&mut *t); // what you have to write today
-    use_mut(t);       // what you'd be able to write
-    use_mut(&mut &mut &mut t);
-
-    use_ref(&*t);      // what you have to write today
-    use_ref(t);        // what you'd be able to write
-    use_ref(&&&&&&t);
-    use_ref(&mut &&&&&t);
-    use_ref(&&&mut &&&t);
-}
-
-fn use_nested<T>(t: &Box<T>) {
-    use_ref(&**t);  // what you have to write today
-    use_ref(t);     // what you'd be able to write (note: recursive deref)
-    use_ref(&&&&&&t);
-    use_ref(&mut &&&&&t);
-    use_ref(&&&mut &&&t);
-}
-
-fn use_slice(_: &[u8]) {}
-fn use_slice_mut(_: &mut [u8]) {}
-
-fn use_vec(mut v: Vec<u8>) {
-    use_slice_mut(&mut v[..]); // what you have to write today
-    use_slice_mut(&mut v);     // what you'd be able to write
-    use_slice_mut(&mut &mut &mut v);
-
-    use_slice(&v[..]);  // what you have to write today
-    use_slice(&v);      // what you'd be able to write
-    use_slice(&&&&&&v);
-    use_slice(&mut &&&&&v);
-    use_slice(&&&mut &&&v);
-}
-
-fn use_vec_ref(v: &Vec<u8>) {
-    use_slice(&v[..]);  // what you have to write today
-    use_slice(v);       // what you'd be able to write
-    use_slice(&&&&&&v);
-    use_slice(&mut &&&&&v);
-    use_slice(&&&mut &&&v);
-}
-
-fn use_op_rhs(s: &mut String) {
-    *s += {&String::from(" ")};
-}
-
-pub fn main() {}
diff --git a/src/test/ui/coerce/coerce-expect-unsized.rs b/src/test/ui/coercion/coerce-expect-unsized.rs
index d486fdf73ab..d486fdf73ab 100644
--- a/src/test/ui/coerce/coerce-expect-unsized.rs
+++ b/src/test/ui/coercion/coerce-expect-unsized.rs
diff --git a/src/test/ui/coercion/coerce-overloaded-autoderef-fail.rs b/src/test/ui/coercion/coerce-overloaded-autoderef-fail.rs
new file mode 100644
index 00000000000..01d9c1e486a
--- /dev/null
+++ b/src/test/ui/coercion/coerce-overloaded-autoderef-fail.rs
@@ -0,0 +1,32 @@
+fn borrow_mut<T>(x: &mut T) -> &mut T { x }
+fn borrow<T>(x: &T) -> &T { x }
+
+fn borrow_mut2<T>(_: &mut T, _: &mut T) {}
+fn borrow2<T>(_: &mut T, _: &T) {}
+
+fn double_mut_borrow<T>(x: &mut Box<T>) {
+    let y = borrow_mut(x);
+    let z = borrow_mut(x);
+    //~^ ERROR cannot borrow `*x` as mutable more than once at a time
+    drop((y, z));
+}
+
+fn double_imm_borrow(x: &mut Box<i32>) {
+    let y = borrow(x);
+    let z = borrow(x);
+    **x += 1;
+    //~^ ERROR cannot assign to `**x` because it is borrowed
+    drop((y, z));
+}
+
+fn double_mut_borrow2<T>(x: &mut Box<T>) {
+    borrow_mut2(x, x);
+    //~^ ERROR cannot borrow `*x` as mutable more than once at a time
+}
+
+fn double_borrow2<T>(x: &mut Box<T>) {
+    borrow2(x, x);
+    //~^ ERROR cannot borrow `*x` as mutable because it is also borrowed as immutable
+}
+
+pub fn main() {}
diff --git a/src/test/ui/coercion/coerce-overloaded-autoderef.stderr b/src/test/ui/coercion/coerce-overloaded-autoderef-fail.stderr
index 7cdfcb5f4fc..d067c3b3a18 100644
--- a/src/test/ui/coercion/coerce-overloaded-autoderef.stderr
+++ b/src/test/ui/coercion/coerce-overloaded-autoderef-fail.stderr
@@ -1,5 +1,5 @@
 error[E0499]: cannot borrow `*x` as mutable more than once at a time
-  --> $DIR/coerce-overloaded-autoderef.rs:9:24
+  --> $DIR/coerce-overloaded-autoderef-fail.rs:9:24
    |
 LL |     let y = borrow_mut(x);
    |                        - first mutable borrow occurs here
@@ -10,7 +10,7 @@ LL |     drop((y, z));
    |           - first borrow later used here
 
 error[E0506]: cannot assign to `**x` because it is borrowed
-  --> $DIR/coerce-overloaded-autoderef.rs:17:5
+  --> $DIR/coerce-overloaded-autoderef-fail.rs:17:5
    |
 LL |     let y = borrow(x);
    |                    - borrow of `**x` occurs here
@@ -22,7 +22,7 @@ LL |     drop((y, z));
    |           - borrow later used here
 
 error[E0499]: cannot borrow `*x` as mutable more than once at a time
-  --> $DIR/coerce-overloaded-autoderef.rs:23:20
+  --> $DIR/coerce-overloaded-autoderef-fail.rs:23:20
    |
 LL |     borrow_mut2(x, x);
    |     ----------- -  ^ second mutable borrow occurs here
@@ -31,7 +31,7 @@ LL |     borrow_mut2(x, x);
    |     first borrow later used by call
 
 error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable
-  --> $DIR/coerce-overloaded-autoderef.rs:28:5
+  --> $DIR/coerce-overloaded-autoderef-fail.rs:28:5
    |
 LL |     borrow2(x, x);
    |     -------^^^^-^
diff --git a/src/test/ui/coercion/coerce-overloaded-autoderef.rs b/src/test/ui/coercion/coerce-overloaded-autoderef.rs
index 01d9c1e486a..d5484607c8b 100644
--- a/src/test/ui/coercion/coerce-overloaded-autoderef.rs
+++ b/src/test/ui/coercion/coerce-overloaded-autoderef.rs
@@ -1,32 +1,68 @@
-fn borrow_mut<T>(x: &mut T) -> &mut T { x }
-fn borrow<T>(x: &T) -> &T { x }
+// run-pass
+#![allow(unused_braces)]
+#![allow(dead_code)]
+// pretty-expanded FIXME #23616
 
-fn borrow_mut2<T>(_: &mut T, _: &mut T) {}
-fn borrow2<T>(_: &mut T, _: &T) {}
+use std::rc::Rc;
 
-fn double_mut_borrow<T>(x: &mut Box<T>) {
-    let y = borrow_mut(x);
-    let z = borrow_mut(x);
-    //~^ ERROR cannot borrow `*x` as mutable more than once at a time
-    drop((y, z));
+// Examples from the "deref coercions" RFC, at rust-lang/rfcs#241.
+
+fn use_ref<T>(_: &T) {}
+fn use_mut<T>(_: &mut T) {}
+
+fn use_rc<T>(t: Rc<T>) {
+    use_ref(&*t);  // what you have to write today
+    use_ref(&t);   // what you'd be able to write
+    use_ref(&&&&&&t);
+    use_ref(&mut &&&&&t);
+    use_ref(&&&mut &&&t);
+}
+
+fn use_mut_box<T>(mut t: &mut Box<T>) {
+    use_mut(&mut *t); // what you have to write today
+    use_mut(t);       // what you'd be able to write
+    use_mut(&mut &mut &mut t);
+
+    use_ref(&*t);      // what you have to write today
+    use_ref(t);        // what you'd be able to write
+    use_ref(&&&&&&t);
+    use_ref(&mut &&&&&t);
+    use_ref(&&&mut &&&t);
 }
 
-fn double_imm_borrow(x: &mut Box<i32>) {
-    let y = borrow(x);
-    let z = borrow(x);
-    **x += 1;
-    //~^ ERROR cannot assign to `**x` because it is borrowed
-    drop((y, z));
+fn use_nested<T>(t: &Box<T>) {
+    use_ref(&**t);  // what you have to write today
+    use_ref(t);     // what you'd be able to write (note: recursive deref)
+    use_ref(&&&&&&t);
+    use_ref(&mut &&&&&t);
+    use_ref(&&&mut &&&t);
+}
+
+fn use_slice(_: &[u8]) {}
+fn use_slice_mut(_: &mut [u8]) {}
+
+fn use_vec(mut v: Vec<u8>) {
+    use_slice_mut(&mut v[..]); // what you have to write today
+    use_slice_mut(&mut v);     // what you'd be able to write
+    use_slice_mut(&mut &mut &mut v);
+
+    use_slice(&v[..]);  // what you have to write today
+    use_slice(&v);      // what you'd be able to write
+    use_slice(&&&&&&v);
+    use_slice(&mut &&&&&v);
+    use_slice(&&&mut &&&v);
 }
 
-fn double_mut_borrow2<T>(x: &mut Box<T>) {
-    borrow_mut2(x, x);
-    //~^ ERROR cannot borrow `*x` as mutable more than once at a time
+fn use_vec_ref(v: &Vec<u8>) {
+    use_slice(&v[..]);  // what you have to write today
+    use_slice(v);       // what you'd be able to write
+    use_slice(&&&&&&v);
+    use_slice(&mut &&&&&v);
+    use_slice(&&&mut &&&v);
 }
 
-fn double_borrow2<T>(x: &mut Box<T>) {
-    borrow2(x, x);
-    //~^ ERROR cannot borrow `*x` as mutable because it is also borrowed as immutable
+fn use_op_rhs(s: &mut String) {
+    *s += {&String::from(" ")};
 }
 
 pub fn main() {}
diff --git a/src/test/ui/coerce/coerce-reborrow-imm-ptr-arg.rs b/src/test/ui/coercion/coerce-reborrow-imm-ptr-arg.rs
index f033e1b5d2b..f033e1b5d2b 100644
--- a/src/test/ui/coerce/coerce-reborrow-imm-ptr-arg.rs
+++ b/src/test/ui/coercion/coerce-reborrow-imm-ptr-arg.rs
diff --git a/src/test/ui/coerce/coerce-reborrow-imm-ptr-rcvr.rs b/src/test/ui/coercion/coerce-reborrow-imm-ptr-rcvr.rs
index 64a365229cb..64a365229cb 100644
--- a/src/test/ui/coerce/coerce-reborrow-imm-ptr-rcvr.rs
+++ b/src/test/ui/coercion/coerce-reborrow-imm-ptr-rcvr.rs
diff --git a/src/test/ui/coerce/coerce-reborrow-imm-vec-arg.rs b/src/test/ui/coercion/coerce-reborrow-imm-vec-arg.rs
index c2aaae1c73e..c2aaae1c73e 100644
--- a/src/test/ui/coerce/coerce-reborrow-imm-vec-arg.rs
+++ b/src/test/ui/coercion/coerce-reborrow-imm-vec-arg.rs
diff --git a/src/test/ui/coerce/coerce-reborrow-imm-vec-rcvr.rs b/src/test/ui/coercion/coerce-reborrow-imm-vec-rcvr.rs
index 9a5652acf87..9a5652acf87 100644
--- a/src/test/ui/coerce/coerce-reborrow-imm-vec-rcvr.rs
+++ b/src/test/ui/coercion/coerce-reborrow-imm-vec-rcvr.rs
diff --git a/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.rs b/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.rs
new file mode 100644
index 00000000000..48be2d3146b
--- /dev/null
+++ b/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.rs
@@ -0,0 +1,6 @@
+fn test<T>(_a: T, _b: T) {}
+
+fn main() {
+    test(&mut 7, &7);
+    //~^ mismatched types
+}
diff --git a/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.stderr b/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.stderr
new file mode 100644
index 00000000000..59b0ec496f1
--- /dev/null
+++ b/src/test/ui/coercion/coerce-reborrow-multi-arg-fail.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/coerce-reborrow-multi-arg-fail.rs:4:18
+   |
+LL |     test(&mut 7, &7);
+   |                  ^^ types differ in mutability
+   |
+   = note: expected mutable reference `&mut {integer}`
+                      found reference `&{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/coercion/coerce-reborrow-multi-arg.rs b/src/test/ui/coercion/coerce-reborrow-multi-arg.rs
new file mode 100644
index 00000000000..93cd0bb3e27
--- /dev/null
+++ b/src/test/ui/coercion/coerce-reborrow-multi-arg.rs
@@ -0,0 +1,9 @@
+// build-pass
+fn test<T>(_a: T, _b: T) {}
+
+fn main() {
+    test(&7, &7);
+    test(&7, &mut 7);
+    test::<&i32>(&mut 7, &7);
+    test::<&i32>(&mut 7, &mut 7);
+}
diff --git a/src/test/ui/coerce/coerce-reborrow-mut-ptr-arg.rs b/src/test/ui/coercion/coerce-reborrow-mut-ptr-arg.rs
index 76cd6793b3c..76cd6793b3c 100644
--- a/src/test/ui/coerce/coerce-reborrow-mut-ptr-arg.rs
+++ b/src/test/ui/coercion/coerce-reborrow-mut-ptr-arg.rs
diff --git a/src/test/ui/coerce/coerce-reborrow-mut-ptr-rcvr.rs b/src/test/ui/coercion/coerce-reborrow-mut-ptr-rcvr.rs
index e6e7c3a51aa..e6e7c3a51aa 100644
--- a/src/test/ui/coerce/coerce-reborrow-mut-ptr-rcvr.rs
+++ b/src/test/ui/coercion/coerce-reborrow-mut-ptr-rcvr.rs
diff --git a/src/test/ui/coerce/coerce-reborrow-mut-vec-arg.rs b/src/test/ui/coercion/coerce-reborrow-mut-vec-arg.rs
index 2635754f14d..2635754f14d 100644
--- a/src/test/ui/coerce/coerce-reborrow-mut-vec-arg.rs
+++ b/src/test/ui/coercion/coerce-reborrow-mut-vec-arg.rs
diff --git a/src/test/ui/coerce/coerce-reborrow-mut-vec-rcvr.rs b/src/test/ui/coercion/coerce-reborrow-mut-vec-rcvr.rs
index c03336ea37a..c03336ea37a 100644
--- a/src/test/ui/coerce/coerce-reborrow-mut-vec-rcvr.rs
+++ b/src/test/ui/coercion/coerce-reborrow-mut-vec-rcvr.rs
diff --git a/src/test/ui/coercion/coerce-to-bang-cast.rs b/src/test/ui/coercion/coerce-to-bang-cast.rs
index 8ef19480846..85598a42ecc 100644
--- a/src/test/ui/coercion/coerce-to-bang-cast.rs
+++ b/src/test/ui/coercion/coerce-to-bang-cast.rs
@@ -1,7 +1,5 @@
 #![feature(never_type)]
 
-fn foo(x: usize, y: !, z: usize) { }
-
 fn cast_a() {
     let y = {return; 22} as !;
     //~^ ERROR non-primitive cast
diff --git a/src/test/ui/coercion/coerce-to-bang-cast.stderr b/src/test/ui/coercion/coerce-to-bang-cast.stderr
index d3adbd5158d..50e009aa25b 100644
--- a/src/test/ui/coercion/coerce-to-bang-cast.stderr
+++ b/src/test/ui/coercion/coerce-to-bang-cast.stderr
@@ -1,11 +1,11 @@
 error[E0605]: non-primitive cast: `i32` as `!`
-  --> $DIR/coerce-to-bang-cast.rs:6:13
+  --> $DIR/coerce-to-bang-cast.rs:4:13
    |
 LL |     let y = {return; 22} as !;
    |             ^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error[E0605]: non-primitive cast: `i32` as `!`
-  --> $DIR/coerce-to-bang-cast.rs:11:13
+  --> $DIR/coerce-to-bang-cast.rs:9:13
    |
 LL |     let y = 22 as !;
    |             ^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
diff --git a/src/test/ui/coerce/coerce-unify-return.rs b/src/test/ui/coercion/coerce-unify-return.rs
index 95a7ee8fe0f..95a7ee8fe0f 100644
--- a/src/test/ui/coerce/coerce-unify-return.rs
+++ b/src/test/ui/coercion/coerce-unify-return.rs
diff --git a/src/test/ui/coerce/coerce-unify.rs b/src/test/ui/coercion/coerce-unify.rs
index f1818f9bb5a..f1818f9bb5a 100644
--- a/src/test/ui/coerce/coerce-unify.rs
+++ b/src/test/ui/coercion/coerce-unify.rs
diff --git a/src/test/ui/coerce/coerce-unsize-subtype.rs b/src/test/ui/coercion/coerce-unsize-subtype.rs
index 45b53300c5b..45b53300c5b 100644
--- a/src/test/ui/coerce/coerce-unsize-subtype.rs
+++ b/src/test/ui/coercion/coerce-unsize-subtype.rs
diff --git a/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs b/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs
index 7f0e5472c3c..d74d3a2a523 100644
--- a/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs
+++ b/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs
@@ -4,6 +4,7 @@
 //
 // No we expect to run into a more user-friendly cycle error instead.
 #![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
 
 trait Trait<T> { type Assoc; }
 //~^ ERROR E0391
diff --git a/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr b/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr
index 71f997c54c6..7e140480b77 100644
--- a/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr
+++ b/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr
@@ -1,16 +1,25 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:6:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0391]: cycle detected when building specialization graph of trait `Trait`
-  --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:8:1
+  --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:9:1
    |
 LL | trait Trait<T> { type Assoc; }
    | ^^^^^^^^^^^^^^
    |
    = note: ...which again requires building specialization graph of trait `Trait`, completing the cycle
 note: cycle used when coherence checking all impls of trait `Trait`
-  --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:8:1
+  --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:9:1
    |
 LL | trait Trait<T> { type Assoc; }
    | ^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/consts/const-eval/issue-65394.rs b/src/test/ui/consts/const-eval/issue-65394.rs
index b1c058eac9e..2518e4ed40b 100644
--- a/src/test/ui/consts/const-eval/issue-65394.rs
+++ b/src/test/ui/consts/const-eval/issue-65394.rs
@@ -5,7 +5,7 @@
 
 const _: Vec<i32> = {
     let mut x = Vec::<i32>::new(); //~ ERROR destructors cannot be evaluated at compile-time
-    let r = &mut x; //~ ERROR references in constants may only refer to immutable values
+    let r = &mut x; //~ ERROR mutable references are not allowed in constants
     let y = x;
     y
 };
diff --git a/src/test/ui/consts/const-eval/issue-65394.stderr b/src/test/ui/consts/const-eval/issue-65394.stderr
index d85a1a1a3c3..f843a94fabd 100644
--- a/src/test/ui/consts/const-eval/issue-65394.stderr
+++ b/src/test/ui/consts/const-eval/issue-65394.stderr
@@ -1,11 +1,8 @@
-error[E0658]: references in constants may only refer to immutable values
+error[E0764]: mutable references are not allowed in constants
   --> $DIR/issue-65394.rs:8:13
    |
 LL |     let r = &mut x;
-   |             ^^^^^^ constants require immutable values
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+   |             ^^^^^^ `&mut` is only allowed in `const fn`
 
 error[E0493]: destructors cannot be evaluated at compile-time
   --> $DIR/issue-65394.rs:7:9
@@ -15,5 +12,5 @@ LL |     let mut x = Vec::<i32>::new();
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0493, E0658.
+Some errors have detailed explanations: E0493, E0764.
 For more information about an error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/const-multi-ref.rs b/src/test/ui/consts/const-multi-ref.rs
index 5e2be0d4f3f..18645efc887 100644
--- a/src/test/ui/consts/const-multi-ref.rs
+++ b/src/test/ui/consts/const-multi-ref.rs
@@ -3,7 +3,7 @@
 
 const _: i32 = {
     let mut a = 5;
-    let p = &mut a; //~ ERROR references in constants may only refer to immutable values
+    let p = &mut a; //~ ERROR mutable references are not allowed in constants
 
     let reborrow = {p};
     let pp = &reborrow;
diff --git a/src/test/ui/consts/const-multi-ref.stderr b/src/test/ui/consts/const-multi-ref.stderr
index e01dd4e5747..9a7914b4588 100644
--- a/src/test/ui/consts/const-multi-ref.stderr
+++ b/src/test/ui/consts/const-multi-ref.stderr
@@ -1,11 +1,8 @@
-error[E0658]: references in constants may only refer to immutable values
+error[E0764]: mutable references are not allowed in constants
   --> $DIR/const-multi-ref.rs:6:13
    |
 LL |     let p = &mut a;
-   |             ^^^^^^ constants require immutable values
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+   |             ^^^^^^ `&mut` is only allowed in `const fn`
 
 error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
   --> $DIR/const-multi-ref.rs:16:13
@@ -15,5 +12,5 @@ LL |     let p = &a;
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0492, E0658.
+Some errors have detailed explanations: E0492, E0764.
 For more information about an error, try `rustc --explain E0492`.
diff --git a/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs
index 130ba9283b1..5819daa817a 100644
--- a/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs
+++ b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs
@@ -1,5 +1,3 @@
-// check-pass
-
 #![feature(const_mut_refs)]
 #![feature(const_fn)]
 #![feature(raw_ref_op)]
@@ -24,7 +22,9 @@ const fn baz(foo: &mut Foo)-> *mut usize {
 
 const _: () = {
     foo().bar();
+    //~^ ERROR mutable references are not allowed in constants
     baz(&mut foo());
+    //~^ ERROR mutable references are not allowed in constants
 };
 
 fn main() {}
diff --git a/src/test/ui/consts/const-mut-refs/const_mut_address_of.stderr b/src/test/ui/consts/const-mut-refs/const_mut_address_of.stderr
new file mode 100644
index 00000000000..2214ce6ee1c
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/const_mut_address_of.stderr
@@ -0,0 +1,15 @@
+error[E0764]: mutable references are not allowed in constants
+  --> $DIR/const_mut_address_of.rs:24:5
+   |
+LL |     foo().bar();
+   |     ^^^^^ `&mut` is only allowed in `const fn`
+
+error[E0764]: mutable references are not allowed in constants
+  --> $DIR/const_mut_address_of.rs:26:9
+   |
+LL |     baz(&mut foo());
+   |         ^^^^^^^^^^ `&mut` is only allowed in `const fn`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0764`.
diff --git a/src/test/ui/consts/const-mut-refs/const_mut_refs.rs b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs
index 99006a20b1b..9099d5a1b8e 100644
--- a/src/test/ui/consts/const-mut-refs/const_mut_refs.rs
+++ b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![feature(const_mut_refs)]
 
 struct Foo {
@@ -31,6 +29,9 @@ const fn bazz(foo: &mut Foo) -> usize {
 
 fn main() {
     let _: [(); foo().bar()] = [(); 1];
+    //~^ ERROR mutable references are not allowed in constants
     let _: [(); baz(&mut foo())] = [(); 2];
+    //~^ ERROR mutable references are not allowed in constants
     let _: [(); bazz(&mut foo())] = [(); 3];
+    //~^ ERROR mutable references are not allowed in constants
 }
diff --git a/src/test/ui/consts/const-mut-refs/const_mut_refs.stderr b/src/test/ui/consts/const-mut-refs/const_mut_refs.stderr
new file mode 100644
index 00000000000..4ca7b128b7c
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/const_mut_refs.stderr
@@ -0,0 +1,21 @@
+error[E0764]: mutable references are not allowed in constants
+  --> $DIR/const_mut_refs.rs:31:17
+   |
+LL |     let _: [(); foo().bar()] = [(); 1];
+   |                 ^^^^^ `&mut` is only allowed in `const fn`
+
+error[E0764]: mutable references are not allowed in constants
+  --> $DIR/const_mut_refs.rs:33:21
+   |
+LL |     let _: [(); baz(&mut foo())] = [(); 2];
+   |                     ^^^^^^^^^^ `&mut` is only allowed in `const fn`
+
+error[E0764]: mutable references are not allowed in constants
+  --> $DIR/const_mut_refs.rs:35:22
+   |
+LL |     let _: [(); bazz(&mut foo())] = [(); 3];
+   |                      ^^^^^^^^^^ `&mut` is only allowed in `const fn`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0764`.
diff --git a/src/test/ui/consts/const_let_assign3.rs b/src/test/ui/consts/const_let_assign3.rs
index cbe73923e9c..f993a427b48 100644
--- a/src/test/ui/consts/const_let_assign3.rs
+++ b/src/test/ui/consts/const_let_assign3.rs
@@ -13,14 +13,14 @@ impl S {
 
 const FOO: S = {
     let mut s = S { state: 42 };
-    s.foo(3); //~ ERROR references in constants may only refer to immutable values
+    s.foo(3); //~ ERROR mutable references are not allowed in constants
     s
 };
 
 type Array = [u32; {
     let mut x = 2;
     let y = &mut x;
-//~^ ERROR references in constants may only refer to immutable values
+//~^ ERROR mutable references are not allowed in constants
     *y = 42;
 //~^ ERROR constant contains unimplemented expression type
     *y
diff --git a/src/test/ui/consts/const_let_assign3.stderr b/src/test/ui/consts/const_let_assign3.stderr
index 62fd04ea522..dd05a4c0bb0 100644
--- a/src/test/ui/consts/const_let_assign3.stderr
+++ b/src/test/ui/consts/const_let_assign3.stderr
@@ -6,23 +6,17 @@ LL |         self.state = x;
    |
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
-error[E0658]: references in constants may only refer to immutable values
+error[E0764]: mutable references are not allowed in constants
   --> $DIR/const_let_assign3.rs:16:5
    |
 LL |     s.foo(3);
-   |     ^ constants require immutable values
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+   |     ^ `&mut` is only allowed in `const fn`
 
-error[E0658]: references in constants may only refer to immutable values
+error[E0764]: mutable references are not allowed in constants
   --> $DIR/const_let_assign3.rs:22:13
    |
 LL |     let y = &mut x;
-   |             ^^^^^^ constants require immutable values
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+   |             ^^^^^^ `&mut` is only allowed in `const fn`
 
 error[E0019]: constant contains unimplemented expression type
   --> $DIR/const_let_assign3.rs:24:5
@@ -34,5 +28,5 @@ LL |     *y = 42;
 
 error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0019, E0658.
+Some errors have detailed explanations: E0019, E0764.
 For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/projection_qualif.mut_refs.stderr b/src/test/ui/consts/projection_qualif.mut_refs.stderr
index 0945a23f3b1..fad8f011f75 100644
--- a/src/test/ui/consts/projection_qualif.mut_refs.stderr
+++ b/src/test/ui/consts/projection_qualif.mut_refs.stderr
@@ -1,3 +1,9 @@
+error[E0764]: mutable references are not allowed in constants
+  --> $DIR/projection_qualif.rs:10:27
+   |
+LL |         let b: *mut u32 = &mut a;
+   |                           ^^^^^^ `&mut` is only allowed in `const fn`
+
 error[E0658]: dereferencing raw pointers in constants is unstable
   --> $DIR/projection_qualif.rs:11:18
    |
@@ -7,6 +13,7 @@ LL |         unsafe { *b = 5; }
    = note: see issue #51911 <https://github.com/rust-lang/rust/issues/51911> for more information
    = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
+Some errors have detailed explanations: E0658, E0764.
+For more information about an error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/projection_qualif.rs b/src/test/ui/consts/projection_qualif.rs
index cfe8e7f03d5..7db970cf137 100644
--- a/src/test/ui/consts/projection_qualif.rs
+++ b/src/test/ui/consts/projection_qualif.rs
@@ -7,7 +7,7 @@ use std::cell::Cell;
 const FOO: &u32 = {
     let mut a = 42;
     {
-        let b: *mut u32 = &mut a; //[stock]~ ERROR may only refer to immutable values
+        let b: *mut u32 = &mut a; //~ ERROR mutable references are not allowed in constants
         unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants
         //[stock]~^ contains unimplemented expression
     }
diff --git a/src/test/ui/consts/projection_qualif.stock.stderr b/src/test/ui/consts/projection_qualif.stock.stderr
index cfa48d947c9..212f1228645 100644
--- a/src/test/ui/consts/projection_qualif.stock.stderr
+++ b/src/test/ui/consts/projection_qualif.stock.stderr
@@ -1,11 +1,8 @@
-error[E0658]: references in constants may only refer to immutable values
+error[E0764]: mutable references are not allowed in constants
   --> $DIR/projection_qualif.rs:10:27
    |
 LL |         let b: *mut u32 = &mut a;
-   |                           ^^^^^^ constants require immutable values
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+   |                           ^^^^^^ `&mut` is only allowed in `const fn`
 
 error[E0658]: dereferencing raw pointers in constants is unstable
   --> $DIR/projection_qualif.rs:11:18
@@ -26,5 +23,5 @@ LL |         unsafe { *b = 5; }
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0019, E0658.
+Some errors have detailed explanations: E0019, E0658, E0764.
 For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/read_from_static_mut_ref.rs b/src/test/ui/consts/read_from_static_mut_ref.rs
index c18227e0f55..5faa983ab09 100644
--- a/src/test/ui/consts/read_from_static_mut_ref.rs
+++ b/src/test/ui/consts/read_from_static_mut_ref.rs
@@ -1,10 +1,9 @@
-// run-pass
+// We are keeping this test in case we decide to allow mutable references in statics again
 #![feature(const_mut_refs)]
 #![allow(const_err)]
 
-static OH_YES: &mut i32 = &mut 42;
-
+static OH_NO: &mut i32 = &mut 42;
+//~^ ERROR mutable references are not allowed in statics
 fn main() {
-    // Make sure `OH_YES` can be read.
-    assert_eq!(*OH_YES, 42);
+    assert_eq!(*OH_NO, 42);
 }
diff --git a/src/test/ui/consts/read_from_static_mut_ref.stderr b/src/test/ui/consts/read_from_static_mut_ref.stderr
new file mode 100644
index 00000000000..c936ac0b7d5
--- /dev/null
+++ b/src/test/ui/consts/read_from_static_mut_ref.stderr
@@ -0,0 +1,9 @@
+error[E0764]: mutable references are not allowed in statics
+  --> $DIR/read_from_static_mut_ref.rs:5:26
+   |
+LL | static OH_NO: &mut i32 = &mut 42;
+   |                          ^^^^^^^ `&mut` is only allowed in `const fn`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0764`.
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr
index 8db75dd63cf..36c280ca5c6 100644
--- a/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr
@@ -1,9 +1,9 @@
-error[E0080]: could not evaluate static initializer
-  --> $DIR/static_mut_containing_mut_ref2.rs:7:45
+error[E0764]: mutable references are not allowed in statics
+  --> $DIR/static_mut_containing_mut_ref2.rs:7:46
    |
 LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
-   |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ modifying a static's initial value from another static's initializer
+   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^ `&mut` is only allowed in `const fn`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0080`.
+For more information about this error, try `rustc --explain E0764`.
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.rs b/src/test/ui/consts/static_mut_containing_mut_ref2.rs
index 74162fbd54b..a6bbe8d6ec2 100644
--- a/src/test/ui/consts/static_mut_containing_mut_ref2.rs
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.rs
@@ -5,8 +5,7 @@
 static mut STDERR_BUFFER_SPACE: u8 = 0;
 
 pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
-//[mut_refs]~^ ERROR could not evaluate static initializer
-//[stock]~^^ ERROR references in statics may only refer to immutable values
+//~^ ERROR  mutable references are not allowed in statics
 //[stock]~| ERROR static contains unimplemented expression type
 
 fn main() {}
diff --git a/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr b/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr
index cc169351bf2..57fb27e642e 100644
--- a/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr
+++ b/src/test/ui/consts/static_mut_containing_mut_ref2.stock.stderr
@@ -1,11 +1,8 @@
-error[E0658]: references in statics may only refer to immutable values
+error[E0764]: mutable references are not allowed in statics
   --> $DIR/static_mut_containing_mut_ref2.rs:7:46
    |
 LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
-   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^ statics require immutable values
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^ `&mut` is only allowed in `const fn`
 
 error[E0019]: static contains unimplemented expression type
   --> $DIR/static_mut_containing_mut_ref2.rs:7:45
@@ -17,5 +14,5 @@ LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 4
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0019, E0658.
+Some errors have detailed explanations: E0019, E0764.
 For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/consts/trait_specialization.rs b/src/test/ui/consts/trait_specialization.rs
index 8010d2fe1ae..3adbbb53046 100644
--- a/src/test/ui/consts/trait_specialization.rs
+++ b/src/test/ui/consts/trait_specialization.rs
@@ -5,7 +5,7 @@
 // Tests that specialization does not cause optimizations running on polymorphic MIR to resolve
 // to a `default` implementation.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Marker {}
 
diff --git a/src/test/ui/consts/trait_specialization.stderr b/src/test/ui/consts/trait_specialization.stderr
new file mode 100644
index 00000000000..03da7d512e5
--- /dev/null
+++ b/src/test/ui/consts/trait_specialization.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/trait_specialization.rs:8:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/error-codes/E0017.rs b/src/test/ui/error-codes/E0017.rs
index 64be41170d0..818dec1207b 100644
--- a/src/test/ui/error-codes/E0017.rs
+++ b/src/test/ui/error-codes/E0017.rs
@@ -2,10 +2,10 @@ static X: i32 = 1;
 const C: i32 = 2;
 static mut M: i32 = 3;
 
-const CR: &'static mut i32 = &mut C; //~ ERROR E0658
-static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658
+const CR: &'static mut i32 = &mut C; //~ ERROR E0764
+static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0764
                                               //~| ERROR E0019
                                               //~| ERROR cannot borrow
-static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0658
-static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR E0658
+static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0764
+static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR E0764
 fn main() {}
diff --git a/src/test/ui/error-codes/E0017.stderr b/src/test/ui/error-codes/E0017.stderr
index f959ad0d008..c1d96de1dca 100644
--- a/src/test/ui/error-codes/E0017.stderr
+++ b/src/test/ui/error-codes/E0017.stderr
@@ -1,11 +1,8 @@
-error[E0658]: references in constants may only refer to immutable values
+error[E0764]: mutable references are not allowed in constants
   --> $DIR/E0017.rs:5:30
    |
 LL | const CR: &'static mut i32 = &mut C;
-   |                              ^^^^^^ constants require immutable values
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+   |                              ^^^^^^ `&mut` is only allowed in `const fn`
 
 error[E0019]: static contains unimplemented expression type
   --> $DIR/E0017.rs:6:39
@@ -15,14 +12,11 @@ LL | static STATIC_REF: &'static mut i32 = &mut X;
    |
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
-error[E0658]: references in statics may only refer to immutable values
+error[E0764]: mutable references are not allowed in statics
   --> $DIR/E0017.rs:6:39
    |
 LL | static STATIC_REF: &'static mut i32 = &mut X;
-   |                                       ^^^^^^ statics require immutable values
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+   |                                       ^^^^^^ `&mut` is only allowed in `const fn`
 
 error[E0596]: cannot borrow immutable static item `X` as mutable
   --> $DIR/E0017.rs:6:39
@@ -30,25 +24,19 @@ error[E0596]: cannot borrow immutable static item `X` as mutable
 LL | static STATIC_REF: &'static mut i32 = &mut X;
    |                                       ^^^^^^ cannot borrow as mutable
 
-error[E0658]: references in statics may only refer to immutable values
+error[E0764]: mutable references are not allowed in statics
   --> $DIR/E0017.rs:9:38
    |
 LL | static CONST_REF: &'static mut i32 = &mut C;
-   |                                      ^^^^^^ statics require immutable values
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+   |                                      ^^^^^^ `&mut` is only allowed in `const fn`
 
-error[E0658]: references in statics may only refer to immutable values
+error[E0764]: mutable references are not allowed in statics
   --> $DIR/E0017.rs:10:52
    |
 LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M };
-   |                                                    ^^^^^^ statics require immutable values
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+   |                                                    ^^^^^^ `&mut` is only allowed in `const fn`
 
 error: aborting due to 6 previous errors
 
-Some errors have detailed explanations: E0019, E0596, E0658.
+Some errors have detailed explanations: E0019, E0596, E0764.
 For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/error-codes/E0388.rs b/src/test/ui/error-codes/E0388.rs
index 5954e3490b0..13131017c2e 100644
--- a/src/test/ui/error-codes/E0388.rs
+++ b/src/test/ui/error-codes/E0388.rs
@@ -1,10 +1,10 @@
 static X: i32 = 1;
 const C: i32 = 2;
 
-const CR: &'static mut i32 = &mut C; //~ ERROR E0658
-static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658
+const CR: &'static mut i32 = &mut C; //~ ERROR E0764
+static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0019
                                               //~| ERROR cannot borrow
-                                              //~| ERROR E0019
-static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0658
+                                              //~| ERROR E0764
+static CONST_REF: &'static mut i32 = &mut C; //~ ERROR E0764
 
 fn main() {}
diff --git a/src/test/ui/error-codes/E0388.stderr b/src/test/ui/error-codes/E0388.stderr
index 8bdfbac3681..f09100bac43 100644
--- a/src/test/ui/error-codes/E0388.stderr
+++ b/src/test/ui/error-codes/E0388.stderr
@@ -1,11 +1,8 @@
-error[E0658]: references in constants may only refer to immutable values
+error[E0764]: mutable references are not allowed in constants
   --> $DIR/E0388.rs:4:30
    |
 LL | const CR: &'static mut i32 = &mut C;
-   |                              ^^^^^^ constants require immutable values
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+   |                              ^^^^^^ `&mut` is only allowed in `const fn`
 
 error[E0019]: static contains unimplemented expression type
   --> $DIR/E0388.rs:5:39
@@ -15,14 +12,11 @@ LL | static STATIC_REF: &'static mut i32 = &mut X;
    |
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
-error[E0658]: references in statics may only refer to immutable values
+error[E0764]: mutable references are not allowed in statics
   --> $DIR/E0388.rs:5:39
    |
 LL | static STATIC_REF: &'static mut i32 = &mut X;
-   |                                       ^^^^^^ statics require immutable values
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+   |                                       ^^^^^^ `&mut` is only allowed in `const fn`
 
 error[E0596]: cannot borrow immutable static item `X` as mutable
   --> $DIR/E0388.rs:5:39
@@ -30,16 +24,13 @@ error[E0596]: cannot borrow immutable static item `X` as mutable
 LL | static STATIC_REF: &'static mut i32 = &mut X;
    |                                       ^^^^^^ cannot borrow as mutable
 
-error[E0658]: references in statics may only refer to immutable values
+error[E0764]: mutable references are not allowed in statics
   --> $DIR/E0388.rs:8:38
    |
 LL | static CONST_REF: &'static mut i32 = &mut C;
-   |                                      ^^^^^^ statics require immutable values
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+   |                                      ^^^^^^ `&mut` is only allowed in `const fn`
 
 error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0019, E0596, E0658.
+Some errors have detailed explanations: E0019, E0596, E0764.
 For more information about an error, try `rustc --explain E0019`.
diff --git a/src/test/ui/error-codes/E0520.rs b/src/test/ui/error-codes/E0520.rs
index b746ca63590..ead78b7ffa2 100644
--- a/src/test/ui/error-codes/E0520.rs
+++ b/src/test/ui/error-codes/E0520.rs
@@ -1,4 +1,5 @@
 #![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
 
 trait SpaceLlama {
     fn fly(&self);
diff --git a/src/test/ui/error-codes/E0520.stderr b/src/test/ui/error-codes/E0520.stderr
index 72fc85ab1e7..1041ccee937 100644
--- a/src/test/ui/error-codes/E0520.stderr
+++ b/src/test/ui/error-codes/E0520.stderr
@@ -1,5 +1,14 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/E0520.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0520]: `fly` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/E0520.rs:16:5
+  --> $DIR/E0520.rs:17:5
    |
 LL | / impl<T: Clone> SpaceLlama for T {
 LL | |     fn fly(&self) {}
@@ -11,6 +20,6 @@ LL |       default fn fly(&self) {}
    |
    = note: to specialize, `fly` in the parent `impl` must be marked `default`
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0520`.
diff --git a/src/test/ui/impl-trait/equality-rpass.rs b/src/test/ui/impl-trait/equality-rpass.rs
index 05c9e4173b0..607b4a49661 100644
--- a/src/test/ui/impl-trait/equality-rpass.rs
+++ b/src/test/ui/impl-trait/equality-rpass.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo: std::fmt::Debug + Eq {}
 
diff --git a/src/test/ui/impl-trait/equality-rpass.stderr b/src/test/ui/impl-trait/equality-rpass.stderr
new file mode 100644
index 00000000000..1abf05dca82
--- /dev/null
+++ b/src/test/ui/impl-trait/equality-rpass.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/equality-rpass.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/impl-trait/equality.rs b/src/test/ui/impl-trait/equality.rs
index 14b0eeb739a..828b5aac896 100644
--- a/src/test/ui/impl-trait/equality.rs
+++ b/src/test/ui/impl-trait/equality.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo: Copy + ToString {}
 
diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr
index 9178358b60a..628dfb13d4c 100644
--- a/src/test/ui/impl-trait/equality.stderr
+++ b/src/test/ui/impl-trait/equality.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/equality.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0308]: mismatched types
   --> $DIR/equality.rs:15:5
    |
@@ -24,7 +33,7 @@ LL |         n + sum_to(n - 1)
    |
    = help: the trait `std::ops::Add<impl Foo>` is not implemented for `u32`
 
-error: aborting due to 2 previous errors
+error: aborting due to 2 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0277, E0308.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/equality2.rs b/src/test/ui/impl-trait/equality2.rs
index abce8c8c204..2e325867da8 100644
--- a/src/test/ui/impl-trait/equality2.rs
+++ b/src/test/ui/impl-trait/equality2.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo: Copy + ToString {}
 
diff --git a/src/test/ui/impl-trait/equality2.stderr b/src/test/ui/impl-trait/equality2.stderr
index 2454c218ffc..1780931efc5 100644
--- a/src/test/ui/impl-trait/equality2.stderr
+++ b/src/test/ui/impl-trait/equality2.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/equality2.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0308]: mismatched types
   --> $DIR/equality2.rs:25:18
    |
@@ -58,6 +67,6 @@ LL |          x.0);
    = note: expected opaque type `impl Foo` (`i32`)
               found opaque type `impl Foo` (`u32`)
 
-error: aborting due to 4 previous errors
+error: aborting due to 4 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-17718-const-bad-values.rs b/src/test/ui/issues/issue-17718-const-bad-values.rs
index 9355c8ab152..49023f18ddb 100644
--- a/src/test/ui/issues/issue-17718-const-bad-values.rs
+++ b/src/test/ui/issues/issue-17718-const-bad-values.rs
@@ -1,10 +1,10 @@
 const C1: &'static mut [usize] = &mut [];
-//~^ ERROR: references in constants may only refer to immutable values
+//~^ ERROR: mutable references are not allowed in constants
 
 static mut S: usize = 3;
 const C2: &'static mut usize = unsafe { &mut S };
 //~^ ERROR: constants cannot refer to statics
 //~| ERROR: constants cannot refer to statics
-//~| ERROR: references in constants may only refer to immutable values
+//~| ERROR: mutable references are not allowed in constants
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-17718-const-bad-values.stderr b/src/test/ui/issues/issue-17718-const-bad-values.stderr
index 688efcdd022..7c50978d4eb 100644
--- a/src/test/ui/issues/issue-17718-const-bad-values.stderr
+++ b/src/test/ui/issues/issue-17718-const-bad-values.stderr
@@ -1,11 +1,8 @@
-error[E0658]: references in constants may only refer to immutable values
+error[E0764]: mutable references are not allowed in constants
   --> $DIR/issue-17718-const-bad-values.rs:1:34
    |
 LL | const C1: &'static mut [usize] = &mut [];
-   |                                  ^^^^^^^ constants require immutable values
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+   |                                  ^^^^^^^ `&mut` is only allowed in `const fn`
 
 error[E0013]: constants cannot refer to statics
   --> $DIR/issue-17718-const-bad-values.rs:5:46
@@ -23,16 +20,13 @@ LL | const C2: &'static mut usize = unsafe { &mut S };
    |
    = help: consider extracting the value of the `static` to a `const`, and referring to that
 
-error[E0658]: references in constants may only refer to immutable values
+error[E0764]: mutable references are not allowed in constants
   --> $DIR/issue-17718-const-bad-values.rs:5:41
    |
 LL | const C2: &'static mut usize = unsafe { &mut S };
-   |                                         ^^^^^^ constants require immutable values
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+   |                                         ^^^^^^ `&mut` is only allowed in `const fn`
 
 error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0013, E0658.
+Some errors have detailed explanations: E0013, E0764.
 For more information about an error, try `rustc --explain E0013`.
diff --git a/src/test/ui/issues/issue-23046.rs b/src/test/ui/issues/issue-23046.rs
index a68369616d8..75be4a11efd 100644
--- a/src/test/ui/issues/issue-23046.rs
+++ b/src/test/ui/issues/issue-23046.rs
@@ -14,7 +14,7 @@ pub fn let_<'var, VAR, F: for<'v> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>>
 }
 
 fn main() {
-    let ex = |x| { //~ ERROR type annotations needed
-        let_(add(x,x), |y| {
+    let ex = |x| {
+        let_(add(x,x), |y| { //~ ERROR type annotations needed
             let_(add(x, x), |x|x)})};
 }
diff --git a/src/test/ui/issues/issue-23046.stderr b/src/test/ui/issues/issue-23046.stderr
index 12b2eb48e7e..77555fce7c4 100644
--- a/src/test/ui/issues/issue-23046.stderr
+++ b/src/test/ui/issues/issue-23046.stderr
@@ -1,8 +1,13 @@
-error[E0282]: type annotations needed for `Expr<'_, VAR>`
-  --> $DIR/issue-23046.rs:17:15
+error[E0282]: type annotations needed for the closure `fn(Expr<'_, _>) -> Expr<'_, _>`
+  --> $DIR/issue-23046.rs:18:9
    |
-LL |     let ex = |x| {
-   |               ^ consider giving this closure parameter the explicit type `Expr<'_, VAR>`, where the type parameter `VAR` is specified
+LL |         let_(add(x,x), |y| {
+   |         ^^^^ cannot infer type for type parameter `VAR` declared on the function `let_`
+   |
+help: give this closure an explicit return type without `_` placeholders
+   |
+LL |             let_(add(x, x), |x|-> Expr<'_, _> { x })})};
+   |                                ^^^^^^^^^^^^^^^^   ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-35376.rs b/src/test/ui/issues/issue-35376.rs
index eb139ec4d7f..cc35213b93d 100644
--- a/src/test/ui/issues/issue-35376.rs
+++ b/src/test/ui/issues/issue-35376.rs
@@ -1,5 +1,6 @@
 // check-pass
 #![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
 
 fn main() {}
 
diff --git a/src/test/ui/issues/issue-35376.stderr b/src/test/ui/issues/issue-35376.stderr
new file mode 100644
index 00000000000..06c31f3bae0
--- /dev/null
+++ b/src/test/ui/issues/issue-35376.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-35376.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/issues/issue-38091.rs b/src/test/ui/issues/issue-38091.rs
index 00aa810f830..c1262430502 100644
--- a/src/test/ui/issues/issue-38091.rs
+++ b/src/test/ui/issues/issue-38091.rs
@@ -1,5 +1,6 @@
 // run-pass
 #![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
 
 trait Iterate<'a> {
     type Ty: Valid;
diff --git a/src/test/ui/issues/issue-38091.stderr b/src/test/ui/issues/issue-38091.stderr
new file mode 100644
index 00000000000..a9855445f66
--- /dev/null
+++ b/src/test/ui/issues/issue-38091.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-38091.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/issues/issue-46604.rs b/src/test/ui/issues/issue-46604.rs
index e1967eb7655..273187a5a13 100644
--- a/src/test/ui/issues/issue-46604.rs
+++ b/src/test/ui/issues/issue-46604.rs
@@ -1,4 +1,4 @@
-static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];   //~ ERROR E0658
+static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];   //~ ERROR E0764
 fn write<T: AsRef<[u8]>>(buffer: T) { }
 
 fn main() {
diff --git a/src/test/ui/issues/issue-46604.stderr b/src/test/ui/issues/issue-46604.stderr
index 771e368a35d..5421721dec2 100644
--- a/src/test/ui/issues/issue-46604.stderr
+++ b/src/test/ui/issues/issue-46604.stderr
@@ -1,11 +1,8 @@
-error[E0658]: references in statics may only refer to immutable values
+error[E0764]: mutable references are not allowed in statics
   --> $DIR/issue-46604.rs:1:25
    |
 LL | static buf: &mut [u8] = &mut [1u8,2,3,4,5,7];
-   |                         ^^^^^^^^^^^^^^^^^^^^ statics require immutable values
-   |
-   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
-   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+   |                         ^^^^^^^^^^^^^^^^^^^^ `&mut` is only allowed in `const fn`
 
 error[E0594]: cannot assign to `buf[_]`, as `buf` is an immutable static item
   --> $DIR/issue-46604.rs:6:5
@@ -15,5 +12,5 @@ LL |     buf[0]=2;
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0594, E0658.
+Some errors have detailed explanations: E0594, E0764.
 For more information about an error, try `rustc --explain E0594`.
diff --git a/src/test/ui/issues/issue-55380.rs b/src/test/ui/issues/issue-55380.rs
index 862218e2192..f7cb296d3b8 100644
--- a/src/test/ui/issues/issue-55380.rs
+++ b/src/test/ui/issues/issue-55380.rs
@@ -1,6 +1,6 @@
 // run-pass
-
 #![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
 
 pub trait Foo {
     fn abc() -> u32;
diff --git a/src/test/ui/issues/issue-55380.stderr b/src/test/ui/issues/issue-55380.stderr
new file mode 100644
index 00000000000..451beebd106
--- /dev/null
+++ b/src/test/ui/issues/issue-55380.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-55380.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/issues/issue-72690.rs b/src/test/ui/issues/issue-72690.rs
new file mode 100644
index 00000000000..4edbd9ca15d
--- /dev/null
+++ b/src/test/ui/issues/issue-72690.rs
@@ -0,0 +1,62 @@
+fn no_err() {
+    |x: String| x;
+    let _ = String::from("x");
+}
+
+fn err() {
+    String::from("x".as_ref()); //~ ERROR type annotations needed
+}
+
+fn arg_pat_closure_err() {
+    |x| String::from("x".as_ref()); //~ ERROR type annotations needed
+}
+
+fn local_pat_closure_err() {
+    let _ = "x".as_ref(); //~ ERROR type annotations needed
+}
+
+fn err_first_arg_pat() {
+    String::from("x".as_ref()); //~ ERROR type annotations needed
+    |x: String| x;
+}
+
+fn err_second_arg_pat() {
+    |x: String| x;
+    String::from("x".as_ref()); //~ ERROR type annotations needed
+}
+
+fn err_mid_arg_pat() {
+    |x: String| x;
+    |x: String| x;
+    |x: String| x;
+    |x: String| x;
+    String::from("x".as_ref()); //~ ERROR type annotations needed
+    |x: String| x;
+    |x: String| x;
+    |x: String| x;
+    |x: String| x;
+}
+
+fn err_first_local_pat() {
+    String::from("x".as_ref()); //~ ERROR type annotations needed
+    let _ = String::from("x");
+}
+
+fn err_second_local_pat() {
+    let _ = String::from("x");
+    String::from("x".as_ref()); //~ ERROR type annotations needed
+}
+
+fn err_mid_local_pat() {
+    let _ = String::from("x");
+    let _ = String::from("x");
+    let _ = String::from("x");
+    let _ = String::from("x");
+    String::from("x".as_ref()); //~ ERROR type annotations needed
+    let _ = String::from("x");
+    let _ = String::from("x");
+    let _ = String::from("x");
+    let _ = String::from("x");
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-72690.stderr b/src/test/ui/issues/issue-72690.stderr
new file mode 100644
index 00000000000..64e78ddf604
--- /dev/null
+++ b/src/test/ui/issues/issue-72690.stderr
@@ -0,0 +1,88 @@
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:7:5
+   |
+LL |     String::from("x".as_ref());
+   |     ^^^^^^^^^^^^ cannot infer type for struct `std::string::String`
+   |
+   = note: cannot satisfy `std::string::String: std::convert::From<&_>`
+   = note: required by `std::convert::From::from`
+
+error[E0282]: type annotations needed
+  --> $DIR/issue-72690.rs:11:6
+   |
+LL |     |x| String::from("x".as_ref());
+   |      ^ consider giving this closure parameter a type
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:15:17
+   |
+LL |     let _ = "x".as_ref();
+   |                 ^^^^^^ cannot infer type for type `str`
+   |
+   = note: cannot satisfy `str: std::convert::AsRef<_>`
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:19:5
+   |
+LL |     String::from("x".as_ref());
+   |     ^^^^^^^^^^^^ cannot infer type for struct `std::string::String`
+   |
+   = note: cannot satisfy `std::string::String: std::convert::From<&_>`
+   = note: required by `std::convert::From::from`
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:25:5
+   |
+LL |     String::from("x".as_ref());
+   |     ^^^^^^^^^^^^ cannot infer type for struct `std::string::String`
+   |
+   = note: cannot satisfy `std::string::String: std::convert::From<&_>`
+   = note: required by `std::convert::From::from`
+
+error[E0283]: type annotations needed
+  --> $DIR/issue-72690.rs:33:5
+   |
+LL |     String::from("x".as_ref());
+   |     ^^^^^^^^^^^^ cannot infer type for struct `std::string::String`
+   |
+   = note: cannot satisfy `std::string::String: std::convert::From<&_>`
+   = note: required by `std::convert::From::from`
+
+error[E0283]: type annotations needed for `std::string::String`
+  --> $DIR/issue-72690.rs:41:5
+   |
+LL |     String::from("x".as_ref());
+   |     ^^^^^^^^^^^^ cannot infer type for struct `std::string::String`
+LL |     let _ = String::from("x");
+   |         - consider giving this pattern a type
+   |
+   = note: cannot satisfy `std::string::String: std::convert::From<&_>`
+   = note: required by `std::convert::From::from`
+
+error[E0283]: type annotations needed for `std::string::String`
+  --> $DIR/issue-72690.rs:47:5
+   |
+LL |     let _ = String::from("x");
+   |         - consider giving this pattern a type
+LL |     String::from("x".as_ref());
+   |     ^^^^^^^^^^^^ cannot infer type for struct `std::string::String`
+   |
+   = note: cannot satisfy `std::string::String: std::convert::From<&_>`
+   = note: required by `std::convert::From::from`
+
+error[E0283]: type annotations needed for `std::string::String`
+  --> $DIR/issue-72690.rs:55:5
+   |
+LL |     let _ = String::from("x");
+   |         - consider giving this pattern a type
+...
+LL |     String::from("x".as_ref());
+   |     ^^^^^^^^^^^^ cannot infer type for struct `std::string::String`
+   |
+   = note: cannot satisfy `std::string::String: std::convert::From<&_>`
+   = note: required by `std::convert::From::from`
+
+error: aborting due to 9 previous errors
+
+Some errors have detailed explanations: E0282, E0283.
+For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/overlap-doesnt-conflict-with-specialization.rs b/src/test/ui/overlap-doesnt-conflict-with-specialization.rs
index dd09d68367e..1e413120a37 100644
--- a/src/test/ui/overlap-doesnt-conflict-with-specialization.rs
+++ b/src/test/ui/overlap-doesnt-conflict-with-specialization.rs
@@ -1,7 +1,7 @@
 // run-pass
 
 #![feature(marker_trait_attr)]
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 #[marker]
 trait MyMarker {}
diff --git a/src/test/ui/overlap-doesnt-conflict-with-specialization.stderr b/src/test/ui/overlap-doesnt-conflict-with-specialization.stderr
new file mode 100644
index 00000000000..16df31ba2a8
--- /dev/null
+++ b/src/test/ui/overlap-doesnt-conflict-with-specialization.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/overlap-doesnt-conflict-with-specialization.rs:4:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/parser/assoc-static-semantic-fail.rs b/src/test/ui/parser/assoc-static-semantic-fail.rs
index 215a2921315..a8759d2090d 100644
--- a/src/test/ui/parser/assoc-static-semantic-fail.rs
+++ b/src/test/ui/parser/assoc-static-semantic-fail.rs
@@ -1,6 +1,7 @@
 // Semantically, we do not allow e.g., `static X: u8 = 0;` as an associated item.
 
 #![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
 
 fn main() {}
 
diff --git a/src/test/ui/parser/assoc-static-semantic-fail.stderr b/src/test/ui/parser/assoc-static-semantic-fail.stderr
index 612297c9cd8..bc3054c3e30 100644
--- a/src/test/ui/parser/assoc-static-semantic-fail.stderr
+++ b/src/test/ui/parser/assoc-static-semantic-fail.stderr
@@ -1,17 +1,17 @@
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:9:5
+  --> $DIR/assoc-static-semantic-fail.rs:10:5
    |
 LL |     static IA: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:11:5
+  --> $DIR/assoc-static-semantic-fail.rs:12:5
    |
 LL |     static IB: u8;
    |     ^^^^^^^^^^^^^^
 
 error: a static item cannot be `default`
-  --> $DIR/assoc-static-semantic-fail.rs:14:5
+  --> $DIR/assoc-static-semantic-fail.rs:15:5
    |
 LL |     default static IC: u8 = 0;
    |     ^^^^^^^ `default` because of this
@@ -19,13 +19,13 @@ LL |     default static IC: u8 = 0;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:14:5
+  --> $DIR/assoc-static-semantic-fail.rs:15:5
    |
 LL |     default static IC: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a static item cannot be `default`
-  --> $DIR/assoc-static-semantic-fail.rs:17:16
+  --> $DIR/assoc-static-semantic-fail.rs:18:16
    |
 LL |     pub(crate) default static ID: u8;
    |                ^^^^^^^ `default` because of this
@@ -33,25 +33,25 @@ LL |     pub(crate) default static ID: u8;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:17:5
+  --> $DIR/assoc-static-semantic-fail.rs:18:5
    |
 LL |     pub(crate) default static ID: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:24:5
+  --> $DIR/assoc-static-semantic-fail.rs:25:5
    |
 LL |     static TA: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:26:5
+  --> $DIR/assoc-static-semantic-fail.rs:27:5
    |
 LL |     static TB: u8;
    |     ^^^^^^^^^^^^^^
 
 error: a static item cannot be `default`
-  --> $DIR/assoc-static-semantic-fail.rs:28:5
+  --> $DIR/assoc-static-semantic-fail.rs:29:5
    |
 LL |     default static TC: u8 = 0;
    |     ^^^^^^^ `default` because of this
@@ -59,13 +59,13 @@ LL |     default static TC: u8 = 0;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:28:5
+  --> $DIR/assoc-static-semantic-fail.rs:29:5
    |
 LL |     default static TC: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a static item cannot be `default`
-  --> $DIR/assoc-static-semantic-fail.rs:31:16
+  --> $DIR/assoc-static-semantic-fail.rs:32:16
    |
 LL |     pub(crate) default static TD: u8;
    |                ^^^^^^^ `default` because of this
@@ -73,25 +73,25 @@ LL |     pub(crate) default static TD: u8;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:31:5
+  --> $DIR/assoc-static-semantic-fail.rs:32:5
    |
 LL |     pub(crate) default static TD: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:38:5
+  --> $DIR/assoc-static-semantic-fail.rs:39:5
    |
 LL |     static TA: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:40:5
+  --> $DIR/assoc-static-semantic-fail.rs:41:5
    |
 LL |     static TB: u8;
    |     ^^^^^^^^^^^^^^
 
 error: a static item cannot be `default`
-  --> $DIR/assoc-static-semantic-fail.rs:43:5
+  --> $DIR/assoc-static-semantic-fail.rs:44:5
    |
 LL |     default static TC: u8 = 0;
    |     ^^^^^^^ `default` because of this
@@ -99,13 +99,13 @@ LL |     default static TC: u8 = 0;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:43:5
+  --> $DIR/assoc-static-semantic-fail.rs:44:5
    |
 LL |     default static TC: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a static item cannot be `default`
-  --> $DIR/assoc-static-semantic-fail.rs:46:9
+  --> $DIR/assoc-static-semantic-fail.rs:47:9
    |
 LL |     pub default static TD: u8;
    |         ^^^^^^^ `default` because of this
@@ -113,13 +113,13 @@ LL |     pub default static TD: u8;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:46:5
+  --> $DIR/assoc-static-semantic-fail.rs:47:5
    |
 LL |     pub default static TD: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: associated constant in `impl` without body
-  --> $DIR/assoc-static-semantic-fail.rs:11:5
+  --> $DIR/assoc-static-semantic-fail.rs:12:5
    |
 LL |     static IB: u8;
    |     ^^^^^^^^^^^^^-
@@ -127,7 +127,7 @@ LL |     static IB: u8;
    |                  help: provide a definition for the constant: `= <expr>;`
 
 error: associated constant in `impl` without body
-  --> $DIR/assoc-static-semantic-fail.rs:17:5
+  --> $DIR/assoc-static-semantic-fail.rs:18:5
    |
 LL |     pub(crate) default static ID: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -135,13 +135,13 @@ LL |     pub(crate) default static ID: u8;
    |                                     help: provide a definition for the constant: `= <expr>;`
 
 error[E0449]: unnecessary visibility qualifier
-  --> $DIR/assoc-static-semantic-fail.rs:31:5
+  --> $DIR/assoc-static-semantic-fail.rs:32:5
    |
 LL |     pub(crate) default static TD: u8;
    |     ^^^^^^^^^^
 
 error: associated constant in `impl` without body
-  --> $DIR/assoc-static-semantic-fail.rs:40:5
+  --> $DIR/assoc-static-semantic-fail.rs:41:5
    |
 LL |     static TB: u8;
    |     ^^^^^^^^^^^^^-
@@ -149,7 +149,7 @@ LL |     static TB: u8;
    |                  help: provide a definition for the constant: `= <expr>;`
 
 error: associated constant in `impl` without body
-  --> $DIR/assoc-static-semantic-fail.rs:46:5
+  --> $DIR/assoc-static-semantic-fail.rs:47:5
    |
 LL |     pub default static TD: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -157,11 +157,20 @@ LL |     pub default static TD: u8;
    |                              help: provide a definition for the constant: `= <expr>;`
 
 error[E0449]: unnecessary visibility qualifier
-  --> $DIR/assoc-static-semantic-fail.rs:46:5
+  --> $DIR/assoc-static-semantic-fail.rs:47:5
    |
 LL |     pub default static TD: u8;
    |     ^^^ `pub` not permitted here because it's implied
 
-error: aborting due to 24 previous errors
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/assoc-static-semantic-fail.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+error: aborting due to 24 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0449`.
diff --git a/src/test/ui/parser/default.rs b/src/test/ui/parser/default.rs
index 64ba4b55311..52338c1f13a 100644
--- a/src/test/ui/parser/default.rs
+++ b/src/test/ui/parser/default.rs
@@ -1,6 +1,7 @@
 // Test successful and unsuccessful parsing of the `default` contextual keyword
 
 #![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
 
 trait Foo {
     fn foo<T: Default>() -> T;
diff --git a/src/test/ui/parser/default.stderr b/src/test/ui/parser/default.stderr
index 15c49e8b627..dea35666f37 100644
--- a/src/test/ui/parser/default.stderr
+++ b/src/test/ui/parser/default.stderr
@@ -1,5 +1,5 @@
 error: `default` is not followed by an item
-  --> $DIR/default.rs:22:5
+  --> $DIR/default.rs:23:5
    |
 LL |     default pub fn foo<T: Default>() -> T { T::default() }
    |     ^^^^^^^ the `default` qualifier
@@ -7,7 +7,7 @@ LL |     default pub fn foo<T: Default>() -> T { T::default() }
    = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
 
 error: non-item in item list
-  --> $DIR/default.rs:22:13
+  --> $DIR/default.rs:23:13
    |
 LL | impl Foo for u32 {
    |                  - item list starts here
@@ -18,13 +18,22 @@ LL | }
    | - item list ends here
 
 error[E0449]: unnecessary visibility qualifier
-  --> $DIR/default.rs:16:5
+  --> $DIR/default.rs:17:5
    |
 LL |     pub default fn foo<T: Default>() -> T {
    |     ^^^ `pub` not permitted here because it's implied
 
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/default.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0046]: not all trait items implemented, missing: `foo`
-  --> $DIR/default.rs:21:1
+  --> $DIR/default.rs:22:1
    |
 LL |     fn foo<T: Default>() -> T;
    |     -------------------------- `foo` from trait
@@ -32,7 +41,7 @@ LL |     fn foo<T: Default>() -> T;
 LL | impl Foo for u32 {
    | ^^^^^^^^^^^^^^^^ missing `foo` in implementation
 
-error: aborting due to 4 previous errors
+error: aborting due to 4 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0046, E0449.
 For more information about an error, try `rustc --explain E0046`.
diff --git a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs
index 09f967f161e..34aee7f6935 100644
--- a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs
+++ b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 fn main() {}
 
diff --git a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr
index 6bb946d5b64..e8ff93f6323 100644
--- a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr
+++ b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr
@@ -46,5 +46,14 @@ LL |     default fn f2() {}
    |     |
    |     `default` because of this
 
-error: aborting due to 6 previous errors
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/trait-item-with-defaultness-fail-semantic.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+error: aborting due to 6 previous errors; 1 warning emitted
 
diff --git a/src/test/ui/sanitize/incompatible.rs b/src/test/ui/sanitize/incompatible.rs
new file mode 100644
index 00000000000..4947f3b3d8b
--- /dev/null
+++ b/src/test/ui/sanitize/incompatible.rs
@@ -0,0 +1,6 @@
+// compile-flags: -Z sanitizer=address -Z sanitizer=memory --target x86_64-unknown-linux-gnu
+// error-pattern: error: `-Zsanitizer=address` is incompatible with `-Zsanitizer=memory`
+
+#![feature(no_core)]
+#![no_core]
+#![no_main]
diff --git a/src/test/ui/sanitize/incompatible.stderr b/src/test/ui/sanitize/incompatible.stderr
new file mode 100644
index 00000000000..f86db41bac7
--- /dev/null
+++ b/src/test/ui/sanitize/incompatible.stderr
@@ -0,0 +1,4 @@
+error: `-Zsanitizer=address` is incompatible with `-Zsanitizer=memory`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/sanitize/unsupported-target.rs b/src/test/ui/sanitize/unsupported-target.rs
index 444333c3f01..6ccc9988cde 100644
--- a/src/test/ui/sanitize/unsupported-target.rs
+++ b/src/test/ui/sanitize/unsupported-target.rs
@@ -1,6 +1,5 @@
-// ignore-tidy-linelength
 // compile-flags: -Z sanitizer=leak --target i686-unknown-linux-gnu
-// error-pattern: error: LeakSanitizer only works with the `x86_64-unknown-linux-gnu` or `x86_64-apple-darwin` target
+// error-pattern: error: `-Zsanitizer=leak` only works with targets:
 
 #![feature(no_core)]
 #![no_core]
diff --git a/src/test/ui/sanitize/unsupported-target.stderr b/src/test/ui/sanitize/unsupported-target.stderr
index 38be58dd4b3..f9434bc9512 100644
--- a/src/test/ui/sanitize/unsupported-target.stderr
+++ b/src/test/ui/sanitize/unsupported-target.stderr
@@ -1,4 +1,4 @@
-error: LeakSanitizer only works with the `x86_64-unknown-linux-gnu` or `x86_64-apple-darwin` target
+error: `-Zsanitizer=leak` only works with targets: x86_64-apple-darwin, x86_64-unknown-linux-gnu
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/specialization/assoc-ty-graph-cycle.rs b/src/test/ui/specialization/assoc-ty-graph-cycle.rs
index 54d51492ab3..fc39b553a61 100644
--- a/src/test/ui/specialization/assoc-ty-graph-cycle.rs
+++ b/src/test/ui/specialization/assoc-ty-graph-cycle.rs
@@ -2,7 +2,7 @@
 
 // Make sure we don't crash with a cycle error during coherence.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Trait<T> {
     type Assoc;
diff --git a/src/test/ui/specialization/assoc-ty-graph-cycle.stderr b/src/test/ui/specialization/assoc-ty-graph-cycle.stderr
new file mode 100644
index 00000000000..250f48f8e59
--- /dev/null
+++ b/src/test/ui/specialization/assoc-ty-graph-cycle.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/assoc-ty-graph-cycle.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/cross-crate-defaults.rs b/src/test/ui/specialization/cross-crate-defaults.rs
index 79cb6594397..fc28d0c815e 100644
--- a/src/test/ui/specialization/cross-crate-defaults.rs
+++ b/src/test/ui/specialization/cross-crate-defaults.rs
@@ -2,7 +2,7 @@
 
 // aux-build:cross_crates_defaults.rs
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 extern crate cross_crates_defaults;
 
diff --git a/src/test/ui/specialization/cross-crate-defaults.stderr b/src/test/ui/specialization/cross-crate-defaults.stderr
new file mode 100644
index 00000000000..f18bc99d739
--- /dev/null
+++ b/src/test/ui/specialization/cross-crate-defaults.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/cross-crate-defaults.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/defaultimpl/allowed-cross-crate.rs b/src/test/ui/specialization/defaultimpl/allowed-cross-crate.rs
index 15550bcce2a..5d67160eb96 100644
--- a/src/test/ui/specialization/defaultimpl/allowed-cross-crate.rs
+++ b/src/test/ui/specialization/defaultimpl/allowed-cross-crate.rs
@@ -5,7 +5,7 @@
 
 // aux-build:go_trait.rs
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 extern crate go_trait;
 
diff --git a/src/test/ui/specialization/defaultimpl/allowed-cross-crate.stderr b/src/test/ui/specialization/defaultimpl/allowed-cross-crate.stderr
new file mode 100644
index 00000000000..1b50329719d
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/allowed-cross-crate.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/allowed-cross-crate.rs:8:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/defaultimpl/out-of-order.rs b/src/test/ui/specialization/defaultimpl/out-of-order.rs
index f9c73a19cfa..13258ac8c9f 100644
--- a/src/test/ui/specialization/defaultimpl/out-of-order.rs
+++ b/src/test/ui/specialization/defaultimpl/out-of-order.rs
@@ -2,7 +2,7 @@
 
 // Test that you can list the more specific impl before the more general one.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo {
     type Out;
diff --git a/src/test/ui/specialization/defaultimpl/out-of-order.stderr b/src/test/ui/specialization/defaultimpl/out-of-order.stderr
new file mode 100644
index 00000000000..deae021a891
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/out-of-order.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/out-of-order.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/defaultimpl/overlap-projection.rs b/src/test/ui/specialization/defaultimpl/overlap-projection.rs
index ed38bb3fc3a..0add4d5516c 100644
--- a/src/test/ui/specialization/defaultimpl/overlap-projection.rs
+++ b/src/test/ui/specialization/defaultimpl/overlap-projection.rs
@@ -4,7 +4,7 @@
 // projections involve specialization, so long as the associated type is
 // provided by the most specialized impl.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Assoc {
     type Output;
diff --git a/src/test/ui/specialization/defaultimpl/overlap-projection.stderr b/src/test/ui/specialization/defaultimpl/overlap-projection.stderr
new file mode 100644
index 00000000000..46899ca9954
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/overlap-projection.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/overlap-projection.rs:7:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/defaultimpl/projection.rs b/src/test/ui/specialization/defaultimpl/projection.rs
index 897a7aade2f..4a914096932 100644
--- a/src/test/ui/specialization/defaultimpl/projection.rs
+++ b/src/test/ui/specialization/defaultimpl/projection.rs
@@ -1,7 +1,7 @@
 // run-pass
 #![allow(dead_code)]
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Make sure we *can* project non-defaulted associated types
 // cf compile-fail/specialization-default-projection.rs
diff --git a/src/test/ui/specialization/defaultimpl/projection.stderr b/src/test/ui/specialization/defaultimpl/projection.stderr
new file mode 100644
index 00000000000..8629c6c52d4
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/projection.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/projection.rs:4:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/defaultimpl/specialization-no-default.rs b/src/test/ui/specialization/defaultimpl/specialization-no-default.rs
index 37005f839d4..661724eef8a 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-no-default.rs
+++ b/src/test/ui/specialization/defaultimpl/specialization-no-default.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Check a number of scenarios in which one impl tries to override another,
 // without correctly using `default`.
diff --git a/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr b/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr
index 13636b28b12..7958eddbeba 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr
+++ b/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-no-default.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
   --> $DIR/specialization-no-default.rs:20:5
    |
@@ -65,6 +74,6 @@ LL |       fn redundant(&self) {}
    |
    = note: to specialize, `redundant` in the parent `impl` must be marked `default`
 
-error: aborting due to 5 previous errors
+error: aborting due to 5 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0520`.
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs
index 2b8ca6bb1dd..89fef5b5ef9 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs
@@ -3,7 +3,7 @@
 // Tests that we can combine a default impl that supplies one method with a
 // full impl that supplies the other, and they can invoke one another.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo {
     fn foo_one(&self) -> &'static str;
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr
new file mode 100644
index 00000000000..dc377dd10c8
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-trait-item-not-implemented-rpass.rs:6:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs
index 2a121e61aaa..3c5414469fa 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs
@@ -1,6 +1,6 @@
 // Tests that default impls do not have to supply all items but regular impls do.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo {
     fn foo_one(&self) -> &'static str;
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr
index b862a937066..9d1eca1d6af 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-trait-item-not-implemented.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0046]: not all trait items implemented, missing: `foo_two`
   --> $DIR/specialization-trait-item-not-implemented.rs:18:1
    |
@@ -7,6 +16,6 @@ LL |     fn foo_two(&self) -> &'static str;
 LL | impl Foo for MyStruct {}
    | ^^^^^^^^^^^^^^^^^^^^^ missing `foo_two` in implementation
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0046`.
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
index 5c104449fe9..35e3b8725a8 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
@@ -2,7 +2,7 @@
 // - default impls do not have to supply all items and
 // - a default impl does not count as an impl (in this case, an incomplete default impl).
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo {
     fn foo_one(&self) -> &'static str;
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
index a55d79ee035..6b8e559bc36 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-trait-not-implemented.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0599]: no method named `foo_one` found for struct `MyStruct` in the current scope
   --> $DIR/specialization-trait-not-implemented.rs:22:29
    |
@@ -19,6 +28,6 @@ note: `Foo` defines an item `foo_one`, perhaps you need to implement it
 LL | trait Foo {
    | ^^^^^^^^^
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.rs b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.rs
index 232338d9d4d..afd634725e3 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.rs
+++ b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.rs
@@ -1,6 +1,6 @@
 // Tests that a default impl still has to have a WF trait ref.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo<'a, T: Eq + 'a> { }
 
diff --git a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr
index f499c1f5698..d45825651a8 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr
+++ b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-wfcheck.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0277]: the trait bound `U: std::cmp::Eq` is not satisfied
   --> $DIR/specialization-wfcheck.rs:7:17
    |
@@ -12,6 +21,6 @@ help: consider restricting type parameter `U`
 LL | default impl<U: std::cmp::Eq> Foo<'static, U> for () {}
    |               ^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/specialization/defaultimpl/validation.rs b/src/test/ui/specialization/defaultimpl/validation.rs
index 8134333c58f..8558a1efb82 100644
--- a/src/test/ui/specialization/defaultimpl/validation.rs
+++ b/src/test/ui/specialization/defaultimpl/validation.rs
@@ -1,5 +1,5 @@
 #![feature(negative_impls)]
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 struct S;
 struct Z;
diff --git a/src/test/ui/specialization/defaultimpl/validation.stderr b/src/test/ui/specialization/defaultimpl/validation.stderr
index 254eaf51a64..2449849725f 100644
--- a/src/test/ui/specialization/defaultimpl/validation.stderr
+++ b/src/test/ui/specialization/defaultimpl/validation.stderr
@@ -8,6 +8,15 @@ LL | default impl S {}
    |
    = note: only trait implementations may be annotated with `default`
 
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/validation.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error: impls of auto traits cannot be default
   --> $DIR/validation.rs:9:21
    |
@@ -36,6 +45,6 @@ error[E0750]: negative impls cannot be default impls
 LL | default impl !Tr for S {}
    | ^^^^^^^      ^
 
-error: aborting due to 5 previous errors
+error: aborting due to 5 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0750`.
diff --git a/src/test/ui/specialization/issue-36804.rs b/src/test/ui/specialization/issue-36804.rs
index 9546a5dd5f5..89350602f36 100644
--- a/src/test/ui/specialization/issue-36804.rs
+++ b/src/test/ui/specialization/issue-36804.rs
@@ -1,5 +1,5 @@
 // check-pass
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 pub struct Cloned<I>(I);
 
diff --git a/src/test/ui/specialization/issue-36804.stderr b/src/test/ui/specialization/issue-36804.stderr
new file mode 100644
index 00000000000..744d8820424
--- /dev/null
+++ b/src/test/ui/specialization/issue-36804.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-36804.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/issue-39448.rs b/src/test/ui/specialization/issue-39448.rs
index 8ac6d8e9311..9dd47a4a17e 100644
--- a/src/test/ui/specialization/issue-39448.rs
+++ b/src/test/ui/specialization/issue-39448.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Regression test for a specialization-related ICE (#39448).
 
diff --git a/src/test/ui/specialization/issue-39448.stderr b/src/test/ui/specialization/issue-39448.stderr
index 861a1d9e8fc..f3bb69b8f71 100644
--- a/src/test/ui/specialization/issue-39448.stderr
+++ b/src/test/ui/specialization/issue-39448.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-39448.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0275]: overflow evaluating the requirement `T: FromA<U>`
   --> $DIR/issue-39448.rs:45:13
    |
@@ -7,6 +16,6 @@ LL |     x.foo(y.to()).to()
    = note: required because of the requirements on the impl of `FromA<U>` for `T`
    = note: required because of the requirements on the impl of `ToA<T>` for `U`
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/specialization/issue-39618.rs b/src/test/ui/specialization/issue-39618.rs
index 20e81e4359b..72630ee9c70 100644
--- a/src/test/ui/specialization/issue-39618.rs
+++ b/src/test/ui/specialization/issue-39618.rs
@@ -4,7 +4,7 @@
 
 // check-pass
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo {
     fn foo(&self);
diff --git a/src/test/ui/specialization/issue-39618.stderr b/src/test/ui/specialization/issue-39618.stderr
new file mode 100644
index 00000000000..d40d17d8f71
--- /dev/null
+++ b/src/test/ui/specialization/issue-39618.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-39618.rs:7:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/issue-50452.rs b/src/test/ui/specialization/issue-50452.rs
index 93f081d9558..29fc12066e8 100644
--- a/src/test/ui/specialization/issue-50452.rs
+++ b/src/test/ui/specialization/issue-50452.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 pub trait Foo {
     fn foo();
diff --git a/src/test/ui/specialization/issue-50452.stderr b/src/test/ui/specialization/issue-50452.stderr
new file mode 100644
index 00000000000..c01817e0b27
--- /dev/null
+++ b/src/test/ui/specialization/issue-50452.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-50452.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/issue-52050.rs b/src/test/ui/specialization/issue-52050.rs
index 1e1bfe9cf07..80465870206 100644
--- a/src/test/ui/specialization/issue-52050.rs
+++ b/src/test/ui/specialization/issue-52050.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Regression test for #52050: when inserting the blanket impl `I`
 // into the tree, we had to replace the child node for `Foo`, which
diff --git a/src/test/ui/specialization/issue-52050.stderr b/src/test/ui/specialization/issue-52050.stderr
index 36f96b01198..a7564ced055 100644
--- a/src/test/ui/specialization/issue-52050.stderr
+++ b/src/test/ui/specialization/issue-52050.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-52050.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0119]: conflicting implementations of trait `IntoPyDictPointer` for type `()`:
   --> $DIR/issue-52050.rs:28:1
    |
@@ -13,6 +22,6 @@ LL |   impl IntoPyDictPointer for ()
    |
    = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/specialization/issue-63716-parse-async.rs b/src/test/ui/specialization/issue-63716-parse-async.rs
index c3764ffaab8..10f185c3351 100644
--- a/src/test/ui/specialization/issue-63716-parse-async.rs
+++ b/src/test/ui/specialization/issue-63716-parse-async.rs
@@ -4,7 +4,7 @@
 // check-pass
 // edition:2018
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 fn main() {}
 
diff --git a/src/test/ui/specialization/issue-63716-parse-async.stderr b/src/test/ui/specialization/issue-63716-parse-async.stderr
new file mode 100644
index 00000000000..43620e1ba51
--- /dev/null
+++ b/src/test/ui/specialization/issue-63716-parse-async.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-63716-parse-async.rs:7:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/issue-70442.rs b/src/test/ui/specialization/issue-70442.rs
index 4371dd2e167..d41b5355c2c 100644
--- a/src/test/ui/specialization/issue-70442.rs
+++ b/src/test/ui/specialization/issue-70442.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // check-pass
 
diff --git a/src/test/ui/specialization/issue-70442.stderr b/src/test/ui/specialization/issue-70442.stderr
new file mode 100644
index 00000000000..f71e4c7dd1c
--- /dev/null
+++ b/src/test/ui/specialization/issue-70442.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-70442.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/non-defaulted-item-fail.rs b/src/test/ui/specialization/non-defaulted-item-fail.rs
index 403f718d7dd..b7d6ac829dd 100644
--- a/src/test/ui/specialization/non-defaulted-item-fail.rs
+++ b/src/test/ui/specialization/non-defaulted-item-fail.rs
@@ -1,4 +1,5 @@
 #![feature(specialization, associated_type_defaults)]
+//~^ WARN the feature `specialization` is incomplete
 
 // Test that attempting to override a non-default method or one not in the
 // parent impl causes an error.
diff --git a/src/test/ui/specialization/non-defaulted-item-fail.stderr b/src/test/ui/specialization/non-defaulted-item-fail.stderr
index e6c5fc1441b..eae045b92c0 100644
--- a/src/test/ui/specialization/non-defaulted-item-fail.stderr
+++ b/src/test/ui/specialization/non-defaulted-item-fail.stderr
@@ -1,5 +1,14 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/non-defaulted-item-fail.rs:1:12
+   |
+LL | #![feature(specialization, associated_type_defaults)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/non-defaulted-item-fail.rs:29:5
+  --> $DIR/non-defaulted-item-fail.rs:30:5
    |
 LL | / impl<T> Foo for Box<T> {
 LL | |     type Ty = bool;
@@ -14,7 +23,7 @@ LL |       type Ty = Vec<()>;
    = note: to specialize, `Ty` in the parent `impl` must be marked `default`
 
 error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/non-defaulted-item-fail.rs:31:5
+  --> $DIR/non-defaulted-item-fail.rs:32:5
    |
 LL | / impl<T> Foo for Box<T> {
 LL | |     type Ty = bool;
@@ -29,7 +38,7 @@ LL |       const CONST: u8 = 42;
    = note: to specialize, `CONST` in the parent `impl` must be marked `default`
 
 error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/non-defaulted-item-fail.rs:33:5
+  --> $DIR/non-defaulted-item-fail.rs:34:5
    |
 LL | / impl<T> Foo for Box<T> {
 LL | |     type Ty = bool;
@@ -44,7 +53,7 @@ LL |       fn foo(&self) -> bool { true }
    = note: to specialize, `foo` in the parent `impl` must be marked `default`
 
 error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/non-defaulted-item-fail.rs:45:5
+  --> $DIR/non-defaulted-item-fail.rs:46:5
    |
 LL | impl<T> Foo for Vec<T> {}
    | ------------------------- parent `impl` is here
@@ -55,7 +64,7 @@ LL |     type Ty = Vec<()>;
    = note: to specialize, `Ty` in the parent `impl` must be marked `default`
 
 error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/non-defaulted-item-fail.rs:47:5
+  --> $DIR/non-defaulted-item-fail.rs:48:5
    |
 LL | impl<T> Foo for Vec<T> {}
    | ------------------------- parent `impl` is here
@@ -66,7 +75,7 @@ LL |     const CONST: u8 = 42;
    = note: to specialize, `CONST` in the parent `impl` must be marked `default`
 
 error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/non-defaulted-item-fail.rs:49:5
+  --> $DIR/non-defaulted-item-fail.rs:50:5
    |
 LL | impl<T> Foo for Vec<T> {}
    | ------------------------- parent `impl` is here
@@ -76,6 +85,6 @@ LL |     fn foo(&self) -> bool { true }
    |
    = note: to specialize, `foo` in the parent `impl` must be marked `default`
 
-error: aborting due to 6 previous errors
+error: aborting due to 6 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0520`.
diff --git a/src/test/ui/specialization/specialization-allowed-cross-crate.rs b/src/test/ui/specialization/specialization-allowed-cross-crate.rs
index 15550bcce2a..5d67160eb96 100644
--- a/src/test/ui/specialization/specialization-allowed-cross-crate.rs
+++ b/src/test/ui/specialization/specialization-allowed-cross-crate.rs
@@ -5,7 +5,7 @@
 
 // aux-build:go_trait.rs
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 extern crate go_trait;
 
diff --git a/src/test/ui/specialization/specialization-allowed-cross-crate.stderr b/src/test/ui/specialization/specialization-allowed-cross-crate.stderr
new file mode 100644
index 00000000000..7d087545725
--- /dev/null
+++ b/src/test/ui/specialization/specialization-allowed-cross-crate.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-allowed-cross-crate.rs:8:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-assoc-fns.rs b/src/test/ui/specialization/specialization-assoc-fns.rs
index b6a7a48972a..cbfcb4719f6 100644
--- a/src/test/ui/specialization/specialization-assoc-fns.rs
+++ b/src/test/ui/specialization/specialization-assoc-fns.rs
@@ -2,7 +2,7 @@
 
 // Test that non-method associated functions can be specialized
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo {
     fn mk() -> Self;
diff --git a/src/test/ui/specialization/specialization-assoc-fns.stderr b/src/test/ui/specialization/specialization-assoc-fns.stderr
new file mode 100644
index 00000000000..b12738604ea
--- /dev/null
+++ b/src/test/ui/specialization/specialization-assoc-fns.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-assoc-fns.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-basics.rs b/src/test/ui/specialization/specialization-basics.rs
index 6c359e51bc2..721c934dbfa 100644
--- a/src/test/ui/specialization/specialization-basics.rs
+++ b/src/test/ui/specialization/specialization-basics.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Tests a variety of basic specialization scenarios and method
 // dispatch for them.
diff --git a/src/test/ui/specialization/specialization-basics.stderr b/src/test/ui/specialization/specialization-basics.stderr
new file mode 100644
index 00000000000..ad00cd81df1
--- /dev/null
+++ b/src/test/ui/specialization/specialization-basics.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-basics.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-cross-crate.rs b/src/test/ui/specialization/specialization-cross-crate.rs
index fa63c866329..4171505aa37 100644
--- a/src/test/ui/specialization/specialization-cross-crate.rs
+++ b/src/test/ui/specialization/specialization-cross-crate.rs
@@ -2,7 +2,7 @@
 
 // aux-build:specialization_cross_crate.rs
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 extern crate specialization_cross_crate;
 
diff --git a/src/test/ui/specialization/specialization-cross-crate.stderr b/src/test/ui/specialization/specialization-cross-crate.stderr
new file mode 100644
index 00000000000..7481eed796d
--- /dev/null
+++ b/src/test/ui/specialization/specialization-cross-crate.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-cross-crate.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-default-methods.rs b/src/test/ui/specialization/specialization-default-methods.rs
index 9ae3d1e9f39..dcf68afa945 100644
--- a/src/test/ui/specialization/specialization-default-methods.rs
+++ b/src/test/ui/specialization/specialization-default-methods.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Test that default methods are cascaded correctly
 
diff --git a/src/test/ui/specialization/specialization-default-methods.stderr b/src/test/ui/specialization/specialization-default-methods.stderr
new file mode 100644
index 00000000000..4fa19adad06
--- /dev/null
+++ b/src/test/ui/specialization/specialization-default-methods.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-default-methods.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-default-projection.rs b/src/test/ui/specialization/specialization-default-projection.rs
index e9343f23601..7f3ae951287 100644
--- a/src/test/ui/specialization/specialization-default-projection.rs
+++ b/src/test/ui/specialization/specialization-default-projection.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Make sure we can't project defaulted associated types
 
diff --git a/src/test/ui/specialization/specialization-default-projection.stderr b/src/test/ui/specialization/specialization-default-projection.stderr
index ac15ab0681a..456eb6d5ca5 100644
--- a/src/test/ui/specialization/specialization-default-projection.stderr
+++ b/src/test/ui/specialization/specialization-default-projection.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-default-projection.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0308]: mismatched types
   --> $DIR/specialization-default-projection.rs:21:5
    |
@@ -28,6 +37,6 @@ LL |     generic::<()>()
    = help: consider constraining the associated type `<() as Foo>::Assoc` to `()`
    = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 
-error: aborting due to 2 previous errors
+error: aborting due to 2 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/specialization/specialization-default-types.rs b/src/test/ui/specialization/specialization-default-types.rs
index acb86d889d4..346471f11e4 100644
--- a/src/test/ui/specialization/specialization-default-types.rs
+++ b/src/test/ui/specialization/specialization-default-types.rs
@@ -2,7 +2,7 @@
 // associated type in the impl defining it -- otherwise, what happens
 // if it's overridden?
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Example {
     type Output;
diff --git a/src/test/ui/specialization/specialization-default-types.stderr b/src/test/ui/specialization/specialization-default-types.stderr
index 7233387eba1..5e0221f0788 100644
--- a/src/test/ui/specialization/specialization-default-types.stderr
+++ b/src/test/ui/specialization/specialization-default-types.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-default-types.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0308]: mismatched types
   --> $DIR/specialization-default-types.rs:15:9
    |
@@ -24,6 +33,6 @@ LL |     Example::generate(t)
    = help: consider constraining the associated type `<T as Example>::Output` to `std::boxed::Box<T>`
    = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 
-error: aborting due to 2 previous errors
+error: aborting due to 2 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/specialization/specialization-no-default.rs b/src/test/ui/specialization/specialization-no-default.rs
index 57346b26d24..ae739b2358d 100644
--- a/src/test/ui/specialization/specialization-no-default.rs
+++ b/src/test/ui/specialization/specialization-no-default.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Check a number of scenarios in which one impl tries to override another,
 // without correctly using `default`.
diff --git a/src/test/ui/specialization/specialization-no-default.stderr b/src/test/ui/specialization/specialization-no-default.stderr
index 992e9abbd4c..bb8b2a6c98e 100644
--- a/src/test/ui/specialization/specialization-no-default.stderr
+++ b/src/test/ui/specialization/specialization-no-default.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-no-default.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
   --> $DIR/specialization-no-default.rs:20:5
    |
@@ -65,6 +74,6 @@ LL |       default fn redundant(&self) {}
    |
    = note: to specialize, `redundant` in the parent `impl` must be marked `default`
 
-error: aborting due to 5 previous errors
+error: aborting due to 5 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0520`.
diff --git a/src/test/ui/specialization/specialization-on-projection.rs b/src/test/ui/specialization/specialization-on-projection.rs
index 5606eaea307..be8dcc4232e 100644
--- a/src/test/ui/specialization/specialization-on-projection.rs
+++ b/src/test/ui/specialization/specialization-on-projection.rs
@@ -1,7 +1,7 @@
 // run-pass
 #![allow(dead_code)]
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Ensure that specialization works for impls defined directly on a projection
 
diff --git a/src/test/ui/specialization/specialization-on-projection.stderr b/src/test/ui/specialization/specialization-on-projection.stderr
new file mode 100644
index 00000000000..d91668d10c5
--- /dev/null
+++ b/src/test/ui/specialization/specialization-on-projection.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-on-projection.rs:4:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-out-of-order.rs b/src/test/ui/specialization/specialization-out-of-order.rs
index 94e764f7636..cb7563e2760 100644
--- a/src/test/ui/specialization/specialization-out-of-order.rs
+++ b/src/test/ui/specialization/specialization-out-of-order.rs
@@ -2,7 +2,7 @@
 
 // Test that you can list the more specific impl before the more general one.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo {
     type Out;
diff --git a/src/test/ui/specialization/specialization-out-of-order.stderr b/src/test/ui/specialization/specialization-out-of-order.stderr
new file mode 100644
index 00000000000..a17f9f11a3f
--- /dev/null
+++ b/src/test/ui/specialization/specialization-out-of-order.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-out-of-order.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-overlap-negative.rs b/src/test/ui/specialization/specialization-overlap-negative.rs
index 90dbef3075b..550d3708295 100644
--- a/src/test/ui/specialization/specialization-overlap-negative.rs
+++ b/src/test/ui/specialization/specialization-overlap-negative.rs
@@ -1,5 +1,5 @@
 #![feature(negative_impls)]
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait MyTrait {}
 
diff --git a/src/test/ui/specialization/specialization-overlap-negative.stderr b/src/test/ui/specialization/specialization-overlap-negative.stderr
index e2616534d20..6141174ba8c 100644
--- a/src/test/ui/specialization/specialization-overlap-negative.stderr
+++ b/src/test/ui/specialization/specialization-overlap-negative.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-overlap-negative.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0751]: found both positive and negative implementation of trait `std::marker::Send` for type `TestType<_>`:
   --> $DIR/specialization-overlap-negative.rs:9:1
    |
@@ -6,6 +15,6 @@ LL | unsafe impl<T: Clone> Send for TestType<T> {}
 LL | impl<T: MyTrait> !Send for TestType<T> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0751`.
diff --git a/src/test/ui/specialization/specialization-overlap-projection.rs b/src/test/ui/specialization/specialization-overlap-projection.rs
index 00b83c7e7a1..b07efb2a5c1 100644
--- a/src/test/ui/specialization/specialization-overlap-projection.rs
+++ b/src/test/ui/specialization/specialization-overlap-projection.rs
@@ -4,7 +4,7 @@
 // projections involve specialization, so long as the associated type is
 // provided by the most specialized impl.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Assoc {
     type Output;
diff --git a/src/test/ui/specialization/specialization-overlap-projection.stderr b/src/test/ui/specialization/specialization-overlap-projection.stderr
new file mode 100644
index 00000000000..6f1a594bacb
--- /dev/null
+++ b/src/test/ui/specialization/specialization-overlap-projection.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-overlap-projection.rs:7:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-overlap.rs b/src/test/ui/specialization/specialization-overlap.rs
index c8ef8d61c1e..6bee22ceb8b 100644
--- a/src/test/ui/specialization/specialization-overlap.rs
+++ b/src/test/ui/specialization/specialization-overlap.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo { fn foo() {} }
 impl<T: Clone> Foo for T {}
diff --git a/src/test/ui/specialization/specialization-overlap.stderr b/src/test/ui/specialization/specialization-overlap.stderr
index 4275e7bdd85..cf0f186a183 100644
--- a/src/test/ui/specialization/specialization-overlap.stderr
+++ b/src/test/ui/specialization/specialization-overlap.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-overlap.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0119]: conflicting implementations of trait `Foo` for type `std::vec::Vec<_>`:
   --> $DIR/specialization-overlap.rs:5:1
    |
@@ -30,6 +39,6 @@ LL | impl<T: Clone> Qux for T {}
 LL | impl<T: Eq> Qux for T {}
    | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
 
-error: aborting due to 4 previous errors
+error: aborting due to 4 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/specialization/specialization-polarity.rs b/src/test/ui/specialization/specialization-polarity.rs
index e78035f1710..17897d8b803 100644
--- a/src/test/ui/specialization/specialization-polarity.rs
+++ b/src/test/ui/specialization/specialization-polarity.rs
@@ -2,7 +2,7 @@
 
 #![feature(optin_builtin_traits)]
 #![feature(negative_impls)]
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 auto trait Foo {}
 
diff --git a/src/test/ui/specialization/specialization-polarity.stderr b/src/test/ui/specialization/specialization-polarity.stderr
index 44e60cad67a..c44af22b8e6 100644
--- a/src/test/ui/specialization/specialization-polarity.stderr
+++ b/src/test/ui/specialization/specialization-polarity.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-polarity.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0751]: found both positive and negative implementation of trait `Foo` for type `u8`:
   --> $DIR/specialization-polarity.rs:10:1
    |
@@ -14,6 +23,6 @@ LL | impl<T> !Bar for T {}
 LL | impl Bar for u8 {}
    | ^^^^^^^^^^^^^^^ positive implementation here
 
-error: aborting due to 2 previous errors
+error: aborting due to 2 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0751`.
diff --git a/src/test/ui/specialization/specialization-projection-alias.rs b/src/test/ui/specialization/specialization-projection-alias.rs
index 0081ed455c9..f1f0b47bb65 100644
--- a/src/test/ui/specialization/specialization-projection-alias.rs
+++ b/src/test/ui/specialization/specialization-projection-alias.rs
@@ -2,7 +2,7 @@
 #![allow(dead_code)]
 #![allow(unused_variables)]
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Regression test for ICE when combining specialized associated types and type
 // aliases
diff --git a/src/test/ui/specialization/specialization-projection-alias.stderr b/src/test/ui/specialization/specialization-projection-alias.stderr
new file mode 100644
index 00000000000..0c3659a8f7a
--- /dev/null
+++ b/src/test/ui/specialization/specialization-projection-alias.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-projection-alias.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-projection.rs b/src/test/ui/specialization/specialization-projection.rs
index 86cdccf131e..700975e3b82 100644
--- a/src/test/ui/specialization/specialization-projection.rs
+++ b/src/test/ui/specialization/specialization-projection.rs
@@ -1,7 +1,7 @@
 // run-pass
 #![allow(dead_code)]
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Make sure we *can* project non-defaulted associated types
 // cf compile-fail/specialization-default-projection.rs
diff --git a/src/test/ui/specialization/specialization-projection.stderr b/src/test/ui/specialization/specialization-projection.stderr
new file mode 100644
index 00000000000..c5c86f5108e
--- /dev/null
+++ b/src/test/ui/specialization/specialization-projection.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-projection.rs:4:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-super-traits.rs b/src/test/ui/specialization/specialization-super-traits.rs
index a0f71d87693..fb85d801921 100644
--- a/src/test/ui/specialization/specialization-super-traits.rs
+++ b/src/test/ui/specialization/specialization-super-traits.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Test that you can specialize via an explicit trait hierarchy
 
diff --git a/src/test/ui/specialization/specialization-super-traits.stderr b/src/test/ui/specialization/specialization-super-traits.stderr
new file mode 100644
index 00000000000..05bdfd40136
--- /dev/null
+++ b/src/test/ui/specialization/specialization-super-traits.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-super-traits.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs b/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs
index 2e32e3ff02d..5c2781a9c63 100644
--- a/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs
+++ b/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Iterator {
     fn next(&self);
diff --git a/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.stderr b/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.stderr
new file mode 100644
index 00000000000..6284dd8f3f7
--- /dev/null
+++ b/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-translate-projections-with-lifetimes.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-translate-projections-with-params.rs b/src/test/ui/specialization/specialization-translate-projections-with-params.rs
index bdc6501df44..62d63590a66 100644
--- a/src/test/ui/specialization/specialization-translate-projections-with-params.rs
+++ b/src/test/ui/specialization/specialization-translate-projections-with-params.rs
@@ -4,7 +4,7 @@
 // type parameters *and* rely on projections, and the type parameters are input
 // types on the trait.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Trait<T> {
     fn convert(&self) -> T;
diff --git a/src/test/ui/specialization/specialization-translate-projections-with-params.stderr b/src/test/ui/specialization/specialization-translate-projections-with-params.stderr
new file mode 100644
index 00000000000..b17794173c5
--- /dev/null
+++ b/src/test/ui/specialization/specialization-translate-projections-with-params.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-translate-projections-with-params.rs:7:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-translate-projections.rs b/src/test/ui/specialization/specialization-translate-projections.rs
index fcccb67902e..92ea9e2b85d 100644
--- a/src/test/ui/specialization/specialization-translate-projections.rs
+++ b/src/test/ui/specialization/specialization-translate-projections.rs
@@ -3,7 +3,7 @@
 // Ensure that provided items are inherited properly even when impls vary in
 // type parameters *and* rely on projections.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 use std::convert::Into;
 
diff --git a/src/test/ui/specialization/specialization-translate-projections.stderr b/src/test/ui/specialization/specialization-translate-projections.stderr
new file mode 100644
index 00000000000..fbb28e60640
--- /dev/null
+++ b/src/test/ui/specialization/specialization-translate-projections.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-translate-projections.rs:6:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/traits/negative-impls/negative-default-impls.rs b/src/test/ui/traits/negative-impls/negative-default-impls.rs
index 2d50bc83ec3..c68bca432fa 100644
--- a/src/test/ui/traits/negative-impls/negative-default-impls.rs
+++ b/src/test/ui/traits/negative-impls/negative-default-impls.rs
@@ -1,5 +1,6 @@
 #![feature(negative_impls)]
 #![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
 
 trait MyTrait {
     type Foo;
diff --git a/src/test/ui/traits/negative-impls/negative-default-impls.stderr b/src/test/ui/traits/negative-impls/negative-default-impls.stderr
index a70bbe6b948..50e74373b53 100644
--- a/src/test/ui/traits/negative-impls/negative-default-impls.stderr
+++ b/src/test/ui/traits/negative-impls/negative-default-impls.stderr
@@ -1,9 +1,18 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/negative-default-impls.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0750]: negative impls cannot be default impls
-  --> $DIR/negative-default-impls.rs:8:1
+  --> $DIR/negative-default-impls.rs:9:1
    |
 LL | default impl !MyTrait for u32 {}
    | ^^^^^^^      ^
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0750`.
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-negative.rs b/src/test/ui/traits/negative-impls/negative-specializes-negative.rs
index 877c3e8af4f..35297ab124e 100644
--- a/src/test/ui/traits/negative-impls/negative-specializes-negative.rs
+++ b/src/test/ui/traits/negative-impls/negative-specializes-negative.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 #![feature(negative_impls)]
 
 // Test a negative impl that "specializes" another negative impl.
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-negative.stderr b/src/test/ui/traits/negative-impls/negative-specializes-negative.stderr
new file mode 100644
index 00000000000..8b536de3786
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/negative-specializes-negative.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/negative-specializes-negative.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs
index da22e43377f..4281eedaf63 100644
--- a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs
+++ b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 #![feature(negative_impls)]
 
 // Negative impl for u32 cannot "specialize" the base impl.
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr
index 079546a7df4..89ef15e89ac 100644
--- a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr
+++ b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/negative-specializes-positive-item.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`:
   --> $DIR/negative-specializes-positive-item.rs:11:1
    |
@@ -7,6 +16,6 @@ LL | impl<T> MyTrait for T {
 LL | impl !MyTrait for u32 {}
    | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0751`.
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive.rs b/src/test/ui/traits/negative-impls/negative-specializes-positive.rs
index 1939a098b50..0e227691e04 100644
--- a/src/test/ui/traits/negative-impls/negative-specializes-positive.rs
+++ b/src/test/ui/traits/negative-impls/negative-specializes-positive.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 #![feature(negative_impls)]
 
 // Negative impl for u32 cannot "specialize" the base impl.
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr b/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr
index ea005c1cbe0..e45d5a251ab 100644
--- a/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr
+++ b/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/negative-specializes-positive.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`:
   --> $DIR/negative-specializes-positive.rs:7:1
    |
@@ -6,6 +15,6 @@ LL | impl<T> MyTrait for T {}
 LL | impl !MyTrait for u32 {}
    | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0751`.
diff --git a/src/test/ui/traits/negative-impls/positive-specializes-negative.rs b/src/test/ui/traits/negative-impls/positive-specializes-negative.rs
index f2c5f507a4e..a06b3576540 100644
--- a/src/test/ui/traits/negative-impls/positive-specializes-negative.rs
+++ b/src/test/ui/traits/negative-impls/positive-specializes-negative.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 #![feature(negative_impls)]
 
 trait MyTrait {}
diff --git a/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr b/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr
index a24d7aa442f..49c16d47404 100644
--- a/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr
+++ b/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/positive-specializes-negative.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`:
   --> $DIR/positive-specializes-negative.rs:7:1
    |
@@ -6,6 +15,6 @@ LL | impl<T> !MyTrait for T {}
 LL | impl MyTrait for u32 {}
    | ^^^^^^^^^^^^^^^^^^^^ positive implementation here
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0751`.
diff --git a/src/test/ui/traits/traits-inductive-overflow-lifetime.rs b/src/test/ui/traits/traits-inductive-overflow-lifetime.rs
new file mode 100644
index 00000000000..205d50a2ed9
--- /dev/null
+++ b/src/test/ui/traits/traits-inductive-overflow-lifetime.rs
@@ -0,0 +1,30 @@
+// Test that we don't hit the recursion limit for short cycles involving lifetimes.
+
+// Shouldn't hit this, we should realize that we're in a cycle sooner.
+#![recursion_limit="20"]
+
+trait NotAuto {}
+trait Y {
+    type P;
+}
+
+impl<'a> Y for C<'a> {
+    type P = Box<X<C<'a>>>;
+}
+
+struct C<'a>(&'a ());
+struct X<T: Y>(T::P);
+
+impl<T: NotAuto> NotAuto for Box<T> {}
+impl<T: Y> NotAuto for X<T> where T::P: NotAuto {}
+impl<'a> NotAuto for C<'a> {}
+
+fn is_send<S: NotAuto>() {}
+//~^ NOTE: required
+
+fn main() {
+    // Should only be a few notes.
+    is_send::<X<C<'static>>>();
+    //~^ ERROR overflow evaluating
+    //~| NOTE: required
+}
diff --git a/src/test/ui/traits/traits-inductive-overflow-lifetime.stderr b/src/test/ui/traits/traits-inductive-overflow-lifetime.stderr
new file mode 100644
index 00000000000..9a227229ea4
--- /dev/null
+++ b/src/test/ui/traits/traits-inductive-overflow-lifetime.stderr
@@ -0,0 +1,14 @@
+error[E0275]: overflow evaluating the requirement `std::boxed::Box<X<C<'_>>>: NotAuto`
+  --> $DIR/traits-inductive-overflow-lifetime.rs:27:5
+   |
+LL | fn is_send<S: NotAuto>() {}
+   |               ------- required by this bound in `is_send`
+...
+LL |     is_send::<X<C<'static>>>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: required because of the requirements on the impl of `NotAuto` for `X<C<'static>>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/transmute-specialization.rs b/src/test/ui/transmute-specialization.rs
index 002fba9ce81..499334d983b 100644
--- a/src/test/ui/transmute-specialization.rs
+++ b/src/test/ui/transmute-specialization.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Specializable { type Output; }
 
diff --git a/src/test/ui/transmute-specialization.stderr b/src/test/ui/transmute-specialization.stderr
new file mode 100644
index 00000000000..02315051d30
--- /dev/null
+++ b/src/test/ui/transmute-specialization.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/transmute-specialization.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/tools/rls b/src/tools/rls
-Subproject 8d7a7167c15b9154755588c39b22b2336c89ca6
+Subproject fb46b914c11b06828680cb526e2abe9e1d69b86
diff --git a/src/tools/rustfmt b/src/tools/rustfmt
-Subproject aedff61f7ac4fc2b287ff76d33f2584e1f63a3a
+Subproject c1e9b7b87493c5197c4330693bdf4ccb30a9097