about summary refs log tree commit diff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/assembly/static-relocation-model.rs41
-rw-r--r--src/test/codegen/auxiliary/thread_local_aux.rs6
-rw-r--r--src/test/codegen/thread-local.rs50
-rw-r--r--src/test/codegen/try_identity.rs21
-rw-r--r--src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir70
-rw-r--r--src/test/mir-opt/simplify-arm.rs17
-rw-r--r--src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff140
-rw-r--r--src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff91
-rw-r--r--src/test/mir-opt/simplify_try.rs18
-rw-r--r--src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff93
-rw-r--r--src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff136
-rw-r--r--src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir75
-rw-r--r--src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir34
-rw-r--r--src/test/rustdoc-gui/escape-key.goml27
-rw-r--r--src/test/rustdoc/external-doc.rs1
-rw-r--r--src/test/ui/async-await/issue-61076.rs4
-rw-r--r--src/test/ui/async-await/issue-61076.stderr4
-rw-r--r--src/test/ui/async-await/try-on-option-in-async.stderr30
-rw-r--r--src/test/ui/attributes/key-value-expansion-on-mac.rs1
-rw-r--r--src/test/ui/attributes/key-value-expansion-on-mac.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.rs8
-rw-r--r--src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.stderr39
-rw-r--r--src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs4
-rw-r--r--src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr11
-rw-r--r--src/test/ui/inference/cannot-infer-async.rs4
-rw-r--r--src/test/ui/inference/cannot-infer-async.stderr9
-rw-r--r--src/test/ui/inference/cannot-infer-closure-circular.stderr2
-rw-r--r--src/test/ui/inference/cannot-infer-closure.rs4
-rw-r--r--src/test/ui/inference/cannot-infer-closure.stderr7
-rw-r--r--src/test/ui/inference/cannot-infer-partial-try-return.stderr3
-rw-r--r--src/test/ui/issues/issue-32709.stderr3
-rw-r--r--src/test/ui/option-to-result.stderr35
-rw-r--r--src/test/ui/proc-macro/auxiliary/api/cmp.rs21
-rw-r--r--src/test/ui/proc-macro/auxiliary/api/mod.rs24
-rw-r--r--src/test/ui/proc-macro/auxiliary/api/parse.rs23
-rw-r--r--src/test/ui/proc-macro/test.rs12
-rw-r--r--src/test/ui/question-mark-type-infer.stderr7
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr42
-rw-r--r--src/test/ui/suffixed-literal-meta.rs2
-rw-r--r--src/test/ui/suggestions/issue-72766.stderr2
-rw-r--r--src/test/ui/symbol-names/trait-objects.rs48
-rw-r--r--src/test/ui/symbol-names/trait-objects.v0.stderr56
-rw-r--r--src/test/ui/try-block/try-block-bad-type.rs5
-rw-r--r--src/test/ui/try-block/try-block-bad-type.stderr31
-rw-r--r--src/test/ui/try-block/try-block-in-while.rs2
-rw-r--r--src/test/ui/try-block/try-block-in-while.stderr7
-rw-r--r--src/test/ui/try-block/try-block-type-error.stderr4
-rw-r--r--src/test/ui/try-on-option.stderr33
-rw-r--r--src/test/ui/try-operator-custom.rs63
-rw-r--r--src/test/ui/try-trait/bad-interconversion.rs48
-rw-r--r--src/test/ui/try-trait/bad-interconversion.stderr115
-rw-r--r--src/test/ui/try-trait/option-to-result.rs (renamed from src/test/ui/option-to-result.rs)4
-rw-r--r--src/test/ui/try-trait/option-to-result.stderr31
-rw-r--r--src/test/ui/try-trait/try-as-monad.rs24
-rw-r--r--src/test/ui/try-trait/try-on-option-diagnostics.rs (renamed from src/test/ui/try-on-option-diagnostics.rs)0
-rw-r--r--src/test/ui/try-trait/try-on-option-diagnostics.stderr (renamed from src/test/ui/try-on-option-diagnostics.stderr)40
-rw-r--r--src/test/ui/try-trait/try-on-option.rs (renamed from src/test/ui/try-on-option.rs)2
-rw-r--r--src/test/ui/try-trait/try-on-option.stderr31
-rw-r--r--src/test/ui/try-trait/try-operator-custom.rs91
-rw-r--r--src/test/ui/try-trait/try-operator-on-main.rs (renamed from src/test/ui/try-operator-on-main.rs)7
-rw-r--r--src/test/ui/try-trait/try-operator-on-main.stderr (renamed from src/test/ui/try-operator-on-main.stderr)38
-rw-r--r--src/test/ui/try-trait/try-poll.rs (renamed from src/test/ui/try-poll.rs)0
62 files changed, 1138 insertions, 665 deletions
diff --git a/src/test/assembly/static-relocation-model.rs b/src/test/assembly/static-relocation-model.rs
index 0463045c156..ce2b3b1cfa4 100644
--- a/src/test/assembly/static-relocation-model.rs
+++ b/src/test/assembly/static-relocation-model.rs
@@ -1,8 +1,8 @@
 // min-llvm-version: 12.0.0
 // needs-llvm-components: aarch64 x86
-// revisions:X64 A64
+// revisions:x64 A64
 // assembly-output: emit-asm
-// [X64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=static
+// [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=static
 // [A64] compile-flags: --target aarch64-unknown-linux-gnu -Crelocation-model=static
 
 #![feature(no_core, lang_items)]
@@ -15,14 +15,26 @@ trait Sized {}
 #[lang="copy"]
 trait Copy {}
 
+#[lang="sync"]
+trait Sync {}
+
+#[lang = "drop_in_place"]
+fn drop_in_place<T>(_: *mut T) {}
+
 impl Copy for u8 {}
+impl Sync for u8 {}
+
+#[no_mangle]
+pub static PIERIS: u8 = 42;
 
 extern "C" {
+    static EXOCHORDA: *mut u8;
+
     fn chaenomeles();
 }
 
 // CHECK-LABEL: banana:
-// x64: movb    chaenomeles, %{{[a,z]+}}
+// x64: movb   chaenomeles{{(\(%[a-z0-9]+\))?}}, %{{[a-z0-9]+}}
 // A64:      adrp    [[REG:[a-z0-9]+]], chaenomeles
 // A64-NEXT: ldrb    {{[a-z0-9]+}}, {{\[}}[[REG]], :lo12:chaenomeles]
 #[no_mangle]
@@ -33,7 +45,7 @@ pub fn banana() -> u8 {
 }
 
 // CHECK-LABEL: peach:
-// x64: movb    banana, %{{[a,z]+}}
+// x64: movb    banana{{(\(%[a-z0-9]+\))?}}, %{{[a-z0-9]+}}
 // A64:      adrp    [[REG2:[a-z0-9]+]], banana
 // A64-NEXT: ldrb    {{[a-z0-9]+}}, {{\[}}[[REG2]], :lo12:banana]
 #[no_mangle]
@@ -42,3 +54,24 @@ pub fn peach() -> u8 {
         *(banana as *mut u8)
     }
 }
+
+// CHECK-LABEL: mango:
+// x64:      movq    EXOCHORDA{{(\(%[a-z0-9]+\))?}}, %[[REG:[a-z0-9]+]]
+// x64-NEXT: movb    (%[[REG]]), %{{[a-z0-9]+}}
+// A64:      adrp    [[REG2:[a-z0-9]+]], EXOCHORDA
+// A64-NEXT: ldr     {{[a-z0-9]+}}, {{\[}}[[REG2]], :lo12:EXOCHORDA]
+#[no_mangle]
+pub fn mango() -> u8 {
+    unsafe {
+        *EXOCHORDA
+    }
+}
+
+// CHECK-LABEL: orange:
+// x64: mov{{l|absq}}    $PIERIS, %{{[a-z0-9]+}}
+// A64:      adrp    [[REG2:[a-z0-9]+]], PIERIS
+// A64-NEXT: add     {{[a-z0-9]+}}, [[REG2]], :lo12:PIERIS
+#[no_mangle]
+pub fn orange() -> &'static u8 {
+    &PIERIS
+}
diff --git a/src/test/codegen/auxiliary/thread_local_aux.rs b/src/test/codegen/auxiliary/thread_local_aux.rs
new file mode 100644
index 00000000000..29b5e3ca244
--- /dev/null
+++ b/src/test/codegen/auxiliary/thread_local_aux.rs
@@ -0,0 +1,6 @@
+#![crate_type = "lib"]
+#![feature(thread_local_const_init)]
+
+use std::cell::Cell;
+
+thread_local!(pub static A: Cell<u64> = const { Cell::new(0) });
diff --git a/src/test/codegen/thread-local.rs b/src/test/codegen/thread-local.rs
new file mode 100644
index 00000000000..f14368e3990
--- /dev/null
+++ b/src/test/codegen/thread-local.rs
@@ -0,0 +1,50 @@
+// compile-flags: -O
+// aux-build:thread_local_aux.rs
+// ignore-windows FIXME(#84933)
+// ignore-wasm globals are used instead of thread locals
+// ignore-emscripten globals are used instead of thread locals
+// ignore-android does not use #[thread_local]
+
+#![crate_type = "lib"]
+#![feature(thread_local_const_init)]
+
+extern crate thread_local_aux as aux;
+
+use std::cell::Cell;
+
+thread_local!(static A: Cell<u32> = const { Cell::new(1) });
+
+// CHECK: [[TLS_AUX:@.+]] = external thread_local local_unnamed_addr global i64
+// CHECK: [[TLS:@.+]] = internal thread_local unnamed_addr global
+
+// CHECK-LABEL: @get
+#[no_mangle]
+fn get() -> u32 {
+    // CHECK: %0 = load i32, i32* bitcast ({{.*}} [[TLS]] to i32*)
+    // CHECK-NEXT: ret i32 %0
+    A.with(|a| a.get())
+}
+
+// CHECK-LABEL: @set
+#[no_mangle]
+fn set(v: u32) {
+    // CHECK: store i32 %0, i32* bitcast ({{.*}} [[TLS]] to i32*)
+    // CHECK-NEXT: ret void
+    A.with(|a| a.set(v))
+}
+
+// CHECK-LABEL: @get_aux
+#[no_mangle]
+fn get_aux() -> u64 {
+    // CHECK: %0 = load i64, i64* [[TLS_AUX]]
+    // CHECK-NEXT: ret i64 %0
+    aux::A.with(|a| a.get())
+}
+
+// CHECK-LABEL: @set_aux
+#[no_mangle]
+fn set_aux(v: u64) {
+    // CHECK: store i64 %0, i64* [[TLS_AUX]]
+    // CHECK-NEXT: ret void
+    aux::A.with(|a| a.set(v))
+}
diff --git a/src/test/codegen/try_identity.rs b/src/test/codegen/try_identity.rs
index 81e2435e5b8..3ff77163b9f 100644
--- a/src/test/codegen/try_identity.rs
+++ b/src/test/codegen/try_identity.rs
@@ -7,11 +7,28 @@
 
 type R = Result<u64, i32>;
 
+// This was written to the `?` from `try_trait`, but `try_trait_v2` uses a different structure,
+// so the relevant desugar is copied inline in order to keep the test testing the same thing.
+// FIXME(#85133): while this might be useful for `r#try!`, it would be nice to have a MIR
+// optimization that picks up the `?` desugaring, as `SimplifyArmIdentity` does not.
 #[no_mangle]
