Skip to content

Commit

Permalink
Fix compiler crash from match with extra parens around let in tup…
Browse files Browse the repository at this point in the history
…le (#4595)

The compiler would crash if an extra set of parens were added to a
single element tuple match of a union type. For example,
if `type Foo is (I32 | (I32, I32))` is being matched, then a match
clause like `| (123, (let x: I32)) => x` would crash the compiler.
This was caused by the codegen for the match not handling the extra
SEQ node in the AST created by the parens. This change now skips
any extra SEQ nodes when performing codegen for tuple matches.

Fixes #4412
  • Loading branch information
chriskdon authored Jan 24, 2025
1 parent c21a80f commit f4e94df
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 0 deletions.
13 changes: 13 additions & 0 deletions .release-notes/4595.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Fix compiler crash from `match` with extra parens around `let` in tuple

When matching on a tuple element within a union type, the compiler would crash when extra parentheses were present.

The following code fails to compile because of `(123, (let x: I32))` in the `match`. The extra parentheses should be ignored and treated like `(123, let x: I32)`.

```pony
let value: (I32 | (I32, I32)) = (123, 42)
match value
| (123, (let x: I32)) => x
end
```
5 changes: 5 additions & 0 deletions src/libponyc/codegen/genmatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,11 @@ static bool dynamic_tuple_ptr(compile_t* c, LLVMValueRef ptr,

// Skip over the SEQ node.
ast_t* pattern_expr = ast_child(pattern_child);
while(ast_id(pattern_expr) == TK_SEQ)
{
pony_assert(ast_childcount(pattern_expr) == 1);
pattern_expr = ast_child(pattern_expr);
}

if(!dynamic_tuple_element(c, ptr, desc, pattern_expr, next_block, i))
return false;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
42
14 changes: 14 additions & 0 deletions test/full-program-tests/regression-4412/main.pony
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use @pony_exitcode[None](code: I32)

// As long as #4412 is fixed, this program will compile.

actor Main
new create(env: Env) =>
// A union type with a tuple is required to trigger the crash
let z: (I32 | (I32, I32)) = (123, 42)

match z
// This is the line that triggered the crash due to the extra parens around
// the let.
| (123, (let x: I32)) => @pony_exitcode(x)
end

0 comments on commit f4e94df

Please sign in to comment.