Skip to content

Implement the new desugaring from try_trait_v2 #84767

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 11 commits into from
May 18, 2021
58 changes: 26 additions & 32 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,8 +562,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| {
Expand Down Expand Up @@ -592,9 +592,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,
Expand Down Expand Up @@ -1896,14 +1896,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],
)
};
Expand All @@ -1921,8 +1921,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(
Expand All @@ -1931,27 +1931,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);
Expand All @@ -1962,25 +1956,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,
)
}
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,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)
Expand Down Expand Up @@ -2479,14 +2479,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> {
Expand Down
11 changes: 7 additions & 4 deletions compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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});

Expand Down
13 changes: 8 additions & 5 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,12 @@ symbols! {
BTreeSet,
BinaryHeap,
Borrow,
Break,
C,
CString,
Center,
Clone,
Continue,
Copy,
Count,
Debug,
Expand Down Expand Up @@ -326,6 +328,7 @@ symbols! {
box_patterns,
box_syntax,
braced_empty_structs,
branch,
breakpoint,
bridge,
bswap,
Expand Down Expand Up @@ -410,6 +413,7 @@ symbols! {
constructor,
contents,
context,
control_flow_enum,
convert,
copy,
copy_closures,
Expand Down Expand Up @@ -510,7 +514,6 @@ symbols! {
env,
eq,
ermsb_target_feature,
err,
exact_div,
except,
exchange_malloc,
Expand Down Expand Up @@ -580,10 +583,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,
Expand Down Expand Up @@ -652,7 +655,6 @@ symbols! {
instruction_set,
intel,
into_iter,
into_result,
into_trait,
intra_doc_pointers,
intrinsics,
Expand Down Expand Up @@ -962,6 +964,7 @@ symbols! {
repr_packed,
repr_simd,
repr_transparent,
residual,
result,
result_type,
rhs,
Expand Down Expand Up @@ -1227,7 +1230,7 @@ symbols! {
try_blocks,
try_from_trait,
try_into_trait,
try_trait,
try_trait_v2,
tt,
tuple,
tuple_from_req,
Expand Down
4 changes: 2 additions & 2 deletions library/alloc/src/collections/vec_deque/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down
3 changes: 2 additions & 1 deletion library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
4 changes: 2 additions & 2 deletions library/core/src/iter/adapters/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)?;
Expand Down Expand Up @@ -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)?;
Expand Down
4 changes: 2 additions & 2 deletions library/core/src/iter/adapters/cloned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
Expand Down Expand Up @@ -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))
}
Expand Down
4 changes: 2 additions & 2 deletions library/core/src/iter/adapters/copied.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
Expand Down Expand Up @@ -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))
}
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/iter/adapters/cycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions library/core/src/iter/adapters/enumerate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>(
Expand Down Expand Up @@ -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`.
Expand Down
6 changes: 3 additions & 3 deletions library/core/src/iter/adapters/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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))
}
Expand Down Expand Up @@ -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))
}
Expand Down
Loading