about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs58
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs10
-rw-r--r--compiler/rustc_hir/src/lang_items.rs11
-rw-r--r--compiler/rustc_span/src/symbol.rs13
-rw-r--r--library/alloc/src/collections/vec_deque/iter.rs4
-rw-r--r--library/alloc/src/lib.rs3
-rw-r--r--library/core/src/iter/adapters/chain.rs4
-rw-r--r--library/core/src/iter/adapters/cloned.rs4
-rw-r--r--library/core/src/iter/adapters/copied.rs4
-rw-r--r--library/core/src/iter/adapters/cycle.rs2
-rw-r--r--library/core/src/iter/adapters/enumerate.rs4
-rw-r--r--library/core/src/iter/adapters/filter.rs6
-rw-r--r--library/core/src/iter/adapters/filter_map.rs6
-rw-r--r--library/core/src/iter/adapters/flatten.rs16
-rw-r--r--library/core/src/iter/adapters/fuse.rs16
-rw-r--r--library/core/src/iter/adapters/inspect.rs4
-rw-r--r--library/core/src/iter/adapters/map.rs4
-rw-r--r--library/core/src/iter/adapters/map_while.rs2
-rw-r--r--library/core/src/iter/adapters/mod.rs2
-rw-r--r--library/core/src/iter/adapters/peekable.rs31
-rw-r--r--library/core/src/iter/adapters/rev.rs4
-rw-r--r--library/core/src/iter/adapters/scan.rs4
-rw-r--r--library/core/src/iter/adapters/skip.rs6
-rw-r--r--library/core/src/iter/adapters/skip_while.rs2
-rw-r--r--library/core/src/iter/adapters/step_by.rs4
-rw-r--r--library/core/src/iter/adapters/take.rs6
-rw-r--r--library/core/src/iter/adapters/take_while.rs4
-rw-r--r--library/core/src/iter/range.rs4
-rw-r--r--library/core/src/iter/traits/double_ended.rs2
-rw-r--r--library/core/src/iter/traits/iterator.rs39
-rw-r--r--library/core/src/ops/control_flow.rs45
-rw-r--r--library/core/src/ops/mod.rs10
-rw-r--r--library/core/src/ops/try.rs14
-rw-r--r--library/core/src/ops/try_trait.rs105
-rw-r--r--library/core/src/option.rs4
-rw-r--r--library/core/src/result.rs4
-rw-r--r--library/core/src/slice/ascii.rs2
-rw-r--r--library/core/src/str/iter.rs2
-rw-r--r--library/core/src/task/poll.rs18
-rw-r--r--library/core/tests/lib.rs1
-rw-r--r--library/core/tests/option.rs12
-rw-r--r--library/core/tests/result.rs30
-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
91 files changed, 1176 insertions, 798 deletions
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 483135ed3a3..866f2180bb6 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -560,8 +560,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
         )
     }
 
-    /// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_ok(<expr>) }`,
-    /// `try { <stmts>; }` into `{ <stmts>; ::std::ops::Try::from_ok(()) }`
+    /// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_output(<expr>) }`,
+    /// `try { <stmts>; }` into `{ <stmts>; ::std::ops::Try::from_output(()) }`
     /// and save the block id to use it as a break target for desugaring of the `?` operator.
     fn lower_expr_try_block(&mut self, body: &Block) -> hir::ExprKind<'hir> {
         self.with_catch_scope(body.id, |this| {
@@ -590,9 +590,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let ok_wrapped_span =
                 this.mark_span_with_reason(DesugaringKind::TryBlock, tail_expr.span, None);
 
-            // `::std::ops::Try::from_ok($tail_expr)`
+            // `::std::ops::Try::from_output($tail_expr)`
             block.expr = Some(this.wrap_in_try_constructor(
-                hir::LangItem::TryFromOk,
+                hir::LangItem::TryTraitFromOutput,
                 try_span,
                 tail_expr,
                 ok_wrapped_span,
@@ -1579,14 +1579,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
             self.allow_try_trait.clone(),
         );
 
-        // `Try::into_result(<expr>)`
+        // `Try::branch(<expr>)`
         let scrutinee = {
             // expand <expr>
             let sub_expr = self.lower_expr_mut(sub_expr);
 
             self.expr_call_lang_item_fn(
                 unstable_span,
-                hir::LangItem::TryIntoResult,
+                hir::LangItem::TryTraitBranch,
                 arena_vec![self; sub_expr],
             )
         };
@@ -1604,8 +1604,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
         };
         let attrs = vec![attr];
 
-        // `Ok(val) => #[allow(unreachable_code)] val,`
-        let ok_arm = {
+        // `ControlFlow::Continue(val) => #[allow(unreachable_code)] val,`
+        let continue_arm = {
             let val_ident = Ident::with_dummy_span(sym::val);
             let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident);
             let val_expr = self.arena.alloc(self.expr_ident_with_attrs(
@@ -1614,27 +1614,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 val_pat_nid,
                 ThinVec::from(attrs.clone()),
             ));
-            let ok_pat = self.pat_ok(span, val_pat);
-            self.arm(ok_pat, val_expr)
+            let continue_pat = self.pat_cf_continue(unstable_span, val_pat);
+            self.arm(continue_pat, val_expr)
         };
 
-        // `Err(err) => #[allow(unreachable_code)]
-        //              return Try::from_error(From::from(err)),`
-        let err_arm = {
-            let err_ident = Ident::with_dummy_span(sym::err);
-            let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident);
-            let from_expr = {
-                let err_expr = self.expr_ident_mut(try_span, err_ident, err_local_nid);
-                self.expr_call_lang_item_fn(
-                    try_span,
-                    hir::LangItem::FromFrom,
-                    arena_vec![self; err_expr],
-                )
-            };
-            let from_err_expr = self.wrap_in_try_constructor(
-                hir::LangItem::TryFromError,
-                unstable_span,
-                from_expr,
+        // `ControlFlow::Break(residual) =>
+        //     #[allow(unreachable_code)]
+        //     return Try::from_residual(residual),`
+        let break_arm = {
+            let residual_ident = Ident::with_dummy_span(sym::residual);
+            let (residual_local, residual_local_nid) = self.pat_ident(try_span, residual_ident);
+            let residual_expr = self.expr_ident_mut(try_span, residual_ident, residual_local_nid);
+            let from_residual_expr = self.wrap_in_try_constructor(
+                hir::LangItem::TryTraitFromResidual,
+                try_span,
+                self.arena.alloc(residual_expr),
                 unstable_span,
             );
             let thin_attrs = ThinVec::from(attrs);
@@ -1645,25 +1639,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     try_span,
                     hir::ExprKind::Break(
                         hir::Destination { label: None, target_id },
-                        Some(from_err_expr),
+                        Some(from_residual_expr),
                     ),
                     thin_attrs,
                 ))
             } else {
                 self.arena.alloc(self.expr(
                     try_span,
-                    hir::ExprKind::Ret(Some(from_err_expr)),
+                    hir::ExprKind::Ret(Some(from_residual_expr)),
                     thin_attrs,
                 ))
             };
 
-            let err_pat = self.pat_err(try_span, err_local);
-            self.arm(err_pat, ret_expr)
+            let break_pat = self.pat_cf_break(try_span, residual_local);
+            self.arm(break_pat, ret_expr)
         };
 
         hir::ExprKind::Match(
             scrutinee,
-            arena_vec![self; err_arm, ok_arm],
+            arena_vec![self; break_arm, continue_arm],
             hir::MatchSource::TryDesugar,
         )
     }
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 740dfc65df8..56f97054f96 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -332,7 +332,7 @@ pub fn lower_crate<'a, 'hir>(
         lifetimes_to_define: Vec::new(),
         is_collecting_in_band_lifetimes: false,
         in_scope_lifetimes: Vec::new(),
-        allow_try_trait: Some([sym::try_trait][..].into()),
+        allow_try_trait: Some([sym::control_flow_enum, sym::try_trait_v2][..].into()),
         allow_gen_future: Some([sym::gen_future][..].into()),
     }
     .lower_crate(krate)
