Skip to content

Commit

Permalink
fix: Fix the order of evaluation when unpacking tuples
Browse files Browse the repository at this point in the history
  • Loading branch information
tibordp committed Sep 29, 2024
1 parent 453c866 commit cbcdaa6
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 13 deletions.
35 changes: 22 additions & 13 deletions src/alumina-boot/src/ir/mono/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4284,6 +4284,7 @@ impl<'a, 'ast, 'ir> Mono<'a, 'ast, 'ir> {
let mut lowered = Vec::with_capacity(exprs.len());

for expr in exprs {
let _guard = self.diag.push_span(expr.span);
match expr.kind {
ast::ExprKind::EtCetera(inner) => {
// type hint is None since we do not know the length beforehand. If
Expand Down Expand Up @@ -4331,22 +4332,30 @@ impl<'a, 'ast, 'ir> Mono<'a, 'ast, 'ir> {
let element_types: Vec<_> = lowered.iter().map(|e| e.ty).collect();
let tuple_type = self.types.tuple(element_types);

let ret = self
// Unpacking produced an empty tuple, but there may have been side effects
// in the process, so we need to wrap the tuple in a block. This is slightly
// involved because we care about evaluating the expressions in order.
let ret = if stmts.is_empty() {
self
.exprs
.tuple(lowered.into_iter().enumerate(), tuple_type, ast_span)
.alloc_on(self.ctx.ir);

if !stmts.is_empty() {
// Unpacking produced an empty tuple, but there may have been side effects
// in the process, so we need to wrap the tuple in a block

let (tuple, assign) = self.ensure_local(ret);
stmts.extend(assign);

Ok(self.exprs.block(stmts, tuple, ast_span))
.alloc_on(self.ctx.ir)
} else if let Some(last) = lowered.last_mut() {
// Attach the remaining statements after the last tuple element
let (expr, stmt) = self.ensure_local(last);
stmts.extend(stmt);

*last = self.exprs.block(stmts, expr, ast_span);
self
.exprs
.tuple(lowered.into_iter().enumerate(), tuple_type, ast_span)
.alloc_on(self.ctx.ir)
} else {
Ok(ret)
}
let ret = self.exprs.void(tuple_type, ir::ValueType::RValue, ast_span);
self.exprs.block(stmts, ret, ast_span)
};

Ok(ret)
}

fn lower_cast(
Expand Down
20 changes: 20 additions & 0 deletions tests/lang/lang.alu
Original file line number Diff line number Diff line change
Expand Up @@ -927,4 +927,24 @@ fn test_tuple_slicing_types() {
#[test]
fn test_tuple_unpack() {
assert_eq!((1, (2, 3)..., 4, 5), (1, 2, 3, 4, 5));
assert_eq!((()...,), ());

// Test side effects & order of evaluation
let counter = 0;

let a = (1, {
assert_eq!(counter, 0);
counter += 1;
(2, 3)
}..., {
assert_eq!(counter, 1);
counter += 1;
(4, 5)
}..., {
assert_eq!(counter, 2);
counter += 1;
()
}...);

assert_eq!(a, (1, 2, 3, 4, 5));
}

0 comments on commit cbcdaa6

Please sign in to comment.