about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-05-18 20:50:01 +0000
committerbors <bors@rust-lang.org>2021-05-18 20:50:01 +0000
commit4e3e6db011c5b482d2bef8ba02274657f93b5e0d (patch)
tree18c4d91304ab931792236935417dfe51ad998a7a /src
parent491cf5561efb1f5ff33c3234ccd0bc5cacbebe3e (diff)
parente2edee4da07032de72ac930df1453780dbe73f3b (diff)
downloadrust-4e3e6db011c5b482d2bef8ba02274657f93b5e0d.tar.gz
rust-4e3e6db011c5b482d2bef8ba02274657f93b5e0d.zip
Auto merge of #84767 - scottmcm:try_trait_actual, r=lcnr
Implement the new desugaring from `try_trait_v2`

~~Currently blocked on https://github.com/rust-lang/rust/issues/84782, which has a PR in https://github.com/rust-lang/rust/pull/84811~~ Rebased atop that fix.

`try_trait_v2` tracking issue: https://github.com/rust-lang/rust/issues/84277

Unfortunately this is already touching a ton of things, so if you have suggestions for good ways to split it up, I'd be happy to hear them.  (The combination between the use in the library, the compiler changes, the corresponding diagnostic differences, even MIR tests mean that I don't really have a great plan for it other than trying to have decently-readable commits.

r? `@ghost`

~~(This probably shouldn't go in during the last week before the fork anyway.)~~ Fork happened.
Diffstat (limited to 'src')
-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/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/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/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/suggestions/issue-72766.stderr2
-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
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_question_mark.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/try_err.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_io_amount.rs2
49 files changed, 835 insertions, 613 deletions
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/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/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/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/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/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
diff --git a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs
index 7b156a8c49d..d8417c7dc70 100644
--- a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs
@@ -147,7 +147,7 @@ fn is_some_or_ok_call<'a>(cx: &'a LateContext<'_>, expr: &'a Expr<'_>) -> Option
         if let ExprKind::Call(called, args) = &inner_expr_with_q.kind;
         if args.len() == 1;
 
-        if let ExprKind::Path(QPath::LangItem(LangItem::TryIntoResult, _)) = &called.kind;
+        if let ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, _)) = &called.kind;
         then {
             // Extract inner expr type from match argument generated by
             // question mark operator
diff --git a/src/tools/clippy/clippy_lints/src/try_err.rs b/src/tools/clippy/clippy_lints/src/try_err.rs
index ebb39ea4877..f2ba2b2ecf6 100644
--- a/src/tools/clippy/clippy_lints/src/try_err.rs
+++ b/src/tools/clippy/clippy_lints/src/try_err.rs
@@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for TryErr {
             if let ExprKind::Match(match_arg, _, MatchSource::TryDesugar) = expr.kind;
             if let ExprKind::Call(match_fun, try_args) = match_arg.kind;
             if let ExprKind::Path(ref match_fun_path) = match_fun.kind;
-            if matches!(match_fun_path, QPath::LangItem(LangItem::TryIntoResult, _));
+            if matches!(match_fun_path, QPath::LangItem(LangItem::TryTraitBranch, _));
             if let Some(try_arg) = try_args.get(0);
             if let ExprKind::Call(err_fun, err_args) = try_arg.kind;
             if let Some(err_arg) = err_args.get(0);
diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
index 3387f35bac3..c27a6d4e347 100644
--- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
@@ -45,7 +45,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount {
                 if let hir::ExprKind::Call(func, args) = res.kind {
                     if matches!(
                         func.kind,
-                        hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryIntoResult, _))
+                        hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, _))
                     ) {
                         check_map_error(cx, &args[0], expr);
                     }