Skip to content

Commit e094ee5

Browse files
committed
Add do yeet expressions to allow experimentation in nightly
Using an obviously-placeholder syntax. An RFC would still be needed before this could have any chance at stabilization, and it might be removed at any point. But I'd really like to have it in nightly at least to ensure it works well with try_trait_v2, especially as we refactor the traits.
1 parent 2c858a7 commit e094ee5

File tree

23 files changed

+236
-3
lines changed

23 files changed

+236
-3
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,6 +1275,7 @@ impl Expr {
12751275
ExprKind::Paren(..) => ExprPrecedence::Paren,
12761276
ExprKind::Try(..) => ExprPrecedence::Try,
12771277
ExprKind::Yield(..) => ExprPrecedence::Yield,
1278+
ExprKind::Yeet(..) => ExprPrecedence::Yeet,
12781279
ExprKind::Err => ExprPrecedence::Err,
12791280
}
12801281
}
@@ -1462,6 +1463,10 @@ pub enum ExprKind {
14621463
/// A `yield`, with an optional value to be yielded.
14631464
Yield(Option<P<Expr>>),
14641465

1466+
/// A `do yeet` (aka `throw`/`fail`/`bail`/`raise`/whatever),
1467+
/// with an optional value to be returned.
1468+
Yeet(Option<P<Expr>>),
1469+
14651470
/// Placeholder for an expression that wasn't syntactically well formed in some way.
14661471
Err,
14671472
}

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,6 +1394,9 @@ pub fn noop_visit_expr<T: MutVisitor>(
13941394
ExprKind::Ret(expr) => {
13951395
visit_opt(expr, |expr| vis.visit_expr(expr));
13961396
}
1397+
ExprKind::Yeet(expr) => {
1398+
visit_opt(expr, |expr| vis.visit_expr(expr));
1399+
}
13971400
ExprKind::InlineAsm(asm) => vis.visit_inline_asm(asm),
13981401
ExprKind::MacCall(mac) => vis.visit_mac_call(mac),
13991402
ExprKind::Struct(se) => {

compiler/rustc_ast/src/util/parser.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ pub enum ExprPrecedence {
247247
Continue,
248248
Ret,
249249
Yield,
250+
Yeet,
250251

251252
Range,
252253

@@ -299,7 +300,8 @@ impl ExprPrecedence {
299300
ExprPrecedence::Break |
300301
ExprPrecedence::Continue |
301302
ExprPrecedence::Ret |
302-
ExprPrecedence::Yield => PREC_JUMP,
303+
ExprPrecedence::Yield |
304+
ExprPrecedence::Yeet => PREC_JUMP,
303305

304306
// `Range` claims to have higher precedence than `Assign`, but `x .. x = x` fails to
305307
// parse, instead of parsing as `(x .. x) = x`. Giving `Range` a lower precedence

compiler/rustc_ast/src/visit.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,6 +893,9 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
893893
ExprKind::Ret(ref optional_expression) => {
894894
walk_list!(visitor, visit_expr, optional_expression);
895895
}
896+
ExprKind::Yeet(ref optional_expression) => {
897+
walk_list!(visitor, visit_expr, optional_expression);
898+
}
896899
ExprKind::MacCall(ref mac) => visitor.visit_mac_call(mac),
897900
ExprKind::Paren(ref subexpression) => visitor.visit_expr(subexpression),
898901
ExprKind::InlineAsm(ref asm) => walk_inline_asm(visitor, asm),

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
221221
let e = e.as_ref().map(|x| self.lower_expr(x));
222222
hir::ExprKind::Ret(e)
223223
}
224+
ExprKind::Yeet(ref sub_expr) => self.lower_expr_yeet(e.span, sub_expr.as_deref()),
224225
ExprKind::InlineAsm(ref asm) => {
225226
hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm))
226227
}
@@ -1543,6 +1544,44 @@ impl<'hir> LoweringContext<'_, 'hir> {
15431544
)
15441545
}
15451546

