Skip to content

Commit cffd2df

Browse files
committed
thir: Add Become expression kind
Note that this doesn't implement `become` correctly, there is still no early drop or tail calls involved. Moreother, it seems like MIR simply can not represent tail calls in its current form so I'll probably need to add new statement kinds or smh. to it in order to represent them...
1 parent 47ab1e5 commit cffd2df

File tree

12 files changed

+36
-7
lines changed

12 files changed

+36
-7
lines changed

compiler/rustc_middle/src/thir.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,10 @@ pub enum ExprKind<'tcx> {
410410
Return {
411411
value: Option<ExprId>,
412412
},
413+
/// A `become` expression.
414+
Become {
415+
value: ExprId,
416+
},
413417
/// An inline `const` block, e.g. `const {}`.
414418
ConstBlock {
415419
did: DefId,

compiler/rustc_middle/src/thir/visit.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
100100
visitor.visit_expr(&visitor.thir()[value])
101101
}
102102
}
103+
Become { value } => visitor.visit_expr(&visitor.thir()[value]),
103104
ConstBlock { did: _, substs: _ } => {}
104105
Repeat { value, count: _ } => {
105106
visitor.visit_expr(&visitor.thir()[value]);

compiler/rustc_mir_build/src/build/expr/as_place.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
549549
| ExprKind::Break { .. }
550550
| ExprKind::Continue { .. }
551551
| ExprKind::Return { .. }
552+
| ExprKind::Become { .. }
552553
| ExprKind::Literal { .. }
553554
| ExprKind::NamedConst { .. }
554555
| ExprKind::NonHirLiteral { .. }

compiler/rustc_mir_build/src/build/expr/as_rvalue.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
532532
| ExprKind::Break { .. }
533533
| ExprKind::Continue { .. }
534534
| ExprKind::Return { .. }
535+
| ExprKind::Become { .. }
535536
| ExprKind::InlineAsm { .. }
536537
| ExprKind::PlaceTypeAscription { .. }
537538
| ExprKind::ValueTypeAscription { .. } => {

compiler/rustc_mir_build/src/build/expr/category.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ impl Category {
8282
| ExprKind::Block { .. }
8383
| ExprKind::Break { .. }
8484
| ExprKind::Continue { .. }
85-
| ExprKind::Return { .. } =>
85+
| ExprKind::Return { .. }
86+
| ExprKind::Become { .. } =>
8687
// FIXME(#27840) these probably want their own
8788
// category, like "nonterminating"
8889
{

compiler/rustc_mir_build/src/build/expr/into.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
489489
block.unit()
490490
}
491491

492-
ExprKind::Continue { .. } | ExprKind::Break { .. } | ExprKind::Return { .. } => {
492+
ExprKind::Continue { .. }
493+
| ExprKind::Break { .. }
494+
| ExprKind::Return { .. }
495+
| ExprKind::Become { .. } => {
493496
unpack!(block = this.stmt_expr(block, expr, None));
494497
// No assign, as these have type `!`.
495498
block.unit()

compiler/rustc_mir_build/src/build/expr/stmt.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
9999
BreakableTarget::Return,
100100
source_info,
101101
),
102+
ExprKind::Become { value } => this.break_scope(
103+
block,
104+
Some(&this.thir[value]),
105+
BreakableTarget::Become,
106+
source_info,
107+
),
102108
_ => {
103109
assert!(
104110
statement_scope.is_some(),

compiler/rustc_mir_build/src/build/scope.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ pub(crate) enum BreakableTarget {
182182
Continue(region::Scope),
183183
Break(region::Scope),
184184
Return,
185+
Become,
185186
}
186187

187188
rustc_index::newtype_index! {
@@ -627,10 +628,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
627628
.unwrap_or_else(|| span_bug!(span, "no enclosing breakable scope found"))
628629
};
629630
let (break_index, destination) = match target {
630-
BreakableTarget::Return => {
631+
BreakableTarget::Return | BreakableTarget::Become => {
631632
let scope = &self.scopes.breakable_scopes[0];
632633
if scope.break_destination != Place::return_place() {
633-
span_bug!(span, "`return` in item with no return scope");
634+
span_bug!(span, "`return` or `become` in item with no return scope");
634635
}
635636
(0, Some(scope.break_destination))
636637
}
@@ -668,6 +669,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
668669
(None, None) => {}
669670
}
670671

672+
// FIXME(explicit_tail_calls): this should drop stuff early for `become`
673+
671674
let region_scope = self.scopes.breakable_scopes[break_index].region_scope;
672675
let scope_index = self.scopes.scope_index(region_scope, span);
673676
let drops = if destination.is_some() {

compiler/rustc_mir_build/src/check_unsafety.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
316316
| ExprKind::Closure { .. }
317317
| ExprKind::Continue { .. }
318318
| ExprKind::Return { .. }
319+
| ExprKind::Become { .. }
319320
| ExprKind::Yield { .. }
320321
| ExprKind::Loop { .. }
321322
| ExprKind::Let { .. }

compiler/rustc_mir_build/src/thir/cx/expr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -694,8 +694,8 @@ impl<'tcx> Cx<'tcx> {
694694

695695
ExprKind::Repeat { value: self.mirror_expr(v), count: *count }
696696
}
697-
hir::ExprKind::Ret(ref v) => ExprKind::Return { value: v.map(|v| self.mirror_expr(v)) },
698-
hir::ExprKind::Become(_call) => unimplemented!("lol (lmao)"),
697+
hir::ExprKind::Ret(v) => ExprKind::Return { value: v.map(|v| self.mirror_expr(v)) },
698+
hir::ExprKind::Become(call) => ExprKind::Become { value: self.mirror_expr(call) },
699699
hir::ExprKind::Break(dest, ref value) => match dest.target_id {
700700
Ok(target_id) => ExprKind::Break {
701701
label: region::Scope { id: target_id.local_id, data: region::ScopeData::Node },

compiler/rustc_mir_build/src/thir/print.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,12 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
421421

422422
print_indented!(self, "}", depth_lvl);
423423
}
424+
Become { value } => {
425+
print_indented!(self, "Return {", depth_lvl);
426+
print_indented!(self, "value:", depth_lvl + 1);
427+
self.print_expr(*value, depth_lvl + 2);
428+
print_indented!(self, "}", depth_lvl);
429+
}
424430
ConstBlock { did, substs } => {
425431
print_indented!(self, "ConstBlock {", depth_lvl);
426432
print_indented!(self, format!("did: {:?}", did), depth_lvl + 1);

compiler/rustc_ty_utils/src/consts.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,8 @@ fn recurse_build<'tcx>(
240240
ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => {
241241
error(GenericConstantTooComplexSub::AssignNotSupported(node.span))?
242242
}
243-
ExprKind::Closure { .. } | ExprKind::Return { .. } => {
243+
// FIXME(explicit_tail_calls): maybe get `become` a new error
244+
ExprKind::Closure { .. } | ExprKind::Return { .. } | ExprKind::Become { .. } => {
244245
error(GenericConstantTooComplexSub::ClosureAndReturnNotSupported(node.span))?
245246
}
246247
// let expressions imply control flow
@@ -336,6 +337,7 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> {
336337
| thir::ExprKind::Break { .. }
337338
| thir::ExprKind::Continue { .. }
338339
| thir::ExprKind::Return { .. }
340+
| thir::ExprKind::Become { .. }
339341
| thir::ExprKind::Array { .. }
340342
| thir::ExprKind::Tuple { .. }
341343
| thir::ExprKind::Adt(_)

0 commit comments

Comments
 (0)