about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-01-22 22:04:50 +0000
committerbors <bors@rust-lang.org>2024-01-22 22:04:50 +0000
commitd6b151fc77e213bf637db0f12c1965ace3ffe255 (patch)
treee420a6d4c1774e65195f08e30fe1d6c70df1b002
parentd5fd0997291ca0135401a39dff25c8a9c13b8961 (diff)
parenta787232abb960290eb62051e8236b8449113407c (diff)
downloadrust-d6b151fc77e213bf637db0f12c1965ace3ffe255.tar.gz
rust-d6b151fc77e213bf637db0f12c1965ace3ffe255.zip
Auto merge of #120251 - matthiaskrgr:rollup-gttrw68, r=matthiaskrgr
Rollup of 8 pull requests

Successful merges:

 - #119664 (Fix tty detection for msys2's `/dev/ptmx`)
 - #120104 (never_patterns: Count `!` bindings as diverging)
 - #120109 (Move cmath into `sys`)
 - #120143 (Consolidate logic around resolving built-in coroutine trait impls)
 - #120159 (Track `verbose` and `verbose_internals`)
 - #120216 (Fix a `trimmed_def_paths` assertion failure.)
 - #120220 (Document `Token{Stream,Tree}::Display` more thoroughly.)
 - #120233 (Revert stabilization of trait_upcasting feature)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_feature/src/accepted.rs3