1547+
/// Desugar `ExprKind::Yeet` from: `do yeet <expr>` into:
1548+
/// ```rust
1549+
/// // If there is an enclosing `try {...}`:
1550+
/// break 'catch_target FromResidual::from_residual(Yeet(residual)),
1551+
/// // Otherwise:
1552+
/// return FromResidual::from_residual(Yeet(residual)),
1553+
/// ```
1554+
/// But to simplify this, there's a `from_yeet` lang item function which
1555+
/// handles the combined `FromResidual::from_residual(Yeet(residual))`.
1556+
fn lower_expr_yeet(&mut self, span: Span, sub_expr: Option<&Expr>) -> hir::ExprKind<'hir> {
1557+
// The expression (if present) or `()` otherwise.
1558+
let (yeeted_span, yeeted_expr) = if let Some(sub_expr) = sub_expr {
1559+
(sub_expr.span, self.lower_expr(sub_expr))
1560+
} else {
1561+
(self.mark_span_with_reason(DesugaringKind::YeetExpr, span, None), self.expr_unit(span))
1562+
};
1563+
1564+
let unstable_span = self.mark_span_with_reason(
1565+
DesugaringKind::YeetExpr,
1566+
span,
1567+
self.allow_try_trait.clone(),
1568+
);
1569+
1570+
let from_yeet_expr = self.wrap_in_try_constructor(
1571+
hir::LangItem::TryTraitFromYeet,
1572+
unstable_span,
1573+
yeeted_expr,
1574+
yeeted_span,
1575+
);
1576+
1577+
if let Some(catch_node) = self.catch_scope {
1578+
let target_id = Ok(self.lower_node_id(catch_node));
1579+
hir::ExprKind::Break(hir::Destination { label: None, target_id }, Some(from_yeet_expr))
1580+
} else {
1581+
hir::ExprKind::Ret(Some(from_yeet_expr))
1582+
}
1583+
}
1584+
15461585
// =========================================================================
15471586
// Helper methods for building HIR.
15481587
// =========================================================================

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
8585
task_context: None,
8686
current_item: None,
8787
captured_lifetimes: None,
88-
allow_try_trait: Some([sym::try_trait_v2][..].into()),
88+
allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()),
8989
allow_gen_future: Some([sym::gen_future][..].into()),
9090
allow_into_future: Some([sym::into_future][..].into()),
9191
};

compiler/rustc_ast_passes/src/feature_gate.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
619619
ast::ExprKind::TryBlock(_) => {
620620
gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental");
621621
}
622+
ast::ExprKind::Yeet(_) => {
623+
gate_feature_post!(
624+
&self,
625+
yeet_expr,
626+
e.span,
627+
"`do yeet` expression is experimental"
628+
);
629+
}
622630
ast::ExprKind::Block(_, Some(label)) => {
623631
gate_feature_post!(
624632
&self,

compiler/rustc_ast_pretty/src/pprust/state/expr.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ impl<'a> State<'a> {
6464
// parses as the erroneous construct `if (return {})`, not `if (return) {}`.
6565
pub(super) fn cond_needs_par(expr: &ast::Expr) -> bool {
6666
match expr.kind {
67-
ast::ExprKind::Break(..) | ast::ExprKind::Closure(..) | ast::ExprKind::Ret(..) => true,
67+
ast::ExprKind::Break(..)
68+
| ast::ExprKind::Closure(..)
69+
| ast::ExprKind::Ret(..)
70+
| ast::ExprKind::Yeet(..) => true,
6871
_ => parser::contains_exterior_struct_lit(expr),
6972
}
7073
}
@@ -502,6 +505,15 @@ impl<'a> State<'a> {
502505
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
503506
}
504507
}
508+
ast::ExprKind::Yeet(ref result) => {
509+
self.word("do");
510+
self.word(" ");
511+
self.word("yeet");
512+
if let Some(ref expr) = *result {
513+
self.word(" ");
514+
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
515+
}
516+
}
505517
ast::ExprKind::InlineAsm(ref a) => {
506518
self.word("asm!");
507519
self.print_inline_asm(a);

compiler/rustc_feature/src/active.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,8 @@ declare_features! (
544544
(active, used_with_arg, "1.60.0", Some(93798), None),
545545
/// Allows `extern "wasm" fn`
546546
(active, wasm_abi, "1.53.0", Some(83788), None),
547+
/// Allows `do yeet` expressions
548+
(active, yeet_expr, "1.62.0", Some(96373), None),
547549
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
548550
// Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
549551
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!

compiler/rustc_hir/src/lang_items.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ language_item_table! {
293293
TryTraitFromResidual, sym::from_residual, from_residual_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
294294
TryTraitFromOutput, sym::from_output, from_output_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
295295
TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
296+
TryTraitFromYeet, sym::from_yeet, from_yeet_fn, Target::Fn, GenericRequirement::None;
296297

297298
PollReady, sym::Ready, poll_ready_variant, Target::Variant, GenericRequirement::None;
298299
PollPending, sym::Pending, poll_pending_variant, Target::Variant, GenericRequirement::None;

0 commit comments

Comments
 (0)