@@ -2490,14 +2490,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         self.pat(span, hir::PatKind::Lit(expr))
     }
 
-    fn pat_ok(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
+    fn pat_cf_continue(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
         let field = self.single_pat_field(span, pat);
-        self.pat_lang_item_variant(span, hir::LangItem::ResultOk, field)
+        self.pat_lang_item_variant(span, hir::LangItem::ControlFlowContinue, field)
     }
 
-    fn pat_err(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
+    fn pat_cf_break(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
         let field = self.single_pat_field(span, pat);
-        self.pat_lang_item_variant(span, hir::LangItem::ResultErr, field)
+        self.pat_lang_item_variant(span, hir::LangItem::ControlFlowBreak, field)
     }
 
     fn pat_some(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 7b788b13b9f..0b8535f8ca5 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -308,12 +308,12 @@ language_item_table! {
 
     Termination,             sym::termination,         termination,                Target::Trait;
 
-    Try,                     kw::Try,                  try_trait,                  Target::Trait;
+    Try,                     sym::Try,                 try_trait,                  Target::Trait;
 
     // Language items from AST lowering
-    TryFromError,            sym::from_error,          from_error_fn,              Target::Method(MethodKind::Trait { body: false });
-    TryFromOk,               sym::from_ok,             from_ok_fn,                 Target::Method(MethodKind::Trait { body: false });
-    TryIntoResult,           sym::into_result,         into_result_fn,             Target::Method(MethodKind::Trait { body: false });
+    TryTraitFromResidual,    sym::from_residual,       from_residual_fn,           Target::Method(MethodKind::Trait { body: false });
+    TryTraitFromOutput,      sym::from_output,         from_output_fn,             Target::Method(MethodKind::Trait { body: false });
+    TryTraitBranch,          sym::branch,              branch_fn,                  Target::Method(MethodKind::Trait { body: false });
 
     PollReady,               sym::Ready,               poll_ready_variant,         Target::Variant;
     PollPending,             sym::Pending,             poll_pending_variant,       Target::Variant;
@@ -331,6 +331,9 @@ language_item_table! {
     ResultOk,                sym::Ok,                  result_ok_variant,          Target::Variant;
     ResultErr,               sym::Err,                 result_err_variant,         Target::Variant;
 
+    ControlFlowContinue,     sym::Continue,            cf_continue_variant,        Target::Variant;
+    ControlFlowBreak,        sym::Break,               cf_break_variant,           Target::Variant;
+
     IntoIterIntoIter,        sym::into_iter,           into_iter_fn,               Target::Method(MethodKind::Trait { body: false });
     IteratorNext,            sym::next,                next_fn,                    Target::Method(MethodKind::Trait { body: false});
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 03a8f2be156..14ee083ecee 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -130,10 +130,12 @@ symbols! {
         BTreeSet,
         BinaryHeap,
         Borrow,
+        Break,
         C,
         CString,
         Center,
         Clone,
+        Continue,
         Copy,
         Count,
         Debug,
@@ -326,6 +328,7 @@ symbols! {
         box_patterns,
         box_syntax,
         braced_empty_structs,
+        branch,
         breakpoint,
         bridge,
         bswap,
@@ -411,6 +414,7 @@ symbols! {
         constructor,
         contents,
         context,
+        control_flow_enum,
         convert,
         copy,
         copy_closures,
@@ -511,7 +515,6 @@ symbols! {
         env,
         eq,
         ermsb_target_feature,
-        err,
         exact_div,
         except,
         exchange_malloc,
@@ -581,10 +584,10 @@ symbols! {
         frem_fast,
         from,
         from_desugaring,
-        from_error,
         from_generator,
         from_method,
-        from_ok,
+        from_output,
+        from_residual,
         from_size_align_unchecked,
         from_trait,
         from_usize,
@@ -653,7 +656,6 @@ symbols! {
         instruction_set,
         intel,
         into_iter,
-        into_result,
         into_trait,
         intra_doc_pointers,
         intrinsics,
@@ -965,6 +967,7 @@ symbols! {
         repr_packed,
         repr_simd,
         repr_transparent,
+        residual,
         result,
         result_type,
         rhs,
@@ -1232,7 +1235,7 @@ symbols! {
         try_blocks,
         try_from_trait,
         try_into_trait,
-        try_trait,
+        try_trait_v2,
         tt,
         tuple,
         tuple_from_req,
diff --git a/library/alloc/src/collections/vec_deque/iter.rs b/library/alloc/src/collections/vec_deque/iter.rs
index e4cfb3acdfd..f3eb228c9e3 100644
--- a/library/alloc/src/collections/vec_deque/iter.rs
+++ b/library/alloc/src/collections/vec_deque/iter.rs
@@ -66,7 +66,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
     where
         Self: Sized,
         F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
+        R: Try<Output = B>,
     {
         let (mut iter, final_res);
         if self.tail <= self.head {
@@ -140,7 +140,7 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
     where
         Self: Sized,
         F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
+        R: Try<Output = B>,
     {
         let (mut iter, final_res);
         if self.tail <= self.head {
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 66b1036f2ab..3bc376482e9 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -140,7 +140,8 @@
 #![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_uninit_array)]
 #![feature(alloc_layout_extra)]
 #![feature(trusted_random_access)]
-#![feature(try_trait)]
+#![cfg_attr(bootstrap, feature(try_trait))]
+#![cfg_attr(not(bootstrap), feature(try_trait_v2))]
 #![feature(min_type_alias_impl_trait)]
 #![feature(associated_type_bounds)]
 #![feature(slice_group_by)]
diff --git a/library/core/src/iter/adapters/chain.rs b/library/core/src/iter/adapters/chain.rs
index ce5e9936bbd..53e48500e3b 100644
--- a/library/core/src/iter/adapters/chain.rs
+++ b/library/core/src/iter/adapters/chain.rs
@@ -98,7 +98,7 @@ where
     where
         Self: Sized,
         F: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         if let Some(ref mut a) = self.a {
             acc = a.try_fold(acc, &mut f)?;
@@ -281,7 +281,7 @@ where
     where
         Self: Sized,
         F: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         if let Some(ref mut b) = self.b {
             acc = b.try_rfold(acc, &mut f)?;
diff --git a/library/core/src/iter/adapters/cloned.rs b/library/core/src/iter/adapters/cloned.rs
index 0abdbba2ef1..7efc155175c 100644
--- a/library/core/src/iter/adapters/cloned.rs
+++ b/library/core/src/iter/adapters/cloned.rs
@@ -46,7 +46,7 @@ where
     where
         Self: Sized,
         F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
+        R: Try<Output = B>,
     {
         self.it.try_fold(init, clone_try_fold(f))
     }
@@ -82,7 +82,7 @@ where
     where
         Self: Sized,
         F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
+        R: Try<Output = B>,
     {
         self.it.try_rfold(init, clone_try_fold(f))
     }
diff --git a/library/core/src/iter/adapters/copied.rs b/library/core/src/iter/adapters/copied.rs
index 0a5822452a3..def24089275 100644
--- a/library/core/src/iter/adapters/copied.rs
+++ b/library/core/src/iter/adapters/copied.rs
@@ -50,7 +50,7 @@ where
     where
         Self: Sized,
         F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
+        R: Try<Output = B>,
     {
         self.it.try_fold(init, copy_try_fold(f))
     }
@@ -98,7 +98,7 @@ where
     where
         Self: Sized,
         F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
+        R: Try<Output = B>,
     {
         self.it.try_rfold(init, copy_try_fold(f))
     }
diff --git a/library/core/src/iter/adapters/cycle.rs b/library/core/src/iter/adapters/cycle.rs
index 6e9a011f819..815e708f9ec 100644
--- a/library/core/src/iter/adapters/cycle.rs
+++ b/library/core/src/iter/adapters/cycle.rs
@@ -53,7 +53,7 @@ where
     fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
     where
         F: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         // fully iterate the current iterator. this is necessary because
         // `self.iter` may be empty even when `self.orig` isn't
diff --git a/library/core/src/iter/adapters/enumerate.rs b/library/core/src/iter/adapters/enumerate.rs
index 73cee1df30c..91722a4b62a 100644
--- a/library/core/src/iter/adapters/enumerate.rs
+++ b/library/core/src/iter/adapters/enumerate.rs
@@ -71,7 +71,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         #[inline]
         fn enumerate<'a, T, Acc, R>(
@@ -150,7 +150,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         // Can safely add and subtract the count, as `ExactSizeIterator` promises
         // that the number of elements fits into a `usize`.
diff --git a/library/core/src/iter/adapters/filter.rs b/library/core/src/iter/adapters/filter.rs
index 0337892b9e8..d5f19f12747 100644
--- a/library/core/src/iter/adapters/filter.rs
+++ b/library/core/src/iter/adapters/filter.rs
@@ -37,7 +37,7 @@ fn filter_fold<T, Acc>(
     move |acc, item| if predicate(&item) { fold(acc, item) } else { acc }
 }
 
-fn filter_try_fold<'a, T, Acc, R: Try<Ok = Acc>>(
+fn filter_try_fold<'a, T, Acc, R: Try<Output = Acc>>(
     predicate: &'a mut impl FnMut(&T) -> bool,
     mut fold: impl FnMut(Acc, T) -> R + 'a,
 ) -> impl FnMut(Acc, T) -> R + 'a {
@@ -88,7 +88,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         self.iter.try_fold(init, filter_try_fold(&mut self.predicate, fold))
     }
@@ -117,7 +117,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         self.iter.try_rfold(init, filter_try_fold(&mut self.predicate, fold))
     }
diff --git a/library/core/src/iter/adapters/filter_map.rs b/library/core/src/iter/adapters/filter_map.rs
index 0dccf2c533b..01b7be9d52d 100644
--- a/library/core/src/iter/adapters/filter_map.rs
+++ b/library/core/src/iter/adapters/filter_map.rs
@@ -39,7 +39,7 @@ fn filter_map_fold<T, B, Acc>(
     }
 }
 
-fn filter_map_try_fold<'a, T, B, Acc, R: Try<Ok = Acc>>(
+fn filter_map_try_fold<'a, T, B, Acc, R: Try<Output = Acc>>(
     f: &'a mut impl FnMut(T) -> Option<B>,
     mut fold: impl FnMut(Acc, B) -> R + 'a,
 ) -> impl FnMut(Acc, T) -> R + 'a {
@@ -72,7 +72,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         self.iter.try_fold(init, filter_map_try_fold(&mut self.f, fold))
     }
@@ -111,7 +111,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         self.iter.try_rfold(init, filter_map_try_fold(&mut self.f, fold))
     }
diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs
index 0114d7af4f4..3315d346596 100644
--- a/library/core/src/iter/adapters/flatten.rs
+++ b/library/core/src/iter/adapters/flatten.rs
@@ -61,7 +61,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         self.inner.try_fold(init, fold)
     }
@@ -91,7 +91,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         self.inner.try_rfold(init, fold)
     }
@@ -178,7 +178,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         self.inner.try_fold(init, fold)
     }
@@ -208,7 +208,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         self.inner.try_rfold(init, fold)
     }
@@ -293,10 +293,10 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         #[inline]
-        fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
+        fn flatten<'a, T: IntoIterator, Acc, R: Try<Output = Acc>>(
             frontiter: &'a mut Option<T::IntoIter>,
             fold: &'a mut impl FnMut(Acc, T::Item) -> R,
         ) -> impl FnMut(Acc, T) -> R + 'a {
@@ -382,10 +382,10 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         #[inline]
-        fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
+        fn flatten<'a, T: IntoIterator, Acc, R: Try<Output = Acc>>(
             backiter: &'a mut Option<T::IntoIter>,
             fold: &'a mut impl FnMut(Acc, T::Item) -> R,
         ) -> impl FnMut(Acc, T) -> R + 'a
diff --git a/library/core/src/iter/adapters/fuse.rs b/library/core/src/iter/adapters/fuse.rs
index c01f384dec5..aff48b1b220 100644
--- a/library/core/src/iter/adapters/fuse.rs
+++ b/library/core/src/iter/adapters/fuse.rs
@@ -92,7 +92,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         FuseImpl::try_fold(self, acc, fold)
     }
@@ -148,7 +148,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         FuseImpl::try_rfold(self, acc, fold)
     }
@@ -219,7 +219,7 @@ trait FuseImpl<I> {
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>;
+        R: Try<Output = Acc>;
     fn fold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
     where
         Fold: FnMut(Acc, Self::Item) -> Acc;
@@ -238,7 +238,7 @@ trait FuseImpl<I> {
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
         I: DoubleEndedIterator;
     fn rfold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
     where
@@ -305,7 +305,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         if let Some(ref mut iter) = self.iter {
             acc = iter.try_fold(acc, fold)?;
@@ -354,7 +354,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
         I: DoubleEndedIterator,
     {
         if let Some(ref mut iter) = self.iter {
@@ -443,7 +443,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         unchecked!(self).try_fold(init, fold)
     }
@@ -485,7 +485,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
         I: DoubleEndedIterator,
     {
         unchecked!(self).try_rfold(init, fold)
diff --git a/library/core/src/iter/adapters/inspect.rs b/library/core/src/iter/adapters/inspect.rs
index 88f5ee61b6b..36835d12e56 100644
--- a/library/core/src/iter/adapters/inspect.rs
+++ b/library/core/src/iter/adapters/inspect.rs
@@ -87,7 +87,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         self.iter.try_fold(init, inspect_try_fold(&mut self.f, fold))
     }
@@ -117,7 +117,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         self.iter.try_rfold(init, inspect_try_fold(&mut self.f, fold))
     }
diff --git a/library/core/src/iter/adapters/map.rs b/library/core/src/iter/adapters/map.rs
index 2a4b7efd5e6..0bf9f4b0327 100644
--- a/library/core/src/iter/adapters/map.rs
+++ b/library/core/src/iter/adapters/map.rs
@@ -110,7 +110,7 @@ where
     where
         Self: Sized,
         G: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         self.iter.try_fold(init, map_try_fold(&mut self.f, g))
     }
@@ -146,7 +146,7 @@ where
     where
         Self: Sized,
         G: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         self.iter.try_rfold(init, map_try_fold(&mut self.f, g))
     }
diff --git a/library/core/src/iter/adapters/map_while.rs b/library/core/src/iter/adapters/map_while.rs
index 26114d53284..8f89e158804 100644
--- a/library/core/src/iter/adapters/map_while.rs
+++ b/library/core/src/iter/adapters/map_while.rs
@@ -54,7 +54,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         let Self { iter, predicate } = self;
         iter.try_fold(init, |acc, x| match predicate(x) {
diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs
index 4f69b82ba4c..9fdd4fca04c 100644
--- a/library/core/src/iter/adapters/mod.rs
+++ b/library/core/src/iter/adapters/mod.rs
@@ -168,7 +168,7 @@ where
     fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
     where
         F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
+        R: Try<Output = B>,
     {
         let error = &mut *self.error;
         self.iter
diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs
index 21386e28a96..8ee7d0955c6 100644
--- a/library/core/src/iter/adapters/peekable.rs
+++ b/library/core/src/iter/adapters/peekable.rs
@@ -1,5 +1,5 @@
 use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen};
-use crate::ops::Try;
+use crate::ops::{ControlFlow, Try};
 
 /// An iterator with a `peek()` that returns an optional reference to the next
 /// element.
@@ -91,7 +91,7 @@ impl<I: Iterator> Iterator for Peekable<I> {
     where
         Self: Sized,
         F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
+        R: Try<Output = B>,
     {
         let acc = match self.peeked.take() {
             Some(None) => return try { init },
@@ -130,19 +130,42 @@ where
     }
 
     #[inline]
+    #[cfg(not(bootstrap))]
     fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
     where
         Self: Sized,
         F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
+        R: Try<Output = B>,
     {
         match self.peeked.take() {
             Some(None) => try { init },
+            Some(Some(v)) => match self.iter.try_rfold(init, &mut f).branch() {
+                ControlFlow::Continue(acc) => f(acc, v),
+                ControlFlow::Break(r) => {
+                    self.peeked = Some(Some(v));
+                    R::from_residual(r)
+                }
+            },
+            None => self.iter.try_rfold(init, f),
+        }
+    }
+
+    #[inline]
+    #[cfg(bootstrap)]
+    fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
+    where
+        Self: Sized,
+        F: FnMut(B, Self::Item) -> R,
+        R: Try<Output = B>,
+    {
+        let _use_the_import: ControlFlow<()>;
+        match self.peeked.take() {
+            Some(None) => try { init },
             Some(Some(v)) => match self.iter.try_rfold(init, &mut f).into_result() {
                 Ok(acc) => f(acc, v),
                 Err(e) => {
                     self.peeked = Some(Some(v));
-                    Try::from_error(e)
+                    R::from_error(e)
                 }
             },
             None => self.iter.try_rfold(init, f),
diff --git a/library/core/src/iter/adapters/rev.rs b/library/core/src/iter/adapters/rev.rs
index 105ed40a3ed..139fb7bbdd9 100644
--- a/library/core/src/iter/adapters/rev.rs
+++ b/library/core/src/iter/adapters/rev.rs
@@ -51,7 +51,7 @@ where
     where
         Self: Sized,
         F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
+        R: Try<Output = B>,
     {
         self.iter.try_rfold(init, f)
     }
@@ -96,7 +96,7 @@ where
     where
         Self: Sized,
         F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
+        R: Try<Output = B>,
     {
         self.iter.try_fold(init, f)
     }
diff --git a/library/core/src/iter/adapters/scan.rs b/library/core/src/iter/adapters/scan.rs
index 0214899295e..96705b01f66 100644
--- a/library/core/src/iter/adapters/scan.rs
+++ b/library/core/src/iter/adapters/scan.rs
@@ -56,9 +56,9 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
-        fn scan<'a, T, St, B, Acc, R: Try<Ok = Acc>>(
+        fn scan<'a, T, St, B, Acc, R: Try<Output = Acc>>(
             state: &'a mut St,
             f: &'a mut impl FnMut(&mut St, T) -> Option<B>,
             mut fold: impl FnMut(Acc, B) -> R + 'a,
diff --git a/library/core/src/iter/adapters/skip.rs b/library/core/src/iter/adapters/skip.rs
index e55c7a6bf5d..c358a6d12b7 100644
--- a/library/core/src/iter/adapters/skip.rs
+++ b/library/core/src/iter/adapters/skip.rs
@@ -88,7 +88,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         let n = self.n;
         self.n = 0;
@@ -146,9 +146,9 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
-        fn check<T, Acc, R: Try<Ok = Acc>>(
+        fn check<T, Acc, R: Try<Output = Acc>>(
             mut n: usize,
             mut fold: impl FnMut(Acc, T) -> R,
         ) -> impl FnMut(Acc, T) -> ControlFlow<R, Acc> {
diff --git a/library/core/src/iter/adapters/skip_while.rs b/library/core/src/iter/adapters/skip_while.rs
index efcb469fc95..93e29edc8df 100644
--- a/library/core/src/iter/adapters/skip_while.rs
+++ b/library/core/src/iter/adapters/skip_while.rs
@@ -70,7 +70,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         if !self.flag {
             match self.next() {
diff --git a/library/core/src/iter/adapters/step_by.rs b/library/core/src/iter/adapters/step_by.rs
index 2ba56eeccba..4252c34a0e0 100644
--- a/library/core/src/iter/adapters/step_by.rs
+++ b/library/core/src/iter/adapters/step_by.rs
@@ -111,7 +111,7 @@ where
     fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
     where
         F: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         #[inline]
         fn nth<I: Iterator>(iter: &mut I, step: usize) -> impl FnMut() -> Option<I::Item> + '_ {
@@ -187,7 +187,7 @@ where
     fn try_rfold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R
     where
         F: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         #[inline]
         fn nth_back<I: DoubleEndedIterator>(
diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs
index 54a47f1323e..92f82ae2325 100644
--- a/library/core/src/iter/adapters/take.rs
+++ b/library/core/src/iter/adapters/take.rs
@@ -80,9 +80,9 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
-        fn check<'a, T, Acc, R: Try<Ok = Acc>>(
+        fn check<'a, T, Acc, R: Try<Output = Acc>>(
             n: &'a mut usize,
             mut fold: impl FnMut(Acc, T) -> R + 'a,
         ) -> impl FnMut(Acc, T) -> ControlFlow<R, Acc> + 'a {
@@ -178,7 +178,7 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
         if self.n == 0 {
             try { init }
diff --git a/library/core/src/iter/adapters/take_while.rs b/library/core/src/iter/adapters/take_while.rs
index 746eb41f4c3..93457d20f7c 100644
--- a/library/core/src/iter/adapters/take_while.rs
+++ b/library/core/src/iter/adapters/take_while.rs
@@ -68,9 +68,9 @@ where
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: Try<Ok = Acc>,
+        R: Try<Output = Acc>,
     {
-        fn check<'a, T, Acc, R: Try<Ok = Acc>>(
+        fn check<'a, T, Acc, R: Try<Output = Acc>>(
             flag: &'a mut bool,
             p: &'a mut impl FnMut(&T) -> bool,
             mut fold: impl FnMut(Acc, T) -> R + 'a,
diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs
index 5e39e71252f..8d0b2b9f55c 100644
--- a/library/core/src/iter/range.rs
+++ b/library/core/src/iter/range.rs
@@ -755,7 +755,7 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
     where
         Self: Sized,
         F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
+        R: Try<Output = B>,
     {
         if self.is_empty() {
             return try { init };
@@ -860,7 +860,7 @@ impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
     where
         Self: Sized,
         F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
+        R: Try<Output = B>,
     {
         if self.is_empty() {
             return try { init };
diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs
index 6f8cb6b5a65..c302502b3b7 100644
--- a/library/core/src/iter/traits/double_ended.rs
+++ b/library/core/src/iter/traits/double_ended.rs
@@ -218,7 +218,7 @@ pub trait DoubleEndedIterator: Iterator {
     where
         Self: Sized,
         F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
+        R: Try<Output = B>,
     {
         let mut accum = init;
         while let Some(x) = self.next_back() {
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index da9e5fde7cc..777e4bc2c89 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -1999,7 +1999,7 @@ pub trait Iterator {
     where
         Self: Sized,
         F: FnMut(B, Self::Item) -> R,
-        R: Try<Ok = B>,
+        R: Try<Output = B>,
     {
         let mut accum = init;
         while let Some(x) = self.next() {
@@ -2041,7 +2041,7 @@ pub trait Iterator {
     where
         Self: Sized,
         F: FnMut(Self::Item) -> R,
-        R: Try<Ok = ()>,
+        R: Try<Output = ()>,
     {
         #[inline]
         fn call<T, R>(mut f: impl FnMut(T) -> R) -> impl FnMut((), T) -> R {
@@ -2412,17 +2412,48 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[unstable(feature = "try_find", reason = "new API", issue = "63178")]
+    #[cfg(not(bootstrap))]
+    fn try_find<F, R, E>(&mut self, f: F) -> Result<Option<Self::Item>, E>
+    where
+        Self: Sized,
+        F: FnMut(&Self::Item) -> R,
+        R: Try<Output = bool>,
+        // FIXME: This bound is rather strange, but means minimal breakage on nightly.
+        // See #85115 for the issue tracking a holistic solution for this and try_map.
+        R: crate::ops::TryV2<Residual = Result<crate::convert::Infallible, E>>,
+    {
+        #[inline]
+        fn check<F, T, R, E>(mut f: F) -> impl FnMut((), T) -> ControlFlow<Result<T, E>>
+        where
+            F: FnMut(&T) -> R,
+            R: Try<Output = bool>,
+            R: crate::ops::TryV2<Residual = Result<crate::convert::Infallible, E>>,
+        {
+            move |(), x| match f(&x).branch() {
+                ControlFlow::Continue(false) => ControlFlow::CONTINUE,
+                ControlFlow::Continue(true) => ControlFlow::Break(Ok(x)),
+                ControlFlow::Break(Err(x)) => ControlFlow::Break(Err(x)),
+            }
+        }
+
+        self.try_fold((), check(f)).break_value().transpose()
+    }
+
+    /// We're bootstrapping.
+    #[inline]
+    #[unstable(feature = "try_find", reason = "new API", issue = "63178")]
+    #[cfg(bootstrap)]
     fn try_find<F, R>(&mut self, f: F) -> Result<Option<Self::Item>, R::Error>
     where
         Self: Sized,
         F: FnMut(&Self::Item) -> R,
-        R: Try<Ok = bool>,
+        R: Try<Output = bool>,
     {
         #[inline]
         fn check<F, T, R>(mut f: F) -> impl FnMut((), T) -> ControlFlow<Result<T, R::Error>>
         where
             F: FnMut(&T) -> R,
-            R: Try<Ok = bool>,
+            R: Try<Output = bool>,
         {
             move |(), x| match f(&x).into_result() {
                 Ok(false) => ControlFlow::CONTINUE,
diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs
index ecaff053bd5..dbb51540bd4 100644
--- a/library/core/src/ops/control_flow.rs
+++ b/library/core/src/ops/control_flow.rs
@@ -1,5 +1,4 @@
-use crate::convert;
-use crate::ops::{self, Try};
+use crate::{convert, ops};
 
 /// Used to tell an operation whether it should exit early or go on as usual.
 ///
@@ -53,8 +52,10 @@ use crate::ops::{self, Try};
 #[derive(Debug, Clone, Copy, PartialEq)]
 pub enum ControlFlow<B, C = ()> {
     /// Move on to the next phase of the operation as normal.
+    #[cfg_attr(not(bootstrap), lang = "Continue")]
     Continue(C),
     /// Exit the operation without running subsequent phases.
+    #[cfg_attr(not(bootstrap), lang = "Break")]
     Break(B),
     // Yes, the order of the variants doesn't match the type parameters.
     // They're in this order so that `ControlFlow<A, B>` <-> `Result<B, A>`
@@ -62,11 +63,11 @@ pub enum ControlFlow<B, C = ()> {
 }
 
 #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
-impl<B, C> Try for ControlFlow<B, C> {
-    type Ok = C;
+impl<B, C> ops::TryV1 for ControlFlow<B, C> {
+    type Output = C;
     type Error = B;
     #[inline]
-    fn into_result(self) -> Result<Self::Ok, Self::Error> {
+    fn into_result(self) -> Result<Self::Output, Self::Error> {
         match self {
             ControlFlow::Continue(y) => Ok(y),
             ControlFlow::Break(x) => Err(x),
@@ -77,7 +78,7 @@ impl<B, C> Try for ControlFlow<B, C> {
         ControlFlow::Break(v)
     }
     #[inline]
-    fn from_ok(v: Self::Ok) -> Self {
+    fn from_ok(v: Self::Output) -> Self {
         ControlFlow::Continue(v)
     }
 }
@@ -182,14 +183,38 @@ impl<B, C> ControlFlow<B, C> {
     }
 }
 
-impl<R: Try> ControlFlow<R, R::Ok> {
+#[cfg(bootstrap)]
+impl<R: ops::TryV1> ControlFlow<R, R::Output> {
     /// Create a `ControlFlow` from any type implementing `Try`.
     #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
     #[inline]
     pub fn from_try(r: R) -> Self {
-        match Try::into_result(r) {
+        match R::into_result(r) {
             Ok(v) => ControlFlow::Continue(v),
-            Err(v) => ControlFlow::Break(Try::from_error(v)),
+            Err(v) => ControlFlow::Break(R::from_error(v)),
+        }
+    }
+
+    /// Convert a `ControlFlow` into any type implementing `Try`;
+    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
+    #[inline]
+    pub fn into_try(self) -> R {
+        match self {
+            ControlFlow::Continue(v) => R::from_ok(v),
+            ControlFlow::Break(v) => v,
+        }
+    }
+}
+
+#[cfg(not(bootstrap))]
+impl<R: ops::TryV2> ControlFlow<R, R::Output> {
+    /// Create a `ControlFlow` from any type implementing `Try`.
+    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
+    #[inline]
+    pub fn from_try(r: R) -> Self {
+        match R::branch(r) {
+            ControlFlow::Continue(v) => ControlFlow::Continue(v),
+            ControlFlow::Break(v) => ControlFlow::Break(R::from_residual(v)),
         }
     }
 
@@ -198,7 +223,7 @@ impl<R: Try> ControlFlow<R, R::Ok> {
     #[inline]
     pub fn into_try(self) -> R {
         match self {
-            ControlFlow::Continue(v) => Try::from_ok(v),
+            ControlFlow::Continue(v) => R::from_output(v),
             ControlFlow::Break(v) => v,
         }
     }
diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs
index 1b07936ccde..beef74de617 100644
--- a/library/core/src/ops/mod.rs
+++ b/library/core/src/ops/mod.rs
@@ -183,13 +183,21 @@ pub use self::range::{Range, RangeFrom, RangeFull, RangeTo};
 pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive};
 
 #[unstable(feature = "try_trait", issue = "42327")]
+#[cfg(bootstrap)]
 pub use self::r#try::Try;
 
+#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")]
+pub(crate) use self::r#try::Try as TryV1;
+
 #[unstable(feature = "try_trait_v2", issue = "84277")]
 pub use self::try_trait::FromResidual;
 
+#[unstable(feature = "try_trait_v2", issue = "84277")]
+#[cfg(not(bootstrap))]
+pub use self::try_trait::Try;
+
 #[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")]
-pub use self::try_trait::Try as TryV2;
+pub(crate) use self::try_trait::Try as TryV2;
 
 #[unstable(feature = "generator_trait", issue = "43122")]
 pub use self::generator::{Generator, GeneratorState};
diff --git a/library/core/src/ops/try.rs b/library/core/src/ops/try.rs
index 3bede569978..9d659e78d3c 100644
--- a/library/core/src/ops/try.rs
+++ b/library/core/src/ops/try.rs
@@ -25,11 +25,11 @@
     )
 )]
 #[doc(alias = "?")]
-#[lang = "try"]
+#[cfg_attr(bootstrap, lang = "try")]
 pub trait Try {
     /// The type of this value when viewed as successful.
     #[unstable(feature = "try_trait", issue = "42327")]
-    type Ok;
+    type Output; // This no longer follows its RFC, but is only used in bootstrap.
     /// The type of this value when viewed as failed.
     #[unstable(feature = "try_trait", issue = "42327")]
     type Error;
@@ -43,19 +43,19 @@ pub trait Try {
     /// in the return type of the enclosing scope (which must itself implement
     /// `Try`). Specifically, the value `X::from_error(From::from(e))`
     /// is returned, where `X` is the return type of the enclosing function.
-    #[lang = "into_result"]
+    #[cfg_attr(bootstrap, lang = "into_result")]
     #[unstable(feature = "try_trait", issue = "42327")]
-    fn into_result(self) -> Result<Self::Ok, Self::Error>;
+    fn into_result(self) -> Result<Self::Output, Self::Error>;
 
     /// Wrap an error value to construct the composite result. For example,
     /// `Result::Err(x)` and `Result::from_error(x)` are equivalent.
-    #[lang = "from_error"]
+    #[cfg_attr(bootstrap, lang = "from_error")]
     #[unstable(feature = "try_trait", issue = "42327")]
     fn from_error(v: Self::Error) -> Self;
 
     /// Wrap an OK value to construct the composite result. For example,
     /// `Result::Ok(x)` and `Result::from_ok(x)` are equivalent.
-    #[lang = "from_ok"]
+    #[cfg_attr(bootstrap, lang = "from_ok")]
     #[unstable(feature = "try_trait", issue = "42327")]
-    fn from_ok(v: Self::Ok) -> Self;
+    fn from_ok(v: Self::Output) -> Self;
 }
diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs
index 0c819b000aa..87044ed2fce 100644
--- a/library/core/src/ops/try_trait.rs
+++ b/library/core/src/ops/try_trait.rs
@@ -41,8 +41,7 @@ use crate::ops::ControlFlow;
 /// output type that we want:
 /// ```
 /// # #![feature(try_trait_v2)]
-/// # #![feature(try_trait_transition)]
-/// # use std::ops::TryV2 as Try;
+/// # use std::ops::Try;
 /// fn simple_try_fold_1<A, T, R: Try<Output = A>>(
 ///     iter: impl Iterator<Item = T>,
 ///     mut accum: A,
@@ -56,9 +55,8 @@ use crate::ops::ControlFlow;
 /// into the return type using [`Try::from_output`]:
 /// ```
 /// # #![feature(try_trait_v2)]
-/// # #![feature(try_trait_transition)]
 /// # #![feature(control_flow_enum)]
-/// # use std::ops::{ControlFlow, TryV2 as Try};
+/// # use std::ops::{ControlFlow, Try};
 /// fn simple_try_fold_2<A, T, R: Try<Output = A>>(
 ///     iter: impl Iterator<Item = T>,
 ///     mut accum: A,
@@ -81,9 +79,8 @@ use crate::ops::ControlFlow;
 /// recreated from their corresponding residual, so we'll just call it:
 /// ```
 /// # #![feature(try_trait_v2)]
-/// # #![feature(try_trait_transition)]
 /// # #![feature(control_flow_enum)]
-/// # use std::ops::{ControlFlow, TryV2 as Try};
+/// # use std::ops::{ControlFlow, Try};
 /// pub fn simple_try_fold_3<A, T, R: Try<Output = A>>(
 ///     iter: impl Iterator<Item = T>,
 ///     mut accum: A,
@@ -103,10 +100,9 @@ use crate::ops::ControlFlow;
 /// But this "call `branch`, then `match` on it, and `return` if it was a
 /// `Break`" is exactly what happens inside the `?` operator.  So rather than
 /// do all this manually, we can just use `?` instead:
-/// ```compile_fail (enable again once ? converts to the new trait)
+/// ```
 /// # #![feature(try_trait_v2)]
-/// # #![feature(try_trait_transition)]
-/// # use std::ops::TryV2 as Try;
+/// # use std::ops::Try;
 /// fn simple_try_fold<A, T, R: Try<Output = A>>(
 ///     iter: impl Iterator<Item = T>,
 ///     mut accum: A,
@@ -119,6 +115,22 @@ use crate::ops::ControlFlow;
 /// }
 /// ```
 #[unstable(feature = "try_trait_v2", issue = "84277")]
+#[rustc_on_unimplemented(
+    on(
+        all(from_method = "from_output", from_desugaring = "TryBlock"),
+        message = "a `try` block must return `Result` or `Option` \
+                    (or another type that implements `{Try}`)",
+        label = "could not wrap the final value of the block as `{Self}` doesn't implement `Try`",
+    ),
+    on(
+        all(from_method = "branch", from_desugaring = "QuestionMark"),
+        message = "the `?` operator can only be applied to values \
+                    that implement `{Try}`",
+        label = "the `?` operator cannot be applied to type `{Self}`"
+    )
+)]
+#[doc(alias = "?")]
+#[cfg_attr(not(bootstrap), lang = "Try")]
 pub trait Try: FromResidual {
     /// The type of the value produced by `?` when *not* short-circuiting.
     #[unstable(feature = "try_trait_v2", issue = "84277")]
@@ -159,8 +171,7 @@ pub trait Try: FromResidual {
     /// ```
     /// #![feature(try_trait_v2)]
     /// #![feature(control_flow_enum)]
-    /// #![feature(try_trait_transition)]
-    /// use std::ops::TryV2 as Try;
+    /// use std::ops::Try;
     ///
     /// assert_eq!(<Result<_, String> as Try>::from_output(3), Ok(3));
     /// assert_eq!(<Option<_> as Try>::from_output(4), Some(4));
@@ -178,6 +189,7 @@ pub trait Try: FromResidual {
     /// let r = std::iter::empty().try_fold(4, |_, ()| -> Option<_> { unreachable!() });
     /// assert_eq!(r, Some(4));
     /// ```
+    #[cfg_attr(not(bootstrap), lang = "from_output")]
     #[unstable(feature = "try_trait_v2", issue = "84277")]
     fn from_output(output: Self::Output) -> Self;
 
@@ -191,8 +203,7 @@ pub trait Try: FromResidual {
     /// ```
     /// #![feature(try_trait_v2)]
     /// #![feature(control_flow_enum)]
-    /// #![feature(try_trait_transition)]
-    /// use std::ops::{ControlFlow, TryV2 as Try};
+    /// use std::ops::{ControlFlow, Try};
     ///
     /// assert_eq!(Ok::<_, String>(3).branch(), ControlFlow::Continue(3));
     /// assert_eq!(Err::<String, _>(3).branch(), ControlFlow::Break(Err(3)));
@@ -206,15 +217,80 @@ pub trait Try: FromResidual {
     ///     ControlFlow::Break(ControlFlow::Break(3)),
     /// );
     /// ```
+    #[cfg_attr(not(bootstrap), lang = "branch")]
     #[unstable(feature = "try_trait_v2", issue = "84277")]
     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
 }
 
-/// Used to specify which residuals can be converted into which [`Try`] types.
+/// Used to specify which residuals can be converted into which [`crate::ops::Try`] types.
 ///
 /// Every `Try` type needs to be recreatable from its own associated
 /// `Residual` type, but can also have additional `FromResidual` implementations
 /// to support interconversion with other `Try` types.
+#[rustc_on_unimplemented(
+    on(
+        all(
+            from_method = "from_residual",
+            from_desugaring = "QuestionMark",
+            _Self = "std::result::Result<T, E>",
+            R = "std::option::Option<std::convert::Infallible>"
+        ),
+        message = "the `?` operator can only be used on `Result`s, not `Option`s, \
+            in {ItemContext} that returns `Result`",
+        label = "use `.ok_or(...)?` to provide an error compatible with `{Self}`",
+        enclosing_scope = "this function returns a `Result`"
+    ),
+    on(
+        all(
+            from_method = "from_residual",
+            from_desugaring = "QuestionMark",
+            _Self = "std::result::Result<T, E>",
+        ),
+        // There's a special error message in the trait selection code for
+        // `From` in `?`, so this is not shown for result-in-result errors,
+        // and thus it can be phrased more strongly than `ControlFlow`'s.
+        message = "the `?` operator can only be used on `Result`s \
+            in {ItemContext} that returns `Result`",
+        label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
+        enclosing_scope = "this function returns a `Result`"
+    ),
+    on(
+        all(
+            from_method = "from_residual",
+            from_desugaring = "QuestionMark",
+            _Self = "std::option::Option<T>",
+        ),
+        // `Option`-in-`Option` always works, as there's only one possible
+        // residual, so this can also be phrased strongly.
+        message = "the `?` operator can only be used on `Option`s \
+            in {ItemContext} that returns `Option`",
+        label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
+        enclosing_scope = "this function returns an `Option`"
+    ),
+    on(
+        all(
+            from_method = "from_residual",
+            from_desugaring = "QuestionMark",
+            _Self = "std::ops::ControlFlow<B, C>",
+        ),
+        message = "the `?` operator can only be used on `ControlFlow<B, _>`s \
+            in {ItemContext} that returns `ControlFlow<B, _>`",
+        label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
+        enclosing_scope = "this function returns a `ControlFlow`",
+        note = "unlike `Result`, there's no `From`-conversion performed for `ControlFlow`"
+    ),
+    on(
+        all(
+            from_method = "from_residual",
+            from_desugaring = "QuestionMark"
+        ),
+        message = "the `?` operator can only be used in {ItemContext} \
+                    that returns `Result` or `Option` \
+                    (or another type that implements `{FromResidual}`)",
+        label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`",
+        enclosing_scope = "this function should return `Result` or `Option` to accept `?`"
+    ),
+)]
 #[unstable(feature = "try_trait_v2", issue = "84277")]
 pub trait FromResidual<R = <Self as Try>::Residual> {
     /// Constructs the type from a compatible `Residual` type.
@@ -238,6 +314,7 @@ pub trait FromResidual<R = <Self as Try>::Residual> {
     ///     ControlFlow::Break(5),
     /// );
     /// ```
+    #[cfg_attr(not(bootstrap), lang = "from_residual")]
     #[unstable(feature = "try_trait_v2", issue = "84277")]
     fn from_residual(residual: R) -> Self;
 }
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 04551dded8c..c5b1c804ead 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -1644,8 +1644,8 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
 pub struct NoneError;
 
 #[unstable(feature = "try_trait", issue = "42327")]
-impl<T> ops::Try for Option<T> {
-    type Ok = T;
+impl<T> ops::TryV1 for Option<T> {
+    type Output = T;
     type Error = NoneError;
 
     #[inline]
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index e0071f806aa..21e406194bc 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -1627,8 +1627,8 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
 }
 
 #[unstable(feature = "try_trait", issue = "42327")]
-impl<T, E> ops::Try for Result<T, E> {
-    type Ok = T;
+impl<T, E> ops::TryV1 for Result<T, E> {
+    type Output = T;
     type Error = E;
 
     #[inline]
diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs
index 906dcb1e8bc..b92ab7e3475 100644
--- a/library/core/src/slice/ascii.rs
+++ b/library/core/src/slice/ascii.rs
@@ -110,7 +110,7 @@ impl<'a> iter::Iterator for EscapeAscii<'a> {
     fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
     where
         Fold: FnMut(Acc, Self::Item) -> R,
-        R: ops::Try<Ok = Acc>,
+        R: ops::Try<Output = Acc>,
     {
         self.inner.try_fold(init, fold)
     }
diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs
index 724137aba9f..6ec6b70b571 100644
--- a/library/core/src/str/iter.rs
+++ b/library/core/src/str/iter.rs
@@ -1467,7 +1467,7 @@ macro_rules! escape_types_impls {
 
             #[inline]
             fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
-                Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
+                Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Output = Acc>
             {
                 self.inner.try_fold(init, fold)
             }
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
index 2765c21a46d..188639e7962 100644
--- a/library/core/src/task/poll.rs
+++ b/library/core/src/task/poll.rs
@@ -1,7 +1,7 @@
 #![stable(feature = "futures_api", since = "1.36.0")]
 
 use crate::convert;
-use crate::ops::{self, ControlFlow, Try};
+use crate::ops::{self, ControlFlow};
 use crate::result::Result;
 
 /// Indicates whether a value is available or if the current task has been
@@ -129,12 +129,12 @@ impl<T> From<T> for Poll<T> {
 }
 
 #[stable(feature = "futures_api", since = "1.36.0")]
-impl<T, E> Try for Poll<Result<T, E>> {
-    type Ok = Poll<T>;
+impl<T, E> ops::TryV1 for Poll<Result<T, E>> {
+    type Output = Poll<T>;
     type Error = E;
 
     #[inline]
-    fn into_result(self) -> Result<Self::Ok, Self::Error> {
+    fn into_result(self) -> Result<Self::Output, Self::Error> {
         match self {
             Poll::Ready(Ok(x)) => Ok(Poll::Ready(x)),
             Poll::Ready(Err(e)) => Err(e),
@@ -148,7 +148,7 @@ impl<T, E> Try for Poll<Result<T, E>> {
     }
 
     #[inline]
-    fn from_ok(x: Self::Ok) -> Self {
+    fn from_ok(x: Self::Output) -> Self {
         x.map(Ok)
     }
 }
@@ -184,12 +184,12 @@ impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>> for Pol
 }
 
 #[stable(feature = "futures_api", since = "1.36.0")]
-impl<T, E> Try for Poll<Option<Result<T, E>>> {
-    type Ok = Poll<Option<T>>;
+impl<T, E> ops::TryV1 for Poll<Option<Result<T, E>>> {
+    type Output = Poll<Option<T>>;
     type Error = E;
 
     #[inline]
-    fn into_result(self) -> Result<Self::Ok, Self::Error> {
+    fn into_result(self) -> Result<Self::Output, Self::Error> {
         match self {
             Poll::Ready(Some(Ok(x))) => Ok(Poll::Ready(Some(x))),
             Poll::Ready(Some(Err(e))) => Err(e),
@@ -204,7 +204,7 @@ impl<T, E> Try for Poll<Option<Result<T, E>>> {
     }
 
     #[inline]
-    fn from_ok(x: Self::Ok) -> Self {
+    fn from_ok(x: Self::Output) -> Self {
         x.map(|x| x.map(Ok))
     }
 }
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 35e4d213dde..db12d79c00c 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -45,6 +45,7 @@
 #![feature(test)]
 #![feature(trusted_len)]
 #![feature(try_trait)]
+#![feature(try_trait_v2)]
 #![feature(slice_internals)]
 #![feature(slice_partition_dedup)]
 #![feature(int_error_matching)]
diff --git a/library/core/tests/option.rs b/library/core/tests/option.rs
index 9470451278c..88ea15a3b33 100644
--- a/library/core/tests/option.rs
+++ b/library/core/tests/option.rs
@@ -301,18 +301,6 @@ fn test_try() {
         Some(val)
     }
     assert_eq!(try_option_none(), None);
-
-    fn try_option_ok() -> Result<u8, NoneError> {
-        let val = Some(1)?;
-        Ok(val)
-    }
-    assert_eq!(try_option_ok(), Ok(1));
-
-    fn try_option_err() -> Result<u8, NoneError> {
-        let val = None?;
-        Ok(val)
-    }
-    assert_eq!(try_option_err(), Err(NoneError));
 }
 
 #[test]
diff --git a/library/core/tests/result.rs b/library/core/tests/result.rs
index c461ab380ad..f4e5e7751b8 100644
--- a/library/core/tests/result.rs
+++ b/library/core/tests/result.rs
@@ -249,26 +249,14 @@ pub fn test_into_err() {
 
 #[test]
 fn test_try() {
-    fn try_result_some() -> Option<u8> {
-        let val = Ok(1)?;
-        Some(val)
-    }
-    assert_eq!(try_result_some(), Some(1));
-
-    fn try_result_none() -> Option<u8> {
-        let val = Err(NoneError)?;
-        Some(val)
-    }
-    assert_eq!(try_result_none(), None);
-
-    fn try_result_ok() -> Result<u8, u8> {
+    fn try_result_ok() -> Result<u8, u32> {
         let result: Result<u8, u8> = Ok(1);
         let val = result?;
         Ok(val)
     }
     assert_eq!(try_result_ok(), Ok(1));
 
-    fn try_result_err() -> Result<u8, u8> {
+    fn try_result_err() -> Result<u8, u32> {
         let result: Result<u8, u8> = Err(1);
         let val = result?;
         Ok(val)
@@ -401,3 +389,17 @@ fn result_opt_conversions() {
 
     assert_eq!(res, Err(BadNumErr))
 }
+
+#[test]
+#[cfg(not(bootstrap))] // Needs the V2 trait
+fn result_try_trait_v2_branch() {
+    use core::num::NonZeroU32;
+    use core::ops::{ControlFlow::*, Try};
+    assert_eq!(Ok::<i32, i32>(4).branch(), Continue(4));
+    assert_eq!(Err::<i32, i32>(4).branch(), Break(Err(4)));
+    let one = NonZeroU32::new(1).unwrap();
+    assert_eq!(Ok::<(), NonZeroU32>(()).branch(), Continue(()));
+    assert_eq!(Err::<(), NonZeroU32>(one).branch(), Break(Err(one)));
+    assert_eq!(Ok::<NonZeroU32, ()>(one).branch(), Continue(one));
+    assert_eq!(Err::<NonZeroU32, ()>(()).branch(), Break(Err(())));
+}
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);
                     }