mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 01:04:03 +00:00
Auto merge of #84767 - scottmcm:try_trait_actual, r=lcnr
Implement the new desugaring from `try_trait_v2` ~~Currently blocked on https://github.com/rust-lang/rust/issues/84782, which has a PR in https://github.com/rust-lang/rust/pull/84811~~ Rebased atop that fix. `try_trait_v2` tracking issue: https://github.com/rust-lang/rust/issues/84277 Unfortunately this is already touching a ton of things, so if you have suggestions for good ways to split it up, I'd be happy to hear them. (The combination between the use in the library, the compiler changes, the corresponding diagnostic differences, even MIR tests mean that I don't really have a great plan for it other than trying to have decently-readable commits. r? `@ghost` ~~(This probably shouldn't go in during the last week before the fork anyway.)~~ Fork happened.
This commit is contained in:
commit
4e3e6db011
@ -560,8 +560,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
)
|
||||
}
|
||||
|
||||
/// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_ok(<expr>) }`,
|
||||
/// `try { <stmts>; }` into `{ <stmts>; ::std::ops::Try::from_ok(()) }`
|
||||
/// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_output(<expr>) }`,
|
||||
/// `try { <stmts>; }` into `{ <stmts>; ::std::ops::Try::from_output(()) }`
|
||||
/// and save the block id to use it as a break target for desugaring of the `?` operator.
|
||||
fn lower_expr_try_block(&mut self, body: &Block) -> hir::ExprKind<'hir> {
|
||||
self.with_catch_scope(body.id, |this| {
|
||||
@ -590,9 +590,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let ok_wrapped_span =
|
||||
this.mark_span_with_reason(DesugaringKind::TryBlock, tail_expr.span, None);
|
||||
|
||||
// `::std::ops::Try::from_ok($tail_expr)`
|
||||
// `::std::ops::Try::from_output($tail_expr)`
|
||||
block.expr = Some(this.wrap_in_try_constructor(
|
||||
hir::LangItem::TryFromOk,
|
||||
hir::LangItem::TryTraitFromOutput,
|
||||
try_span,
|
||||
tail_expr,
|
||||
ok_wrapped_span,
|
||||
@ -1579,14 +1579,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
self.allow_try_trait.clone(),
|
||||
);
|
||||
|
||||
// `Try::into_result(<expr>)`
|
||||
// `Try::branch(<expr>)`
|
||||
let scrutinee = {
|
||||
// expand <expr>
|
||||
let sub_expr = self.lower_expr_mut(sub_expr);
|
||||
|
||||
self.expr_call_lang_item_fn(
|
||||
unstable_span,
|
||||
hir::LangItem::TryIntoResult,
|
||||
hir::LangItem::TryTraitBranch,
|
||||
arena_vec![self; sub_expr],
|
||||
)
|
||||
};
|
||||
@ -1604,8 +1604,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
};
|
||||
let attrs = vec![attr];
|
||||
|
||||
// `Ok(val) => #[allow(unreachable_code)] val,`
|
||||
let ok_arm = {
|
||||
// `ControlFlow::Continue(val) => #[allow(unreachable_code)] val,`
|
||||
let continue_arm = {
|
||||
let val_ident = Ident::with_dummy_span(sym::val);
|
||||
let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident);
|
||||
let val_expr = self.arena.alloc(self.expr_ident_with_attrs(
|
||||
@ -1614,27 +1614,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
val_pat_nid,
|
||||
ThinVec::from(attrs.clone()),
|
||||
));
|
||||
let ok_pat = self.pat_ok(span, val_pat);
|
||||
self.arm(ok_pat, val_expr)
|
||||
let continue_pat = self.pat_cf_continue(unstable_span, val_pat);
|
||||
self.arm(continue_pat, val_expr)
|
||||
};
|
||||
|
||||
// `Err(err) => #[allow(unreachable_code)]
|
||||
// return Try::from_error(From::from(err)),`
|
||||
let err_arm = {
|
||||
let err_ident = Ident::with_dummy_span(sym::err);
|
||||
let (err_local, err_local_nid) = self.pat_ident(try_span, err_ident);
|
||||
let from_expr = {
|
||||
let err_expr = self.expr_ident_mut(try_span, err_ident, err_local_nid);
|
||||
self.expr_call_lang_item_fn(
|
||||
try_span,
|
||||
hir::LangItem::FromFrom,
|
||||
arena_vec![self; err_expr],
|
||||
)
|
||||
};
|
||||
let from_err_expr = self.wrap_in_try_constructor(
|
||||
hir::LangItem::TryFromError,
|
||||
unstable_span,
|
||||
from_expr,
|
||||
// `ControlFlow::Break(residual) =>
|
||||
// #[allow(unreachable_code)]
|
||||
// return Try::from_residual(residual),`
|
||||
let break_arm = {
|
||||
let residual_ident = Ident::with_dummy_span(sym::residual);
|
||||
let (residual_local, residual_local_nid) = self.pat_ident(try_span, residual_ident);
|
||||
let residual_expr = self.expr_ident_mut(try_span, residual_ident, residual_local_nid);
|
||||
let from_residual_expr = self.wrap_in_try_constructor(
|
||||
hir::LangItem::TryTraitFromResidual,
|
||||
try_span,
|
||||
self.arena.alloc(residual_expr),
|
||||
unstable_span,
|
||||
);
|
||||
let thin_attrs = ThinVec::from(attrs);
|
||||
@ -1645,25 +1639,25 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
try_span,
|
||||
hir::ExprKind::Break(
|
||||
hir::Destination { label: None, target_id },
|
||||
Some(from_err_expr),
|
||||
Some(from_residual_expr),
|
||||
),
|
||||
thin_attrs,
|
||||
))
|
||||
} else {
|
||||
self.arena.alloc(self.expr(
|
||||
try_span,
|
||||
hir::ExprKind::Ret(Some(from_err_expr)),
|
||||
hir::ExprKind::Ret(Some(from_residual_expr)),
|
||||
thin_attrs,
|
||||
))
|
||||
};
|
||||
|
||||
let err_pat = self.pat_err(try_span, err_local);
|
||||
self.arm(err_pat, ret_expr)
|
||||
let break_pat = self.pat_cf_break(try_span, residual_local);
|
||||
self.arm(break_pat, ret_expr)
|
||||
};
|
||||
|
||||
hir::ExprKind::Match(
|
||||
scrutinee,
|
||||
arena_vec![self; err_arm, ok_arm],
|
||||
arena_vec![self; break_arm, continue_arm],
|
||||
hir::MatchSource::TryDesugar,
|
||||
)
|
||||
}
|
||||
|
@ -332,7 +332,7 @@ pub fn lower_crate<'a, 'hir>(
|
||||
lifetimes_to_define: Vec::new(),
|
||||
is_collecting_in_band_lifetimes: false,
|
||||
in_scope_lifetimes: Vec::new(),
|
||||
allow_try_trait: Some([sym::try_trait][..].into()),
|
||||
allow_try_trait: Some([sym::control_flow_enum, sym::try_trait_v2][..].into()),
|
||||
allow_gen_future: Some([sym::gen_future][..].into()),
|
||||
}
|
||||
.lower_crate(krate)
|
||||
@ -2490,14 +2490,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
self.pat(span, hir::PatKind::Lit(expr))
|
||||
}
|
||||
|
||||
fn pat_ok(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
|
||||
fn pat_cf_continue(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
|
||||
let field = self.single_pat_field(span, pat);
|
||||
self.pat_lang_item_variant(span, hir::LangItem::ResultOk, field)
|
||||
self.pat_lang_item_variant(span, hir::LangItem::ControlFlowContinue, field)
|
||||
}
|
||||
|
||||
fn pat_err(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
|
||||
fn pat_cf_break(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
|
||||
let field = self.single_pat_field(span, pat);
|
||||
self.pat_lang_item_variant(span, hir::LangItem::ResultErr, field)
|
||||
self.pat_lang_item_variant(span, hir::LangItem::ControlFlowBreak, field)
|
||||
}
|
||||
|
||||
fn pat_some(&mut self, span: Span, pat: &'hir hir::Pat<'hir>) -> &'hir hir::Pat<'hir> {
|
||||
|
@ -308,12 +308,12 @@ language_item_table! {
|
||||
|
||||
Termination, sym::termination, termination, Target::Trait;
|
||||
|
||||
Try, kw::Try, try_trait, Target::Trait;
|
||||
Try, sym::Try, try_trait, Target::Trait;
|
||||
|
||||
// Language items from AST lowering
|
||||
TryFromError, sym::from_error, from_error_fn, Target::Method(MethodKind::Trait { body: false });
|
||||
TryFromOk, sym::from_ok, from_ok_fn, Target::Method(MethodKind::Trait { body: false });
|
||||
TryIntoResult, sym::into_result, into_result_fn, Target::Method(MethodKind::Trait { body: false });
|
||||
TryTraitFromResidual, sym::from_residual, from_residual_fn, Target::Method(MethodKind::Trait { body: false });
|
||||
TryTraitFromOutput, sym::from_output, from_output_fn, Target::Method(MethodKind::Trait { body: false });
|
||||
TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false });
|
||||
|
||||
PollReady, sym::Ready, poll_ready_variant, Target::Variant;
|
||||
PollPending, sym::Pending, poll_pending_variant, Target::Variant;
|
||||
@ -331,6 +331,9 @@ language_item_table! {
|
||||
ResultOk, sym::Ok, result_ok_variant, Target::Variant;
|
||||
ResultErr, sym::Err, result_err_variant, Target::Variant;
|
||||
|
||||
ControlFlowContinue, sym::Continue, cf_continue_variant, Target::Variant;
|
||||
ControlFlowBreak, sym::Break, cf_break_variant, Target::Variant;
|
||||
|
||||
IntoIterIntoIter, sym::into_iter, into_iter_fn, Target::Method(MethodKind::Trait { body: false });
|
||||
IteratorNext, sym::next, next_fn, Target::Method(MethodKind::Trait { body: false});
|
||||
|
||||
|
@ -130,10 +130,12 @@ symbols! {
|
||||
BTreeSet,
|
||||
BinaryHeap,
|
||||
Borrow,
|
||||
Break,
|
||||
C,
|
||||
CString,
|
||||
Center,
|
||||
Clone,
|
||||
Continue,
|
||||
Copy,
|
||||
Count,
|
||||
Debug,
|
||||
@ -326,6 +328,7 @@ symbols! {
|
||||
box_patterns,
|
||||
box_syntax,
|
||||
braced_empty_structs,
|
||||
branch,
|
||||
breakpoint,
|
||||
bridge,
|
||||
bswap,
|
||||
@ -411,6 +414,7 @@ symbols! {
|
||||
constructor,
|
||||
contents,
|
||||
context,
|
||||
control_flow_enum,
|
||||
convert,
|
||||
copy,
|
||||
copy_closures,
|
||||
@ -511,7 +515,6 @@ symbols! {
|
||||
env,
|
||||
eq,
|
||||
ermsb_target_feature,
|
||||
err,
|
||||
exact_div,
|
||||
except,
|
||||
exchange_malloc,
|
||||
@ -581,10 +584,10 @@ symbols! {
|
||||
frem_fast,
|
||||
from,
|
||||
from_desugaring,
|
||||
from_error,
|
||||
from_generator,
|
||||
from_method,
|
||||
from_ok,
|
||||
from_output,
|
||||
from_residual,
|
||||
from_size_align_unchecked,
|
||||
from_trait,
|
||||
from_usize,
|
||||
@ -653,7 +656,6 @@ symbols! {
|
||||
instruction_set,
|
||||
intel,
|
||||
into_iter,
|
||||
into_result,
|
||||
into_trait,
|
||||
intra_doc_pointers,
|
||||
intrinsics,
|
||||
@ -965,6 +967,7 @@ symbols! {
|
||||
repr_packed,
|
||||
repr_simd,
|
||||
repr_transparent,
|
||||
residual,
|
||||
result,
|
||||
result_type,
|
||||
rhs,
|
||||
@ -1232,7 +1235,7 @@ symbols! {
|
||||
try_blocks,
|
||||
try_from_trait,
|
||||
try_into_trait,
|
||||
try_trait,
|
||||
try_trait_v2,
|
||||
tt,
|
||||
tuple,
|
||||
tuple_from_req,
|
||||
|
@ -66,7 +66,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
R: Try<Output = B>,
|
||||
{
|
||||
let (mut iter, final_res);
|
||||
if self.tail <= self.head {
|
||||
@ -140,7 +140,7 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
R: Try<Output = B>,
|
||||
{
|
||||
let (mut iter, final_res);
|
||||
if self.tail <= self.head {
|
||||
|
@ -140,7 +140,8 @@
|
||||
#![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_uninit_array)]
|
||||
#![feature(alloc_layout_extra)]
|
||||
#![feature(trusted_random_access)]
|
||||
#![feature(try_trait)]
|
||||
#![cfg_attr(bootstrap, feature(try_trait))]
|
||||
#![cfg_attr(not(bootstrap), feature(try_trait_v2))]
|
||||
#![feature(min_type_alias_impl_trait)]
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(slice_group_by)]
|
||||
|
@ -98,7 +98,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
if let Some(ref mut a) = self.a {
|
||||
acc = a.try_fold(acc, &mut f)?;
|
||||
@ -281,7 +281,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
if let Some(ref mut b) = self.b {
|
||||
acc = b.try_rfold(acc, &mut f)?;
|
||||
|
@ -46,7 +46,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
R: Try<Output = B>,
|
||||
{
|
||||
self.it.try_fold(init, clone_try_fold(f))
|
||||
}
|
||||
@ -82,7 +82,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
R: Try<Output = B>,
|
||||
{
|
||||
self.it.try_rfold(init, clone_try_fold(f))
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
R: Try<Output = B>,
|
||||
{
|
||||
self.it.try_fold(init, copy_try_fold(f))
|
||||
}
|
||||
@ -98,7 +98,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
R: Try<Output = B>,
|
||||
{
|
||||
self.it.try_rfold(init, copy_try_fold(f))
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ where
|
||||
fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
// fully iterate the current iterator. this is necessary because
|
||||
// `self.iter` may be empty even when `self.orig` isn't
|
||||
|
@ -71,7 +71,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
#[inline]
|
||||
fn enumerate<'a, T, Acc, R>(
|
||||
@ -150,7 +150,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
// Can safely add and subtract the count, as `ExactSizeIterator` promises
|
||||
// that the number of elements fits into a `usize`.
|
||||
|
@ -37,7 +37,7 @@ fn filter_fold<T, Acc>(
|
||||
move |acc, item| if predicate(&item) { fold(acc, item) } else { acc }
|
||||
}
|
||||
|
||||
fn filter_try_fold<'a, T, Acc, R: Try<Ok = Acc>>(
|
||||
fn filter_try_fold<'a, T, Acc, R: Try<Output = Acc>>(
|
||||
predicate: &'a mut impl FnMut(&T) -> bool,
|
||||
mut fold: impl FnMut(Acc, T) -> R + 'a,
|
||||
) -> impl FnMut(Acc, T) -> R + 'a {
|
||||
@ -88,7 +88,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
self.iter.try_fold(init, filter_try_fold(&mut self.predicate, fold))
|
||||
}
|
||||
@ -117,7 +117,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
self.iter.try_rfold(init, filter_try_fold(&mut self.predicate, fold))
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ fn filter_map_fold<T, B, Acc>(
|
||||
}
|
||||
}
|
||||
|
||||
fn filter_map_try_fold<'a, T, B, Acc, R: Try<Ok = Acc>>(
|
||||
fn filter_map_try_fold<'a, T, B, Acc, R: Try<Output = Acc>>(
|
||||
f: &'a mut impl FnMut(T) -> Option<B>,
|
||||
mut fold: impl FnMut(Acc, B) -> R + 'a,
|
||||
) -> impl FnMut(Acc, T) -> R + 'a {
|
||||
@ -72,7 +72,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
self.iter.try_fold(init, filter_map_try_fold(&mut self.f, fold))
|
||||
}
|
||||
@ -111,7 +111,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
self.iter.try_rfold(init, filter_map_try_fold(&mut self.f, fold))
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
self.inner.try_fold(init, fold)
|
||||
}
|
||||
@ -91,7 +91,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
self.inner.try_rfold(init, fold)
|
||||
}
|
||||
@ -178,7 +178,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
self.inner.try_fold(init, fold)
|
||||
}
|
||||
@ -208,7 +208,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
self.inner.try_rfold(init, fold)
|
||||
}
|
||||
@ -293,10 +293,10 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
#[inline]
|
||||
fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
|
||||
fn flatten<'a, T: IntoIterator, Acc, R: Try<Output = Acc>>(
|
||||
frontiter: &'a mut Option<T::IntoIter>,
|
||||
fold: &'a mut impl FnMut(Acc, T::Item) -> R,
|
||||
) -> impl FnMut(Acc, T) -> R + 'a {
|
||||
@ -382,10 +382,10 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
#[inline]
|
||||
fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
|
||||
fn flatten<'a, T: IntoIterator, Acc, R: Try<Output = Acc>>(
|
||||
backiter: &'a mut Option<T::IntoIter>,
|
||||
fold: &'a mut impl FnMut(Acc, T::Item) -> R,
|
||||
) -> impl FnMut(Acc, T) -> R + 'a
|
||||
|
@ -92,7 +92,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
FuseImpl::try_fold(self, acc, fold)
|
||||
}
|
||||
@ -148,7 +148,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
FuseImpl::try_rfold(self, acc, fold)
|
||||
}
|
||||
@ -219,7 +219,7 @@ trait FuseImpl<I> {
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>;
|
||||
R: Try<Output = Acc>;
|
||||
fn fold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc;
|
||||
@ -238,7 +238,7 @@ trait FuseImpl<I> {
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
I: DoubleEndedIterator;
|
||||
fn rfold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
@ -305,7 +305,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
if let Some(ref mut iter) = self.iter {
|
||||
acc = iter.try_fold(acc, fold)?;
|
||||
@ -354,7 +354,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
if let Some(ref mut iter) = self.iter {
|
||||
@ -443,7 +443,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
unchecked!(self).try_fold(init, fold)
|
||||
}
|
||||
@ -485,7 +485,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
unchecked!(self).try_rfold(init, fold)
|
||||
|
@ -87,7 +87,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
self.iter.try_fold(init, inspect_try_fold(&mut self.f, fold))
|
||||
}
|
||||
@ -117,7 +117,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
self.iter.try_rfold(init, inspect_try_fold(&mut self.f, fold))
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
G: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
self.iter.try_fold(init, map_try_fold(&mut self.f, g))
|
||||
}
|
||||
@ -146,7 +146,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
G: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
self.iter.try_rfold(init, map_try_fold(&mut self.f, g))
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
let Self { iter, predicate } = self;
|
||||
iter.try_fold(init, |acc, x| match predicate(x) {
|
||||
|
@ -168,7 +168,7 @@ where
|
||||
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
|
||||
where
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
R: Try<Output = B>,
|
||||
{
|
||||
let error = &mut *self.error;
|
||||
self.iter
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen};
|
||||
use crate::ops::Try;
|
||||
use crate::ops::{ControlFlow, Try};
|
||||
|
||||
/// An iterator with a `peek()` that returns an optional reference to the next
|
||||
/// element.
|
||||
@ -91,7 +91,7 @@ impl<I: Iterator> Iterator for Peekable<I> {
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
R: Try<Output = B>,
|
||||
{
|
||||
let acc = match self.peeked.take() {
|
||||
Some(None) => return try { init },
|
||||
@ -130,19 +130,42 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(bootstrap))]
|
||||
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
R: Try<Output = B>,
|
||||
{
|
||||
match self.peeked.take() {
|
||||
Some(None) => try { init },
|
||||
Some(Some(v)) => match self.iter.try_rfold(init, &mut f).branch() {
|
||||
ControlFlow::Continue(acc) => f(acc, v),
|
||||
ControlFlow::Break(r) => {
|
||||
self.peeked = Some(Some(v));
|
||||
R::from_residual(r)
|
||||
}
|
||||
},
|
||||
None => self.iter.try_rfold(init, f),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(bootstrap)]
|
||||
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Output = B>,
|
||||
{
|
||||
let _use_the_import: ControlFlow<()>;
|
||||
match self.peeked.take() {
|
||||
Some(None) => try { init },
|
||||
Some(Some(v)) => match self.iter.try_rfold(init, &mut f).into_result() {
|
||||
Ok(acc) => f(acc, v),
|
||||
Err(e) => {
|
||||
self.peeked = Some(Some(v));
|
||||
Try::from_error(e)
|
||||
R::from_error(e)
|
||||
}
|
||||
},
|
||||
None => self.iter.try_rfold(init, f),
|
||||
|
@ -51,7 +51,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
R: Try<Output = B>,
|
||||
{
|
||||
self.iter.try_rfold(init, f)
|
||||
}
|
||||
@ -96,7 +96,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
R: Try<Output = B>,
|
||||
{
|
||||
self.iter.try_fold(init, f)
|
||||
}
|
||||
|
@ -56,9 +56,9 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
fn scan<'a, T, St, B, Acc, R: Try<Ok = Acc>>(
|
||||
fn scan<'a, T, St, B, Acc, R: Try<Output = Acc>>(
|
||||
state: &'a mut St,
|
||||
f: &'a mut impl FnMut(&mut St, T) -> Option<B>,
|
||||
mut fold: impl FnMut(Acc, B) -> R + 'a,
|
||||
|
@ -88,7 +88,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
let n = self.n;
|
||||
self.n = 0;
|
||||
@ -146,9 +146,9 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
fn check<T, Acc, R: Try<Ok = Acc>>(
|
||||
fn check<T, Acc, R: Try<Output = Acc>>(
|
||||
mut n: usize,
|
||||
mut fold: impl FnMut(Acc, T) -> R,
|
||||
) -> impl FnMut(Acc, T) -> ControlFlow<R, Acc> {
|
||||
|
@ -70,7 +70,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
if !self.flag {
|
||||
match self.next() {
|
||||
|
@ -111,7 +111,7 @@ where
|
||||
fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
#[inline]
|
||||
fn nth<I: Iterator>(iter: &mut I, step: usize) -> impl FnMut() -> Option<I::Item> + '_ {
|
||||
@ -187,7 +187,7 @@ where
|
||||
fn try_rfold<Acc, F, R>(&mut self, init: Acc, mut f: F) -> R
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
#[inline]
|
||||
fn nth_back<I: DoubleEndedIterator>(
|
||||
|
@ -80,9 +80,9 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
fn check<'a, T, Acc, R: Try<Ok = Acc>>(
|
||||
fn check<'a, T, Acc, R: Try<Output = Acc>>(
|
||||
n: &'a mut usize,
|
||||
mut fold: impl FnMut(Acc, T) -> R + 'a,
|
||||
) -> impl FnMut(Acc, T) -> ControlFlow<R, Acc> + 'a {
|
||||
@ -178,7 +178,7 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
if self.n == 0 {
|
||||
try { init }
|
||||
|
@ -68,9 +68,9 @@ where
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
R: Try<Output = Acc>,
|
||||
{
|
||||
fn check<'a, T, Acc, R: Try<Ok = Acc>>(
|
||||
fn check<'a, T, Acc, R: Try<Output = Acc>>(
|
||||
flag: &'a mut bool,
|
||||
p: &'a mut impl FnMut(&T) -> bool,
|
||||
mut fold: impl FnMut(Acc, T) -> R + 'a,
|
||||
|
@ -755,7 +755,7 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
R: Try<Output = B>,
|
||||
{
|
||||
if self.is_empty() {
|
||||
return try { init };
|
||||
@ -860,7 +860,7 @@ impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
R: Try<Output = B>,
|
||||
{
|
||||
if self.is_empty() {
|
||||
return try { init };
|
||||
|
@ -218,7 +218,7 @@ pub trait DoubleEndedIterator: Iterator {
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
R: Try<Output = B>,
|
||||
{
|
||||
let mut accum = init;
|
||||
while let Some(x) = self.next_back() {
|
||||
|
@ -1999,7 +1999,7 @@ pub trait Iterator {
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
R: Try<Output = B>,
|
||||
{
|
||||
let mut accum = init;
|
||||
while let Some(x) = self.next() {
|
||||
@ -2041,7 +2041,7 @@ pub trait Iterator {
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(Self::Item) -> R,
|
||||
R: Try<Ok = ()>,
|
||||
R: Try<Output = ()>,
|
||||
{
|
||||
#[inline]
|
||||
fn call<T, R>(mut f: impl FnMut(T) -> R) -> impl FnMut((), T) -> R {
|
||||
@ -2412,17 +2412,48 @@ pub trait Iterator {
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "try_find", reason = "new API", issue = "63178")]
|
||||
#[cfg(not(bootstrap))]
|
||||
fn try_find<F, R, E>(&mut self, f: F) -> Result<Option<Self::Item>, E>
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(&Self::Item) -> R,
|
||||
R: Try<Output = bool>,
|
||||
// FIXME: This bound is rather strange, but means minimal breakage on nightly.
|
||||
// See #85115 for the issue tracking a holistic solution for this and try_map.
|
||||
R: crate::ops::TryV2<Residual = Result<crate::convert::Infallible, E>>,
|
||||
{
|
||||
#[inline]
|
||||
fn check<F, T, R, E>(mut f: F) -> impl FnMut((), T) -> ControlFlow<Result<T, E>>
|
||||
where
|
||||
F: FnMut(&T) -> R,
|
||||
R: Try<Output = bool>,
|
||||
R: crate::ops::TryV2<Residual = Result<crate::convert::Infallible, E>>,
|
||||
{
|
||||
move |(), x| match f(&x).branch() {
|
||||
ControlFlow::Continue(false) => ControlFlow::CONTINUE,
|
||||
ControlFlow::Continue(true) => ControlFlow::Break(Ok(x)),
|
||||
ControlFlow::Break(Err(x)) => ControlFlow::Break(Err(x)),
|
||||
}
|
||||
}
|
||||
|
||||
self.try_fold((), check(f)).break_value().transpose()
|
||||
}
|
||||
|
||||
/// We're bootstrapping.
|
||||
#[inline]
|
||||
#[unstable(feature = "try_find", reason = "new API", issue = "63178")]
|
||||
#[cfg(bootstrap)]
|
||||
fn try_find<F, R>(&mut self, f: F) -> Result<Option<Self::Item>, R::Error>
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(&Self::Item) -> R,
|
||||
R: Try<Ok = bool>,
|
||||
R: Try<Output = bool>,
|
||||
{
|
||||
#[inline]
|
||||
fn check<F, T, R>(mut f: F) -> impl FnMut((), T) -> ControlFlow<Result<T, R::Error>>
|
||||
where
|
||||
F: FnMut(&T) -> R,
|
||||
R: Try<Ok = bool>,
|
||||
R: Try<Output = bool>,
|
||||
{
|
||||
move |(), x| match f(&x).into_result() {
|
||||
Ok(false) => ControlFlow::CONTINUE,
|
||||
|
@ -1,5 +1,4 @@
|
||||
use crate::convert;
|
||||
use crate::ops::{self, Try};
|
||||
use crate::{convert, ops};
|
||||
|
||||
/// Used to tell an operation whether it should exit early or go on as usual.
|
||||
///
|
||||
@ -53,8 +52,10 @@ use crate::ops::{self, Try};
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum ControlFlow<B, C = ()> {
|
||||
/// Move on to the next phase of the operation as normal.
|
||||
#[cfg_attr(not(bootstrap), lang = "Continue")]
|
||||
Continue(C),
|
||||
/// Exit the operation without running subsequent phases.
|
||||
#[cfg_attr(not(bootstrap), lang = "Break")]
|
||||
Break(B),
|
||||
// Yes, the order of the variants doesn't match the type parameters.
|
||||
// They're in this order so that `ControlFlow<A, B>` <-> `Result<B, A>`
|
||||
@ -62,11 +63,11 @@ pub enum ControlFlow<B, C = ()> {
|
||||
}
|
||||
|
||||
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
|
||||
impl<B, C> Try for ControlFlow<B, C> {
|
||||
type Ok = C;
|
||||
impl<B, C> ops::TryV1 for ControlFlow<B, C> {
|
||||
type Output = C;
|
||||
type Error = B;
|
||||
#[inline]
|
||||
fn into_result(self) -> Result<Self::Ok, Self::Error> {
|
||||
fn into_result(self) -> Result<Self::Output, Self::Error> {
|
||||
match self {
|
||||
ControlFlow::Continue(y) => Ok(y),
|
||||
ControlFlow::Break(x) => Err(x),
|
||||
@ -77,7 +78,7 @@ impl<B, C> Try for ControlFlow<B, C> {
|
||||
ControlFlow::Break(v)
|
||||
}
|
||||
#[inline]
|
||||
fn from_ok(v: Self::Ok) -> Self {
|
||||
fn from_ok(v: Self::Output) -> Self {
|
||||
ControlFlow::Continue(v)
|
||||
}
|
||||
}
|
||||
@ -182,14 +183,15 @@ impl<B, C> ControlFlow<B, C> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Try> ControlFlow<R, R::Ok> {
|
||||
#[cfg(bootstrap)]
|
||||
impl<R: ops::TryV1> ControlFlow<R, R::Output> {
|
||||
/// Create a `ControlFlow` from any type implementing `Try`.
|
||||
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
|
||||
#[inline]
|
||||
pub fn from_try(r: R) -> Self {
|
||||
match Try::into_result(r) {
|
||||
match R::into_result(r) {
|
||||
Ok(v) => ControlFlow::Continue(v),
|
||||
Err(v) => ControlFlow::Break(Try::from_error(v)),
|
||||
Err(v) => ControlFlow::Break(R::from_error(v)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,7 +200,30 @@ impl<R: Try> ControlFlow<R, R::Ok> {
|
||||
#[inline]
|
||||
pub fn into_try(self) -> R {
|
||||
match self {
|
||||
ControlFlow::Continue(v) => Try::from_ok(v),
|
||||
ControlFlow::Continue(v) => R::from_ok(v),
|
||||
ControlFlow::Break(v) => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
impl<R: ops::TryV2> ControlFlow<R, R::Output> {
|
||||
/// Create a `ControlFlow` from any type implementing `Try`.
|
||||
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
|
||||
#[inline]
|
||||
pub fn from_try(r: R) -> Self {
|
||||
match R::branch(r) {
|
||||
ControlFlow::Continue(v) => ControlFlow::Continue(v),
|
||||
ControlFlow::Break(v) => ControlFlow::Break(R::from_residual(v)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a `ControlFlow` into any type implementing `Try`;
|
||||
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
|
||||
#[inline]
|
||||
pub fn into_try(self) -> R {
|
||||
match self {
|
||||
ControlFlow::Continue(v) => R::from_output(v),
|
||||
ControlFlow::Break(v) => v,
|
||||
}
|
||||
}
|
||||
|
@ -183,13 +183,21 @@ pub use self::range::{Range, RangeFrom, RangeFull, RangeTo};
|
||||
pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive};
|
||||
|
||||
#[unstable(feature = "try_trait", issue = "42327")]
|
||||
#[cfg(bootstrap)]
|
||||
pub use self::r#try::Try;
|
||||
|
||||
#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")]
|
||||
pub(crate) use self::r#try::Try as TryV1;
|
||||
|
||||
#[unstable(feature = "try_trait_v2", issue = "84277")]
|
||||
pub use self::try_trait::FromResidual;
|
||||
|
||||
#[unstable(feature = "try_trait_v2", issue = "84277")]
|
||||
#[cfg(not(bootstrap))]
|
||||
pub use self::try_trait::Try;
|
||||
|
||||
#[unstable(feature = "try_trait_transition", reason = "for bootstrap", issue = "none")]
|
||||
pub use self::try_trait::Try as TryV2;
|
||||
pub(crate) use self::try_trait::Try as TryV2;
|
||||
|
||||
#[unstable(feature = "generator_trait", issue = "43122")]
|
||||
pub use self::generator::{Generator, GeneratorState};
|
||||
|
@ -25,11 +25,11 @@
|
||||
)
|
||||
)]
|
||||
#[doc(alias = "?")]
|
||||
#[lang = "try"]
|
||||
#[cfg_attr(bootstrap, lang = "try")]
|
||||
pub trait Try {
|
||||
/// The type of this value when viewed as successful.
|
||||
#[unstable(feature = "try_trait", issue = "42327")]
|
||||
type Ok;
|
||||
type Output; // This no longer follows its RFC, but is only used in bootstrap.
|
||||
/// The type of this value when viewed as failed.
|
||||
#[unstable(feature = "try_trait", issue = "42327")]
|
||||
type Error;
|
||||
@ -43,19 +43,19 @@ pub trait Try {
|
||||
/// in the return type of the enclosing scope (which must itself implement
|
||||
/// `Try`). Specifically, the value `X::from_error(From::from(e))`
|
||||
/// is returned, where `X` is the return type of the enclosing function.
|
||||
#[lang = "into_result"]
|
||||
#[cfg_attr(bootstrap, lang = "into_result")]
|
||||
#[unstable(feature = "try_trait", issue = "42327")]
|
||||
fn into_result(self) -> Result<Self::Ok, Self::Error>;
|
||||
fn into_result(self) -> Result<Self::Output, Self::Error>;
|
||||
|
||||
/// Wrap an error value to construct the composite result. For example,
|
||||
/// `Result::Err(x)` and `Result::from_error(x)` are equivalent.
|
||||
#[lang = "from_error"]
|
||||
#[cfg_attr(bootstrap, lang = "from_error")]
|
||||
#[unstable(feature = "try_trait", issue = "42327")]
|
||||
fn from_error(v: Self::Error) -> Self;
|
||||
|
||||
/// Wrap an OK value to construct the composite result. For example,
|
||||
/// `Result::Ok(x)` and `Result::from_ok(x)` are equivalent.
|
||||
#[lang = "from_ok"]
|
||||
#[cfg_attr(bootstrap, lang = "from_ok")]
|
||||
#[unstable(feature = "try_trait", issue = "42327")]
|
||||
fn from_ok(v: Self::Ok) -> Self;
|
||||
fn from_ok(v: Self::Output) -> Self;
|
||||
}
|
||||
|
@ -41,8 +41,7 @@ use crate::ops::ControlFlow;
|
||||
/// output type that we want:
|
||||
/// ```
|
||||
/// # #![feature(try_trait_v2)]
|
||||
/// # #![feature(try_trait_transition)]
|
||||
/// # use std::ops::TryV2 as Try;
|
||||
/// # use std::ops::Try;
|
||||
/// fn simple_try_fold_1<A, T, R: Try<Output = A>>(
|
||||
/// iter: impl Iterator<Item = T>,
|
||||
/// mut accum: A,
|
||||
@ -56,9 +55,8 @@ use crate::ops::ControlFlow;
|
||||
/// into the return type using [`Try::from_output`]:
|
||||
/// ```
|
||||
/// # #![feature(try_trait_v2)]
|
||||
/// # #![feature(try_trait_transition)]
|
||||
/// # #![feature(control_flow_enum)]
|
||||
/// # use std::ops::{ControlFlow, TryV2 as Try};
|
||||
/// # use std::ops::{ControlFlow, Try};
|
||||
/// fn simple_try_fold_2<A, T, R: Try<Output = A>>(
|
||||
/// iter: impl Iterator<Item = T>,
|
||||
/// mut accum: A,
|
||||
@ -81,9 +79,8 @@ use crate::ops::ControlFlow;
|
||||
/// recreated from their corresponding residual, so we'll just call it:
|
||||
/// ```
|
||||
/// # #![feature(try_trait_v2)]
|
||||
/// # #![feature(try_trait_transition)]
|
||||
/// # #![feature(control_flow_enum)]
|
||||
/// # use std::ops::{ControlFlow, TryV2 as Try};
|
||||
/// # use std::ops::{ControlFlow, Try};
|
||||
/// pub fn simple_try_fold_3<A, T, R: Try<Output = A>>(
|
||||
/// iter: impl Iterator<Item = T>,
|
||||
/// mut accum: A,
|
||||
@ -103,10 +100,9 @@ use crate::ops::ControlFlow;
|
||||
/// But this "call `branch`, then `match` on it, and `return` if it was a
|
||||
/// `Break`" is exactly what happens inside the `?` operator. So rather than
|
||||
/// do all this manually, we can just use `?` instead:
|
||||
/// ```compile_fail (enable again once ? converts to the new trait)
|
||||
/// ```
|
||||
/// # #![feature(try_trait_v2)]
|
||||
/// # #![feature(try_trait_transition)]
|
||||
/// # use std::ops::TryV2 as Try;
|
||||
/// # use std::ops::Try;
|
||||
/// fn simple_try_fold<A, T, R: Try<Output = A>>(
|
||||
/// iter: impl Iterator<Item = T>,
|
||||
/// mut accum: A,
|
||||
@ -119,6 +115,22 @@ use crate::ops::ControlFlow;
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "try_trait_v2", issue = "84277")]
|
||||
#[rustc_on_unimplemented(
|
||||
on(
|
||||
all(from_method = "from_output", from_desugaring = "TryBlock"),
|
||||
message = "a `try` block must return `Result` or `Option` \
|
||||
(or another type that implements `{Try}`)",
|
||||
label = "could not wrap the final value of the block as `{Self}` doesn't implement `Try`",
|
||||
),
|
||||
on(
|
||||
all(from_method = "branch", from_desugaring = "QuestionMark"),
|
||||
message = "the `?` operator can only be applied to values \
|
||||
that implement `{Try}`",
|
||||
label = "the `?` operator cannot be applied to type `{Self}`"
|
||||
)
|
||||
)]
|
||||
#[doc(alias = "?")]
|
||||
#[cfg_attr(not(bootstrap), lang = "Try")]
|
||||
pub trait Try: FromResidual {
|
||||
/// The type of the value produced by `?` when *not* short-circuiting.
|
||||
#[unstable(feature = "try_trait_v2", issue = "84277")]
|
||||
@ -159,8 +171,7 @@ pub trait Try: FromResidual {
|
||||
/// ```
|
||||
/// #![feature(try_trait_v2)]
|
||||
/// #![feature(control_flow_enum)]
|
||||
/// #![feature(try_trait_transition)]
|
||||
/// use std::ops::TryV2 as Try;
|
||||
/// use std::ops::Try;
|
||||
///
|
||||
/// assert_eq!(<Result<_, String> as Try>::from_output(3), Ok(3));
|
||||
/// assert_eq!(<Option<_> as Try>::from_output(4), Some(4));
|
||||
@ -178,6 +189,7 @@ pub trait Try: FromResidual {
|
||||
/// let r = std::iter::empty().try_fold(4, |_, ()| -> Option<_> { unreachable!() });
|
||||
/// assert_eq!(r, Some(4));
|
||||
/// ```
|
||||
#[cfg_attr(not(bootstrap), lang = "from_output")]
|
||||
#[unstable(feature = "try_trait_v2", issue = "84277")]
|
||||
fn from_output(output: Self::Output) -> Self;
|
||||
|
||||
@ -191,8 +203,7 @@ pub trait Try: FromResidual {
|
||||
/// ```
|
||||
/// #![feature(try_trait_v2)]
|
||||
/// #![feature(control_flow_enum)]
|
||||
/// #![feature(try_trait_transition)]
|
||||
/// use std::ops::{ControlFlow, TryV2 as Try};
|
||||
/// use std::ops::{ControlFlow, Try};
|
||||
///
|
||||
/// assert_eq!(Ok::<_, String>(3).branch(), ControlFlow::Continue(3));
|
||||
/// assert_eq!(Err::<String, _>(3).branch(), ControlFlow::Break(Err(3)));
|
||||
@ -206,15 +217,80 @@ pub trait Try: FromResidual {
|
||||
/// ControlFlow::Break(ControlFlow::Break(3)),
|
||||
/// );
|
||||
/// ```
|
||||
#[cfg_attr(not(bootstrap), lang = "branch")]
|
||||
#[unstable(feature = "try_trait_v2", issue = "84277")]
|
||||
fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
|
||||
}
|
||||
|
||||
/// Used to specify which residuals can be converted into which [`Try`] types.
|
||||
/// Used to specify which residuals can be converted into which [`crate::ops::Try`] types.
|
||||
///
|
||||
/// Every `Try` type needs to be recreatable from its own associated
|
||||
/// `Residual` type, but can also have additional `FromResidual` implementations
|
||||
/// to support interconversion with other `Try` types.
|
||||
#[rustc_on_unimplemented(
|
||||
on(
|
||||
all(
|
||||
from_method = "from_residual",
|
||||
from_desugaring = "QuestionMark",
|
||||
_Self = "std::result::Result<T, E>",
|
||||
R = "std::option::Option<std::convert::Infallible>"
|
||||
),
|
||||
message = "the `?` operator can only be used on `Result`s, not `Option`s, \
|
||||
in {ItemContext} that returns `Result`",
|
||||
label = "use `.ok_or(...)?` to provide an error compatible with `{Self}`",
|
||||
enclosing_scope = "this function returns a `Result`"
|
||||
),
|
||||
on(
|
||||
all(
|
||||
from_method = "from_residual",
|
||||
from_desugaring = "QuestionMark",
|
||||
_Self = "std::result::Result<T, E>",
|
||||
),
|
||||
// There's a special error message in the trait selection code for
|
||||
// `From` in `?`, so this is not shown for result-in-result errors,
|
||||
// and thus it can be phrased more strongly than `ControlFlow`'s.
|
||||
message = "the `?` operator can only be used on `Result`s \
|
||||
in {ItemContext} that returns `Result`",
|
||||
label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
|
||||
enclosing_scope = "this function returns a `Result`"
|
||||
),
|
||||
on(
|
||||
all(
|
||||
from_method = "from_residual",
|
||||
from_desugaring = "QuestionMark",
|
||||
_Self = "std::option::Option<T>",
|
||||
),
|
||||
// `Option`-in-`Option` always works, as there's only one possible
|
||||
// residual, so this can also be phrased strongly.
|
||||
message = "the `?` operator can only be used on `Option`s \
|
||||
in {ItemContext} that returns `Option`",
|
||||
label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
|
||||
enclosing_scope = "this function returns an `Option`"
|
||||
),
|
||||
on(
|
||||
all(
|
||||
from_method = "from_residual",
|
||||
from_desugaring = "QuestionMark",
|
||||
_Self = "std::ops::ControlFlow<B, C>",
|
||||
),
|
||||
message = "the `?` operator can only be used on `ControlFlow<B, _>`s \
|
||||
in {ItemContext} that returns `ControlFlow<B, _>`",
|
||||
label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
|
||||
enclosing_scope = "this function returns a `ControlFlow`",
|
||||
note = "unlike `Result`, there's no `From`-conversion performed for `ControlFlow`"
|
||||
),
|
||||
on(
|
||||
all(
|
||||
from_method = "from_residual",
|
||||
from_desugaring = "QuestionMark"
|
||||
),
|
||||
message = "the `?` operator can only be used in {ItemContext} \
|
||||
that returns `Result` or `Option` \
|
||||
(or another type that implements `{FromResidual}`)",
|
||||
label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`",
|
||||
enclosing_scope = "this function should return `Result` or `Option` to accept `?`"
|
||||
),
|
||||
)]
|
||||
#[unstable(feature = "try_trait_v2", issue = "84277")]
|
||||
pub trait FromResidual<R = <Self as Try>::Residual> {
|
||||
/// Constructs the type from a compatible `Residual` type.
|
||||
@ -238,6 +314,7 @@ pub trait FromResidual<R = <Self as Try>::Residual> {
|
||||
/// ControlFlow::Break(5),
|
||||
/// );
|
||||
/// ```
|
||||
#[cfg_attr(not(bootstrap), lang = "from_residual")]
|
||||
#[unstable(feature = "try_trait_v2", issue = "84277")]
|
||||
fn from_residual(residual: R) -> Self;
|
||||
}
|
||||
|
@ -1644,8 +1644,8 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
|
||||
pub struct NoneError;
|
||||
|
||||
#[unstable(feature = "try_trait", issue = "42327")]
|
||||
impl<T> ops::Try for Option<T> {
|
||||
type Ok = T;
|
||||
impl<T> ops::TryV1 for Option<T> {
|
||||
type Output = T;
|
||||
type Error = NoneError;
|
||||
|
||||
#[inline]
|
||||
|
@ -1627,8 +1627,8 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
|
||||
}
|
||||
|
||||
#[unstable(feature = "try_trait", issue = "42327")]
|
||||
impl<T, E> ops::Try for Result<T, E> {
|
||||
type Ok = T;
|
||||
impl<T, E> ops::TryV1 for Result<T, E> {
|
||||
type Output = T;
|
||||
type Error = E;
|
||||
|
||||
#[inline]
|
||||
|
@ -110,7 +110,7 @@ impl<'a> iter::Iterator for EscapeAscii<'a> {
|
||||
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: ops::Try<Ok = Acc>,
|
||||
R: ops::Try<Output = Acc>,
|
||||
{
|
||||
self.inner.try_fold(init, fold)
|
||||
}
|
||||
|
@ -1467,7 +1467,7 @@ macro_rules! escape_types_impls {
|
||||
|
||||
#[inline]
|
||||
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R where
|
||||
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Ok=Acc>
|
||||
Self: Sized, Fold: FnMut(Acc, Self::Item) -> R, R: Try<Output = Acc>
|
||||
{
|
||||
self.inner.try_fold(init, fold)
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#![stable(feature = "futures_api", since = "1.36.0")]
|
||||
|
||||
use crate::convert;
|
||||
use crate::ops::{self, ControlFlow, Try};
|
||||
use crate::ops::{self, ControlFlow};
|
||||
use crate::result::Result;
|
||||
|
||||
/// Indicates whether a value is available or if the current task has been
|
||||
@ -129,12 +129,12 @@ impl<T> From<T> for Poll<T> {
|
||||
}
|
||||
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
impl<T, E> Try for Poll<Result<T, E>> {
|
||||
type Ok = Poll<T>;
|
||||
impl<T, E> ops::TryV1 for Poll<Result<T, E>> {
|
||||
type Output = Poll<T>;
|
||||
type Error = E;
|
||||
|
||||
#[inline]
|
||||
fn into_result(self) -> Result<Self::Ok, Self::Error> {
|
||||
fn into_result(self) -> Result<Self::Output, Self::Error> {
|
||||
match self {
|
||||
Poll::Ready(Ok(x)) => Ok(Poll::Ready(x)),
|
||||
Poll::Ready(Err(e)) => Err(e),
|
||||
@ -148,7 +148,7 @@ impl<T, E> Try for Poll<Result<T, E>> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_ok(x: Self::Ok) -> Self {
|
||||
fn from_ok(x: Self::Output) -> Self {
|
||||
x.map(Ok)
|
||||
}
|
||||
}
|
||||
@ -184,12 +184,12 @@ impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>> for Pol
|
||||
}
|
||||
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
impl<T, E> Try for Poll<Option<Result<T, E>>> {
|
||||
type Ok = Poll<Option<T>>;
|
||||
impl<T, E> ops::TryV1 for Poll<Option<Result<T, E>>> {
|
||||
type Output = Poll<Option<T>>;
|
||||
type Error = E;
|
||||
|
||||
#[inline]
|
||||
fn into_result(self) -> Result<Self::Ok, Self::Error> {
|
||||
fn into_result(self) -> Result<Self::Output, Self::Error> {
|
||||
match self {
|
||||
Poll::Ready(Some(Ok(x))) => Ok(Poll::Ready(Some(x))),
|
||||
Poll::Ready(Some(Err(e))) => Err(e),
|
||||
@ -204,7 +204,7 @@ impl<T, E> Try for Poll<Option<Result<T, E>>> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_ok(x: Self::Ok) -> Self {
|
||||
fn from_ok(x: Self::Output) -> Self {
|
||||
x.map(|x| x.map(Ok))
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,7 @@
|
||||
#![feature(test)]
|
||||
#![feature(trusted_len)]
|
||||
#![feature(try_trait)]
|
||||
#![feature(try_trait_v2)]
|
||||
#![feature(slice_internals)]
|
||||
#![feature(slice_partition_dedup)]
|
||||
#![feature(int_error_matching)]
|
||||
|
@ -301,18 +301,6 @@ fn test_try() {
|
||||
Some(val)
|
||||
}
|
||||
assert_eq!(try_option_none(), None);
|
||||
|
||||
fn try_option_ok() -> Result<u8, NoneError> {
|
||||
let val = Some(1)?;
|
||||
Ok(val)
|
||||
}
|
||||
assert_eq!(try_option_ok(), Ok(1));
|
||||
|
||||
fn try_option_err() -> Result<u8, NoneError> {
|
||||
let val = None?;
|
||||
Ok(val)
|
||||
}
|
||||
assert_eq!(try_option_err(), Err(NoneError));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -249,26 +249,14 @@ pub fn test_into_err() {
|
||||
|
||||
#[test]
|
||||
fn test_try() {
|
||||
fn try_result_some() -> Option<u8> {
|
||||
let val = Ok(1)?;
|
||||
Some(val)
|
||||
}
|
||||
assert_eq!(try_result_some(), Some(1));
|
||||
|
||||
fn try_result_none() -> Option<u8> {
|
||||
let val = Err(NoneError)?;
|
||||
Some(val)
|
||||
}
|
||||
assert_eq!(try_result_none(), None);
|
||||
|
||||
fn try_result_ok() -> Result<u8, u8> {
|
||||
fn try_result_ok() -> Result<u8, u32> {
|
||||
let result: Result<u8, u8> = Ok(1);
|
||||
let val = result?;
|
||||
Ok(val)
|
||||
}
|
||||
assert_eq!(try_result_ok(), Ok(1));
|
||||
|
||||
fn try_result_err() -> Result<u8, u8> {
|
||||
fn try_result_err() -> Result<u8, u32> {
|
||||
let result: Result<u8, u8> = Err(1);
|
||||
let val = result?;
|
||||
Ok(val)
|
||||
@ -401,3 +389,17 @@ fn result_opt_conversions() {
|
||||
|
||||
assert_eq!(res, Err(BadNumErr))
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(bootstrap))] // Needs the V2 trait
|
||||
fn result_try_trait_v2_branch() {
|
||||
use core::num::NonZeroU32;
|
||||
use core::ops::{ControlFlow::*, Try};
|
||||
assert_eq!(Ok::<i32, i32>(4).branch(), Continue(4));
|
||||
assert_eq!(Err::<i32, i32>(4).branch(), Break(Err(4)));
|
||||
let one = NonZeroU32::new(1).unwrap();
|
||||
assert_eq!(Ok::<(), NonZeroU32>(()).branch(), Continue(()));
|
||||
assert_eq!(Err::<(), NonZeroU32>(one).branch(), Break(Err(one)));
|
||||
assert_eq!(Ok::<NonZeroU32, ()>(one).branch(), Continue(one));
|
||||
assert_eq!(Err::<NonZeroU32, ()>(()).branch(), Break(Err(())));
|
||||
}
|
||||
|
@ -7,11 +7,28 @@
|
||||
|
||||
type R = Result<u64, i32>;
|
||||
|
||||
// This was written to the `?` from `try_trait`, but `try_trait_v2` uses a different structure,
|
||||
// so the relevant desugar is copied inline in order to keep the test testing the same thing.
|
||||
// FIXME(#85133): while this might be useful for `r#try!`, it would be nice to have a MIR
|
||||
// optimization that picks up the `?` desugaring, as `SimplifyArmIdentity` does not.
|
||||
#[no_mangle]
|
||||
fn try_identity(x: R) -> R {
|
||||
pub fn try_identity(x: R) -> R {
|
||||
// CHECK: start:
|
||||
// CHECK-NOT: br {{.*}}
|
||||
// CHECK ret void
|
||||
let y = x?;
|
||||
let y = match into_result(x) {
|
||||
Err(e) => return from_error(From::from(e)),
|
||||
Ok(v) => v,
|
||||
};
|
||||
Ok(y)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_result<T, E>(r: Result<T, E>) -> Result<T, E> {
|
||||
r
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_error<T, E>(e: E) -> Result<T, E> {
|
||||
Err(e)
|
||||
}
|
||||
|
@ -4,21 +4,20 @@ fn test() -> Option<Box<u32>> {
|
||||
let mut _0: std::option::Option<std::boxed::Box<u32>>; // return place in scope 0 at $DIR/issue-62289.rs:8:14: 8:30
|
||||
let mut _1: std::boxed::Box<u32>; // in scope 0 at $DIR/issue-62289.rs:9:10: 9:21
|
||||
let mut _2: std::boxed::Box<u32>; // in scope 0 at $DIR/issue-62289.rs:9:10: 9:21
|
||||
let mut _3: std::result::Result<u32, std::option::NoneError>; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20
|
||||
let mut _3: std::ops::ControlFlow<std::option::Option<std::convert::Infallible>, u32>; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20
|
||||
let mut _4: std::option::Option<u32>; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:19
|
||||
let mut _5: isize; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
let _6: std::option::NoneError; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
let _6: std::option::Option<std::convert::Infallible>; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
let mut _7: !; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
let mut _8: std::option::NoneError; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
let mut _9: std::option::NoneError; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
let _10: u32; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20
|
||||
let mut _8: std::option::Option<std::convert::Infallible>; // in scope 0 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
let _9: u32; // in scope 0 at $DIR/issue-62289.rs:9:15: 9:20
|
||||
scope 1 {
|
||||
debug err => _6; // in scope 1 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
debug residual => _6; // in scope 1 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
scope 2 {
|
||||
}
|
||||
}
|
||||
scope 3 {
|
||||
debug val => _10; // in scope 3 at $DIR/issue-62289.rs:9:15: 9:20
|
||||
debug val => _9; // in scope 3 at $DIR/issue-62289.rs:9:15: 9:20
|
||||
scope 4 {
|
||||
}
|
||||
}
|
||||
@ -30,10 +29,10 @@ fn test() -> Option<Box<u32>> {
|
||||
StorageLive(_3); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
|
||||
StorageLive(_4); // scope 0 at $DIR/issue-62289.rs:9:15: 9:19
|
||||
_4 = Option::<u32>::None; // scope 0 at $DIR/issue-62289.rs:9:15: 9:19
|
||||
_3 = <Option<u32> as Try>::into_result(move _4) -> [return: bb1, unwind: bb12]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
|
||||
_3 = <Option<u32> as Try>::branch(move _4) -> [return: bb1, unwind: bb11]; // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
|
||||
// mir::Constant
|
||||
// + span: $DIR/issue-62289.rs:9:15: 9:20
|
||||
// + literal: Const { ty: fn(std::option::Option<u32>) -> std::result::Result<<std::option::Option<u32> as std::ops::Try>::Ok, <std::option::Option<u32> as std::ops::Try>::Error> {<std::option::Option<u32> as std::ops::Try>::into_result}, val: Value(Scalar(<ZST>)) }
|
||||
// + literal: Const { ty: fn(std::option::Option<u32>) -> std::ops::ControlFlow<<std::option::Option<u32> as std::ops::Try>::Residual, <std::option::Option<u32> as std::ops::Try>::Output> {<std::option::Option<u32> as std::ops::Try>::branch}, val: Value(Scalar(<ZST>)) }
|
||||
}
|
||||
|
||||
bb1: {
|
||||
@ -43,12 +42,12 @@ fn test() -> Option<Box<u32>> {
|
||||
}
|
||||
|
||||
bb2: {
|
||||
StorageLive(_10); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
|
||||
_10 = ((_3 as Ok).0: u32); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
|
||||
(*_2) = _10; // scope 4 at $DIR/issue-62289.rs:9:15: 9:20
|
||||
StorageDead(_10); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
StorageLive(_9); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
|
||||
_9 = ((_3 as Continue).0: u32); // scope 0 at $DIR/issue-62289.rs:9:15: 9:20
|
||||
(*_2) = _9; // scope 4 at $DIR/issue-62289.rs:9:15: 9:20
|
||||
StorageDead(_9); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
_1 = move _2; // scope 0 at $DIR/issue-62289.rs:9:10: 9:21
|
||||
drop(_2) -> [return: bb7, unwind: bb11]; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
|
||||
drop(_2) -> [return: bb6, unwind: bb10]; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
|
||||
}
|
||||
|
||||
bb3: {
|
||||
@ -57,62 +56,53 @@ fn test() -> Option<Box<u32>> {
|
||||
|
||||
bb4: {
|
||||
StorageLive(_6); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
_6 = ((_3 as Err).0: std::option::NoneError); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
_6 = ((_3 as Break).0: std::option::Option<std::convert::Infallible>); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
StorageLive(_8); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
StorageLive(_9); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
_9 = _6; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
_8 = <NoneError as From<NoneError>>::from(move _9) -> [return: bb5, unwind: bb12]; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
_8 = _6; // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
_0 = <Option<Box<u32>> as FromResidual<Option<Infallible>>>::from_residual(move _8) -> [return: bb5, unwind: bb11]; // scope 2 at $DIR/issue-62289.rs:9:15: 9:20
|
||||
// mir::Constant
|
||||
// + span: $DIR/issue-62289.rs:9:19: 9:20
|
||||
// + literal: Const { ty: fn(std::option::NoneError) -> std::option::NoneError {<std::option::NoneError as std::convert::From<std::option::NoneError>>::from}, val: Value(Scalar(<ZST>)) }
|
||||
// + literal: Const { ty: fn(std::option::Option<std::convert::Infallible>) -> std::option::Option<std::boxed::Box<u32>> {<std::option::Option<std::boxed::Box<u32>> as std::ops::FromResidual<std::option::Option<std::convert::Infallible>>>::from_residual}, val: Value(Scalar(<ZST>)) }
|
||||
}
|
||||
|
||||
bb5: {
|
||||
StorageDead(_9); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
_0 = <Option<Box<u32>> as Try>::from_error(move _8) -> [return: bb6, unwind: bb12]; // scope 2 at $DIR/issue-62289.rs:9:15: 9:20
|
||||
// mir::Constant
|
||||
// + span: $DIR/issue-62289.rs:9:15: 9:20
|
||||
// + literal: Const { ty: fn(<std::option::Option<std::boxed::Box<u32>> as std::ops::Try>::Error) -> std::option::Option<std::boxed::Box<u32>> {<std::option::Option<std::boxed::Box<u32>> as std::ops::Try>::from_error}, val: Value(Scalar(<ZST>)) }
|
||||
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) -> bb8; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
|
||||
}
|
||||
|
||||
bb6: {
|
||||
StorageDead(_8); // scope 2 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
StorageDead(_6); // scope 0 at $DIR/issue-62289.rs:9:19: 9:20
|
||||
drop(_2) -> bb9; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
|
||||
StorageDead(_2); // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
|
||||
_0 = Option::<Box<u32>>::Some(move _1); // scope 0 at $DIR/issue-62289.rs:9:5: 9:22
|
||||
drop(_1) -> bb7; // scope 0 at $DIR/issue-62289.rs:9:21: 9:22
|
||||
}
|
||||
|
||||
bb7: {
|
||||
StorageDead(_2); // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
|
||||
_0 = Option::<Box<u32>>::Some(move _1); // scope 0 at $DIR/issue-62289.rs:9:5: 9:22
|
||||
drop(_1) -> bb8; // scope 0 at $DIR/issue-62289.rs:9:21: 9:22
|
||||
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 -> bb9; // scope 0 at $DIR/issue-62289.rs:10:2: 10:2
|
||||
}
|
||||
|
||||
bb8: {
|
||||
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
|
||||
}
|
||||
|
||||
bb9: {
|
||||
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
|
||||
}
|
||||
|
||||
bb10 (cleanup): {
|
||||
drop(_1) -> bb12; // scope 0 at $DIR/issue-62289.rs:9:21: 9:22
|
||||
}
|
||||
|
||||
bb11 (cleanup): {
|
||||
drop(_1) -> bb13; // scope 0 at $DIR/issue-62289.rs:9:21: 9:22
|
||||
drop(_2) -> bb12; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
|
||||
}
|
||||
|
||||
bb12 (cleanup): {
|
||||
drop(_2) -> bb13; // scope 0 at $DIR/issue-62289.rs:9:20: 9:21
|
||||
}
|
||||
|
||||
bb13 (cleanup): {
|
||||
resume; // scope 0 at $DIR/issue-62289.rs:8:1: 10:2
|
||||
}
|
||||
}
|
||||
|
@ -20,8 +20,23 @@ fn id_result(r: Result<u8, i32>) -> Result<u8, i32> {
|
||||
}
|
||||
}
|
||||
|
||||
fn into_result<T, E>(r: Result<T, E>) -> Result<T, E> {
|
||||
r
|
||||
}
|
||||
|
||||
fn from_error<T, E>(e: E) -> Result<T, E> {
|
||||
Err(e)
|
||||
}
|
||||
|
||||
// This was written to the `?` from `try_trait`, but `try_trait_v2` uses a different structure,
|
||||
// so the relevant desugar is copied inline in order to keep the test testing the same thing.
|
||||
// FIXME(#85133): while this might be useful for `r#try!`, it would be nice to have a MIR
|
||||
// optimization that picks up the `?` desugaring, as `SimplifyArmIdentity` does not.
|
||||
fn id_try(r: Result<u8, i32>) -> Result<u8, i32> {
|
||||
let x = r?;
|
||||
let x = match into_result(r) {
|
||||
Err(e) => return from_error(From::from(e)),
|
||||
Ok(v) => v,
|
||||
};
|
||||
Ok(x)
|
||||
}
|
||||
|
||||
|
@ -2,101 +2,93 @@
|
||||
+ // MIR for `id_try` after SimplifyArmIdentity
|
||||
|
||||
fn id_try(_1: Result<u8, i32>) -> Result<u8, i32> {
|
||||
debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:23:11: 23:12
|
||||
let mut _0: std::result::Result<u8, i32>; // return place in scope 0 at $DIR/simplify-arm.rs:23:34: 23:49
|
||||
let _2: u8; // in scope 0 at $DIR/simplify-arm.rs:24:9: 24:10
|
||||
let mut _3: std::result::Result<u8, i32>; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
let mut _4: std::result::Result<u8, i32>; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:14
|
||||
let mut _5: isize; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
let _6: i32; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
let mut _7: !; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
let mut _8: i32; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
let mut _9: i32; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
let _10: u8; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
let mut _11: u8; // in scope 0 at $DIR/simplify-arm.rs:25:8: 25:9
|
||||
debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:35:11: 35:12
|
||||
let mut _0: std::result::Result<u8, i32>; // return place in scope 0 at $DIR/simplify-arm.rs:35:34: 35:49
|
||||
let _2: u8; // in scope 0 at $DIR/simplify-arm.rs:36:9: 36:10
|
||||
let mut _3: std::result::Result<u8, i32>; // in scope 0 at $DIR/simplify-arm.rs:36:19: 36:33
|
||||
let mut _4: std::result::Result<u8, i32>; // in scope 0 at $DIR/simplify-arm.rs:36:31: 36:32
|
||||
let mut _5: isize; // in scope 0 at $DIR/simplify-arm.rs:37:9: 37:15
|
||||
let _6: i32; // in scope 0 at $DIR/simplify-arm.rs:37:13: 37:14
|
||||
let mut _7: !; // in scope 0 at $DIR/simplify-arm.rs:37:19: 37:51
|
||||
let mut _8: i32; // in scope 0 at $DIR/simplify-arm.rs:37:37: 37:50
|
||||
let mut _9: i32; // in scope 0 at $DIR/simplify-arm.rs:37:48: 37:49
|
||||
let _10: u8; // in scope 0 at $DIR/simplify-arm.rs:38:12: 38:13
|
||||
let mut _11: u8; // in scope 0 at $DIR/simplify-arm.rs:40:8: 40:9
|
||||
scope 1 {
|
||||
- debug x => _2; // in scope 1 at $DIR/simplify-arm.rs:24:9: 24:10
|
||||
+ debug x => ((_0 as Ok).0: u8); // in scope 1 at $DIR/simplify-arm.rs:24:9: 24:10
|
||||
- debug x => _2; // in scope 1 at $DIR/simplify-arm.rs:36:9: 36:10
|
||||
+ debug x => ((_0 as Ok).0: u8); // in scope 1 at $DIR/simplify-arm.rs:36:9: 36:10
|
||||
}
|
||||
scope 2 {
|
||||
- debug err => _6; // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
+ debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
scope 3 {
|
||||
scope 7 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
- debug t => _9; // in scope 7 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
+ debug t => ((_0 as Err).0: i32); // in scope 7 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
}
|
||||
scope 8 (inlined <Result<u8, i32> as Try>::from_error) { // at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
- debug v => _8; // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
+ debug v => ((_0 as Err).0: i32); // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
let mut _12: i32; // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
}
|
||||
- debug e => _6; // in scope 2 at $DIR/simplify-arm.rs:37:13: 37:14
|
||||
+ debug e => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:37:13: 37:14
|
||||
scope 5 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify-arm.rs:37:37: 37:50
|
||||
- debug t => _9; // in scope 5 at $DIR/simplify-arm.rs:37:37: 37:50
|
||||
+ debug t => ((_0 as Err).0: i32); // in scope 5 at $DIR/simplify-arm.rs:37:37: 37:50
|
||||
}
|
||||
scope 6 (inlined from_error::<u8, i32>) { // at $DIR/simplify-arm.rs:37:26: 37:51
|
||||
- debug e => _8; // in scope 6 at $DIR/simplify-arm.rs:37:26: 37:51
|
||||
+ debug e => ((_0 as Err).0: i32); // in scope 6 at $DIR/simplify-arm.rs:37:26: 37:51
|
||||
}
|
||||
}
|
||||
scope 4 {
|
||||
- debug val => _10; // in scope 4 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
+ debug val => ((_0 as Ok).0: u8); // in scope 4 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
scope 5 {
|
||||
}
|
||||
scope 3 {
|
||||
- debug v => _10; // in scope 3 at $DIR/simplify-arm.rs:38:12: 38:13
|
||||
+ debug v => ((_0 as Ok).0: u8); // in scope 3 at $DIR/simplify-arm.rs:38:12: 38:13
|
||||
}
|
||||
scope 6 (inlined <Result<u8, i32> as Try>::into_result) { // at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
debug self => _4; // in scope 6 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
scope 4 (inlined into_result::<u8, i32>) { // at $DIR/simplify-arm.rs:36:19: 36:33
|
||||
debug r => _4; // in scope 4 at $DIR/simplify-arm.rs:36:19: 36:33
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/simplify-arm.rs:24:9: 24:10
|
||||
StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
StorageLive(_4); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:14
|
||||
_4 = _1; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:14
|
||||
_3 = move _4; // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
StorageDead(_4); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
_5 = discriminant(_3); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
StorageLive(_2); // scope 0 at $DIR/simplify-arm.rs:36:9: 36:10
|
||||
StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:36:19: 36:33
|
||||
StorageLive(_4); // scope 0 at $DIR/simplify-arm.rs:36:31: 36:32
|
||||
_4 = _1; // scope 0 at $DIR/simplify-arm.rs:36:31: 36:32
|
||||
_3 = move _4; // scope 4 at $DIR/simplify-arm.rs:36:19: 36:33
|
||||
StorageDead(_4); // scope 0 at $DIR/simplify-arm.rs:36:32: 36:33
|
||||
_5 = discriminant(_3); // scope 0 at $DIR/simplify-arm.rs:37:9: 37:15
|
||||
switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:37:9: 37:15
|
||||
}
|
||||
|
||||
bb1: {
|
||||
- StorageLive(_10); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
- _10 = ((_3 as Ok).0: u8); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
- _2 = _10; // scope 5 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
- StorageDead(_10); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
+ _0 = move _3; // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
|
||||
StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16
|
||||
- StorageLive(_11); // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9
|
||||
- _11 = _2; // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9
|
||||
- ((_0 as Ok).0: u8) = move _11; // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
|
||||
- discriminant(_0) = 0; // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
|
||||
- StorageDead(_11); // scope 1 at $DIR/simplify-arm.rs:25:9: 25:10
|
||||
StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2
|
||||
goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
|
||||
- StorageLive(_10); // scope 0 at $DIR/simplify-arm.rs:38:12: 38:13
|
||||
- _10 = ((_3 as Ok).0: u8); // scope 0 at $DIR/simplify-arm.rs:38:12: 38:13
|
||||
- _2 = _10; // scope 3 at $DIR/simplify-arm.rs:38:18: 38:19
|
||||
- StorageDead(_10); // scope 0 at $DIR/simplify-arm.rs:38:18: 38:19
|
||||
+ _0 = move _3; // scope 1 at $DIR/simplify-arm.rs:40:5: 40:10
|
||||
StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:39:6: 39:7
|
||||
- StorageLive(_11); // scope 1 at $DIR/simplify-arm.rs:40:8: 40:9
|
||||
- _11 = _2; // scope 1 at $DIR/simplify-arm.rs:40:8: 40:9
|
||||
- ((_0 as Ok).0: u8) = move _11; // scope 1 at $DIR/simplify-arm.rs:40:5: 40:10
|
||||
- discriminant(_0) = 0; // scope 1 at $DIR/simplify-arm.rs:40:5: 40:10
|
||||
- StorageDead(_11); // scope 1 at $DIR/simplify-arm.rs:40:9: 40:10
|
||||
StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:41:1: 41:2
|
||||
goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2
|
||||
}
|
||||
|
||||
bb2: {
|
||||
unreachable; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
unreachable; // scope 0 at $DIR/simplify-arm.rs:36:19: 36:33
|
||||
}
|
||||
|
||||
bb3: {
|
||||
- StorageLive(_6); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
- _6 = ((_3 as Err).0: i32); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
- StorageLive(_8); // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
- StorageLive(_9); // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
- _9 = _6; // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
- _8 = move _9; // scope 7 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
- StorageDead(_9); // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
- StorageLive(_12); // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
- _12 = move _8; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
- ((_0 as Err).0: i32) = move _12; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
- discriminant(_0) = 1; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
- StorageDead(_12); // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
- StorageDead(_8); // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
- StorageDead(_6); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
+ _0 = move _3; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16
|
||||
StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2
|
||||
goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
|
||||
- StorageLive(_6); // scope 0 at $DIR/simplify-arm.rs:37:13: 37:14
|
||||
- _6 = ((_3 as Err).0: i32); // scope 0 at $DIR/simplify-arm.rs:37:13: 37:14
|
||||
- StorageLive(_8); // scope 2 at $DIR/simplify-arm.rs:37:37: 37:50
|
||||
- StorageLive(_9); // scope 2 at $DIR/simplify-arm.rs:37:48: 37:49
|
||||
- _9 = _6; // scope 2 at $DIR/simplify-arm.rs:37:48: 37:49
|
||||
- _8 = move _9; // scope 5 at $DIR/simplify-arm.rs:37:37: 37:50
|
||||
- StorageDead(_9); // scope 2 at $DIR/simplify-arm.rs:37:49: 37:50
|
||||
- ((_0 as Err).0: i32) = move _8; // scope 6 at $DIR/simplify-arm.rs:37:26: 37:51
|
||||
- discriminant(_0) = 1; // scope 6 at $DIR/simplify-arm.rs:37:26: 37:51
|
||||
- StorageDead(_8); // scope 2 at $DIR/simplify-arm.rs:37:50: 37:51
|
||||
- StorageDead(_6); // scope 0 at $DIR/simplify-arm.rs:37:50: 37:51
|
||||
+ _0 = move _3; // scope 6 at $DIR/simplify-arm.rs:37:26: 37:51
|
||||
StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:39:6: 39:7
|
||||
StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:41:1: 41:2
|
||||
goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2
|
||||
}
|
||||
|
||||
bb4: {
|
||||
return; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
|
||||
return; // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,75 +2,70 @@
|
||||
+ // MIR for `id_try` after SimplifyBranchSame
|
||||
|
||||
fn id_try(_1: Result<u8, i32>) -> Result<u8, i32> {
|
||||
debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:23:11: 23:12
|
||||
let mut _0: std::result::Result<u8, i32>; // return place in scope 0 at $DIR/simplify-arm.rs:23:34: 23:49
|
||||
let _2: u8; // in scope 0 at $DIR/simplify-arm.rs:24:9: 24:10
|
||||
let mut _3: std::result::Result<u8, i32>; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
let mut _4: std::result::Result<u8, i32>; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:14
|
||||
let mut _5: isize; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
let _6: i32; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
let mut _7: !; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
let mut _8: i32; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
let mut _9: i32; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
let _10: u8; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
let mut _11: u8; // in scope 0 at $DIR/simplify-arm.rs:25:8: 25:9
|
||||
debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:35:11: 35:12
|
||||
let mut _0: std::result::Result<u8, i32>; // return place in scope 0 at $DIR/simplify-arm.rs:35:34: 35:49
|
||||
let _2: u8; // in scope 0 at $DIR/simplify-arm.rs:36:9: 36:10
|
||||
let mut _3: std::result::Result<u8, i32>; // in scope 0 at $DIR/simplify-arm.rs:36:19: 36:33
|
||||
let mut _4: std::result::Result<u8, i32>; // in scope 0 at $DIR/simplify-arm.rs:36:31: 36:32
|
||||
let mut _5: isize; // in scope 0 at $DIR/simplify-arm.rs:37:9: 37:15
|
||||
let _6: i32; // in scope 0 at $DIR/simplify-arm.rs:37:13: 37:14
|
||||
let mut _7: !; // in scope 0 at $DIR/simplify-arm.rs:37:19: 37:51
|
||||
let mut _8: i32; // in scope 0 at $DIR/simplify-arm.rs:37:37: 37:50
|
||||
let mut _9: i32; // in scope 0 at $DIR/simplify-arm.rs:37:48: 37:49
|
||||
let _10: u8; // in scope 0 at $DIR/simplify-arm.rs:38:12: 38:13
|
||||
let mut _11: u8; // in scope 0 at $DIR/simplify-arm.rs:40:8: 40:9
|
||||
scope 1 {
|
||||
debug x => ((_0 as Ok).0: u8); // in scope 1 at $DIR/simplify-arm.rs:24:9: 24:10
|
||||
debug x => ((_0 as Ok).0: u8); // in scope 1 at $DIR/simplify-arm.rs:36:9: 36:10
|
||||
}
|
||||
scope 2 {
|
||||
debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
scope 3 {
|
||||
scope 7 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
debug t => ((_0 as Err).0: i32); // in scope 7 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
}
|
||||
scope 8 (inlined <Result<u8, i32> as Try>::from_error) { // at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
debug v => ((_0 as Err).0: i32); // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
let mut _12: i32; // in scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
}
|
||||
debug e => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify-arm.rs:37:13: 37:14
|
||||
scope 5 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify-arm.rs:37:37: 37:50
|
||||
debug t => ((_0 as Err).0: i32); // in scope 5 at $DIR/simplify-arm.rs:37:37: 37:50
|
||||
}
|
||||
scope 6 (inlined from_error::<u8, i32>) { // at $DIR/simplify-arm.rs:37:26: 37:51
|
||||
debug e => ((_0 as Err).0: i32); // in scope 6 at $DIR/simplify-arm.rs:37:26: 37:51
|
||||
}
|
||||
}
|
||||
scope 4 {
|
||||
debug val => ((_0 as Ok).0: u8); // in scope 4 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
scope 5 {
|
||||
}
|
||||
scope 3 {
|
||||
debug v => ((_0 as Ok).0: u8); // in scope 3 at $DIR/simplify-arm.rs:38:12: 38:13
|
||||
}
|
||||
scope 6 (inlined <Result<u8, i32> as Try>::into_result) { // at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
debug self => _4; // in scope 6 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
scope 4 (inlined into_result::<u8, i32>) { // at $DIR/simplify-arm.rs:36:19: 36:33
|
||||
debug r => _4; // in scope 4 at $DIR/simplify-arm.rs:36:19: 36:33
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/simplify-arm.rs:24:9: 24:10
|
||||
StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
StorageLive(_4); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:14
|
||||
_4 = _1; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:14
|
||||
_3 = move _4; // scope 6 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
StorageDead(_4); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
_5 = discriminant(_3); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
- switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
+ goto -> bb1; // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15
|
||||
StorageLive(_2); // scope 0 at $DIR/simplify-arm.rs:36:9: 36:10
|
||||
StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:36:19: 36:33
|
||||
StorageLive(_4); // scope 0 at $DIR/simplify-arm.rs:36:31: 36:32
|
||||
_4 = _1; // scope 0 at $DIR/simplify-arm.rs:36:31: 36:32
|
||||
_3 = move _4; // scope 4 at $DIR/simplify-arm.rs:36:19: 36:33
|
||||
StorageDead(_4); // scope 0 at $DIR/simplify-arm.rs:36:32: 36:33
|
||||
_5 = discriminant(_3); // scope 0 at $DIR/simplify-arm.rs:37:9: 37:15
|
||||
- switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:37:9: 37:15
|
||||
+ goto -> bb1; // scope 0 at $DIR/simplify-arm.rs:37:9: 37:15
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_0 = move _3; // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10
|
||||
StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16
|
||||
StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2
|
||||
- goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
|
||||
+ goto -> bb2; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
|
||||
_0 = move _3; // scope 1 at $DIR/simplify-arm.rs:40:5: 40:10
|
||||
StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:39:6: 39:7
|
||||
StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:41:1: 41:2
|
||||
- goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2
|
||||
+ goto -> bb2; // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2
|
||||
}
|
||||
|
||||
bb2: {
|
||||
- unreachable; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
- unreachable; // scope 0 at $DIR/simplify-arm.rs:36:19: 36:33
|
||||
- }
|
||||
-
|
||||
- bb3: {
|
||||
- _0 = move _3; // scope 8 at $DIR/simplify-arm.rs:24:13: 24:15
|
||||
- StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16
|
||||
- StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2
|
||||
- goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
|
||||
- _0 = move _3; // scope 6 at $DIR/simplify-arm.rs:37:26: 37:51
|
||||
- StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:39:6: 39:7
|
||||
- StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:41:1: 41:2
|
||||
- goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2
|
||||
- }
|
||||
-
|
||||
- bb4: {
|
||||
return; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2
|
||||
return; // scope 0 at $DIR/simplify-arm.rs:41:2: 41:2
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,24 @@
|
||||
// EMIT_MIR simplify_try.try_identity.SimplifyLocals.after.mir
|
||||
// EMIT_MIR simplify_try.try_identity.DestinationPropagation.diff
|
||||
|
||||
|
||||
fn into_result<T, E>(r: Result<T, E>) -> Result<T, E> {
|
||||
r
|
||||
}
|
||||
|
||||
fn from_error<T, E>(e: E) -> Result<T, E> {
|
||||
Err(e)
|
||||
}
|
||||
|
||||
// This was written to the `?` from `try_trait`, but `try_trait_v2` uses a different structure,
|
||||
// so the relevant desugar is copied inline in order to keep the test testing the same thing.
|
||||
// FIXME(#85133): while this might be useful for `r#try!`, it would be nice to have a MIR
|
||||
// optimization that picks up the `?` desugaring, as `SimplifyArmIdentity` does not.
|
||||
fn try_identity(x: Result<u32, i32>) -> Result<u32, i32> {
|
||||
let y = x?;
|
||||
let y = match into_result(x) {
|
||||
Err(e) => return from_error(From::from(e)),
|
||||
Ok(v) => v,
|
||||
};
|
||||
Ok(y)
|
||||
}
|
||||
|
||||
|
@ -2,67 +2,62 @@
|
||||
+ // MIR for `try_identity` after DestinationPropagation
|
||||
|
||||
fn try_identity(_1: Result<u32, i32>) -> Result<u32, i32> {
|
||||
debug x => _1; // in scope 0 at $DIR/simplify_try.rs:7:17: 7:18
|
||||
let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:7:41: 7:57
|
||||
let _2: u32; // in scope 0 at $DIR/simplify_try.rs:8:9: 8:10
|
||||
let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:14
|
||||
let mut _5: isize; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
let _6: i32; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
let mut _7: !; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
let mut _8: i32; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
let mut _9: i32; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
let _10: u32; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
let mut _11: u32; // in scope 0 at $DIR/simplify_try.rs:9:8: 9:9
|
||||
debug x => _1; // in scope 0 at $DIR/simplify_try.rs:20:17: 20:18
|
||||
let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:20:41: 20:57
|
||||
let _2: u32; // in scope 0 at $DIR/simplify_try.rs:21:9: 21:10
|
||||
let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:21:19: 21:33
|
||||
let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:21:31: 21:32
|
||||
let mut _5: isize; // in scope 0 at $DIR/simplify_try.rs:22:9: 22:15
|
||||
let _6: i32; // in scope 0 at $DIR/simplify_try.rs:22:13: 22:14
|
||||
let mut _7: !; // in scope 0 at $DIR/simplify_try.rs:22:19: 22:51
|
||||
let mut _8: i32; // in scope 0 at $DIR/simplify_try.rs:22:37: 22:50
|
||||
let mut _9: i32; // in scope 0 at $DIR/simplify_try.rs:22:48: 22:49
|
||||
let _10: u32; // in scope 0 at $DIR/simplify_try.rs:23:12: 23:13
|
||||
let mut _11: u32; // in scope 0 at $DIR/simplify_try.rs:25:8: 25:9
|
||||
scope 1 {
|
||||
debug y => ((_0 as Ok).0: u32); // in scope 1 at $DIR/simplify_try.rs:8:9: 8:10
|
||||
debug y => ((_0 as Ok).0: u32); // in scope 1 at $DIR/simplify_try.rs:21:9: 21:10
|
||||
}
|
||||
scope 2 {
|
||||
debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
scope 3 {
|
||||
scope 7 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify_try.rs:8:14: 8:15
|
||||
debug t => ((_0 as Err).0: i32); // in scope 7 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
}
|
||||
scope 8 (inlined <Result<u32, i32> as Try>::from_error) { // at $DIR/simplify_try.rs:8:13: 8:15
|
||||
debug v => ((_0 as Err).0: i32); // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
}
|
||||
debug e => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:22:13: 22:14
|
||||
scope 5 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify_try.rs:22:37: 22:50
|
||||
debug t => ((_0 as Err).0: i32); // in scope 5 at $DIR/simplify_try.rs:22:37: 22:50
|
||||
}
|
||||
scope 6 (inlined from_error::<u32, i32>) { // at $DIR/simplify_try.rs:22:26: 22:51
|
||||
debug e => ((_0 as Err).0: i32); // in scope 6 at $DIR/simplify_try.rs:22:26: 22:51
|
||||
}
|
||||
}
|
||||
scope 4 {
|
||||
debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
scope 5 {
|
||||
}
|
||||
scope 3 {
|
||||
debug v => ((_0 as Ok).0: u32); // in scope 3 at $DIR/simplify_try.rs:23:12: 23:13
|
||||
}
|
||||
scope 6 (inlined <Result<u32, i32> as Try>::into_result) { // at $DIR/simplify_try.rs:8:13: 8:15
|
||||
- debug self => _4; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
+ debug self => _0; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
scope 4 (inlined into_result::<u32, i32>) { // at $DIR/simplify_try.rs:21:19: 21:33
|
||||
- debug r => _4; // in scope 4 at $DIR/simplify_try.rs:21:19: 21:33
|
||||
+ debug r => _0; // in scope 4 at $DIR/simplify_try.rs:21:19: 21:33
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/simplify_try.rs:8:9: 8:10
|
||||
- StorageLive(_3); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
- StorageLive(_4); // scope 0 at $DIR/simplify_try.rs:8:13: 8:14
|
||||
- _4 = _1; // scope 0 at $DIR/simplify_try.rs:8:13: 8:14
|
||||
- _3 = move _4; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
- StorageDead(_4); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
- _5 = discriminant(_3); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
+ nop; // scope 0 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
+ nop; // scope 0 at $DIR/simplify_try.rs:8:13: 8:14
|
||||
+ _0 = _1; // scope 0 at $DIR/simplify_try.rs:8:13: 8:14
|
||||
+ nop; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
+ nop; // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
+ _5 = discriminant(_0); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
goto -> bb1; // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
StorageLive(_2); // scope 0 at $DIR/simplify_try.rs:21:9: 21:10
|
||||
- StorageLive(_3); // scope 0 at $DIR/simplify_try.rs:21:19: 21:33
|
||||
- StorageLive(_4); // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
|
||||
- _4 = _1; // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
|
||||
- _3 = move _4; // scope 4 at $DIR/simplify_try.rs:21:19: 21:33
|
||||
- StorageDead(_4); // scope 0 at $DIR/simplify_try.rs:21:32: 21:33
|
||||
- _5 = discriminant(_3); // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
|
||||
+ nop; // scope 0 at $DIR/simplify_try.rs:21:19: 21:33
|
||||
+ nop; // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
|
||||
+ _0 = _1; // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
|
||||
+ nop; // scope 4 at $DIR/simplify_try.rs:21:19: 21:33
|
||||
+ nop; // scope 0 at $DIR/simplify_try.rs:21:32: 21:33
|
||||
+ _5 = discriminant(_0); // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
|
||||
goto -> bb1; // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
|
||||
}
|
||||
|
||||
bb1: {
|
||||
- _0 = move _3; // scope 1 at $DIR/simplify_try.rs:9:5: 9:10
|
||||
- StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:8:15: 8:16
|
||||
+ nop; // scope 1 at $DIR/simplify_try.rs:9:5: 9:10
|
||||
+ nop; // scope 0 at $DIR/simplify_try.rs:8:15: 8:16
|
||||
StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:10:1: 10:2
|
||||
return; // scope 0 at $DIR/simplify_try.rs:10:2: 10:2
|
||||
- _0 = move _3; // scope 1 at $DIR/simplify_try.rs:25:5: 25:10
|
||||
- StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:24:6: 24:7
|
||||
+ nop; // scope 1 at $DIR/simplify_try.rs:25:5: 25:10
|
||||
+ nop; // scope 0 at $DIR/simplify_try.rs:24:6: 24:7
|
||||
StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:26:1: 26:2
|
||||
return; // scope 0 at $DIR/simplify_try.rs:26:2: 26:2
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,93 +2,85 @@
|
||||
+ // MIR for `try_identity` after SimplifyArmIdentity
|
||||
|
||||
fn try_identity(_1: Result<u32, i32>) -> Result<u32, i32> {
|
||||
debug x => _1; // in scope 0 at $DIR/simplify_try.rs:7:17: 7:18
|
||||
let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:7:41: 7:57
|
||||
let _2: u32; // in scope 0 at $DIR/simplify_try.rs:8:9: 8:10
|
||||
let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:14
|
||||
let mut _5: isize; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
let _6: i32; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
let mut _7: !; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
let mut _8: i32; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
let mut _9: i32; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
let _10: u32; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
let mut _11: u32; // in scope 0 at $DIR/simplify_try.rs:9:8: 9:9
|
||||
debug x => _1; // in scope 0 at $DIR/simplify_try.rs:20:17: 20:18
|
||||
let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:20:41: 20:57
|
||||
let _2: u32; // in scope 0 at $DIR/simplify_try.rs:21:9: 21:10
|
||||
let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:21:19: 21:33
|
||||
let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:21:31: 21:32
|
||||
let mut _5: isize; // in scope 0 at $DIR/simplify_try.rs:22:9: 22:15
|
||||
let _6: i32; // in scope 0 at $DIR/simplify_try.rs:22:13: 22:14
|
||||
let mut _7: !; // in scope 0 at $DIR/simplify_try.rs:22:19: 22:51
|
||||
let mut _8: i32; // in scope 0 at $DIR/simplify_try.rs:22:37: 22:50
|
||||
let mut _9: i32; // in scope 0 at $DIR/simplify_try.rs:22:48: 22:49
|
||||
let _10: u32; // in scope 0 at $DIR/simplify_try.rs:23:12: 23:13
|
||||
let mut _11: u32; // in scope 0 at $DIR/simplify_try.rs:25:8: 25:9
|
||||
scope 1 {
|
||||
- debug y => _2; // in scope 1 at $DIR/simplify_try.rs:8:9: 8:10
|
||||
+ debug y => ((_0 as Ok).0: u32); // in scope 1 at $DIR/simplify_try.rs:8:9: 8:10
|
||||
- debug y => _2; // in scope 1 at $DIR/simplify_try.rs:21:9: 21:10
|
||||
+ debug y => ((_0 as Ok).0: u32); // in scope 1 at $DIR/simplify_try.rs:21:9: 21:10
|
||||
}
|
||||
scope 2 {
|
||||
- debug err => _6; // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
+ debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
scope 3 {
|
||||
scope 7 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify_try.rs:8:14: 8:15
|
||||
- debug t => _9; // in scope 7 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
+ debug t => ((_0 as Err).0: i32); // in scope 7 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
}
|
||||
scope 8 (inlined <Result<u32, i32> as Try>::from_error) { // at $DIR/simplify_try.rs:8:13: 8:15
|
||||
- debug v => _8; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
+ debug v => ((_0 as Err).0: i32); // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
}
|
||||
- debug e => _6; // in scope 2 at $DIR/simplify_try.rs:22:13: 22:14
|
||||
+ debug e => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:22:13: 22:14
|
||||
scope 5 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify_try.rs:22:37: 22:50
|
||||
- debug t => _9; // in scope 5 at $DIR/simplify_try.rs:22:37: 22:50
|
||||
+ debug t => ((_0 as Err).0: i32); // in scope 5 at $DIR/simplify_try.rs:22:37: 22:50
|
||||
}
|
||||
scope 6 (inlined from_error::<u32, i32>) { // at $DIR/simplify_try.rs:22:26: 22:51
|
||||
- debug e => _8; // in scope 6 at $DIR/simplify_try.rs:22:26: 22:51
|
||||
+ debug e => ((_0 as Err).0: i32); // in scope 6 at $DIR/simplify_try.rs:22:26: 22:51
|
||||
}
|
||||
}
|
||||
scope 4 {
|
||||
- debug val => _10; // in scope 4 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
+ debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
scope 5 {
|
||||
}
|
||||
scope 3 {
|
||||
- debug v => _10; // in scope 3 at $DIR/simplify_try.rs:23:12: 23:13
|
||||
+ debug v => ((_0 as Ok).0: u32); // in scope 3 at $DIR/simplify_try.rs:23:12: 23:13
|
||||
}
|
||||
scope 6 (inlined <Result<u32, i32> as Try>::into_result) { // at $DIR/simplify_try.rs:8:13: 8:15
|
||||
debug self => _4; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
scope 4 (inlined into_result::<u32, i32>) { // at $DIR/simplify_try.rs:21:19: 21:33
|
||||
debug r => _4; // in scope 4 at $DIR/simplify_try.rs:21:19: 21:33
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/simplify_try.rs:8:9: 8:10
|
||||
StorageLive(_3); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
StorageLive(_4); // scope 0 at $DIR/simplify_try.rs:8:13: 8:14
|
||||
_4 = _1; // scope 0 at $DIR/simplify_try.rs:8:13: 8:14
|
||||
_3 = move _4; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
StorageDead(_4); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
_5 = discriminant(_3); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
StorageLive(_2); // scope 0 at $DIR/simplify_try.rs:21:9: 21:10
|
||||
StorageLive(_3); // scope 0 at $DIR/simplify_try.rs:21:19: 21:33
|
||||
StorageLive(_4); // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
|
||||
_4 = _1; // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
|
||||
_3 = move _4; // scope 4 at $DIR/simplify_try.rs:21:19: 21:33
|
||||
StorageDead(_4); // scope 0 at $DIR/simplify_try.rs:21:32: 21:33
|
||||
_5 = discriminant(_3); // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
|
||||
switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
|
||||
}
|
||||
|
||||
bb1: {
|
||||
- StorageLive(_10); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
- _10 = ((_3 as Ok).0: u32); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
- _2 = _10; // scope 5 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
- StorageDead(_10); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
+ _0 = move _3; // scope 1 at $DIR/simplify_try.rs:9:5: 9:10
|
||||
StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:8:15: 8:16
|
||||
- StorageLive(_11); // scope 1 at $DIR/simplify_try.rs:9:8: 9:9
|
||||
- _11 = _2; // scope 1 at $DIR/simplify_try.rs:9:8: 9:9
|
||||
- ((_0 as Ok).0: u32) = move _11; // scope 1 at $DIR/simplify_try.rs:9:5: 9:10
|
||||
- discriminant(_0) = 0; // scope 1 at $DIR/simplify_try.rs:9:5: 9:10
|
||||
- StorageDead(_11); // scope 1 at $DIR/simplify_try.rs:9:9: 9:10
|
||||
StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:10:1: 10:2
|
||||
return; // scope 0 at $DIR/simplify_try.rs:10:2: 10:2
|
||||
- StorageLive(_10); // scope 0 at $DIR/simplify_try.rs:23:12: 23:13
|
||||
- _10 = ((_3 as Ok).0: u32); // scope 0 at $DIR/simplify_try.rs:23:12: 23:13
|
||||
- _2 = _10; // scope 3 at $DIR/simplify_try.rs:23:18: 23:19
|
||||
- StorageDead(_10); // scope 0 at $DIR/simplify_try.rs:23:18: 23:19
|
||||
+ _0 = move _3; // scope 1 at $DIR/simplify_try.rs:25:5: 25:10
|
||||
StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:24:6: 24:7
|
||||
- StorageLive(_11); // scope 1 at $DIR/simplify_try.rs:25:8: 25:9
|
||||
- _11 = _2; // scope 1 at $DIR/simplify_try.rs:25:8: 25:9
|
||||
- ((_0 as Ok).0: u32) = move _11; // scope 1 at $DIR/simplify_try.rs:25:5: 25:10
|
||||
- discriminant(_0) = 0; // scope 1 at $DIR/simplify_try.rs:25:5: 25:10
|
||||
- StorageDead(_11); // scope 1 at $DIR/simplify_try.rs:25:9: 25:10
|
||||
StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:26:1: 26:2
|
||||
return; // scope 0 at $DIR/simplify_try.rs:26:2: 26:2
|
||||
}
|
||||
|
||||
bb2: {
|
||||
- StorageLive(_6); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
- _6 = ((_3 as Err).0: i32); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
- StorageLive(_8); // scope 3 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
- StorageLive(_9); // scope 3 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
- _9 = _6; // scope 3 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
- _8 = move _9; // scope 7 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
- StorageDead(_9); // scope 3 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
- StorageLive(_12); // scope 8 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
- _12 = move _8; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
- ((_0 as Err).0: i32) = move _12; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
- discriminant(_0) = 1; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
- StorageDead(_12); // scope 8 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
- StorageDead(_8); // scope 3 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
- StorageDead(_6); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
+ _0 = move _3; // scope 8 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:8:15: 8:16
|
||||
StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:10:1: 10:2
|
||||
return; // scope 0 at $DIR/simplify_try.rs:10:2: 10:2
|
||||
- StorageLive(_6); // scope 0 at $DIR/simplify_try.rs:22:13: 22:14
|
||||
- _6 = ((_3 as Err).0: i32); // scope 0 at $DIR/simplify_try.rs:22:13: 22:14
|
||||
- StorageLive(_8); // scope 2 at $DIR/simplify_try.rs:22:37: 22:50
|
||||
- StorageLive(_9); // scope 2 at $DIR/simplify_try.rs:22:48: 22:49
|
||||
- _9 = _6; // scope 2 at $DIR/simplify_try.rs:22:48: 22:49
|
||||
- _8 = move _9; // scope 5 at $DIR/simplify_try.rs:22:37: 22:50
|
||||
- StorageDead(_9); // scope 2 at $DIR/simplify_try.rs:22:49: 22:50
|
||||
- ((_0 as Err).0: i32) = move _8; // scope 6 at $DIR/simplify_try.rs:22:26: 22:51
|
||||
- discriminant(_0) = 1; // scope 6 at $DIR/simplify_try.rs:22:26: 22:51
|
||||
- StorageDead(_8); // scope 2 at $DIR/simplify_try.rs:22:50: 22:51
|
||||
- StorageDead(_6); // scope 0 at $DIR/simplify_try.rs:22:50: 22:51
|
||||
+ _0 = move _3; // scope 6 at $DIR/simplify_try.rs:22:26: 22:51
|
||||
StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:24:6: 24:7
|
||||
StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:26:1: 26:2
|
||||
return; // scope 0 at $DIR/simplify_try.rs:26:2: 26:2
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,57 +1,52 @@
|
||||
// MIR for `try_identity` after SimplifyBranchSame
|
||||
|
||||
fn try_identity(_1: Result<u32, i32>) -> Result<u32, i32> {
|
||||
debug x => _1; // in scope 0 at $DIR/simplify_try.rs:7:17: 7:18
|
||||
let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:7:41: 7:57
|
||||
let _2: u32; // in scope 0 at $DIR/simplify_try.rs:8:9: 8:10
|
||||
let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:14
|
||||
let mut _5: isize; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
let _6: i32; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
let mut _7: !; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
let mut _8: i32; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
let mut _9: i32; // in scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
let _10: u32; // in scope 0 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
let mut _11: u32; // in scope 0 at $DIR/simplify_try.rs:9:8: 9:9
|
||||
debug x => _1; // in scope 0 at $DIR/simplify_try.rs:20:17: 20:18
|
||||
let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:20:41: 20:57
|
||||
let _2: u32; // in scope 0 at $DIR/simplify_try.rs:21:9: 21:10
|
||||
let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:21:19: 21:33
|
||||
let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:21:31: 21:32
|
||||
let mut _5: isize; // in scope 0 at $DIR/simplify_try.rs:22:9: 22:15
|
||||
let _6: i32; // in scope 0 at $DIR/simplify_try.rs:22:13: 22:14
|
||||
let mut _7: !; // in scope 0 at $DIR/simplify_try.rs:22:19: 22:51
|
||||
let mut _8: i32; // in scope 0 at $DIR/simplify_try.rs:22:37: 22:50
|
||||
let mut _9: i32; // in scope 0 at $DIR/simplify_try.rs:22:48: 22:49
|
||||
let _10: u32; // in scope 0 at $DIR/simplify_try.rs:23:12: 23:13
|
||||
let mut _11: u32; // in scope 0 at $DIR/simplify_try.rs:25:8: 25:9
|
||||
scope 1 {
|
||||
debug y => ((_0 as Ok).0: u32); // in scope 1 at $DIR/simplify_try.rs:8:9: 8:10
|
||||
debug y => ((_0 as Ok).0: u32); // in scope 1 at $DIR/simplify_try.rs:21:9: 21:10
|
||||
}
|
||||
scope 2 {
|
||||
debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
scope 3 {
|
||||
scope 7 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify_try.rs:8:14: 8:15
|
||||
debug t => ((_0 as Err).0: i32); // in scope 7 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
}
|
||||
scope 8 (inlined <Result<u32, i32> as Try>::from_error) { // at $DIR/simplify_try.rs:8:13: 8:15
|
||||
debug v => ((_0 as Err).0: i32); // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
}
|
||||
debug e => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:22:13: 22:14
|
||||
scope 5 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify_try.rs:22:37: 22:50
|
||||
debug t => ((_0 as Err).0: i32); // in scope 5 at $DIR/simplify_try.rs:22:37: 22:50
|
||||
}
|
||||
scope 6 (inlined from_error::<u32, i32>) { // at $DIR/simplify_try.rs:22:26: 22:51
|
||||
debug e => ((_0 as Err).0: i32); // in scope 6 at $DIR/simplify_try.rs:22:26: 22:51
|
||||
}
|
||||
}
|
||||
scope 4 {
|
||||
debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
scope 5 {
|
||||
}
|
||||
scope 3 {
|
||||
debug v => ((_0 as Ok).0: u32); // in scope 3 at $DIR/simplify_try.rs:23:12: 23:13
|
||||
}
|
||||
scope 6 (inlined <Result<u32, i32> as Try>::into_result) { // at $DIR/simplify_try.rs:8:13: 8:15
|
||||
debug self => _4; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
scope 4 (inlined into_result::<u32, i32>) { // at $DIR/simplify_try.rs:21:19: 21:33
|
||||
debug r => _4; // in scope 4 at $DIR/simplify_try.rs:21:19: 21:33
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2); // scope 0 at $DIR/simplify_try.rs:8:9: 8:10
|
||||
StorageLive(_3); // scope 0 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
StorageLive(_4); // scope 0 at $DIR/simplify_try.rs:8:13: 8:14
|
||||
_4 = _1; // scope 0 at $DIR/simplify_try.rs:8:13: 8:14
|
||||
_3 = move _4; // scope 6 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
StorageDead(_4); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
_5 = discriminant(_3); // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
goto -> bb1; // scope 0 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
StorageLive(_2); // scope 0 at $DIR/simplify_try.rs:21:9: 21:10
|
||||
StorageLive(_3); // scope 0 at $DIR/simplify_try.rs:21:19: 21:33
|
||||
StorageLive(_4); // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
|
||||
_4 = _1; // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
|
||||
_3 = move _4; // scope 4 at $DIR/simplify_try.rs:21:19: 21:33
|
||||
StorageDead(_4); // scope 0 at $DIR/simplify_try.rs:21:32: 21:33
|
||||
_5 = discriminant(_3); // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
|
||||
goto -> bb1; // scope 0 at $DIR/simplify_try.rs:22:9: 22:15
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_0 = move _3; // scope 1 at $DIR/simplify_try.rs:9:5: 9:10
|
||||
StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:8:15: 8:16
|
||||
StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:10:1: 10:2
|
||||
return; // scope 0 at $DIR/simplify_try.rs:10:2: 10:2
|
||||
_0 = move _3; // scope 1 at $DIR/simplify_try.rs:25:5: 25:10
|
||||
StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:24:6: 24:7
|
||||
StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:26:1: 26:2
|
||||
return; // scope 0 at $DIR/simplify_try.rs:26:2: 26:2
|
||||
}
|
||||
}
|
||||
|
@ -1,33 +1,29 @@
|
||||
// MIR for `try_identity` after SimplifyLocals
|
||||
|
||||
fn try_identity(_1: Result<u32, i32>) -> Result<u32, i32> {
|
||||
debug x => _1; // in scope 0 at $DIR/simplify_try.rs:7:17: 7:18
|
||||
let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:7:41: 7:57
|
||||
debug x => _1; // in scope 0 at $DIR/simplify_try.rs:20:17: 20:18
|
||||
let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:20:41: 20:57
|
||||
scope 1 {
|
||||
debug y => ((_0 as Ok).0: u32); // in scope 1 at $DIR/simplify_try.rs:8:9: 8:10
|
||||
debug y => ((_0 as Ok).0: u32); // in scope 1 at $DIR/simplify_try.rs:21:9: 21:10
|
||||
}
|
||||
scope 2 {
|
||||
debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
scope 3 {
|
||||
scope 7 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify_try.rs:8:14: 8:15
|
||||
debug t => ((_0 as Err).0: i32); // in scope 7 at $DIR/simplify_try.rs:8:14: 8:15
|
||||
}
|
||||
scope 8 (inlined <Result<u32, i32> as Try>::from_error) { // at $DIR/simplify_try.rs:8:13: 8:15
|
||||
debug v => ((_0 as Err).0: i32); // in scope 8 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
}
|
||||
debug e => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:22:13: 22:14
|
||||
scope 5 (inlined <i32 as From<i32>>::from) { // at $DIR/simplify_try.rs:22:37: 22:50
|
||||
debug t => ((_0 as Err).0: i32); // in scope 5 at $DIR/simplify_try.rs:22:37: 22:50
|
||||
}
|
||||
scope 6 (inlined from_error::<u32, i32>) { // at $DIR/simplify_try.rs:22:26: 22:51
|
||||
debug e => ((_0 as Err).0: i32); // in scope 6 at $DIR/simplify_try.rs:22:26: 22:51
|
||||
}
|
||||
}
|
||||
scope 4 {
|
||||
debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
scope 5 {
|
||||
}
|
||||
scope 3 {
|
||||
debug v => ((_0 as Ok).0: u32); // in scope 3 at $DIR/simplify_try.rs:23:12: 23:13
|
||||
}
|
||||
scope 6 (inlined <Result<u32, i32> as Try>::into_result) { // at $DIR/simplify_try.rs:8:13: 8:15
|
||||
debug self => _0; // in scope 6 at $DIR/simplify_try.rs:8:13: 8:15
|
||||
scope 4 (inlined into_result::<u32, i32>) { // at $DIR/simplify_try.rs:21:19: 21:33
|
||||
debug r => _0; // in scope 4 at $DIR/simplify_try.rs:21:19: 21:33
|
||||
}
|
||||
|
||||
bb0: {
|
||||
_0 = _1; // scope 0 at $DIR/simplify_try.rs:8:13: 8:14
|
||||
return; // scope 0 at $DIR/simplify_try.rs:10:2: 10:2
|
||||
_0 = _1; // scope 0 at $DIR/simplify_try.rs:21:31: 21:32
|
||||
return; // scope 0 at $DIR/simplify_try.rs:26:2: 26:2
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ async fn bar() -> Result<(), ()> {
|
||||
foo()?; //~ ERROR the `?` operator can only be applied to values that implement `Try`
|
||||
//~^ NOTE the `?` operator cannot be applied to type `impl Future`
|
||||
//~| HELP the trait `Try` is not implemented for `impl Future`
|
||||
//~| NOTE required by `into_result`
|
||||
//~| NOTE required by `branch`
|
||||
//~| HELP consider `await`ing on the `Future`
|
||||
//~| NOTE in this expansion of desugaring of operator `?`
|
||||
//~| NOTE in this expansion of desugaring of operator `?`
|
||||
@ -65,7 +65,7 @@ async fn baz() -> Result<(), ()> {
|
||||
t?; //~ ERROR the `?` operator can only be applied to values that implement `Try`
|
||||
//~^ NOTE the `?` operator cannot be applied to type `T`
|
||||
//~| HELP the trait `Try` is not implemented for `T`
|
||||
//~| NOTE required by `into_result`
|
||||
//~| NOTE required by `branch`
|
||||
//~| HELP consider `await`ing on the `Future`
|
||||
//~| NOTE in this expansion of desugaring of operator `?`
|
||||
//~| NOTE in this expansion of desugaring of operator `?`
|
||||
|
@ -5,7 +5,7 @@ LL | foo()?;
|
||||
| ^^^^^^ the `?` operator cannot be applied to type `impl Future`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `impl Future`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
help: consider `await`ing on the `Future`
|
||||
|
|
||||
LL | foo().await?;
|
||||
@ -18,7 +18,7 @@ LL | t?;
|
||||
| ^^ the `?` operator cannot be applied to type `T`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `T`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
help: consider `await`ing on the `Future`
|
||||
|
|
||||
LL | t.await?;
|
||||
|
@ -1,47 +1,47 @@
|
||||
error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-on-option-in-async.rs:8:9
|
||||
error[E0277]: the `?` operator can only be used in an async block that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/try-on-option-in-async.rs:8:10
|
||||
|
|
||||
LL | async {
|
||||
| ___________-
|
||||
LL | | let x: Option<u32> = None;
|
||||
LL | | x?;
|
||||
| | ^^ cannot use the `?` operator in an async block that returns `{integer}`
|
||||
| | ^ cannot use the `?` operator in an async block that returns `{integer}`
|
||||
LL | | 22
|
||||
LL | | }
|
||||
| |_____- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `{integer}`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `{integer}`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-on-option-in-async.rs:17:9
|
||||
error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/try-on-option-in-async.rs:17:10
|
||||
|
|
||||
LL | let async_closure = async || {
|
||||
| __________________________________-
|
||||
LL | | let x: Option<u32> = None;
|
||||
LL | | x?;
|
||||
| | ^^ cannot use the `?` operator in an async closure that returns `u32`
|
||||
| | ^ cannot use the `?` operator in an async closure that returns `u32`
|
||||
LL | | 22_u32
|
||||
LL | | };
|
||||
| |_____- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `u32`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-on-option-in-async.rs:26:5
|
||||
error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/try-on-option-in-async.rs:26:6
|
||||
|
|
||||
LL | async fn an_async_function() -> u32 {
|
||||
| _____________________________________-
|
||||
LL | | let x: Option<u32> = None;
|
||||
LL | | x?;
|
||||
| | ^^ cannot use the `?` operator in an async function that returns `u32`
|
||||
| | ^ cannot use the `?` operator in an async function that returns `u32`
|
||||
LL | | 22
|
||||
LL | | }
|
||||
| |_- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `u32`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -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
|
||||
};
|
||||
}
|
||||
|
@ -8,14 +8,13 @@ LL | #![feature(impl_trait_in_bindings)]
|
||||
= note: see issue #63065 <https://github.com/rust-lang/rust/issues/63065> for more information
|
||||
|
||||
error[E0282]: type annotations needed for `impl Future`
|
||||
--> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:13:20
|
||||
--> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:15:9
|
||||
|
|
||||
LL | let fut = async {
|
||||
| --- consider giving `fut` the explicit type `impl Future`, with the type parameters specified
|
||||
LL | make_unit()?;
|
||||
| ^ cannot infer type of error for `?` operator
|
||||
|
|
||||
= note: `?` implicitly converts the error value into a type implementing `From<std::io::Error>`
|
||||
| --- consider giving `fut` the explicit type `impl Future`, where the type parameter `E` is specified
|
||||
...
|
||||
LL | Ok(())
|
||||
| ^^ cannot infer type for type parameter `E` declared on the enum `Result`
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
|
@ -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
|
||||
};
|
||||
}
|
||||
|
@ -1,12 +1,11 @@
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/cannot-infer-async.rs:11:20
|
||||
--> $DIR/cannot-infer-async.rs:13:9
|
||||
|
|
||||
LL | let fut = async {
|
||||
| --- consider giving `fut` a type
|
||||
LL | make_unit()?;
|
||||
| ^ cannot infer type of error for `?` operator
|
||||
|
|
||||
= note: `?` implicitly converts the error value into a type implementing `From<std::io::Error>`
|
||||
...
|
||||
LL | Ok(())
|
||||
| ^^ cannot infer type for type parameter `E` declared on the enum `Result`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,9 @@
|
||||
error[E0282]: type annotations needed for the closure `fn((), ()) -> Result<(), _>`
|
||||
--> $DIR/cannot-infer-closure.rs:3:15
|
||||
--> $DIR/cannot-infer-closure.rs:4:9
|
||||
|
|
||||
LL | Err(a)?;
|
||||
| ^ cannot infer type of error for `?` operator
|
||||
LL | Ok(b)
|
||||
| ^^ cannot infer type for type parameter `E` declared on the enum `Result`
|
||||
|
|
||||
= note: `?` implicitly converts the error value into a type implementing `From<()>`
|
||||
help: give this closure an explicit return type without `_` placeholders
|
||||
|
|
||||
LL | let x = |a: (), b: ()| -> Result<(), _> {
|
||||
|
@ -2,9 +2,8 @@ error[E0282]: type annotations needed for the closure `fn() -> Result<(), Qualif
|
||||
--> $DIR/cannot-infer-partial-try-return.rs:19:9
|
||||
|
|
||||
LL | infallible()?;
|
||||
| ^^^^^^^^^^^^^ cannot infer type of error for `?` operator
|
||||
| ^^^^^^^^^^^^^ cannot infer type
|
||||
|
|
||||
= note: `?` implicitly converts the error value into `QualifiedError<_>` using its implementation of `From<Infallible>`
|
||||
help: give this closure an explicit return type without `_` placeholders
|
||||
|
|
||||
LL | let x = || -> Result<(), QualifiedError<_>> {
|
||||
|
@ -7,7 +7,8 @@ LL | Err(5)?;
|
||||
| ^ the trait `From<{integer}>` is not implemented for `()`
|
||||
|
|
||||
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
|
||||
= note: required by `from`
|
||||
= note: required because of the requirements on the impl of `FromResidual<Result<Infallible, {integer}>>` for `Result<i32, ()>`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,35 +0,0 @@
|
||||
error[E0277]: `?` couldn't convert the error to `()`
|
||||
--> $DIR/option-to-result.rs:5:6
|
||||
|
|
||||
LL | fn test_result() -> Result<(),()> {
|
||||
| ------------- expected `()` because of this
|
||||
LL | let a:Option<()> = Some(());
|
||||
LL | a?;
|
||||
| ^ the trait `From<NoneError>` is not implemented for `()`
|
||||
|
|
||||
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
|
||||
= note: required by `from`
|
||||
help: consider converting the `Option<T>` into a `Result<T, _>` using `Option::ok_or` or `Option::ok_or_else`
|
||||
|
|
||||
LL | a.ok_or_else(|| /* error value */)?;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: `?` couldn't convert the error to `NoneError`
|
||||
--> $DIR/option-to-result.rs:11:6
|
||||
|
|
||||
LL | fn test_option() -> Option<i32>{
|
||||
| ----------- expected `NoneError` because of this
|
||||
LL | let a:Result<i32, i32> = Ok(5);
|
||||
LL | a?;
|
||||
| ^ the trait `From<i32>` is not implemented for `NoneError`
|
||||
|
|
||||
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
|
||||
= note: required by `from`
|
||||
help: consider converting the `Result<T, _>` into an `Option<T>` using `Result::ok`
|
||||
|
|
||||
LL | a.ok()?;
|
||||
| ^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -1,11 +1,10 @@
|
||||
error[E0283]: type annotations needed
|
||||
error[E0284]: type annotations needed
|
||||
--> $DIR/question-mark-type-infer.rs:12:21
|
||||
|
|
||||
LL | l.iter().map(f).collect()?
|
||||
| ^^^^^^^ cannot infer type
|
||||
|
|
||||
= note: cannot satisfy `_: Try`
|
||||
= note: required by `into_result`
|
||||
= note: cannot satisfy `<_ as Try>::Residual == _`
|
||||
help: consider specifying the type argument in the method call
|
||||
|
|
||||
LL | l.iter().map(f).collect::<B>()?
|
||||
@ -13,4 +12,4 @@ LL | l.iter().map(f).collect::<B>()?
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0283`.
|
||||
For more information about this error, try `rustc --explain E0284`.
|
||||
|
@ -502,10 +502,10 @@ LL | if (let 0 = 0)? {}
|
||||
| ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `bool`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/disallowed-positions.rs:46:8
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/disallowed-positions.rs:46:19
|
||||
|
|
||||
LL | / fn nested_within_if_expr() {
|
||||
LL | | if &let 0 = 0 {}
|
||||
@ -513,14 +513,14 @@ LL | |
|
||||
LL | |
|
||||
... |
|
||||
LL | | if (let 0 = 0)? {}
|
||||
| | ^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
|
||||
| | ^ cannot use the `?` operator in a function that returns `()`
|
||||
... |
|
||||
LL | | if let true = let true = true {}
|
||||
LL | | }
|
||||
| |_- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `()`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<_>` is not implemented for `()`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/disallowed-positions.rs:56:8
|
||||
@ -660,7 +660,7 @@ LL | if let 0 = 0? {}
|
||||
| ^^ the `?` operator cannot be applied to type `{integer}`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `{integer}`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/disallowed-positions.rs:96:11
|
||||
@ -690,10 +690,10 @@ LL | while (let 0 = 0)? {}
|
||||
| ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `bool`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/disallowed-positions.rs:110:11
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/disallowed-positions.rs:110:22
|
||||
|
|
||||
LL | / fn nested_within_while_expr() {
|
||||
LL | | while &let 0 = 0 {}
|
||||
@ -701,14 +701,14 @@ LL | |
|
||||
LL | |
|
||||
... |
|
||||
LL | | while (let 0 = 0)? {}
|
||||
| | ^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
|
||||
| | ^ cannot use the `?` operator in a function that returns `()`
|
||||
... |
|
||||
LL | | while let true = let true = true {}
|
||||
LL | | }
|
||||
| |_- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `()`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<_>` is not implemented for `()`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/disallowed-positions.rs:120:11
|
||||
@ -848,7 +848,7 @@ LL | while let 0 = 0? {}
|
||||
| ^^ the `?` operator cannot be applied to type `{integer}`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `{integer}`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
|
||||
error[E0614]: type `bool` cannot be dereferenced
|
||||
--> $DIR/disallowed-positions.rs:173:5
|
||||
@ -869,10 +869,10 @@ LL | (let 0 = 0)?;
|
||||
| ^^^^^^^^^^^^ the `?` operator cannot be applied to type `bool`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `bool`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/disallowed-positions.rs:183:5
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/disallowed-positions.rs:183:16
|
||||
|
|
||||
LL | / fn outside_if_and_while_expr() {
|
||||
LL | | &let 0 = 0;
|
||||
@ -880,14 +880,14 @@ LL | |
|
||||
LL | | !let 0 = 0;
|
||||
... |
|
||||
LL | | (let 0 = 0)?;
|
||||
| | ^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
|
||||
| | ^ cannot use the `?` operator in a function that returns `()`
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `()`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<_>` is not implemented for `()`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/disallowed-positions.rs:198:10
|
||||
@ -916,7 +916,7 @@ LL | let 0 = 0?;
|
||||
| ^^ the `?` operator cannot be applied to type `{integer}`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `{integer}`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
|
||||
error: aborting due to 104 previous errors; 2 warnings emitted
|
||||
|
||||
|
@ -5,7 +5,7 @@ LL | SadGirl {}.call()?;
|
||||
| ^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl Future`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `impl Future`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
help: consider `await`ing on the `Future`
|
||||
|
|
||||
LL | SadGirl {}.call().await?;
|
||||
|
@ -15,8 +15,7 @@ pub fn main() {
|
||||
let res: Result<i32, i32> = try { }; //~ ERROR type mismatch
|
||||
|
||||
let res: () = try { };
|
||||
//~^ ERROR the trait bound `(): Try` is not satisfied
|
||||
//~| ERROR the trait bound `(): Try` is not satisfied
|
||||
//~^ ERROR a `try` block must return `Result` or `Option`
|
||||
|
||||
let res: i32 = try { 5 }; //~ ERROR the trait bound `i32: Try` is not satisfied
|
||||
let res: i32 = try { 5 }; //~ ERROR a `try` block must return `Result` or `Option`
|
||||
}
|
||||
|
@ -7,43 +7,40 @@ LL | Err("")?;
|
||||
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
|
||||
= help: the following implementations were found:
|
||||
<TryFromSliceError as From<Infallible>>
|
||||
= note: required by `from`
|
||||
= note: required because of the requirements on the impl of `FromResidual<Result<Infallible, &str>>` for `Result<u32, TryFromSliceError>`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Ok == &str`
|
||||
error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == &str`
|
||||
--> $DIR/try-block-bad-type.rs:12:9
|
||||
|
|
||||
LL | ""
|
||||
| ^^ expected `i32`, found `&str`
|
||||
|
||||
error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Ok == ()`
|
||||
error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == ()`
|
||||
--> $DIR/try-block-bad-type.rs:15:39
|
||||
|
|
||||
LL | let res: Result<i32, i32> = try { };
|
||||
| ^ expected `i32`, found `()`
|
||||
|
||||
error[E0277]: the trait bound `(): Try` is not satisfied
|
||||
error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-block-bad-type.rs:17:25
|
||||
|
|
||||
LL | let res: () = try { };
|
||||
| ^ the trait `Try` is not implemented for `()`
|
||||
| ^ could not wrap the final value of the block as `()` doesn't implement `Try`
|
||||
|
|
||||
= note: required by `from_ok`
|
||||
= help: the trait `Try` is not implemented for `()`
|
||||
= note: required by `from_output`
|
||||
|
||||
error[E0277]: the trait bound `(): Try` is not satisfied
|
||||
--> $DIR/try-block-bad-type.rs:17:25
|
||||
|
|
||||
LL | let res: () = try { };
|
||||
| ^ the trait `Try` is not implemented for `()`
|
||||
|
||||
error[E0277]: the trait bound `i32: Try` is not satisfied
|
||||
--> $DIR/try-block-bad-type.rs:21:26
|
||||
error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-block-bad-type.rs:20:26
|
||||
|
|
||||
LL | let res: i32 = try { 5 };
|
||||
| ^ the trait `Try` is not implemented for `i32`
|
||||
| ^ could not wrap the final value of the block as `i32` doesn't implement `Try`
|
||||
|
|
||||
= note: required by `from_ok`
|
||||
= help: the trait `Try` is not implemented for `i32`
|
||||
= note: required by `from_output`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0271, E0277.
|
||||
For more information about an error, try `rustc --explain E0271`.
|
||||
|
@ -4,5 +4,5 @@
|
||||
|
||||
fn main() {
|
||||
while try { false } {}
|
||||
//~^ ERROR the trait bound `bool: Try` is not satisfied
|
||||
//~^ ERROR a `try` block must
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
error[E0277]: the trait bound `bool: Try` is not satisfied
|
||||
error[E0277]: a `try` block must return `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-block-in-while.rs:6:17
|
||||
|
|
||||
LL | while try { false } {}
|
||||
| ^^^^^ the trait `Try` is not implemented for `bool`
|
||||
| ^^^^^ could not wrap the final value of the block as `bool` doesn't implement `Try`
|
||||
|
|
||||
= note: required by `from_ok`
|
||||
= help: the trait `Try` is not implemented for `bool`
|
||||
= note: required by `from_output`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
error[E0271]: type mismatch resolving `<Option<f32> as Try>::Ok == {integer}`
|
||||
error[E0271]: type mismatch resolving `<Option<f32> as Try>::Output == {integer}`
|
||||
--> $DIR/try-block-type-error.rs:10:9
|
||||
|
|
||||
LL | 42
|
||||
@ -7,7 +7,7 @@ LL | 42
|
||||
| expected `f32`, found integer
|
||||
| help: use a float literal: `42.0`
|
||||
|
||||
error[E0271]: type mismatch resolving `<Option<i32> as Try>::Ok == ()`
|
||||
error[E0271]: type mismatch resolving `<Option<i32> as Try>::Output == ()`
|
||||
--> $DIR/try-block-type-error.rs:16:5
|
||||
|
|
||||
LL | };
|
||||
|
@ -1,33 +0,0 @@
|
||||
error[E0277]: `?` couldn't convert the error to `()`
|
||||
--> $DIR/try-on-option.rs:7:6
|
||||
|
|
||||
LL | fn foo() -> Result<u32, ()> {
|
||||
| --------------- expected `()` because of this
|
||||
LL | let x: Option<u32> = None;
|
||||
LL | x?;
|
||||
| ^ the trait `From<NoneError>` is not implemented for `()`
|
||||
|
|
||||
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
|
||||
= note: required by `from`
|
||||
help: consider converting the `Option<T>` into a `Result<T, _>` using `Option::ok_or` or `Option::ok_or_else`
|
||||
|
|
||||
LL | x.ok_or_else(|| /* error value */)?;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-on-option.rs:13:5
|
||||
|
|
||||
LL | / fn bar() -> u32 {
|
||||
LL | | let x: Option<u32> = None;
|
||||
LL | | x?;
|
||||
| | ^^ cannot use the `?` operator in a function that returns `u32`
|
||||
LL | | 22
|
||||
LL | | }
|
||||
| |_- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `u32`
|
||||
= note: required by `from_error`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -1,63 +0,0 @@
|
||||
// run-pass
|
||||
|
||||
#![feature(try_trait)]
|
||||
|
||||
use std::ops::Try;
|
||||
|
||||
enum MyResult<T, U> {
|
||||
Awesome(T),
|
||||
Terrible(U)
|
||||
}
|
||||
|
||||
impl<U, V> Try for MyResult<U, V> {
|
||||
type Ok = U;
|
||||
type Error = V;
|
||||
|
||||
fn from_ok(u: U) -> MyResult<U, V> {
|
||||
MyResult::Awesome(u)
|
||||
}
|
||||
|
||||
fn from_error(e: V) -> MyResult<U, V> {
|
||||
MyResult::Terrible(e)
|
||||
}
|
||||
|
||||
fn into_result(self) -> Result<U, V> {
|
||||
match self {
|
||||
MyResult::Awesome(u) => Ok(u),
|
||||
MyResult::Terrible(e) => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn f(x: i32) -> Result<i32, String> {
|
||||
if x == 0 {
|
||||
Ok(42)
|
||||
} else {
|
||||
let y = g(x)?;
|
||||
Ok(y)
|
||||
}
|
||||
}
|
||||
|
||||
fn g(x: i32) -> MyResult<i32, String> {
|
||||
let _y = f(x - 1)?;
|
||||
MyResult::Terrible("Hello".to_owned())
|
||||
}
|
||||
|
||||
fn h() -> MyResult<i32, String> {
|
||||
let a: Result<i32, &'static str> = Err("Hello");
|
||||
let b = a?;
|
||||
MyResult::Awesome(b)
|
||||
}
|
||||
|
||||
fn i() -> MyResult<i32, String> {
|
||||
let a: MyResult<i32, &'static str> = MyResult::Terrible("Hello");
|
||||
let b = a?;
|
||||
MyResult::Awesome(b)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert!(f(0) == Ok(42));
|
||||
assert!(f(10) == Err("Hello".to_owned()));
|
||||
let _ = h();
|
||||
let _ = i();
|
||||
}
|
48
src/test/ui/try-trait/bad-interconversion.rs
Normal file
48
src/test/ui/try-trait/bad-interconversion.rs
Normal file
@ -0,0 +1,48 @@
|
||||
#![feature(control_flow_enum)]
|
||||
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
fn result_to_result() -> Result<u64, u8> {
|
||||
Ok(Err(123_i32)?)
|
||||
//~^ ERROR `?` couldn't convert the error to `u8`
|
||||
}
|
||||
|
||||
fn option_to_result() -> Result<u64, String> {
|
||||
Some(3)?;
|
||||
//~^ ERROR the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
|
||||
Ok(10)
|
||||
}
|
||||
|
||||
fn control_flow_to_result() -> Result<u64, String> {
|
||||
Ok(ControlFlow::Break(123)?)
|
||||
//~^ ERROR the `?` operator can only be used on `Result`s in a function that returns `Result`
|
||||
}
|
||||
|
||||
fn result_to_option() -> Option<u16> {
|
||||
Some(Err("hello")?)
|
||||
//~^ ERROR the `?` operator can only be used on `Option`s in a function that returns `Option`
|
||||
}
|
||||
|
||||
fn control_flow_to_option() -> Option<u64> {
|
||||
Some(ControlFlow::Break(123)?)
|
||||
//~^ ERROR the `?` operator can only be used on `Option`s in a function that returns `Option`
|
||||
}
|
||||
|
||||
fn result_to_control_flow() -> ControlFlow<String> {
|
||||
ControlFlow::Continue(Err("hello")?)
|
||||
//~^ ERROR the `?` operator can only be used on `ControlFlow<B, _>`s in a function that returns `ControlFlow<B, _>`
|
||||
}
|
||||
|
||||
fn option_to_control_flow() -> ControlFlow<u64> {
|
||||
Some(3)?;
|
||||
//~^ ERROR the `?` operator can only be used on `ControlFlow<B, _>`s in a function that returns `ControlFlow<B, _>`
|
||||
ControlFlow::Break(10)
|
||||
}
|
||||
|
||||
fn control_flow_to_control_flow() -> ControlFlow<i64> {
|
||||
ControlFlow::Break(4_u8)?;
|
||||
//~^ ERROR the `?` operator can only be used on `ControlFlow<B, _>`s in a function that returns `ControlFlow<B, _>`
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
|
||||
fn main() {}
|
115
src/test/ui/try-trait/bad-interconversion.stderr
Normal file
115
src/test/ui/try-trait/bad-interconversion.stderr
Normal file
@ -0,0 +1,115 @@
|
||||
error[E0277]: `?` couldn't convert the error to `u8`
|
||||
--> $DIR/bad-interconversion.rs:6:20
|
||||
|
|
||||
LL | fn result_to_result() -> Result<u64, u8> {
|
||||
| --------------- expected `u8` because of this
|
||||
LL | Ok(Err(123_i32)?)
|
||||
| ^ the trait `From<i32>` is not implemented for `u8`
|
||||
|
|
||||
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
|
||||
= help: the following implementations were found:
|
||||
<u8 as From<NonZeroU8>>
|
||||
<u8 as From<bool>>
|
||||
= note: required because of the requirements on the impl of `FromResidual<Result<Infallible, i32>>` for `Result<u64, u8>`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
|
||||
--> $DIR/bad-interconversion.rs:11:12
|
||||
|
|
||||
LL | / fn option_to_result() -> Result<u64, String> {
|
||||
LL | | Some(3)?;
|
||||
| | ^ use `.ok_or(...)?` to provide an error compatible with `Result<u64, String>`
|
||||
LL | |
|
||||
LL | | Ok(10)
|
||||
LL | | }
|
||||
| |_- this function returns a `Result`
|
||||
|
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u64, String>`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used on `Result`s in a function that returns `Result`
|
||||
--> $DIR/bad-interconversion.rs:17:31
|
||||
|
|
||||
LL | / fn control_flow_to_result() -> Result<u64, String> {
|
||||
LL | | Ok(ControlFlow::Break(123)?)
|
||||
| | ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Result<u64, String>`
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_- this function returns a `Result`
|
||||
|
|
||||
= help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Result<u64, String>`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option`
|
||||
--> $DIR/bad-interconversion.rs:22:22
|
||||
|
|
||||
LL | / fn result_to_option() -> Option<u16> {
|
||||
LL | | Some(Err("hello")?)
|
||||
| | ^ this `?` produces `Result<Infallible, &str>`, which is incompatible with `Option<u16>`
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_- this function returns an `Option`
|
||||
|
|
||||
= help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `Option<u16>`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option`
|
||||
--> $DIR/bad-interconversion.rs:27:33
|
||||
|
|
||||
LL | / fn control_flow_to_option() -> Option<u64> {
|
||||
LL | | Some(ControlFlow::Break(123)?)
|
||||
| | ^ this `?` produces `ControlFlow<{integer}, Infallible>`, which is incompatible with `Option<u64>`
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_- this function returns an `Option`
|
||||
|
|
||||
= help: the trait `FromResidual<ControlFlow<{integer}, Infallible>>` is not implemented for `Option<u64>`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used on `ControlFlow<B, _>`s in a function that returns `ControlFlow<B, _>`
|
||||
--> $DIR/bad-interconversion.rs:32:39
|
||||
|
|
||||
LL | / fn result_to_control_flow() -> ControlFlow<String> {
|
||||
LL | | ControlFlow::Continue(Err("hello")?)
|
||||
| | ^ this `?` produces `Result<Infallible, &str>`, which is incompatible with `ControlFlow<String>`
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_- this function returns a `ControlFlow`
|
||||
|
|
||||
= help: the trait `FromResidual<Result<Infallible, &str>>` is not implemented for `ControlFlow<String>`
|
||||
= note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used on `ControlFlow<B, _>`s in a function that returns `ControlFlow<B, _>`
|
||||
--> $DIR/bad-interconversion.rs:37:12
|
||||
|
|
||||
LL | / fn option_to_control_flow() -> ControlFlow<u64> {
|
||||
LL | | Some(3)?;
|
||||
| | ^ this `?` produces `Option<Infallible>`, which is incompatible with `ControlFlow<u64>`
|
||||
LL | |
|
||||
LL | | ControlFlow::Break(10)
|
||||
LL | | }
|
||||
| |_- this function returns a `ControlFlow`
|
||||
|
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `ControlFlow<u64>`
|
||||
= note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used on `ControlFlow<B, _>`s in a function that returns `ControlFlow<B, _>`
|
||||
--> $DIR/bad-interconversion.rs:43:29
|
||||
|
|
||||
LL | / fn control_flow_to_control_flow() -> ControlFlow<i64> {
|
||||
LL | | ControlFlow::Break(4_u8)?;
|
||||
| | ^ this `?` produces `ControlFlow<u8, Infallible>`, which is incompatible with `ControlFlow<i64>`
|
||||
LL | |
|
||||
LL | | ControlFlow::Continue(())
|
||||
LL | | }
|
||||
| |_- this function returns a `ControlFlow`
|
||||
|
|
||||
= help: the trait `FromResidual<ControlFlow<u8, Infallible>>` is not implemented for `ControlFlow<i64>`
|
||||
= note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -2,12 +2,12 @@ fn main(){ }
|
||||
|
||||
fn test_result() -> Result<(),()> {
|
||||
let a:Option<()> = Some(());
|
||||
a?;//~ ERROR `?` couldn't convert the error
|
||||
a?;//~ ERROR the `?` operator can only be used
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_option() -> Option<i32>{
|
||||
let a:Result<i32, i32> = Ok(5);
|
||||
a?;//~ ERROR `?` couldn't convert the error
|
||||
a?;//~ ERROR the `?` operator can only be used
|
||||
Some(5)
|
||||
}
|
31
src/test/ui/try-trait/option-to-result.stderr
Normal file
31
src/test/ui/try-trait/option-to-result.stderr
Normal file
@ -0,0 +1,31 @@
|
||||
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
|
||||
--> $DIR/option-to-result.rs:5:6
|
||||
|
|
||||
LL | / fn test_result() -> Result<(),()> {
|
||||
LL | | let a:Option<()> = Some(());
|
||||
LL | | a?;
|
||||
| | ^ use `.ok_or(...)?` to provide an error compatible with `Result<(), ()>`
|
||||
LL | | Ok(())
|
||||
LL | | }
|
||||
| |_- this function returns a `Result`
|
||||
|
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<(), ()>`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option`
|
||||
--> $DIR/option-to-result.rs:11:6
|
||||
|
|
||||
LL | / fn test_option() -> Option<i32>{
|
||||
LL | | let a:Result<i32, i32> = Ok(5);
|
||||
LL | | a?;
|
||||
| | ^ this `?` produces `Result<Infallible, i32>`, which is incompatible with `Option<i32>`
|
||||
LL | | Some(5)
|
||||
LL | | }
|
||||
| |_- this function returns an `Option`
|
||||
|
|
||||
= help: the trait `FromResidual<Result<Infallible, i32>>` is not implemented for `Option<i32>`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
24
src/test/ui/try-trait/try-as-monad.rs
Normal file
24
src/test/ui/try-trait/try-as-monad.rs
Normal file
@ -0,0 +1,24 @@
|
||||
// run-pass
|
||||
|
||||
#![feature(try_trait_v2)]
|
||||
|
||||
use std::ops::Try;
|
||||
|
||||
fn monad_unit<T: Try>(x: <T as Try>::Output) -> T {
|
||||
T::from_output(x)
|
||||
}
|
||||
|
||||
fn monad_bind<T1: Try<Residual = R>, T2: Try<Residual = R>, R>(
|
||||
mx: T1,
|
||||
f: impl FnOnce(<T1 as Try>::Output) -> T2)
|
||||
-> T2 {
|
||||
let x = mx?;
|
||||
f(x)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mx: Option<i32> = monad_unit(1);
|
||||
let my = monad_bind(mx, |x| Some(x + 1));
|
||||
let mz = monad_bind(my, |x| Some(-x));
|
||||
assert_eq!(mz, Some(-2));
|
||||
}
|
@ -1,57 +1,57 @@
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-on-option-diagnostics.rs:7:5
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/try-on-option-diagnostics.rs:7:6
|
||||
|
|
||||
LL | / fn a_function() -> u32 {
|
||||
LL | | let x: Option<u32> = None;
|
||||
LL | | x?;
|
||||
| | ^^ cannot use the `?` operator in a function that returns `u32`
|
||||
| | ^ cannot use the `?` operator in a function that returns `u32`
|
||||
LL | | 22
|
||||
LL | | }
|
||||
| |_- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `u32`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-on-option-diagnostics.rs:14:9
|
||||
error[E0277]: the `?` operator can only be used in a closure that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/try-on-option-diagnostics.rs:14:10
|
||||
|
|
||||
LL | let a_closure = || {
|
||||
| _____________________-
|
||||
LL | | let x: Option<u32> = None;
|
||||
LL | | x?;
|
||||
| | ^^ cannot use the `?` operator in a closure that returns `{integer}`
|
||||
| | ^ cannot use the `?` operator in a closure that returns `{integer}`
|
||||
LL | | 22
|
||||
LL | | };
|
||||
| |_____- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `{integer}`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `{integer}`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-on-option-diagnostics.rs:26:13
|
||||
error[E0277]: the `?` operator can only be used in a method that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/try-on-option-diagnostics.rs:26:14
|
||||
|
|
||||
LL | / fn a_method() {
|
||||
LL | | let x: Option<u32> = None;
|
||||
LL | | x?;
|
||||
| | ^^ cannot use the `?` operator in a method that returns `()`
|
||||
| | ^ cannot use the `?` operator in a method that returns `()`
|
||||
LL | | }
|
||||
| |_________- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `()`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `()`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-on-option-diagnostics.rs:39:13
|
||||
error[E0277]: the `?` operator can only be used in a trait method that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/try-on-option-diagnostics.rs:39:14
|
||||
|
|
||||
LL | / fn a_trait_method() {
|
||||
LL | | let x: Option<u32> = None;
|
||||
LL | | x?;
|
||||
| | ^^ cannot use the `?` operator in a trait method that returns `()`
|
||||
| | ^ cannot use the `?` operator in a trait method that returns `()`
|
||||
LL | | }
|
||||
| |_________- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `()`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `()`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
@ -4,7 +4,7 @@ fn main() {}
|
||||
|
||||
fn foo() -> Result<u32, ()> {
|
||||
let x: Option<u32> = None;
|
||||
x?; //~ ERROR `?` couldn't convert the error
|
||||
x?; //~ ERROR the `?` operator
|
||||
Ok(22)
|
||||
}
|
||||
|
31
src/test/ui/try-trait/try-on-option.stderr
Normal file
31
src/test/ui/try-trait/try-on-option.stderr
Normal file
@ -0,0 +1,31 @@
|
||||
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
|
||||
--> $DIR/try-on-option.rs:7:6
|
||||
|
|
||||
LL | / fn foo() -> Result<u32, ()> {
|
||||
LL | | let x: Option<u32> = None;
|
||||
LL | | x?;
|
||||
| | ^ use `.ok_or(...)?` to provide an error compatible with `Result<u32, ()>`
|
||||
LL | | Ok(22)
|
||||
LL | | }
|
||||
| |_- this function returns a `Result`
|
||||
|
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `Result<u32, ()>`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/try-on-option.rs:13:6
|
||||
|
|
||||
LL | / fn bar() -> u32 {
|
||||
LL | | let x: Option<u32> = None;
|
||||
LL | | x?;
|
||||
| | ^ cannot use the `?` operator in a function that returns `u32`
|
||||
LL | | 22
|
||||
LL | | }
|
||||
| |_- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `FromResidual<Option<Infallible>>` is not implemented for `u32`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
91
src/test/ui/try-trait/try-operator-custom.rs
Normal file
91
src/test/ui/try-trait/try-operator-custom.rs
Normal file
@ -0,0 +1,91 @@
|
||||
// run-pass
|
||||
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(try_trait_v2)]
|
||||
|
||||
use std::ops::{ControlFlow, FromResidual, Try};
|
||||
|
||||
enum MyResult<T, U> {
|
||||
Awesome(T),
|
||||
Terrible(U)
|
||||
}
|
||||
|
||||
enum Never {}
|
||||
|
||||
impl<U, V> Try for MyResult<U, V> {
|
||||
type Output = U;
|
||||
type Residual = MyResult<Never, V>;
|
||||
|
||||
fn from_output(u: U) -> MyResult<U, V> {
|
||||
MyResult::Awesome(u)
|
||||
}
|
||||
|
||||
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
|
||||
match self {
|
||||
MyResult::Awesome(u) => ControlFlow::Continue(u),
|
||||
MyResult::Terrible(e) => ControlFlow::Break(MyResult::Terrible(e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<U, V, W> FromResidual<MyResult<Never, V>> for MyResult<U, W> where V: Into<W> {
|
||||
fn from_residual(x: MyResult<Never, V>) -> Self {
|
||||
match x {
|
||||
MyResult::Awesome(u) => match u {},
|
||||
MyResult::Terrible(e) => MyResult::Terrible(e.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type ResultResidual<E> = Result<std::convert::Infallible, E>;
|
||||
|
||||
impl<U, V, W> FromResidual<ResultResidual<V>> for MyResult<U, W> where V: Into<W> {
|
||||
fn from_residual(x: ResultResidual<V>) -> Self {
|
||||
match x {
|
||||
Ok(v) => match v {}
|
||||
Err(e) => MyResult::Terrible(e.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<U, V, W> FromResidual<MyResult<Never, V>> for Result<U, W> where V: Into<W> {
|
||||
fn from_residual(x: MyResult<Never, V>) -> Self {
|
||||
match x {
|
||||
MyResult::Awesome(u) => match u {},
|
||||
MyResult::Terrible(e) => Err(e.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn f(x: i32) -> Result<i32, String> {
|
||||
if x == 0 {
|
||||
Ok(42)
|
||||
} else {
|
||||
let y = g(x)?;
|
||||
Ok(y)
|
||||
}
|
||||
}
|
||||
|
||||
fn g(x: i32) -> MyResult<i32, String> {
|
||||
let _y = f(x - 1)?;
|
||||
MyResult::Terrible("Hello".to_owned())
|
||||
}
|
||||
|
||||
fn h() -> MyResult<i32, String> {
|
||||
let a: Result<i32, &'static str> = Err("Hello");
|
||||
let b = a?;
|
||||
MyResult::Awesome(b)
|
||||
}
|
||||
|
||||
fn i() -> MyResult<i32, String> {
|
||||
let a: MyResult<i32, &'static str> = MyResult::Terrible("Hello");
|
||||
let b = a?;
|
||||
MyResult::Awesome(b)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert!(f(0) == Ok(42));
|
||||
assert!(f(10) == Err("Hello".to_owned()));
|
||||
let _ = h();
|
||||
let _ = i();
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
#![feature(try_trait)]
|
||||
#![feature(try_trait_v2)]
|
||||
|
||||
use std::ops::Try;
|
||||
|
||||
@ -7,14 +7,13 @@ fn main() {
|
||||
std::fs::File::open("foo")?; //~ ERROR the `?` operator can only
|
||||
|
||||
// a non-`Try` type on a non-`Try` fn
|
||||
()?; //~ ERROR the `?` operator can only
|
||||
()?; //~ ERROR the `?` operator can only be applied to
|
||||
//~^ ERROR the `?` operator can only be used in a function that
|
||||
|
||||
// an unrelated use of `Try`
|
||||
try_trait_generic::<()>(); //~ ERROR the trait bound
|
||||
}
|
||||
|
||||
|
||||
|
||||
fn try_trait_generic<T: Try>() -> T {
|
||||
// and a non-`Try` object on a `Try` fn.
|
||||
()?; //~ ERROR the `?` operator can only be applied to values that implement `Try`
|
@ -1,18 +1,18 @@
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `Try`)
|
||||
--> $DIR/try-operator-on-main.rs:7:5
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/try-operator-on-main.rs:7:31
|
||||
|
|
||||
LL | / fn main() {
|
||||
LL | | // error for a `Try` type on a non-`Try` fn
|
||||
LL | | std::fs::File::open("foo")?;
|
||||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
|
||||
| | ^ cannot use the `?` operator in a function that returns `()`
|
||||
LL | |
|
||||
... |
|
||||
LL | | try_trait_generic::<()>();
|
||||
LL | | }
|
||||
| |_- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `()`
|
||||
= note: required by `from_error`
|
||||
= help: the trait `FromResidual<Result<Infallible, std::io::Error>>` is not implemented for `()`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the `?` operator can only be applied to values that implement `Try`
|
||||
--> $DIR/try-operator-on-main.rs:10:5
|
||||
@ -21,10 +21,28 @@ LL | ()?;
|
||||
| ^^^ the `?` operator cannot be applied to type `()`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `()`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
|
||||
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
|
||||
--> $DIR/try-operator-on-main.rs:10:7
|
||||
|
|
||||
LL | / fn main() {
|
||||
LL | | // error for a `Try` type on a non-`Try` fn
|
||||
LL | | std::fs::File::open("foo")?;
|
||||
LL | |
|
||||
LL | | // a non-`Try` type on a non-`Try` fn
|
||||
LL | | ()?;
|
||||
| | ^ cannot use the `?` operator in a function that returns `()`
|
||||
... |
|
||||
LL | | try_trait_generic::<()>();
|
||||
LL | | }
|
||||
| |_- this function should return `Result` or `Option` to accept `?`
|
||||
|
|
||||
= help: the trait `FromResidual<_>` is not implemented for `()`
|
||||
= note: required by `from_residual`
|
||||
|
||||
error[E0277]: the trait bound `(): Try` is not satisfied
|
||||
--> $DIR/try-operator-on-main.rs:13:25
|
||||
--> $DIR/try-operator-on-main.rs:14:25
|
||||
|
|
||||
LL | try_trait_generic::<()>();
|
||||
| ^^ the trait `Try` is not implemented for `()`
|
||||
@ -33,14 +51,14 @@ LL | fn try_trait_generic<T: Try>() -> T {
|
||||
| --- required by this bound in `try_trait_generic`
|
||||
|
||||
error[E0277]: the `?` operator can only be applied to values that implement `Try`
|
||||
--> $DIR/try-operator-on-main.rs:20:5
|
||||
--> $DIR/try-operator-on-main.rs:19:5
|
||||
|
|
||||
LL | ()?;
|
||||
| ^^^ the `?` operator cannot be applied to type `()`
|
||||
|
|
||||
= help: the trait `Try` is not implemented for `()`
|
||||
= note: required by `into_result`
|
||||
= note: required by `branch`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
@ -147,7 +147,7 @@ fn is_some_or_ok_call<'a>(cx: &'a LateContext<'_>, expr: &'a Expr<'_>) -> Option
|
||||
if let ExprKind::Call(called, args) = &inner_expr_with_q.kind;
|
||||
if args.len() == 1;
|
||||
|
||||
if let ExprKind::Path(QPath::LangItem(LangItem::TryIntoResult, _)) = &called.kind;
|
||||
if let ExprKind::Path(QPath::LangItem(LangItem::TryTraitBranch, _)) = &called.kind;
|
||||
then {
|
||||
// Extract inner expr type from match argument generated by
|
||||
// question mark operator
|
||||
|
@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for TryErr {
|
||||
if let ExprKind::Match(match_arg, _, MatchSource::TryDesugar) = expr.kind;
|
||||
if let ExprKind::Call(match_fun, try_args) = match_arg.kind;
|
||||
if let ExprKind::Path(ref match_fun_path) = match_fun.kind;
|
||||
if matches!(match_fun_path, QPath::LangItem(LangItem::TryIntoResult, _));
|
||||
if matches!(match_fun_path, QPath::LangItem(LangItem::TryTraitBranch, _));
|
||||
if let Some(try_arg) = try_args.get(0);
|
||||
if let ExprKind::Call(err_fun, err_args) = try_arg.kind;
|
||||
if let Some(err_arg) = err_args.get(0);
|
||||
|
@ -45,7 +45,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount {
|
||||
if let hir::ExprKind::Call(func, args) = res.kind {
|
||||
if matches!(
|
||||
func.kind,
|
||||
hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryIntoResult, _))
|
||||
hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, _))
|
||||
) {
|
||||
check_map_error(cx, &args[0], expr);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user