-fn try_identity(x: R) -> R {
+pub fn try_identity(x: R) -> R {
 // CHECK: start:
 // CHECK-NOT: br {{.*}}
 // CHECK ret void
-    let y = x?;
+    let y = match into_result(x) {
+        Err(e) => return from_error(From::from(e)),
+        Ok(v) => v,
+    };
     Ok(y)
 }
+
+#[inline]
+fn into_result<T, E>(r: Result<T, E>) -> Result<T, E> {
+    r
+}
+
+#[inline]
+fn from_error<T, E>(e: E) -> Result<T, E> {
+    Err(e)
+}
diff --git a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir
index c1421f20a0b..ba17a45f984 100644
--- a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir
+++ b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir
@@ -4,21 +4,20 @@ fn test() -> Option<Box<u32>> {
     let mut _0: std::option::Option<std::boxed::Box<u32>>; // return place in scope 0 at $DIR/issue-62289.rs:8:14: 8:30
     let mut _1: std::boxed::Box<u32>;    // in scope 0 at $DIR/issue-62289.rs:9:10: 9:21
     let mut _2: std::boxed::Box<u32>;    // in scope 0 at $DIR/issue-62289.rs:9:10: 9:21
-    let mut _3: std::result::Result<u32, std::option::NoneError>; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20
+    let mut _3: std::ops::ControlFlow<std::option::Option<std::convert::Infallible>, u32>; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20
     let mut _4: std::option::Option<u32>; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:19
     let mut _5: isize;                   // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
-    let _6: std::option::NoneError;      // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
+    let _6: std::option::Option<std::convert::Infallible>; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
     let mut _7: !;                       // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
-    let mut _8: std::option::NoneError;  // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
-    let mut _9: std::option::NoneError;  // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
-    let _10: u32;                        // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20
+    let mut _8: std::option::Option<std::convert::Infallible>; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
+    let _9: u32;                         // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20
     scope 1 {
-        debug err => _6;                 // in scope 1 at $DIR/issue-62289.rs:9:19: 9:20
+        debug residual => _6;            // in scope 1 at $DIR/issue-62289.rs:9:19: 9:20
         scope 2 {
         }
     }
     scope 3 {
-        debug val => _10;                // in scope 3 at $DIR/issue-62289.rs:9:15: 9:20
+        debug val => _9;                 // in scope 3 at $DIR/issue-62289.rs:9:15: 9:20
         scope 4 {
         }
     }
@@ -30,10 +29,10 @@ fn test() -> Option<Box<u32>> {
         StorageLive(_3);                 // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
         StorageLive(_4);                 // scope 0 at $DIR/issue-62289.rs:9:15: 9:19
         _4 = Option::<u32>::None;        // scope 0 at $DIR/issue-62289.rs:9:15: 9:19
-        _3 = <Option<u32> as Try>::into_result(move _4) -> [return: bb1, unwind: bb12]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
+        _3 = <Option<u32> as Try>::branch(move _4) -> [return: bb1, unwind: bb11]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
                                          // mir::Constant
                                          // + span: $DIR/issue-62289.rs:9:15: 9:20
-                                         // + literal: Const { ty: fn(std::option::Option<u32>) -> std::result::Result<<std::option::Option<u32> as std::ops::Try>::Ok, <std::option::Option<u32> as std::ops::Try>::Error> {<std::option::Option<u32> as std::ops::Try>::into_result}, val: Value(Scalar(<ZST>)) }
+                                         // + literal: Const { ty: fn(std::option::Option<u32>) -> std::ops::ControlFlow<<std::option::Option<u32> as std::ops::Try>::Residual, <std::option::Option<u32> as std::ops::Try>::Output> {<std::option::Option<u32> as std::ops::Try>::branch}, val: Value(Scalar(<ZST>)) }
     }
 
     bb1: {
@@ -43,12 +42,12 @@ fn test() -> Option<Box<u32>> {
     }
 
     bb2: {
-        StorageLive(_10);                // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
-        _10 = ((_3 as Ok).0: u32);       // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
-        (*_2) = _10;                     // scope 4 at $DIR/issue-62289.rs:9:15: 9:20
-        StorageDead(_10);                // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
+        StorageLive(_9);                 // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
+        _9 = ((_3 as Continue).0: u32);  // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
+        (*_2) = _9;                      // scope 4 at $DIR/issue-62289.rs:9:15: 9:20
+        StorageDead(_9);                 // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
         _1 = move _2;                    // scope 0 at $DIR/issue-62289.rs:9:10: 9:21
-        drop(_2) -> [return: bb7, unwind: bb11]; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
+        drop(_2) -> [return: bb6, unwind: bb10]; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
     }
 
     bb3: {
@@ -57,62 +56,53 @@ fn test() -> Option<Box<u32>> {
 
     bb4: {
         StorageLive(_6);                 // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
-        _6 = ((_3 as Err).0: std::option::NoneError); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
+        _6 = ((_3 as Break).0: std::option::Option<std::convert::Infallible>); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
         StorageLive(_8);                 // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
-        StorageLive(_9);                 // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
-        _9 = _6;                         // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
-        _8 = <NoneError as From<NoneError>>::from(move _9) -> [return: bb5, unwind: bb12]; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
+        _8 = _6;                         // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
+        _0 = <Option<Box<u32>> as FromResidual<Option<Infallible>>>::from_residual(move _8) -> [return: bb5, unwind: bb11]; // scope 2 at $DIR/issue-62289.rs:9:15: 9:20
                                          // mir::Constant
                                          // + span: $DIR/issue-62289.rs:9:19: 9:20
-                                         // + literal: Const { ty: fn(std::option::NoneError) -> std::option::NoneError {<std::option::NoneError as std::convert::From<std::option::NoneError>>::from}, val: Value(Scalar(<ZST>)) }
+                                         // + literal: Const { ty: fn(std::option::Option<std::convert::Infallible>) -> std::option::Option<std::boxed::Box<u32>> {<std::option::Option<std::boxed::Box<u32>> as std::ops::FromResidual<std::option::Option<std::convert::Infallible>>>::from_residual}, val: Value(Scalar(<ZST>)) }
     }
 
     bb5: {
-        StorageDead(_9);                 // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
-        _0 = <Option<Box<u32>> as Try>::from_error(move _8) -> [return: bb6, unwind: bb12]; // scope 2 at $DIR/issue-62289.rs:9:15: 9:20
-                                         // mir::Constant
-                                         // + span: $DIR/issue-62289.rs:9:15: 9:20
-                                         // + literal: Const { ty: fn(<std::option::Option<std::boxed::Box<u32>> as std::ops::Try>::Error) -> std::option::Option<std::boxed::Box<u32>> {<std::option::Option<std::boxed::Box<u32>> as std::ops::Try>::from_error}, val: Value(Scalar(<ZST>)) }
-    }
-
-    bb6: {
         StorageDead(_8);                 // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
         StorageDead(_6);                 // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
-        drop(_2) -> bb9;                 // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
+        drop(_2) -> bb8;                 // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
     }
 
-    bb7: {
+    bb6: {
         StorageDead(_2);                 // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
         _0 = Option::<Box<u32>>::Some(move _1); // scope 0 at $DIR/issue-62289.rs:9:5: 9:22
-        drop(_1) -> bb8;                 // scope 0 at $DIR/issue-62289.rs:9:21: 9:22
+        drop(_1) -> bb7;                 // scope 0 at $DIR/issue-62289.rs:9:21: 9:22
     }
 
-    bb8: {
+    bb7: {
         StorageDead(_1);                 // scope 0 at $DIR/issue-62289.rs:9:21: 9:22
         StorageDead(_3);                 // scope 0 at $DIR/issue-62289.rs:10:1: 10:2
-        goto -> bb10;                    // scope 0 at $DIR/issue-62289.rs:10:2: 10:2
+        goto -> bb9;                     // scope 0 at $DIR/issue-62289.rs:10:2: 10:2
     }
 
-    bb9: {
+    bb8: {
         StorageDead(_2);                 // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
         StorageDead(_1);                 // scope 0 at $DIR/issue-62289.rs:9:21: 9:22
         StorageDead(_3);                 // scope 0 at $DIR/issue-62289.rs:10:1: 10:2
-        goto -> bb10;                    // scope 0 at $DIR/issue-62289.rs:10:2: 10:2
+        goto -> bb9;                     // scope 0 at $DIR/issue-62289.rs:10:2: 10:2
     }
 
-    bb10: {
+    bb9: {
         return;                          // scope 0 at $DIR/issue-62289.rs:10:2: 10:2
     }
 
-    bb11 (cleanup): {
-        drop(_1) -> bb13;                // scope 0 at $DIR/issue-62289.rs:9:21: 9:22
+    bb10 (cleanup): {
+        drop(_1) -> bb12;                // scope 0 at $DIR/issue-62289.rs:9:21: 9:22
     }
 
-    bb12 (cleanup): {
-        drop(_2) -> bb13;                // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
+    bb11 (cleanup): {
+        drop(_2) -> bb12;                // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
     }
 
-    bb13 (cleanup): {
+    bb12 (cleanup): {
         resume;                          // scope 0 at $DIR/issue-62289.rs:8:1: 10:2
     }
 }
diff --git a/src/test/mir-opt/simplify-arm.rs b/src/test/mir-opt/simplify-arm.rs
index 50b5147e0cf..f7dcaa13449 100644
--- a/src/test/mir-opt/simplify-arm.rs
+++ b/src/test/mir-opt/simplify-arm.rs
@@ -20,8 +20,23 @@ fn id_result(r: Result<u8, i32>) -> Result<u8, i32> {
     }
 }
 
+fn into_result<T, E>(r: Result<T, E>) -> Result<T, E> {
+    r
+}
+
+fn from_error<T, E>(e: E) -> Result<T, E> {
+    Err(e)
+}
+
+// This was written to the `?` from `try_trait`, but `try_trait_v2` uses a different structure,
+// so the relevant desugar is copied inline in order to keep the test testing the same thing.
+// FIXME(#85133): while this might be useful for `r#try!`, it would be nice to have a MIR
+// optimization that picks up the `?` desugaring, as `SimplifyArmIdentity` does not.
 fn id_try(r: Result<u8, i32>) -> Result<u8, i32> {
-    let x = r?;
+    let x = match into_result(r) {
+        Err(e) => return from_error(From::from(e)),
+        Ok(v) => v,
+    };
     Ok(x)
 }
 
diff --git a/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff
index ccb3b71817f..a3bad4f0c62 100644
--- a/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff
@@ -2,101 +2,93 @@
 + // MIR for `id_try` after SimplifyArmIdentity
   
   fn id_try(_1: Result<u8, i32>) -> Result<u8, i32> {
-      debug r => _1;                       // in scope 0 at $DIR/simplify-arm.rs:23:11: 23:12
-      let mut _0: std::result::Result<u8, i32>; // return place in scope 0 at $DIR/simplify-arm.rs:23:34: 23:49
-      let _2: u8;                          // in scope 0 at $DIR/simplify-arm.rs:24:9: 24:10
-      let mut _3: std::result::Result<u8, i32>; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
-      let mut _4: std::result::Result<u8, i32>; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:14
-      let mut _5: isize;                   // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-      let _6: i32;                         // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-      let mut _7: !;                       // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-      let mut _8: i32;                     // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-      let mut _9: i32;                     // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-      let _10: u8;                         // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
-      let mut _11: u8;                     // in scope 0 at $DIR/simplify-arm.rs:25:8: 25:9
+      debug r => _1;                       // in scope 0 at $DIR/simplify-arm.rs:35:11: 35:12
+      let mut _0: std::result::Result<u8, i32>; // return place in scope 0 at $DIR/simplify-arm.rs:35:34: 35:49
+      let _2: u8;                          // in scope 0 at $DIR/simplify-arm.rs:36:9: 36:10
+      let mut _3: std::result::Result<u8, i32>; // in scope 0 at $DIR/simplify-arm.rs:36:19: 36:33
+      let mut _4: std::result::Result<u8, i32>; // in scope 0 at $DIR/simplify-arm.rs:36:31: 36:32
+      let mut _5: isize;                   // in scope 0 at $DIR/simplify-arm.rs:37:9: 37:15
+      let _6: i32;                         // in scope 0 at $DIR/simplify-arm.rs:37:13: 37:14
+      let mut _7: !;                       // in scope 0 at $DIR/simplify-arm.rs:37:19: 37:51
+      let mut _8: i32;                     // in scope 0 at $DIR/simplify-arm.rs:37:37: 37:50
+      let mut _9: i32;                     // in scope 0 at $DIR/simplify-arm.rs:37:48: 37:49
+      let _10: u8;                         // in scope 0 at $DIR/simplify-arm.rs:38:12: 38:13
+      let mut _11: u8;                     // in scope 0 at $DIR/simplify-arm.rs:40:8: 40:9
       scope 1 {
--         debug x => _2;                   // in scope 1 at $DIR/simplify-arm.rs:24:9: 24:10
-+         debug x => ((_0 as Ok).0: u8);   // in scope 1 at $DIR/simplify-arm.rs:24:9: 24:10
+-         debug x => _2;                   // in scope 1 at $DIR/simplify-arm.rs:36:9: 36:10
++         debug x => ((_0 as Ok).0: u8);   // in scope 1 at $DIR/simplify-arm.rs:36:9: 36:10
       }
       scope 2 {
--         debug err => _6;                 // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15
-+         debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15
-          scope 3 {
-              scope 7 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify-arm.rs:24:14: 24:15
--                 debug t => _9;           // in scope 7 at $DIR/simplify-arm.rs:24:14: 24:15
-+                 debug t => ((_0 as Err).0: i32); // in scope 7 at $DIR/simplify-arm.rs:24:14: 24:15
-              }
-              scope 8 (inlined <Result<u8, i32> as Try>::from_error) { // at $DIR/simplify-arm.rs:24:13: 24:15
--                 debug v => _8;           // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
-+                 debug v => ((_0 as Err).0: i32); // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
-                  let mut _12: i32;        // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
-              }
+-         debug e => _6;                   // in scope 2 at $DIR/simplify-arm.rs:37:13: 37:14
++         debug e => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:37:13: 37:14
+          scope 5 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify-arm.rs:37:37: 37:50
+-             debug t => _9;               // in scope 5 at $DIR/simplify-arm.rs:37:37: 37:50
++             debug t => ((_0 as Err).0: i32); // in scope 5 at $DIR/simplify-arm.rs:37:37: 37:50
           }
-      }
-      scope 4 {
--         debug val => _10;                // in scope 4 at $DIR/simplify-arm.rs:24:13: 24:15
-+         debug val => ((_0 as Ok).0: u8); // in scope 4 at $DIR/simplify-arm.rs:24:13: 24:15
-          scope 5 {
+          scope 6 (inlined from_error::<u8, i32>) { // at $DIR/simplify-arm.rs:37:26: 37:51
+-             debug e => _8;               // in scope 6 at $DIR/simplify-arm.rs:37:26: 37:51
++             debug e => ((_0 as Err).0: i32); // in scope 6 at $DIR/simplify-arm.rs:37:26: 37:51
           }
       }
-      scope 6 (inlined <Result<u8, i32> as Try>::into_result) { // at $DIR/simplify-arm.rs:24:13: 24:15
-          debug self => _4;                // in scope 6 at $DIR/simplify-arm.rs:24:13: 24:15
+      scope 3 {
+-         debug v => _10;                  // in scope 3 at $DIR/simplify-arm.rs:38:12: 38:13
++         debug v => ((_0 as Ok).0: u8);   // in scope 3 at $DIR/simplify-arm.rs:38:12: 38:13
+      }
+      scope 4 (inlined into_result::<u8, i32>) { // at $DIR/simplify-arm.rs:36:19: 36:33
+          debug r => _4;                   // in scope 4 at $DIR/simplify-arm.rs:36:19: 36:33
       }
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/simplify-arm.rs:24:9: 24:10
-          StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
-          StorageLive(_4);                 // scope 0 at $DIR/simplify-arm.rs:24:13: 24:14
-          _4 = _1;                         // scope 0 at $DIR/simplify-arm.rs:24:13: 24:14
-          _3 = move _4;                    // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15
-          StorageDead(_4);                 // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-          _5 = discriminant(_3);           // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-          switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
+          StorageLive(_2);                 // scope 0 at $DIR/simplify-arm.rs:36:9: 36:10
+          StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:36:19: 36:33
+          StorageLive(_4);                 // scope 0 at $DIR/simplify-arm.rs:36:31: 36:32
+          _4 = _1;                         // scope 0 at $DIR/simplify-arm.rs:36:31: 36:32
+          _3 = move _4;                    // scope 4 at $DIR/simplify-arm.rs:36:19: 36:33
+          StorageDead(_4);                 // scope 0 at $DIR/simplify-arm.rs:36:32: 36:33
+          _5 = discriminant(_3);           // scope 0 at $DIR/simplify-arm.rs:37:9: 37:15
+          switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:37:9: 37:15
       }
   
       bb1: {
--         StorageLive(_10);                // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
--         _10 = ((_3 as Ok).0: u8);        // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
--         _2 = _10;                        // scope 5 at $DIR/simplify-arm.rs:24:13: 24:15
--         StorageDead(_10);                // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-+         _0 = move _3;                    // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
-          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16
--         StorageLive(_11);                // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9
--         _11 = _2;                        // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9
--         ((_0 as Ok).0: u8) = move _11;   // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
--         discriminant(_0) = 0;            // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
--         StorageDead(_11);                // scope 1 at $DIR/simplify-arm.rs:25:9: 25:10
-          StorageDead(_2);                 // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2
-          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
+-         StorageLive(_10);                // scope 0 at $DIR/simplify-arm.rs:38:12: 38:13
+-         _10 = ((_3 as Ok).0: u8);        // scope 0 at $DIR/simplify-arm.rs:38:12: 38:13
+-         _2 = _10;                        // scope 3 at $DIR/simplify-arm.rs:38:18: 38:19
+-         StorageDead(_10);                // scope 0 at $DIR/simplify-arm.rs:38:18: 38:19
++         _0 = move _3;                    // scope 1 at $DIR/simplify-arm.rs:40:5: 40:10
+          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:39:6: 39:7
+-         StorageLive(_11);                // scope 1 at $DIR/simplify-arm.rs:40:8: 40:9
+-         _11 = _2;                        // scope 1 at $DIR/simplify-arm.rs:40:8: 40:9
+-         ((_0 as Ok).0: u8) = move _11;   // scope 1 at $DIR/simplify-arm.rs:40:5: 40:10
+-         discriminant(_0) = 0;            // scope 1 at $DIR/simplify-arm.rs:40:5: 40:10
+-         StorageDead(_11);                // scope 1 at $DIR/simplify-arm.rs:40:9: 40:10
+          StorageDead(_2);                 // scope 0 at $DIR/simplify-arm.rs:41:1: 41:2
+          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2
       }
   
       bb2: {
-          unreachable;                     // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
+          unreachable;                     // scope 0 at $DIR/simplify-arm.rs:36:19: 36:33
       }
   
       bb3: {
--         StorageLive(_6);                 // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
--         _6 = ((_3 as Err).0: i32);       // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
--         StorageLive(_8);                 // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
--         StorageLive(_9);                 // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
--         _9 = _6;                         // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
--         _8 = move _9;                    // scope 7 at $DIR/simplify-arm.rs:24:14: 24:15
--         StorageDead(_9);                 // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
--         StorageLive(_12);                // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
--         _12 = move _8;                   // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
--         ((_0 as Err).0: i32) = move _12; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
--         discriminant(_0) = 1;            // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
--         StorageDead(_12);                // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
--         StorageDead(_8);                 // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
--         StorageDead(_6);                 // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-+         _0 = move _3;                    // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
-          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16
-          StorageDead(_2);                 // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2
-          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
+-         StorageLive(_6);                 // scope 0 at $DIR/simplify-arm.rs:37:13: 37:14
+-         _6 = ((_3 as Err).0: i32);       // scope 0 at $DIR/simplify-arm.rs:37:13: 37:14
+-         StorageLive(_8);                 // scope 2 at $DIR/simplify-arm.rs:37:37: 37:50
+-         StorageLive(_9);                 // scope 2 at $DIR/simplify-arm.rs:37:48: 37:49
+-         _9 = _6;                         // scope 2 at $DIR/simplify-arm.rs:37:48: 37:49
+-         _8 = move _9;                    // scope 5 at $DIR/simplify-arm.rs:37:37: 37:50
+-         StorageDead(_9);                 // scope 2 at $DIR/simplify-arm.rs:37:49: 37:50
+-         ((_0 as Err).0: i32) = move _8;  // scope 6 at $DIR/simplify-arm.rs:37:26: 37:51
+-         discriminant(_0) = 1;            // scope 6 at $DIR/simplify-arm.rs:37:26: 37:51
+-         StorageDead(_8);                 // scope 2 at $DIR/simplify-arm.rs:37:50: 37:51
+-         StorageDead(_6);                 // scope 0 at $DIR/simplify-arm.rs:37:50: 37:51
++         _0 = move _3;                    // scope 6 at $DIR/simplify-arm.rs:37:26: 37:51
+          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:39:6: 39:7
+          StorageDead(_2);                 // scope 0 at $DIR/simplify-arm.rs:41:1: 41:2
+          goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2
       }
   
       bb4: {
-          return;                          // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
+          return;                          // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2
       }
   }
   
diff --git a/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff b/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff
index ec8ac30228e..b6b7511b3f5 100644
--- a/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff
+++ b/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff
@@ -2,75 +2,70 @@
 + // MIR for `id_try` after SimplifyBranchSame
   
   fn id_try(_1: Result<u8, i32>) -> Result<u8, i32> {
-      debug r => _1;                       // in scope 0 at $DIR/simplify-arm.rs:23:11: 23:12
-      let mut _0: std::result::Result<u8, i32>; // return place in scope 0 at $DIR/simplify-arm.rs:23:34: 23:49
-      let _2: u8;                          // in scope 0 at $DIR/simplify-arm.rs:24:9: 24:10
-      let mut _3: std::result::Result<u8, i32>; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
-      let mut _4: std::result::Result<u8, i32>; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:14
-      let mut _5: isize;                   // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-      let _6: i32;                         // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-      let mut _7: !;                       // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-      let mut _8: i32;                     // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-      let mut _9: i32;                     // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-      let _10: u8;                         // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
-      let mut _11: u8;                     // in scope 0 at $DIR/simplify-arm.rs:25:8: 25:9
+      debug r => _1;                       // in scope 0 at $DIR/simplify-arm.rs:35:11: 35:12
+      let mut _0: std::result::Result<u8, i32>; // return place in scope 0 at $DIR/simplify-arm.rs:35:34: 35:49
+      let _2: u8;                          // in scope 0 at $DIR/simplify-arm.rs:36:9: 36:10
+      let mut _3: std::result::Result<u8, i32>; // in scope 0 at $DIR/simplify-arm.rs:36:19: 36:33
+      let mut _4: std::result::Result<u8, i32>; // in scope 0 at $DIR/simplify-arm.rs:36:31: 36:32
+      let mut _5: isize;                   // in scope 0 at $DIR/simplify-arm.rs:37:9: 37:15
+      let _6: i32;                         // in scope 0 at $DIR/simplify-arm.rs:37:13: 37:14
+      let mut _7: !;                       // in scope 0 at $DIR/simplify-arm.rs:37:19: 37:51
+      let mut _8: i32;                     // in scope 0 at $DIR/simplify-arm.rs:37:37: 37:50
+      let mut _9: i32;                     // in scope 0 at $DIR/simplify-arm.rs:37:48: 37:49
+      let _10: u8;                         // in scope 0 at $DIR/simplify-arm.rs:38:12: 38:13
+      let mut _11: u8;                     // in scope 0 at $DIR/simplify-arm.rs:40:8: 40:9
       scope 1 {
-          debug x => ((_0 as Ok).0: u8);   // in scope 1 at $DIR/simplify-arm.rs:24:9: 24:10
+          debug x => ((_0 as Ok).0: u8);   // in scope 1 at $DIR/simplify-arm.rs:36:9: 36:10
       }
       scope 2 {
-          debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15
-          scope 3 {
-              scope 7 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify-arm.rs:24:14: 24:15
-                  debug t => ((_0 as Err).0: i32); // in scope 7 at $DIR/simplify-arm.rs:24:14: 24:15
-              }
-              scope 8 (inlined <Result<u8, i32> as Try>::from_error) { // at $DIR/simplify-arm.rs:24:13: 24:15
-                  debug v => ((_0 as Err).0: i32); // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
-                  let mut _12: i32;        // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
-              }
+          debug e => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:37:13: 37:14
+          scope 5 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify-arm.rs:37:37: 37:50
+              debug t => ((_0 as Err).0: i32); // in scope 5 at $DIR/simplify-arm.rs:37:37: 37:50
           }
-      }
-      scope 4 {
-          debug val => ((_0 as Ok).0: u8); // in scope 4 at $DIR/simplify-arm.rs:24:13: 24:15
-          scope 5 {
+          scope 6 (inlined from_error::<u8, i32>) { // at $DIR/simplify-arm.rs:37:26: 37:51
+              debug e => ((_0 as Err).0: i32); // in scope 6 at $DIR/simplify-arm.rs:37:26: 37:51
           }
       }
-      scope 6 (inlined <Result<u8, i32> as Try>::into_result) { // at $DIR/simplify-arm.rs:24:13: 24:15
-          debug self => _4;                // in scope 6 at $DIR/simplify-arm.rs:24:13: 24:15
+      scope 3 {
+          debug v => ((_0 as Ok).0: u8);   // in scope 3 at $DIR/simplify-arm.rs:38:12: 38:13
+      }
+      scope 4 (inlined into_result::<u8, i32>) { // at $DIR/simplify-arm.rs:36:19: 36:33
+          debug r => _4;                   // in scope 4 at $DIR/simplify-arm.rs:36:19: 36:33
       }
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/simplify-arm.rs:24:9: 24:10
-          StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
-          StorageLive(_4);                 // scope 0 at $DIR/simplify-arm.rs:24:13: 24:14
-          _4 = _1;                         // scope 0 at $DIR/simplify-arm.rs:24:13: 24:14
-          _3 = move _4;                    // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15
-          StorageDead(_4);                 // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-          _5 = discriminant(_3);           // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
--         switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
-+         goto -> bb1;                     // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
+          StorageLive(_2);                 // scope 0 at $DIR/simplify-arm.rs:36:9: 36:10
+          StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:36:19: 36:33
+          StorageLive(_4);                 // scope 0 at $DIR/simplify-arm.rs:36:31: 36:32
+          _4 = _1;                         // scope 0 at $DIR/simplify-arm.rs:36:31: 36:32
+          _3 = move _4;                    // scope 4 at $DIR/simplify-arm.rs:36:19: 36:33
+          StorageDead(_4);                 // scope 0 at $DIR/simplify-arm.rs:36:32: 36:33
+          _5 = discriminant(_3);           // scope 0 at $DIR/simplify-arm.rs:37:9: 37:15
+-         switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:37:9: 37:15
++         goto -> bb1;                     // scope 0 at $DIR/simplify-arm.rs:37:9: 37:15
       }
   
       bb1: {
-          _0 = move _3;                    // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
-          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16
-          StorageDead(_2);                 // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2
--         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
-+         goto -> bb2;                     // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
+          _0 = move _3;                    // scope 1 at $DIR/simplify-arm.rs:40:5: 40:10
+          StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:39:6: 39:7
+          StorageDead(_2);                 // scope 0 at $DIR/simplify-arm.rs:41:1: 41:2
+-         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2
++         goto -> bb2;                     // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2
       }
   
       bb2: {
--         unreachable;                     // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
+-         unreachable;                     // scope 0 at $DIR/simplify-arm.rs:36:19: 36:33
 -     }
 - 
 -     bb3: {
--         _0 = move _3;                    // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
--         StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16
--         StorageDead(_2);                 // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2
--         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
+-         _0 = move _3;                    // scope 6 at $DIR/simplify-arm.rs:37:26: 37:51
+-         StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:39:6: 39:7
+-         StorageDead(_2);                 // scope 0 at $DIR/simplify-arm.rs:41:1: 41:2
+-         goto -> bb4;                     // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2
 -     }
 - 
 -     bb4: {
-          return;                          // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
+          return;                          // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2
       }
   }
   
diff --git a/src/test/mir-opt/simplify_try.rs b/src/test/mir-opt/simplify_try.rs
index eb307de2074..15e351e7d50 100644
--- a/src/test/mir-opt/simplify_try.rs
+++ b/src/test/mir-opt/simplify_try.rs
@@ -4,8 +4,24 @@
 // EMIT_MIR simplify_try.try_identity.SimplifyLocals.after.mir
 // EMIT_MIR simplify_try.try_identity.DestinationPropagation.diff
 
+
+fn into_result<T, E>(r: Result<T, E>) -> Result<T, E> {
+    r
+}
+
+fn from_error<T, E>(e: E) -> Result<T, E> {
+    Err(e)
+}
+
+// This was written to the `?` from `try_trait`, but `try_trait_v2` uses a different structure,
+// so the relevant desugar is copied inline in order to keep the test testing the same thing.
+// FIXME(#85133): while this might be useful for `r#try!`, it would be nice to have a MIR
+// optimization that picks up the `?` desugaring, as `SimplifyArmIdentity` does not.
 fn try_identity(x: Result<u32, i32>) -> Result<u32, i32> {
-    let y = x?;
+    let y = match into_result(x) {
+        Err(e) => return from_error(From::from(e)),
+        Ok(v) => v,
+    };
     Ok(y)
 }
 
diff --git a/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff b/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff
index b1bae447f9c..e09b8cb39bd 100644
--- a/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff
+++ b/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff
@@ -2,67 +2,62 @@
 + // MIR for `try_identity` after DestinationPropagation
   
   fn try_identity(_1: Result<u32, i32>) -> Result<u32, i32> {
-      debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:7:17: 7:18
-      let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:7:41: 7:57
-      let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:8:9: 8:10
-      let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15
-      let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:14
-      let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-      let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-      let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-      let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-      let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-      let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15
-      let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:9:8: 9:9
+      debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:20:17: 20:18
+      let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:20:41: 20:57
+      let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:21:9: 21:10
+      let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:21:19: 21:33
+      let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:21:31: 21:32
+      let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:22:9: 22:15
+      let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:22:13: 22:14
+      let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:22:19: 22:51
+      let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:22:37: 22:50
+      let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:22:48: 22:49
+      let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:23:12: 23:13
+      let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:25:8: 25:9
       scope 1 {
-          debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:8:9: 8:10
+          debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:21:9: 21:10
       }
       scope 2 {
-          debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15
-          scope 3 {
-              scope 7 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify_try.rs:8:14: 8:15
-                  debug t => ((_0 as Err).0: i32); // in scope 7 at $DIR/simplify_try.rs:8:14: 8:15
-              }
-              scope 8 (inlined <Result<u32, i32> as Try>::from_error) { // at $DIR/simplify_try.rs:8:13: 8:15
-                  debug v => ((_0 as Err).0: i32); // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
-                  let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
-              }
+          debug e => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:22:13: 22:14
+          scope 5 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify_try.rs:22:37: 22:50
+              debug t => ((_0 as Err).0: i32); // in scope 5 at $DIR/simplify_try.rs:22:37: 22:50
           }
-      }
-      scope 4 {
-          debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:8:13: 8:15
-          scope 5 {
+          scope 6 (inlined from_error::<u32, i32>) { // at $DIR/simplify_try.rs:22:26: 22:51
+              debug e => ((_0 as Err).0: i32); // in scope 6 at $DIR/simplify_try.rs:22:26: 22:51
           }
       }
-      scope 6 (inlined <Result<u32, i32> as Try>::into_result) { // at $DIR/simplify_try.rs:8:13: 8:15
--         debug self => _4;                // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15
-+         debug self => _0;                // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15
+      scope 3 {
+          debug v => ((_0 as Ok).0: u32);  // in scope 3 at $DIR/simplify_try.rs:23:12: 23:13
+      }
+      scope 4 (inlined into_result::<u32, i32>) { // at $DIR/simplify_try.rs:21:19: 21:33
+-         debug r => _4;                   // in scope 4 at $DIR/simplify_try.rs:21:19: 21:33
++         debug r => _0;                   // in scope 4 at $DIR/simplify_try.rs:21:19: 21:33
       }
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:8:9: 8:10
--         StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:8:13: 8:15
--         StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:8:13: 8:14
--         _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:8:13: 8:14
--         _3 = move _4;                    // scope 6 at $DIR/simplify_try.rs:8:13: 8:15
--         StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
--         _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-+         nop;                             // scope 0 at $DIR/simplify_try.rs:8:13: 8:15
-+         nop;                             // scope 0 at $DIR/simplify_try.rs:8:13: 8:14
-+         _0 = _1;                         // scope 0 at $DIR/simplify_try.rs:8:13: 8:14
-+         nop;                             // scope 6 at $DIR/simplify_try.rs:8:13: 8:15
-+         nop;                             // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-+         _5 = discriminant(_0);           // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-          goto -> bb1;                     // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
+          StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:21:9: 21:10
+-         StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:21:19: 21:33
+-         StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
+-         _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
+-         _3 = move _4;                    // scope 4 at $DIR/simplify_try.rs:21:19: 21:33
+-         StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:21:32: 21:33
+-         _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
++         nop;                             // scope 0 at $DIR/simplify_try.rs:21:19: 21:33
++         nop;                             // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
++         _0 = _1;                         // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
++         nop;                             // scope 4 at $DIR/simplify_try.rs:21:19: 21:33
++         nop;                             // scope 0 at $DIR/simplify_try.rs:21:32: 21:33
++         _5 = discriminant(_0);           // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
+          goto -> bb1;                     // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
       }
   
       bb1: {
--         _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:9:5: 9:10
--         StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:8:15: 8:16
-+         nop;                             // scope 1 at $DIR/simplify_try.rs:9:5: 9:10
-+         nop;                             // scope 0 at $DIR/simplify_try.rs:8:15: 8:16
-          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:10:1: 10:2
-          return;                          // scope 0 at $DIR/simplify_try.rs:10:2: 10:2
+-         _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:25:5: 25:10
+-         StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:24:6: 24:7
++         nop;                             // scope 1 at $DIR/simplify_try.rs:25:5: 25:10
++         nop;                             // scope 0 at $DIR/simplify_try.rs:24:6: 24:7
+          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:26:1: 26:2
+          return;                          // scope 0 at $DIR/simplify_try.rs:26:2: 26:2
       }
   }
   
diff --git a/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff
index df274852f68..488ad33f80a 100644
--- a/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff
@@ -2,93 +2,85 @@
 + // MIR for `try_identity` after SimplifyArmIdentity
   
   fn try_identity(_1: Result<u32, i32>) -> Result<u32, i32> {
-      debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:7:17: 7:18
-      let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:7:41: 7:57
-      let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:8:9: 8:10
-      let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15
-      let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:14
-      let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-      let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-      let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-      let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-      let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-      let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15
-      let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:9:8: 9:9
+      debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:20:17: 20:18
+      let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:20:41: 20:57
+      let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:21:9: 21:10
+      let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:21:19: 21:33
+      let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:21:31: 21:32
+      let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:22:9: 22:15
+      let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:22:13: 22:14
+      let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:22:19: 22:51
+      let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:22:37: 22:50
+      let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:22:48: 22:49
+      let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:23:12: 23:13
+      let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:25:8: 25:9
       scope 1 {
--         debug y => _2;                   // in scope 1 at $DIR/simplify_try.rs:8:9: 8:10
-+         debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:8:9: 8:10
+-         debug y => _2;                   // in scope 1 at $DIR/simplify_try.rs:21:9: 21:10
++         debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:21:9: 21:10
       }
       scope 2 {
--         debug err => _6;                 // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15
-+         debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15
-          scope 3 {
-              scope 7 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify_try.rs:8:14: 8:15
--                 debug t => _9;           // in scope 7 at $DIR/simplify_try.rs:8:14: 8:15
-+                 debug t => ((_0 as Err).0: i32); // in scope 7 at $DIR/simplify_try.rs:8:14: 8:15
-              }
-              scope 8 (inlined <Result<u32, i32> as Try>::from_error) { // at $DIR/simplify_try.rs:8:13: 8:15
--                 debug v => _8;           // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
-+                 debug v => ((_0 as Err).0: i32); // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
-                  let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
-              }
+-         debug e => _6;                   // in scope 2 at $DIR/simplify_try.rs:22:13: 22:14
++         debug e => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:22:13: 22:14
+          scope 5 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify_try.rs:22:37: 22:50
+-             debug t => _9;               // in scope 5 at $DIR/simplify_try.rs:22:37: 22:50
++             debug t => ((_0 as Err).0: i32); // in scope 5 at $DIR/simplify_try.rs:22:37: 22:50
           }
-      }
-      scope 4 {
--         debug val => _10;                // in scope 4 at $DIR/simplify_try.rs:8:13: 8:15
-+         debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:8:13: 8:15
-          scope 5 {
+          scope 6 (inlined from_error::<u32, i32>) { // at $DIR/simplify_try.rs:22:26: 22:51
+-             debug e => _8;               // in scope 6 at $DIR/simplify_try.rs:22:26: 22:51
++             debug e => ((_0 as Err).0: i32); // in scope 6 at $DIR/simplify_try.rs:22:26: 22:51
           }
       }
-      scope 6 (inlined <Result<u32, i32> as Try>::into_result) { // at $DIR/simplify_try.rs:8:13: 8:15
-          debug self => _4;                // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15
+      scope 3 {
+-         debug v => _10;                  // in scope 3 at $DIR/simplify_try.rs:23:12: 23:13
++         debug v => ((_0 as Ok).0: u32);  // in scope 3 at $DIR/simplify_try.rs:23:12: 23:13
+      }
+      scope 4 (inlined into_result::<u32, i32>) { // at $DIR/simplify_try.rs:21:19: 21:33
+          debug r => _4;                   // in scope 4 at $DIR/simplify_try.rs:21:19: 21:33
       }
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:8:9: 8:10
-          StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:8:13: 8:15
-          StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:8:13: 8:14
-          _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:8:13: 8:14
-          _3 = move _4;                    // scope 6 at $DIR/simplify_try.rs:8:13: 8:15
-          StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-          _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-          switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
+          StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:21:9: 21:10
+          StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:21:19: 21:33
+          StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
+          _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
+          _3 = move _4;                    // scope 4 at $DIR/simplify_try.rs:21:19: 21:33
+          StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:21:32: 21:33
+          _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
+          switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
       }
   
       bb1: {
--         StorageLive(_10);                // scope 0 at $DIR/simplify_try.rs:8:13: 8:15
--         _10 = ((_3 as Ok).0: u32);       // scope 0 at $DIR/simplify_try.rs:8:13: 8:15
--         _2 = _10;                        // scope 5 at $DIR/simplify_try.rs:8:13: 8:15
--         StorageDead(_10);                // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-+         _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:9:5: 9:10
-          StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:8:15: 8:16
--         StorageLive(_11);                // scope 1 at $DIR/simplify_try.rs:9:8: 9:9
--         _11 = _2;                        // scope 1 at $DIR/simplify_try.rs:9:8: 9:9
--         ((_0 as Ok).0: u32) = move _11;  // scope 1 at $DIR/simplify_try.rs:9:5: 9:10
--         discriminant(_0) = 0;            // scope 1 at $DIR/simplify_try.rs:9:5: 9:10
--         StorageDead(_11);                // scope 1 at $DIR/simplify_try.rs:9:9: 9:10
-          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:10:1: 10:2
-          return;                          // scope 0 at $DIR/simplify_try.rs:10:2: 10:2
+-         StorageLive(_10);                // scope 0 at $DIR/simplify_try.rs:23:12: 23:13
+-         _10 = ((_3 as Ok).0: u32);       // scope 0 at $DIR/simplify_try.rs:23:12: 23:13
+-         _2 = _10;                        // scope 3 at $DIR/simplify_try.rs:23:18: 23:19
+-         StorageDead(_10);                // scope 0 at $DIR/simplify_try.rs:23:18: 23:19
++         _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:25:5: 25:10
+          StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:24:6: 24:7
+-         StorageLive(_11);                // scope 1 at $DIR/simplify_try.rs:25:8: 25:9
+-         _11 = _2;                        // scope 1 at $DIR/simplify_try.rs:25:8: 25:9
+-         ((_0 as Ok).0: u32) = move _11;  // scope 1 at $DIR/simplify_try.rs:25:5: 25:10
+-         discriminant(_0) = 0;            // scope 1 at $DIR/simplify_try.rs:25:5: 25:10
+-         StorageDead(_11);                // scope 1 at $DIR/simplify_try.rs:25:9: 25:10
+          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:26:1: 26:2
+          return;                          // scope 0 at $DIR/simplify_try.rs:26:2: 26:2
       }
   
       bb2: {
--         StorageLive(_6);                 // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
--         _6 = ((_3 as Err).0: i32);       // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
--         StorageLive(_8);                 // scope 3 at $DIR/simplify_try.rs:8:14: 8:15
--         StorageLive(_9);                 // scope 3 at $DIR/simplify_try.rs:8:14: 8:15
--         _9 = _6;                         // scope 3 at $DIR/simplify_try.rs:8:14: 8:15
--         _8 = move _9;                    // scope 7 at $DIR/simplify_try.rs:8:14: 8:15
--         StorageDead(_9);                 // scope 3 at $DIR/simplify_try.rs:8:14: 8:15
--         StorageLive(_12);                // scope 8 at $DIR/simplify_try.rs:8:13: 8:15
--         _12 = move _8;                   // scope 8 at $DIR/simplify_try.rs:8:13: 8:15
--         ((_0 as Err).0: i32) = move _12; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15
--         discriminant(_0) = 1;            // scope 8 at $DIR/simplify_try.rs:8:13: 8:15
--         StorageDead(_12);                // scope 8 at $DIR/simplify_try.rs:8:13: 8:15
--         StorageDead(_8);                 // scope 3 at $DIR/simplify_try.rs:8:14: 8:15
--         StorageDead(_6);                 // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-+         _0 = move _3;                    // scope 8 at $DIR/simplify_try.rs:8:13: 8:15
-          StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:8:15: 8:16
-          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:10:1: 10:2
-          return;                          // scope 0 at $DIR/simplify_try.rs:10:2: 10:2
+-         StorageLive(_6);                 // scope 0 at $DIR/simplify_try.rs:22:13: 22:14
+-         _6 = ((_3 as Err).0: i32);       // scope 0 at $DIR/simplify_try.rs:22:13: 22:14
+-         StorageLive(_8);                 // scope 2 at $DIR/simplify_try.rs:22:37: 22:50
+-         StorageLive(_9);                 // scope 2 at $DIR/simplify_try.rs:22:48: 22:49
+-         _9 = _6;                         // scope 2 at $DIR/simplify_try.rs:22:48: 22:49
+-         _8 = move _9;                    // scope 5 at $DIR/simplify_try.rs:22:37: 22:50
+-         StorageDead(_9);                 // scope 2 at $DIR/simplify_try.rs:22:49: 22:50
+-         ((_0 as Err).0: i32) = move _8;  // scope 6 at $DIR/simplify_try.rs:22:26: 22:51
+-         discriminant(_0) = 1;            // scope 6 at $DIR/simplify_try.rs:22:26: 22:51
+-         StorageDead(_8);                 // scope 2 at $DIR/simplify_try.rs:22:50: 22:51
+-         StorageDead(_6);                 // scope 0 at $DIR/simplify_try.rs:22:50: 22:51
++         _0 = move _3;                    // scope 6 at $DIR/simplify_try.rs:22:26: 22:51
+          StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:24:6: 24:7
+          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:26:1: 26:2
+          return;                          // scope 0 at $DIR/simplify_try.rs:26:2: 26:2
       }
   }
   
diff --git a/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir b/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir
index 37274691fb4..5d829f859e9 100644
--- a/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir
+++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir
@@ -1,57 +1,52 @@
 // MIR for `try_identity` after SimplifyBranchSame
 
 fn try_identity(_1: Result<u32, i32>) -> Result<u32, i32> {
-    debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:7:17: 7:18
-    let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:7:41: 7:57
-    let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:8:9: 8:10
-    let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15
-    let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:14
-    let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-    let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-    let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-    let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-    let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-    let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15
-    let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:9:8: 9:9
+    debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:20:17: 20:18
+    let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:20:41: 20:57
+    let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:21:9: 21:10
+    let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:21:19: 21:33
+    let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:21:31: 21:32
+    let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:22:9: 22:15
+    let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:22:13: 22:14
+    let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:22:19: 22:51
+    let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:22:37: 22:50
+    let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:22:48: 22:49
+    let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:23:12: 23:13
+    let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:25:8: 25:9
     scope 1 {
-        debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:8:9: 8:10
+        debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:21:9: 21:10
     }
     scope 2 {
-        debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15
-        scope 3 {
-            scope 7 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify_try.rs:8:14: 8:15
-                debug t => ((_0 as Err).0: i32); // in scope 7 at $DIR/simplify_try.rs:8:14: 8:15
-            }
-            scope 8 (inlined <Result<u32, i32> as Try>::from_error) { // at $DIR/simplify_try.rs:8:13: 8:15
-                debug v => ((_0 as Err).0: i32); // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
-                let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
-            }
+        debug e => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:22:13: 22:14
+        scope 5 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify_try.rs:22:37: 22:50
+            debug t => ((_0 as Err).0: i32); // in scope 5 at $DIR/simplify_try.rs:22:37: 22:50
         }
-    }
-    scope 4 {
-        debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:8:13: 8:15
-        scope 5 {
+        scope 6 (inlined from_error::<u32, i32>) { // at $DIR/simplify_try.rs:22:26: 22:51
+            debug e => ((_0 as Err).0: i32); // in scope 6 at $DIR/simplify_try.rs:22:26: 22:51
         }
     }
-    scope 6 (inlined <Result<u32, i32> as Try>::into_result) { // at $DIR/simplify_try.rs:8:13: 8:15
-        debug self => _4;                // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15
+    scope 3 {
+        debug v => ((_0 as Ok).0: u32);  // in scope 3 at $DIR/simplify_try.rs:23:12: 23:13
+    }
+    scope 4 (inlined into_result::<u32, i32>) { // at $DIR/simplify_try.rs:21:19: 21:33
+        debug r => _4;                   // in scope 4 at $DIR/simplify_try.rs:21:19: 21:33
     }
 
     bb0: {
-        StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:8:9: 8:10
-        StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:8:13: 8:15
-        StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:8:13: 8:14
-        _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:8:13: 8:14
-        _3 = move _4;                    // scope 6 at $DIR/simplify_try.rs:8:13: 8:15
-        StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-        _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
-        goto -> bb1;                     // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
+        StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:21:9: 21:10
+        StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:21:19: 21:33
+        StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
+        _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
+        _3 = move _4;                    // scope 4 at $DIR/simplify_try.rs:21:19: 21:33
+        StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:21:32: 21:33
+        _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
+        goto -> bb1;                     // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
     }
 
     bb1: {
-        _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:9:5: 9:10
-        StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:8:15: 8:16
-        StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:10:1: 10:2
-        return;                          // scope 0 at $DIR/simplify_try.rs:10:2: 10:2
+        _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:25:5: 25:10
+        StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:24:6: 24:7
+        StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:26:1: 26:2
+        return;                          // scope 0 at $DIR/simplify_try.rs:26:2: 26:2
     }
 }
diff --git a/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir b/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir
index f8adcced4b3..1b5232422b6 100644
--- a/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir
+++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir
@@ -1,33 +1,29 @@
 // MIR for `try_identity` after SimplifyLocals
 
 fn try_identity(_1: Result<u32, i32>) -> Result<u32, i32> {
-    debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:7:17: 7:18
-    let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:7:41: 7:57
+    debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:20:17: 20:18
+    let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:20:41: 20:57
     scope 1 {
-        debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:8:9: 8:10
+        debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:21:9: 21:10
     }
     scope 2 {
-        debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15
-        scope 3 {
-            scope 7 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify_try.rs:8:14: 8:15
-                debug t => ((_0 as Err).0: i32); // in scope 7 at $DIR/simplify_try.rs:8:14: 8:15
-            }
-            scope 8 (inlined <Result<u32, i32> as Try>::from_error) { // at $DIR/simplify_try.rs:8:13: 8:15
-                debug v => ((_0 as Err).0: i32); // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
-            }
+        debug e => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:22:13: 22:14
+        scope 5 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify_try.rs:22:37: 22:50
+            debug t => ((_0 as Err).0: i32); // in scope 5 at $DIR/simplify_try.rs:22:37: 22:50
         }
-    }
-    scope 4 {
-        debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:8:13: 8:15
-        scope 5 {
+        scope 6 (inlined from_error::<u32, i32>) { // at $DIR/simplify_try.rs:22:26: 22:51
+            debug e => ((_0 as Err).0: i32); // in scope 6 at $DIR/simplify_try.rs:22:26: 22:51
         }
     }
-    scope 6 (inlined <Result<u32, i32> as Try>::into_result) { // at $DIR/simplify_try.rs:8:13: 8:15
-        debug self => _0;                // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15
+    scope 3 {
+        debug v => ((_0 as Ok).0: u32);  // in scope 3 at $DIR/simplify_try.rs:23:12: 23:13
+    }
+    scope 4 (inlined into_result::<u32, i32>) { // at $DIR/simplify_try.rs:21:19: 21:33
+        debug r => _0;                   // in scope 4 at $DIR/simplify_try.rs:21:19: 21:33
     }
 
     bb0: {
-        _0 = _1;                         // scope 0 at $DIR/simplify_try.rs:8:13: 8:14
-        return;                          // scope 0 at $DIR/simplify_try.rs:10:2: 10:2
+        _0 = _1;                         // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
+        return;                          // scope 0 at $DIR/simplify_try.rs:26:2: 26:2
     }
 }
diff --git a/src/test/rustdoc-gui/escape-key.goml b/src/test/rustdoc-gui/escape-key.goml
new file mode 100644
index 00000000000..303dd000ba3
--- /dev/null
+++ b/src/test/rustdoc-gui/escape-key.goml
@@ -0,0 +1,27 @@
+goto: file://|DOC_PATH|/test_docs/index.html
+// First, we check that the search results are hidden when the Escape key is pressed.
+write: (".search-input", "test")
+wait-for: "#search > h1" // The search element is empty before the first search 
+assert: ("#search", "class", "content")
+assert: ("#main", "class", "content hidden")
+press-key: "Escape"
+assert: ("#search", "class", "content hidden")
+assert: ("#main", "class", "content")
+
+// Check that focusing the search input brings back the search results
+focus: ".search-input"
+assert: ("#search", "class", "content")
+assert: ("#main", "class", "content hidden")
+
+// Now let's check that when the help popup is displayed and we press Escape, it doesn't
+// hide the search results too.
+click: "#help-button"
+assert: ("#help", "class", "")
+press-key: "Escape"
+assert: ("#help", "class", "hidden")
+assert: ("#search", "class", "content")
+assert: ("#main", "class", "content hidden")
+
+// FIXME: Once https://github.com/rust-lang/rust/pull/84462 is merged, add check to ensure
+// that Escape hides the search results when a result is focused.
+// press-key: "ArrowDown"
diff --git a/src/test/rustdoc/external-doc.rs b/src/test/rustdoc/external-doc.rs
index befd31a5492..0dadca551a9 100644
--- a/src/test/rustdoc/external-doc.rs
+++ b/src/test/rustdoc/external-doc.rs
@@ -1,5 +1,4 @@
 #![feature(external_doc)]
-#![feature(extended_key_value_attributes)]
 
 // @has external_doc/struct.CanHasDocs.html
 // @has - '//h1' 'External Docs'
diff --git a/src/test/ui/async-await/issue-61076.rs b/src/test/ui/async-await/issue-61076.rs
index 4a8e841b33d..9fe3313ee6c 100644
--- a/src/test/ui/async-await/issue-61076.rs
+++ b/src/test/ui/async-await/issue-61076.rs
@@ -42,7 +42,7 @@ async fn bar() -> Result<(), ()> {
     foo()?; //~ ERROR the `?` operator can only be applied to values that implement `Try`
     //~^ NOTE the `?` operator cannot be applied to type `impl Future`
     //~| HELP the trait `Try` is not implemented for `impl Future`
-    //~| NOTE required by `into_result`
+    //~| NOTE required by `branch`
     //~| HELP consider `await`ing on the `Future`
     //~| NOTE in this expansion of desugaring of operator `?`
     //~| NOTE in this expansion of desugaring of operator `?`
@@ -65,7 +65,7 @@ async fn baz() -> Result<(), ()> {
     t?; //~ ERROR the `?` operator can only be applied to values that implement `Try`
     //~^ NOTE the `?` operator cannot be applied to type `T`
     //~| HELP the trait `Try` is not implemented for `T`
-    //~| NOTE required by `into_result`
+    //~| NOTE required by `branch`
     //~| HELP consider `await`ing on the `Future`
     //~| NOTE in this expansion of desugaring of operator `?`
     //~| NOTE in this expansion of desugaring of operator `?`
diff --git a/src/test/ui/async-await/issue-61076.stderr b/src/test/ui/async-await/issue-61076.stderr
index fd00522fac7..ad661fb2833 100644
--- a/src/test/ui/async-await/issue-61076.stderr
+++ b/src/test/ui/async-await/issue-61076.stderr
@@ -5,7 +5,7 @@ LL |     foo()?;
    |     ^^^^^^ the `?` operator cannot be applied to type `impl Future`
    |
    = help: the trait `Try` is not implemented for `impl Future`
-   = note: required by `into_result`
+   = note: required by `branch`
 help: consider `await`ing on the `Future`
    |
 LL |     foo().await?;
@@ -18,7 +18,7 @@ LL |     t?;
    |     ^^ the `?` operator cannot be applied to type `T`
    |
    = help: the trait `Try` is not implemented for `T`
-   = note: required by `into_result`
+   = note: required by `branch`
 help: consider `await`ing on the `Future`
    |
 LL |     t.await?;
diff --git a/src/test/ui/async-await/try-on-option-in-async.stderr b/src/test/ui/async-await/try-on-option-in-async.stderr
index 8e7823f3571..a3f122a4663 100644
--- a/src/test/ui/async-await/try-on-option-in-async.stderr
+++ b/src/test/ui/async-await/try-on-option-in-async.stderr
@@ -1,47 +1,47 @@
-error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `Try`)
-  --> $DIR/try-on-option-in-async.rs:8:9
+error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/try-on-option-in-async.rs:8:10
    |
 LL |       async {
    |  ___________-
 LL | |         let x: Option<u32> = None;
 LL | |         x?;
-   | |         ^^ cannot use the `?` operator in an async block that returns `{integer}`
+   | |          ^ cannot use the `?` operator in an async block that returns `{integer}`
 LL | |         22
 LL | |     }
    | |_____- this function should return `Result` or `Option` to accept `?`
    |
-   = help: the trait `Try` is not implemented for `{integer}`
-   = note: required by `from_error`
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `{integer}`
+   = note: required by `from_residual`
 
-error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `Try`)
-  --> $DIR/try-on-option-in-async.rs:17:9
+error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/try-on-option-in-async.rs:17:10
    |
 LL |       let async_closure = async || {
    |  __________________________________-
 LL | |         let x: Option<u32> = None;
 LL | |         x?;
-   | |         ^^ cannot use the `?` operator in an async closure that returns `u32`
+   | |          ^ cannot use the `?` operator in an async closure that returns `u32`
 LL | |         22_u32
 LL | |     };
    | |_____- this function should return `Result` or `Option` to accept `?`
    |
-   = help: the trait `Try` is not implemented for `u32`
-   = note: required by `from_error`
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
+   = note: required by `from_residual`
 
-error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `Try`)
-  --> $DIR/try-on-option-in-async.rs:26:5
+error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/try-on-option-in-async.rs:26:6
    |
 LL |   async fn an_async_function() -> u32 {
    |  _____________________________________-
 LL | |     let x: Option<u32> = None;
 LL | |     x?;
-   | |     ^^ cannot use the `?` operator in an async function that returns `u32`
+   | |      ^ cannot use the `?` operator in an async function that returns `u32`
 LL | |     22
 LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
-   = help: the trait `Try` is not implemented for `u32`
-   = note: required by `from_error`
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
+   = note: required by `from_residual`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/attributes/key-value-expansion-on-mac.rs b/src/test/ui/attributes/key-value-expansion-on-mac.rs
index 1247ff2b230..95bc1c04961 100644
--- a/src/test/ui/attributes/key-value-expansion-on-mac.rs
+++ b/src/test/ui/attributes/key-value-expansion-on-mac.rs
@@ -1,4 +1,3 @@
-#![feature(extended_key_value_attributes)]
 #![feature(rustc_attrs)]
 
 #[rustc_dummy = stringify!(a)] // OK
diff --git a/src/test/ui/attributes/key-value-expansion-on-mac.stderr b/src/test/ui/attributes/key-value-expansion-on-mac.stderr
index b74f3518a7e..fa9ea543765 100644
--- a/src/test/ui/attributes/key-value-expansion-on-mac.stderr
+++ b/src/test/ui/attributes/key-value-expansion-on-mac.stderr
@@ -1,5 +1,5 @@
 error: unexpected token: `stringify!(b)`
-  --> $DIR/key-value-expansion-on-mac.rs:12:17
+  --> $DIR/key-value-expansion-on-mac.rs:11:17
    |
 LL | #[rustc_dummy = stringify!(b)]
    |                 ^^^^^^^^^^^^^
diff --git a/src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.rs b/src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.rs
deleted file mode 100644
index f19fdb45f1f..00000000000
--- a/src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-#[cfg(FALSE)]
-#[attr = multi::segment::path] //~ ERROR arbitrary expressions in key-value attributes are unstable
-#[attr = macro_call!()] //~ ERROR arbitrary expressions in key-value attributes are unstable
-#[attr = 1 + 2] //~ ERROR arbitrary expressions in key-value attributes are unstable
-#[attr = what?] //~ ERROR arbitrary expressions in key-value attributes are unstable
-struct S;
-
-fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.stderr b/src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.stderr
deleted file mode 100644
index 9887814b907..00000000000
--- a/src/test/ui/feature-gates/feature-gate-extended_key_value_attributes.stderr
+++ /dev/null
@@ -1,39 +0,0 @@
-error[E0658]: arbitrary expressions in key-value attributes are unstable
-  --> $DIR/feature-gate-extended_key_value_attributes.rs:2:10
-   |
-LL | #[attr = multi::segment::path]
-   |          ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #78835 <https://github.com/rust-lang/rust/issues/78835> for more information
-   = help: add `#![feature(extended_key_value_attributes)]` to the crate attributes to enable
-
-error[E0658]: arbitrary expressions in key-value attributes are unstable
-  --> $DIR/feature-gate-extended_key_value_attributes.rs:3:10
-   |
-LL | #[attr = macro_call!()]
-   |          ^^^^^^^^^^^^^
-   |
-   = note: see issue #78835 <https://github.com/rust-lang/rust/issues/78835> for more information
-   = help: add `#![feature(extended_key_value_attributes)]` to the crate attributes to enable
-
-error[E0658]: arbitrary expressions in key-value attributes are unstable
-  --> $DIR/feature-gate-extended_key_value_attributes.rs:4:10
-   |
-LL | #[attr = 1 + 2]
-   |          ^^^^^
-   |
-   = note: see issue #78835 <https://github.com/rust-lang/rust/issues/78835> for more information
-   = help: add `#![feature(extended_key_value_attributes)]` to the crate attributes to enable
-
-error[E0658]: arbitrary expressions in key-value attributes are unstable
-  --> $DIR/feature-gate-extended_key_value_attributes.rs:5:10
-   |
-LL | #[attr = what?]
-   |          ^^^^^
-   |
-   = note: see issue #78835 <https://github.com/rust-lang/rust/issues/78835> for more information
-   = help: add `#![feature(extended_key_value_attributes)]` to the crate attributes to enable
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs
index 2e96022318b..7beb2db3969 100644
--- a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs
+++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs
@@ -10,8 +10,8 @@ fn make_unit() -> Result<(), Error> {
 
 fn main() {
     let fut = async {
-        make_unit()?; //~ ERROR type annotations needed
+        make_unit()?;
 
-        Ok(())
+        Ok(()) //~ ERROR type annotations needed
     };
 }
diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr
index 2875cef6801..8e632fbc1de 100644
--- a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr
+++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr
@@ -8,14 +8,13 @@ LL | #![feature(impl_trait_in_bindings)]
    = note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
 
 error[E0282]: type annotations needed for `impl Future`
-  --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:13:20
+  --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:15:9
    |
 LL |     let fut = async {
-   |         --- consider giving `fut` the explicit type `impl Future`, with the type parameters specified
-LL |         make_unit()?;
-   |                    ^ cannot infer type of error for `?` operator
-   |
-   = note: `?` implicitly converts the error value into a type implementing `From<std::io::Error>`
+   |         --- consider giving `fut` the explicit type `impl Future`, where the type parameter `E` is specified
+...
+LL |         Ok(())
+   |         ^^ cannot infer type for type parameter `E` declared on the enum `Result`
 
 error: aborting due to previous error; 1 warning emitted
 
diff --git a/src/test/ui/inference/cannot-infer-async.rs b/src/test/ui/inference/cannot-infer-async.rs
index 05f62f3d8cb..e7fabd0ffbc 100644
--- a/src/test/ui/inference/cannot-infer-async.rs
+++ b/src/test/ui/inference/cannot-infer-async.rs
@@ -8,8 +8,8 @@ fn make_unit() -> Result<(), Error> {
 
 fn main() {
     let fut = async {
-        make_unit()?; //~ ERROR type annotations needed
+        make_unit()?;
 
-        Ok(())
+        Ok(()) //~ ERROR type annotations needed
     };
 }
diff --git a/src/test/ui/inference/cannot-infer-async.stderr b/src/test/ui/inference/cannot-infer-async.stderr
index 282bc13e9e7..23360483361 100644
--- a/src/test/ui/inference/cannot-infer-async.stderr
+++ b/src/test/ui/inference/cannot-infer-async.stderr
@@ -1,12 +1,11 @@
 error[E0282]: type annotations needed
-  --> $DIR/cannot-infer-async.rs:11:20
+  --> $DIR/cannot-infer-async.rs:13:9
    |
 LL |     let fut = async {
    |         --- consider giving `fut` a type
-LL |         make_unit()?;
-   |                    ^ cannot infer type of error for `?` operator
-   |
-   = note: `?` implicitly converts the error value into a type implementing `From<std::io::Error>`
+...
+LL |         Ok(())
+   |         ^^ cannot infer type for type parameter `E` declared on the enum `Result`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/inference/cannot-infer-closure-circular.stderr b/src/test/ui/inference/cannot-infer-closure-circular.stderr
index 211ae13e46d..a6ddb7ae908 100644
--- a/src/test/ui/inference/cannot-infer-closure-circular.stderr
+++ b/src/test/ui/inference/cannot-infer-closure-circular.stderr
@@ -2,7 +2,7 @@ error[E0282]: type annotations needed for `Result<(), E>`
   --> $DIR/cannot-infer-closure-circular.rs:7:14
    |
 LL |     let x = |r| {
-   |              ^ consider giving this closure parameter the explicit type `Result<(), E>`, with the type parameters specified
+   |              ^ consider giving this closure parameter the explicit type `Result<(), E>`, where the type parameter `E` is specified
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/inference/cannot-infer-closure.rs b/src/test/ui/inference/cannot-infer-closure.rs
index 8f48483c254..6e84b6d5ad0 100644
--- a/src/test/ui/inference/cannot-infer-closure.rs
+++ b/src/test/ui/inference/cannot-infer-closure.rs
@@ -1,6 +1,6 @@
 fn main() {
     let x = |a: (), b: ()| {
-        Err(a)?; //~ ERROR type annotations needed for the closure
-        Ok(b)
+        Err(a)?;
+        Ok(b) //~ ERROR type annotations needed for the closure
     };
 }
diff --git a/src/test/ui/inference/cannot-infer-closure.stderr b/src/test/ui/inference/cannot-infer-closure.stderr
index 0dcce9e990b..e055d1a94ff 100644
--- a/src/test/ui/inference/cannot-infer-closure.stderr
+++ b/src/test/ui/inference/cannot-infer-closure.stderr
@@ -1,10 +1,9 @@
 error[E0282]: type annotations needed for the closure `fn((), ()) -> Result<(), _>`
-  --> $DIR/cannot-infer-closure.rs:3:15
+  --> $DIR/cannot-infer-closure.rs:4:9
    |
-LL |         Err(a)?;
-   |               ^ cannot infer type of error for `?` operator
+LL |         Ok(b)
+   |         ^^ cannot infer type for type parameter `E` declared on the enum `Result`
    |
-   = note: `?` implicitly converts the error value into a type implementing `From<()>`
 help: give this closure an explicit return type without `_` placeholders
    |
 LL |     let x = |a: (), b: ()| -> Result<(), _> {
diff --git a/src/test/ui/inference/cannot-infer-partial-try-return.stderr b/src/test/ui/inference/cannot-infer-partial-try-return.stderr
index 86e2126e1ae..c394f6efbda 100644
--- a/src/test/ui/inference/cannot-infer-partial-try-return.stderr
+++ b/src/test/ui/inference/cannot-infer-partial-try-return.stderr
@@ -2,9 +2,8 @@ error[E0282]: type annotations needed for the closure `fn() -> Result<(), Qualif
   --> $DIR/cannot-infer-partial-try-return.rs:19:9
    |
 LL |         infallible()?;
-   |         ^^^^^^^^^^^^^ cannot infer type of error for `?` operator
+   |         ^^^^^^^^^^^^^ cannot infer type
    |
-   = note: `?` implicitly converts the error value into `QualifiedError<_>` using its implementation of `From<Infallible>`
 help: give this closure an explicit return type without `_` placeholders
    |
 LL |     let x = || -> Result<(), QualifiedError<_>> {
diff --git a/src/test/ui/issues/issue-32709.stderr b/src/test/ui/issues/issue-32709.stderr
index cc12c153621..2d020188198 100644
--- a/src/test/ui/issues/issue-32709.stderr
+++ b/src/test/ui/issues/issue-32709.stderr
@@ -7,7 +7,8 @@ LL |     Err(5)?;
    |           ^ the trait `From<{integer}>` is not implemented for `()`
    |
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
-   = note: required by `from`
+   = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, {integer}>>` for `Result<i32, ()>`
+   = note: required by `from_residual`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/option-to-result.stderr b/src/test/ui/option-to-result.stderr
deleted file mode 100644
index 551b9f4650a..00000000000
--- a/src/test/ui/option-to-result.stderr
+++ /dev/null
@@ -1,35 +0,0 @@
-error[E0277]: `?` couldn't convert the error to `()`
-  --> $DIR/option-to-result.rs:5:6
-   |
-LL | fn test_result() -> Result<(),()> {
-   |                     ------------- expected `()` because of this
-LL |     let a:Option<()> = Some(());
-LL |     a?;
-   |      ^ the trait `From<NoneError>` is not implemented for `()`
-   |
-   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
-   = note: required by `from`
-help: consider converting the `Option<T>` into a `Result<T, _>` using `Option::ok_or` or `Option::ok_or_else`
-   |
-LL |     a.ok_or_else(|| /* error value */)?;
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: `?` couldn't convert the error to `NoneError`
-  --> $DIR/option-to-result.rs:11:6
-   |
-LL | fn test_option() -> Option<i32>{
-   |                     ----------- expected `NoneError` because of this
-LL |     let a:Result<i32, i32> = Ok(5);
-LL |     a?;
-   |      ^ the trait `From<i32>` is not implemented for `NoneError`
-   |
-   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
-   = note: required by `from`
-help: consider converting the `Result<T, _>` into an `Option<T>` using `Result::ok`
-   |
-LL |     a.ok()?;
-   |      ^^^^^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/proc-macro/auxiliary/api/cmp.rs b/src/test/ui/proc-macro/auxiliary/api/cmp.rs
new file mode 100644
index 00000000000..5784a6e5d94
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/api/cmp.rs
@@ -0,0 +1,21 @@
+use proc_macro::{LineColumn, Punct, Spacing};
+
+pub fn test() {
+    test_line_column_ord();
+    test_punct_eq();
+}
+
+fn test_line_column_ord() {
+    let line0_column0 = LineColumn { line: 0, column: 0 };
+    let line0_column1 = LineColumn { line: 0, column: 1 };
+    let line1_column0 = LineColumn { line: 1, column: 0 };
+    assert!(line0_column0 < line0_column1);
+    assert!(line0_column1 < line1_column0);
+}
+
+fn test_punct_eq() {
+    let colon_alone = Punct::new(':', Spacing::Alone);
+    assert_eq!(colon_alone, ':');
+    let colon_joint = Punct::new(':', Spacing::Joint);
+    assert_eq!(colon_joint, ':');
+}
diff --git a/src/test/ui/proc-macro/auxiliary/api/mod.rs b/src/test/ui/proc-macro/auxiliary/api/mod.rs
new file mode 100644
index 00000000000..739c25132e7
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/api/mod.rs
@@ -0,0 +1,24 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![crate_name = "proc_macro_api_tests"]
+#![feature(proc_macro_span)]
+#![deny(dead_code)] // catch if a test function is never called
+
+extern crate proc_macro;
+
+mod cmp;
+mod parse;
+
+use proc_macro::TokenStream;
+
+#[proc_macro]
+pub fn run(input: TokenStream) -> TokenStream {
+    assert!(input.is_empty());
+
+    cmp::test();
+    parse::test();
+
+    TokenStream::new()
+}
diff --git a/src/test/ui/proc-macro/auxiliary/api/parse.rs b/src/test/ui/proc-macro/auxiliary/api/parse.rs
new file mode 100644
index 00000000000..4105236b7f2
--- /dev/null
+++ b/src/test/ui/proc-macro/auxiliary/api/parse.rs
@@ -0,0 +1,23 @@
+use proc_macro::Literal;
+
+pub fn test() {
+    test_parse_literal();
+}
+
+fn test_parse_literal() {
+    assert_eq!("1".parse::<Literal>().unwrap().to_string(), "1");
+    assert_eq!("1.0".parse::<Literal>().unwrap().to_string(), "1.0");
+    assert_eq!("'a'".parse::<Literal>().unwrap().to_string(), "'a'");
+    assert_eq!("\"\n\"".parse::<Literal>().unwrap().to_string(), "\"\n\"");
+    assert_eq!("b\"\"".parse::<Literal>().unwrap().to_string(), "b\"\"");
+    assert_eq!("r##\"\"##".parse::<Literal>().unwrap().to_string(), "r##\"\"##");
+    assert_eq!("10ulong".parse::<Literal>().unwrap().to_string(), "10ulong");
+
+    assert!("0 1".parse::<Literal>().is_err());
+    assert!("'a".parse::<Literal>().is_err());
+    assert!(" 0".parse::<Literal>().is_err());
+    assert!("0 ".parse::<Literal>().is_err());
+    assert!("/* comment */0".parse::<Literal>().is_err());
+    assert!("0/* comment */".parse::<Literal>().is_err());
+    assert!("0// comment".parse::<Literal>().is_err());
+}
diff --git a/src/test/ui/proc-macro/test.rs b/src/test/ui/proc-macro/test.rs
new file mode 100644
index 00000000000..c96aa73175f
--- /dev/null
+++ b/src/test/ui/proc-macro/test.rs
@@ -0,0 +1,12 @@
+// check-pass
+// aux-build:api/mod.rs
+
+//! This is for everything that *would* be a #[test] inside of libproc_macro,
+//! except for the fact that proc_macro objects are not capable of existing
+//! inside of an ordinary Rust test execution, only inside a macro.
+
+extern crate proc_macro_api_tests;
+
+proc_macro_api_tests::run!();
+
+fn main() {}
diff --git a/src/test/ui/question-mark-type-infer.stderr b/src/test/ui/question-mark-type-infer.stderr
index 381959b7ae4..db5042b40d8 100644
--- a/src/test/ui/question-mark-type-infer.stderr
+++ b/src/test/ui/question-mark-type-infer.stderr
@@ -1,11 +1,10 @@
-error[E0283]: type annotations needed
+error[E0284]: type annotations needed
   --> $DIR/question-mark-type-infer.rs:12:21
    |
 LL |     l.iter().map(f).collect()?
    |                     ^^^^^^^ cannot infer type
    |
-   = note: cannot satisfy `_: Try`
-   = note: required by `into_result`
+   = note: cannot satisfy `<_ as Try>::Residual == _`
 help: consider specifying the type argument in the method call
    |
 LL |     l.iter().map(f).collect::<B>()?
@@ -13,4 +12,4 @@ LL |     l.iter().map(f).collect::<B>()?
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0284`.
diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
index 1adce5e0150..6985f1b71a8 100644
--- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
@@ -502,10 +502,10 @@ LL |     if (let 0 = 0)? {}
    |        ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
    |
    = help: the trait `Try` is not implemented for `bool`
-   = note: required by `into_result`
+   = note: required by `branch`
 
-error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`)
-  --> $DIR/disallowed-positions.rs:46:8
+error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/disallowed-positions.rs:46:19
    |
 LL | / fn nested_within_if_expr() {
 LL | |     if &let 0 = 0 {}
@@ -513,14 +513,14 @@ LL | |
 LL | |
 ...  |
 LL | |     if (let 0 = 0)? {}
-   | |        ^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
+   | |                   ^ cannot use the `?` operator in a function that returns `()`
 ...  |
 LL | |     if let true = let true = true {}
 LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
-   = help: the trait `Try` is not implemented for `()`
-   = note: required by `from_error`
+   = help: the trait `FromResidual<_>` is not implemented for `()`
+   = note: required by `from_residual`
 
 error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:56:8
@@ -660,7 +660,7 @@ LL |         if let 0 = 0? {}
    |                    ^^ the `?` operator cannot be applied to type `{integer}`
    |
    = help: the trait `Try` is not implemented for `{integer}`
-   = note: required by `into_result`
+   = note: required by `branch`
 
 error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:96:11
@@ -690,10 +690,10 @@ LL |     while (let 0 = 0)? {}
    |           ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
    |
    = help: the trait `Try` is not implemented for `bool`
-   = note: required by `into_result`
+   = note: required by `branch`
 
-error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`)
-  --> $DIR/disallowed-positions.rs:110:11
+error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/disallowed-positions.rs:110:22
    |
 LL | / fn nested_within_while_expr() {
 LL | |     while &let 0 = 0 {}
@@ -701,14 +701,14 @@ LL | |
 LL | |
 ...  |
 LL | |     while (let 0 = 0)? {}
-   | |           ^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
+   | |                      ^ cannot use the `?` operator in a function that returns `()`
 ...  |
 LL | |     while let true = let true = true {}
 LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
-   = help: the trait `Try` is not implemented for `()`
-   = note: required by `from_error`
+   = help: the trait `FromResidual<_>` is not implemented for `()`
+   = note: required by `from_residual`
 
 error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:120:11
@@ -848,7 +848,7 @@ LL |         while let 0 = 0? {}
    |                       ^^ the `?` operator cannot be applied to type `{integer}`
    |
    = help: the trait `Try` is not implemented for `{integer}`
-   = note: required by `into_result`
+   = note: required by `branch`
 
 error[E0614]: type `bool` cannot be dereferenced
   --> $DIR/disallowed-positions.rs:173:5
@@ -869,10 +869,10 @@ LL |     (let 0 = 0)?;
    |     ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
    |
    = help: the trait `Try` is not implemented for `bool`
-   = note: required by `into_result`
+   = note: required by `branch`
 
-error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`)
-  --> $DIR/disallowed-positions.rs:183:5
+error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/disallowed-positions.rs:183:16
    |
 LL | / fn outside_if_and_while_expr() {
 LL | |     &let 0 = 0;
@@ -880,14 +880,14 @@ LL | |
 LL | |     !let 0 = 0;
 ...  |
 LL | |     (let 0 = 0)?;
-   | |     ^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
+   | |                ^ cannot use the `?` operator in a function that returns `()`
 ...  |
 LL | |
 LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
-   = help: the trait `Try` is not implemented for `()`
-   = note: required by `from_error`
+   = help: the trait `FromResidual<_>` is not implemented for `()`
+   = note: required by `from_residual`
 
 error[E0308]: mismatched types
   --> $DIR/disallowed-positions.rs:198:10
@@ -916,7 +916,7 @@ LL |         let 0 = 0?;
    |                 ^^ the `?` operator cannot be applied to type `{integer}`
    |
    = help: the trait `Try` is not implemented for `{integer}`
-   = note: required by `into_result`
+   = note: required by `branch`
 
 error: aborting due to 104 previous errors; 2 warnings emitted
 
diff --git a/src/test/ui/suffixed-literal-meta.rs b/src/test/ui/suffixed-literal-meta.rs
index 319264aec9c..a6531490c01 100644
--- a/src/test/ui/suffixed-literal-meta.rs
+++ b/src/test/ui/suffixed-literal-meta.rs
@@ -1,4 +1,4 @@
-#![feature(rustc_attrs, extended_key_value_attributes)]
+#![feature(rustc_attrs)]
 
 #[rustc_dummy = 1usize] //~ ERROR: suffixed literals are not allowed in attributes
 #[rustc_dummy = 1u8] //~ ERROR: suffixed literals are not allowed in attributes
diff --git a/src/test/ui/suggestions/issue-72766.stderr b/src/test/ui/suggestions/issue-72766.stderr
index 5c9c549fa07..eb67170d47c 100644
--- a/src/test/ui/suggestions/issue-72766.stderr
+++ b/src/test/ui/suggestions/issue-72766.stderr
@@ -5,7 +5,7 @@ LL |     SadGirl {}.call()?;
    |     ^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future`
    |
    = help: the trait `Try` is not implemented for `impl Future`
-   = note: required by `into_result`
+   = note: required by `branch`
 help: consider `await`ing on the `Future`
    |
 LL |     SadGirl {}.call().await?;
diff --git a/src/test/ui/symbol-names/trait-objects.rs b/src/test/ui/symbol-names/trait-objects.rs
new file mode 100644
index 00000000000..cea1a89d757
--- /dev/null
+++ b/src/test/ui/symbol-names/trait-objects.rs
@@ -0,0 +1,48 @@
+// Ensure that trait objects don't include more than one binder. See #83611
+
+// build-fail
+// revisions: v0
+//[v0]compile-flags: -Z symbol-mangling-version=v0
+//[v0]normalize-stderr-test: "Cs.*?_" -> "CRATE_HASH"
+//[v0]normalize-stderr-test: "core\[.*?\]" -> "core[HASH]"
+
+#![feature(rustc_attrs)]
+
+trait Bar {
+    fn method(&self) {}
+}
+
+impl Bar for &dyn FnMut(&u8) {
+    #[rustc_symbol_name]
+    //[v0]~^ ERROR symbol-name
+    //[v0]~| ERROR demangling
+    //[v0]~| ERROR demangling-alt
+    fn method(&self) {}
+}
+
+trait Foo {
+    fn method(&self) {}
+}
+
+impl Foo for &(dyn FnMut(&u8) + for<'b> Send) {
+    #[rustc_symbol_name]
+    //[v0]~^ ERROR symbol-name
+    //[v0]~| ERROR demangling
+    //[v0]~| ERROR demangling-alt
+    fn method(&self) {}
+}
+
+trait Baz {
+    fn method(&self) {}
+}
+
+impl Baz for &(dyn for<'b> Send + FnMut(&u8)) {
+    #[rustc_symbol_name]
+    //[v0]~^ ERROR symbol-name
+    //[v0]~| ERROR demangling
+    //[v0]~| ERROR demangling-alt
+    fn method(&self) {}
+}
+
+fn main() {
+}
diff --git a/src/test/ui/symbol-names/trait-objects.v0.stderr b/src/test/ui/symbol-names/trait-objects.v0.stderr
new file mode 100644
index 00000000000..2b09318f06c
--- /dev/null
+++ b/src/test/ui/symbol-names/trait-objects.v0.stderr
@@ -0,0 +1,56 @@
+error: symbol-name(_RNvXCRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3ops8function5FnMutTRL0_hEEp6OutputuEL_NtB2_3Bar6method)
+  --> $DIR/trait-objects.rs:16:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[17891616a171812d]::Bar>::method)
+  --> $DIR/trait-objects.rs:16:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects::Bar>::method)
+  --> $DIR/trait-objects.rs:16:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RNvXs_CRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3ops8function5FnMutTRL0_hEEp6OutputuNtNtBI_6marker4SendEL_NtB4_3Foo6method)
+  --> $DIR/trait-objects.rs:28:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[17891616a171812d]::Foo>::method)
+  --> $DIR/trait-objects.rs:28:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> + core::marker::Send as trait_objects::Foo>::method)
+  --> $DIR/trait-objects.rs:28:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: symbol-name(_RNvXs0_CRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3ops8function5FnMutTRL0_hEEp6OutputuNtNtBJ_6marker4SendEL_NtB5_3Baz6method)
+  --> $DIR/trait-objects.rs:40:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[17891616a171812d]::Baz>::method)
+  --> $DIR/trait-objects.rs:40:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> + core::marker::Send as trait_objects::Baz>::method)
+  --> $DIR/trait-objects.rs:40:5
+   |
+LL |     #[rustc_symbol_name]
+   |     ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/try-block/try-block-bad-type.rs b/src/test/ui/try-block/try-block-bad-type.rs
index ef6e690e1bd..30ae96763c0 100644
--- a/src/test/ui/try-block/try-block-bad-type.rs
+++ b/src/test/ui/try-block/try-block-bad-type.rs
@@ -15,8 +15,7 @@ pub fn main() {
     let res: Result<i32, i32> = try { }; //~ ERROR type mismatch
 
     let res: () = try { };
-    //~^ ERROR the trait bound `(): Try` is not satisfied
-    //~| ERROR the trait bound `(): Try` is not satisfied
+    //~^ ERROR a `try` block must return `Result` or `Option`
 
-    let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: Try` is not satisfied
+    let res: i32 = try { 5 }; //~ ERROR a `try` block must return `Result` or `Option`
 }
diff --git a/src/test/ui/try-block/try-block-bad-type.stderr b/src/test/ui/try-block/try-block-bad-type.stderr
index 75a42c0d6b7..ec5e91f10c2 100644
--- a/src/test/ui/try-block/try-block-bad-type.stderr
+++ b/src/test/ui/try-block/try-block-bad-type.stderr
@@ -7,43 +7,40 @@ LL |         Err("")?;
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
    = help: the following implementations were found:
              <TryFromSliceError as From<Infallible>>
-   = note: required by `from`
+   = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, &str>>` for `Result<u32, TryFromSliceError>`
+   = note: required by `from_residual`
 
-error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Ok == &str`
+error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == &str`
   --> $DIR/try-block-bad-type.rs:12:9
    |
 LL |         ""
    |         ^^ expected `i32`, found `&str`
 
-error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Ok == ()`
+error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == ()`
   --> $DIR/try-block-bad-type.rs:15:39
    |
 LL |     let res: Result<i32, i32> = try { };
    |                                       ^ expected `i32`, found `()`
 
-error[E0277]: the trait bound `(): Try` is not satisfied
+error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
   --> $DIR/try-block-bad-type.rs:17:25
    |
 LL |     let res: () = try { };
-   |                         ^ the trait `Try` is not implemented for `()`
+   |                         ^ could not wrap the final value of the block as `()` doesn't implement `Try`
    |
-   = note: required by `from_ok`
+   = help: the trait `Try` is not implemented for `()`
+   = note: required by `from_output`
 
-error[E0277]: the trait bound `(): Try` is not satisfied
-  --> $DIR/try-block-bad-type.rs:17:25
-   |
-LL |     let res: () = try { };
-   |                         ^ the trait `Try` is not implemented for `()`
-
-error[E0277]: the trait bound `i32: Try` is not satisfied
-  --> $DIR/try-block-bad-type.rs:21:26
+error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
+  --> $DIR/try-block-bad-type.rs:20:26
    |
 LL |     let res: i32 = try { 5 };
-   |                          ^ the trait `Try` is not implemented for `i32`
+   |                          ^ could not wrap the final value of the block as `i32` doesn't implement `Try`
    |
-   = note: required by `from_ok`
+   = help: the trait `Try` is not implemented for `i32`
+   = note: required by `from_output`
 
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0271, E0277.
 For more information about an error, try `rustc --explain E0271`.
diff --git a/src/test/ui/try-block/try-block-in-while.rs b/src/test/ui/try-block/try-block-in-while.rs
index 5d8748f1dd3..69793df525e 100644
--- a/src/test/ui/try-block/try-block-in-while.rs
+++ b/src/test/ui/try-block/try-block-in-while.rs
@@ -4,5 +4,5 @@
 
 fn main() {
     while try { false } {}
-    //~^ ERROR the trait bound `bool: Try` is not satisfied
+    //~^ ERROR a `try` block must
 }
diff --git a/src/test/ui/try-block/try-block-in-while.stderr b/src/test/ui/try-block/try-block-in-while.stderr
index 75a4e8d065c..c83351d5c43 100644
--- a/src/test/ui/try-block/try-block-in-while.stderr
+++ b/src/test/ui/try-block/try-block-in-while.stderr
@@ -1,10 +1,11 @@
-error[E0277]: the trait bound `bool: Try` is not satisfied
+error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
   --> $DIR/try-block-in-while.rs:6:17
    |
 LL |     while try { false } {}
-   |                 ^^^^^ the trait `Try` is not implemented for `bool`
+   |                 ^^^^^ could not wrap the final value of the block as `bool` doesn't implement `Try`
    |
-   = note: required by `from_ok`
+   = help: the trait `Try` is not implemented for `bool`
+   = note: required by `from_output`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/try-block/try-block-type-error.stderr b/src/test/ui/try-block/try-block-type-error.stderr
index df1441c83d4..3e9a584a551 100644
--- a/src/test/ui/try-block/try-block-type-error.stderr
+++ b/src/test/ui/try-block/try-block-type-error.stderr
@@ -1,4 +1,4 @@
-error[E0271]: type mismatch resolving `<Option<f32> as Try>::Ok == {integer}`
+error[E0271]: type mismatch resolving `<Option<f32> as Try>::Output == {integer}`
   --> $DIR/try-block-type-error.rs:10:9
    |
 LL |         42
@@ -7,7 +7,7 @@ LL |         42
    |         expected `f32`, found integer
    |         help: use a float literal: `42.0`
 
-error[E0271]: type mismatch resolving `<Option<i32> as Try>::Ok == ()`
+error[E0271]: type mismatch resolving `<Option<i32> as Try>::Output == ()`
   --> $DIR/try-block-type-error.rs:16:5
    |
 LL |     };
diff --git a/src/test/ui/try-on-option.stderr b/src/test/ui/try-on-option.stderr
deleted file mode 100644
index ecd12c430f1..00000000000
--- a/src/test/ui/try-on-option.stderr
+++ /dev/null
@@ -1,33 +0,0 @@
-error[E0277]: `?` couldn't convert the error to `()`
-  --> $DIR/try-on-option.rs:7:6
-   |
-LL | fn foo() -> Result<u32, ()> {
-   |             --------------- expected `()` because of this
-LL |     let x: Option<u32> = None;
-LL |     x?;
-   |      ^ the trait `From<NoneError>` is not implemented for `()`
-   |
-   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
-   = note: required by `from`
-help: consider converting the `Option<T>` into a `Result<T, _>` using `Option::ok_or` or `Option::ok_or_else`
-   |
-LL |     x.ok_or_else(|| /* error value */)?;
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`)
-  --> $DIR/try-on-option.rs:13:5
-   |
-LL | / fn bar() -> u32 {
-LL | |     let x: Option<u32> = None;
-LL | |     x?;
-   | |     ^^ cannot use the `?` operator in a function that returns `u32`
-LL | |     22
-LL | | }
-   | |_- this function should return `Result` or `Option` to accept `?`
-   |
-   = help: the trait `Try` is not implemented for `u32`
-   = note: required by `from_error`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/try-operator-custom.rs b/src/test/ui/try-operator-custom.rs
deleted file mode 100644
index 9993061ea61..00000000000
--- a/src/test/ui/try-operator-custom.rs
+++ /dev/null
@@ -1,63 +0,0 @@
-// run-pass
-
-#![feature(try_trait)]
-
-use std::ops::Try;
-
-enum MyResult<T, U> {
-    Awesome(T),
-    Terrible(U)
-}
-
-impl<U, V> Try for MyResult<U, V> {
-    type Ok = U;
-    type Error = V;
-
-    fn from_ok(u: U) -> MyResult<U, V> {
-        MyResult::Awesome(u)
-    }
-
-    fn from_error(e: V) -> MyResult<U, V> {
-        MyResult::Terrible(e)
-    }
-
-    fn into_result(self) -> Result<U, V> {
-        match self {
-            MyResult::Awesome(u) => Ok(u),
-            MyResult::Terrible(e) => Err(e),
-        }
-    }
-}
-
-fn f(x: i32) -> Result<i32, String> {
-    if x == 0 {
-        Ok(42)
-    } else {
-        let y = g(x)?;
-        Ok(y)
-    }
-}
-
-fn g(x: i32) -> MyResult<i32, String> {
-    let _y = f(x - 1)?;
-    MyResult::Terrible("Hello".to_owned())
-}
-
-fn h() -> MyResult<i32, String> {
-    let a: Result<i32, &'static str> = Err("Hello");
-    let b = a?;
-    MyResult::Awesome(b)
-}
-
-fn i() -> MyResult<i32, String> {
-    let a: MyResult<i32, &'static str> = MyResult::Terrible("Hello");
-    let b = a?;
-    MyResult::Awesome(b)
-}
-
-fn main() {
-    assert!(f(0) == Ok(42));
-    assert!(f(10) == Err("Hello".to_owned()));
-    let _ = h();
-    let _ = i();
-}
diff --git a/src/test/ui/try-trait/bad-interconversion.rs b/src/test/ui/try-trait/bad-interconversion.rs
new file mode 100644
index 00000000000..87585822f57
--- /dev/null
+++ b/src/test/ui/try-trait/bad-interconversion.rs
@@ -0,0 +1,48 @@
+#![feature(control_flow_enum)]
+
+use std::ops::ControlFlow;
+
+fn result_to_result() -> Result<u64, u8> {
+    Ok(Err(123_i32)?)
+    //~^ ERROR `?` couldn't convert the error to `u8`
+}
+
+fn option_to_result() -> Result<u64, String> {
+    Some(3)?;
+    //~^ ERROR the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
+    Ok(10)
+}
+
+fn control_flow_to_result() -> Result<u64, String> {
+    Ok(ControlFlow::Break(123)?)
+    //~^ ERROR the `?` operator can only be used on `Result`s in a function that returns `Result`
+}
+
+fn result_to_option() -> Option<u16> {
+    Some(Err("hello")?)
+    //~^ ERROR the `?` operator can only be used on `Option`s in a function that returns `Option`
+}
+
+fn control_flow_to_option() -> Option<u64> {
+    Some(ControlFlow::Break(123)?)
+    //~^ ERROR the `?` operator can only be used on `Option`s in a function that returns `Option`
+}
+
+fn result_to_control_flow() -> ControlFlow<String> {
+    ControlFlow::Continue(Err("hello")?)
+    //~^ ERROR the `?` operator can only be used on `ControlFlow<B, _>`s in a function that returns `ControlFlow<B, _>`
+}
+
+fn option_to_control_flow() -> ControlFlow<u64> {
+    Some(3)?;
+    //~^ ERROR the `?` operator can only be used on `ControlFlow<B, _>`s in a function that returns `ControlFlow<B, _>`
+    ControlFlow::Break(10)
+}
+
+fn control_flow_to_control_flow() -> ControlFlow<i64> {
+    ControlFlow::Break(4_u8)?;
+    //~^ ERROR the `?` operator can only be used on `ControlFlow<B, _>`s in a function that returns `ControlFlow<B, _>`
+    ControlFlow::Continue(())
+}
+
+fn main() {}
diff --git a/src/test/ui/try-trait/bad-interconversion.stderr b/src/test/ui/try-trait/bad-interconversion.stderr
new file mode 100644
index 00000000000..e396256de22
--- /dev/null
+++ b/src/test/ui/try-trait/bad-interconversion.stderr
@@ -0,0 +1,115 @@
+error[E0277]: `?` couldn't convert the error to `u8`
+  --> $DIR/bad-interconversion.rs:6:20
+   |
+LL | fn result_to_result() -> Result<u64, u8> {
+   |                          --------------- expected `u8` because of this
+LL |     Ok(Err(123_i32)?)
+   |                    ^ the trait `From<i32>` is not implemented for `u8`
+   |
+   = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
+   = help: the following implementations were found:
+             <u8 as From<NonZeroU8>>
+             <u8 as From<bool>>
+   = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, i32>>` for `Result<u64, u8>`
+   = note: required by `from_residual`
+
+error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
+  --> $DIR/bad-interconversion.rs:11:12
+   |
+LL | / fn option_to_result() -> Result<u64, String> {
+LL | |     Some(3)?;
+   | |            ^ use `.ok_or(...)?` to provide an error compatible with `Result<u64, String>`
+LL | |
+LL | |     Ok(10)
+LL | | }
+   | |_- this function returns a `Result`
+   |
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u64, String>`
+   = note: required by `from_residual`
+
+error[E0277]: the `?` operator can only be used on `Result`s in a function that returns `Result`
+  --> $DIR/bad-interconversion.rs:17:31
+   |
+LL | / fn control_flow_to_result() -> Result<u64, String> {
+LL | |     Ok(ControlFlow::Break(123)?)
+   | |                               ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Result<u64, String>`
+LL | |
+LL | | }
+   | |_- this function returns a `Result`
+   |
+   = help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Result<u64, String>`
+   = note: required by `from_residual`
+
+error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option`
+  --> $DIR/bad-interconversion.rs:22:22
+   |
+LL | / fn result_to_option() -> Option<u16> {
+LL | |     Some(Err("hello")?)
+   | |                      ^ this `?` produces `Result<Infallible, &str>`, which is incompatible with `Option<u16>`
+LL | |
+LL | | }
+   | |_- this function returns an `Option`
+   |
+   = help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `Option<u16>`
+   = note: required by `from_residual`
+
+error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option`
+  --> $DIR/bad-interconversion.rs:27:33
+   |
+LL | / fn control_flow_to_option() -> Option<u64> {
+LL | |     Some(ControlFlow::Break(123)?)
+   | |                                 ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Option<u64>`
+LL | |
+LL | | }
+   | |_- this function returns an `Option`
+   |
+   = help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Option<u64>`
+   = note: required by `from_residual`
+
+error[E0277]: the `?` operator can only be used on `ControlFlow<B, _>`s in a function that returns `ControlFlow<B, _>`
+  --> $DIR/bad-interconversion.rs:32:39
+   |
+LL | / fn result_to_control_flow() -> ControlFlow<String> {
+LL | |     ControlFlow::Continue(Err("hello")?)
+   | |                                       ^ this `?` produces `Result<Infallible, &str>`, which is incompatible with `ControlFlow<String>`
+LL | |
+LL | | }
+   | |_- this function returns a `ControlFlow`
+   |
+   = help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `ControlFlow<String>`
+   = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow`
+   = note: required by `from_residual`
+
+error[E0277]: the `?` operator can only be used on `ControlFlow<B, _>`s in a function that returns `ControlFlow<B, _>`
+  --> $DIR/bad-interconversion.rs:37:12
+   |
+LL | / fn option_to_control_flow() -> ControlFlow<u64> {
+LL | |     Some(3)?;
+   | |            ^ this `?` produces `Option<Infallible>`, which is incompatible with `ControlFlow<u64>`
+LL | |
+LL | |     ControlFlow::Break(10)
+LL | | }
+   | |_- this function returns a `ControlFlow`
+   |
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `ControlFlow<u64>`
+   = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow`
+   = note: required by `from_residual`
+
+error[E0277]: the `?` operator can only be used on `ControlFlow<B, _>`s in a function that returns `ControlFlow<B, _>`
+  --> $DIR/bad-interconversion.rs:43:29
+   |
+LL | / fn control_flow_to_control_flow() -> ControlFlow<i64> {
+LL | |     ControlFlow::Break(4_u8)?;
+   | |                             ^ this `?` produces `ControlFlow<u8, Infallible>`, which is incompatible with `ControlFlow<i64>`
+LL | |
+LL | |     ControlFlow::Continue(())
+LL | | }
+   | |_- this function returns a `ControlFlow`
+   |
+   = help: the trait `FromResidual<ControlFlow<u8, Infallible>>` is not implemented for `ControlFlow<i64>`
+   = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow`
+   = note: required by `from_residual`
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/option-to-result.rs b/src/test/ui/try-trait/option-to-result.rs
index 00e8b5244c5..45aaf361a9c 100644
--- a/src/test/ui/option-to-result.rs
+++ b/src/test/ui/try-trait/option-to-result.rs
@@ -2,12 +2,12 @@ fn main(){ }
 
 fn test_result() -> Result<(),()> {
     let a:Option<()> = Some(());
-    a?;//~ ERROR `?` couldn't convert the error
+    a?;//~ ERROR the `?` operator can only be used
     Ok(())
 }
 
 fn test_option() -> Option<i32>{
     let a:Result<i32, i32> = Ok(5);
-    a?;//~ ERROR `?` couldn't convert the error
+    a?;//~ ERROR the `?` operator can only be used
     Some(5)
 }
diff --git a/src/test/ui/try-trait/option-to-result.stderr b/src/test/ui/try-trait/option-to-result.stderr
new file mode 100644
index 00000000000..92087c2aba2
--- /dev/null
+++ b/src/test/ui/try-trait/option-to-result.stderr
@@ -0,0 +1,31 @@
+error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
+  --> $DIR/option-to-result.rs:5:6
+   |
+LL | / fn test_result() -> Result<(),()> {
+LL | |     let a:Option<()> = Some(());
+LL | |     a?;
+   | |      ^ use `.ok_or(...)?` to provide an error compatible with `Result<(), ()>`
+LL | |     Ok(())
+LL | | }
+   | |_- this function returns a `Result`
+   |
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<(), ()>`
+   = note: required by `from_residual`
+
+error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option`
+  --> $DIR/option-to-result.rs:11:6
+   |
+LL | / fn test_option() -> Option<i32>{
+LL | |     let a:Result<i32, i32> = Ok(5);
+LL | |     a?;
+   | |      ^ this `?` produces `Result<Infallible, i32>`, which is incompatible with `Option<i32>`
+LL | |     Some(5)
+LL | | }
+   | |_- this function returns an `Option`
+   |
+   = help: the trait `FromResidual<Result<Infallible, i32>>` is not implemented for `Option<i32>`
+   = note: required by `from_residual`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/try-trait/try-as-monad.rs b/src/test/ui/try-trait/try-as-monad.rs
new file mode 100644
index 00000000000..cf09838b304
--- /dev/null
+++ b/src/test/ui/try-trait/try-as-monad.rs
@@ -0,0 +1,24 @@
+// run-pass
+
+#![feature(try_trait_v2)]
+
+use std::ops::Try;
+
+fn monad_unit<T: Try>(x: <T as Try>::Output) -> T {
+    T::from_output(x)
+}
+
+fn monad_bind<T1: Try<Residual = R>, T2: Try<Residual = R>, R>(
+    mx: T1,
+    f: impl FnOnce(<T1 as Try>::Output) -> T2)
+-> T2 {
+    let x = mx?;
+    f(x)
+}
+
+fn main() {
+    let mx: Option<i32> = monad_unit(1);
+    let my = monad_bind(mx, |x| Some(x + 1));
+    let mz = monad_bind(my, |x| Some(-x));
+    assert_eq!(mz, Some(-2));
+}
diff --git a/src/test/ui/try-on-option-diagnostics.rs b/src/test/ui/try-trait/try-on-option-diagnostics.rs
index 63d17414c31..63d17414c31 100644
--- a/src/test/ui/try-on-option-diagnostics.rs
+++ b/src/test/ui/try-trait/try-on-option-diagnostics.rs
diff --git a/src/test/ui/try-on-option-diagnostics.stderr b/src/test/ui/try-trait/try-on-option-diagnostics.stderr
index a71ee20aacf..e7c67c21bb3 100644
--- a/src/test/ui/try-on-option-diagnostics.stderr
+++ b/src/test/ui/try-trait/try-on-option-diagnostics.stderr
@@ -1,57 +1,57 @@
-error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`)
-  --> $DIR/try-on-option-diagnostics.rs:7:5
+error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/try-on-option-diagnostics.rs:7:6
    |
 LL | / fn a_function() -> u32 {
 LL | |     let x: Option<u32> = None;
 LL | |     x?;
-   | |     ^^ cannot use the `?` operator in a function that returns `u32`
+   | |      ^ cannot use the `?` operator in a function that returns `u32`
 LL | |     22
 LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
-   = help: the trait `Try` is not implemented for `u32`
-   = note: required by `from_error`
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
+   = note: required by `from_residual`
 
-error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `Try`)
-  --> $DIR/try-on-option-diagnostics.rs:14:9
+error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/try-on-option-diagnostics.rs:14:10
    |
 LL |       let a_closure = || {
    |  _____________________-
 LL | |         let x: Option<u32> = None;
 LL | |         x?;
-   | |         ^^ cannot use the `?` operator in a closure that returns `{integer}`
+   | |          ^ cannot use the `?` operator in a closure that returns `{integer}`
 LL | |         22
 LL | |     };
    | |_____- this function should return `Result` or `Option` to accept `?`
    |
-   = help: the trait `Try` is not implemented for `{integer}`
-   = note: required by `from_error`
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `{integer}`
+   = note: required by `from_residual`
 
-error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `Try`)
-  --> $DIR/try-on-option-diagnostics.rs:26:13
+error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/try-on-option-diagnostics.rs:26:14
    |
 LL | /         fn a_method() {
 LL | |             let x: Option<u32> = None;
 LL | |             x?;
-   | |             ^^ cannot use the `?` operator in a method that returns `()`
+   | |              ^ cannot use the `?` operator in a method that returns `()`
 LL | |         }
    | |_________- this function should return `Result` or `Option` to accept `?`
    |
-   = help: the trait `Try` is not implemented for `()`
-   = note: required by `from_error`
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `()`
+   = note: required by `from_residual`
 
-error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `Try`)
-  --> $DIR/try-on-option-diagnostics.rs:39:13
+error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/try-on-option-diagnostics.rs:39:14
    |
 LL | /         fn a_trait_method() {
 LL | |             let x: Option<u32> = None;
 LL | |             x?;
-   | |             ^^ cannot use the `?` operator in a trait method that returns `()`
+   | |              ^ cannot use the `?` operator in a trait method that returns `()`
 LL | |         }
    | |_________- this function should return `Result` or `Option` to accept `?`
    |
-   = help: the trait `Try` is not implemented for `()`
-   = note: required by `from_error`
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `()`
+   = note: required by `from_residual`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/try-on-option.rs b/src/test/ui/try-trait/try-on-option.rs
index 5d94cee8e37..f2012936a11 100644
--- a/src/test/ui/try-on-option.rs
+++ b/src/test/ui/try-trait/try-on-option.rs
@@ -4,7 +4,7 @@ fn main() {}
 
 fn foo() -> Result<u32, ()> {
     let x: Option<u32> = None;
-    x?; //~ ERROR `?` couldn't convert the error
+    x?; //~ ERROR the `?` operator
     Ok(22)
 }
 
diff --git a/src/test/ui/try-trait/try-on-option.stderr b/src/test/ui/try-trait/try-on-option.stderr
new file mode 100644
index 00000000000..604baa8550b
--- /dev/null
+++ b/src/test/ui/try-trait/try-on-option.stderr
@@ -0,0 +1,31 @@
+error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
+  --> $DIR/try-on-option.rs:7:6
+   |
+LL | / fn foo() -> Result<u32, ()> {
+LL | |     let x: Option<u32> = None;
+LL | |     x?;
+   | |      ^ use `.ok_or(...)?` to provide an error compatible with `Result<u32, ()>`
+LL | |     Ok(22)
+LL | | }
+   | |_- this function returns a `Result`
+   |
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u32, ()>`
+   = note: required by `from_residual`
+
+error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/try-on-option.rs:13:6
+   |
+LL | / fn bar() -> u32 {
+LL | |     let x: Option<u32> = None;
+LL | |     x?;
+   | |      ^ cannot use the `?` operator in a function that returns `u32`
+LL | |     22
+LL | | }
+   | |_- this function should return `Result` or `Option` to accept `?`
+   |
+   = help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
+   = note: required by `from_residual`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/try-trait/try-operator-custom.rs b/src/test/ui/try-trait/try-operator-custom.rs
new file mode 100644
index 00000000000..45636a7fced
--- /dev/null
+++ b/src/test/ui/try-trait/try-operator-custom.rs
@@ -0,0 +1,91 @@
+// run-pass
+
+#![feature(control_flow_enum)]
+#![feature(try_trait_v2)]
+
+use std::ops::{ControlFlow, FromResidual, Try};
+
+enum MyResult<T, U> {
+    Awesome(T),
+    Terrible(U)
+}
+
+enum Never {}
+
+impl<U, V> Try for MyResult<U, V> {
+    type Output = U;
+    type Residual = MyResult<Never, V>;
+
+    fn from_output(u: U) -> MyResult<U, V> {
+        MyResult::Awesome(u)
+    }
+
+    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
+        match self {
+            MyResult::Awesome(u) => ControlFlow::Continue(u),
+            MyResult::Terrible(e) => ControlFlow::Break(MyResult::Terrible(e)),
+        }
+    }
+}
+
+impl<U, V, W> FromResidual<MyResult<Never, V>> for MyResult<U, W> where V: Into<W> {
+    fn from_residual(x: MyResult<Never, V>) -> Self {
+        match x {
+            MyResult::Awesome(u) => match u {},
+            MyResult::Terrible(e) => MyResult::Terrible(e.into()),
+        }
+    }
+}
+
+type ResultResidual<E> = Result<std::convert::Infallible, E>;
+
+impl<U, V, W> FromResidual<ResultResidual<V>> for MyResult<U, W> where V: Into<W> {
+    fn from_residual(x: ResultResidual<V>) -> Self {
+        match x {
+            Ok(v) => match v {}
+            Err(e) => MyResult::Terrible(e.into()),
+        }
+    }
+}
+
+impl<U, V, W> FromResidual<MyResult<Never, V>> for Result<U, W> where V: Into<W> {
+    fn from_residual(x: MyResult<Never, V>) -> Self {
+        match x {
+            MyResult::Awesome(u) => match u {},
+            MyResult::Terrible(e) => Err(e.into()),
+        }
+    }
+}
+
+fn f(x: i32) -> Result<i32, String> {
+    if x == 0 {
+        Ok(42)
+    } else {
+        let y = g(x)?;
+        Ok(y)
+    }
+}
+
+fn g(x: i32) -> MyResult<i32, String> {
+    let _y = f(x - 1)?;
+    MyResult::Terrible("Hello".to_owned())
+}
+
+fn h() -> MyResult<i32, String> {
+    let a: Result<i32, &'static str> = Err("Hello");
+    let b = a?;
+    MyResult::Awesome(b)
+}
+
+fn i() -> MyResult<i32, String> {
+    let a: MyResult<i32, &'static str> = MyResult::Terrible("Hello");
+    let b = a?;
+    MyResult::Awesome(b)
+}
+
+fn main() {
+    assert!(f(0) == Ok(42));
+    assert!(f(10) == Err("Hello".to_owned()));
+    let _ = h();
+    let _ = i();
+}
diff --git a/src/test/ui/try-operator-on-main.rs b/src/test/ui/try-trait/try-operator-on-main.rs
index e1b6cfbe5ae..3b364f7e7d3 100644
--- a/src/test/ui/try-operator-on-main.rs
+++ b/src/test/ui/try-trait/try-operator-on-main.rs
@@ -1,4 +1,4 @@
-#![feature(try_trait)]
+#![feature(try_trait_v2)]
 
 use std::ops::Try;
 
@@ -7,14 +7,13 @@ fn main() {
     std::fs::File::open("foo")?; //~ ERROR the `?` operator can only
 
     // a non-`Try` type on a non-`Try` fn
-    ()?; //~ ERROR the `?` operator can only
+    ()?; //~ ERROR the `?` operator can only be applied to
+    //~^ ERROR the `?` operator can only be used in a function that
 
     // an unrelated use of `Try`
     try_trait_generic::<()>(); //~ ERROR the trait bound
 }
 
-
-
 fn try_trait_generic<T: Try>() -> T {
     // and a non-`Try` object on a `Try` fn.
     ()?; //~ ERROR the `?` operator can only be applied to values that implement `Try`
diff --git a/src/test/ui/try-operator-on-main.stderr b/src/test/ui/try-trait/try-operator-on-main.stderr
index be17de2fe7c..7d42c2e4d10 100644
--- a/src/test/ui/try-operator-on-main.stderr
+++ b/src/test/ui/try-trait/try-operator-on-main.stderr
@@ -1,18 +1,18 @@
-error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`)
-  --> $DIR/try-operator-on-main.rs:7:5
+error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/try-operator-on-main.rs:7:31
    |
 LL | / fn main() {
 LL | |     // error for a `Try` type on a non-`Try` fn
 LL | |     std::fs::File::open("foo")?;
-   | |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
+   | |                               ^ cannot use the `?` operator in a function that returns `()`
 LL | |
 ...  |
 LL | |     try_trait_generic::<()>();
 LL | | }
    | |_- this function should return `Result` or `Option` to accept `?`
    |
-   = help: the trait `Try` is not implemented for `()`
-   = note: required by `from_error`
+   = help: the trait `FromResidual<Result<Infallible, std::io::Error>>` is not implemented for `()`
+   = note: required by `from_residual`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
   --> $DIR/try-operator-on-main.rs:10:5
@@ -21,10 +21,28 @@ LL |     ()?;
    |     ^^^ the `?` operator cannot be applied to type `()`
    |
    = help: the trait `Try` is not implemented for `()`
-   = note: required by `into_result`
+   = note: required by `branch`
+
+error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
+  --> $DIR/try-operator-on-main.rs:10:7
+   |
+LL | / fn main() {
+LL | |     // error for a `Try` type on a non-`Try` fn
+LL | |     std::fs::File::open("foo")?;
+LL | |
+LL | |     // a non-`Try` type on a non-`Try` fn
+LL | |     ()?;
+   | |       ^ cannot use the `?` operator in a function that returns `()`
+...  |
+LL | |     try_trait_generic::<()>();
+LL | | }
+   | |_- this function should return `Result` or `Option` to accept `?`
+   |
+   = help: the trait `FromResidual<_>` is not implemented for `()`
+   = note: required by `from_residual`
 
 error[E0277]: the trait bound `(): Try` is not satisfied
-  --> $DIR/try-operator-on-main.rs:13:25
+  --> $DIR/try-operator-on-main.rs:14:25
    |
 LL |     try_trait_generic::<()>();
    |                         ^^ the trait `Try` is not implemented for `()`
@@ -33,14 +51,14 @@ LL | fn try_trait_generic<T: Try>() -> T {
    |                         --- required by this bound in `try_trait_generic`
 
 error[E0277]: the `?` operator can only be applied to values that implement `Try`
-  --> $DIR/try-operator-on-main.rs:20:5
+  --> $DIR/try-operator-on-main.rs:19:5
    |
 LL |     ()?;
    |     ^^^ the `?` operator cannot be applied to type `()`
    |
    = help: the trait `Try` is not implemented for `()`
-   = note: required by `into_result`
+   = note: required by `branch`
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/try-poll.rs b/src/test/ui/try-trait/try-poll.rs
index d42e51c7405..d42e51c7405 100644
--- a/src/test/ui/try-poll.rs
+++ b/src/test/ui/try-trait/try-poll.rs