-rw-r--r--compiler/rustc_feature/src/unstable.rs3
-rw-r--r--compiler/rustc_hir/src/lang_items.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs23
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs15
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs9
-rw-r--r--compiler/rustc_interface/src/tests.rs3
-rw-r--r--compiler/rustc_lint/src/deref_into_dyn_supertrait.rs13
-rw-r--r--compiler/rustc_lint/src/lib.rs1
-rw-r--r--compiler/rustc_lint/src/lints.rs1
-rw-r--r--compiler/rustc_middle/src/lib.rs1
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs50
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs2
-rw-r--r--compiler/rustc_session/src/options.rs4
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs51
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs59
-rw-r--r--library/core/src/ops/coroutine.rs1
-rw-r--r--library/core/tests/lib.rs1
-rw-r--r--library/proc_macro/src/lib.rs16
-rw-r--r--library/std/src/sys/cmath/builtins.rs (renamed from library/std/src/sys/pal/unix/cmath.rs)2
-rw-r--r--library/std/src/sys/cmath/mod.rs11
-rw-r--r--library/std/src/sys/cmath/windows.rs (renamed from library/std/src/sys/pal/windows/cmath.rs)2
-rw-r--r--library/std/src/sys/mod.rs4
-rw-r--r--library/std/src/sys/pal/hermit/mod.rs2
-rw-r--r--library/std/src/sys/pal/sgx/mod.rs2
-rw-r--r--library/std/src/sys/pal/solid/mod.rs2
-rw-r--r--library/std/src/sys/pal/teeos/mod.rs2
-rw-r--r--library/std/src/sys/pal/uefi/mod.rs2
-rw-r--r--library/std/src/sys/pal/unix/mod.rs2
-rw-r--r--library/std/src/sys/pal/unsupported/mod.rs2
-rw-r--r--library/std/src/sys/pal/wasi/mod.rs2
-rw-r--r--library/std/src/sys/pal/wasm/mod.rs2
-rw-r--r--library/std/src/sys/pal/windows/io.rs14
-rw-r--r--library/std/src/sys/pal/windows/mod.rs1
-rw-r--r--library/std/src/sys/pal/xous/mod.rs2
-rw-r--r--src/doc/unstable-book/src/language-features/trait-upcasting.md27
-rw-r--r--src/tools/miri/src/lib.rs2
-rw-r--r--src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs3
-rw-r--r--src/tools/miri/tests/pass/box-custom-alloc.rs3
-rw-r--r--src/tools/miri/tests/pass/dyn-upcast.rs3
-rw-r--r--tests/incremental/commandline-args.rs6
-rw-r--r--tests/ui/codegen/issue-99551.rs1
-rw-r--r--tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs2
-rw-r--r--tests/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr2
-rw-r--r--tests/ui/dyn-star/upcast.rs2
-rw-r--r--tests/ui/dyn-star/upcast.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-trait_upcasting.rs13
-rw-r--r--tests/ui/feature-gates/feature-gate-trait_upcasting.stderr14
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/120240-async-fn-never-arg.rs16
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/120240-async-fn-never-arg.stderr12
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/diverge-causes-unreachable-code.rs36
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/diverge-causes-unreachable-code.stderr49
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/diverges-not.rs56
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/diverges-not.stderr55
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/diverges.rs38
-rw-r--r--tests/ui/traits/next-solver/normalize-unsize-rhs.rs1
-rw-r--r--tests/ui/traits/next-solver/trait-upcast-lhs-needs-normalization.rs1
-rw-r--r--tests/ui/traits/next-solver/upcast-right-substs.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/basic.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/deref-lint-regions.stderr14
-rw-r--r--tests/ui/traits/trait-upcasting/deref-lint.stderr14
-rw-r--r--tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.rs3
-rw-r--r--tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.stderr23
-rw-r--r--tests/ui/traits/trait-upcasting/diamond.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/fewer-associated.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.current.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.next.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/inference-behavior-change-deref.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/inference-behavior-change-deref.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/invalid-upcast.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/invalid-upcast.stderr30
-rw-r--r--tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/issue-11515.current.stderr14
-rw-r--r--tests/ui/traits/trait-upcasting/issue-11515.next.stderr14
-rw-r--r--tests/ui/traits/trait-upcasting/issue-11515.rs3
-rw-r--r--tests/ui/traits/trait-upcasting/lifetime.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.rs (renamed from tests/ui/traits/trait-upcasting/deref-lint-regions.rs)5
-rw-r--r--tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.stderr19
-rw-r--r--tests/ui/traits/trait-upcasting/migrate-lint-deny.rs (renamed from tests/ui/traits/trait-upcasting/deref-lint.rs)5
-rw-r--r--tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr19
-rw-r--r--tests/ui/traits/trait-upcasting/migrate-lint-different-substs.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/migrate-lint-different-substs.stderr5
-rw-r--r--tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/normalization.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/replace-vptr.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/struct.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/subtrait-method.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/subtrait-method.stderr20
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-1.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-2.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-2.stderr4
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-3.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-3.stderr4
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-4.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-4.stderr12
-rw-r--r--tests/ui/traits/trait-upcasting/upcast-through-struct-tail.current.stderr14
-rw-r--r--tests/ui/traits/trait-upcasting/upcast-through-struct-tail.next.stderr14
-rw-r--r--tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs2
-rw-r--r--tests/ui/traits/upcast_soundness_bug.rs69
109 files changed, 816 insertions, 214 deletions
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 6e3996b4509..1155366db85 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -339,9 +339,6 @@ declare_features! (
     /// Allows `#[track_caller]` to be used which provides
     /// accurate caller location reporting during panic (RFC 2091).
     (accepted, track_caller, "1.46.0", Some(47809)),
-    /// Allows dyn upcasting trait objects via supertraits.
-    /// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
-    (accepted, trait_upcasting, "1.76.0", Some(65991)),
     /// Allows #[repr(transparent)] on univariant enums (RFC 2645).
     (accepted, transparent_enums, "1.42.0", Some(60405)),
     /// Allows indexing tuples.
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 371b651f5e8..6eed2178ead 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -584,6 +584,9 @@ declare_features! (
     (unstable, thread_local, "1.0.0", Some(29594)),
     /// Allows defining `trait X = A + B;` alias items.
     (unstable, trait_alias, "1.24.0", Some(41517)),
+    /// Allows dyn upcasting trait objects via supertraits.
+    /// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
+    (unstable, trait_upcasting, "1.56.0", Some(65991)),
     /// Allows for transmuting between arrays with sizes that contain generic consts.
     (unstable, transmute_generic_consts, "1.70.0", Some(109929)),
     /// Allows #[repr(transparent)] on unions (RFC 2645).
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 1cc1f11b3c8..85d10872b3d 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -213,8 +213,11 @@ language_item_table! {
     Iterator,                sym::iterator,            iterator_trait,             Target::Trait,          GenericRequirement::Exact(0);
     Future,                  sym::future_trait,        future_trait,               Target::Trait,          GenericRequirement::Exact(0);
     AsyncIterator,           sym::async_iterator,      async_iterator_trait,       Target::Trait,          GenericRequirement::Exact(0);
+
     CoroutineState,          sym::coroutine_state,     coroutine_state,            Target::Enum,           GenericRequirement::None;
     Coroutine,               sym::coroutine,           coroutine_trait,            Target::Trait,          GenericRequirement::Minimum(1);
+    CoroutineResume,         sym::coroutine_resume,    coroutine_resume,           Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
+
     Unpin,                   sym::unpin,               unpin_trait,                Target::Trait,          GenericRequirement::None;
     Pin,                     sym::pin,                 pin_type,                   Target::Struct,         GenericRequirement::None;
 
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index c887368b2a2..4d9f5b831c1 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -2,8 +2,7 @@ use std::cell::RefCell;
 
 use crate::coercion::CoerceMany;
 use crate::gather_locals::GatherLocalsVisitor;
-use crate::CoroutineTypes;
-use crate::FnCtxt;
+use crate::{CoroutineTypes, Diverges, FnCtxt};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::intravisit::Visitor;
@@ -76,6 +75,12 @@ pub(super) fn check_fn<'a, 'tcx>(
         let ty: Option<&hir::Ty<'_>> = try { inputs_hir?.get(idx)? };
         let ty_span = ty.map(|ty| ty.span);
         fcx.check_pat_top(param.pat, param_ty, ty_span, None, None);
+        if param.pat.is_never_pattern() {
+            fcx.function_diverges_because_of_empty_arguments.set(Diverges::Always {
+                span: param.pat.span,
+                custom_note: Some("any code following a never pattern is unreachable"),
+            });
+        }
 
         // Check that argument is Sized.
         if !params_can_be_unsized {
@@ -105,6 +110,7 @@ pub(super) fn check_fn<'a, 'tcx>(
         hir::FnRetTy::Return(ty) => ty.span,
     };
     fcx.require_type_is_sized(declared_ret_ty, return_or_body_span, traits::SizedReturnType);
+    fcx.is_whole_body.set(true);
     fcx.check_return_expr(body.value, false);
 
     // Finalize the return check by taking the LUB of the return types
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index e9d373119fa..858faf161f6 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -625,6 +625,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         )];
 
         let mut has_unsized_tuple_coercion = false;
+        let mut has_trait_upcasting_coercion = None;
 
         // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
         // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
@@ -692,6 +693,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                     // these here and emit a feature error if coercion doesn't fail
                     // due to another reason.
                     match impl_source {
+                        traits::ImplSource::Builtin(
+                            BuiltinImplSource::TraitUpcasting { .. },
+                            _,
+                        ) => {
+                            has_trait_upcasting_coercion =
+                                Some((trait_pred.self_ty(), trait_pred.trait_ref.args.type_at(1)));
+                        }
                         traits::ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
                             has_unsized_tuple_coercion = true;
                         }
@@ -702,6 +710,21 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
             }
         }
 
+        if let Some((sub, sup)) = has_trait_upcasting_coercion
+            && !self.tcx().features().trait_upcasting
+        {
+            // Renders better when we erase regions, since they're not really the point here.
+            let (sub, sup) = self.tcx.erase_regions((sub, sup));
+            let mut err = feature_err(
+                &self.tcx.sess,
+                sym::trait_upcasting,
+                self.cause.span,
+                format!("cannot cast `{sub}` to `{sup}`, trait upcasting coercion is experimental"),
+            );
+            err.note(format!("required when coercing `{source}` into `{target}`"));
+            err.emit();
+        }
+
         if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion {
             feature_err(
                 &self.tcx.sess,
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index f48d712cd60..3bc259c17b7 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -208,10 +208,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // without the final expr (e.g. `try { return; }`). We don't want to generate an
         // unreachable_code lint for it since warnings for autogenerated code are confusing.
         let is_try_block_generated_unit_expr = match expr.kind {
-            ExprKind::Call(_, args) if expr.span.is_desugaring(DesugaringKind::TryBlock) => {
-                args.len() == 1 && args[0].span.is_desugaring(DesugaringKind::TryBlock)
+            ExprKind::Call(_, [arg]) => {
+                expr.span.is_desugaring(DesugaringKind::TryBlock)
+                    && arg.span.is_desugaring(DesugaringKind::TryBlock)
             }
-
             _ => false,
         };
 
@@ -220,9 +220,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.warn_if_unreachable(expr.hir_id, expr.span, "expression");
         }
 
-        // Hide the outer diverging and has_errors flags.
+        // Whether a past expression diverges doesn't affect typechecking of this expression, so we
+        // reset `diverges` while checking `expr`.
         let old_diverges = self.diverges.replace(Diverges::Maybe);
 
+        if self.is_whole_body.replace(false) {
+            // If this expression is the whole body and the function diverges because of its
+            // arguments, we check this here to ensure the body is considered to diverge.
+            self.diverges.set(self.function_diverges_because_of_empty_arguments.get())
+        };
+
         let ty = ensure_sufficient_stack(|| match &expr.kind {
             hir::ExprKind::Path(
                 qpath @ (hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)),
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index ddb4224b60d..136ed1a709e 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1471,6 +1471,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Type check a `let` statement.
     pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) {
         self.check_decl(local.into());
+        if local.pat.is_never_pattern() {
+            self.diverges.set(Diverges::Always {
+                span: local.pat.span,
+                custom_note: Some("any code following a never pattern is unreachable"),
+            });
+        }
     }
 
     pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>) {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index e6c2091d85a..f65e9b698ab 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -103,6 +103,13 @@ pub struct FnCtxt<'a, 'tcx> {
     /// the diverges flag is set to something other than `Maybe`.
     pub(super) diverges: Cell<Diverges>,
 
+    /// If one of the function arguments is a never pattern, this counts as diverging code. This
+    /// affect typechecking of the function body.
+    pub(super) function_diverges_because_of_empty_arguments: Cell<Diverges>,
+
+    /// Whether the currently checked node is the whole body of the function.
+    pub(super) is_whole_body: Cell<bool>,
+
     pub(super) enclosing_breakables: RefCell<EnclosingBreakables<'tcx>>,
 
     pub(super) inh: &'a Inherited<'tcx>,
@@ -124,6 +131,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ret_coercion_span: Cell::new(None),
             coroutine_types: None,
             diverges: Cell::new(Diverges::Maybe),
+            function_diverges_because_of_empty_arguments: Cell::new(Diverges::Maybe),
+            is_whole_body: Cell::new(false),
             enclosing_breakables: RefCell::new(EnclosingBreakables {
                 stack: Vec::new(),
                 by_id: Default::default(),
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 555c822ad6d..2d4963a8b90 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -98,6 +98,7 @@ fn assert_same_hash(x: &Options, y: &Options) {
     assert_same_clone(y);
 }
 
+#[track_caller]
 fn assert_different_hash(x: &Options, y: &Options) {
     assert_ne!(x.dep_tracking_hash(true), y.dep_tracking_hash(true));
     assert_ne!(x.dep_tracking_hash(false), y.dep_tracking_hash(false));
@@ -713,7 +714,6 @@ fn test_unstable_options_tracking_hash() {
     untracked!(unpretty, Some("expanded".to_string()));
     untracked!(unstable_options, true);
     untracked!(validate_mir, true);
-    untracked!(verbose_internals, true);
     untracked!(write_long_types_to_disk, false);
     // tidy-alphabetical-end
 
@@ -845,6 +845,7 @@ fn test_unstable_options_tracking_hash() {
         };
     }
     tracked_no_crate_hash!(no_codegen, true);
+    tracked_no_crate_hash!(verbose_internals, true);
 }
 
 #[test]
diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
index 98bafc0f263..4673b801dc1 100644
--- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
+++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
@@ -5,6 +5,7 @@ use crate::{
 
 use rustc_hir as hir;
 use rustc_middle::ty;
+use rustc_session::lint::FutureIncompatibilityReason;
 use rustc_span::sym;
 use rustc_trait_selection::traits::supertraits;
 
@@ -12,6 +13,9 @@ declare_lint! {
     /// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the
     /// `Deref` implementation with a `dyn SuperTrait` type as `Output`.
     ///
+    /// These implementations will become shadowed when the `trait_upcasting` feature is stabilized.
+    /// The `deref` functions will no longer be called implicitly, so there might be behavior change.
+    ///
     /// ### Example
     ///
     /// ```rust,compile_fail
@@ -40,10 +44,15 @@ declare_lint! {
     ///
     /// ### Explanation
     ///
-    /// The implicit dyn upcasting coercion take priority over those `Deref` impls.
+    /// The dyn upcasting coercion feature adds new coercion rules, taking priority
+    /// over certain other coercion rules, which will cause some behavior change.
     pub DEREF_INTO_DYN_SUPERTRAIT,
     Warn,
-    "`Deref` implementation usage with a supertrait trait object for output are shadow by implicit coercion",
+    "`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::FutureReleaseSemanticsChange,
+        reference: "issue #89460 <https://github.com/rust-lang/rust/issues/89460>",
+    };
 }
 
 declare_lint_pass!(DerefIntoDynSupertrait => [DEREF_INTO_DYN_SUPERTRAIT]);
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index a9996e4a155..b5798af7553 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -35,6 +35,7 @@
 #![feature(iter_intersperse)]
 #![feature(iter_order_by)]
 #![feature(let_chains)]
+#![cfg_attr(not(bootstrap), feature(trait_upcasting))]
 #![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(rustc_attrs)]
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 65d47b9acc2..94ecc7d9587 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -532,7 +532,6 @@ pub enum BuiltinSpecialModuleNameUsed {
 // deref_into_dyn_supertrait.rs
 #[derive(LintDiagnostic)]
 #[diag(lint_supertrait_as_deref_target)]
-#[help]
 pub struct SupertraitAsDerefTarget<'a> {
     pub self_ty: Ty<'a>,
     pub supertrait_principal: PolyExistentialTraitRef<'a>,
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 3475e582a8f..dec3419819f 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -49,6 +49,7 @@
 #![feature(associated_type_bounds)]
 #![feature(rustc_attrs)]
 #![feature(control_flow_enum)]
+#![cfg_attr(not(bootstrap), feature(trait_upcasting))]
 #![feature(trusted_step)]
 #![feature(try_blocks)]
 #![feature(try_reserve_kind)]
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index dd41cb5a61f..b6c3c34078f 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -3,6 +3,7 @@ use crate::ty::print::{FmtPrinter, Printer};
 use crate::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable};
 use crate::ty::{EarlyBinder, GenericArgs, GenericArgsRef, TypeVisitableExt};
 use rustc_errors::ErrorGuaranteed;
+use rustc_hir as hir;
 use rustc_hir::def::Namespace;
 use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_hir::lang_items::LangItem;
@@ -11,6 +12,7 @@ use rustc_macros::HashStable;
 use rustc_middle::ty::normalize_erasing_regions::NormalizationError;
 use rustc_span::Symbol;
 
+use std::assert_matches::assert_matches;
 use std::fmt;
 
 /// A monomorphized `InstanceDef`.
@@ -572,6 +574,54 @@ impl<'tcx> Instance<'tcx> {
         Some(Instance { def, args })
     }
 
+    pub fn try_resolve_item_for_coroutine(
+        tcx: TyCtxt<'tcx>,
+        trait_item_id: DefId,
+        trait_id: DefId,
+        rcvr_args: ty::GenericArgsRef<'tcx>,
+    ) -> Option<Instance<'tcx>> {
+        let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else {
+            return None;
+        };
+        let coroutine_kind = tcx.coroutine_kind(coroutine_def_id).unwrap();
+
+        let lang_items = tcx.lang_items();
+        let coroutine_callable_item = if Some(trait_id) == lang_items.future_trait() {
+            assert_matches!(
+                coroutine_kind,
+                hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)
+            );
+            hir::LangItem::FuturePoll
+        } else if Some(trait_id) == lang_items.iterator_trait() {
+            assert_matches!(
+                coroutine_kind,
+                hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
+            );
+            hir::LangItem::IteratorNext
+        } else if Some(trait_id) == lang_items.async_iterator_trait() {
+            assert_matches!(
+                coroutine_kind,
+                hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)
+            );
+            hir::LangItem::AsyncIteratorPollNext
+        } else if Some(trait_id) == lang_items.coroutine_trait() {
+            assert_matches!(coroutine_kind, hir::CoroutineKind::Coroutine(_));
+            hir::LangItem::CoroutineResume
+        } else {
+            return None;
+        };
+
+        if tcx.lang_items().get(coroutine_callable_item) == Some(trait_item_id) {
+            Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args: args })
+        } else {
+            // All other methods should be defaulted methods of the built-in trait.
+            // This is important for `Iterator`'s combinators, but also useful for
+            // adding future default methods to `Future`, for instance.
+            debug_assert!(tcx.defaultness(trait_item_id).has_value());
+            Some(Instance::new(trait_item_id, rcvr_args))
+        }
+    }
+
     /// Depending on the kind of `InstanceDef`, the MIR body associated with an
     /// instance is expressed in terms of the generic parameters of `self.def_id()`, and in other
     /// cases the MIR body is expressed in terms of the types found in the substitution array.
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 4028de27cae..a06f4c6ba12 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -3072,8 +3072,6 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
 /// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths!`].
 // this is pub to be able to intra-doc-link it
 pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap<Symbol> {
-    assert!(tcx.sess.opts.trimmed_def_paths);
-
     // Trimming paths is expensive and not optimized, since we expect it to only be used for error
     // reporting.
     //
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 1337ade62c0..486b6d4bf2e 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -224,7 +224,7 @@ top_level_options!(
         working_dir: RealFileName [TRACKED],
         color: ColorConfig [UNTRACKED],
 
-        verbose: bool [UNTRACKED],
+        verbose: bool [TRACKED_NO_CRATE_HASH],
     }
 );
 
@@ -1986,7 +1986,7 @@ written to standard error output)"),
     validate_mir: bool = (false, parse_bool, [UNTRACKED],
         "validate MIR after each transformation"),
     #[rustc_lint_opt_deny_field_access("use `Session::verbose_internals` instead of this field")]
-    verbose_internals: bool = (false, parse_bool, [UNTRACKED],
+    verbose_internals: bool = (false, parse_bool, [TRACKED_NO_CRATE_HASH],
         "in general, enable more debug printouts (default: no)"),
     #[rustc_lint_opt_deny_field_access("use `Session::verify_llvm_ir` instead of this field")]
     verify_llvm_ir: bool = (false, parse_bool, [TRACKED],
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 7b0138d50ba..6c39a38750e 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -600,6 +600,7 @@ symbols! {
         core_panic_macro,
         coroutine,
         coroutine_clone,
+        coroutine_resume,
         coroutine_state,
         coroutines,
         cosf32,
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 342b12ba498..12aea88e9b6 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -9,10 +9,13 @@
 use hir::def_id::DefId;
 use hir::LangItem;
 use rustc_hir as hir;
+use rustc_infer::traits::ObligationCause;
 use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
 use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 
+use crate::traits;
+use crate::traits::query::evaluate_obligation::InferCtxtExt;
 use crate::traits::util;
 
 use super::BuiltinImplConditions;
@@ -723,6 +726,45 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         })
     }
 
+    /// Temporary migration for #89190
+    fn need_migrate_deref_output_trait_object(
+        &mut self,
+        ty: Ty<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        cause: &ObligationCause<'tcx>,
+    ) -> Option<ty::PolyExistentialTraitRef<'tcx>> {
+        let tcx = self.tcx();
+        if tcx.features().trait_upcasting {
+            return None;
+        }
+
+        // <ty as Deref>
+        let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]);
+
+        let obligation =
+            traits::Obligation::new(tcx, cause.clone(), param_env, ty::Binder::dummy(trait_ref));
+        if !self.infcx.predicate_may_hold(&obligation) {
+            return None;
+        }
+
+        self.infcx.probe(|_| {
+            let ty = traits::normalize_projection_type(
+                self,
+                param_env,
+                ty::AliasTy::new(tcx, tcx.lang_items().deref_target()?, trait_ref.args),
+                cause.clone(),
+                0,
+                // We're *intentionally* throwing these away,
+                // since we don't actually use them.
+                &mut vec![],
+            )
+            .ty()
+            .unwrap();
+
+            if let ty::Dynamic(data, ..) = ty.kind() { data.principal() } else { None }
+        })
+    }
+
     /// Searches for unsizing that might apply to `obligation`.
     fn assemble_candidates_for_unsizing(
         &mut self,
@@ -780,6 +822,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         let principal_a = a_data.principal().unwrap();
                         let target_trait_did = principal_def_id_b.unwrap();
                         let source_trait_ref = principal_a.with_self_ty(self.tcx(), source);
+                        if let Some(deref_trait_ref) = self.need_migrate_deref_output_trait_object(
+                            source,
+                            obligation.param_env,
+                            &obligation.cause,
+                        ) {
+                            if deref_trait_ref.def_id() == target_trait_did {
+                                return;
+                            }
+                        }
 
                         for (idx, upcast_trait_ref) in
                             util::supertraits(self.tcx(), source_trait_ref).enumerate()
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 81d5304b812..e5e31f7caaa 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -245,63 +245,6 @@ fn resolve_associated_item<'tcx>(
                         span: tcx.def_span(trait_item_id),
                     })
                 }
