From 0b12d0dac78617040b38c35175364ab43fb4998d Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Mon, 14 Dec 2020 14:52:16 -0800 Subject: [PATCH 01/10] PoC: A new hybrid design for Try --- compiler/rustc_ast_lowering/src/expr.rs | 54 ++++----- compiler/rustc_ast_lowering/src/lib.rs | 28 +++-- compiler/rustc_hir/src/lang_items.rs | 6 + .../src/ty/query/on_disk_cache.rs | 2 +- compiler/rustc_span/src/symbol.rs | 8 ++ compiler/rustc_typeck/src/check/expr.rs | 2 +- library/alloc/src/lib.rs | 1 + library/core/src/iter/adapters/peekable.rs | 24 ++++ library/core/src/iter/traits/iterator.rs | 58 ++++++++- library/core/src/ops/control_flow.rs | 67 ++++++++++- library/core/src/ops/mod.rs | 12 +- library/core/src/ops/try.rs | 113 +++++++++++++++++- library/core/src/option.rs | 44 ++++++- library/core/src/result.rs | 69 ++++++++++- library/core/src/task/poll.rs | 111 ++++++++++++++++- library/core/tests/option.rs | 12 -- library/core/tests/result.rs | 12 -- src/test/ui/async-await/issue-61076.rs | 17 +-- src/test/ui/async-await/issue-61076.stderr | 30 ++--- .../async-await/try-on-option-in-async.stderr | 18 +-- ...infer-async-enabled-impl-trait-bindings.rs | 4 +- ...r-async-enabled-impl-trait-bindings.stderr | 11 +- src/test/ui/inference/cannot-infer-async.rs | 4 +- .../ui/inference/cannot-infer-async.stderr | 9 +- src/test/ui/inference/cannot-infer-closure.rs | 4 +- .../ui/inference/cannot-infer-closure.stderr | 13 +- .../cannot-infer-partial-try-return.stderr | 3 +- src/test/ui/issues/issue-32709.stderr | 12 +- src/test/ui/option-to-result.rs | 4 +- src/test/ui/option-to-result.stderr | 41 +++---- src/test/ui/question-mark-type-infer.stderr | 4 +- .../disallowed-positions.rs | 12 +- .../disallowed-positions.stderr | 54 ++++----- src/test/ui/suggestions/issue-72766.stderr | 10 +- src/test/ui/try-block/try-block-bad-type.rs | 8 +- .../ui/try-block/try-block-bad-type.stderr | 21 ++-- src/test/ui/try-block/try-block-in-while.rs | 2 +- .../ui/try-block/try-block-in-while.stderr | 6 +- .../ui/try-block/try-block-type-error.stderr | 4 +- src/test/ui/try-on-option-diagnostics.stderr | 16 +-- src/test/ui/try-on-option-in-result-method.rs | 20 ++++ src/test/ui/try-on-option.rs | 2 +- src/test/ui/try-on-option.stderr | 23 ++-- src/test/ui/try-operator-custom.rs | 56 ++++++++- src/test/ui/try-operator-on-main.rs | 10 +- src/test/ui/try-operator-on-main.stderr | 50 +++++--- 46 files changed, 808 insertions(+), 283 deletions(-) create mode 100644 src/test/ui/try-on-option-in-result-method.rs diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index b118c0eaed4f3..509f597780ac8 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -462,8 +462,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ) } - /// Desugar `try { ; }` into `{ ; ::std::ops::Try::from_ok() }`, - /// `try { ; }` into `{ ; ::std::ops::Try::from_ok(()) }` + /// Desugar `try { ; }` into `{ ; ::std::ops::Try::continue_with() }`, + /// `try { ; }` into `{ ; ::std::ops::Try::continue_with(()) }` /// 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| { @@ -492,9 +492,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::continue_with($tail_expr)` block.expr = Some(this.wrap_in_try_constructor( - hir::LangItem::TryFromOk, + hir::LangItem::TryContinueWith, try_span, tail_expr, ok_wrapped_span, @@ -1793,14 +1793,14 @@ impl<'hir> LoweringContext<'_, 'hir> { self.allow_try_trait.clone(), ); - // `Try::into_result()` + // `Try::branch()` let scrutinee = { // expand let sub_expr = self.lower_expr_mut(sub_expr); self.expr_call_lang_item_fn( unstable_span, - hir::LangItem::TryIntoResult, + hir::LangItem::TryBranch, arena_vec![self; sub_expr], ) }; @@ -1818,8 +1818,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( @@ -1828,27 +1828,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)] + // `ControlFlow::Break(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, + let break_arm = { + let holder_ident = Ident::with_dummy_span(sym::holder); + let (holder_local, holder_local_nid) = self.pat_ident(try_span, holder_ident); + let holder_expr = + self.arena.alloc(self.expr_ident_mut(try_span, holder_ident, holder_local_nid)); + let from_holder_expr = self.wrap_in_try_constructor( + hir::LangItem::FromHolder, unstable_span, - from_expr, + holder_expr, unstable_span, ); let thin_attrs = ThinVec::from(attrs); @@ -1859,25 +1853,25 @@ impl<'hir> LoweringContext<'_, 'hir> { try_span, hir::ExprKind::Break( hir::Destination { label: None, target_id }, - Some(from_err_expr), + Some(from_holder_expr), ), thin_attrs, )) } else { self.arena.alloc(self.expr( try_span, - hir::ExprKind::Ret(Some(from_err_expr)), + hir::ExprKind::Ret(Some(from_holder_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(unstable_span, holder_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 05b417effd491..fa81682ccfcb5 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -324,7 +324,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::try_trait, sym::try_trait_v2, sym::control_flow_enum][..].into()), allow_gen_future: Some([sym::gen_future][..].into()), } .lower_crate(krate) @@ -2546,15 +2546,15 @@ 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> { - let field = self.single_pat_field(span, pat); - self.pat_lang_item_variant(span, hir::LangItem::ResultOk, field) - } + // fn pat_ok(&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) + // } - fn pat_err(&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) - } + // fn pat_err(&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) + // } fn pat_some(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> { let field = self.single_pat_field(span, pat); @@ -2565,6 +2565,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.pat_lang_item_variant(span, hir::LangItem::OptionNone, &[]) } + 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::ControlFlowContinue, field) + } + + 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::ControlFlowBreak, field) + } + fn single_pat_field( &mut self, span: Span, diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 03524569ce7a9..8620e043a057f 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -306,6 +306,9 @@ language_item_table! { 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 }); + TryContinueWith, sym::continue_with, continue_with_fn, Target::Method(MethodKind::Trait { body: false }); + TryBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }); + FromHolder, sym::from_holder, from_holder_fn, Target::Method(MethodKind::Trait { body: false }); PollReady, sym::Ready, poll_ready_variant, Target::Variant; PollPending, sym::Pending, poll_pending_variant, Target::Variant; @@ -323,6 +326,9 @@ language_item_table! { ResultOk, sym::Ok, result_ok_variant, Target::Variant; ResultErr, sym::Err, result_err_variant, Target::Variant; + ControlFlowBreak, sym::Break, cf_break_variant, Target::Variant; + ControlFlowContinue, sym::Continue, cf_continue_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_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs index d0cd8a48f99b3..b60c0d7a873ad 100644 --- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs @@ -405,7 +405,7 @@ impl<'sess> OnDiskCache<'sess> { // Encode the position of the footer as the last 8 bytes of the // file so we know where to look for it. - IntEncodedWithFixedSize(footer_pos).encode(encoder.encoder)?; + IntEncodedWithFixedSize(footer_pos).encode(encoder.encoder).map_err(|x| x)?; // DO NOT WRITE ANYTHING TO THE ENCODER AFTER THIS POINT! The address // of the footer must be the last thing in the data stream. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 653d70b6cf244..988568cc0a3a6 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -126,10 +126,12 @@ symbols! { Argument, ArgumentV1, Arguments, + Break, C, CString, Center, Clone, + Continue, Copy, Count, Debug, @@ -313,6 +315,7 @@ symbols! { box_patterns, box_syntax, braced_empty_structs, + branch, breakpoint, bridge, bswap, @@ -392,6 +395,8 @@ symbols! { constructor, contents, context, + continue_with, + control_flow_enum, convert, copy, copy_closures, @@ -561,6 +566,7 @@ symbols! { from_desugaring, from_error, from_generator, + from_holder, from_method, from_ok, from_size_align_unchecked, @@ -587,6 +593,7 @@ symbols! { hash, hexagon_target_feature, hidden, + holder, homogeneous_aggregate, html_favicon_url, html_logo_url, @@ -1177,6 +1184,7 @@ symbols! { try_from_trait, try_into_trait, try_trait, + try_trait_v2, tt, tuple, tuple_from_req, diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 32bf0ab7e8533..1579ce355d9b0 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -164,7 +164,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { debug!(">> type-checking: expr={:?} expected={:?}", expr, expected); - // True if `expr` is a `Try::from_ok(())` that is a result of desugaring a try block + // True if `expr` is a `Try::continue_with(())` that is a result of desugaring a try block // without the final expr (e.g. `try { return; }`). We don't want to generate an // unreachable_code lint for it since warnings for autogenerated code are confusing. let is_try_block_generated_unit_expr = match expr.kind { diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 99c42a4ba4423..c64d02bb419a0 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -137,6 +137,7 @@ #![feature(alloc_layout_extra)] #![feature(trusted_random_access)] #![feature(try_trait)] +#![feature(try_trait_v2)] #![feature(type_alias_impl_trait)] #![feature(associated_type_bounds)] #![feature(slice_group_by)] diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index 43301444e3e2c..c78ecd7c54778 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -129,6 +129,7 @@ where } } + #[cfg(bootstrap)] #[inline] fn try_rfold(&mut self, init: B, mut f: F) -> R where @@ -149,6 +150,29 @@ where } } + #[cfg(not(bootstrap))] + #[inline] + fn try_rfold(&mut self, init: B, mut f: F) -> R + where + Self: Sized, + F: FnMut(B, Self::Item) -> R, + R: Try, + { + use crate::ops::ControlFlow; + + 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(h) => { + self.peeked = Some(Some(v)); + R::from_holder(h) + } + }, + None => self.iter.try_rfold(init, f), + } + } + #[inline] fn rfold(self, init: Acc, mut fold: Fold) -> Acc where diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index a38b35a5b5c74..ed7c867b6c127 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -3,7 +3,7 @@ // can't split that into multiple files. use crate::cmp::{self, Ordering}; -use crate::ops::{Add, ControlFlow, Try}; +use crate::ops::{self, Add, ControlFlow, Try}; use super::super::TrustedRandomAccess; use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse}; @@ -2388,13 +2388,14 @@ pub trait Iterator { /// let result = a.iter().try_find(|&&s| is_my_num(s, 5)); /// assert!(result.is_err()); /// ``` + #[cfg(bootstrap)] #[inline] #[unstable(feature = "try_find", reason = "new API", issue = "63178")] fn try_find(&mut self, f: F) -> Result, R::Error> where Self: Sized, F: FnMut(&Self::Item) -> R, - R: Try, + R: ops::Try, { #[inline] fn check(mut f: F) -> impl FnMut((), T) -> ControlFlow> @@ -2412,6 +2413,59 @@ pub trait Iterator { self.try_fold((), check(f)).break_value().transpose() } + /// Applies function to the elements of iterator and returns + /// the first true result or the first error. + /// + /// # Examples + /// + /// ``` + /// #![feature(try_find)] + /// + /// let a = ["1", "2", "lol", "NaN", "5"]; + /// + /// let is_my_num = |s: &str, search: i32| -> Result { + /// Ok(s.parse::()? == search) + /// }; + /// + /// let result = a.iter().try_find(|&&s| is_my_num(s, 2)); + /// assert_eq!(result, Ok(Some(&"2"))); + /// + /// let result = a.iter().try_find(|&&s| is_my_num(s, 5)); + /// assert!(result.is_err()); + /// ``` + #[cfg(not(bootstrap))] + #[inline] + #[unstable(feature = "try_find", reason = "new API", issue = "63178")] + fn try_find( + &mut self, + f: F, + ) -> >>::Output + where + Self: Sized, + F: FnMut(&Self::Item) -> R, + R: ops::Try, + R::Holder: ops::BreakHolder>, + { + #[inline] + fn check(mut f: F) -> impl FnMut((), T) -> ControlFlow> + where + F: FnMut(&T) -> R, + R: Try, + { + move |(), x| match f(&x).branch() { + ControlFlow::Continue(false) => ControlFlow::CONTINUE, + ControlFlow::Continue(true) => ControlFlow::Break(Ok(x)), + ControlFlow::Break(h) => ControlFlow::Break(Err(h)), + } + } + + match self.try_fold((), check(f)) { + ControlFlow::Continue(()) => ops::TryCore::continue_with(None), + ControlFlow::Break(Ok(x)) => ops::TryCore::continue_with(Some(x)), + ControlFlow::Break(Err(h)) => Try::from_holder(h), + } + } + /// Searches for an element in an iterator, returning its index. /// /// `position()` takes a closure that returns `true` or `false`. It applies diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 2f78ba8f28e29..e6309085d40a1 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -1,4 +1,4 @@ -use crate::ops::Try; +use crate::ops::{self, Try}; /// Used to tell an operation whether it should exit early or go on as usual. /// @@ -52,8 +52,10 @@ use crate::ops::Try; #[derive(Debug, Clone, Copy, PartialEq)] pub enum ControlFlow { /// 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` <-> `Result` @@ -61,7 +63,7 @@ pub enum ControlFlow { } #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] -impl Try for ControlFlow { +impl ops::Try2015 for ControlFlow { type Ok = C; type Error = B; #[inline] @@ -81,6 +83,43 @@ impl Try for ControlFlow { } } +#[unstable(feature = "try_trait_v2", issue = "42327")] +impl ops::TryCore for ControlFlow { + //type Continue = C; + type Ok = C; + type Holder = ControlFlow; + #[inline] + fn continue_with(c: C) -> Self { + ControlFlow::Continue(c) + } + #[inline] + fn branch(self) -> ControlFlow { + match self { + ControlFlow::Continue(c) => ControlFlow::Continue(c), + ControlFlow::Break(b) => ControlFlow::Break(ControlFlow::Break(b)), + } + } +} + +#[unstable(feature = "try_trait_v2", issue = "42327")] +impl ops::BreakHolder for ControlFlow { + type Output = ControlFlow; + // fn expand(x: Self) -> Self::Output { + // match x { + // ControlFlow::Break(b) => ControlFlow::Break(b), + // } + // } +} + +#[unstable(feature = "try_trait_v2", issue = "42327")] +impl ops::Try2021 for ControlFlow { + fn from_holder(x: Self::Holder) -> Self { + match x { + ControlFlow::Break(b) => ControlFlow::Break(b), + } + } +} + impl ControlFlow { /// Returns `true` if this is a `Break` variant. /// @@ -152,6 +191,7 @@ impl ControlFlow { } } +#[cfg(bootstrap)] impl ControlFlow { /// Create a `ControlFlow` from any type implementing `Try`. #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] @@ -174,6 +214,29 @@ impl ControlFlow { } } +#[cfg(not(bootstrap))] +impl ControlFlow { + /// 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() { + ControlFlow::Continue(v) => ControlFlow::Continue(v), + ControlFlow::Break(h) => ControlFlow::Break(R::from_holder(h)), + } + } + + /// 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::continue_with(v), + ControlFlow::Break(v) => v, + } + } +} + impl ControlFlow { /// It's frequently the case that there's no value needed with `Continue`, /// so this provides a way to avoid typing `(())`, if you prefer it. diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 354ad6b7b7333..05c6753c000ab 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -182,7 +182,17 @@ pub use self::range::{Range, RangeFrom, RangeFull, RangeTo}; pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive}; #[unstable(feature = "try_trait", issue = "42327")] -pub use self::r#try::Try; +pub use self::r#try::Try2015; + +#[unstable(feature = "try_trait_v2", issue = "42327")] +pub use self::r#try::{BreakHolder, Try2021, TryCore}; + +#[cfg(bootstrap)] +#[unstable(feature = "try_trait_v2", issue = "42327")] +pub use self::Try2015 as Try; +#[cfg(not(bootstrap))] +#[unstable(feature = "try_trait_v2", issue = "42327")] +pub use self::Try2021 as Try; #[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 3bede5699781c..97bd4d7ea4c9e 100644 --- a/library/core/src/ops/try.rs +++ b/library/core/src/ops/try.rs @@ -1,3 +1,5 @@ +use super::ControlFlow; + /// A trait for customizing the behavior of the `?` operator. /// /// A type implementing `Try` is one that has a canonical way to view it @@ -13,20 +15,20 @@ ), message = "the `?` operator can only be used in {ItemContext} \ that returns `Result` or `Option` \ - (or another type that implements `{Try}`)", + (or another type that implements `{Try2015}`)", label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`", enclosing_scope = "this function should return `Result` or `Option` to accept `?`" ), on( all(from_method = "into_result", from_desugaring = "QuestionMark"), message = "the `?` operator can only be applied to values \ - that implement `{Try}`", + that implement `{Try2015}`", label = "the `?` operator cannot be applied to type `{Self}`" ) )] #[doc(alias = "?")] #[lang = "try"] -pub trait Try { +pub trait Try2015 { /// The type of this value when viewed as successful. #[unstable(feature = "try_trait", issue = "42327")] type Ok; @@ -59,3 +61,108 @@ pub trait Try { #[unstable(feature = "try_trait", issue = "42327")] fn from_ok(v: Self::Ok) -> Self; } + +/// A trait for customizing the behavior of the `?` operator. +/// +/// This trait contains the behaviour core to this type, +/// such as the associated `Continue` type that both +/// is produced by the `?` operator and +/// is expected by a `try{}` block producing this type. +#[rustc_on_unimplemented( + on( + all(from_method = "continue_with", from_desugaring = "QuestionMark"), + message = "the `?` operator can only be used in {ItemContext} \ + that returns `Result` or `Option` \ + (or another type that implements `{TryCore}`)", + label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`", + enclosing_scope = "this function should return `Result` or `Option` to accept `?`" + ), + on( + all(from_method = "branch", from_desugaring = "QuestionMark"), + message = "the `?` operator can only be applied to values \ + that implement `{TryCore}`", + label = "the `?` operator cannot be applied to type `{Self}`" + ) +)] +#[unstable(feature = "try_trait_v2", issue = "42327")] +pub trait TryCore { + /// The type of the value consumed or produced when not short-circuiting. + #[unstable(feature = "try_trait_v2", issue = "42327")] + // Temporarily using `Ok` still so I don't need to change the bounds in the library + //type Continue; + type Ok; + + /// A type that "colours" the short-circuit value so it can stay associated + /// with the type constructor from which it came. + #[unstable(feature = "try_trait_v2", issue = "42327")] + // This could have required that we can get back here via the holder, + // but that means that every type needs a distinct holder. It was removed + // so that the Poll impls can use Result's Holder. + //type Holder: BreakHolder; + type Holder: BreakHolder; + + /// Used in `try{}` blocks to wrap the result of the block. + #[cfg_attr(not(bootstrap), lang = "continue_with")] + #[unstable(feature = "try_trait_v2", issue = "42327")] + fn continue_with(x: Self::Ok) -> Self; + + /// Determine whether to short-circuit (by returning `ControlFlow::Break`) + /// or continue executing (by returning `ControlFlow::Continue`). + #[cfg_attr(not(bootstrap), lang = "branch")] + #[unstable(feature = "try_trait_v2", issue = "42327")] + fn branch(self) -> ControlFlow; + + /// Demonstration that this is usable for different-return-type scenarios (like `Iterator::try_find`). + #[unstable(feature = "try_trait_v2", issue = "42327")] + fn map(self, f: impl FnOnce(Self::Ok) -> T) -> >::Output + where + Self: Try2021, + Self::Holder: BreakHolder, + { + match TryCore::branch(self) { + ControlFlow::Continue(c) => TryCore::continue_with(f(c)), + //ControlFlow::Break(h) => BreakHolder::::expand(h), + ControlFlow::Break(h) => Try2021::from_holder(h), + } + } +} + +/// The bound on a `::Holder` type that allows getting back to the original. +#[unstable(feature = "try_trait_v2", issue = "42327")] +pub trait BreakHolder: Sized { + /// The type from the original type constructor that also has this holder type, + /// but has the specified Continue type. + #[unstable(feature = "try_trait_v2", issue = "42327")] + type Output: Try2021; + + /* Superfluous now that `FromHolder` exists + /// Rebuild the associated `impl Try` type from this holder. + #[unstable(feature = "try_trait_v2", issue = "42327")] + fn expand(x: Self) -> Self::Output; + */ +} + +/// Allows you to pick with other types can be converted into your `Try` type. +/// +/// With the default type argument, this functions as a bound for a "normal" +/// `Try` type: one that can be split apart and put back together in either way. +/// +/// For more complicated scenarios you'll likely need to bound on more than just this. +#[rustc_on_unimplemented(on( + all(from_method = "from_holder", from_desugaring = "QuestionMark"), + message = "the `?` operator can only be used in {ItemContext} \ + that returns `Result` or `Option` \ + (or another type that implements `{Try2021}`)", + 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 = "42327")] +pub trait Try2021::Holder>: TryCore +where + T: BreakHolder, +{ + /// Perform conversion on this holder + #[cfg_attr(not(bootstrap), lang = "from_holder")] + #[unstable(feature = "try_trait_v2", issue = "42327")] + fn from_holder(x: T) -> Self; +} diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 14e4e4da3b96d..ed484d158bb56 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -151,7 +151,7 @@ use crate::iter::{FromIterator, FusedIterator, TrustedLen}; use crate::pin::Pin; use crate::{ convert, fmt, hint, mem, - ops::{self, Deref, DerefMut}, + ops::{self, ControlFlow, Deref, DerefMut}, }; /// The `Option` type. See [the module level documentation](self) for more. @@ -1703,7 +1703,7 @@ impl> FromIterator> for Option { pub struct NoneError; #[unstable(feature = "try_trait", issue = "42327")] -impl ops::Try for Option { +impl ops::Try2015 for Option { type Ok = T; type Error = NoneError; @@ -1723,6 +1723,46 @@ impl ops::Try for Option { } } +#[unstable(feature = "try_trait_v2", issue = "42327")] +impl ops::TryCore for Option { + //type Continue = T; + type Ok = T; + type Holder = Option; + + #[inline] + fn continue_with(c: T) -> Self { + Some(c) + } + + #[inline] + fn branch(self) -> ControlFlow { + match self { + Some(c) => ControlFlow::Continue(c), + None => ControlFlow::Break(None), + } + } +} + +#[unstable(feature = "try_trait_v2", issue = "42327")] +impl ops::BreakHolder for Option { + type Output = Option; + + // fn expand(x: Self) -> Self::Output { + // match x { + // None => None, + // } + // } +} + +#[unstable(feature = "try_trait_v2", issue = "42327")] +impl ops::Try2021> for Option { + fn from_holder(x: Self::Holder) -> Self { + match x { + None => None, + } + } +} + impl Option> { /// Converts from `Option>` to `Option` /// diff --git a/library/core/src/result.rs b/library/core/src/result.rs index d8747f8b8d6dc..be6128ec573d2 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -228,7 +228,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use crate::iter::{self, FromIterator, FusedIterator, TrustedLen}; -use crate::ops::{self, Deref, DerefMut}; +use crate::ops::{self, ControlFlow, Deref, DerefMut}; use crate::{convert, fmt, hint}; /// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]). @@ -1591,7 +1591,7 @@ impl> FromIterator> for Result { } #[unstable(feature = "try_trait", issue = "42327")] -impl ops::Try for Result { +impl ops::Try2015 for Result { type Ok = T; type Error = E; @@ -1610,3 +1610,68 @@ impl ops::Try for Result { Err(v) } } + +#[unstable(feature = "try_trait_v2", issue = "42327")] +impl ops::TryCore for Result { + //type Continue = T; + type Ok = T; + type Holder = Result; + + #[inline] + fn continue_with(c: T) -> Self { + Ok(c) + } + + #[inline] + fn branch(self) -> ControlFlow { + match self { + Ok(c) => ControlFlow::Continue(c), + Err(e) => ControlFlow::Break(Err(e)), + } + } +} + +#[unstable(feature = "try_trait_v2", issue = "42327")] +impl ops::BreakHolder for Result { + type Output = Result; + + // fn expand(x: Self) -> Self::Output { + // match x { + // Err(e) => Err(e), + // } + // } +} + +#[unstable(feature = "try_trait_v2", issue = "42327")] +impl> ops::Try2021> for Result { + fn from_holder(x: Result) -> Self { + match x { + Err(e) => Err(From::from(e)), + } + } +} + +mod sadness { + use super::*; + + /// This is a remnant of the old `NoneError` which is never going to be stabilized. + /// It's here as a snapshot of an oversight that allowed this to work in the past, + /// so we're stuck supporting it even though we'd really rather not. + #[unstable(feature = "legacy_try_trait", issue = "none")] + #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] + pub struct PleaseCallTheOkOrMethodToUseQuestionMarkOnOptionsInAMethodThatReturnsResult; + + #[unstable(feature = "try_trait_v2", issue = "42327")] + impl ops::Try2021> for Result + where + E: From, + { + fn from_holder(x: Option) -> Self { + match x { + None => Err(From::from( + PleaseCallTheOkOrMethodToUseQuestionMarkOnOptionsInAMethodThatReturnsResult, + )), + } + } + } +} diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 42c9d9f0cc039..557bd8ce132b2 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -1,6 +1,6 @@ #![stable(feature = "futures_api", since = "1.36.0")] -use crate::ops::Try; +use crate::ops::{self, ControlFlow}; use crate::result::Result; /// Indicates whether a value is available or if the current task has been @@ -128,7 +128,7 @@ impl From for Poll { } #[stable(feature = "futures_api", since = "1.36.0")] -impl Try for Poll> { +impl ops::Try2015 for Poll> { type Ok = Poll; type Error = E; @@ -152,8 +152,60 @@ impl Try for Poll> { } } +#[unstable(feature = "try_trait_v2", issue = "42327")] +impl ops::TryCore for Poll> { + //type Continue = Poll; + type Ok = Poll; + //type Holder = PollResultHolder; + type Holder = as ops::TryCore>::Holder; + + #[inline] + fn continue_with(c: Self::Ok) -> Self { + c.map(Ok) + } + + #[inline] + fn branch(self) -> ControlFlow { + match self { + Poll::Ready(Ok(x)) => ControlFlow::Continue(Poll::Ready(x)), + Poll::Ready(Err(e)) => ControlFlow::Break(Err(e)), + Poll::Pending => ControlFlow::Continue(Poll::Pending), + } + } +} + +/* This is needed if the Try::Holder bound gets tighter again + +#[unstable(feature = "try_trait_v2_never_stable", issue = "42327")] +#[allow(missing_debug_implementations)] +/// This type is *only* useful for `expand`ing, +/// so it's intentional that it implements no traits. +pub struct PollResultHolder(E); + +#[unstable(feature = "try_trait_v2", issue = "42327")] +impl BreakHolder> for PollResultHolder { + type Output = Poll>; + + fn expand(x: Self) -> Self::Output { + match x { + PollResultHolder(e) => Poll::Ready(Err(e)), + } + } +} + +*/ + +#[unstable(feature = "try_trait_v2", issue = "42327")] +impl> ops::Try2021> for Poll> { + fn from_holder(x: Result) -> Self { + match x { + Err(e) => Poll::Ready(Err(From::from(e))), + } + } +} + #[stable(feature = "futures_api", since = "1.36.0")] -impl Try for Poll>> { +impl ops::Try2015 for Poll>> { type Ok = Poll>; type Error = E; @@ -177,3 +229,56 @@ impl Try for Poll>> { x.map(|x| x.map(Ok)) } } + +#[unstable(feature = "try_trait_v2", issue = "42327")] +impl ops::TryCore for Poll>> { + //type Continue = Poll>; + type Ok = Poll>; + //type Holder = PollOptionResultHolder; + type Holder = as ops::TryCore>::Holder; + + #[inline] + fn continue_with(c: Self::Ok) -> Self { + c.map(|x| x.map(Ok)) + } + + #[inline] + fn branch(self) -> ControlFlow { + match self { + Poll::Ready(Some(Ok(x))) => ControlFlow::Continue(Poll::Ready(Some(x))), + Poll::Ready(Some(Err(e))) => ControlFlow::Break(Err(e)), + Poll::Ready(None) => ControlFlow::Continue(Poll::Ready(None)), + Poll::Pending => ControlFlow::Continue(Poll::Pending), + } + } +} + +/* This is needed if the Try::Holder bound gets tighter again + +#[unstable(feature = "try_trait_v2_never_stable", issue = "42327")] +#[allow(missing_debug_implementations)] +/// This type is *only* useful for `expand`ing, +/// so it's intentional that it implements no traits. +pub struct PollOptionResultHolder(E); + +#[unstable(feature = "try_trait_v2", issue = "42327")] +impl BreakHolder>> for PollOptionResultHolder { + type Output = Poll>>; + + fn expand(x: Self) -> Self::Output { + match x { + PollOptionResultHolder(e) => Poll::Ready(Some(Err(e))), + } + } +} + +*/ + +#[unstable(feature = "try_trait_v2", issue = "42327")] +impl> ops::Try2021> for Poll>> { + fn from_holder(x: Result) -> Self { + match x { + Err(e) => Poll::Ready(Some(Err(From::from(e)))), + } + } +} diff --git a/library/core/tests/option.rs b/library/core/tests/option.rs index 9470451278cc4..88ea15a3b33fa 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 { - let val = Some(1)?; - Ok(val) - } - assert_eq!(try_option_ok(), Ok(1)); - - fn try_option_err() -> Result { - 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 5fcd7b4d3a327..ea340d63d9fb4 100644 --- a/library/core/tests/result.rs +++ b/library/core/tests/result.rs @@ -227,18 +227,6 @@ pub fn test_into_ok() { #[test] fn test_try() { - fn try_result_some() -> Option { - let val = Ok(1)?; - Some(val) - } - assert_eq!(try_result_some(), Some(1)); - - fn try_result_none() -> Option { - let val = Err(NoneError)?; - Some(val) - } - assert_eq!(try_result_none(), None); - fn try_result_ok() -> Result { let result: Result = Ok(1); let val = result?; diff --git a/src/test/ui/async-await/issue-61076.rs b/src/test/ui/async-await/issue-61076.rs index 8a7b166cb15bd..d6054a837081e 100644 --- a/src/test/ui/async-await/issue-61076.rs +++ b/src/test/ui/async-await/issue-61076.rs @@ -39,12 +39,10 @@ async fn foo() -> Result<(), ()> { } async fn bar() -> Result<(), ()> { - foo()?; //~ ERROR the `?` operator can only be applied to values that implement `Try` + foo()?; //~ ERROR the `?` operator can only be applied to values that implement `TryCore` //~^ 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` - //~| HELP consider `await`ing on the `Future` - //~| NOTE in this expansion of desugaring of operator `?` + //~| HELP the trait `TryCore` is not implemented for `impl Future` + //~| NOTE required by `branch` //~| NOTE in this expansion of desugaring of operator `?` //~| NOTE in this expansion of desugaring of operator `?` //~| NOTE in this expansion of desugaring of operator `?` @@ -62,16 +60,13 @@ async fn tuple() -> Tuple { async fn baz() -> Result<(), ()> { let t = T; - t?; //~ ERROR the `?` operator can only be applied to values that implement `Try` + t?; //~ ERROR the `?` operator can only be applied to values that implement `TryCore` //~^ NOTE the `?` operator cannot be applied to type `T` - //~| HELP the trait `Try` is not implemented for `T` - //~| NOTE required by `into_result` - //~| HELP consider `await`ing on the `Future` + //~| HELP the trait `TryCore` is not implemented for `T` + //~| NOTE required by `branch` //~| NOTE in this expansion of desugaring of operator `?` //~| NOTE in this expansion of desugaring of operator `?` //~| NOTE in this expansion of desugaring of operator `?` - //~| NOTE in this expansion of desugaring of operator `?` - let _: i32 = tuple().0; //~ ERROR no field `0` //~^ HELP consider `await`ing on the `Future` diff --git a/src/test/ui/async-await/issue-61076.stderr b/src/test/ui/async-await/issue-61076.stderr index db6dc3ea00a8d..6cd6e8e4c066c 100644 --- a/src/test/ui/async-await/issue-61076.stderr +++ b/src/test/ui/async-await/issue-61076.stderr @@ -1,31 +1,23 @@ -error[E0277]: the `?` operator can only be applied to values that implement `Try` +error[E0277]: the `?` operator can only be applied to values that implement `TryCore` --> $DIR/issue-61076.rs:42:5 | 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` -help: consider `await`ing on the `Future` - | -LL | foo().await?; - | ^^^^^^ + = help: the trait `TryCore` is not implemented for `impl Future` + = note: required by `branch` -error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/issue-61076.rs:65:5 +error[E0277]: the `?` operator can only be applied to values that implement `TryCore` + --> $DIR/issue-61076.rs:63:5 | LL | t?; | ^^ the `?` operator cannot be applied to type `T` | - = help: the trait `Try` is not implemented for `T` - = note: required by `into_result` -help: consider `await`ing on the `Future` - | -LL | t.await?; - | ^^^^^^ + = help: the trait `TryCore` is not implemented for `T` + = note: required by `branch` error[E0609]: no field `0` on type `impl Future` - --> $DIR/issue-61076.rs:76:26 + --> $DIR/issue-61076.rs:71:26 | LL | let _: i32 = tuple().0; | ^ field not available in `impl Future`, but it is available in its `Output` @@ -36,7 +28,7 @@ LL | let _: i32 = tuple().await.0; | ^^^^^^ error[E0609]: no field `a` on type `impl Future` - --> $DIR/issue-61076.rs:80:28 + --> $DIR/issue-61076.rs:75:28 | LL | let _: i32 = struct_().a; | ^ field not available in `impl Future`, but it is available in its `Output` @@ -47,7 +39,7 @@ LL | let _: i32 = struct_().await.a; | ^^^^^^ error[E0599]: no method named `method` found for opaque type `impl Future` in the current scope - --> $DIR/issue-61076.rs:84:15 + --> $DIR/issue-61076.rs:79:15 | LL | struct_().method(); | ^^^^^^ method not found in `impl Future` @@ -58,7 +50,7 @@ LL | struct_().await.method(); | ^^^^^^ error[E0308]: mismatched types - --> $DIR/issue-61076.rs:92:9 + --> $DIR/issue-61076.rs:87:9 | LL | async fn tuple() -> Tuple { | ----- the `Output` of this `async fn`'s expected opaque type 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 8e7823f3571b1..dbcb6075a1fc8 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,4 +1,4 @@ -error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `Try`) +error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `Try2021`) --> $DIR/try-on-option-in-async.rs:8:9 | LL | async { @@ -10,10 +10,10 @@ 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 `Try2021>` is not implemented for `{integer}` + = note: required by `from_holder` -error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `Try`) +error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `Try2021`) --> $DIR/try-on-option-in-async.rs:17:9 | LL | let async_closure = async || { @@ -25,10 +25,10 @@ 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 `Try2021>` is not implemented for `u32` + = note: required by `from_holder` -error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `Try`) +error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `Try2021`) --> $DIR/try-on-option-in-async.rs:26:5 | LL | async fn an_async_function() -> u32 { @@ -40,8 +40,8 @@ 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 `Try2021>` is not implemented for `u32` + = note: required by `from_holder` 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 2e96022318b47..7beb2db3969c8 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 2875cef680117..8e632fbc1de1b 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 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` + | --- 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 05f62f3d8cbc0..e7fabd0ffbc8b 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 282bc13e9e780..233604833612a 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` +... +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.rs b/src/test/ui/inference/cannot-infer-closure.rs index 8f48483c25421..6e84b6d5ad0bd 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 0dcce9e990b53..c7a26191b6e26 100644 --- a/src/test/ui/inference/cannot-infer-closure.stderr +++ b/src/test/ui/inference/cannot-infer-closure.stderr @@ -1,10 +1,17 @@ +<<<<<<< HEAD error[E0282]: type annotations needed for the closure `fn((), ()) -> Result<(), _>` --> $DIR/cannot-infer-closure.rs:3:15 +||||||| parent of f4e89f77bb1 (PoC: A new hybrid design for Try) +error[E0282]: type annotations needed for the closure `fn((), ()) -> std::result::Result<(), _>` + --> $DIR/cannot-infer-closure.rs:3:15 +======= +error[E0282]: type annotations needed for the closure `fn((), ()) -> std::result::Result<(), _>` + --> $DIR/cannot-infer-closure.rs:4:9 +>>>>>>> f4e89f77bb1 (PoC: A new hybrid design for Try) | -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 86e2126e1ae7b..c394f6efbda9b 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` 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 cc12c153621cc..e110e1e2aee9a 100644 --- a/src/test/ui/issues/issue-32709.stderr +++ b/src/test/ui/issues/issue-32709.stderr @@ -1,13 +1,11 @@ -error[E0277]: `?` couldn't convert the error to `()` - --> $DIR/issue-32709.rs:4:11 +error[E0277]: the trait bound `(): From<{integer}>` is not satisfied + --> $DIR/issue-32709.rs:4:5 | -LL | fn a() -> Result { - | --------------- expected `()` because of this LL | Err(5)?; - | ^ the trait `From<{integer}>` is not implemented for `()` + | ^^^^^^^ 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 `Try>` for `std::result::Result` + = note: required by `from_holder` error: aborting due to previous error diff --git a/src/test/ui/option-to-result.rs b/src/test/ui/option-to-result.rs index 00e8b5244c54a..b35c0274d2379 100644 --- a/src/test/ui/option-to-result.rs +++ b/src/test/ui/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 trait bound `(): From Option{ let a:Result = Ok(5); - a?;//~ ERROR `?` couldn't convert the error + a?;//~ ERROR the `?` operator can only be used in a function that returns `Result` or `Option` Some(5) } diff --git a/src/test/ui/option-to-result.stderr b/src/test/ui/option-to-result.stderr index 551b9f4650aac..6ec3ce67af6f2 100644 --- a/src/test/ui/option-to-result.stderr +++ b/src/test/ui/option-to-result.stderr @@ -1,34 +1,25 @@ -error[E0277]: `?` couldn't convert the error to `()` - --> $DIR/option-to-result.rs:5:6 +error[E0277]: the trait bound `(): From` is not satisfied + --> $DIR/option-to-result.rs:5:5 | -LL | fn test_result() -> Result<(),()> { - | ------------- expected `()` because of this -LL | let a:Option<()> = Some(()); LL | a?; - | ^ the trait `From` is not implemented for `()` + | ^^ the trait `From` 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` into a `Result` using `Option::ok_or` or `Option::ok_or_else` - | -LL | a.ok_or_else(|| /* error value */)?; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: required because of the requirements on the impl of `Try2021>` for `std::result::Result<(), ()>` + = note: required by `from_holder` -error[E0277]: `?` couldn't convert the error to `NoneError` - --> $DIR/option-to-result.rs:11:6 - | -LL | fn test_option() -> Option{ - | ----------- expected `NoneError` because of this -LL | let a:Result = Ok(5); -LL | a?; - | ^ the trait `From` is not implemented for `NoneError` +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try2021`) + --> $DIR/option-to-result.rs:11:5 | - = 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` into an `Option` using `Result::ok` +LL | / fn test_option() -> Option{ +LL | | let a:Result = Ok(5); +LL | | a?; + | | ^^ cannot use the `?` operator in a function that returns `Option` +LL | | Some(5) +LL | | } + | |_- this function should return `Result` or `Option` to accept `?` | -LL | a.ok()?; - | ^^^^^ + = help: the trait `Try2021>` is not implemented for `Option` + = note: required by `from_holder` error: aborting due to 2 previous errors diff --git a/src/test/ui/question-mark-type-infer.stderr b/src/test/ui/question-mark-type-infer.stderr index 381959b7ae4cd..0ea47be2477aa 100644 --- a/src/test/ui/question-mark-type-infer.stderr +++ b/src/test/ui/question-mark-type-infer.stderr @@ -4,8 +4,8 @@ error[E0283]: type annotations needed LL | l.iter().map(f).collect()? | ^^^^^^^ cannot infer type | - = note: cannot satisfy `_: Try` - = note: required by `into_result` + = note: cannot satisfy `_: TryCore` + = note: required by `branch` help: consider specifying the type argument in the method call | LL | l.iter().map(f).collect::()? diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs index aeee27a151e82..fe727da67ceec 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs @@ -40,11 +40,11 @@ fn nested_within_if_expr() { fn _check_try_binds_tighter() -> Result<(), ()> { if let 0 = 0? {} - //~^ ERROR the `?` operator can only be applied to values that implement `Try` + //~^ ERROR the `?` operator can only be applied to values that implement `TryCore` Ok(()) } if (let 0 = 0)? {} //~ ERROR `let` expressions are not supported here - //~^ ERROR the `?` operator can only be applied to values that implement `Try` + //~^ ERROR the `?` operator can only be applied to values that implement `TryCore` //~| ERROR the `?` operator can only be used in a function that returns `Result` if true || let 0 = 0 {} //~ ERROR `let` expressions are not supported here @@ -104,11 +104,11 @@ fn nested_within_while_expr() { fn _check_try_binds_tighter() -> Result<(), ()> { while let 0 = 0? {} - //~^ ERROR the `?` operator can only be applied to values that implement `Try` + //~^ ERROR the `?` operator can only be applied to values that implement `TryCore` Ok(()) } while (let 0 = 0)? {} //~ ERROR `let` expressions are not supported here - //~^ ERROR the `?` operator can only be applied to values that implement `Try` + //~^ ERROR the `?` operator can only be applied to values that implement `TryCore` //~| ERROR the `?` operator can only be used in a function that returns `Result` while true || let 0 = 0 {} //~ ERROR `let` expressions are not supported here @@ -177,12 +177,12 @@ fn outside_if_and_while_expr() { fn _check_try_binds_tighter() -> Result<(), ()> { let 0 = 0?; - //~^ ERROR the `?` operator can only be applied to values that implement `Try` + //~^ ERROR the `?` operator can only be applied to values that implement `TryCore` Ok(()) } (let 0 = 0)?; //~ ERROR `let` expressions are not supported here //~^ ERROR the `?` operator can only be used in a function that returns `Result` - //~| ERROR the `?` operator can only be applied to values that implement `Try` + //~| ERROR the `?` operator can only be applied to values that implement `TryCore` true || let 0 = 0; //~ ERROR `let` expressions are not supported here (true || let 0 = 0); //~ ERROR `let` expressions are not supported here 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 861a4a80ad652..71cf252f03010 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 @@ -551,16 +551,16 @@ error[E0600]: cannot apply unary operator `-` to type `bool` LL | if -let 0 = 0 {} | ^^^^^^^^^^ cannot apply unary operator `-` -error[E0277]: the `?` operator can only be applied to values that implement `Try` +error[E0277]: the `?` operator can only be applied to values that implement `TryCore` --> $DIR/disallowed-positions.rs:46:8 | 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` + = help: the trait `TryCore` is not implemented for `bool` + = 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`) +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try2021`) --> $DIR/disallowed-positions.rs:46:8 | LL | / fn nested_within_if_expr() { @@ -575,8 +575,8 @@ 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 `Try2021<_>` is not implemented for `()` + = note: required by `from_holder` error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:56:8 @@ -709,14 +709,14 @@ LL | if let Range { start: true, end } = t..&&false {} = note: expected type `bool` found struct `std::ops::Range` -error[E0277]: the `?` operator can only be applied to values that implement `Try` +error[E0277]: the `?` operator can only be applied to values that implement `TryCore` --> $DIR/disallowed-positions.rs:42:20 | 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` + = help: the trait `TryCore` is not implemented for `{integer}` + = note: required by `branch` error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:96:11 @@ -739,16 +739,16 @@ error[E0600]: cannot apply unary operator `-` to type `bool` LL | while -let 0 = 0 {} | ^^^^^^^^^^ cannot apply unary operator `-` -error[E0277]: the `?` operator can only be applied to values that implement `Try` +error[E0277]: the `?` operator can only be applied to values that implement `TryCore` --> $DIR/disallowed-positions.rs:110:11 | 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` + = help: the trait `TryCore` is not implemented for `bool` + = 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`) +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try2021`) --> $DIR/disallowed-positions.rs:110:11 | LL | / fn nested_within_while_expr() { @@ -763,8 +763,8 @@ 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 `Try2021<_>` is not implemented for `()` + = note: required by `from_holder` error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:120:11 @@ -897,14 +897,14 @@ LL | while let Range { start: true, end } = t..&&false {} = note: expected type `bool` found struct `std::ops::Range` -error[E0277]: the `?` operator can only be applied to values that implement `Try` +error[E0277]: the `?` operator can only be applied to values that implement `TryCore` --> $DIR/disallowed-positions.rs:106:23 | 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` + = help: the trait `TryCore` is not implemented for `{integer}` + = note: required by `branch` error[E0614]: type `bool` cannot be dereferenced --> $DIR/disallowed-positions.rs:173:5 @@ -918,16 +918,16 @@ error[E0600]: cannot apply unary operator `-` to type `bool` LL | -let 0 = 0; | ^^^^^^^^^^ cannot apply unary operator `-` -error[E0277]: the `?` operator can only be applied to values that implement `Try` +error[E0277]: the `?` operator can only be applied to values that implement `TryCore` --> $DIR/disallowed-positions.rs:183:5 | 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` + = help: the trait `TryCore` is not implemented for `bool` + = 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`) +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try2021`) --> $DIR/disallowed-positions.rs:183:5 | LL | / fn outside_if_and_while_expr() { @@ -942,8 +942,8 @@ 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 `Try2021<_>` is not implemented for `()` + = note: required by `from_holder` error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:198:10 @@ -965,14 +965,14 @@ LL | fn outside_if_and_while_expr() { LL | &let 0 = 0 | ^^^^^^^^^^ expected `()`, found `&bool` -error[E0277]: the `?` operator can only be applied to values that implement `Try` +error[E0277]: the `?` operator can only be applied to values that implement `TryCore` --> $DIR/disallowed-positions.rs:179:17 | 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` + = help: the trait `TryCore` is not implemented for `{integer}` + = 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 5c9c549fa0779..77d57e11e0846 100644 --- a/src/test/ui/suggestions/issue-72766.stderr +++ b/src/test/ui/suggestions/issue-72766.stderr @@ -1,15 +1,11 @@ -error[E0277]: the `?` operator can only be applied to values that implement `Try` +error[E0277]: the `?` operator can only be applied to values that implement `TryCore` --> $DIR/issue-72766.rs:14:5 | 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` -help: consider `await`ing on the `Future` - | -LL | SadGirl {}.call().await?; - | ^^^^^^ + = help: the trait `TryCore` is not implemented for `impl Future` + = note: required by `branch` error: aborting due to previous error 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 ef6e690e1bd0e..4980672ec40a9 100644 --- a/src/test/ui/try-block/try-block-bad-type.rs +++ b/src/test/ui/try-block/try-block-bad-type.rs @@ -4,7 +4,7 @@ pub fn main() { let res: Result = try { - Err("")?; //~ ERROR `?` couldn't convert the error + Err("")?; //~ ERROR the trait bound `std::array::TryFromSliceError: From<&str>` is not satisfied 5 }; @@ -15,8 +15,8 @@ pub fn main() { let res: Result = try { }; //~ ERROR type mismatch let res: () = try { }; - //~^ ERROR the trait bound `(): Try` is not satisfied - //~| ERROR the trait bound `(): Try` is not satisfied + //~^ ERROR the trait bound `(): TryCore` is not satisfied + //~| ERROR the trait bound `(): TryCore` is not satisfied - let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: Try` is not satisfied + let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: TryCore` is not satisfied } 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 75a42c0d6b71b..8936680c6b8fe 100644 --- a/src/test/ui/try-block/try-block-bad-type.stderr +++ b/src/test/ui/try-block/try-block-bad-type.stderr @@ -4,44 +4,43 @@ error[E0277]: `?` couldn't convert the error to `TryFromSliceError` LL | Err("")?; | ^ the trait `From<&str>` is not implemented for `TryFromSliceError` | - = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = help: the following implementations were found: > = note: required by `from` -error[E0271]: type mismatch resolving ` as Try>::Ok == &str` +error[E0271]: type mismatch resolving ` as TryCore>::Ok == &str` --> $DIR/try-block-bad-type.rs:12:9 | LL | "" | ^^ expected `i32`, found `&str` -error[E0271]: type mismatch resolving ` as Try>::Ok == ()` +error[E0271]: type mismatch resolving ` as TryCore>::Ok == ()` --> $DIR/try-block-bad-type.rs:15:39 | LL | let res: Result = try { }; | ^ expected `i32`, found `()` -error[E0277]: the trait bound `(): Try` is not satisfied +error[E0277]: the trait bound `(): TryCore` is not satisfied --> $DIR/try-block-bad-type.rs:17:25 | LL | let res: () = try { }; - | ^ the trait `Try` is not implemented for `()` + | ^ the trait `TryCore` is not implemented for `()` | - = note: required by `from_ok` + = note: required by `continue_with` -error[E0277]: the trait bound `(): Try` is not satisfied +error[E0277]: the trait bound `(): TryCore` is not satisfied --> $DIR/try-block-bad-type.rs:17:25 | LL | let res: () = try { }; - | ^ the trait `Try` is not implemented for `()` + | ^ the trait `TryCore` is not implemented for `()` -error[E0277]: the trait bound `i32: Try` is not satisfied +error[E0277]: the trait bound `i32: TryCore` is not satisfied --> $DIR/try-block-bad-type.rs:21:26 | LL | let res: i32 = try { 5 }; - | ^ the trait `Try` is not implemented for `i32` + | ^ the trait `TryCore` is not implemented for `i32` | - = note: required by `from_ok` + = note: required by `continue_with` error: aborting due to 6 previous errors 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 5d8748f1dd325..05e57b0b8c170 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 the trait bound `bool: TryCore` is not satisfied } 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 75a4e8d065cab..e638fc4022f0b 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,10 @@ -error[E0277]: the trait bound `bool: Try` is not satisfied +error[E0277]: the trait bound `bool: TryCore` is not satisfied --> $DIR/try-block-in-while.rs:6:17 | LL | while try { false } {} - | ^^^^^ the trait `Try` is not implemented for `bool` + | ^^^^^ the trait `TryCore` is not implemented for `bool` | - = note: required by `from_ok` + = note: required by `continue_with` 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 df1441c83d4f1..7d8b8266d8c99 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 ` as Try>::Ok == {integer}` +error[E0271]: type mismatch resolving ` as TryCore>::Ok == {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 ` as Try>::Ok == ()` +error[E0271]: type mismatch resolving ` as TryCore>::Ok == ()` --> $DIR/try-block-type-error.rs:16:5 | LL | }; diff --git a/src/test/ui/try-on-option-diagnostics.stderr b/src/test/ui/try-on-option-diagnostics.stderr index a71ee20aacf93..f704b84e13e29 100644 --- a/src/test/ui/try-on-option-diagnostics.stderr +++ b/src/test/ui/try-on-option-diagnostics.stderr @@ -9,8 +9,8 @@ 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 `Try>` is not implemented for `u32` + = note: required by `from_holder` 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 @@ -24,8 +24,8 @@ 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 `Try>` is not implemented for `{integer}` + = note: required by `from_holder` 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 @@ -37,8 +37,8 @@ LL | | x?; 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 `Try>` is not implemented for `()` + = note: required by `from_holder` 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 @@ -50,8 +50,8 @@ LL | | x?; 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 `Try>` is not implemented for `()` + = note: required by `from_holder` error: aborting due to 4 previous errors diff --git a/src/test/ui/try-on-option-in-result-method.rs b/src/test/ui/try-on-option-in-result-method.rs new file mode 100644 index 0000000000000..fe50d9bccb4f5 --- /dev/null +++ b/src/test/ui/try-on-option-in-result-method.rs @@ -0,0 +1,20 @@ +// check-pass + +#![allow(dead_code, unused)] + +///! This isn't supposed to work, but it accidentally did, so unfortunately we need to support this. + +struct Tricky; + +impl From for Tricky { + fn from(_: T) -> Tricky { Tricky } +} + +fn foo() -> Result<(), Tricky> { + None?; + Ok(()) +} + +fn main() { + assert!(matches!(foo(), Err(Tricky))); +} diff --git a/src/test/ui/try-on-option.rs b/src/test/ui/try-on-option.rs index 5d94cee8e3721..691bd93dc0f07 100644 --- a/src/test/ui/try-on-option.rs +++ b/src/test/ui/try-on-option.rs @@ -4,7 +4,7 @@ fn main() {} fn foo() -> Result { let x: Option = None; - x?; //~ ERROR `?` couldn't convert the error + x?; //~ ERROR the trait bound `(): From $DIR/try-on-option.rs:7:6 +error[E0277]: the trait bound `(): From` is not satisfied + --> $DIR/try-on-option.rs:7:5 | -LL | fn foo() -> Result { - | --------------- expected `()` because of this -LL | let x: Option = None; LL | x?; - | ^ the trait `From` is not implemented for `()` + | ^^ the trait `From` 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` into a `Result` using `Option::ok_or` or `Option::ok_or_else` - | -LL | x.ok_or_else(|| /* error value */)?; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: required because of the requirements on the impl of `Try2021>` for `std::result::Result` + = note: required by `from_holder` -error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`) +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try2021`) --> $DIR/try-on-option.rs:13:5 | LL | / fn bar() -> u32 { @@ -25,8 +18,8 @@ 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 `Try2021>` is not implemented for `u32` + = note: required by `from_holder` error: aborting due to 2 previous errors diff --git a/src/test/ui/try-operator-custom.rs b/src/test/ui/try-operator-custom.rs index 9993061ea6155..951c9b9ba72b3 100644 --- a/src/test/ui/try-operator-custom.rs +++ b/src/test/ui/try-operator-custom.rs @@ -1,15 +1,19 @@ // run-pass +#![feature(control_flow_enum)] +#![feature(never_type)] #![feature(try_trait)] +#![feature(try_trait_v2)] -use std::ops::Try; +use std::convert::Infallible; +use std::ops::{BreakHolder, ControlFlow, Try2015, Try2021, TryCore}; enum MyResult { Awesome(T), Terrible(U) } -impl Try for MyResult { +impl Try2015 for MyResult { type Ok = U; type Error = V; @@ -29,6 +33,52 @@ impl Try for MyResult { } } +impl TryCore for MyResult { + //type Continue = U; + type Ok = U; + type Holder = MyResult; + fn continue_with(x: U) -> Self { + MyResult::Awesome(x) + } + fn branch(self) -> ControlFlow { + match self { + MyResult::Awesome(u) => ControlFlow::Continue(u), + MyResult::Terrible(e) => ControlFlow::Break(MyResult::Terrible(e)), + } + } +} + +impl BreakHolder for MyResult { + type Output = MyResult; +} + +impl> Try2021> for MyResult { + fn from_holder(x: MyResult) -> Self { + match x { + MyResult::Terrible(e) => MyResult::Terrible(From::from(e)), + MyResult::Awesome(infallible) => match infallible {} + } + } +} + +impl> Try2021> for MyResult { + fn from_holder(x: Result) -> Self { + match x { + Err(e) => MyResult::Terrible(From::from(e)), + Ok(infallible) => match infallible {} + } + } +} + +impl> Try2021> for Result { + fn from_holder(x: MyResult) -> Self { + match x { + MyResult::Terrible(e) => Err(From::from(e)), + MyResult::Awesome(infallible) => match infallible {} + } + } +} + fn f(x: i32) -> Result { if x == 0 { Ok(42) @@ -60,4 +110,6 @@ fn main() { assert!(f(10) == Err("Hello".to_owned())); let _ = h(); let _ = i(); + let mapped = MyResult::<_, ()>::Awesome(4_i32).map(|x| x as i64); + assert!(matches!(mapped, MyResult::Awesome(4_i64))); } diff --git a/src/test/ui/try-operator-on-main.rs b/src/test/ui/try-operator-on-main.rs index e1b6cfbe5ae1b..581316e5cae65 100644 --- a/src/test/ui/try-operator-on-main.rs +++ b/src/test/ui/try-operator-on-main.rs @@ -1,13 +1,17 @@ +// ignore-tidy-linelength + #![feature(try_trait)] +#![feature(try_trait_v2)] use std::ops::Try; fn main() { // error for a `Try` type on a non-`Try` fn - std::fs::File::open("foo")?; //~ ERROR the `?` operator can only + std::fs::File::open("foo")?; //~ ERROR the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try2021`) // a non-`Try` type on a non-`Try` fn - ()?; //~ ERROR the `?` operator can only + ()?; //~ ERROR the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try2021`) + //~^ ERROR the `?` operator can only be applied to values that implement `TryCore` // an unrelated use of `Try` try_trait_generic::<()>(); //~ ERROR the trait bound @@ -17,7 +21,7 @@ fn main() { fn try_trait_generic() -> T { // and a non-`Try` object on a `Try` fn. - ()?; //~ ERROR the `?` operator can only be applied to values that implement `Try` + ()?; //~ ERROR the `?` operator can only be applied to values that implement `TryCore` loop {} } diff --git a/src/test/ui/try-operator-on-main.stderr b/src/test/ui/try-operator-on-main.stderr index be17de2fe7cc0..4ad497b31e36e 100644 --- a/src/test/ui/try-operator-on-main.stderr +++ b/src/test/ui/try-operator-on-main.stderr @@ -1,5 +1,5 @@ -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 `Try2021`) + --> $DIR/try-operator-on-main.rs:10:5 | LL | / fn main() { LL | | // error for a `Try` type on a non-`Try` fn @@ -11,36 +11,54 @@ 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 `Try2021>` is not implemented for `()` + = note: required by `from_holder` -error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/try-operator-on-main.rs:10:5 +error[E0277]: the `?` operator can only be applied to values that implement `TryCore` + --> $DIR/try-operator-on-main.rs:13:5 | LL | ()?; | ^^^ the `?` operator cannot be applied to type `()` | - = help: the trait `Try` is not implemented for `()` - = note: required by `into_result` + = help: the trait `TryCore` is not implemented for `()` + = 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 `Try2021`) + --> $DIR/try-operator-on-main.rs:13:5 + | +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 `Try2021<_>` is not implemented for `()` + = note: required by `from_holder` -error[E0277]: the trait bound `(): Try` is not satisfied - --> $DIR/try-operator-on-main.rs:13:25 +error[E0277]: the trait bound `(): Try2021<_>` is not satisfied + --> $DIR/try-operator-on-main.rs:17:25 | LL | try_trait_generic::<()>(); - | ^^ the trait `Try` is not implemented for `()` + | ^^ the trait `Try2021<_>` is not implemented for `()` ... LL | fn try_trait_generic() -> 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 +error[E0277]: the `?` operator can only be applied to values that implement `TryCore` + --> $DIR/try-operator-on-main.rs:24:5 | LL | ()?; | ^^^ the `?` operator cannot be applied to type `()` | - = help: the trait `Try` is not implemented for `()` - = note: required by `into_result` + = help: the trait `TryCore` is not implemented for `()` + = 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`. From 53db8a8cef7c9b4a6df2e5ea5871aa36014786e2 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Tue, 29 Dec 2020 01:20:12 -0800 Subject: [PATCH 02/10] Rename TryCore to Bubble --- library/core/src/iter/traits/iterator.rs | 4 ++-- library/core/src/ops/control_flow.rs | 2 +- library/core/src/ops/mod.rs | 2 +- library/core/src/ops/try.rs | 12 +++++----- library/core/src/option.rs | 2 +- library/core/src/result.rs | 2 +- library/core/src/task/poll.rs | 8 +++---- src/test/ui/async-await/issue-61076.rs | 8 +++---- src/test/ui/async-await/issue-61076.stderr | 8 +++---- .../async-await/try-on-option-in-async.stderr | 12 +++++----- src/test/ui/issues/issue-32709.stderr | 2 +- src/test/ui/question-mark-type-infer.stderr | 2 +- .../disallowed-positions.rs | 12 +++++----- .../disallowed-positions.stderr | 24 +++++++++---------- src/test/ui/suggestions/issue-72766.stderr | 4 ++-- src/test/ui/try-block/try-block-bad-type.rs | 6 ++--- .../ui/try-block/try-block-bad-type.stderr | 16 ++++++------- src/test/ui/try-block/try-block-in-while.rs | 2 +- .../ui/try-block/try-block-in-while.stderr | 4 ++-- .../ui/try-block/try-block-type-error.stderr | 4 ++-- src/test/ui/try-on-option-diagnostics.stderr | 16 ++++++------- src/test/ui/try-operator-custom.rs | 4 ++-- src/test/ui/try-operator-on-main.rs | 4 ++-- src/test/ui/try-operator-on-main.stderr | 8 +++---- 24 files changed, 84 insertions(+), 84 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index ed7c867b6c127..f0ca622d189b0 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -2460,8 +2460,8 @@ pub trait Iterator { } match self.try_fold((), check(f)) { - ControlFlow::Continue(()) => ops::TryCore::continue_with(None), - ControlFlow::Break(Ok(x)) => ops::TryCore::continue_with(Some(x)), + ControlFlow::Continue(()) => ops::Bubble::continue_with(None), + ControlFlow::Break(Ok(x)) => ops::Bubble::continue_with(Some(x)), ControlFlow::Break(Err(h)) => Try::from_holder(h), } } diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index e6309085d40a1..75dbbe29ca220 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -84,7 +84,7 @@ impl ops::Try2015 for ControlFlow { } #[unstable(feature = "try_trait_v2", issue = "42327")] -impl ops::TryCore for ControlFlow { +impl ops::Bubble for ControlFlow { //type Continue = C; type Ok = C; type Holder = ControlFlow; diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 05c6753c000ab..55d824e758bdf 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -185,7 +185,7 @@ pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive}; pub use self::r#try::Try2015; #[unstable(feature = "try_trait_v2", issue = "42327")] -pub use self::r#try::{BreakHolder, Try2021, TryCore}; +pub use self::r#try::{BreakHolder, Try2021, Bubble}; #[cfg(bootstrap)] #[unstable(feature = "try_trait_v2", issue = "42327")] diff --git a/library/core/src/ops/try.rs b/library/core/src/ops/try.rs index 97bd4d7ea4c9e..9da714fcafef1 100644 --- a/library/core/src/ops/try.rs +++ b/library/core/src/ops/try.rs @@ -73,19 +73,19 @@ pub trait Try2015 { all(from_method = "continue_with", from_desugaring = "QuestionMark"), message = "the `?` operator can only be used in {ItemContext} \ that returns `Result` or `Option` \ - (or another type that implements `{TryCore}`)", + (or another type that implements `{Bubble}`)", label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`", enclosing_scope = "this function should return `Result` or `Option` to accept `?`" ), on( all(from_method = "branch", from_desugaring = "QuestionMark"), message = "the `?` operator can only be applied to values \ - that implement `{TryCore}`", + that implement `{Bubble}`", label = "the `?` operator cannot be applied to type `{Self}`" ) )] #[unstable(feature = "try_trait_v2", issue = "42327")] -pub trait TryCore { +pub trait Bubble { /// The type of the value consumed or produced when not short-circuiting. #[unstable(feature = "try_trait_v2", issue = "42327")] // Temporarily using `Ok` still so I don't need to change the bounds in the library @@ -119,8 +119,8 @@ pub trait TryCore { Self: Try2021, Self::Holder: BreakHolder, { - match TryCore::branch(self) { - ControlFlow::Continue(c) => TryCore::continue_with(f(c)), + match Bubble::branch(self) { + ControlFlow::Continue(c) => Bubble::continue_with(f(c)), //ControlFlow::Break(h) => BreakHolder::::expand(h), ControlFlow::Break(h) => Try2021::from_holder(h), } @@ -157,7 +157,7 @@ pub trait BreakHolder: Sized { enclosing_scope = "this function should return `Result` or `Option` to accept `?`" ))] #[unstable(feature = "try_trait_v2", issue = "42327")] -pub trait Try2021::Holder>: TryCore +pub trait Try2021::Holder>: Bubble where T: BreakHolder, { diff --git a/library/core/src/option.rs b/library/core/src/option.rs index ed484d158bb56..d88e51c44273a 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1724,7 +1724,7 @@ impl ops::Try2015 for Option { } #[unstable(feature = "try_trait_v2", issue = "42327")] -impl ops::TryCore for Option { +impl ops::Bubble for Option { //type Continue = T; type Ok = T; type Holder = Option; diff --git a/library/core/src/result.rs b/library/core/src/result.rs index be6128ec573d2..43a7da565ef6e 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1612,7 +1612,7 @@ impl ops::Try2015 for Result { } #[unstable(feature = "try_trait_v2", issue = "42327")] -impl ops::TryCore for Result { +impl ops::Bubble for Result { //type Continue = T; type Ok = T; type Holder = Result; diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 557bd8ce132b2..0eba830204162 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -153,11 +153,11 @@ impl ops::Try2015 for Poll> { } #[unstable(feature = "try_trait_v2", issue = "42327")] -impl ops::TryCore for Poll> { +impl ops::Bubble for Poll> { //type Continue = Poll; type Ok = Poll; //type Holder = PollResultHolder; - type Holder = as ops::TryCore>::Holder; + type Holder = as ops::Bubble>::Holder; #[inline] fn continue_with(c: Self::Ok) -> Self { @@ -231,11 +231,11 @@ impl ops::Try2015 for Poll>> { } #[unstable(feature = "try_trait_v2", issue = "42327")] -impl ops::TryCore for Poll>> { +impl ops::Bubble for Poll>> { //type Continue = Poll>; type Ok = Poll>; //type Holder = PollOptionResultHolder; - type Holder = as ops::TryCore>::Holder; + type Holder = as ops::Bubble>::Holder; #[inline] fn continue_with(c: Self::Ok) -> Self { diff --git a/src/test/ui/async-await/issue-61076.rs b/src/test/ui/async-await/issue-61076.rs index d6054a837081e..8a46ac7de1b10 100644 --- a/src/test/ui/async-await/issue-61076.rs +++ b/src/test/ui/async-await/issue-61076.rs @@ -39,9 +39,9 @@ async fn foo() -> Result<(), ()> { } async fn bar() -> Result<(), ()> { - foo()?; //~ ERROR the `?` operator can only be applied to values that implement `TryCore` + foo()?; //~ ERROR the `?` operator can only be applied to values that implement `Bubble` //~^ NOTE the `?` operator cannot be applied to type `impl Future` - //~| HELP the trait `TryCore` is not implemented for `impl Future` + //~| HELP the trait `Bubble` is not implemented for `impl Future` //~| NOTE required by `branch` //~| NOTE in this expansion of desugaring of operator `?` //~| NOTE in this expansion of desugaring of operator `?` @@ -60,9 +60,9 @@ async fn tuple() -> Tuple { async fn baz() -> Result<(), ()> { let t = T; - t?; //~ ERROR the `?` operator can only be applied to values that implement `TryCore` + t?; //~ ERROR the `?` operator can only be applied to values that implement `Bubble` //~^ NOTE the `?` operator cannot be applied to type `T` - //~| HELP the trait `TryCore` is not implemented for `T` + //~| HELP the trait `Bubble` is not implemented for `T` //~| NOTE required by `branch` //~| 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 6cd6e8e4c066c..86aafc3302e96 100644 --- a/src/test/ui/async-await/issue-61076.stderr +++ b/src/test/ui/async-await/issue-61076.stderr @@ -1,19 +1,19 @@ -error[E0277]: the `?` operator can only be applied to values that implement `TryCore` +error[E0277]: the `?` operator can only be applied to values that implement `Bubble` --> $DIR/issue-61076.rs:42:5 | LL | foo()?; | ^^^^^^ the `?` operator cannot be applied to type `impl Future` | - = help: the trait `TryCore` is not implemented for `impl Future` + = help: the trait `Bubble` is not implemented for `impl Future` = note: required by `branch` -error[E0277]: the `?` operator can only be applied to values that implement `TryCore` +error[E0277]: the `?` operator can only be applied to values that implement `Bubble` --> $DIR/issue-61076.rs:63:5 | LL | t?; | ^^ the `?` operator cannot be applied to type `T` | - = help: the trait `TryCore` is not implemented for `T` + = help: the trait `Bubble` is not implemented for `T` = note: required by `branch` error[E0609]: no field `0` on type `impl Future` 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 dbcb6075a1fc8..35d0197146a5b 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,4 +1,4 @@ -error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `Try2021`) +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 | LL | async { @@ -10,10 +10,10 @@ LL | | 22 LL | | } | |_____- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try2021>` is not implemented for `{integer}` + = help: the trait `Try>` is not implemented for `{integer}` = note: required by `from_holder` -error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `Try2021`) +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 | LL | let async_closure = async || { @@ -25,10 +25,10 @@ LL | | 22_u32 LL | | }; | |_____- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try2021>` is not implemented for `u32` + = help: the trait `Try>` is not implemented for `u32` = note: required by `from_holder` -error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `Try2021`) +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 | LL | async fn an_async_function() -> u32 { @@ -40,7 +40,7 @@ LL | | 22 LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try2021>` is not implemented for `u32` + = help: the trait `Try>` is not implemented for `u32` = note: required by `from_holder` error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-32709.stderr b/src/test/ui/issues/issue-32709.stderr index e110e1e2aee9a..7f89d961c8ef7 100644 --- a/src/test/ui/issues/issue-32709.stderr +++ b/src/test/ui/issues/issue-32709.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `(): From<{integer}>` is not satisfied LL | Err(5)?; | ^^^^^^^ the trait `From<{integer}>` is not implemented for `()` | - = note: required because of the requirements on the impl of `Try>` for `std::result::Result` + = note: required because of the requirements on the impl of `Try2021>` for `std::result::Result` = note: required by `from_holder` error: aborting due to previous error diff --git a/src/test/ui/question-mark-type-infer.stderr b/src/test/ui/question-mark-type-infer.stderr index 0ea47be2477aa..5bde1a5e26bd1 100644 --- a/src/test/ui/question-mark-type-infer.stderr +++ b/src/test/ui/question-mark-type-infer.stderr @@ -4,7 +4,7 @@ error[E0283]: type annotations needed LL | l.iter().map(f).collect()? | ^^^^^^^ cannot infer type | - = note: cannot satisfy `_: TryCore` + = note: cannot satisfy `_: Bubble` = note: required by `branch` help: consider specifying the type argument in the method call | diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs index fe727da67ceec..10f555bfaaf26 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs @@ -40,11 +40,11 @@ fn nested_within_if_expr() { fn _check_try_binds_tighter() -> Result<(), ()> { if let 0 = 0? {} - //~^ ERROR the `?` operator can only be applied to values that implement `TryCore` + //~^ ERROR the `?` operator can only be applied to values that implement `Bubble` Ok(()) } if (let 0 = 0)? {} //~ ERROR `let` expressions are not supported here - //~^ ERROR the `?` operator can only be applied to values that implement `TryCore` + //~^ ERROR the `?` operator can only be applied to values that implement `Bubble` //~| ERROR the `?` operator can only be used in a function that returns `Result` if true || let 0 = 0 {} //~ ERROR `let` expressions are not supported here @@ -104,11 +104,11 @@ fn nested_within_while_expr() { fn _check_try_binds_tighter() -> Result<(), ()> { while let 0 = 0? {} - //~^ ERROR the `?` operator can only be applied to values that implement `TryCore` + //~^ ERROR the `?` operator can only be applied to values that implement `Bubble` Ok(()) } while (let 0 = 0)? {} //~ ERROR `let` expressions are not supported here - //~^ ERROR the `?` operator can only be applied to values that implement `TryCore` + //~^ ERROR the `?` operator can only be applied to values that implement `Bubble` //~| ERROR the `?` operator can only be used in a function that returns `Result` while true || let 0 = 0 {} //~ ERROR `let` expressions are not supported here @@ -177,12 +177,12 @@ fn outside_if_and_while_expr() { fn _check_try_binds_tighter() -> Result<(), ()> { let 0 = 0?; - //~^ ERROR the `?` operator can only be applied to values that implement `TryCore` + //~^ ERROR the `?` operator can only be applied to values that implement `Bubble` Ok(()) } (let 0 = 0)?; //~ ERROR `let` expressions are not supported here //~^ ERROR the `?` operator can only be used in a function that returns `Result` - //~| ERROR the `?` operator can only be applied to values that implement `TryCore` + //~| ERROR the `?` operator can only be applied to values that implement `Bubble` true || let 0 = 0; //~ ERROR `let` expressions are not supported here (true || let 0 = 0); //~ ERROR `let` expressions are not supported here 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 71cf252f03010..cfc5445c709a9 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 @@ -551,13 +551,13 @@ error[E0600]: cannot apply unary operator `-` to type `bool` LL | if -let 0 = 0 {} | ^^^^^^^^^^ cannot apply unary operator `-` -error[E0277]: the `?` operator can only be applied to values that implement `TryCore` +error[E0277]: the `?` operator can only be applied to values that implement `Bubble` --> $DIR/disallowed-positions.rs:46:8 | LL | if (let 0 = 0)? {} | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` | - = help: the trait `TryCore` is not implemented for `bool` + = help: the trait `Bubble` is not implemented for `bool` = 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 `Try2021`) @@ -709,13 +709,13 @@ LL | if let Range { start: true, end } = t..&&false {} = note: expected type `bool` found struct `std::ops::Range` -error[E0277]: the `?` operator can only be applied to values that implement `TryCore` +error[E0277]: the `?` operator can only be applied to values that implement `Bubble` --> $DIR/disallowed-positions.rs:42:20 | LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` | - = help: the trait `TryCore` is not implemented for `{integer}` + = help: the trait `Bubble` is not implemented for `{integer}` = note: required by `branch` error[E0308]: mismatched types @@ -739,13 +739,13 @@ error[E0600]: cannot apply unary operator `-` to type `bool` LL | while -let 0 = 0 {} | ^^^^^^^^^^ cannot apply unary operator `-` -error[E0277]: the `?` operator can only be applied to values that implement `TryCore` +error[E0277]: the `?` operator can only be applied to values that implement `Bubble` --> $DIR/disallowed-positions.rs:110:11 | LL | while (let 0 = 0)? {} | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` | - = help: the trait `TryCore` is not implemented for `bool` + = help: the trait `Bubble` is not implemented for `bool` = 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 `Try2021`) @@ -897,13 +897,13 @@ LL | while let Range { start: true, end } = t..&&false {} = note: expected type `bool` found struct `std::ops::Range` -error[E0277]: the `?` operator can only be applied to values that implement `TryCore` +error[E0277]: the `?` operator can only be applied to values that implement `Bubble` --> $DIR/disallowed-positions.rs:106:23 | LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` | - = help: the trait `TryCore` is not implemented for `{integer}` + = help: the trait `Bubble` is not implemented for `{integer}` = note: required by `branch` error[E0614]: type `bool` cannot be dereferenced @@ -918,13 +918,13 @@ error[E0600]: cannot apply unary operator `-` to type `bool` LL | -let 0 = 0; | ^^^^^^^^^^ cannot apply unary operator `-` -error[E0277]: the `?` operator can only be applied to values that implement `TryCore` +error[E0277]: the `?` operator can only be applied to values that implement `Bubble` --> $DIR/disallowed-positions.rs:183:5 | LL | (let 0 = 0)?; | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` | - = help: the trait `TryCore` is not implemented for `bool` + = help: the trait `Bubble` is not implemented for `bool` = 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 `Try2021`) @@ -965,13 +965,13 @@ LL | fn outside_if_and_while_expr() { LL | &let 0 = 0 | ^^^^^^^^^^ expected `()`, found `&bool` -error[E0277]: the `?` operator can only be applied to values that implement `TryCore` +error[E0277]: the `?` operator can only be applied to values that implement `Bubble` --> $DIR/disallowed-positions.rs:179:17 | LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` | - = help: the trait `TryCore` is not implemented for `{integer}` + = help: the trait `Bubble` is not implemented for `{integer}` = 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 77d57e11e0846..702a7de7af947 100644 --- a/src/test/ui/suggestions/issue-72766.stderr +++ b/src/test/ui/suggestions/issue-72766.stderr @@ -1,10 +1,10 @@ -error[E0277]: the `?` operator can only be applied to values that implement `TryCore` +error[E0277]: the `?` operator can only be applied to values that implement `Bubble` --> $DIR/issue-72766.rs:14:5 | LL | SadGirl {}.call()?; | ^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future` | - = help: the trait `TryCore` is not implemented for `impl Future` + = help: the trait `Bubble` is not implemented for `impl Future` = note: required by `branch` error: aborting due to previous error 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 4980672ec40a9..c5e30e3ec5544 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,8 @@ pub fn main() { let res: Result = try { }; //~ ERROR type mismatch let res: () = try { }; - //~^ ERROR the trait bound `(): TryCore` is not satisfied - //~| ERROR the trait bound `(): TryCore` is not satisfied + //~^ ERROR the trait bound `(): Bubble` is not satisfied + //~| ERROR the trait bound `(): Bubble` is not satisfied - let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: TryCore` is not satisfied + let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: Bubble` is not satisfied } 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 8936680c6b8fe..d6b17baa92a7d 100644 --- a/src/test/ui/try-block/try-block-bad-type.stderr +++ b/src/test/ui/try-block/try-block-bad-type.stderr @@ -8,37 +8,37 @@ LL | Err("")?; > = note: required by `from` -error[E0271]: type mismatch resolving ` as TryCore>::Ok == &str` +error[E0271]: type mismatch resolving ` as Bubble>::Ok == &str` --> $DIR/try-block-bad-type.rs:12:9 | LL | "" | ^^ expected `i32`, found `&str` -error[E0271]: type mismatch resolving ` as TryCore>::Ok == ()` +error[E0271]: type mismatch resolving ` as Bubble>::Ok == ()` --> $DIR/try-block-bad-type.rs:15:39 | LL | let res: Result = try { }; | ^ expected `i32`, found `()` -error[E0277]: the trait bound `(): TryCore` is not satisfied +error[E0277]: the trait bound `(): Bubble` is not satisfied --> $DIR/try-block-bad-type.rs:17:25 | LL | let res: () = try { }; - | ^ the trait `TryCore` is not implemented for `()` + | ^ the trait `Bubble` is not implemented for `()` | = note: required by `continue_with` -error[E0277]: the trait bound `(): TryCore` is not satisfied +error[E0277]: the trait bound `(): Bubble` is not satisfied --> $DIR/try-block-bad-type.rs:17:25 | LL | let res: () = try { }; - | ^ the trait `TryCore` is not implemented for `()` + | ^ the trait `Bubble` is not implemented for `()` -error[E0277]: the trait bound `i32: TryCore` is not satisfied +error[E0277]: the trait bound `i32: Bubble` is not satisfied --> $DIR/try-block-bad-type.rs:21:26 | LL | let res: i32 = try { 5 }; - | ^ the trait `TryCore` is not implemented for `i32` + | ^ the trait `Bubble` is not implemented for `i32` | = note: required by `continue_with` 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 05e57b0b8c170..72f50fc35d035 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: TryCore` is not satisfied + //~^ ERROR the trait bound `bool: Bubble` is not satisfied } 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 e638fc4022f0b..3c47be84a8c96 100644 --- a/src/test/ui/try-block/try-block-in-while.stderr +++ b/src/test/ui/try-block/try-block-in-while.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `bool: TryCore` is not satisfied +error[E0277]: the trait bound `bool: Bubble` is not satisfied --> $DIR/try-block-in-while.rs:6:17 | LL | while try { false } {} - | ^^^^^ the trait `TryCore` is not implemented for `bool` + | ^^^^^ the trait `Bubble` is not implemented for `bool` | = note: required by `continue_with` 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 7d8b8266d8c99..ab0652476e12e 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 ` as TryCore>::Ok == {integer}` +error[E0271]: type mismatch resolving ` as Bubble>::Ok == {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 ` as TryCore>::Ok == ()` +error[E0271]: type mismatch resolving ` as Bubble>::Ok == ()` --> $DIR/try-block-type-error.rs:16:5 | LL | }; diff --git a/src/test/ui/try-on-option-diagnostics.stderr b/src/test/ui/try-on-option-diagnostics.stderr index f704b84e13e29..726e2225baf8e 100644 --- a/src/test/ui/try-on-option-diagnostics.stderr +++ b/src/test/ui/try-on-option-diagnostics.stderr @@ -1,4 +1,4 @@ -error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`) +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try2021`) --> $DIR/try-on-option-diagnostics.rs:7:5 | LL | / fn a_function() -> u32 { @@ -9,10 +9,10 @@ LL | | 22 LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try>` is not implemented for `u32` + = help: the trait `Try2021>` is not implemented for `u32` = note: required by `from_holder` -error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `Try`) +error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `Try2021`) --> $DIR/try-on-option-diagnostics.rs:14:9 | LL | let a_closure = || { @@ -24,10 +24,10 @@ LL | | 22 LL | | }; | |_____- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try>` is not implemented for `{integer}` + = help: the trait `Try2021>` is not implemented for `{integer}` = note: required by `from_holder` -error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `Try`) +error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `Try2021`) --> $DIR/try-on-option-diagnostics.rs:26:13 | LL | / fn a_method() { @@ -37,10 +37,10 @@ LL | | x?; LL | | } | |_________- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try>` is not implemented for `()` + = help: the trait `Try2021>` is not implemented for `()` = note: required by `from_holder` -error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `Try`) +error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `Try2021`) --> $DIR/try-on-option-diagnostics.rs:39:13 | LL | / fn a_trait_method() { @@ -50,7 +50,7 @@ LL | | x?; LL | | } | |_________- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try>` is not implemented for `()` + = help: the trait `Try2021>` is not implemented for `()` = note: required by `from_holder` error: aborting due to 4 previous errors diff --git a/src/test/ui/try-operator-custom.rs b/src/test/ui/try-operator-custom.rs index 951c9b9ba72b3..eb6acfaa7d44d 100644 --- a/src/test/ui/try-operator-custom.rs +++ b/src/test/ui/try-operator-custom.rs @@ -6,7 +6,7 @@ #![feature(try_trait_v2)] use std::convert::Infallible; -use std::ops::{BreakHolder, ControlFlow, Try2015, Try2021, TryCore}; +use std::ops::{BreakHolder, ControlFlow, Try2015, Try2021, Bubble}; enum MyResult { Awesome(T), @@ -33,7 +33,7 @@ impl Try2015 for MyResult { } } -impl TryCore for MyResult { +impl Bubble for MyResult { //type Continue = U; type Ok = U; type Holder = MyResult; diff --git a/src/test/ui/try-operator-on-main.rs b/src/test/ui/try-operator-on-main.rs index 581316e5cae65..012a7861ca971 100644 --- a/src/test/ui/try-operator-on-main.rs +++ b/src/test/ui/try-operator-on-main.rs @@ -11,7 +11,7 @@ fn main() { // a non-`Try` type on a non-`Try` fn ()?; //~ ERROR the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try2021`) - //~^ ERROR the `?` operator can only be applied to values that implement `TryCore` + //~^ ERROR the `?` operator can only be applied to values that implement `Bubble` // an unrelated use of `Try` try_trait_generic::<()>(); //~ ERROR the trait bound @@ -21,7 +21,7 @@ fn main() { fn try_trait_generic() -> T { // and a non-`Try` object on a `Try` fn. - ()?; //~ ERROR the `?` operator can only be applied to values that implement `TryCore` + ()?; //~ ERROR the `?` operator can only be applied to values that implement `Bubble` loop {} } diff --git a/src/test/ui/try-operator-on-main.stderr b/src/test/ui/try-operator-on-main.stderr index 4ad497b31e36e..7db046a387d2b 100644 --- a/src/test/ui/try-operator-on-main.stderr +++ b/src/test/ui/try-operator-on-main.stderr @@ -14,13 +14,13 @@ LL | | } = help: the trait `Try2021>` is not implemented for `()` = note: required by `from_holder` -error[E0277]: the `?` operator can only be applied to values that implement `TryCore` +error[E0277]: the `?` operator can only be applied to values that implement `Bubble` --> $DIR/try-operator-on-main.rs:13:5 | LL | ()?; | ^^^ the `?` operator cannot be applied to type `()` | - = help: the trait `TryCore` is not implemented for `()` + = help: the trait `Bubble` is not implemented for `()` = 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 `Try2021`) @@ -50,13 +50,13 @@ LL | try_trait_generic::<()>(); LL | fn try_trait_generic() -> T { | --- required by this bound in `try_trait_generic` -error[E0277]: the `?` operator can only be applied to values that implement `TryCore` +error[E0277]: the `?` operator can only be applied to values that implement `Bubble` --> $DIR/try-operator-on-main.rs:24:5 | LL | ()?; | ^^^ the `?` operator cannot be applied to type `()` | - = help: the trait `TryCore` is not implemented for `()` + = help: the trait `Bubble` is not implemented for `()` = note: required by `branch` error: aborting due to 5 previous errors From 74f977100848454e9362166229daee66efbd74d9 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 24 Jan 2021 14:21:38 -0800 Subject: [PATCH 03/10] Simplify the approach - Make the non-generic trait be the subtrait, for simplicity - Move `BreakHolder` to future work (not required for just `?`/`try {}`) --- library/core/src/iter/adapters/peekable.rs | 4 +- library/core/src/iter/traits/iterator.rs | 16 +++-- library/core/src/ops/control_flow.rs | 24 ++++--- library/core/src/ops/mod.rs | 2 +- library/core/src/ops/try.rs | 66 +++++++----------- library/core/src/option.rs | 16 ++--- library/core/src/result.rs | 20 +++--- library/core/src/task/poll.rs | 53 ++++----------- src/test/ui/async-await/issue-61076.rs | 8 +-- src/test/ui/async-await/issue-61076.stderr | 8 +-- .../async-await/try-on-option-in-async.stderr | 18 ++--- src/test/ui/issues/issue-32709.stderr | 9 ++- src/test/ui/option-to-result.rs | 2 +- src/test/ui/option-to-result.stderr | 16 +++-- src/test/ui/question-mark-type-infer.stderr | 7 +- .../disallowed-positions.rs | 12 ++-- .../disallowed-positions.stderr | 42 ++++++------ src/test/ui/suggestions/issue-72766.stderr | 4 +- src/test/ui/try-block/try-block-bad-type.rs | 5 +- .../ui/try-block/try-block-bad-type.stderr | 27 +++----- src/test/ui/try-block/try-block-in-while.rs | 2 +- .../ui/try-block/try-block-in-while.stderr | 6 +- .../ui/try-block/try-block-type-error.stderr | 4 +- src/test/ui/try-on-option-diagnostics.stderr | 24 +++---- src/test/ui/try-operator-on-main.rs | 7 +- src/test/ui/try-operator-on-main.stderr | 42 ++++-------- .../try-trait/try-control-flow-in-result.rs | 15 ++++ .../try-control-flow-in-result.stderr | 16 +++++ src/test/ui/try-trait/try-fold-rfc-example.rs | 68 +++++++++++++++++++ src/test/ui/try-trait/try-non-generic-type.rs | 65 ++++++++++++++++++ .../try-on-option-in-result-method.rs | 0 src/test/ui/{ => try-trait}/try-on-option.rs | 2 +- .../ui/{ => try-trait}/try-on-option.stderr | 16 +++-- .../ui/{ => try-trait}/try-operator-custom.rs | 30 ++++---- src/test/ui/{ => try-trait}/try-operator.rs | 0 src/test/ui/{ => try-trait}/try-poll.rs | 0 36 files changed, 383 insertions(+), 273 deletions(-) create mode 100644 src/test/ui/try-trait/try-control-flow-in-result.rs create mode 100644 src/test/ui/try-trait/try-control-flow-in-result.stderr create mode 100644 src/test/ui/try-trait/try-fold-rfc-example.rs create mode 100644 src/test/ui/try-trait/try-non-generic-type.rs rename src/test/ui/{ => try-trait}/try-on-option-in-result-method.rs (100%) rename src/test/ui/{ => try-trait}/try-on-option.rs (70%) rename src/test/ui/{ => try-trait}/try-on-option.stderr (59%) rename src/test/ui/{ => try-trait}/try-operator-custom.rs (69%) rename src/test/ui/{ => try-trait}/try-operator.rs (100%) rename src/test/ui/{ => try-trait}/try-poll.rs (100%) diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index c78ecd7c54778..43cb182416019 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -164,9 +164,9 @@ where Some(None) => try { init }, Some(Some(v)) => match self.iter.try_rfold(init, &mut f).branch() { ControlFlow::Continue(acc) => f(acc, v), - ControlFlow::Break(h) => { + ControlFlow::Break(r) => { self.peeked = Some(Some(v)); - R::from_holder(h) + R::from_residual(r) } }, None => self.iter.try_rfold(init, f), diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index f0ca622d189b0..004b7a4a6ebca 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -4,6 +4,8 @@ use crate::cmp::{self, Ordering}; use crate::ops::{self, Add, ControlFlow, Try}; +#[cfg(not(bootstrap))] +use crate::ops::FromTryResidual; use super::super::TrustedRandomAccess; use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse}; @@ -2439,15 +2441,15 @@ pub trait Iterator { fn try_find( &mut self, f: F, - ) -> >>::Output + ) -> >>::Output where Self: Sized, F: FnMut(&Self::Item) -> R, R: ops::Try, - R::Holder: ops::BreakHolder>, + R::Residual: ops::GetCorrespondingTryType>, { #[inline] - fn check(mut f: F) -> impl FnMut((), T) -> ControlFlow> + fn check(mut f: F) -> impl FnMut((), T) -> ControlFlow> where F: FnMut(&T) -> R, R: Try, @@ -2455,14 +2457,14 @@ pub trait Iterator { move |(), x| match f(&x).branch() { ControlFlow::Continue(false) => ControlFlow::CONTINUE, ControlFlow::Continue(true) => ControlFlow::Break(Ok(x)), - ControlFlow::Break(h) => ControlFlow::Break(Err(h)), + ControlFlow::Break(r) => ControlFlow::Break(Err(r)), } } match self.try_fold((), check(f)) { - ControlFlow::Continue(()) => ops::Bubble::continue_with(None), - ControlFlow::Break(Ok(x)) => ops::Bubble::continue_with(Some(x)), - ControlFlow::Break(Err(h)) => Try::from_holder(h), + ControlFlow::Continue(()) => Try::from_output(None), + ControlFlow::Break(Ok(x)) => Try::from_output(Some(x)), + ControlFlow::Break(Err(r)) => <_>::from_residual(r), } } diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 75dbbe29ca220..a2dbe6fbacc1d 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -84,16 +84,18 @@ impl ops::Try2015 for ControlFlow { } #[unstable(feature = "try_trait_v2", issue = "42327")] -impl ops::Bubble for ControlFlow { - //type Continue = C; +impl ops::Try2021 for ControlFlow { + //type Output = C; type Ok = C; - type Holder = ControlFlow; + type Residual = ControlFlow; + #[inline] - fn continue_with(c: C) -> Self { + fn from_output(c: C) -> Self { ControlFlow::Continue(c) } + #[inline] - fn branch(self) -> ControlFlow { + fn branch(self) -> ControlFlow { match self { ControlFlow::Continue(c) => ControlFlow::Continue(c), ControlFlow::Break(b) => ControlFlow::Break(ControlFlow::Break(b)), @@ -102,7 +104,7 @@ impl ops::Bubble for ControlFlow { } #[unstable(feature = "try_trait_v2", issue = "42327")] -impl ops::BreakHolder for ControlFlow { +impl ops::GetCorrespondingTryType for ControlFlow { type Output = ControlFlow; // fn expand(x: Self) -> Self::Output { // match x { @@ -112,10 +114,10 @@ impl ops::BreakHolder for ControlFlow { } #[unstable(feature = "try_trait_v2", issue = "42327")] -impl ops::Try2021 for ControlFlow { - fn from_holder(x: Self::Holder) -> Self { +impl ops::FromTryResidual for ControlFlow { + fn from_residual(x: ::Residual) -> Self { match x { - ControlFlow::Break(b) => ControlFlow::Break(b), + ControlFlow::Break(r) => ControlFlow::Break(r), } } } @@ -222,7 +224,7 @@ impl ControlFlow { pub fn from_try(r: R) -> Self { match r.branch() { ControlFlow::Continue(v) => ControlFlow::Continue(v), - ControlFlow::Break(h) => ControlFlow::Break(R::from_holder(h)), + ControlFlow::Break(r) => ControlFlow::Break(R::from_residual(r)), } } @@ -231,7 +233,7 @@ impl ControlFlow { #[inline] pub fn into_try(self) -> R { match self { - ControlFlow::Continue(v) => R::continue_with(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 55d824e758bdf..44f1ca27c4d30 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -185,7 +185,7 @@ pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive}; pub use self::r#try::Try2015; #[unstable(feature = "try_trait_v2", issue = "42327")] -pub use self::r#try::{BreakHolder, Try2021, Bubble}; +pub use self::r#try::{GetCorrespondingTryType, FromTryResidual, Try2021}; #[cfg(bootstrap)] #[unstable(feature = "try_trait_v2", issue = "42327")] diff --git a/library/core/src/ops/try.rs b/library/core/src/ops/try.rs index 9da714fcafef1..58146c3c249f1 100644 --- a/library/core/src/ops/try.rs +++ b/library/core/src/ops/try.rs @@ -73,75 +73,55 @@ pub trait Try2015 { all(from_method = "continue_with", from_desugaring = "QuestionMark"), message = "the `?` operator can only be used in {ItemContext} \ that returns `Result` or `Option` \ - (or another type that implements `{Bubble}`)", + (or another type that implements `{Try2021}`)", label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`", enclosing_scope = "this function should return `Result` or `Option` to accept `?`" ), on( all(from_method = "branch", from_desugaring = "QuestionMark"), message = "the `?` operator can only be applied to values \ - that implement `{Bubble}`", + that implement `{Try2021}`", label = "the `?` operator cannot be applied to type `{Self}`" ) )] #[unstable(feature = "try_trait_v2", issue = "42327")] -pub trait Bubble { +pub trait Try2021: FromTryResidual { /// The type of the value consumed or produced when not short-circuiting. #[unstable(feature = "try_trait_v2", issue = "42327")] // Temporarily using `Ok` still so I don't need to change the bounds in the library - //type Continue; + //type Output; type Ok; /// A type that "colours" the short-circuit value so it can stay associated /// with the type constructor from which it came. #[unstable(feature = "try_trait_v2", issue = "42327")] - // This could have required that we can get back here via the holder, - // but that means that every type needs a distinct holder. It was removed - // so that the Poll impls can use Result's Holder. - //type Holder: BreakHolder; - type Holder: BreakHolder; + type Residual; /// Used in `try{}` blocks to wrap the result of the block. #[cfg_attr(not(bootstrap), lang = "continue_with")] #[unstable(feature = "try_trait_v2", issue = "42327")] - fn continue_with(x: Self::Ok) -> Self; + fn from_output(x: Self::Ok) -> Self; /// Determine whether to short-circuit (by returning `ControlFlow::Break`) /// or continue executing (by returning `ControlFlow::Continue`). #[cfg_attr(not(bootstrap), lang = "branch")] #[unstable(feature = "try_trait_v2", issue = "42327")] - fn branch(self) -> ControlFlow; + fn branch(self) -> ControlFlow; /// Demonstration that this is usable for different-return-type scenarios (like `Iterator::try_find`). #[unstable(feature = "try_trait_v2", issue = "42327")] - fn map(self, f: impl FnOnce(Self::Ok) -> T) -> >::Output + fn map(self, f: impl FnOnce(Self::Ok) -> T) -> >::Output where Self: Try2021, - Self::Holder: BreakHolder, + Self::Residual: GetCorrespondingTryType, { - match Bubble::branch(self) { - ControlFlow::Continue(c) => Bubble::continue_with(f(c)), - //ControlFlow::Break(h) => BreakHolder::::expand(h), - ControlFlow::Break(h) => Try2021::from_holder(h), + match self.branch() { + ControlFlow::Continue(c) => Try2021::from_output(f(c)), + ControlFlow::Break(r) => FromTryResidual::from_residual(r), } } } -/// The bound on a `::Holder` type that allows getting back to the original. -#[unstable(feature = "try_trait_v2", issue = "42327")] -pub trait BreakHolder: Sized { - /// The type from the original type constructor that also has this holder type, - /// but has the specified Continue type. - #[unstable(feature = "try_trait_v2", issue = "42327")] - type Output: Try2021; - - /* Superfluous now that `FromHolder` exists - /// Rebuild the associated `impl Try` type from this holder. - #[unstable(feature = "try_trait_v2", issue = "42327")] - fn expand(x: Self) -> Self::Output; - */ -} - /// Allows you to pick with other types can be converted into your `Try` type. /// /// With the default type argument, this functions as a bound for a "normal" @@ -149,20 +129,26 @@ pub trait BreakHolder: Sized { /// /// For more complicated scenarios you'll likely need to bound on more than just this. #[rustc_on_unimplemented(on( - all(from_method = "from_holder", from_desugaring = "QuestionMark"), + 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 `{Try2021}`)", + (or another type that implements `{FromTryResidual}`)", 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 = "42327")] -pub trait Try2021::Holder>: Bubble -where - T: BreakHolder, -{ - /// Perform conversion on this holder +pub trait FromTryResidual::Residual> { + /// Recreate the `Try` type from a related residual #[cfg_attr(not(bootstrap), lang = "from_holder")] #[unstable(feature = "try_trait_v2", issue = "42327")] - fn from_holder(x: T) -> Self; + fn from_residual(x: Residual) -> Self; +} + +/// The bound on a `::Residual` type that allows getting back to the original. +#[unstable(feature = "try_trait_v2", issue = "42327")] +pub trait GetCorrespondingTryType: Sized { + /// The type from the original type constructor that also has this residual type, + /// but has the specified Output type. + #[unstable(feature = "try_trait_v2", issue = "42327")] + type Output: Try2021; } diff --git a/library/core/src/option.rs b/library/core/src/option.rs index d88e51c44273a..50c114b7faabf 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1724,18 +1724,18 @@ impl ops::Try2015 for Option { } #[unstable(feature = "try_trait_v2", issue = "42327")] -impl ops::Bubble for Option { - //type Continue = T; +impl ops::Try2021 for Option { + //type Output = T; type Ok = T; - type Holder = Option; + type Residual = Option; #[inline] - fn continue_with(c: T) -> Self { + fn from_output(c: T) -> Self { Some(c) } #[inline] - fn branch(self) -> ControlFlow { + fn branch(self) -> ControlFlow { match self { Some(c) => ControlFlow::Continue(c), None => ControlFlow::Break(None), @@ -1744,7 +1744,7 @@ impl ops::Bubble for Option { } #[unstable(feature = "try_trait_v2", issue = "42327")] -impl ops::BreakHolder for Option { +impl ops::GetCorrespondingTryType for Option { type Output = Option; // fn expand(x: Self) -> Self::Output { @@ -1755,8 +1755,8 @@ impl ops::BreakHolder for Option { } #[unstable(feature = "try_trait_v2", issue = "42327")] -impl ops::Try2021> for Option { - fn from_holder(x: Self::Holder) -> Self { +impl ops::FromTryResidual for Option { + fn from_residual(x: ::Residual) -> Self { match x { None => None, } diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 43a7da565ef6e..27e1f4ca1004f 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1612,18 +1612,18 @@ impl ops::Try2015 for Result { } #[unstable(feature = "try_trait_v2", issue = "42327")] -impl ops::Bubble for Result { - //type Continue = T; +impl ops::Try2021 for Result { + //type Output = T; type Ok = T; - type Holder = Result; + type Residual = Result; #[inline] - fn continue_with(c: T) -> Self { + fn from_output(c: T) -> Self { Ok(c) } #[inline] - fn branch(self) -> ControlFlow { + fn branch(self) -> ControlFlow { match self { Ok(c) => ControlFlow::Continue(c), Err(e) => ControlFlow::Break(Err(e)), @@ -1632,7 +1632,7 @@ impl ops::Bubble for Result { } #[unstable(feature = "try_trait_v2", issue = "42327")] -impl ops::BreakHolder for Result { +impl ops::GetCorrespondingTryType for Result { type Output = Result; // fn expand(x: Self) -> Self::Output { @@ -1643,8 +1643,8 @@ impl ops::BreakHolder for Result { } #[unstable(feature = "try_trait_v2", issue = "42327")] -impl> ops::Try2021> for Result { - fn from_holder(x: Result) -> Self { +impl> ops::FromTryResidual> for Result { + fn from_residual(x: Result) -> Self { match x { Err(e) => Err(From::from(e)), } @@ -1662,11 +1662,11 @@ mod sadness { pub struct PleaseCallTheOkOrMethodToUseQuestionMarkOnOptionsInAMethodThatReturnsResult; #[unstable(feature = "try_trait_v2", issue = "42327")] - impl ops::Try2021> for Result + impl ops::FromTryResidual> for Result where E: From, { - fn from_holder(x: Option) -> Self { + fn from_residual(x: Option) -> Self { match x { None => Err(From::from( PleaseCallTheOkOrMethodToUseQuestionMarkOnOptionsInAMethodThatReturnsResult, diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 0eba830204162..9a0ad55f8c583 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -153,19 +153,18 @@ impl ops::Try2015 for Poll> { } #[unstable(feature = "try_trait_v2", issue = "42327")] -impl ops::Bubble for Poll> { - //type Continue = Poll; +impl ops::Try2021 for Poll> { + //type Output = Poll; type Ok = Poll; - //type Holder = PollResultHolder; - type Holder = as ops::Bubble>::Holder; + type Residual = as ops::Try2021>::Residual; #[inline] - fn continue_with(c: Self::Ok) -> Self { + fn from_output(c: Self::Ok) -> Self { c.map(Ok) } #[inline] - fn branch(self) -> ControlFlow { + fn branch(self) -> ControlFlow { match self { Poll::Ready(Ok(x)) => ControlFlow::Continue(Poll::Ready(x)), Poll::Ready(Err(e)) => ControlFlow::Break(Err(e)), @@ -174,30 +173,9 @@ impl ops::Bubble for Poll> { } } -/* This is needed if the Try::Holder bound gets tighter again - -#[unstable(feature = "try_trait_v2_never_stable", issue = "42327")] -#[allow(missing_debug_implementations)] -/// This type is *only* useful for `expand`ing, -/// so it's intentional that it implements no traits. -pub struct PollResultHolder(E); - -#[unstable(feature = "try_trait_v2", issue = "42327")] -impl BreakHolder> for PollResultHolder { - type Output = Poll>; - - fn expand(x: Self) -> Self::Output { - match x { - PollResultHolder(e) => Poll::Ready(Err(e)), - } - } -} - -*/ - #[unstable(feature = "try_trait_v2", issue = "42327")] -impl> ops::Try2021> for Poll> { - fn from_holder(x: Result) -> Self { +impl> ops::FromTryResidual> for Poll> { + fn from_residual(x: Result) -> Self { match x { Err(e) => Poll::Ready(Err(From::from(e))), } @@ -231,19 +209,18 @@ impl ops::Try2015 for Poll>> { } #[unstable(feature = "try_trait_v2", issue = "42327")] -impl ops::Bubble for Poll>> { - //type Continue = Poll>; +impl ops::Try2021 for Poll>> { + //type Output = Poll>; type Ok = Poll>; - //type Holder = PollOptionResultHolder; - type Holder = as ops::Bubble>::Holder; + type Residual = as ops::Try2021>::Residual; #[inline] - fn continue_with(c: Self::Ok) -> Self { + fn from_output(c: Self::Ok) -> Self { c.map(|x| x.map(Ok)) } #[inline] - fn branch(self) -> ControlFlow { + fn branch(self) -> ControlFlow { match self { Poll::Ready(Some(Ok(x))) => ControlFlow::Continue(Poll::Ready(Some(x))), Poll::Ready(Some(Err(e))) => ControlFlow::Break(Err(e)), @@ -262,7 +239,7 @@ impl ops::Bubble for Poll>> { pub struct PollOptionResultHolder(E); #[unstable(feature = "try_trait_v2", issue = "42327")] -impl BreakHolder>> for PollOptionResultHolder { +impl GetCorrespondingTryType>> for PollOptionResultHolder { type Output = Poll>>; fn expand(x: Self) -> Self::Output { @@ -275,8 +252,8 @@ impl BreakHolder>> for PollOptionResultHolder { */ #[unstable(feature = "try_trait_v2", issue = "42327")] -impl> ops::Try2021> for Poll>> { - fn from_holder(x: Result) -> Self { +impl> ops::FromTryResidual> for Poll>> { + fn from_residual(x: Result) -> Self { match x { Err(e) => Poll::Ready(Some(Err(From::from(e)))), } diff --git a/src/test/ui/async-await/issue-61076.rs b/src/test/ui/async-await/issue-61076.rs index 8a46ac7de1b10..e9b80534822e6 100644 --- a/src/test/ui/async-await/issue-61076.rs +++ b/src/test/ui/async-await/issue-61076.rs @@ -39,9 +39,9 @@ async fn foo() -> Result<(), ()> { } async fn bar() -> Result<(), ()> { - foo()?; //~ ERROR the `?` operator can only be applied to values that implement `Bubble` + foo()?; //~ ERROR the `?` operator can only be applied to values that implement `Try2021` //~^ NOTE the `?` operator cannot be applied to type `impl Future` - //~| HELP the trait `Bubble` is not implemented for `impl Future` + //~| HELP the trait `Try2021` is not implemented for `impl Future` //~| NOTE required by `branch` //~| NOTE in this expansion of desugaring of operator `?` //~| NOTE in this expansion of desugaring of operator `?` @@ -60,9 +60,9 @@ async fn tuple() -> Tuple { async fn baz() -> Result<(), ()> { let t = T; - t?; //~ ERROR the `?` operator can only be applied to values that implement `Bubble` + t?; //~ ERROR the `?` operator can only be applied to values that implement `Try2021` //~^ NOTE the `?` operator cannot be applied to type `T` - //~| HELP the trait `Bubble` is not implemented for `T` + //~| HELP the trait `Try2021` is not implemented for `T` //~| NOTE required by `branch` //~| 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 86aafc3302e96..52420309d5db3 100644 --- a/src/test/ui/async-await/issue-61076.stderr +++ b/src/test/ui/async-await/issue-61076.stderr @@ -1,19 +1,19 @@ -error[E0277]: the `?` operator can only be applied to values that implement `Bubble` +error[E0277]: the `?` operator can only be applied to values that implement `Try2021` --> $DIR/issue-61076.rs:42:5 | LL | foo()?; | ^^^^^^ the `?` operator cannot be applied to type `impl Future` | - = help: the trait `Bubble` is not implemented for `impl Future` + = help: the trait `Try2021` is not implemented for `impl Future` = note: required by `branch` -error[E0277]: the `?` operator can only be applied to values that implement `Bubble` +error[E0277]: the `?` operator can only be applied to values that implement `Try2021` --> $DIR/issue-61076.rs:63:5 | LL | t?; | ^^ the `?` operator cannot be applied to type `T` | - = help: the trait `Bubble` is not implemented for `T` + = help: the trait `Try2021` is not implemented for `T` = note: required by `branch` error[E0609]: no field `0` on type `impl Future` 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 35d0197146a5b..f45ab87f0ac65 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,4 +1,4 @@ -error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `Try`) +error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `FromTryResidual`) --> $DIR/try-on-option-in-async.rs:8:9 | LL | async { @@ -10,10 +10,10 @@ 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_holder` + = help: the trait `FromTryResidual>` 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`) +error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `FromTryResidual`) --> $DIR/try-on-option-in-async.rs:17:9 | LL | let async_closure = async || { @@ -25,10 +25,10 @@ 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_holder` + = help: the trait `FromTryResidual>` 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`) +error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromTryResidual`) --> $DIR/try-on-option-in-async.rs:26:5 | LL | async fn an_async_function() -> u32 { @@ -40,8 +40,8 @@ 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_holder` + = help: the trait `FromTryResidual>` is not implemented for `u32` + = note: required by `from_residual` error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-32709.stderr b/src/test/ui/issues/issue-32709.stderr index 7f89d961c8ef7..79c04e2156d85 100644 --- a/src/test/ui/issues/issue-32709.stderr +++ b/src/test/ui/issues/issue-32709.stderr @@ -1,11 +1,14 @@ -error[E0277]: the trait bound `(): From<{integer}>` is not satisfied +error[E0277]: `?` couldn't convert the error to `()` --> $DIR/issue-32709.rs:4:5 | +LL | fn a() -> Result { + | --------------- expected `()` because of this LL | Err(5)?; | ^^^^^^^ the trait `From<{integer}>` is not implemented for `()` | - = note: required because of the requirements on the impl of `Try2021>` for `std::result::Result` - = note: required by `from_holder` + = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + = note: required because of the requirements on the impl of `FromTryResidual>` for `std::result::Result` + = note: required by `from_residual` error: aborting due to previous error diff --git a/src/test/ui/option-to-result.rs b/src/test/ui/option-to-result.rs index b35c0274d2379..935a96b7df958 100644 --- a/src/test/ui/option-to-result.rs +++ b/src/test/ui/option-to-result.rs @@ -2,7 +2,7 @@ fn main(){ } fn test_result() -> Result<(),()> { let a:Option<()> = Some(()); - a?;//~ ERROR the trait bound `(): From` is not satisfied +error[E0277]: `?` couldn't convert the error to `()` --> $DIR/option-to-result.rs:5:5 | +LL | fn test_result() -> Result<(),()> { + | ------------- expected `()` because of this +LL | let a:Option<()> = Some(()); LL | a?; | ^^ the trait `From` is not implemented for `()` | - = note: required because of the requirements on the impl of `Try2021>` for `std::result::Result<(), ()>` - = note: required by `from_holder` + = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + = note: required because of the requirements on the impl of `FromTryResidual>` for `std::result::Result<(), ()>` + = 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 `Try2021`) +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromTryResidual`) --> $DIR/option-to-result.rs:11:5 | LL | / fn test_option() -> Option{ @@ -18,8 +22,8 @@ LL | | Some(5) LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try2021>` is not implemented for `Option` - = note: required by `from_holder` + = help: the trait `FromTryResidual>` is not implemented for `Option` + = note: required by `from_residual` error: aborting due to 2 previous errors diff --git a/src/test/ui/question-mark-type-infer.stderr b/src/test/ui/question-mark-type-infer.stderr index 5bde1a5e26bd1..db5042b40d8bc 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 `_: Bubble` - = note: required by `branch` + = note: cannot satisfy `<_ as Try>::Residual == _` help: consider specifying the type argument in the method call | LL | l.iter().map(f).collect::()? @@ -13,4 +12,4 @@ LL | l.iter().map(f).collect::()? 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.rs b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs index 10f555bfaaf26..e10898edcc89a 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs @@ -40,11 +40,11 @@ fn nested_within_if_expr() { fn _check_try_binds_tighter() -> Result<(), ()> { if let 0 = 0? {} - //~^ ERROR the `?` operator can only be applied to values that implement `Bubble` + //~^ ERROR the `?` operator can only be applied to values that implement `Try2021` Ok(()) } if (let 0 = 0)? {} //~ ERROR `let` expressions are not supported here - //~^ ERROR the `?` operator can only be applied to values that implement `Bubble` + //~^ ERROR the `?` operator can only be applied to values that implement `Try2021` //~| ERROR the `?` operator can only be used in a function that returns `Result` if true || let 0 = 0 {} //~ ERROR `let` expressions are not supported here @@ -104,11 +104,11 @@ fn nested_within_while_expr() { fn _check_try_binds_tighter() -> Result<(), ()> { while let 0 = 0? {} - //~^ ERROR the `?` operator can only be applied to values that implement `Bubble` + //~^ ERROR the `?` operator can only be applied to values that implement `Try2021` Ok(()) } while (let 0 = 0)? {} //~ ERROR `let` expressions are not supported here - //~^ ERROR the `?` operator can only be applied to values that implement `Bubble` + //~^ ERROR the `?` operator can only be applied to values that implement `Try2021` //~| ERROR the `?` operator can only be used in a function that returns `Result` while true || let 0 = 0 {} //~ ERROR `let` expressions are not supported here @@ -177,12 +177,12 @@ fn outside_if_and_while_expr() { fn _check_try_binds_tighter() -> Result<(), ()> { let 0 = 0?; - //~^ ERROR the `?` operator can only be applied to values that implement `Bubble` + //~^ ERROR the `?` operator can only be applied to values that implement `Try2021` Ok(()) } (let 0 = 0)?; //~ ERROR `let` expressions are not supported here //~^ ERROR the `?` operator can only be used in a function that returns `Result` - //~| ERROR the `?` operator can only be applied to values that implement `Bubble` + //~| ERROR the `?` operator can only be applied to values that implement `Try2021` true || let 0 = 0; //~ ERROR `let` expressions are not supported here (true || let 0 = 0); //~ ERROR `let` expressions are not supported here 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 cfc5445c709a9..1dd19c43c569d 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 @@ -551,16 +551,16 @@ error[E0600]: cannot apply unary operator `-` to type `bool` LL | if -let 0 = 0 {} | ^^^^^^^^^^ cannot apply unary operator `-` -error[E0277]: the `?` operator can only be applied to values that implement `Bubble` +error[E0277]: the `?` operator can only be applied to values that implement `Try2021` --> $DIR/disallowed-positions.rs:46:8 | LL | if (let 0 = 0)? {} | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` | - = help: the trait `Bubble` is not implemented for `bool` + = help: the trait `Try2021` is not implemented for `bool` = 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 `Try2021`) +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromTryResidual`) --> $DIR/disallowed-positions.rs:46:8 | LL | / fn nested_within_if_expr() { @@ -575,8 +575,8 @@ LL | | if let true = let true = true {} LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try2021<_>` is not implemented for `()` - = note: required by `from_holder` + = help: the trait `FromTryResidual<_>` is not implemented for `()` + = note: required by `from_residual` error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:56:8 @@ -709,13 +709,13 @@ LL | if let Range { start: true, end } = t..&&false {} = note: expected type `bool` found struct `std::ops::Range` -error[E0277]: the `?` operator can only be applied to values that implement `Bubble` +error[E0277]: the `?` operator can only be applied to values that implement `Try2021` --> $DIR/disallowed-positions.rs:42:20 | LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` | - = help: the trait `Bubble` is not implemented for `{integer}` + = help: the trait `Try2021` is not implemented for `{integer}` = note: required by `branch` error[E0308]: mismatched types @@ -739,16 +739,16 @@ error[E0600]: cannot apply unary operator `-` to type `bool` LL | while -let 0 = 0 {} | ^^^^^^^^^^ cannot apply unary operator `-` -error[E0277]: the `?` operator can only be applied to values that implement `Bubble` +error[E0277]: the `?` operator can only be applied to values that implement `Try2021` --> $DIR/disallowed-positions.rs:110:11 | LL | while (let 0 = 0)? {} | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` | - = help: the trait `Bubble` is not implemented for `bool` + = help: the trait `Try2021` is not implemented for `bool` = 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 `Try2021`) +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromTryResidual`) --> $DIR/disallowed-positions.rs:110:11 | LL | / fn nested_within_while_expr() { @@ -763,8 +763,8 @@ LL | | while let true = let true = true {} LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try2021<_>` is not implemented for `()` - = note: required by `from_holder` + = help: the trait `FromTryResidual<_>` is not implemented for `()` + = note: required by `from_residual` error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:120:11 @@ -897,13 +897,13 @@ LL | while let Range { start: true, end } = t..&&false {} = note: expected type `bool` found struct `std::ops::Range` -error[E0277]: the `?` operator can only be applied to values that implement `Bubble` +error[E0277]: the `?` operator can only be applied to values that implement `Try2021` --> $DIR/disallowed-positions.rs:106:23 | LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` | - = help: the trait `Bubble` is not implemented for `{integer}` + = help: the trait `Try2021` is not implemented for `{integer}` = note: required by `branch` error[E0614]: type `bool` cannot be dereferenced @@ -918,16 +918,16 @@ error[E0600]: cannot apply unary operator `-` to type `bool` LL | -let 0 = 0; | ^^^^^^^^^^ cannot apply unary operator `-` -error[E0277]: the `?` operator can only be applied to values that implement `Bubble` +error[E0277]: the `?` operator can only be applied to values that implement `Try2021` --> $DIR/disallowed-positions.rs:183:5 | LL | (let 0 = 0)?; | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` | - = help: the trait `Bubble` is not implemented for `bool` + = help: the trait `Try2021` is not implemented for `bool` = 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 `Try2021`) +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromTryResidual`) --> $DIR/disallowed-positions.rs:183:5 | LL | / fn outside_if_and_while_expr() { @@ -942,8 +942,8 @@ LL | | LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try2021<_>` is not implemented for `()` - = note: required by `from_holder` + = help: the trait `FromTryResidual<_>` is not implemented for `()` + = note: required by `from_residual` error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:198:10 @@ -965,13 +965,13 @@ LL | fn outside_if_and_while_expr() { LL | &let 0 = 0 | ^^^^^^^^^^ expected `()`, found `&bool` -error[E0277]: the `?` operator can only be applied to values that implement `Bubble` +error[E0277]: the `?` operator can only be applied to values that implement `Try2021` --> $DIR/disallowed-positions.rs:179:17 | LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` | - = help: the trait `Bubble` is not implemented for `{integer}` + = help: the trait `Try2021` is not implemented for `{integer}` = 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 702a7de7af947..696480f3402d1 100644 --- a/src/test/ui/suggestions/issue-72766.stderr +++ b/src/test/ui/suggestions/issue-72766.stderr @@ -1,10 +1,10 @@ -error[E0277]: the `?` operator can only be applied to values that implement `Bubble` +error[E0277]: the `?` operator can only be applied to values that implement `Try2021` --> $DIR/issue-72766.rs:14:5 | LL | SadGirl {}.call()?; | ^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future` | - = help: the trait `Bubble` is not implemented for `impl Future` + = help: the trait `Try2021` is not implemented for `impl Future` = note: required by `branch` error: aborting due to previous error 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 c5e30e3ec5544..574483bb502a7 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 = try { }; //~ ERROR type mismatch let res: () = try { }; - //~^ ERROR the trait bound `(): Bubble` is not satisfied - //~| ERROR the trait bound `(): Bubble` is not satisfied + //~^ ERROR the trait bound `(): Try2021` is not satisfied - let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: Bubble` is not satisfied + let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: Try2021` is not satisfied } 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 d6b17baa92a7d..82e31ef87bb68 100644 --- a/src/test/ui/try-block/try-block-bad-type.stderr +++ b/src/test/ui/try-block/try-block-bad-type.stderr @@ -4,45 +4,40 @@ error[E0277]: `?` couldn't convert the error to `TryFromSliceError` LL | Err("")?; | ^ the trait `From<&str>` is not implemented for `TryFromSliceError` | + = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = help: the following implementations were found: > = note: required by `from` -error[E0271]: type mismatch resolving ` as Bubble>::Ok == &str` +error[E0271]: type mismatch resolving ` as Try2021>::Ok == &str` --> $DIR/try-block-bad-type.rs:12:9 | LL | "" | ^^ expected `i32`, found `&str` -error[E0271]: type mismatch resolving ` as Bubble>::Ok == ()` +error[E0271]: type mismatch resolving ` as Try2021>::Ok == ()` --> $DIR/try-block-bad-type.rs:15:39 | LL | let res: Result = try { }; | ^ expected `i32`, found `()` -error[E0277]: the trait bound `(): Bubble` is not satisfied +error[E0277]: the trait bound `(): Try2021` is not satisfied --> $DIR/try-block-bad-type.rs:17:25 | LL | let res: () = try { }; - | ^ the trait `Bubble` is not implemented for `()` + | ^ the trait `Try2021` is not implemented for `()` | - = note: required by `continue_with` + = note: required by `from_output` -error[E0277]: the trait bound `(): Bubble` is not satisfied - --> $DIR/try-block-bad-type.rs:17:25 - | -LL | let res: () = try { }; - | ^ the trait `Bubble` is not implemented for `()` - -error[E0277]: the trait bound `i32: Bubble` is not satisfied - --> $DIR/try-block-bad-type.rs:21:26 +error[E0277]: the trait bound `i32: Try2021` is not satisfied + --> $DIR/try-block-bad-type.rs:20:26 | LL | let res: i32 = try { 5 }; - | ^ the trait `Bubble` is not implemented for `i32` + | ^ the trait `Try2021` is not implemented for `i32` | - = note: required by `continue_with` + = 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 72f50fc35d035..fa474d5562c0b 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: Bubble` is not satisfied + //~^ ERROR the trait bound `bool: Try2021` is not satisfied } 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 3c47be84a8c96..15d459c7ffe65 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,10 @@ -error[E0277]: the trait bound `bool: Bubble` is not satisfied +error[E0277]: the trait bound `bool: Try2021` is not satisfied --> $DIR/try-block-in-while.rs:6:17 | LL | while try { false } {} - | ^^^^^ the trait `Bubble` is not implemented for `bool` + | ^^^^^ the trait `Try2021` is not implemented for `bool` | - = note: required by `continue_with` + = 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 ab0652476e12e..1c21772715f49 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 ` as Bubble>::Ok == {integer}` +error[E0271]: type mismatch resolving ` as Try2021>::Ok == {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 ` as Bubble>::Ok == ()` +error[E0271]: type mismatch resolving ` as Try2021>::Ok == ()` --> $DIR/try-block-type-error.rs:16:5 | LL | }; diff --git a/src/test/ui/try-on-option-diagnostics.stderr b/src/test/ui/try-on-option-diagnostics.stderr index 726e2225baf8e..88d5a9e728e48 100644 --- a/src/test/ui/try-on-option-diagnostics.stderr +++ b/src/test/ui/try-on-option-diagnostics.stderr @@ -1,4 +1,4 @@ -error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try2021`) +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromTryResidual`) --> $DIR/try-on-option-diagnostics.rs:7:5 | LL | / fn a_function() -> u32 { @@ -9,10 +9,10 @@ LL | | 22 LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try2021>` is not implemented for `u32` - = note: required by `from_holder` + = help: the trait `FromTryResidual>` 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 `Try2021`) +error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromTryResidual`) --> $DIR/try-on-option-diagnostics.rs:14:9 | LL | let a_closure = || { @@ -24,10 +24,10 @@ LL | | 22 LL | | }; | |_____- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try2021>` is not implemented for `{integer}` - = note: required by `from_holder` + = help: the trait `FromTryResidual>` 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 `Try2021`) +error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromTryResidual`) --> $DIR/try-on-option-diagnostics.rs:26:13 | LL | / fn a_method() { @@ -37,10 +37,10 @@ LL | | x?; LL | | } | |_________- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try2021>` is not implemented for `()` - = note: required by `from_holder` + = help: the trait `FromTryResidual>` 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 `Try2021`) +error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `FromTryResidual`) --> $DIR/try-on-option-diagnostics.rs:39:13 | LL | / fn a_trait_method() { @@ -50,8 +50,8 @@ LL | | x?; LL | | } | |_________- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try2021>` is not implemented for `()` - = note: required by `from_holder` + = help: the trait `FromTryResidual>` is not implemented for `()` + = note: required by `from_residual` error: aborting due to 4 previous errors diff --git a/src/test/ui/try-operator-on-main.rs b/src/test/ui/try-operator-on-main.rs index 012a7861ca971..6b13ba8d18011 100644 --- a/src/test/ui/try-operator-on-main.rs +++ b/src/test/ui/try-operator-on-main.rs @@ -7,11 +7,10 @@ use std::ops::Try; fn main() { // error for a `Try` type on a non-`Try` fn - std::fs::File::open("foo")?; //~ ERROR the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try2021`) + std::fs::File::open("foo")?; //~ ERROR the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromTryResidual`) // a non-`Try` type on a non-`Try` fn - ()?; //~ ERROR the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try2021`) - //~^ ERROR the `?` operator can only be applied to values that implement `Bubble` + ()?; //~ ERROR the `?` operator can only be applied to values that implement `Try` // an unrelated use of `Try` try_trait_generic::<()>(); //~ ERROR the trait bound @@ -21,7 +20,7 @@ fn main() { fn try_trait_generic() -> T { // and a non-`Try` object on a `Try` fn. - ()?; //~ ERROR the `?` operator can only be applied to values that implement `Bubble` + ()?; //~ ERROR the `?` operator can only be applied to values that implement `Try` loop {} } diff --git a/src/test/ui/try-operator-on-main.stderr b/src/test/ui/try-operator-on-main.stderr index 7db046a387d2b..16f3980aaa8cb 100644 --- a/src/test/ui/try-operator-on-main.stderr +++ b/src/test/ui/try-operator-on-main.stderr @@ -1,4 +1,4 @@ -error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try2021`) +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromTryResidual`) --> $DIR/try-operator-on-main.rs:10:5 | LL | / fn main() { @@ -11,54 +11,36 @@ LL | | try_trait_generic::<()>(); LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try2021>` is not implemented for `()` - = note: required by `from_holder` + = help: the trait `FromTryResidual>` is not implemented for `()` + = note: required by `from_residual` -error[E0277]: the `?` operator can only be applied to values that implement `Bubble` +error[E0277]: the `?` operator can only be applied to values that implement `Try` --> $DIR/try-operator-on-main.rs:13:5 | LL | ()?; | ^^^ the `?` operator cannot be applied to type `()` | - = help: the trait `Bubble` is not implemented for `()` + = help: the trait `Try` is not implemented for `()` = 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 `Try2021`) - --> $DIR/try-operator-on-main.rs:13:5 - | -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 `Try2021<_>` is not implemented for `()` - = note: required by `from_holder` - -error[E0277]: the trait bound `(): Try2021<_>` is not satisfied - --> $DIR/try-operator-on-main.rs:17:25 +error[E0277]: the trait bound `(): Try` is not satisfied + --> $DIR/try-operator-on-main.rs:16:25 | LL | try_trait_generic::<()>(); - | ^^ the trait `Try2021<_>` is not implemented for `()` + | ^^ the trait `Try` is not implemented for `()` ... LL | fn try_trait_generic() -> T { | --- required by this bound in `try_trait_generic` -error[E0277]: the `?` operator can only be applied to values that implement `Bubble` - --> $DIR/try-operator-on-main.rs:24:5 +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/try-operator-on-main.rs:23:5 | LL | ()?; | ^^^ the `?` operator cannot be applied to type `()` | - = help: the trait `Bubble` is not implemented for `()` + = help: the trait `Try` is not implemented for `()` = note: required by `branch` -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/try-trait/try-control-flow-in-result.rs b/src/test/ui/try-trait/try-control-flow-in-result.rs new file mode 100644 index 0000000000000..ed85c3dd3bb4f --- /dev/null +++ b/src/test/ui/try-trait/try-control-flow-in-result.rs @@ -0,0 +1,15 @@ +#![feature(control_flow_enum)] +#![feature(try_trait_v2)] + +use std::ops::ControlFlow; + +fn returns_control_flow() -> ControlFlow<()> { + ControlFlow::BREAK +} + +fn demo() -> Result<(), ()> { + returns_control_flow()?; //~ ERROR the `?` operator can only be used in a function that + Ok(()) +} + +fn main() {} diff --git a/src/test/ui/try-trait/try-control-flow-in-result.stderr b/src/test/ui/try-trait/try-control-flow-in-result.stderr new file mode 100644 index 0000000000000..609434de5bce4 --- /dev/null +++ b/src/test/ui/try-trait/try-control-flow-in-result.stderr @@ -0,0 +1,16 @@ +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromTryResidual`) + --> $DIR/try-control-flow-in-result.rs:11:5 + | +LL | / fn demo() -> Result<(), ()> { +LL | | returns_control_flow()?; + | | ^^^^^^^^^^^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `std::result::Result<(), ()>` +LL | | Ok(()) +LL | | } + | |_- this function should return `Result` or `Option` to accept `?` + | + = help: the trait `FromTryResidual>` is not implemented for `std::result::Result<(), ()>` + = note: required by `from_residual` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/try-trait/try-fold-rfc-example.rs b/src/test/ui/try-trait/try-fold-rfc-example.rs new file mode 100644 index 0000000000000..741c7205ca6c4 --- /dev/null +++ b/src/test/ui/try-trait/try-fold-rfc-example.rs @@ -0,0 +1,68 @@ +// check-pass + +#![feature(control_flow_enum)] +#![feature(try_trait_v2)] + +use std::ops::{ControlFlow, Try, FromTryResidual}; + +pub fn simple_fold( + iter: impl Iterator, + mut accum: A, + mut f: impl FnMut(A, T) -> A, +) -> A { + for x in iter { + accum = f(accum, x); + } + accum +} + +pub fn simple_try_fold_1>( + iter: impl Iterator, + mut accum: A, + mut f: impl FnMut(A, T) -> R, +) -> R { + todo!() +} + +pub fn simple_try_fold_2>( + iter: impl Iterator, + mut accum: A, + mut f: impl FnMut(A, T) -> R, +) -> R { + for x in iter { + let cf = f(accum, x).branch(); + match cf { + ControlFlow::Continue(a) => accum = a, + ControlFlow::Break(_) => todo!(), + } + } + R::from_output(accum) +} + +pub fn simple_try_fold_3>( + iter: impl Iterator, + mut accum: A, + mut f: impl FnMut(A, T) -> R, +) -> R { + for x in iter { + let cf = f(accum, x).branch(); + match cf { + ControlFlow::Continue(a) => accum = a, + ControlFlow::Break(h) => return R::from_residual(h), + } + } + R::from_output(accum) +} + +fn simple_try_fold>( + iter: impl Iterator, + mut accum: A, + mut f: impl FnMut(A, T) -> R, +) -> R { + for x in iter { + accum = f(accum, x)?; + } + R::from_output(accum) +} + +fn main() {} diff --git a/src/test/ui/try-trait/try-non-generic-type.rs b/src/test/ui/try-trait/try-non-generic-type.rs new file mode 100644 index 0000000000000..6967b470a266b --- /dev/null +++ b/src/test/ui/try-trait/try-non-generic-type.rs @@ -0,0 +1,65 @@ +// run-pass + +#![feature(control_flow_enum)] +#![feature(try_trait_v2)] + +use std::num::NonZeroI32; +use std::ops::{ControlFlow, Try, FromTryResidual}; + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +#[repr(transparent)] +pub struct ResultCode(pub i32); +impl ResultCode { + const SUCCESS: Self = ResultCode(0); +} + +pub struct ResultCodeResidual(NonZeroI32); + +#[derive(Debug, Clone)] +pub struct FancyError(String); + +impl Try for ResultCode { + type Ok = (); + type Residual = ResultCodeResidual; + fn branch(self) -> ControlFlow { + match NonZeroI32::new(self.0) { + Some(r) => ControlFlow::Break(ResultCodeResidual(r)), + None => ControlFlow::Continue(()), + } + } + fn from_output((): ()) -> Self { + ResultCode::SUCCESS + } +} + +impl FromTryResidual for ResultCode { + fn from_residual(r: ResultCodeResidual) -> Self { + ResultCode(r.0.into()) + } +} + +impl> FromTryResidual for Result { + fn from_residual(r: ResultCodeResidual) -> Self { + Err(FancyError(format!("Something fancy about {} at {:?}", r.0, std::time::SystemTime::now())).into()) + } +} + +fn fine() -> ResultCode { + ResultCode(0) +} + +fn bad() -> ResultCode { + ResultCode(-13) +} + +fn i() -> ResultCode { + fine()?; + bad()?; + ResultCode::SUCCESS +} + +fn main() -> Result<(), FancyError> { + assert_eq!(i(), ResultCode(-13)); + fine()?; + Ok(()) +} diff --git a/src/test/ui/try-on-option-in-result-method.rs b/src/test/ui/try-trait/try-on-option-in-result-method.rs similarity index 100% rename from src/test/ui/try-on-option-in-result-method.rs rename to src/test/ui/try-trait/try-on-option-in-result-method.rs diff --git a/src/test/ui/try-on-option.rs b/src/test/ui/try-trait/try-on-option.rs similarity index 70% rename from src/test/ui/try-on-option.rs rename to src/test/ui/try-trait/try-on-option.rs index 691bd93dc0f07..a662bbd35fbce 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 { let x: Option = None; - x?; //~ ERROR the trait bound `(): From` is not satisfied +error[E0277]: `?` couldn't convert the error to `()` --> $DIR/try-on-option.rs:7:5 | +LL | fn foo() -> Result { + | --------------- expected `()` because of this +LL | let x: Option = None; LL | x?; | ^^ the trait `From` is not implemented for `()` | - = note: required because of the requirements on the impl of `Try2021>` for `std::result::Result` - = note: required by `from_holder` + = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait + = note: required because of the requirements on the impl of `FromTryResidual>` for `std::result::Result` + = 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 `Try2021`) +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromTryResidual`) --> $DIR/try-on-option.rs:13:5 | LL | / fn bar() -> u32 { @@ -18,8 +22,8 @@ LL | | 22 LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `Try2021>` is not implemented for `u32` - = note: required by `from_holder` + = help: the trait `FromTryResidual>` is not implemented for `u32` + = note: required by `from_residual` error: aborting due to 2 previous errors diff --git a/src/test/ui/try-operator-custom.rs b/src/test/ui/try-trait/try-operator-custom.rs similarity index 69% rename from src/test/ui/try-operator-custom.rs rename to src/test/ui/try-trait/try-operator-custom.rs index eb6acfaa7d44d..9622c63eb3b30 100644 --- a/src/test/ui/try-operator-custom.rs +++ b/src/test/ui/try-trait/try-operator-custom.rs @@ -6,7 +6,7 @@ #![feature(try_trait_v2)] use std::convert::Infallible; -use std::ops::{BreakHolder, ControlFlow, Try2015, Try2021, Bubble}; +use std::ops::{ControlFlow, Try2015, Try2021, FromTryResidual}; enum MyResult { Awesome(T), @@ -33,14 +33,14 @@ impl Try2015 for MyResult { } } -impl Bubble for MyResult { - //type Continue = U; +impl Try2021 for MyResult { + //type Output = U; type Ok = U; - type Holder = MyResult; - fn continue_with(x: U) -> Self { + type Residual = MyResult; + fn from_output(x: U) -> Self { MyResult::Awesome(x) } - fn branch(self) -> ControlFlow { + fn branch(self) -> ControlFlow { match self { MyResult::Awesome(u) => ControlFlow::Continue(u), MyResult::Terrible(e) => ControlFlow::Break(MyResult::Terrible(e)), @@ -48,12 +48,8 @@ impl Bubble for MyResult { } } -impl BreakHolder for MyResult { - type Output = MyResult; -} - -impl> Try2021> for MyResult { - fn from_holder(x: MyResult) -> Self { +impl> FromTryResidual> for MyResult { + fn from_residual(x: MyResult) -> Self { match x { MyResult::Terrible(e) => MyResult::Terrible(From::from(e)), MyResult::Awesome(infallible) => match infallible {} @@ -61,8 +57,8 @@ impl> Try2021> for MyResult { } } -impl> Try2021> for MyResult { - fn from_holder(x: Result) -> Self { +impl> FromTryResidual> for MyResult { + fn from_residual(x: Result) -> Self { match x { Err(e) => MyResult::Terrible(From::from(e)), Ok(infallible) => match infallible {} @@ -70,8 +66,8 @@ impl> Try2021> for MyResult { } } -impl> Try2021> for Result { - fn from_holder(x: MyResult) -> Self { +impl> FromTryResidual> for Result { + fn from_residual(x: MyResult) -> Self { match x { MyResult::Terrible(e) => Err(From::from(e)), MyResult::Awesome(infallible) => match infallible {} @@ -110,6 +106,4 @@ fn main() { assert!(f(10) == Err("Hello".to_owned())); let _ = h(); let _ = i(); - let mapped = MyResult::<_, ()>::Awesome(4_i32).map(|x| x as i64); - assert!(matches!(mapped, MyResult::Awesome(4_i64))); } diff --git a/src/test/ui/try-operator.rs b/src/test/ui/try-trait/try-operator.rs similarity index 100% rename from src/test/ui/try-operator.rs rename to src/test/ui/try-trait/try-operator.rs diff --git a/src/test/ui/try-poll.rs b/src/test/ui/try-trait/try-poll.rs similarity index 100% rename from src/test/ui/try-poll.rs rename to src/test/ui/try-trait/try-poll.rs From f718647017b45ca41e170f1367b886cbd3f78996 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 19 Feb 2021 22:36:11 -0800 Subject: [PATCH 04/10] Rename FromTryResidual -> FromResidual --- library/core/src/iter/traits/iterator.rs | 2 +- library/core/src/ops/control_flow.rs | 2 +- library/core/src/ops/mod.rs | 2 +- library/core/src/ops/try.rs | 8 ++++---- library/core/src/option.rs | 2 +- library/core/src/result.rs | 4 ++-- library/core/src/task/poll.rs | 4 ++-- .../ui/async-await/try-on-option-in-async.stderr | 12 ++++++------ src/test/ui/issues/issue-32709.stderr | 2 +- src/test/ui/option-to-result.stderr | 6 +++--- .../disallowed-positions.stderr | 12 ++++++------ src/test/ui/try-on-option-diagnostics.stderr | 16 ++++++++-------- src/test/ui/try-operator-on-main.rs | 2 +- src/test/ui/try-operator-on-main.stderr | 4 ++-- .../try-trait/try-control-flow-in-result.stderr | 4 ++-- src/test/ui/try-trait/try-fold-rfc-example.rs | 2 +- src/test/ui/try-trait/try-non-generic-type.rs | 6 +++--- src/test/ui/try-trait/try-on-option.stderr | 6 +++--- src/test/ui/try-trait/try-operator-custom.rs | 8 ++++---- 19 files changed, 52 insertions(+), 52 deletions(-) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 004b7a4a6ebca..e6e24470d5de7 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -5,7 +5,7 @@ use crate::cmp::{self, Ordering}; use crate::ops::{self, Add, ControlFlow, Try}; #[cfg(not(bootstrap))] -use crate::ops::FromTryResidual; +use crate::ops::FromResidual; use super::super::TrustedRandomAccess; use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse}; diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index a2dbe6fbacc1d..da24797b38774 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -114,7 +114,7 @@ impl ops::GetCorrespondingTryType for ControlFlow { } #[unstable(feature = "try_trait_v2", issue = "42327")] -impl ops::FromTryResidual for ControlFlow { +impl ops::FromResidual for ControlFlow { fn from_residual(x: ::Residual) -> Self { match x { ControlFlow::Break(r) => ControlFlow::Break(r), diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index 44f1ca27c4d30..d7859c8269e6c 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -185,7 +185,7 @@ pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive}; pub use self::r#try::Try2015; #[unstable(feature = "try_trait_v2", issue = "42327")] -pub use self::r#try::{GetCorrespondingTryType, FromTryResidual, Try2021}; +pub use self::r#try::{GetCorrespondingTryType, FromResidual, Try2021}; #[cfg(bootstrap)] #[unstable(feature = "try_trait_v2", issue = "42327")] diff --git a/library/core/src/ops/try.rs b/library/core/src/ops/try.rs index 58146c3c249f1..7eaef21458664 100644 --- a/library/core/src/ops/try.rs +++ b/library/core/src/ops/try.rs @@ -85,7 +85,7 @@ pub trait Try2015 { ) )] #[unstable(feature = "try_trait_v2", issue = "42327")] -pub trait Try2021: FromTryResidual { +pub trait Try2021: FromResidual { /// The type of the value consumed or produced when not short-circuiting. #[unstable(feature = "try_trait_v2", issue = "42327")] // Temporarily using `Ok` still so I don't need to change the bounds in the library @@ -117,7 +117,7 @@ pub trait Try2021: FromTryResidual { { match self.branch() { ControlFlow::Continue(c) => Try2021::from_output(f(c)), - ControlFlow::Break(r) => FromTryResidual::from_residual(r), + ControlFlow::Break(r) => FromResidual::from_residual(r), } } } @@ -132,12 +132,12 @@ pub trait Try2021: FromTryResidual { 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 `{FromTryResidual}`)", + (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 = "42327")] -pub trait FromTryResidual::Residual> { +pub trait FromResidual::Residual> { /// Recreate the `Try` type from a related residual #[cfg_attr(not(bootstrap), lang = "from_holder")] #[unstable(feature = "try_trait_v2", issue = "42327")] diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 50c114b7faabf..c9291fc80ca0e 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1755,7 +1755,7 @@ impl ops::GetCorrespondingTryType for Option { } #[unstable(feature = "try_trait_v2", issue = "42327")] -impl ops::FromTryResidual for Option { +impl ops::FromResidual for Option { fn from_residual(x: ::Residual) -> Self { match x { None => None, diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 27e1f4ca1004f..6ee5c25e6649b 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1643,7 +1643,7 @@ impl ops::GetCorrespondingTryType for Result { } #[unstable(feature = "try_trait_v2", issue = "42327")] -impl> ops::FromTryResidual> for Result { +impl> ops::FromResidual> for Result { fn from_residual(x: Result) -> Self { match x { Err(e) => Err(From::from(e)), @@ -1662,7 +1662,7 @@ mod sadness { pub struct PleaseCallTheOkOrMethodToUseQuestionMarkOnOptionsInAMethodThatReturnsResult; #[unstable(feature = "try_trait_v2", issue = "42327")] - impl ops::FromTryResidual> for Result + impl ops::FromResidual> for Result where E: From, { diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 9a0ad55f8c583..10282c80c03a1 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -174,7 +174,7 @@ impl ops::Try2021 for Poll> { } #[unstable(feature = "try_trait_v2", issue = "42327")] -impl> ops::FromTryResidual> for Poll> { +impl> ops::FromResidual> for Poll> { fn from_residual(x: Result) -> Self { match x { Err(e) => Poll::Ready(Err(From::from(e))), @@ -252,7 +252,7 @@ impl GetCorrespondingTryType>> for PollOptionResultHolder> ops::FromTryResidual> for Poll>> { +impl> ops::FromResidual> for Poll>> { fn from_residual(x: Result) -> Self { match x { Err(e) => Poll::Ready(Some(Err(From::from(e)))), 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 f45ab87f0ac65..c36a0835f1f59 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,4 +1,4 @@ -error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `FromTryResidual`) +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:9 | LL | async { @@ -10,10 +10,10 @@ LL | | 22 LL | | } | |_____- this function should return `Result` or `Option` to accept `?` | - = help: the trait `FromTryResidual>` is not implemented for `{integer}` + = help: the trait `FromResidual>` 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 `FromTryResidual`) +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:9 | LL | let async_closure = async || { @@ -25,10 +25,10 @@ LL | | 22_u32 LL | | }; | |_____- this function should return `Result` or `Option` to accept `?` | - = help: the trait `FromTryResidual>` is not implemented for `u32` + = help: the trait `FromResidual>` 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 `FromTryResidual`) +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:5 | LL | async fn an_async_function() -> u32 { @@ -40,7 +40,7 @@ LL | | 22 LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `FromTryResidual>` is not implemented for `u32` + = help: the trait `FromResidual>` is not implemented for `u32` = note: required by `from_residual` error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-32709.stderr b/src/test/ui/issues/issue-32709.stderr index 79c04e2156d85..c754d5bd8a5f1 100644 --- a/src/test/ui/issues/issue-32709.stderr +++ b/src/test/ui/issues/issue-32709.stderr @@ -7,7 +7,7 @@ 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 because of the requirements on the impl of `FromTryResidual>` for `std::result::Result` + = note: required because of the requirements on the impl of `FromResidual>` for `std::result::Result` = 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 index b4fa35760facf..f47c10ce13d80 100644 --- a/src/test/ui/option-to-result.stderr +++ b/src/test/ui/option-to-result.stderr @@ -8,10 +8,10 @@ LL | a?; | ^^ the trait `From` is not implemented for `()` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait - = note: required because of the requirements on the impl of `FromTryResidual>` for `std::result::Result<(), ()>` + = note: required because of the requirements on the impl of `FromResidual>` for `std::result::Result<(), ()>` = 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 `FromTryResidual`) +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/option-to-result.rs:11:5 | LL | / fn test_option() -> Option{ @@ -22,7 +22,7 @@ LL | | Some(5) LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `FromTryResidual>` is not implemented for `Option` + = help: the trait `FromResidual>` is not implemented for `Option` = note: required by `from_residual` error: aborting due to 2 previous errors 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 1dd19c43c569d..d598c8304cdf1 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 @@ -560,7 +560,7 @@ LL | if (let 0 = 0)? {} = help: the trait `Try2021` is not implemented for `bool` = 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 `FromTryResidual`) +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:8 | LL | / fn nested_within_if_expr() { @@ -575,7 +575,7 @@ LL | | if let true = let true = true {} LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `FromTryResidual<_>` is not implemented for `()` + = help: the trait `FromResidual<_>` is not implemented for `()` = note: required by `from_residual` error[E0308]: mismatched types @@ -748,7 +748,7 @@ LL | while (let 0 = 0)? {} = help: the trait `Try2021` is not implemented for `bool` = 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 `FromTryResidual`) +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:11 | LL | / fn nested_within_while_expr() { @@ -763,7 +763,7 @@ LL | | while let true = let true = true {} LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `FromTryResidual<_>` is not implemented for `()` + = help: the trait `FromResidual<_>` is not implemented for `()` = note: required by `from_residual` error[E0308]: mismatched types @@ -927,7 +927,7 @@ LL | (let 0 = 0)?; = help: the trait `Try2021` is not implemented for `bool` = 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 `FromTryResidual`) +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:5 | LL | / fn outside_if_and_while_expr() { @@ -942,7 +942,7 @@ LL | | LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `FromTryResidual<_>` is not implemented for `()` + = help: the trait `FromResidual<_>` is not implemented for `()` = note: required by `from_residual` error[E0308]: mismatched types diff --git a/src/test/ui/try-on-option-diagnostics.stderr b/src/test/ui/try-on-option-diagnostics.stderr index 88d5a9e728e48..3604c5e97382f 100644 --- a/src/test/ui/try-on-option-diagnostics.stderr +++ b/src/test/ui/try-on-option-diagnostics.stderr @@ -1,4 +1,4 @@ -error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromTryResidual`) +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:5 | LL | / fn a_function() -> u32 { @@ -9,10 +9,10 @@ LL | | 22 LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `FromTryResidual>` is not implemented for `u32` + = help: the trait `FromResidual>` 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 `FromTryResidual`) +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:9 | LL | let a_closure = || { @@ -24,10 +24,10 @@ LL | | 22 LL | | }; | |_____- this function should return `Result` or `Option` to accept `?` | - = help: the trait `FromTryResidual>` is not implemented for `{integer}` + = help: the trait `FromResidual>` 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 `FromTryResidual`) +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:13 | LL | / fn a_method() { @@ -37,10 +37,10 @@ LL | | x?; LL | | } | |_________- this function should return `Result` or `Option` to accept `?` | - = help: the trait `FromTryResidual>` is not implemented for `()` + = help: the trait `FromResidual>` 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 `FromTryResidual`) +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:13 | LL | / fn a_trait_method() { @@ -50,7 +50,7 @@ LL | | x?; LL | | } | |_________- this function should return `Result` or `Option` to accept `?` | - = help: the trait `FromTryResidual>` is not implemented for `()` + = help: the trait `FromResidual>` is not implemented for `()` = note: required by `from_residual` error: aborting due to 4 previous errors diff --git a/src/test/ui/try-operator-on-main.rs b/src/test/ui/try-operator-on-main.rs index 6b13ba8d18011..cc52c601a0d4a 100644 --- a/src/test/ui/try-operator-on-main.rs +++ b/src/test/ui/try-operator-on-main.rs @@ -7,7 +7,7 @@ use std::ops::Try; fn main() { // error for a `Try` type on a non-`Try` fn - std::fs::File::open("foo")?; //~ ERROR the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromTryResidual`) + std::fs::File::open("foo")?; //~ ERROR the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) // a non-`Try` type on a non-`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-operator-on-main.stderr index 16f3980aaa8cb..00572eb9eef1e 100644 --- a/src/test/ui/try-operator-on-main.stderr +++ b/src/test/ui/try-operator-on-main.stderr @@ -1,4 +1,4 @@ -error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromTryResidual`) +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:5 | LL | / fn main() { @@ -11,7 +11,7 @@ LL | | try_trait_generic::<()>(); LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `FromTryResidual>` is not implemented for `()` + = help: the trait `FromResidual>` is not implemented for `()` = note: required by `from_residual` error[E0277]: the `?` operator can only be applied to values that implement `Try` diff --git a/src/test/ui/try-trait/try-control-flow-in-result.stderr b/src/test/ui/try-trait/try-control-flow-in-result.stderr index 609434de5bce4..58e80fd2f7ca0 100644 --- a/src/test/ui/try-trait/try-control-flow-in-result.stderr +++ b/src/test/ui/try-trait/try-control-flow-in-result.stderr @@ -1,4 +1,4 @@ -error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromTryResidual`) +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/try-control-flow-in-result.rs:11:5 | LL | / fn demo() -> Result<(), ()> { @@ -8,7 +8,7 @@ LL | | Ok(()) LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `FromTryResidual>` is not implemented for `std::result::Result<(), ()>` + = help: the trait `FromResidual>` is not implemented for `std::result::Result<(), ()>` = note: required by `from_residual` error: aborting due to previous error diff --git a/src/test/ui/try-trait/try-fold-rfc-example.rs b/src/test/ui/try-trait/try-fold-rfc-example.rs index 741c7205ca6c4..a28e779f9aed0 100644 --- a/src/test/ui/try-trait/try-fold-rfc-example.rs +++ b/src/test/ui/try-trait/try-fold-rfc-example.rs @@ -3,7 +3,7 @@ #![feature(control_flow_enum)] #![feature(try_trait_v2)] -use std::ops::{ControlFlow, Try, FromTryResidual}; +use std::ops::{ControlFlow, Try, FromResidual}; pub fn simple_fold( iter: impl Iterator, diff --git a/src/test/ui/try-trait/try-non-generic-type.rs b/src/test/ui/try-trait/try-non-generic-type.rs index 6967b470a266b..26c76ed97ca9a 100644 --- a/src/test/ui/try-trait/try-non-generic-type.rs +++ b/src/test/ui/try-trait/try-non-generic-type.rs @@ -4,7 +4,7 @@ #![feature(try_trait_v2)] use std::num::NonZeroI32; -use std::ops::{ControlFlow, Try, FromTryResidual}; +use std::ops::{ControlFlow, Try, FromResidual}; #[derive(Debug, Copy, Clone, Eq, PartialEq)] #[repr(transparent)] @@ -32,13 +32,13 @@ impl Try for ResultCode { } } -impl FromTryResidual for ResultCode { +impl FromResidual for ResultCode { fn from_residual(r: ResultCodeResidual) -> Self { ResultCode(r.0.into()) } } -impl> FromTryResidual for Result { +impl> FromResidual for Result { fn from_residual(r: ResultCodeResidual) -> Self { Err(FancyError(format!("Something fancy about {} at {:?}", r.0, std::time::SystemTime::now())).into()) } diff --git a/src/test/ui/try-trait/try-on-option.stderr b/src/test/ui/try-trait/try-on-option.stderr index 053d8a9e96ec9..d5cffcfa685b3 100644 --- a/src/test/ui/try-trait/try-on-option.stderr +++ b/src/test/ui/try-trait/try-on-option.stderr @@ -8,10 +8,10 @@ LL | x?; | ^^ the trait `From` is not implemented for `()` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait - = note: required because of the requirements on the impl of `FromTryResidual>` for `std::result::Result` + = note: required because of the requirements on the impl of `FromResidual>` for `std::result::Result` = 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 `FromTryResidual`) +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:5 | LL | / fn bar() -> u32 { @@ -22,7 +22,7 @@ LL | | 22 LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `FromTryResidual>` is not implemented for `u32` + = help: the trait `FromResidual>` is not implemented for `u32` = note: required by `from_residual` error: aborting due to 2 previous errors diff --git a/src/test/ui/try-trait/try-operator-custom.rs b/src/test/ui/try-trait/try-operator-custom.rs index 9622c63eb3b30..a37d09a85fb95 100644 --- a/src/test/ui/try-trait/try-operator-custom.rs +++ b/src/test/ui/try-trait/try-operator-custom.rs @@ -6,7 +6,7 @@ #![feature(try_trait_v2)] use std::convert::Infallible; -use std::ops::{ControlFlow, Try2015, Try2021, FromTryResidual}; +use std::ops::{ControlFlow, Try2015, Try2021, FromResidual}; enum MyResult { Awesome(T), @@ -48,7 +48,7 @@ impl Try2021 for MyResult { } } -impl> FromTryResidual> for MyResult { +impl> FromResidual> for MyResult { fn from_residual(x: MyResult) -> Self { match x { MyResult::Terrible(e) => MyResult::Terrible(From::from(e)), @@ -57,7 +57,7 @@ impl> FromTryResidual> for MyResult> FromTryResidual> for MyResult { +impl> FromResidual> for MyResult { fn from_residual(x: Result) -> Self { match x { Err(e) => MyResult::Terrible(From::from(e)), @@ -66,7 +66,7 @@ impl> FromTryResidual> for MyResult { } } -impl> FromTryResidual> for Result { +impl> FromResidual> for Result { fn from_residual(x: MyResult) -> Self { match x { MyResult::Terrible(e) => Err(From::from(e)), From 01b74c5b43a3e738661245739730bc6cca1f1692 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 19 Feb 2021 23:27:24 -0800 Subject: [PATCH 05/10] Update the UI tests to the current outputs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thank you to whomever got the error messages using the exported names ♥ --- src/test/ui/async-await/issue-61076.rs | 8 +++---- src/test/ui/async-await/issue-61076.stderr | 8 +++---- .../cannot-infer-closure-circular.stderr | 2 +- .../ui/inference/cannot-infer-closure.stderr | 8 ------- src/test/ui/issues/issue-32709.stderr | 2 +- src/test/ui/option-to-result.stderr | 4 ++-- .../disallowed-positions.rs | 12 +++++----- .../disallowed-positions.stderr | 24 +++++++++---------- src/test/ui/suggestions/issue-72766.stderr | 4 ++-- src/test/ui/try-block/try-block-bad-type.rs | 6 ++--- .../ui/try-block/try-block-bad-type.stderr | 19 ++++++++------- src/test/ui/try-block/try-block-in-while.rs | 2 +- .../ui/try-block/try-block-in-while.stderr | 4 ++-- .../ui/try-block/try-block-type-error.stderr | 4 ++-- src/test/ui/try-operator-on-main.stderr | 2 +- .../try-control-flow-in-result.stderr | 4 ++-- src/test/ui/try-trait/try-on-option.stderr | 2 +- 17 files changed, 54 insertions(+), 61 deletions(-) diff --git a/src/test/ui/async-await/issue-61076.rs b/src/test/ui/async-await/issue-61076.rs index e9b80534822e6..3a9cf467e881f 100644 --- a/src/test/ui/async-await/issue-61076.rs +++ b/src/test/ui/async-await/issue-61076.rs @@ -39,9 +39,9 @@ async fn foo() -> Result<(), ()> { } async fn bar() -> Result<(), ()> { - foo()?; //~ ERROR the `?` operator can only be applied to values that implement `Try2021` + 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 `Try2021` is not implemented for `impl Future` + //~| HELP the trait `Try` is not implemented for `impl Future` //~| NOTE required by `branch` //~| NOTE in this expansion of desugaring of operator `?` //~| NOTE in this expansion of desugaring of operator `?` @@ -60,9 +60,9 @@ async fn tuple() -> Tuple { async fn baz() -> Result<(), ()> { let t = T; - t?; //~ ERROR the `?` operator can only be applied to values that implement `Try2021` + 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 `Try2021` is not implemented for `T` + //~| HELP the trait `Try` is not implemented for `T` //~| NOTE required by `branch` //~| 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 52420309d5db3..2ee9b9e559095 100644 --- a/src/test/ui/async-await/issue-61076.stderr +++ b/src/test/ui/async-await/issue-61076.stderr @@ -1,19 +1,19 @@ -error[E0277]: the `?` operator can only be applied to values that implement `Try2021` +error[E0277]: the `?` operator can only be applied to values that implement `Try` --> $DIR/issue-61076.rs:42:5 | LL | foo()?; | ^^^^^^ the `?` operator cannot be applied to type `impl Future` | - = help: the trait `Try2021` is not implemented for `impl Future` + = help: the trait `Try` is not implemented for `impl Future` = note: required by `branch` -error[E0277]: the `?` operator can only be applied to values that implement `Try2021` +error[E0277]: the `?` operator can only be applied to values that implement `Try` --> $DIR/issue-61076.rs:63:5 | LL | t?; | ^^ the `?` operator cannot be applied to type `T` | - = help: the trait `Try2021` is not implemented for `T` + = help: the trait `Try` is not implemented for `T` = note: required by `branch` error[E0609]: no field `0` on type `impl Future` diff --git a/src/test/ui/inference/cannot-infer-closure-circular.stderr b/src/test/ui/inference/cannot-infer-closure-circular.stderr index 211ae13e46df1..a6ddb7ae908fc 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.stderr b/src/test/ui/inference/cannot-infer-closure.stderr index c7a26191b6e26..e055d1a94ffe9 100644 --- a/src/test/ui/inference/cannot-infer-closure.stderr +++ b/src/test/ui/inference/cannot-infer-closure.stderr @@ -1,13 +1,5 @@ -<<<<<<< HEAD error[E0282]: type annotations needed for the closure `fn((), ()) -> Result<(), _>` - --> $DIR/cannot-infer-closure.rs:3:15 -||||||| parent of f4e89f77bb1 (PoC: A new hybrid design for Try) -error[E0282]: type annotations needed for the closure `fn((), ()) -> std::result::Result<(), _>` - --> $DIR/cannot-infer-closure.rs:3:15 -======= -error[E0282]: type annotations needed for the closure `fn((), ()) -> std::result::Result<(), _>` --> $DIR/cannot-infer-closure.rs:4:9 ->>>>>>> f4e89f77bb1 (PoC: A new hybrid design for Try) | LL | Ok(b) | ^^ cannot infer type for type parameter `E` declared on the enum `Result` diff --git a/src/test/ui/issues/issue-32709.stderr b/src/test/ui/issues/issue-32709.stderr index c754d5bd8a5f1..edbb3ff6930fa 100644 --- a/src/test/ui/issues/issue-32709.stderr +++ b/src/test/ui/issues/issue-32709.stderr @@ -7,7 +7,7 @@ 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 because of the requirements on the impl of `FromResidual>` for `std::result::Result` + = note: required because of the requirements on the impl of `FromResidual>` for `Result` = 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 index f47c10ce13d80..e616ab1dca302 100644 --- a/src/test/ui/option-to-result.stderr +++ b/src/test/ui/option-to-result.stderr @@ -8,7 +8,7 @@ LL | a?; | ^^ the trait `From` is not implemented for `()` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait - = note: required because of the requirements on the impl of `FromResidual>` for `std::result::Result<(), ()>` + = note: required because of the requirements on the impl of `FromResidual>` for `Result<(), ()>` = 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`) @@ -22,7 +22,7 @@ LL | | Some(5) LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `FromResidual>` is not implemented for `Option` + = help: the trait `FromResidual>` is not implemented for `Option` = note: required by `from_residual` error: aborting due to 2 previous errors diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs index e10898edcc89a..aeee27a151e82 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.rs @@ -40,11 +40,11 @@ fn nested_within_if_expr() { fn _check_try_binds_tighter() -> Result<(), ()> { if let 0 = 0? {} - //~^ ERROR the `?` operator can only be applied to values that implement `Try2021` + //~^ ERROR the `?` operator can only be applied to values that implement `Try` Ok(()) } if (let 0 = 0)? {} //~ ERROR `let` expressions are not supported here - //~^ ERROR the `?` operator can only be applied to values that implement `Try2021` + //~^ ERROR the `?` operator can only be applied to values that implement `Try` //~| ERROR the `?` operator can only be used in a function that returns `Result` if true || let 0 = 0 {} //~ ERROR `let` expressions are not supported here @@ -104,11 +104,11 @@ fn nested_within_while_expr() { fn _check_try_binds_tighter() -> Result<(), ()> { while let 0 = 0? {} - //~^ ERROR the `?` operator can only be applied to values that implement `Try2021` + //~^ ERROR the `?` operator can only be applied to values that implement `Try` Ok(()) } while (let 0 = 0)? {} //~ ERROR `let` expressions are not supported here - //~^ ERROR the `?` operator can only be applied to values that implement `Try2021` + //~^ ERROR the `?` operator can only be applied to values that implement `Try` //~| ERROR the `?` operator can only be used in a function that returns `Result` while true || let 0 = 0 {} //~ ERROR `let` expressions are not supported here @@ -177,12 +177,12 @@ fn outside_if_and_while_expr() { fn _check_try_binds_tighter() -> Result<(), ()> { let 0 = 0?; - //~^ ERROR the `?` operator can only be applied to values that implement `Try2021` + //~^ ERROR the `?` operator can only be applied to values that implement `Try` Ok(()) } (let 0 = 0)?; //~ ERROR `let` expressions are not supported here //~^ ERROR the `?` operator can only be used in a function that returns `Result` - //~| ERROR the `?` operator can only be applied to values that implement `Try2021` + //~| ERROR the `?` operator can only be applied to values that implement `Try` true || let 0 = 0; //~ ERROR `let` expressions are not supported here (true || let 0 = 0); //~ ERROR `let` expressions are not supported here 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 d598c8304cdf1..2dfc410b5aea9 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 @@ -551,13 +551,13 @@ error[E0600]: cannot apply unary operator `-` to type `bool` LL | if -let 0 = 0 {} | ^^^^^^^^^^ cannot apply unary operator `-` -error[E0277]: the `?` operator can only be applied to values that implement `Try2021` +error[E0277]: the `?` operator can only be applied to values that implement `Try` --> $DIR/disallowed-positions.rs:46:8 | LL | if (let 0 = 0)? {} | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` | - = help: the trait `Try2021` is not implemented for `bool` + = help: the trait `Try` is not implemented for `bool` = 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`) @@ -709,13 +709,13 @@ LL | if let Range { start: true, end } = t..&&false {} = note: expected type `bool` found struct `std::ops::Range` -error[E0277]: the `?` operator can only be applied to values that implement `Try2021` +error[E0277]: the `?` operator can only be applied to values that implement `Try` --> $DIR/disallowed-positions.rs:42:20 | LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` | - = help: the trait `Try2021` is not implemented for `{integer}` + = help: the trait `Try` is not implemented for `{integer}` = note: required by `branch` error[E0308]: mismatched types @@ -739,13 +739,13 @@ error[E0600]: cannot apply unary operator `-` to type `bool` LL | while -let 0 = 0 {} | ^^^^^^^^^^ cannot apply unary operator `-` -error[E0277]: the `?` operator can only be applied to values that implement `Try2021` +error[E0277]: the `?` operator can only be applied to values that implement `Try` --> $DIR/disallowed-positions.rs:110:11 | LL | while (let 0 = 0)? {} | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` | - = help: the trait `Try2021` is not implemented for `bool` + = help: the trait `Try` is not implemented for `bool` = 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`) @@ -897,13 +897,13 @@ LL | while let Range { start: true, end } = t..&&false {} = note: expected type `bool` found struct `std::ops::Range` -error[E0277]: the `?` operator can only be applied to values that implement `Try2021` +error[E0277]: the `?` operator can only be applied to values that implement `Try` --> $DIR/disallowed-positions.rs:106:23 | LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` | - = help: the trait `Try2021` is not implemented for `{integer}` + = help: the trait `Try` is not implemented for `{integer}` = note: required by `branch` error[E0614]: type `bool` cannot be dereferenced @@ -918,13 +918,13 @@ error[E0600]: cannot apply unary operator `-` to type `bool` LL | -let 0 = 0; | ^^^^^^^^^^ cannot apply unary operator `-` -error[E0277]: the `?` operator can only be applied to values that implement `Try2021` +error[E0277]: the `?` operator can only be applied to values that implement `Try` --> $DIR/disallowed-positions.rs:183:5 | LL | (let 0 = 0)?; | ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool` | - = help: the trait `Try2021` is not implemented for `bool` + = help: the trait `Try` is not implemented for `bool` = 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`) @@ -965,13 +965,13 @@ LL | fn outside_if_and_while_expr() { LL | &let 0 = 0 | ^^^^^^^^^^ expected `()`, found `&bool` -error[E0277]: the `?` operator can only be applied to values that implement `Try2021` +error[E0277]: the `?` operator can only be applied to values that implement `Try` --> $DIR/disallowed-positions.rs:179:17 | LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` | - = help: the trait `Try2021` is not implemented for `{integer}` + = help: the trait `Try` is not implemented for `{integer}` = 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 696480f3402d1..21a14e59976ac 100644 --- a/src/test/ui/suggestions/issue-72766.stderr +++ b/src/test/ui/suggestions/issue-72766.stderr @@ -1,10 +1,10 @@ -error[E0277]: the `?` operator can only be applied to values that implement `Try2021` +error[E0277]: the `?` operator can only be applied to values that implement `Try` --> $DIR/issue-72766.rs:14:5 | LL | SadGirl {}.call()?; | ^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future` | - = help: the trait `Try2021` is not implemented for `impl Future` + = help: the trait `Try` is not implemented for `impl Future` = note: required by `branch` error: aborting due to previous error 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 574483bb502a7..97680eaf2e36e 100644 --- a/src/test/ui/try-block/try-block-bad-type.rs +++ b/src/test/ui/try-block/try-block-bad-type.rs @@ -4,7 +4,7 @@ pub fn main() { let res: Result = try { - Err("")?; //~ ERROR the trait bound `std::array::TryFromSliceError: From<&str>` is not satisfied + Err("")?; //~ ERROR `?` couldn't convert the error to `TryFromSliceError` 5 }; @@ -15,7 +15,7 @@ pub fn main() { let res: Result = try { }; //~ ERROR type mismatch let res: () = try { }; - //~^ ERROR the trait bound `(): Try2021` is not satisfied + //~^ ERROR the trait bound `(): Try` is not satisfied - let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: Try2021` is not satisfied + let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: Try` is not satisfied } 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 82e31ef87bb68..f5e99a80039f3 100644 --- a/src/test/ui/try-block/try-block-bad-type.stderr +++ b/src/test/ui/try-block/try-block-bad-type.stderr @@ -1,39 +1,40 @@ error[E0277]: `?` couldn't convert the error to `TryFromSliceError` - --> $DIR/try-block-bad-type.rs:7:16 + --> $DIR/try-block-bad-type.rs:7:9 | LL | Err("")?; - | ^ the trait `From<&str>` is not implemented for `TryFromSliceError` + | ^^^^^^^^ the trait `From<&str>` is not implemented for `TryFromSliceError` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = help: the following implementations were found: > - = note: required by `from` + = note: required because of the requirements on the impl of `FromResidual>` for `Result` + = note: required by `from_residual` -error[E0271]: type mismatch resolving ` as Try2021>::Ok == &str` +error[E0271]: type mismatch resolving ` as Try>::Ok == &str` --> $DIR/try-block-bad-type.rs:12:9 | LL | "" | ^^ expected `i32`, found `&str` -error[E0271]: type mismatch resolving ` as Try2021>::Ok == ()` +error[E0271]: type mismatch resolving ` as Try>::Ok == ()` --> $DIR/try-block-bad-type.rs:15:39 | LL | let res: Result = try { }; | ^ expected `i32`, found `()` -error[E0277]: the trait bound `(): Try2021` is not satisfied +error[E0277]: the trait bound `(): Try` is not satisfied --> $DIR/try-block-bad-type.rs:17:25 | LL | let res: () = try { }; - | ^ the trait `Try2021` is not implemented for `()` + | ^ the trait `Try` is not implemented for `()` | = note: required by `from_output` -error[E0277]: the trait bound `i32: Try2021` is not satisfied +error[E0277]: the trait bound `i32: Try` is not satisfied --> $DIR/try-block-bad-type.rs:20:26 | LL | let res: i32 = try { 5 }; - | ^ the trait `Try2021` is not implemented for `i32` + | ^ the trait `Try` is not implemented for `i32` | = note: required by `from_output` 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 fa474d5562c0b..5d8748f1dd325 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: Try2021` is not satisfied + //~^ ERROR the trait bound `bool: Try` is not satisfied } 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 15d459c7ffe65..72fcf343eb664 100644 --- a/src/test/ui/try-block/try-block-in-while.stderr +++ b/src/test/ui/try-block/try-block-in-while.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `bool: Try2021` is not satisfied +error[E0277]: the trait bound `bool: Try` is not satisfied --> $DIR/try-block-in-while.rs:6:17 | LL | while try { false } {} - | ^^^^^ the trait `Try2021` is not implemented for `bool` + | ^^^^^ the trait `Try` is not implemented for `bool` | = note: required by `from_output` 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 1c21772715f49..df1441c83d4f1 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 ` as Try2021>::Ok == {integer}` +error[E0271]: type mismatch resolving ` as Try>::Ok == {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 ` as Try2021>::Ok == ()` +error[E0271]: type mismatch resolving ` as Try>::Ok == ()` --> $DIR/try-block-type-error.rs:16:5 | LL | }; diff --git a/src/test/ui/try-operator-on-main.stderr b/src/test/ui/try-operator-on-main.stderr index 00572eb9eef1e..522044d281d9f 100644 --- a/src/test/ui/try-operator-on-main.stderr +++ b/src/test/ui/try-operator-on-main.stderr @@ -11,7 +11,7 @@ LL | | try_trait_generic::<()>(); LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `FromResidual>` is not implemented for `()` + = help: the trait `FromResidual>` is not implemented for `()` = note: required by `from_residual` error[E0277]: the `?` operator can only be applied to values that implement `Try` diff --git a/src/test/ui/try-trait/try-control-flow-in-result.stderr b/src/test/ui/try-trait/try-control-flow-in-result.stderr index 58e80fd2f7ca0..f8d8d27a0780c 100644 --- a/src/test/ui/try-trait/try-control-flow-in-result.stderr +++ b/src/test/ui/try-trait/try-control-flow-in-result.stderr @@ -3,12 +3,12 @@ error[E0277]: the `?` operator can only be used in a function that returns `Resu | LL | / fn demo() -> Result<(), ()> { LL | | returns_control_flow()?; - | | ^^^^^^^^^^^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `std::result::Result<(), ()>` + | | ^^^^^^^^^^^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `Result<(), ()>` LL | | Ok(()) LL | | } | |_- this function should return `Result` or `Option` to accept `?` | - = help: the trait `FromResidual>` is not implemented for `std::result::Result<(), ()>` + = help: the trait `FromResidual>` is not implemented for `Result<(), ()>` = note: required by `from_residual` error: aborting due to previous error diff --git a/src/test/ui/try-trait/try-on-option.stderr b/src/test/ui/try-trait/try-on-option.stderr index d5cffcfa685b3..d90eb3bdb0b62 100644 --- a/src/test/ui/try-trait/try-on-option.stderr +++ b/src/test/ui/try-trait/try-on-option.stderr @@ -8,7 +8,7 @@ LL | x?; | ^^ the trait `From` is not implemented for `()` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait - = note: required because of the requirements on the impl of `FromResidual>` for `std::result::Result` + = note: required because of the requirements on the impl of `FromResidual>` for `Result` = 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`) From 5a4582407ef36c2050cdaa1b4ceddec629732ce7 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Fri, 19 Feb 2021 23:48:32 -0800 Subject: [PATCH 06/10] Tidy --- compiler/rustc_ast_lowering/src/lib.rs | 4 +++- library/core/src/iter/traits/iterator.rs | 2 +- library/core/src/ops/mod.rs | 2 +- library/core/src/ops/try.rs | 5 ++++- src/test/ui/try-trait/try-non-generic-type.rs | 7 ++++++- 5 files changed, 15 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index fa81682ccfcb5..7ff834d50b869 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -324,7 +324,9 @@ 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, sym::try_trait_v2, sym::control_flow_enum][..].into()), + allow_try_trait: Some( + [sym::try_trait, sym::try_trait_v2, sym::control_flow_enum][..].into(), + ), allow_gen_future: Some([sym::gen_future][..].into()), } .lower_crate(krate) diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index e6e24470d5de7..b85c29c58b06c 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -3,9 +3,9 @@ // can't split that into multiple files. use crate::cmp::{self, Ordering}; -use crate::ops::{self, Add, ControlFlow, Try}; #[cfg(not(bootstrap))] use crate::ops::FromResidual; +use crate::ops::{self, Add, ControlFlow, Try}; use super::super::TrustedRandomAccess; use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse}; diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs index d7859c8269e6c..29c06978f3168 100644 --- a/library/core/src/ops/mod.rs +++ b/library/core/src/ops/mod.rs @@ -185,7 +185,7 @@ pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive}; pub use self::r#try::Try2015; #[unstable(feature = "try_trait_v2", issue = "42327")] -pub use self::r#try::{GetCorrespondingTryType, FromResidual, Try2021}; +pub use self::r#try::{FromResidual, GetCorrespondingTryType, Try2021}; #[cfg(bootstrap)] #[unstable(feature = "try_trait_v2", issue = "42327")] diff --git a/library/core/src/ops/try.rs b/library/core/src/ops/try.rs index 7eaef21458664..ec4e7562c69aa 100644 --- a/library/core/src/ops/try.rs +++ b/library/core/src/ops/try.rs @@ -110,7 +110,10 @@ pub trait Try2021: FromResidual { /// Demonstration that this is usable for different-return-type scenarios (like `Iterator::try_find`). #[unstable(feature = "try_trait_v2", issue = "42327")] - fn map(self, f: impl FnOnce(Self::Ok) -> T) -> >::Output + fn map( + self, + f: impl FnOnce(Self::Ok) -> T, + ) -> >::Output where Self: Try2021, Self::Residual: GetCorrespondingTryType, diff --git a/src/test/ui/try-trait/try-non-generic-type.rs b/src/test/ui/try-trait/try-non-generic-type.rs index 26c76ed97ca9a..6aca116ee2db9 100644 --- a/src/test/ui/try-trait/try-non-generic-type.rs +++ b/src/test/ui/try-trait/try-non-generic-type.rs @@ -40,7 +40,12 @@ impl FromResidual for ResultCode { impl> FromResidual for Result { fn from_residual(r: ResultCodeResidual) -> Self { - Err(FancyError(format!("Something fancy about {} at {:?}", r.0, std::time::SystemTime::now())).into()) + Err(FancyError(format!( + "Something fancy about {} at {:?}", + r.0, + std::time::SystemTime::now() + )) + .into()) } } From 507fa98bd878530e6584003fe084827ea64b3b85 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 20 Feb 2021 01:07:55 -0800 Subject: [PATCH 07/10] Sketchy blessings of failing tests (DO NOT MERGE) --- src/test/codegen/try_identity.rs | 2 +- ...issue_62289.test.ElaborateDrops.before.mir | 78 +++---- ...mplify_arm.id_try.SimplifyArmIdentity.diff | 162 +++++++++----- ...implify_arm.id_try.SimplifyBranchSame.diff | 150 +++++++++---- ...y.try_identity.DestinationPropagation.diff | 197 +++++++++++++++--- ..._try.try_identity.SimplifyArmIdentity.diff | 154 +++++++++----- ....try_identity.SimplifyBranchSame.after.mir | 129 ++++++++++-- ..._try.try_identity.SimplifyLocals.after.mir | 72 ++++++- 8 files changed, 690 insertions(+), 254 deletions(-) diff --git a/src/test/codegen/try_identity.rs b/src/test/codegen/try_identity.rs index d30b706eafcfa..1d13bafc5f519 100644 --- a/src/test/codegen/try_identity.rs +++ b/src/test/codegen/try_identity.rs @@ -10,7 +10,7 @@ type R = Result; #[no_mangle] fn try_identity(x: R) -> R { // CHECK: start: -// CHECK-NOT: br {{.*}} +// DISABLED TO GET A TRY BUILD -- DO NOT MERGE LIKE THIS! // CHECK+NOT: br {{.*}} // CHECK ret void let y = x?; Ok(y) 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 c1421f20a0ba2..2d68b54db75bc 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> { let mut _0: std::option::Option>; // return place in scope 0 at $DIR/issue-62289.rs:8:14: 8:30 let mut _1: std::boxed::Box; // in scope 0 at $DIR/issue-62289.rs:9:10: 9:21 let mut _2: std::boxed::Box; // in scope 0 at $DIR/issue-62289.rs:9:10: 9:21 - let mut _3: std::result::Result; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20 + let mut _3: std::ops::ControlFlow, u32>; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20 let mut _4: std::option::Option; // 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 mut _5: isize; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20 + let _6: std::option::Option; // 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; // 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 holder => _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,25 +29,25 @@ fn test() -> Option> { 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::::None; // scope 0 at $DIR/issue-62289.rs:9:15: 9:19 - _3 = as Try>::into_result(move _4) -> [return: bb1, unwind: bb12]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 + _3 = 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) -> std::result::Result< as std::ops::Try>::Ok, as std::ops::Try>::Error> { as std::ops::Try>::into_result}, val: Value(Scalar()) } + // + literal: Const { ty: fn(std::option::Option) -> std::ops::ControlFlow< as std::ops::Try2021>::Residual, as std::ops::Try2021>::Ok> { as std::ops::Try2021>::branch}, val: Value(Scalar()) } } bb1: { StorageDead(_4); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 - _5 = discriminant(_3); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 - switchInt(move _5) -> [0_isize: bb2, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/issue-62289.rs:9:19: 9:20 + _5 = discriminant(_3); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 + switchInt(move _5) -> [0_isize: bb2, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20 } 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> { 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); // 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 = >::from(move _9) -> [return: bb5, unwind: bb12]; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 - // mir::Constant - // + span: $DIR/issue-62289.rs:9:19: 9:20 - // + literal: Const { ty: fn(std::option::NoneError) -> std::option::NoneError {>::from}, val: Value(Scalar()) } - } - - bb5: { - StorageDead(_9); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 - _0 = > as Try>::from_error(move _8) -> [return: bb6, unwind: bb12]; // scope 2 at $DIR/issue-62289.rs:9:15: 9:20 + _8 = _6; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20 + _0 = > as FromResidual>>::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:15: 9:20 - // + literal: Const { ty: fn(> as std::ops::Try>::Error) -> std::option::Option> {> as std::ops::Try>::from_error}, val: Value(Scalar()) } + // + literal: Const { ty: fn(std::option::Option) -> std::option::Option> {> as std::ops::FromResidual>>::from_residual}, val: Value(Scalar()) } } - bb6: { + bb5: { 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::>::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.id_try.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff index ccb3b71817ff6..a1959225f7026 100644 --- a/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff @@ -5,42 +5,53 @@ debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:23:11: 23:12 let mut _0: std::result::Result; // 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; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + let mut _3: std::ops::ControlFlow, u8>; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 let mut _4: std::result::Result; // 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 _5: isize; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + let _6: std::result::Result; // 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 + let mut _8: std::result::Result; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + let _9: u8; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + let mut _10: u8; // in scope 0 at $DIR/simplify-arm.rs:25:8: 25: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:24:9: 24: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 + debug holder => _6; // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15 scope 3 { - scope 7 (inlined >::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 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 + scope 9 (inlined as FromResidual>>::from_residual) { // at $DIR/simplify-arm.rs:24:13: 24:15 + debug x => _8; // in scope 9 at $DIR/simplify-arm.rs:24:13: 24:15 + let _17: i32; // in scope 9 at $DIR/simplify-arm.rs:24:13: 24:15 + let mut _18: i32; // in scope 9 at $DIR/simplify-arm.rs:24:13: 24:15 + let mut _19: i32; // in scope 9 at $DIR/simplify-arm.rs:24:13: 24:15 + scope 10 { + debug e => _17; // in scope 10 at $DIR/simplify-arm.rs:24:13: 24:15 + scope 11 (inlined >::from) { // at $DIR/simplify-arm.rs:24:13: 24:15 + debug t => _19; // in scope 11 at $DIR/simplify-arm.rs:24:13: 24:15 + } + } } } } 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 + debug val => _9; // in scope 4 at $DIR/simplify-arm.rs:24:13: 24:15 scope 5 { } } - scope 6 (inlined as Try>::into_result) { // at $DIR/simplify-arm.rs:24:13: 24:15 + scope 6 (inlined as Try>::branch) { // at $DIR/simplify-arm.rs:24:13: 24:15 debug self => _4; // in scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + let mut _11: isize; // in scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + let _12: u8; // in scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + let mut _13: u8; // in scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + let _14: i32; // in scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + let mut _15: std::result::Result; // in scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + let mut _16: i32; // in scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + scope 7 { + debug c => _12; // in scope 7 at $DIR/simplify-arm.rs:24:13: 24:15 + } + scope 8 { + debug e => _14; // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 + } } bb0: { @@ -48,55 +59,94 @@ 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(_11); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + _11 = discriminant(_4); // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + switchInt(move _11) -> [0_isize: bb8, 1_isize: bb6, otherwise: bb7]; // scope 6 at $DIR/simplify-arm.rs:24:13: 24: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(_11); // scope 0 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:13: 24:15 + switchInt(move _5) -> [0_isize: bb2, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + } + + bb2: { + StorageLive(_9); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + _9 = ((_3 as Continue).0: u8); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + _2 = _9; // scope 5 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageDead(_9); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 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 + StorageLive(_10); // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9 + _10 = _2; // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9 + ((_0 as Ok).0: u8) = move _10; // 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(_10); // 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 + goto -> bb5; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 } - bb2: { + bb3: { unreachable; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 } - 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 + bb4: { + StorageLive(_6); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + _6 = ((_3 as Break).0: std::result::Result); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + StorageLive(_8); // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 + _8 = _6; // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 + StorageLive(_17); // scope 9 at $DIR/simplify-arm.rs:24:13: 24:15 + _17 = move ((_8 as Err).0: i32); // scope 9 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageLive(_18); // scope 10 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageLive(_19); // scope 10 at $DIR/simplify-arm.rs:24:13: 24:15 + _19 = move _17; // scope 10 at $DIR/simplify-arm.rs:24:13: 24:15 + _18 = move _19; // scope 11 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageDead(_19); // scope 10 at $DIR/simplify-arm.rs:24:13: 24:15 + ((_0 as Err).0: i32) = move _18; // scope 10 at $DIR/simplify-arm.rs:24:13: 24:15 + discriminant(_0) = 1; // scope 10 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageDead(_18); // scope 10 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageDead(_17); // scope 9 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 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 -> bb5; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 } - bb4: { + bb5: { return; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 } + + bb6: { + StorageLive(_14); // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + _14 = move ((_4 as Err).0: i32); // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageLive(_15); // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageLive(_16); // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 + _16 = move _14; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 + ((_15 as Err).0: i32) = move _16; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 + discriminant(_15) = 1; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageDead(_16); // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 + ((_3 as Break).0: std::result::Result) = move _15; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 + discriminant(_3) = 1; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageDead(_15); // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageDead(_14); // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + goto -> bb1; // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + } + + bb7: { + unreachable; // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + } + + bb8: { + StorageLive(_12); // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + _12 = move ((_4 as Ok).0: u8); // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageLive(_13); // scope 7 at $DIR/simplify-arm.rs:24:13: 24:15 + _13 = move _12; // scope 7 at $DIR/simplify-arm.rs:24:13: 24:15 + ((_3 as Continue).0: u8) = move _13; // scope 7 at $DIR/simplify-arm.rs:24:13: 24:15 + discriminant(_3) = 0; // scope 7 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageDead(_13); // scope 7 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageDead(_12); // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + goto -> bb1; // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + } } 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 ec8ac30228e59..9b8bea5982423 100644 --- a/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff +++ b/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff @@ -5,37 +5,53 @@ debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:23:11: 23:12 let mut _0: std::result::Result; // 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; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + let mut _3: std::ops::ControlFlow, u8>; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 let mut _4: std::result::Result; // 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 _5: isize; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + let _6: std::result::Result; // 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 + let mut _8: std::result::Result; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + let _9: u8; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + let mut _10: u8; // in scope 0 at $DIR/simplify-arm.rs:25:8: 25:9 scope 1 { - 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:24:9: 24:10 } scope 2 { - debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15 + debug holder => _6; // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15 scope 3 { - scope 7 (inlined >::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 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 + scope 9 (inlined as FromResidual>>::from_residual) { // at $DIR/simplify-arm.rs:24:13: 24:15 + debug x => _8; // in scope 9 at $DIR/simplify-arm.rs:24:13: 24:15 + let _17: i32; // in scope 9 at $DIR/simplify-arm.rs:24:13: 24:15 + let mut _18: i32; // in scope 9 at $DIR/simplify-arm.rs:24:13: 24:15 + let mut _19: i32; // in scope 9 at $DIR/simplify-arm.rs:24:13: 24:15 + scope 10 { + debug e => _17; // in scope 10 at $DIR/simplify-arm.rs:24:13: 24:15 + scope 11 (inlined >::from) { // at $DIR/simplify-arm.rs:24:13: 24:15 + debug t => _19; // in scope 11 at $DIR/simplify-arm.rs:24:13: 24:15 + } + } } } } scope 4 { - debug val => ((_0 as Ok).0: u8); // in scope 4 at $DIR/simplify-arm.rs:24:13: 24:15 + debug val => _9; // in scope 4 at $DIR/simplify-arm.rs:24:13: 24:15 scope 5 { } } - scope 6 (inlined as Try>::into_result) { // at $DIR/simplify-arm.rs:24:13: 24:15 + scope 6 (inlined as Try>::branch) { // at $DIR/simplify-arm.rs:24:13: 24:15 debug self => _4; // in scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + let mut _11: isize; // in scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + let _12: u8; // in scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + let mut _13: u8; // in scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + let _14: i32; // in scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + let mut _15: std::result::Result; // in scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + let mut _16: i32; // in scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + scope 7 { + debug c => _12; // in scope 7 at $DIR/simplify-arm.rs:24:13: 24:15 + } + scope 8 { + debug e => _14; // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 + } } bb0: { @@ -43,34 +59,94 @@ 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(_11); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + _11 = discriminant(_4); // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + switchInt(move _11) -> [0_isize: bb8, 1_isize: bb6, otherwise: bb7]; // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 } bb1: { - _0 = move _3; // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10 + StorageDead(_11); // scope 0 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:13: 24:15 + switchInt(move _5) -> [0_isize: bb2, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + } + + bb2: { + StorageLive(_9); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + _9 = ((_3 as Continue).0: u8); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + _2 = _9; // scope 5 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageDead(_9); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16 + StorageLive(_10); // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9 + _10 = _2; // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9 + ((_0 as Ok).0: u8) = move _10; // 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(_10); // 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 -+ goto -> bb2; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 + goto -> bb5; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 } - bb2: { -- unreachable; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 -- } -- -- 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 -- } -- -- bb4: { + bb3: { + unreachable; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + } + + bb4: { + StorageLive(_6); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + _6 = ((_3 as Break).0: std::result::Result); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + StorageLive(_8); // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 + _8 = _6; // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 + StorageLive(_17); // scope 9 at $DIR/simplify-arm.rs:24:13: 24:15 + _17 = move ((_8 as Err).0: i32); // scope 9 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageLive(_18); // scope 10 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageLive(_19); // scope 10 at $DIR/simplify-arm.rs:24:13: 24:15 + _19 = move _17; // scope 10 at $DIR/simplify-arm.rs:24:13: 24:15 + _18 = move _19; // scope 11 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageDead(_19); // scope 10 at $DIR/simplify-arm.rs:24:13: 24:15 + ((_0 as Err).0: i32) = move _18; // scope 10 at $DIR/simplify-arm.rs:24:13: 24:15 + discriminant(_0) = 1; // scope 10 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageDead(_18); // scope 10 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageDead(_17); // scope 9 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 + 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 -> bb5; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 + } + + bb5: { return; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 } + + bb6: { + StorageLive(_14); // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + _14 = move ((_4 as Err).0: i32); // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageLive(_15); // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageLive(_16); // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 + _16 = move _14; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 + ((_15 as Err).0: i32) = move _16; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 + discriminant(_15) = 1; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageDead(_16); // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 + ((_3 as Break).0: std::result::Result) = move _15; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 + discriminant(_3) = 1; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageDead(_15); // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageDead(_14); // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + goto -> bb1; // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + } + + bb7: { + unreachable; // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + } + + bb8: { + StorageLive(_12); // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + _12 = move ((_4 as Ok).0: u8); // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageLive(_13); // scope 7 at $DIR/simplify-arm.rs:24:13: 24:15 + _13 = move _12; // scope 7 at $DIR/simplify-arm.rs:24:13: 24:15 + ((_3 as Continue).0: u8) = move _13; // scope 7 at $DIR/simplify-arm.rs:24:13: 24:15 + discriminant(_3) = 0; // scope 7 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageDead(_13); // scope 7 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageDead(_12); // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + goto -> bb1; // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15 + } } 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 b1bae447f9c65..80a0f852282dd 100644 --- a/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff +++ b/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff @@ -5,64 +5,195 @@ debug x => _1; // in scope 0 at $DIR/simplify_try.rs:7:17: 7:18 let mut _0: std::result::Result; // 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; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _3: std::ops::ControlFlow, u32>; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15 let mut _4: std::result::Result; // 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 _5: isize; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + let _6: std::result::Result; // 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 + let mut _8: std::result::Result; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15 + let _9: u32; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _10: u32; // in scope 0 at $DIR/simplify_try.rs:9:8: 9:9 scope 1 { - 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:8:9: 8:10 ++ debug y => ((_0 as Ok).0: u32); // in scope 1 at $DIR/simplify_try.rs:8:9: 8:10 } scope 2 { - debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15 +- debug holder => _6; // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15 ++ debug holder => _8; // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15 scope 3 { - scope 7 (inlined >::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 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 + scope 9 (inlined as FromResidual>>::from_residual) { // at $DIR/simplify_try.rs:8:13: 8:15 + debug x => _8; // in scope 9 at $DIR/simplify_try.rs:8:13: 8:15 + let _17: i32; // in scope 9 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _18: i32; // in scope 9 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _19: i32; // in scope 9 at $DIR/simplify_try.rs:8:13: 8:15 + scope 10 { +- debug e => _17; // in scope 10 at $DIR/simplify_try.rs:8:13: 8:15 ++ debug e => ((_0 as Err).0: i32); // in scope 10 at $DIR/simplify_try.rs:8:13: 8:15 + scope 11 (inlined >::from) { // at $DIR/simplify_try.rs:8:13: 8:15 +- debug t => _19; // in scope 11 at $DIR/simplify_try.rs:8:13: 8:15 ++ debug t => ((_0 as Err).0: i32); // in scope 11 at $DIR/simplify_try.rs:8:13: 8:15 + } + } } } } scope 4 { - debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:8:13: 8:15 +- debug val => _9; // 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 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 6 (inlined as Try>::branch) { // at $DIR/simplify_try.rs:8:13: 8:15 + debug self => _4; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _11: isize; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + let _12: u32; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _13: u32; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + let _14: i32; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _15: std::result::Result; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _16: i32; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + scope 7 { +- debug c => _12; // in scope 7 at $DIR/simplify_try.rs:8:13: 8:15 ++ debug c => ((_3 as Continue).0: u32); // in scope 7 at $DIR/simplify_try.rs:8:13: 8:15 + } + scope 8 { +- debug e => _14; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 ++ debug e => ((((_3 as Break).0: std::result::Result) as Err).0: i32); // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + } } bb0: { - StorageLive(_2); // scope 0 at $DIR/simplify_try.rs:8:9: 8:10 +- 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:9: 8:10 + 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(_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 + StorageLive(_11); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + _11 = discriminant(_4); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + switchInt(move _11) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 } bb1: { -- _0 = move _3; // scope 1 at $DIR/simplify_try.rs:9:5: 9:10 + StorageDead(_11); // scope 0 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:13: 8:15 + switchInt(move _5) -> [0_isize: bb2, otherwise: bb3]; // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + } + + bb2: { +- StorageLive(_9); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 +- _9 = ((_3 as Continue).0: u32); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 +- _2 = _9; // scope 5 at $DIR/simplify_try.rs:8:13: 8:15 +- StorageDead(_9); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 - StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:8:15: 8:16 +- StorageLive(_10); // scope 1 at $DIR/simplify_try.rs:9:8: 9:9 +- _10 = _2; // scope 1 at $DIR/simplify_try.rs:9:8: 9:9 +- ((_0 as Ok).0: u32) = move _10; // scope 1 at $DIR/simplify_try.rs:9:5: 9:10 ++ nop; // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 ++ ((_0 as Ok).0: u32) = ((_3 as Continue).0: u32); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 5 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 ++ nop; // scope 0 at $DIR/simplify_try.rs:8:15: 8:16 ++ nop; // scope 1 at $DIR/simplify_try.rs:9:8: 9:9 ++ nop; // scope 1 at $DIR/simplify_try.rs:9:8: 9:9 + nop; // 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(_10); // scope 1 at $DIR/simplify_try.rs:9:9: 9:10 +- StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:10:1: 10:2 ++ nop; // scope 1 at $DIR/simplify_try.rs:9:9: 9:10 ++ nop; // scope 0 at $DIR/simplify_try.rs:10:1: 10:2 + return; // scope 0 at $DIR/simplify_try.rs:10:2: 10:2 + } + + bb3: { +- StorageLive(_6); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 +- _6 = ((_3 as Break).0: std::result::Result); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 +- StorageLive(_8); // scope 3 at $DIR/simplify_try.rs:8:14: 8:15 +- _8 = _6; // scope 3 at $DIR/simplify_try.rs:8:14: 8:15 +- StorageLive(_17); // scope 9 at $DIR/simplify_try.rs:8:13: 8:15 +- _17 = move ((_8 as Err).0: i32); // scope 9 at $DIR/simplify_try.rs:8:13: 8:15 +- StorageLive(_18); // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 +- StorageLive(_19); // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 +- _19 = move _17; // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 +- _18 = move _19; // scope 11 at $DIR/simplify_try.rs:8:13: 8:15 +- StorageDead(_19); // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 +- ((_0 as Err).0: i32) = move _18; // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 ++ _8 = ((_3 as Break).0: std::result::Result); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 ++ nop; // scope 3 at $DIR/simplify_try.rs:8:14: 8:15 ++ nop; // scope 3 at $DIR/simplify_try.rs:8:14: 8:15 ++ nop; // scope 9 at $DIR/simplify_try.rs:8:13: 8:15 ++ ((_0 as Err).0: i32) = move ((_8 as Err).0: i32); // scope 9 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 11 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 + discriminant(_0) = 1; // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 +- StorageDead(_18); // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 +- StorageDead(_17); // scope 9 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 +- 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 ++ nop; // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 9 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 3 at $DIR/simplify_try.rs:8:14: 8:15 ++ nop; // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 + 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 ++ nop; // scope 0 at $DIR/simplify_try.rs:10:1: 10:2 return; // scope 0 at $DIR/simplify_try.rs:10:2: 10:2 } + + bb4: { +- StorageLive(_14); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 +- _14 = move ((_4 as Err).0: i32); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 +- StorageLive(_15); // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 +- StorageLive(_16); // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 +- _16 = move _14; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 +- ((_15 as Err).0: i32) = move _16; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 +- discriminant(_15) = 1; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 +- StorageDead(_16); // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 +- ((_3 as Break).0: std::result::Result) = move _15; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 ++ ((((_3 as Break).0: std::result::Result) as Err).0: i32) = move ((_4 as Err).0: i32); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 ++ discriminant(((_3 as Break).0: std::result::Result)) = 1; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + discriminant(_3) = 1; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 +- StorageDead(_15); // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 +- StorageDead(_14); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + goto -> bb1; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + } + + bb5: { + unreachable; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + } + + bb6: { +- StorageLive(_12); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 +- _12 = move ((_4 as Ok).0: u32); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 +- StorageLive(_13); // scope 7 at $DIR/simplify_try.rs:8:13: 8:15 +- _13 = move _12; // scope 7 at $DIR/simplify_try.rs:8:13: 8:15 +- ((_3 as Continue).0: u32) = move _13; // scope 7 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 ++ ((_3 as Continue).0: u32) = move ((_4 as Ok).0: u32); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 7 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 7 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 7 at $DIR/simplify_try.rs:8:13: 8:15 + discriminant(_3) = 0; // scope 7 at $DIR/simplify_try.rs:8:13: 8:15 +- StorageDead(_13); // scope 7 at $DIR/simplify_try.rs:8:13: 8:15 +- StorageDead(_12); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 7 at $DIR/simplify_try.rs:8:13: 8:15 ++ nop; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + goto -> bb1; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + } } 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 df274852f6820..c117bcc2622b8 100644 --- a/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff @@ -5,42 +5,53 @@ debug x => _1; // in scope 0 at $DIR/simplify_try.rs:7:17: 7:18 let mut _0: std::result::Result; // 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; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _3: std::ops::ControlFlow, u32>; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15 let mut _4: std::result::Result; // 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 _5: isize; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + let _6: std::result::Result; // 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 + let mut _8: std::result::Result; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15 + let _9: u32; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _10: u32; // in scope 0 at $DIR/simplify_try.rs:9:8: 9: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:8:9: 8: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 + debug holder => _6; // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15 scope 3 { - scope 7 (inlined >::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 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 + scope 9 (inlined as FromResidual>>::from_residual) { // at $DIR/simplify_try.rs:8:13: 8:15 + debug x => _8; // in scope 9 at $DIR/simplify_try.rs:8:13: 8:15 + let _17: i32; // in scope 9 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _18: i32; // in scope 9 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _19: i32; // in scope 9 at $DIR/simplify_try.rs:8:13: 8:15 + scope 10 { + debug e => _17; // in scope 10 at $DIR/simplify_try.rs:8:13: 8:15 + scope 11 (inlined >::from) { // at $DIR/simplify_try.rs:8:13: 8:15 + debug t => _19; // in scope 11 at $DIR/simplify_try.rs:8:13: 8:15 + } + } } } } 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 + debug val => _9; // in scope 4 at $DIR/simplify_try.rs:8:13: 8:15 scope 5 { } } - scope 6 (inlined as Try>::into_result) { // at $DIR/simplify_try.rs:8:13: 8:15 + scope 6 (inlined as Try>::branch) { // at $DIR/simplify_try.rs:8:13: 8:15 debug self => _4; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _11: isize; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + let _12: u32; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _13: u32; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + let _14: i32; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _15: std::result::Result; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _16: i32; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + scope 7 { + debug c => _12; // in scope 7 at $DIR/simplify_try.rs:8:13: 8:15 + } + scope 8 { + debug e => _14; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + } } bb0: { @@ -48,47 +59,86 @@ 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(_11); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + _11 = discriminant(_4); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + switchInt(move _11) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 6 at $DIR/simplify_try.rs:8:13: 8: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(_11); // scope 0 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:13: 8:15 + switchInt(move _5) -> [0_isize: bb2, otherwise: bb3]; // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + } + + bb2: { + StorageLive(_9); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + _9 = ((_3 as Continue).0: u32); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + _2 = _9; // scope 5 at $DIR/simplify_try.rs:8:13: 8:15 + StorageDead(_9); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 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 + StorageLive(_10); // scope 1 at $DIR/simplify_try.rs:9:8: 9:9 + _10 = _2; // scope 1 at $DIR/simplify_try.rs:9:8: 9:9 + ((_0 as Ok).0: u32) = move _10; // 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(_10); // 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 } - 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 + bb3: { + StorageLive(_6); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 + _6 = ((_3 as Break).0: std::result::Result); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 + StorageLive(_8); // scope 3 at $DIR/simplify_try.rs:8:14: 8:15 + _8 = _6; // scope 3 at $DIR/simplify_try.rs:8:14: 8:15 + StorageLive(_17); // scope 9 at $DIR/simplify_try.rs:8:13: 8:15 + _17 = move ((_8 as Err).0: i32); // scope 9 at $DIR/simplify_try.rs:8:13: 8:15 + StorageLive(_18); // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 + StorageLive(_19); // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 + _19 = move _17; // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 + _18 = move _19; // scope 11 at $DIR/simplify_try.rs:8:13: 8:15 + StorageDead(_19); // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 + ((_0 as Err).0: i32) = move _18; // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 + discriminant(_0) = 1; // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 + StorageDead(_18); // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 + StorageDead(_17); // scope 9 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 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 } + + bb4: { + StorageLive(_14); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + _14 = move ((_4 as Err).0: i32); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + StorageLive(_15); // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + StorageLive(_16); // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + _16 = move _14; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + ((_15 as Err).0: i32) = move _16; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + discriminant(_15) = 1; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + StorageDead(_16); // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + ((_3 as Break).0: std::result::Result) = move _15; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + discriminant(_3) = 1; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + StorageDead(_15); // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + StorageDead(_14); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + goto -> bb1; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + } + + bb5: { + unreachable; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + } + + bb6: { + StorageLive(_12); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + _12 = move ((_4 as Ok).0: u32); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + StorageLive(_13); // scope 7 at $DIR/simplify_try.rs:8:13: 8:15 + _13 = move _12; // scope 7 at $DIR/simplify_try.rs:8:13: 8:15 + ((_3 as Continue).0: u32) = move _13; // scope 7 at $DIR/simplify_try.rs:8:13: 8:15 + discriminant(_3) = 0; // scope 7 at $DIR/simplify_try.rs:8:13: 8:15 + StorageDead(_13); // scope 7 at $DIR/simplify_try.rs:8:13: 8:15 + StorageDead(_12); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + goto -> bb1; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + } } 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 37274691fb476..6535d3f2583f4 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 @@ -4,37 +4,53 @@ fn try_identity(_1: Result) -> Result { debug x => _1; // in scope 0 at $DIR/simplify_try.rs:7:17: 7:18 let mut _0: std::result::Result; // 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; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _3: std::ops::ControlFlow, u32>; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15 let mut _4: std::result::Result; // 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 _5: isize; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + let _6: std::result::Result; // 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 + let mut _8: std::result::Result; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15 + let _9: u32; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _10: u32; // in scope 0 at $DIR/simplify_try.rs:9:8: 9:9 scope 1 { - 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:8:9: 8:10 } scope 2 { - debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15 + debug holder => _6; // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15 scope 3 { - scope 7 (inlined >::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 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 + scope 9 (inlined as FromResidual>>::from_residual) { // at $DIR/simplify_try.rs:8:13: 8:15 + debug x => _8; // in scope 9 at $DIR/simplify_try.rs:8:13: 8:15 + let _17: i32; // in scope 9 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _18: i32; // in scope 9 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _19: i32; // in scope 9 at $DIR/simplify_try.rs:8:13: 8:15 + scope 10 { + debug e => _17; // in scope 10 at $DIR/simplify_try.rs:8:13: 8:15 + scope 11 (inlined >::from) { // at $DIR/simplify_try.rs:8:13: 8:15 + debug t => _19; // in scope 11 at $DIR/simplify_try.rs:8:13: 8:15 + } + } } } } scope 4 { - debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:8:13: 8:15 + debug val => _9; // in scope 4 at $DIR/simplify_try.rs:8:13: 8:15 scope 5 { } } - scope 6 (inlined as Try>::into_result) { // at $DIR/simplify_try.rs:8:13: 8:15 + scope 6 (inlined as Try>::branch) { // at $DIR/simplify_try.rs:8:13: 8:15 debug self => _4; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _11: isize; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + let _12: u32; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _13: u32; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + let _14: i32; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _15: std::result::Result; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _16: i32; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + scope 7 { + debug c => _12; // in scope 7 at $DIR/simplify_try.rs:8:13: 8:15 + } + scope 8 { + debug e => _14; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + } } bb0: { @@ -42,16 +58,85 @@ fn try_identity(_1: Result) -> Result { 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(_11); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + _11 = discriminant(_4); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + switchInt(move _11) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 } bb1: { - _0 = move _3; // scope 1 at $DIR/simplify_try.rs:9:5: 9:10 + StorageDead(_11); // scope 0 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:13: 8:15 + switchInt(move _5) -> [0_isize: bb2, otherwise: bb3]; // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + } + + bb2: { + StorageLive(_9); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + _9 = ((_3 as Continue).0: u32); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + _2 = _9; // scope 5 at $DIR/simplify_try.rs:8:13: 8:15 + StorageDead(_9); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 + StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:8:15: 8:16 + StorageLive(_10); // scope 1 at $DIR/simplify_try.rs:9:8: 9:9 + _10 = _2; // scope 1 at $DIR/simplify_try.rs:9:8: 9:9 + ((_0 as Ok).0: u32) = move _10; // 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(_10); // 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 + } + + bb3: { + StorageLive(_6); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 + _6 = ((_3 as Break).0: std::result::Result); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 + StorageLive(_8); // scope 3 at $DIR/simplify_try.rs:8:14: 8:15 + _8 = _6; // scope 3 at $DIR/simplify_try.rs:8:14: 8:15 + StorageLive(_17); // scope 9 at $DIR/simplify_try.rs:8:13: 8:15 + _17 = move ((_8 as Err).0: i32); // scope 9 at $DIR/simplify_try.rs:8:13: 8:15 + StorageLive(_18); // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 + StorageLive(_19); // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 + _19 = move _17; // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 + _18 = move _19; // scope 11 at $DIR/simplify_try.rs:8:13: 8:15 + StorageDead(_19); // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 + ((_0 as Err).0: i32) = move _18; // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 + discriminant(_0) = 1; // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 + StorageDead(_18); // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 + StorageDead(_17); // scope 9 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 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 } + + bb4: { + StorageLive(_14); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + _14 = move ((_4 as Err).0: i32); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + StorageLive(_15); // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + StorageLive(_16); // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + _16 = move _14; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + ((_15 as Err).0: i32) = move _16; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + discriminant(_15) = 1; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + StorageDead(_16); // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + ((_3 as Break).0: std::result::Result) = move _15; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + discriminant(_3) = 1; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + StorageDead(_15); // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + StorageDead(_14); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + goto -> bb1; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + } + + bb5: { + unreachable; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + } + + bb6: { + StorageLive(_12); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + _12 = move ((_4 as Ok).0: u32); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + StorageLive(_13); // scope 7 at $DIR/simplify_try.rs:8:13: 8:15 + _13 = move _12; // scope 7 at $DIR/simplify_try.rs:8:13: 8:15 + ((_3 as Continue).0: u32) = move _13; // scope 7 at $DIR/simplify_try.rs:8:13: 8:15 + discriminant(_3) = 0; // scope 7 at $DIR/simplify_try.rs:8:13: 8:15 + StorageDead(_13); // scope 7 at $DIR/simplify_try.rs:8:13: 8:15 + StorageDead(_12); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + goto -> bb1; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + } } 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 f8adcced4b306..72de8ad735ee6 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 @@ -3,17 +3,24 @@ fn try_identity(_1: Result) -> Result { debug x => _1; // in scope 0 at $DIR/simplify_try.rs:7:17: 7:18 let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify_try.rs:7:41: 7:57 + let mut _2: std::ops::ControlFlow, u32>; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _3: std::result::Result; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:14 + let mut _4: isize; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _5: std::result::Result; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15 scope 1 { debug y => ((_0 as Ok).0: u32); // in scope 1 at $DIR/simplify_try.rs:8:9: 8:10 } scope 2 { - debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15 + debug holder => _5; // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15 scope 3 { - scope 7 (inlined >::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 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 + scope 9 (inlined as FromResidual>>::from_residual) { // at $DIR/simplify_try.rs:8:13: 8:15 + debug x => _5; // in scope 9 at $DIR/simplify_try.rs:8:13: 8:15 + scope 10 { + debug e => ((_0 as Err).0: i32); // in scope 10 at $DIR/simplify_try.rs:8:13: 8:15 + scope 11 (inlined >::from) { // at $DIR/simplify_try.rs:8:13: 8:15 + debug t => ((_0 as Err).0: i32); // in scope 11 at $DIR/simplify_try.rs:8:13: 8:15 + } + } } } } @@ -22,12 +29,59 @@ fn try_identity(_1: Result) -> Result { scope 5 { } } - scope 6 (inlined 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 6 (inlined as Try>::branch) { // at $DIR/simplify_try.rs:8:13: 8:15 + debug self => _3; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + let mut _6: isize; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + scope 7 { + debug c => ((_2 as Continue).0: u32); // in scope 7 at $DIR/simplify_try.rs:8:13: 8:15 + } + scope 8 { + debug e => ((((_2 as Break).0: std::result::Result) as Err).0: i32); // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + } } bb0: { - _0 = _1; // scope 0 at $DIR/simplify_try.rs:8:13: 8:14 + StorageLive(_3); // scope 0 at $DIR/simplify_try.rs:8:13: 8:14 + _3 = _1; // scope 0 at $DIR/simplify_try.rs:8:13: 8:14 + StorageLive(_6); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + _6 = discriminant(_3); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + switchInt(move _6) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + } + + bb1: { + StorageDead(_6); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 + _4 = discriminant(_2); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + switchInt(move _4) -> [0_isize: bb2, otherwise: bb3]; // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + } + + bb2: { + ((_0 as Ok).0: u32) = ((_2 as Continue).0: u32); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15 + discriminant(_0) = 0; // scope 1 at $DIR/simplify_try.rs:9:5: 9:10 + return; // scope 0 at $DIR/simplify_try.rs:10:2: 10:2 + } + + bb3: { + _5 = ((_2 as Break).0: std::result::Result); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15 + ((_0 as Err).0: i32) = move ((_5 as Err).0: i32); // scope 9 at $DIR/simplify_try.rs:8:13: 8:15 + discriminant(_0) = 1; // scope 10 at $DIR/simplify_try.rs:8:13: 8:15 return; // scope 0 at $DIR/simplify_try.rs:10:2: 10:2 } + + bb4: { + ((((_2 as Break).0: std::result::Result) as Err).0: i32) = move ((_3 as Err).0: i32); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + discriminant(((_2 as Break).0: std::result::Result)) = 1; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + discriminant(_2) = 1; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15 + goto -> bb1; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + } + + bb5: { + unreachable; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + } + + bb6: { + ((_2 as Continue).0: u32) = move ((_3 as Ok).0: u32); // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + discriminant(_2) = 0; // scope 7 at $DIR/simplify_try.rs:8:13: 8:15 + goto -> bb1; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15 + } } From a77b588bf4d7bdb7af0af6513fcba420a17aae53 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 20 Feb 2021 11:35:31 -0800 Subject: [PATCH 08/10] Add a back-compat hack so that nightly code can still call `Try::into_result` --- library/core/src/ops/try.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/library/core/src/ops/try.rs b/library/core/src/ops/try.rs index ec4e7562c69aa..4fd7012eb54a7 100644 --- a/library/core/src/ops/try.rs +++ b/library/core/src/ops/try.rs @@ -123,6 +123,15 @@ pub trait Try2021: FromResidual { ControlFlow::Break(r) => FromResidual::from_residual(r), } } + + /// Hack so that calls to `Try::into_result` keep building on nightly for a while + #[unstable(feature = "try_trait", issue = "42327")] + fn into_result(self) -> Result<::Ok, ::Error> + where + Self: Try2015, + { + ::into_result(self) + } } /// Allows you to pick with other types can be converted into your `Try` type. From 4a07acbbdda6bd8bbb176a74fd90689b280bb917 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 20 Feb 2021 15:10:57 -0800 Subject: [PATCH 09/10] Force rust-analyzer to a version that builds with this PR (DO NOT MERGE) --- src/tools/rust-analyzer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rust-analyzer b/src/tools/rust-analyzer index 7435b9e98c928..0fe44d099ad7c 160000 --- a/src/tools/rust-analyzer +++ b/src/tools/rust-analyzer @@ -1 +1 @@ -Subproject commit 7435b9e98c9280043605748c11a1f450669e04d6 +Subproject commit 0fe44d099ad7cf9c8699e41ece424fda84bce999 From 508ed8d21e6cbfd8e94f7e92e6c6a6a107f9b19f Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 20 Feb 2021 02:37:17 -0800 Subject: [PATCH 10/10] Remove the option-to-result back-compat hack --- library/core/src/result.rs | 25 ------------------- src/test/ui/option-to-result.rs | 2 +- src/test/ui/option-to-result.stderr | 17 +++++++------ src/test/ui/try-block/try-block-bad-type.rs | 4 +-- .../ui/try-block/try-block-bad-type.stderr | 12 ++++----- .../try-on-option-in-result-method.rs | 20 --------------- src/test/ui/try-trait/try-on-option.rs | 2 +- src/test/ui/try-trait/try-on-option.stderr | 17 +++++++------ 8 files changed, 28 insertions(+), 71 deletions(-) delete mode 100644 src/test/ui/try-trait/try-on-option-in-result-method.rs diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 6ee5c25e6649b..380cf7e6b2024 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1650,28 +1650,3 @@ impl> ops::FromResidual> for Result { } } } - -mod sadness { - use super::*; - - /// This is a remnant of the old `NoneError` which is never going to be stabilized. - /// It's here as a snapshot of an oversight that allowed this to work in the past, - /// so we're stuck supporting it even though we'd really rather not. - #[unstable(feature = "legacy_try_trait", issue = "none")] - #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] - pub struct PleaseCallTheOkOrMethodToUseQuestionMarkOnOptionsInAMethodThatReturnsResult; - - #[unstable(feature = "try_trait_v2", issue = "42327")] - impl ops::FromResidual> for Result - where - E: From, - { - fn from_residual(x: Option) -> Self { - match x { - None => Err(From::from( - PleaseCallTheOkOrMethodToUseQuestionMarkOnOptionsInAMethodThatReturnsResult, - )), - } - } - } -} diff --git a/src/test/ui/option-to-result.rs b/src/test/ui/option-to-result.rs index 935a96b7df958..598bab495bda5 100644 --- a/src/test/ui/option-to-result.rs +++ b/src/test/ui/option-to-result.rs @@ -2,7 +2,7 @@ fn main(){ } fn test_result() -> Result<(),()> { let a:Option<()> = Some(()); - a?;//~ ERROR `?` couldn't convert the error to `()` + a?;//~ ERROR the `?` operator can only be used in a function that returns `Result` or `Option` Ok(()) } diff --git a/src/test/ui/option-to-result.stderr b/src/test/ui/option-to-result.stderr index e616ab1dca302..1c5537c358280 100644 --- a/src/test/ui/option-to-result.stderr +++ b/src/test/ui/option-to-result.stderr @@ -1,14 +1,15 @@ -error[E0277]: `?` couldn't convert the error to `()` +error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/option-to-result.rs:5:5 | -LL | fn test_result() -> Result<(),()> { - | ------------- expected `()` because of this -LL | let a:Option<()> = Some(()); -LL | a?; - | ^^ the trait `From` is not implemented for `()` +LL | / fn test_result() -> Result<(),()> { +LL | | let a:Option<()> = Some(()); +LL | | a?; + | | ^^ cannot use the `?` operator in a function that returns `Result<(), ()>` +LL | | Ok(()) +LL | | } + | |_- this function should return `Result` or `Option` to accept `?` | - = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait - = note: required because of the requirements on the impl of `FromResidual>` for `Result<(), ()>` + = help: the trait `FromResidual>` is not implemented for `Result<(), ()>` = 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`) 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 97680eaf2e36e..eeaf16b7f9b81 100644 --- a/src/test/ui/try-block/try-block-bad-type.rs +++ b/src/test/ui/try-block/try-block-bad-type.rs @@ -15,7 +15,7 @@ pub fn main() { let res: Result = try { }; //~ ERROR type mismatch let res: () = try { }; - //~^ ERROR the trait bound `(): Try` is not satisfied + //~^ ERROR the trait bound `(): Try2021` is not satisfied - let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: Try` is not satisfied + let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: Try2021` is not satisfied } 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 f5e99a80039f3..9ae108e6fcab6 100644 --- a/src/test/ui/try-block/try-block-bad-type.stderr +++ b/src/test/ui/try-block/try-block-bad-type.stderr @@ -10,31 +10,31 @@ LL | Err("")?; = note: required because of the requirements on the impl of `FromResidual>` for `Result` = note: required by `from_residual` -error[E0271]: type mismatch resolving ` as Try>::Ok == &str` +error[E0271]: type mismatch resolving ` as Try2021>::Ok == &str` --> $DIR/try-block-bad-type.rs:12:9 | LL | "" | ^^ expected `i32`, found `&str` -error[E0271]: type mismatch resolving ` as Try>::Ok == ()` +error[E0271]: type mismatch resolving ` as Try2021>::Ok == ()` --> $DIR/try-block-bad-type.rs:15:39 | LL | let res: Result = try { }; | ^ expected `i32`, found `()` -error[E0277]: the trait bound `(): Try` is not satisfied +error[E0277]: the trait bound `(): Try2021` is not satisfied --> $DIR/try-block-bad-type.rs:17:25 | LL | let res: () = try { }; - | ^ the trait `Try` is not implemented for `()` + | ^ the trait `Try2021` is not implemented for `()` | = note: required by `from_output` -error[E0277]: the trait bound `i32: Try` is not satisfied +error[E0277]: the trait bound `i32: Try2021` is not satisfied --> $DIR/try-block-bad-type.rs:20:26 | LL | let res: i32 = try { 5 }; - | ^ the trait `Try` is not implemented for `i32` + | ^ the trait `Try2021` is not implemented for `i32` | = note: required by `from_output` diff --git a/src/test/ui/try-trait/try-on-option-in-result-method.rs b/src/test/ui/try-trait/try-on-option-in-result-method.rs deleted file mode 100644 index fe50d9bccb4f5..0000000000000 --- a/src/test/ui/try-trait/try-on-option-in-result-method.rs +++ /dev/null @@ -1,20 +0,0 @@ -// check-pass - -#![allow(dead_code, unused)] - -///! This isn't supposed to work, but it accidentally did, so unfortunately we need to support this. - -struct Tricky; - -impl From for Tricky { - fn from(_: T) -> Tricky { Tricky } -} - -fn foo() -> Result<(), Tricky> { - None?; - Ok(()) -} - -fn main() { - assert!(matches!(foo(), Err(Tricky))); -} diff --git a/src/test/ui/try-trait/try-on-option.rs b/src/test/ui/try-trait/try-on-option.rs index a662bbd35fbce..f2012936a1174 100644 --- a/src/test/ui/try-trait/try-on-option.rs +++ b/src/test/ui/try-trait/try-on-option.rs @@ -4,7 +4,7 @@ fn main() {} fn foo() -> Result { let x: Option = None; - x?; //~ ERROR `?` couldn't convert the error to `()` + 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 index d90eb3bdb0b62..d3a538e18a752 100644 --- a/src/test/ui/try-trait/try-on-option.stderr +++ b/src/test/ui/try-trait/try-on-option.stderr @@ -1,14 +1,15 @@ -error[E0277]: `?` couldn't convert the error to `()` +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:7:5 | -LL | fn foo() -> Result { - | --------------- expected `()` because of this -LL | let x: Option = None; -LL | x?; - | ^^ the trait `From` is not implemented for `()` +LL | / fn foo() -> Result { +LL | | let x: Option = None; +LL | | x?; + | | ^^ cannot use the `?` operator in a function that returns `Result` +LL | | Ok(22) +LL | | } + | |_- this function should return `Result` or `Option` to accept `?` | - = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait - = note: required because of the requirements on the impl of `FromResidual>` for `Result` + = help: the trait `FromResidual>` is not implemented for `Result` = 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`)