-            } else if Some(trait_ref.def_id) == lang_items.future_trait() {
-                let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else {
-                    bug!()
-                };
-                if Some(trait_item_id) == tcx.lang_items().future_poll_fn() {
-                    // `Future::poll` is generated by the compiler.
-                    Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args: args })
-                } else {
-                    // All other methods are default methods of the `Future` trait.
-                    // (this assumes that `ImplSource::Builtin` is only used for methods on `Future`)
-                    debug_assert!(tcx.defaultness(trait_item_id).has_value());
-                    Some(Instance::new(trait_item_id, rcvr_args))
-                }
-            } else if Some(trait_ref.def_id) == lang_items.iterator_trait() {
-                let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else {
-                    bug!()
-                };
-                if Some(trait_item_id) == tcx.lang_items().next_fn() {
-                    // `Iterator::next` is generated by the compiler.
-                    Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args })
-                } else {
-                    // All other methods are default methods of the `Iterator` trait.
-                    // (this assumes that `ImplSource::Builtin` is only used for methods on `Iterator`)
-                    debug_assert!(tcx.defaultness(trait_item_id).has_value());
-                    Some(Instance::new(trait_item_id, rcvr_args))
-                }
-            } else if Some(trait_ref.def_id) == lang_items.async_iterator_trait() {
-                let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else {
-                    bug!()
-                };
-
-                if cfg!(debug_assertions) && tcx.item_name(trait_item_id) != sym::poll_next {
-                    span_bug!(
-                        tcx.def_span(coroutine_def_id),
-                        "no definition for `{trait_ref}::{}` for built-in coroutine type",
-                        tcx.item_name(trait_item_id)
-                    )
-                }
-
-                // `AsyncIterator::poll_next` is generated by the compiler.
-                Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args })
-            } else if Some(trait_ref.def_id) == lang_items.coroutine_trait() {
-                let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else {
-                    bug!()
-                };
-                if cfg!(debug_assertions) && tcx.item_name(trait_item_id) != sym::resume {
-                    // For compiler developers who'd like to add new items to `Coroutine`,
-                    // you either need to generate a shim body, or perhaps return
-                    // `InstanceDef::Item` pointing to a trait default method body if
-                    // it is given a default implementation by the trait.
-                    span_bug!(
-                        tcx.def_span(coroutine_def_id),
-                        "no definition for `{trait_ref}::{}` for built-in coroutine type",
-                        tcx.item_name(trait_item_id)
-                    )
-                }
-                Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args })
             } else if tcx.fn_trait_kind_from_def_id(trait_ref.def_id).is_some() {
                 // FIXME: This doesn't check for malformed libcore that defines, e.g.,
                 // `trait Fn { fn call_once(&self) { .. } }`. This is mostly for extension
@@ -334,7 +277,7 @@ fn resolve_associated_item<'tcx>(
                     ),
                 }
             } else {
-                None
+                Instance::try_resolve_item_for_coroutine(tcx, trait_item_id, trait_id, rcvr_args)
             }
         }
         traits::ImplSource::Param(..)
diff --git a/library/core/src/ops/coroutine.rs b/library/core/src/ops/coroutine.rs
index e58c9068af8..6faded76a4a 100644
--- a/library/core/src/ops/coroutine.rs
+++ b/library/core/src/ops/coroutine.rs
@@ -111,6 +111,7 @@ pub trait Coroutine<R = ()> {
     /// been returned previously. While coroutine literals in the language are
     /// guaranteed to panic on resuming after `Complete`, this is not guaranteed
     /// for all implementations of the `Coroutine` trait.
+    #[cfg_attr(not(bootstrap), lang = "coroutine_resume")]
     fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return>;
 }
 
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 13fb97fdc7f..89d2b5ef093 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -113,6 +113,7 @@
 #![feature(slice_flatten)]
 #![feature(error_generic_member_access)]
 #![feature(error_in_core)]
+#![cfg_attr(not(bootstrap), feature(trait_upcasting))]
 #![feature(utf8_chunks)]
 #![feature(is_ascii_octdigit)]
 #![feature(get_many_mut)]
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index ca83e2be5c1..87e89a464bc 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -191,6 +191,14 @@ impl ToString for TokenStream {
 /// Prints the token stream as a string that is supposed to be losslessly convertible back
 /// into the same token stream (modulo spans), except for possibly `TokenTree::Group`s
 /// with `Delimiter::None` delimiters and negative numeric literals.
+///
+/// Note: the exact form of the output is subject to change, e.g. there might
+/// be changes in the whitespace used between tokens. Therefore, you should
+/// *not* do any kind of simple substring matching on the output string (as
+/// produced by `to_string`) to implement a proc macro, because that matching
+/// might stop working if such changes happen. Instead, you should work at the
+/// `TokenTree` level, e.g. matching against `TokenTree::Ident`,
+/// `TokenTree::Punct`, or `TokenTree::Literal`.
 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
 impl fmt::Display for TokenStream {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -758,6 +766,14 @@ impl ToString for TokenTree {
 /// Prints the token tree as a string that is supposed to be losslessly convertible back
 /// into the same token tree (modulo spans), except for possibly `TokenTree::Group`s
 /// with `Delimiter::None` delimiters and negative numeric literals.
+///
+/// Note: the exact form of the output is subject to change, e.g. there might
+/// be changes in the whitespace used between tokens. Therefore, you should
+/// *not* do any kind of simple substring matching on the output string (as
+/// produced by `to_string`) to implement a proc macro, because that matching
+/// might stop working if such changes happen. Instead, you should work at the
+/// `TokenTree` level, e.g. matching against `TokenTree::Ident`,
+/// `TokenTree::Punct`, or `TokenTree::Literal`.
 #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
 impl fmt::Display for TokenTree {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/library/std/src/sys/pal/unix/cmath.rs b/library/std/src/sys/cmath/builtins.rs
index 5346d229116..c680132efa4 100644
--- a/library/std/src/sys/pal/unix/cmath.rs
+++ b/library/std/src/sys/cmath/builtins.rs
@@ -1,5 +1,3 @@
-#![cfg(not(test))]
-
 // These symbols are all defined by `libm`,
 // or by `compiler-builtins` on unsupported platforms.
 
diff --git a/library/std/src/sys/cmath/mod.rs b/library/std/src/sys/cmath/mod.rs
new file mode 100644
index 00000000000..79d5021dd8d
--- /dev/null
+++ b/library/std/src/sys/cmath/mod.rs
@@ -0,0 +1,11 @@
+#![cfg(not(test))]
+
+cfg_if::cfg_if! {
+    if #[cfg(target_os = "windows")] {
+        mod windows;
+        pub use windows::*;
+    } else {
+        mod builtins;
+        pub use builtins::*;
+    }
+}
diff --git a/library/std/src/sys/pal/windows/cmath.rs b/library/std/src/sys/cmath/windows.rs
index 36578d5a34e..712097f06ff 100644
--- a/library/std/src/sys/pal/windows/cmath.rs
+++ b/library/std/src/sys/cmath/windows.rs
@@ -1,5 +1,3 @@
-#![cfg(not(test))]
-
 use core::ffi::{c_double, c_float, c_int};
 
 extern "C" {
diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs
index d95c0d8d062..e03e98b18d2 100644
--- a/library/std/src/sys/mod.rs
+++ b/library/std/src/sys/mod.rs
@@ -3,9 +3,11 @@
 /// descriptors.
 mod pal;
 
-pub mod os_str;
 mod personality;
 
+pub mod cmath;
+pub mod os_str;
+
 // FIXME(117276): remove this, move feature implementations into individual
 //                submodules.
 pub use pal::*;
diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs
index 50336296919..3c83afa280b 100644
--- a/library/std/src/sys/pal/hermit/mod.rs
+++ b/library/std/src/sys/pal/hermit/mod.rs
@@ -19,8 +19,6 @@ use crate::os::raw::c_char;
 
 pub mod alloc;
 pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
 pub mod env;
 pub mod fd;
 pub mod fs;
diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs
index 893c5f765a7..a769fc1ef59 100644
--- a/library/std/src/sys/pal/sgx/mod.rs
+++ b/library/std/src/sys/pal/sgx/mod.rs
@@ -13,8 +13,6 @@ mod waitqueue;
 
 pub mod alloc;
 pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
 pub mod env;
 pub mod fd;
 #[path = "../unsupported/fs.rs"]
diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs
index 5742ce9d72c..46699e64169 100644
--- a/library/std/src/sys/pal/solid/mod.rs
+++ b/library/std/src/sys/pal/solid/mod.rs
@@ -21,8 +21,6 @@ mod itron {
 pub mod alloc;
 #[path = "../unsupported/args.rs"]
 pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
 pub mod env;
 // `error` is `pub(crate)` so that it can be accessed by `itron/error.rs` as
 // `crate::sys::error`
diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs
index 764a4e6ad35..95a5b97ea42 100644
--- a/library/std/src/sys/pal/teeos/mod.rs
+++ b/library/std/src/sys/pal/teeos/mod.rs
@@ -11,8 +11,6 @@ pub use self::rand::hashmap_random_keys;
 pub mod alloc;
 #[path = "../unsupported/args.rs"]
 pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
 #[path = "../unsupported/env.rs"]
 pub mod env;
 pub mod locks;
diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs
index fb1a531182a..9ee753aa1a0 100644
--- a/library/std/src/sys/pal/uefi/mod.rs
+++ b/library/std/src/sys/pal/uefi/mod.rs
@@ -14,8 +14,6 @@
 
 pub mod alloc;
 pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
 pub mod env;
 #[path = "../unsupported/fs.rs"]
 pub mod fs;
diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs
index 86027c2b0b0..43cb9d89be9 100644
--- a/library/std/src/sys/pal/unix/mod.rs
+++ b/library/std/src/sys/pal/unix/mod.rs
@@ -11,8 +11,6 @@ pub mod weak;
 pub mod alloc;
 pub mod android;
 pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
 pub mod env;
 pub mod fd;
 pub mod fs;
diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs
index 6254c67a2a3..b56ded8579c 100644
--- a/library/std/src/sys/pal/unsupported/mod.rs
+++ b/library/std/src/sys/pal/unsupported/mod.rs
@@ -2,8 +2,6 @@
 
 pub mod alloc;
 pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
 pub mod env;
 pub mod fs;
 pub mod io;
diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs
index c1fc053bf04..4ffc8ecdd67 100644
--- a/library/std/src/sys/pal/wasi/mod.rs
+++ b/library/std/src/sys/pal/wasi/mod.rs
@@ -20,8 +20,6 @@ use crate::mem;
 #[path = "../unix/alloc.rs"]
 pub mod alloc;
 pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
 pub mod env;
 pub mod fd;
 pub mod fs;
diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs
index d2181565887..76306b618d8 100644
--- a/library/std/src/sys/pal/wasm/mod.rs
+++ b/library/std/src/sys/pal/wasm/mod.rs
@@ -19,8 +19,6 @@
 pub mod alloc;
 #[path = "../unsupported/args.rs"]
 pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
 pub mod env;
 #[path = "../unsupported/fs.rs"]
 pub mod fs;
diff --git a/library/std/src/sys/pal/windows/io.rs b/library/std/src/sys/pal/windows/io.rs
index 649826d25ce..b73d9f3ff4c 100644
--- a/library/std/src/sys/pal/windows/io.rs
+++ b/library/std/src/sys/pal/windows/io.rs
@@ -97,20 +97,6 @@ unsafe fn handle_is_console(handle: BorrowedHandle<'_>) -> bool {
         return true;
     }
 
-    // At this point, we *could* have a false negative. We can determine that this is a true
-    // negative if we can detect the presence of a console on any of the standard I/O streams. If
-    // another stream has a console, then we know we're in a Windows console and can therefore
-    // trust the negative.
-    for std_handle in [c::STD_INPUT_HANDLE, c::STD_OUTPUT_HANDLE, c::STD_ERROR_HANDLE] {
-        let std_handle = c::GetStdHandle(std_handle);
-        if !std_handle.is_null()
-            && std_handle != handle
-            && c::GetConsoleMode(std_handle, &mut out) != 0
-        {
-            return false;
-        }
-    }
-
     // Otherwise, we fall back to an msys hack to see if we can detect the presence of a pty.
     msys_tty_on(handle)
 }
diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs
index d097a7b8bb2..364521dba40 100644
--- a/library/std/src/sys/pal/windows/mod.rs
+++ b/library/std/src/sys/pal/windows/mod.rs
@@ -15,7 +15,6 @@ pub mod compat;
 pub mod alloc;
 pub mod args;
 pub mod c;
-pub mod cmath;
 pub mod env;
 pub mod fs;
 pub mod handle;
diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs
index 516d0a68720..b4948d7e583 100644
--- a/library/std/src/sys/pal/xous/mod.rs
+++ b/library/std/src/sys/pal/xous/mod.rs
@@ -3,8 +3,6 @@
 pub mod alloc;
 #[path = "../unsupported/args.rs"]
 pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
 #[path = "../unsupported/env.rs"]
 pub mod env;
 #[path = "../unsupported/fs.rs"]
diff --git a/src/doc/unstable-book/src/language-features/trait-upcasting.md b/src/doc/unstable-book/src/language-features/trait-upcasting.md
new file mode 100644
index 00000000000..3697ae38f9d
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/trait-upcasting.md
@@ -0,0 +1,27 @@
+# `trait_upcasting`
+
+The tracking issue for this feature is: [#65991]
+
+[#65991]: https://github.com/rust-lang/rust/issues/65991
+
+------------------------
+
+The `trait_upcasting` feature adds support for trait upcasting coercion. This allows a
+trait object of type `dyn Bar` to be cast to a trait object of type `dyn Foo`
+so long as `Bar: Foo`.
+
+```rust,edition2018
+#![feature(trait_upcasting)]
+#![allow(incomplete_features)]
+
+trait Foo {}
+
+trait Bar: Foo {}
+
+impl Foo for i32 {}
+
+impl<T: Foo + ?Sized> Bar for T {}
+
+let bar: &dyn Bar = &123;
+let foo: &dyn Foo = bar;
+```
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 80a47c85269..b0b6d994366 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -10,7 +10,7 @@
 #![feature(nonzero_ops)]
 #![feature(let_chains)]
 #![feature(lint_reasons)]
-#![feature(int_roundings)]
+#![cfg_attr(not(bootstrap), feature(trait_upcasting))]
 // Configure clippy and other lints
 #![allow(
     clippy::collapsible_else_if,
diff --git a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs
index 7d46ecd8f6e..648ac07c43e 100644
--- a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs
+++ b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs
@@ -1,3 +1,6 @@
+#![feature(trait_upcasting)]
+#![allow(incomplete_features)]
+
 trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
     fn a(&self) -> i32 {
         10
diff --git a/src/tools/miri/tests/pass/box-custom-alloc.rs b/src/tools/miri/tests/pass/box-custom-alloc.rs
index 75b512f6f72..8d6da0733fe 100644
--- a/src/tools/miri/tests/pass/box-custom-alloc.rs
+++ b/src/tools/miri/tests/pass/box-custom-alloc.rs
@@ -1,6 +1,7 @@
 //@revisions: stack tree
 //@[tree]compile-flags: -Zmiri-tree-borrows
-#![feature(allocator_api)]
+#![allow(incomplete_features)] // for trait upcasting
+#![feature(allocator_api, trait_upcasting)]
 
 use std::alloc::Layout;
 use std::alloc::{AllocError, Allocator};
diff --git a/src/tools/miri/tests/pass/dyn-upcast.rs b/src/tools/miri/tests/pass/dyn-upcast.rs
index ddaefeca3a3..8432012a9ba 100644
--- a/src/tools/miri/tests/pass/dyn-upcast.rs
+++ b/src/tools/miri/tests/pass/dyn-upcast.rs
@@ -1,3 +1,6 @@
+#![feature(trait_upcasting)]
+#![allow(incomplete_features)]
+
 fn main() {
     basic();
     diamond();
diff --git a/tests/incremental/commandline-args.rs b/tests/incremental/commandline-args.rs
index e17e6feae07..7a4c33d36e4 100644
--- a/tests/incremental/commandline-args.rs
+++ b/tests/incremental/commandline-args.rs
@@ -11,13 +11,13 @@
 #![rustc_partition_codegened(module="commandline_args", cfg="rpass4")]
 
 // Between revisions 1 and 2, we are changing the debuginfo-level, which should
-// invalidate the cache. Between revisions 2 and 3, we are adding `--verbose`
+// invalidate the cache. Between revisions 2 and 3, we are adding `--diagnostic-width`
 // which should have no effect on the cache. Between revisions, we are adding
 // `--remap-path-prefix` which should invalidate the cache:
 //[rpass1] compile-flags: -C debuginfo=0
 //[rpass2] compile-flags: -C debuginfo=2
-//[rpass3] compile-flags: -C debuginfo=2 --verbose
-//[rpass4] compile-flags: -C debuginfo=2 --verbose --remap-path-prefix=/home/bors/rust=src
+//[rpass3] compile-flags: -C debuginfo=2 --diagnostic-width=80
+//[rpass4] compile-flags: -C debuginfo=2 --diagnostic-width=80 --remap-path-prefix=/home/bors/r=src
 
 pub fn main() {
     // empty
diff --git a/tests/ui/codegen/issue-99551.rs b/tests/ui/codegen/issue-99551.rs
index 9e203fba113..b223aff4e94 100644
--- a/tests/ui/codegen/issue-99551.rs
+++ b/tests/ui/codegen/issue-99551.rs
@@ -1,4 +1,5 @@
 // build-pass
+#![feature(trait_upcasting)]
 
 pub trait A {}
 pub trait B {}
diff --git a/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs b/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs
index 0201c889706..a4eb669e321 100644
--- a/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs
+++ b/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs
@@ -1,4 +1,4 @@
-#![feature(dyn_star)]
+#![feature(dyn_star, trait_upcasting)]
 //~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
 
 trait A: B {}
diff --git a/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr b/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr
index 7e2cf661369..1f7bfb1d5bd 100644
--- a/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr
+++ b/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr
@@ -1,7 +1,7 @@
 warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/no-unsize-coerce-dyn-trait.rs:1:12
    |
-LL | #![feature(dyn_star)]
+LL | #![feature(dyn_star, trait_upcasting)]
    |            ^^^^^^^^
    |
    = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
diff --git a/tests/ui/dyn-star/upcast.rs b/tests/ui/dyn-star/upcast.rs
index 7748cdda943..c667ac143a3 100644
--- a/tests/ui/dyn-star/upcast.rs
+++ b/tests/ui/dyn-star/upcast.rs
@@ -1,6 +1,6 @@
 // known-bug: #104800
 
-#![feature(dyn_star)]
+#![feature(dyn_star, trait_upcasting)]
 
 trait Foo: Bar {
     fn hello(&self);
diff --git a/tests/ui/dyn-star/upcast.stderr b/tests/ui/dyn-star/upcast.stderr
index bdf77da713a..adef9525bf1 100644
--- a/tests/ui/dyn-star/upcast.stderr
+++ b/tests/ui/dyn-star/upcast.stderr
@@ -1,7 +1,7 @@
 warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/upcast.rs:3:12
    |
-LL | #![feature(dyn_star)]
+LL | #![feature(dyn_star, trait_upcasting)]
    |            ^^^^^^^^
    |
    = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
diff --git a/tests/ui/feature-gates/feature-gate-trait_upcasting.rs b/tests/ui/feature-gates/feature-gate-trait_upcasting.rs
new file mode 100644
index 00000000000..e4102f1cfa7
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-trait_upcasting.rs
@@ -0,0 +1,13 @@
+trait Foo {}
+
+trait Bar: Foo {}
+
+impl Foo for () {}
+
+impl Bar for () {}
+
+fn main() {
+    let bar: &dyn Bar = &();
+    let foo: &dyn Foo = bar;
+    //~^ ERROR trait upcasting coercion is experimental [E0658]
+}
diff --git a/tests/ui/feature-gates/feature-gate-trait_upcasting.stderr b/tests/ui/feature-gates/feature-gate-trait_upcasting.stderr
new file mode 100644
index 00000000000..6fd277ae8cc
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-trait_upcasting.stderr
@@ -0,0 +1,14 @@
+error[E0658]: cannot cast `dyn Bar` to `dyn Foo`, trait upcasting coercion is experimental
+  --> $DIR/feature-gate-trait_upcasting.rs:11:25
+   |
+LL |     let foo: &dyn Foo = bar;
+   |                         ^^^
+   |
+   = note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
+   = help: add `#![feature(trait_upcasting)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = note: required when coercing `&dyn Bar` into `&dyn Foo`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/120240-async-fn-never-arg.rs b/tests/ui/rfcs/rfc-0000-never_patterns/120240-async-fn-never-arg.rs
new file mode 100644
index 00000000000..9150c831c89
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/120240-async-fn-never-arg.rs
@@ -0,0 +1,16 @@
+// edition: 2018
+// known-bug: #120240
+#![feature(never_patterns)]
+#![allow(incomplete_features)]
+
+fn main() {}
+
+enum Void {}
+
+// Divergence is not detected.
+async fn async_never(!: Void) -> ! {} // gives an error
+
+// Divergence is detected
+async fn async_let(x: Void) -> ! {
+    let ! = x;
+}
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/120240-async-fn-never-arg.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/120240-async-fn-never-arg.stderr
new file mode 100644
index 00000000000..fa71feee5f5
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/120240-async-fn-never-arg.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/120240-async-fn-never-arg.rs:11:36
+   |
+LL | async fn async_never(!: Void) -> ! {} // gives an error
+   |                                    ^^ expected `!`, found `()`
+   |
+   = note:   expected type `!`
+           found unit type `()`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/diverge-causes-unreachable-code.rs b/tests/ui/rfcs/rfc-0000-never_patterns/diverge-causes-unreachable-code.rs
new file mode 100644
index 00000000000..f7e4007b920
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/diverge-causes-unreachable-code.rs
@@ -0,0 +1,36 @@
+#![feature(never_patterns)]
+#![allow(incomplete_features)]
+#![deny(unreachable_patterns)]
+#![deny(unreachable_code)]
+
+fn main() {}
+
+enum Void {}
+
+fn never_arg(!: Void) -> u32 {
+    println!();
+    //~^ ERROR unreachable statement
+}
+
+fn ref_never_arg(&!: &Void) -> u32 {
+    println!();
+    //~^ ERROR unreachable statement
+}
+
+fn never_let() -> u32 {
+    let ptr: *const Void = std::ptr::null();
+    unsafe {
+        let ! = *ptr;
+    }
+    println!();
+    //~^ ERROR unreachable statement
+}
+
+fn never_match() -> u32 {
+    let ptr: *const Void = std::ptr::null();
+    unsafe {
+        match *ptr { ! };
+    }
+    println!();
+    //~^ ERROR unreachable statement
+}
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/diverge-causes-unreachable-code.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/diverge-causes-unreachable-code.stderr
new file mode 100644
index 00000000000..c33a5855d50
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/diverge-causes-unreachable-code.stderr
@@ -0,0 +1,49 @@
+error: unreachable statement
+  --> $DIR/diverge-causes-unreachable-code.rs:11:5
+   |
+LL | fn never_arg(!: Void) -> u32 {
+   |              - any code following a never pattern is unreachable
+LL |     println!();
+   |     ^^^^^^^^^^ unreachable statement
+   |
+note: the lint level is defined here
+  --> $DIR/diverge-causes-unreachable-code.rs:4:9
+   |
+LL | #![deny(unreachable_code)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: this error originates in the macro `$crate::print` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: unreachable statement
+  --> $DIR/diverge-causes-unreachable-code.rs:16:5
+   |
+LL | fn ref_never_arg(&!: &Void) -> u32 {
+   |                  -- any code following a never pattern is unreachable
+LL |     println!();
+   |     ^^^^^^^^^^ unreachable statement
+   |
+   = note: this error originates in the macro `$crate::print` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: unreachable statement
+  --> $DIR/diverge-causes-unreachable-code.rs:25:5
+   |
+LL |         let ! = *ptr;
+   |             - any code following a never pattern is unreachable
+LL |     }
+LL |     println!();
+   |     ^^^^^^^^^^ unreachable statement
+   |
+   = note: this error originates in the macro `$crate::print` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: unreachable statement
+  --> $DIR/diverge-causes-unreachable-code.rs:34:5
+   |
+LL |         match *ptr { ! };
+   |         ---------------- any code following this `match` expression is unreachable, as all arms diverge
+LL |     }
+LL |     println!();
+   |     ^^^^^^^^^^ unreachable statement
+   |
+   = note: this error originates in the macro `$crate::print` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/diverges-not.rs b/tests/ui/rfcs/rfc-0000-never_patterns/diverges-not.rs
new file mode 100644
index 00000000000..6b85ada3aad
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/diverges-not.rs
@@ -0,0 +1,56 @@
+#![feature(never_patterns)]
+#![feature(let_chains)]
+#![allow(incomplete_features)]
+#![deny(unreachable_patterns)]
+
+fn main() {}
+
+enum Void {}
+
+// Contrast with `./diverges.rs`: merely having an empty type around isn't enough to diverge.
+
+fn wild_void(_: Void) -> u32 {}
+//~^ ERROR: mismatched types
+
+fn wild_let() -> u32 {
+    let ptr: *const Void = std::ptr::null();
+    unsafe {
+        //~^ ERROR: mismatched types
+        let _ = *ptr;
+    }
+}
+
+fn wild_match() -> u32 {
+    let ptr: *const Void = std::ptr::null();
+    unsafe {
+        match *ptr {
+            _ => {} //~ ERROR: mismatched types
+        }
+    }
+}
+
+fn binding_void(_x: Void) -> u32 {}
+//~^ ERROR: mismatched types
+
+fn binding_let() -> u32 {
+    let ptr: *const Void = std::ptr::null();
+    unsafe {
+        //~^ ERROR: mismatched types
+        let _x = *ptr;
+    }
+}
+
+fn binding_match() -> u32 {
+    let ptr: *const Void = std::ptr::null();
+    unsafe {
+        match *ptr {
+            _x => {} //~ ERROR: mismatched types
+        }
+    }
+}
+
+// Don't confuse this with a `let !` statement.
+fn let_chain(x: Void) -> u32 {
+    if let true = true && let ! = x {}
+    //~^ ERROR: mismatched types
+}
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/diverges-not.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/diverges-not.stderr
new file mode 100644
index 00000000000..08a1bbe9bff
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/diverges-not.stderr
@@ -0,0 +1,55 @@
+error[E0308]: mismatched types
+  --> $DIR/diverges-not.rs:12:26
+   |
+LL | fn wild_void(_: Void) -> u32 {}
+   |    ---------             ^^^ expected `u32`, found `()`
+   |    |
+   |    implicitly returns `()` as its body has no tail or `return` expression
+
+error[E0308]: mismatched types
+  --> $DIR/diverges-not.rs:17:5
+   |
+LL | /     unsafe {
+LL | |
+LL | |         let _ = *ptr;
+LL | |     }
+   | |_____^ expected `u32`, found `()`
+
+error[E0308]: mismatched types
+  --> $DIR/diverges-not.rs:27:18
+   |
+LL |             _ => {}
+   |                  ^^ expected `u32`, found `()`
+
+error[E0308]: mismatched types
+  --> $DIR/diverges-not.rs:32:30
+   |
+LL | fn binding_void(_x: Void) -> u32 {}
+   |    ------------              ^^^ expected `u32`, found `()`
+   |    |
+   |    implicitly returns `()` as its body has no tail or `return` expression
+
+error[E0308]: mismatched types
+  --> $DIR/diverges-not.rs:37:5
+   |
+LL | /     unsafe {
+LL | |
+LL | |         let _x = *ptr;
+LL | |     }
+   | |_____^ expected `u32`, found `()`
+
+error[E0308]: mismatched types
+  --> $DIR/diverges-not.rs:47:19
+   |
+LL |             _x => {}
+   |                   ^^ expected `u32`, found `()`
+
+error[E0308]: mismatched types
+  --> $DIR/diverges-not.rs:54:37
+   |
+LL |     if let true = true && let ! = x {}
+   |                                     ^^ expected `u32`, found `()`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/diverges.rs b/tests/ui/rfcs/rfc-0000-never_patterns/diverges.rs
new file mode 100644
index 00000000000..3783100b502
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/diverges.rs
@@ -0,0 +1,38 @@
+// check-pass
+// edition: 2018
+#![feature(never_patterns)]
+#![allow(incomplete_features)]
+#![deny(unreachable_patterns)]
+
+fn main() {}
+
+enum Void {}
+
+// A never pattern alone diverges.
+
+fn never_arg(!: Void) -> ! {}
+
+fn never_arg_returns_anything<T>(!: Void) -> T {}
+
+fn ref_never_arg(&!: &Void) -> ! {}
+
+fn never_let() -> ! {
+    let ptr: *const Void = std::ptr::null();
+    unsafe {
+        let ! = *ptr;
+    }
+}
+
+fn never_match() -> ! {
+    let ptr: *const Void = std::ptr::null();
+    unsafe {
+        match *ptr { ! };
+    }
+    // Ensures this typechecks because of divergence and not the type of the match expression.
+    println!();
+}
+
+// Note: divergence is not detected for async fns when the `!` is in the argument (#120240).
+async fn async_let(x: Void) -> ! {
+    let ! = x;
+}
diff --git a/tests/ui/traits/next-solver/normalize-unsize-rhs.rs b/tests/ui/traits/next-solver/normalize-unsize-rhs.rs
index 6ca82d1b872..08bb0cf42e8 100644
--- a/tests/ui/traits/next-solver/normalize-unsize-rhs.rs
+++ b/tests/ui/traits/next-solver/normalize-unsize-rhs.rs
@@ -1,5 +1,6 @@
 // compile-flags: -Znext-solver
 // check-pass
+#![feature(trait_upcasting)]
 
 trait A {}
 trait B: A {}
diff --git a/tests/ui/traits/next-solver/trait-upcast-lhs-needs-normalization.rs b/tests/ui/traits/next-solver/trait-upcast-lhs-needs-normalization.rs
index 2a482f74668..8e0378e94f0 100644
--- a/tests/ui/traits/next-solver/trait-upcast-lhs-needs-normalization.rs
+++ b/tests/ui/traits/next-solver/trait-upcast-lhs-needs-normalization.rs
@@ -1,5 +1,6 @@
 // check-pass
 // compile-flags: -Znext-solver
+#![feature(trait_upcasting)]
 
 pub trait A {}
 pub trait B: A {}
diff --git a/tests/ui/traits/next-solver/upcast-right-substs.rs b/tests/ui/traits/next-solver/upcast-right-substs.rs
index 5e4d958c895..5b4f6d4be0c 100644
--- a/tests/ui/traits/next-solver/upcast-right-substs.rs
+++ b/tests/ui/traits/next-solver/upcast-right-substs.rs
@@ -1,5 +1,6 @@
 // compile-flags: -Znext-solver
 // check-pass
+#![feature(trait_upcasting)]
 
 trait Foo: Bar<i32> + Bar<u32> {}
 
diff --git a/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.rs b/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.rs
index 927a9d6b94f..4a5e445d1ef 100644
--- a/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.rs
+++ b/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.rs
@@ -1,3 +1,4 @@
+#![feature(trait_upcasting)]
 #![feature(trait_alias)]
 
 // Although we *elaborate* `T: Alias` to `i32: B`, we should
diff --git a/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.stderr b/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.stderr
index 1a410519a4e..99c82b88d9c 100644
--- a/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.stderr
+++ b/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/alias-where-clause-isnt-supertrait.rs:26:5
+  --> $DIR/alias-where-clause-isnt-supertrait.rs:27:5
    |
 LL | fn test(x: &dyn C) -> &dyn B {
    |                       ------ expected `&dyn B` because of return type
diff --git a/tests/ui/traits/trait-upcasting/basic.rs b/tests/ui/traits/trait-upcasting/basic.rs
index 538cd8329cc..570ec5160bf 100644
--- a/tests/ui/traits/trait-upcasting/basic.rs
+++ b/tests/ui/traits/trait-upcasting/basic.rs
@@ -1,5 +1,7 @@
 // run-pass
 
+#![feature(trait_upcasting)]
+
 trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
     fn a(&self) -> i32 {
         10
diff --git a/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs b/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs
index 4a379d9f875..eae5cf8d58d 100644
--- a/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs
+++ b/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs
@@ -1,4 +1,5 @@
 // run-pass
+#![feature(trait_upcasting)]
 
 trait Foo<T: Default + ToString>: Bar<i32> + Bar<T> {}
 trait Bar<T: Default + ToString> {
diff --git a/tests/ui/traits/trait-upcasting/deref-lint-regions.stderr b/tests/ui/traits/trait-upcasting/deref-lint-regions.stderr
deleted file mode 100644
index 557a4420a3d..00000000000
--- a/tests/ui/traits/trait-upcasting/deref-lint-regions.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-warning: this `Deref` implementation is covered by an implicit supertrait coercion
-  --> $DIR/deref-lint-regions.rs:8:1
-   |
-LL | impl<'a> Deref for dyn Foo<'a> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo<'_>` implements `Deref<Target = dyn Bar<'_>>` which conflicts with supertrait `Bar<'_>`
-LL |
-LL |     type Target = dyn Bar<'a>;
-   |     -------------------------- target type is a supertrait of `dyn Foo<'_>`
-   |
-   = help: consider removing this implementation or replacing it with a method instead
-   = note: `#[warn(deref_into_dyn_supertrait)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/traits/trait-upcasting/deref-lint.stderr b/tests/ui/traits/trait-upcasting/deref-lint.stderr
deleted file mode 100644
index 5a13659edf5..00000000000
--- a/tests/ui/traits/trait-upcasting/deref-lint.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-warning: this `Deref` implementation is covered by an implicit supertrait coercion
-  --> $DIR/deref-lint.rs:9:1
-   |
-LL | impl<'a> Deref for dyn 'a + B {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn B` implements `Deref<Target = dyn A>` which conflicts with supertrait `A`
-...
-LL |     type Target = dyn A;
-   |     -------------------- target type is a supertrait of `dyn B`
-   |
-   = help: consider removing this implementation or replacing it with a method instead
-   = note: `#[warn(deref_into_dyn_supertrait)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.rs b/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.rs
index 366eae1a58a..e4784fa4101 100644
--- a/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.rs
+++ b/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.rs
@@ -15,6 +15,8 @@ impl Foo for () {
 }
 
 impl<'a> Deref for dyn Foo + 'a {
+    //~^ ERROR this `Deref` implementation is covered by an implicit supertrait coercion
+    //~| WARN this will change its meaning in a future release!
     type Target = dyn Bar<u32> + 'a;
 
     fn deref(&self) -> &Self::Target {
@@ -30,5 +32,4 @@ fn main() {
     let x: &dyn Foo = &();
     let y = take_dyn(x);
     let z: u32 = y;
-    //~^ ERROR mismatched types
 }
diff --git a/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.stderr b/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.stderr
index 193d09e3501..fa93e28c73b 100644
--- a/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.stderr
+++ b/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.stderr
@@ -1,16 +1,19 @@
-error[E0308]: mismatched types
-  --> $DIR/deref-upcast-behavioral-change.rs:32:18
+error: this `Deref` implementation is covered by an implicit supertrait coercion
+  --> $DIR/deref-upcast-behavioral-change.rs:17:1
    |
-LL |     let z: u32 = y;
-   |            ---   ^ expected `u32`, found `i32`
-   |            |
-   |            expected due to this
+LL | impl<'a> Deref for dyn Foo + 'a {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo` implements `Deref<Target = dyn Bar<u32>>` which conflicts with supertrait `Bar<i32>`
+...
+LL |     type Target = dyn Bar<u32> + 'a;
+   |     -------------------------------- target type is a supertrait of `dyn Foo`
    |
-help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
+note: the lint level is defined here
+  --> $DIR/deref-upcast-behavioral-change.rs:1:9
    |
-LL |     let z: u32 = y.try_into().unwrap();
-   |                   ++++++++++++++++++++
+LL | #![deny(deref_into_dyn_supertrait)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/trait-upcasting/diamond.rs b/tests/ui/traits/trait-upcasting/diamond.rs
index 9a78339a4ec..a4f81c464b4 100644
--- a/tests/ui/traits/trait-upcasting/diamond.rs
+++ b/tests/ui/traits/trait-upcasting/diamond.rs
@@ -1,5 +1,7 @@
 // run-pass
 
+#![feature(trait_upcasting)]
+
 trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
     fn a(&self) -> i32 {
         10
diff --git a/tests/ui/traits/trait-upcasting/fewer-associated.rs b/tests/ui/traits/trait-upcasting/fewer-associated.rs
index e7ca6fa5208..58e72d9d7ef 100644
--- a/tests/ui/traits/trait-upcasting/fewer-associated.rs
+++ b/tests/ui/traits/trait-upcasting/fewer-associated.rs
@@ -3,6 +3,8 @@
 // revisions: current next
 //[next] compile-flags: -Znext-solver
 
+#![feature(trait_upcasting)]
+
 trait A: B {
     type Assoc;
 }
diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.current.stderr b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.current.stderr
index 119b3109c63..1538e2f3fd7 100644
--- a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.current.stderr
+++ b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.current.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/illegal-upcast-from-impl.rs:14:66
+  --> $DIR/illegal-upcast-from-impl.rs:16:66
    |
 LL | fn illegal(x: &dyn Sub<Assoc = ()>) -> &dyn Super<Assoc = i32> { x }
    |                                        -----------------------   ^ expected trait `Super`, found trait `Sub`
diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.next.stderr b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.next.stderr
index 119b3109c63..1538e2f3fd7 100644
--- a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.next.stderr
+++ b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.next.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/illegal-upcast-from-impl.rs:14:66
+  --> $DIR/illegal-upcast-from-impl.rs:16:66
    |
 LL | fn illegal(x: &dyn Sub<Assoc = ()>) -> &dyn Super<Assoc = i32> { x }
    |                                        -----------------------   ^ expected trait `Super`, found trait `Sub`
diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs
index 5a493fd48b3..ffed8beb448 100644
--- a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs
+++ b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs
@@ -1,6 +1,8 @@
 // revisions: current next
 //[next] compile-flags: -Znext-solver
 
+#![feature(trait_upcasting)]
+
 trait Super {
     type Assoc;
 }
diff --git a/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.rs b/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.rs
index 999f3b16f50..79fb643eacd 100644
--- a/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.rs
+++ b/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.rs
@@ -1,4 +1,5 @@
 #![deny(deref_into_dyn_supertrait)]
+#![feature(trait_upcasting)] // remove this and the test compiles
 
 use std::ops::Deref;
 
diff --git a/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.stderr b/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.stderr
index fcc80c6148f..6b6a26d1593 100644
--- a/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.stderr
+++ b/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/inference-behavior-change-deref.rs:33:18
+  --> $DIR/inference-behavior-change-deref.rs:34:18
    |
 LL |     let z: u32 = y;
    |            ---   ^ expected `u32`, found `i32`
diff --git a/tests/ui/traits/trait-upcasting/invalid-upcast.rs b/tests/ui/traits/trait-upcasting/invalid-upcast.rs
index 9269a5e3e9f..e634bbd5ac6 100644
--- a/tests/ui/traits/trait-upcasting/invalid-upcast.rs
+++ b/tests/ui/traits/trait-upcasting/invalid-upcast.rs
@@ -1,3 +1,5 @@
+#![feature(trait_upcasting)]
+
 trait Foo {
     fn a(&self) -> i32 {
         10
diff --git a/tests/ui/traits/trait-upcasting/invalid-upcast.stderr b/tests/ui/traits/trait-upcasting/invalid-upcast.stderr
index e70b99d28c7..3aa21ee3ddd 100644
--- a/tests/ui/traits/trait-upcasting/invalid-upcast.stderr
+++ b/tests/ui/traits/trait-upcasting/invalid-upcast.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:51:35
+  --> $DIR/invalid-upcast.rs:53:35
    |
 LL |     let _: &dyn std::fmt::Debug = baz;
    |            --------------------   ^^^ expected trait `Debug`, found trait `Baz`
@@ -10,7 +10,7 @@ LL |     let _: &dyn std::fmt::Debug = baz;
               found reference `&dyn Baz`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:53:24
+  --> $DIR/invalid-upcast.rs:55:24
    |
 LL |     let _: &dyn Send = baz;
    |            ---------   ^^^ expected trait `Send`, found trait `Baz`
@@ -21,7 +21,7 @@ LL |     let _: &dyn Send = baz;
               found reference `&dyn Baz`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:55:24
+  --> $DIR/invalid-upcast.rs:57:24
    |
 LL |     let _: &dyn Sync = baz;
    |            ---------   ^^^ expected trait `Sync`, found trait `Baz`
@@ -32,7 +32,7 @@ LL |     let _: &dyn Sync = baz;
               found reference `&dyn Baz`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:58:25
+  --> $DIR/invalid-upcast.rs:60:25
    |
 LL |     let bar: &dyn Bar = baz;
    |              --------   ^^^ expected trait `Bar`, found trait `Baz`
@@ -43,7 +43,7 @@ LL |     let bar: &dyn Bar = baz;
               found reference `&dyn Baz`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:60:35
+  --> $DIR/invalid-upcast.rs:62:35
    |
 LL |     let _: &dyn std::fmt::Debug = bar;
    |            --------------------   ^^^ expected trait `Debug`, found trait `Bar`
@@ -54,7 +54,7 @@ LL |     let _: &dyn std::fmt::Debug = bar;
               found reference `&dyn Bar`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:62:24
+  --> $DIR/invalid-upcast.rs:64:24
    |
 LL |     let _: &dyn Send = bar;
    |            ---------   ^^^ expected trait `Send`, found trait `Bar`
@@ -65,7 +65,7 @@ LL |     let _: &dyn Send = bar;
               found reference `&dyn Bar`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:64:24
+  --> $DIR/invalid-upcast.rs:66:24
    |
 LL |     let _: &dyn Sync = bar;
    |            ---------   ^^^ expected trait `Sync`, found trait `Bar`
@@ -76,7 +76,7 @@ LL |     let _: &dyn Sync = bar;
               found reference `&dyn Bar`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:67:25
+  --> $DIR/invalid-upcast.rs:69:25
    |
 LL |     let foo: &dyn Foo = baz;
    |              --------   ^^^ expected trait `Foo`, found trait `Baz`
@@ -87,7 +87,7 @@ LL |     let foo: &dyn Foo = baz;
               found reference `&dyn Baz`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:69:35
+  --> $DIR/invalid-upcast.rs:71:35
    |
 LL |     let _: &dyn std::fmt::Debug = foo;
    |            --------------------   ^^^ expected trait `Debug`, found trait `Foo`
@@ -98,7 +98,7 @@ LL |     let _: &dyn std::fmt::Debug = foo;
               found reference `&dyn Foo`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:71:24
+  --> $DIR/invalid-upcast.rs:73:24
    |
 LL |     let _: &dyn Send = foo;
    |            ---------   ^^^ expected trait `Send`, found trait `Foo`
@@ -109,7 +109,7 @@ LL |     let _: &dyn Send = foo;
               found reference `&dyn Foo`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:73:24
+  --> $DIR/invalid-upcast.rs:75:24
    |
 LL |     let _: &dyn Sync = foo;
    |            ---------   ^^^ expected trait `Sync`, found trait `Foo`
@@ -120,7 +120,7 @@ LL |     let _: &dyn Sync = foo;
               found reference `&dyn Foo`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:76:25
+  --> $DIR/invalid-upcast.rs:78:25
    |
 LL |     let foo: &dyn Foo = bar;
    |              --------   ^^^ expected trait `Foo`, found trait `Bar`
@@ -131,7 +131,7 @@ LL |     let foo: &dyn Foo = bar;
               found reference `&dyn Bar`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:78:35
+  --> $DIR/invalid-upcast.rs:80:35
    |
 LL |     let _: &dyn std::fmt::Debug = foo;
    |            --------------------   ^^^ expected trait `Debug`, found trait `Foo`
@@ -142,7 +142,7 @@ LL |     let _: &dyn std::fmt::Debug = foo;
               found reference `&dyn Foo`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:80:24
+  --> $DIR/invalid-upcast.rs:82:24
    |
 LL |     let _: &dyn Send = foo;
    |            ---------   ^^^ expected trait `Send`, found trait `Foo`
@@ -153,7 +153,7 @@ LL |     let _: &dyn Send = foo;
               found reference `&dyn Foo`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:82:24
+  --> $DIR/invalid-upcast.rs:84:24
    |
 LL |     let _: &dyn Sync = foo;
    |            ---------   ^^^ expected trait `Sync`, found trait `Foo`
diff --git a/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs b/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs
index 77ce627078f..b672963ae98 100644
--- a/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs
+++ b/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs
@@ -1,4 +1,5 @@
 // run-pass
+#![feature(trait_upcasting)]
 
 struct Test {
     func: Box<dyn FnMut() + 'static>,
diff --git a/tests/ui/traits/trait-upcasting/issue-11515.current.stderr b/tests/ui/traits/trait-upcasting/issue-11515.current.stderr
new file mode 100644
index 00000000000..ce799dcb7ef
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/issue-11515.current.stderr
@@ -0,0 +1,14 @@
+error[E0658]: cannot cast `dyn Fn()` to `dyn FnMut()`, trait upcasting coercion is experimental
+  --> $DIR/issue-11515.rs:10:38
+   |
+LL |     let test = Box::new(Test { func: closure });
+   |                                      ^^^^^^^
+   |
+   = note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
+   = help: add `#![feature(trait_upcasting)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = note: required when coercing `Box<(dyn Fn() + 'static)>` into `Box<(dyn FnMut() + 'static)>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/traits/trait-upcasting/issue-11515.next.stderr b/tests/ui/traits/trait-upcasting/issue-11515.next.stderr
new file mode 100644
index 00000000000..ce799dcb7ef
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/issue-11515.next.stderr
@@ -0,0 +1,14 @@
+error[E0658]: cannot cast `dyn Fn()` to `dyn FnMut()`, trait upcasting coercion is experimental
+  --> $DIR/issue-11515.rs:10:38
+   |
+LL |     let test = Box::new(Test { func: closure });
+   |                                      ^^^^^^^
+   |
+   = note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
+   = help: add `#![feature(trait_upcasting)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = note: required when coercing `Box<(dyn Fn() + 'static)>` into `Box<(dyn FnMut() + 'static)>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/traits/trait-upcasting/issue-11515.rs b/tests/ui/traits/trait-upcasting/issue-11515.rs
index a1edb53ec37..31ea2fb353c 100644
--- a/tests/ui/traits/trait-upcasting/issue-11515.rs
+++ b/tests/ui/traits/trait-upcasting/issue-11515.rs
@@ -1,4 +1,3 @@
-// check-pass
 // revisions: current next
 //[next] compile-flags: -Znext-solver
 
@@ -8,5 +7,5 @@ struct Test {
 
 fn main() {
     let closure: Box<dyn Fn() + 'static> = Box::new(|| ());
-    let test = Box::new(Test { func: closure });
+    let test = Box::new(Test { func: closure }); //~ ERROR trait upcasting coercion is experimental [E0658]
 }
diff --git a/tests/ui/traits/trait-upcasting/lifetime.rs b/tests/ui/traits/trait-upcasting/lifetime.rs
index 6c65c38870f..9825158c2dd 100644
--- a/tests/ui/traits/trait-upcasting/lifetime.rs
+++ b/tests/ui/traits/trait-upcasting/lifetime.rs
@@ -1,5 +1,7 @@
 // run-pass
 
+#![feature(trait_upcasting)]
+
 trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
     fn a(&self) -> i32 {
         10
diff --git a/tests/ui/traits/trait-upcasting/deref-lint-regions.rs b/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.rs
index 946305cbb2b..da1a9cc2775 100644
--- a/tests/ui/traits/trait-upcasting/deref-lint-regions.rs
+++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.rs
@@ -1,4 +1,4 @@
-// check-pass
+#![deny(deref_into_dyn_supertrait)]
 
 use std::ops::Deref;
 
@@ -6,7 +6,8 @@ trait Bar<'a> {}
 trait Foo<'a>: Bar<'a> {}
 
 impl<'a> Deref for dyn Foo<'a> {
-    //~^ WARN this `Deref` implementation is covered by an implicit supertrait coercion
+    //~^ ERROR this `Deref` implementation is covered by an implicit supertrait coercion
+    //~| WARN this will change its meaning in a future release!
     type Target = dyn Bar<'a>;
 
     fn deref(&self) -> &Self::Target {
diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.stderr b/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.stderr
new file mode 100644
index 00000000000..a5f3660d4bc
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.stderr
@@ -0,0 +1,19 @@
+error: this `Deref` implementation is covered by an implicit supertrait coercion
+  --> $DIR/migrate-lint-deny-regions.rs:8:1
+   |
+LL | impl<'a> Deref for dyn Foo<'a> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo<'_>` implements `Deref<Target = dyn Bar<'_>>` which conflicts with supertrait `Bar<'_>`
+...
+LL |     type Target = dyn Bar<'a>;
+   |     -------------------------- target type is a supertrait of `dyn Foo<'_>`
+   |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
+note: the lint level is defined here
+  --> $DIR/migrate-lint-deny-regions.rs:1:9
+   |
+LL | #![deny(deref_into_dyn_supertrait)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/traits/trait-upcasting/deref-lint.rs b/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs
index 68838d2ae20..926b3649e01 100644
--- a/tests/ui/traits/trait-upcasting/deref-lint.rs
+++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs
@@ -1,4 +1,4 @@
-// check-pass
+#![deny(deref_into_dyn_supertrait)]
 
 use std::ops::Deref;
 
@@ -7,7 +7,8 @@ trait A {}
 trait B: A {}
 
 impl<'a> Deref for dyn 'a + B {
-    //~^ WARN this `Deref` implementation is covered by an implicit supertrait coercion
+    //~^ ERROR this `Deref` implementation is covered by an implicit supertrait coercion
+    //~| WARN this will change its meaning in a future release!
 
     type Target = dyn A;
     fn deref(&self) -> &Self::Target {
diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr b/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr
new file mode 100644
index 00000000000..29997a9b3d9
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr
@@ -0,0 +1,19 @@
+error: this `Deref` implementation is covered by an implicit supertrait coercion
+  --> $DIR/migrate-lint-deny.rs:9:1
+   |
+LL | impl<'a> Deref for dyn 'a + B {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn B` implements `Deref<Target = dyn A>` which conflicts with supertrait `A`
+...
+LL |     type Target = dyn A;
+   |     -------------------- target type is a supertrait of `dyn B`
+   |
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
+note: the lint level is defined here
+  --> $DIR/migrate-lint-deny.rs:1:9
+   |
+LL | #![deny(deref_into_dyn_supertrait)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.rs b/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.rs
index 2c9126c863d..8a90a09ff04 100644
--- a/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.rs
+++ b/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.rs
@@ -10,6 +10,7 @@ trait Foo: Bar<i32> {
 
 impl<'a> Deref for dyn Foo + 'a {
     //~^ WARN this `Deref` implementation is covered by an implicit supertrait coercion
+    //~| WARN this will change its meaning in a future release!
     type Target = dyn Bar<u32> + 'a;
 
     fn deref(&self) -> &Self::Target {
diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.stderr b/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.stderr
index a447f9cf83b..6245da5a176 100644
--- a/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.stderr
+++ b/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.stderr
@@ -3,11 +3,12 @@ warning: this `Deref` implementation is covered by an implicit supertrait coerci
    |
 LL | impl<'a> Deref for dyn Foo + 'a {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo` implements `Deref<Target = dyn Bar<u32>>` which conflicts with supertrait `Bar<i32>`
-LL |
+...
 LL |     type Target = dyn Bar<u32> + 'a;
    |     -------------------------------- target type is a supertrait of `dyn Foo`
    |
-   = help: consider removing this implementation or replacing it with a method instead
+   = warning: this will change its meaning in a future release!
+   = note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
    = note: `#[warn(deref_into_dyn_supertrait)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs
index 0e17c276717..2e53a00a90e 100644
--- a/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs
+++ b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs
@@ -1,4 +1,5 @@
 // check-fail
+#![feature(trait_upcasting)]
 
 trait Bar<T> {
     fn bar(&self, _: T) {}
diff --git a/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr
index c888ccc1ebb..70ba1fcaf38 100644
--- a/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr
+++ b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/multiple-occurrence-ambiguousity.rs:19:26
+  --> $DIR/multiple-occurrence-ambiguousity.rs:20:26
    |
 LL |     let t: &dyn Bar<_> = s;
    |            -----------   ^ expected trait `Bar`, found trait `Foo`
diff --git a/tests/ui/traits/trait-upcasting/normalization.rs b/tests/ui/traits/trait-upcasting/normalization.rs
index b594969483a..24da1ec5dfb 100644
--- a/tests/ui/traits/trait-upcasting/normalization.rs
+++ b/tests/ui/traits/trait-upcasting/normalization.rs
@@ -3,6 +3,8 @@
 // revisions: current next
 //[next] compile-flags: -Znext-solver
 
+#![feature(trait_upcasting)]
+
 trait Mirror {
     type Assoc;
 }
diff --git a/tests/ui/traits/trait-upcasting/replace-vptr.rs b/tests/ui/traits/trait-upcasting/replace-vptr.rs
index 4a7304ec2d7..9ccfc9306ac 100644
--- a/tests/ui/traits/trait-upcasting/replace-vptr.rs
+++ b/tests/ui/traits/trait-upcasting/replace-vptr.rs
@@ -1,5 +1,7 @@
 // run-pass
 
+#![feature(trait_upcasting)]
+
 trait A {
     fn foo_a(&self);
 }
diff --git a/tests/ui/traits/trait-upcasting/struct.rs b/tests/ui/traits/trait-upcasting/struct.rs
index 64fa9ca1b5f..a3e41696956 100644
--- a/tests/ui/traits/trait-upcasting/struct.rs
+++ b/tests/ui/traits/trait-upcasting/struct.rs
@@ -1,5 +1,7 @@
 // run-pass
 
+#![feature(trait_upcasting)]
+
 use std::rc::Rc;
 use std::sync::Arc;
 
diff --git a/tests/ui/traits/trait-upcasting/subtrait-method.rs b/tests/ui/traits/trait-upcasting/subtrait-method.rs
index 20277280440..136d15af0e8 100644
--- a/tests/ui/traits/trait-upcasting/subtrait-method.rs
+++ b/tests/ui/traits/trait-upcasting/subtrait-method.rs
@@ -1,3 +1,5 @@
+#![feature(trait_upcasting)]
+
 trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
     fn a(&self) -> i32 {
         10
diff --git a/tests/ui/traits/trait-upcasting/subtrait-method.stderr b/tests/ui/traits/trait-upcasting/subtrait-method.stderr
index 3fdf3f48161..918159e845b 100644
--- a/tests/ui/traits/trait-upcasting/subtrait-method.stderr
+++ b/tests/ui/traits/trait-upcasting/subtrait-method.stderr
@@ -1,64 +1,64 @@
 error[E0599]: no method named `c` found for reference `&dyn Bar` in the current scope
-  --> $DIR/subtrait-method.rs:53:9
+  --> $DIR/subtrait-method.rs:55:9
    |
 LL |     bar.c();
    |         ^ help: there is a method with a similar name: `a`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `Baz` defines an item `c`, perhaps you need to implement it
-  --> $DIR/subtrait-method.rs:25:1
+  --> $DIR/subtrait-method.rs:27:1
    |
 LL | trait Baz: Bar {
    | ^^^^^^^^^^^^^^
 
 error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope
-  --> $DIR/subtrait-method.rs:57:9
+  --> $DIR/subtrait-method.rs:59:9
    |
 LL |     foo.b();
    |         ^ help: there is a method with a similar name: `a`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `Bar` defines an item `b`, perhaps you need to implement it
-  --> $DIR/subtrait-method.rs:15:1
+  --> $DIR/subtrait-method.rs:17:1
    |
 LL | trait Bar: Foo {
    | ^^^^^^^^^^^^^^
 
 error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
-  --> $DIR/subtrait-method.rs:59:9
+  --> $DIR/subtrait-method.rs:61:9
    |
 LL |     foo.c();
    |         ^ help: there is a method with a similar name: `a`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `Baz` defines an item `c`, perhaps you need to implement it
-  --> $DIR/subtrait-method.rs:25:1
+  --> $DIR/subtrait-method.rs:27:1
    |
 LL | trait Baz: Bar {
    | ^^^^^^^^^^^^^^
 
 error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope
-  --> $DIR/subtrait-method.rs:63:9
+  --> $DIR/subtrait-method.rs:65:9
    |
 LL |     foo.b();
    |         ^ help: there is a method with a similar name: `a`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `Bar` defines an item `b`, perhaps you need to implement it
-  --> $DIR/subtrait-method.rs:15:1
+  --> $DIR/subtrait-method.rs:17:1
    |
 LL | trait Bar: Foo {
    | ^^^^^^^^^^^^^^
 
 error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
-  --> $DIR/subtrait-method.rs:65:9
+  --> $DIR/subtrait-method.rs:67:9
    |
 LL |     foo.c();
    |         ^ help: there is a method with a similar name: `a`
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `Baz` defines an item `c`, perhaps you need to implement it
-  --> $DIR/subtrait-method.rs:25:1
+  --> $DIR/subtrait-method.rs:27:1
    |
 LL | trait Baz: Bar {
    | ^^^^^^^^^^^^^^
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr
index 47ffa68b8ff..10c22440a83 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr
@@ -1,5 +1,5 @@
 error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>`
-  --> $DIR/type-checking-test-1.rs:17:13
+  --> $DIR/type-checking-test-1.rs:19:13
    |
 LL |     let _ = x as &dyn Bar<_>; // Ambiguous
    |             ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr
index 47ffa68b8ff..10c22440a83 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr
@@ -1,5 +1,5 @@
 error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>`
-  --> $DIR/type-checking-test-1.rs:17:13
+  --> $DIR/type-checking-test-1.rs:19:13
    |
 LL |     let _ = x as &dyn Bar<_>; // Ambiguous
    |             ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
index 7d3deeeaa61..54c3c5e0c28 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
@@ -1,6 +1,8 @@
 // revisions: current next
 //[next] compile-flags: -Znext-solver
 
+#![feature(trait_upcasting)]
+
 trait Foo: Bar<i32> + Bar<u32> {}
 trait Bar<T> {
     fn bar(&self) -> Option<T> {
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.rs b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs
index b4df0f5a902..b024b27750b 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-2.rs
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs
@@ -1,3 +1,5 @@
+#![feature(trait_upcasting)]
+
 trait Foo<T>: Bar<i32> + Bar<T> {}
 trait Bar<T> {
     fn bar(&self) -> Option<T> {
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
index f84ea93dc67..3e59b9d3363 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
@@ -1,11 +1,11 @@
 error[E0605]: non-primitive cast: `&dyn Foo<i32>` as `&dyn Bar<u32>`
-  --> $DIR/type-checking-test-2.rs:17:13
+  --> $DIR/type-checking-test-2.rs:19:13
    |
 LL |     let _ = x as &dyn Bar<u32>; // Error
    |             ^^^^^^^^^^^^^^^^^^ 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: `&dyn Foo<u32>` as `&dyn Bar<_>`
-  --> $DIR/type-checking-test-2.rs:22:13
+  --> $DIR/type-checking-test-2.rs:24:13
    |
 LL |     let a = x as &dyn Bar<_>; // Ambiguous
    |             ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.rs b/tests/ui/traits/trait-upcasting/type-checking-test-3.rs
index 3685569d98d..b2db3a12797 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-3.rs
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-3.rs
@@ -1,3 +1,5 @@
+#![feature(trait_upcasting)]
+
 trait Foo<'a>: Bar<'a> {}
 trait Bar<'a> {}
 
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr
index 640a6066268..e6cb6a75399 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-3.rs:9:13
+  --> $DIR/type-checking-test-3.rs:11:13
    |
 LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
    |                -- lifetime `'a` defined here
@@ -7,7 +7,7 @@ LL |     let _ = x as &dyn Bar<'a>; // Error
    |             ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-3.rs:14:13
+  --> $DIR/type-checking-test-3.rs:16:13
    |
 LL | fn test_wrong2<'a>(x: &dyn Foo<'a>) {
    |                -- lifetime `'a` defined here
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.rs b/tests/ui/traits/trait-upcasting/type-checking-test-4.rs
index 65391502386..f40c48f0d12 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-4.rs
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.rs
@@ -1,3 +1,5 @@
+#![feature(trait_upcasting)]
+
 trait Foo<'a>: Bar<'a, 'a> {}
 trait Bar<'a, 'b> {
     fn get_b(&self) -> Option<&'a u32> {
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
index 7e7548955d3..8d506e5807e 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:13:13
+  --> $DIR/type-checking-test-4.rs:15:13
    |
 LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
    |                -- lifetime `'a` defined here
@@ -7,7 +7,7 @@ LL |     let _ = x as &dyn Bar<'static, 'a>; // Error
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:18:13
+  --> $DIR/type-checking-test-4.rs:20:13
    |
 LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) {
    |                -- lifetime `'a` defined here
@@ -15,7 +15,7 @@ LL |     let _ = x as &dyn Bar<'a, 'static>; // Error
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:24:5
+  --> $DIR/type-checking-test-4.rs:26:5
    |
 LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
    |                -- lifetime `'a` defined here
@@ -24,7 +24,7 @@ LL |     y.get_b() // ERROR
    |     ^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:29:5
+  --> $DIR/type-checking-test-4.rs:31:5
    |
 LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
    |                -- lifetime `'a` defined here
@@ -32,7 +32,7 @@ LL |     <_ as Bar>::get_b(x) // ERROR
    |     ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:34:5
+  --> $DIR/type-checking-test-4.rs:36:5
    |
 LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
    |                -- lifetime `'a` defined here
@@ -40,7 +40,7 @@ LL |     <_ as Bar<'_, '_>>::get_b(x) // ERROR
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:42:5
+  --> $DIR/type-checking-test-4.rs:44:5
    |
 LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
    |                -- lifetime `'a` defined here
diff --git a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.current.stderr b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.current.stderr
new file mode 100644
index 00000000000..86de78f858c
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.current.stderr
@@ -0,0 +1,14 @@
+error[E0658]: cannot cast `dyn A` to `dyn B`, trait upcasting coercion is experimental
+  --> $DIR/upcast-through-struct-tail.rs:10:5
+   |
+LL |     x
+   |     ^
+   |
+   = note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
+   = help: add `#![feature(trait_upcasting)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = note: required when coercing `Box<Wrapper<(dyn A + 'a)>>` into `Box<Wrapper<(dyn B + 'a)>>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.next.stderr b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.next.stderr
new file mode 100644
index 00000000000..86de78f858c
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.next.stderr
@@ -0,0 +1,14 @@
+error[E0658]: cannot cast `dyn A` to `dyn B`, trait upcasting coercion is experimental
+  --> $DIR/upcast-through-struct-tail.rs:10:5
+   |
+LL |     x
+   |     ^
+   |
+   = note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
+   = help: add `#![feature(trait_upcasting)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = note: required when coercing `Box<Wrapper<(dyn A + 'a)>>` into `Box<Wrapper<(dyn B + 'a)>>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs
index f8cf793e4a4..948f058e528 100644
--- a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs
+++ b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs
@@ -1,4 +1,3 @@
-// check-pass
 // revisions: current next
 //[next] compile-flags: -Znext-solver
 
@@ -9,6 +8,7 @@ trait B {}
 
 fn test<'a>(x: Box<Wrapper<dyn A + 'a>>) -> Box<Wrapper<dyn B + 'a>> {
     x
+    //~^ ERROR cannot cast `dyn A` to `dyn B`, trait upcasting coercion is experimental
 }
 
 fn main() {}
diff --git a/tests/ui/traits/upcast_soundness_bug.rs b/tests/ui/traits/upcast_soundness_bug.rs
new file mode 100644
index 00000000000..32e32850925
--- /dev/null
+++ b/tests/ui/traits/upcast_soundness_bug.rs
@@ -0,0 +1,69 @@
+#![feature(trait_upcasting)]
+// known-bug: #120222
+// check-pass
+//! This will segfault at runtime.
+
+pub trait SupSupA {
+    fn method(&self) {}
+}
+pub trait SupSupB {}
+impl<T> SupSupA for T {}
+impl<T> SupSupB for T {}
+
+pub trait Super<T>: SupSupA + SupSupB {}
+
+pub trait Unimplemented {}
+
+pub trait Trait<T1, T2>: Super<T1> + Super<T2> {
+    fn missing_method(&self)
+    where
+        T1: Unimplemented,
+    {
+    }
+}
+
+impl<S, T> Super<T> for S {}
+
+impl<S, T1, T2> Trait<T1, T2> for S {}
+
+#[inline(never)]
+pub fn user1() -> &'static dyn Trait<u8, u8> {
+    &()
+    /* VTABLE:
+    .L__unnamed_2:
+            .quad   core::ptr::drop_in_place<()>
+            .asciz  "\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000"
+            .quad   example::SupSupA::method
+            .quad   .L__unnamed_4 // SupSupB vtable (pointer)
+            .zero   8             // null pointer for missing_method
+    */
+}
+
+#[inline(never)]
+pub fn user2() -> &'static dyn Trait<u8, u16> {
+    &()
+    /* VTABLE:
+    .L__unnamed_3:
+            .quad   core::ptr::drop_in_place<()>
+            .asciz  "\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000"
+            .quad   example::SupSupA::method
+            .quad   .L__unnamed_4 // SupSupB vtable (pointer)
+            .quad   .L__unnamed_5 // Super<u16> vtable (pointer)
+            .zero   8             // null pointer for missing_method
+    */
+}
+
+fn main() {
+    let p: *const dyn Trait<u8, u8> = &();
+    let p = p as *const dyn Trait<u8, u16>; // <- this is bad!
+    let p = p as *const dyn Super<u16>; // <- this upcast accesses improper vtable entry
+    // accessing from L__unnamed_2 the position for the 'Super<u16> vtable (pointer)',
+    // thus reading 'null pointer for missing_method'
+
+    let p = p as *const dyn SupSupB; // <- this upcast dereferences (null) pointer from that entry
+    // to read the SupSupB vtable (pointer)
+
+    // SEGFAULT
+
+    println!("{:?}", p);
+}