From e042557d5352baf5de67968c113b23349c56f652 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 24 Dec 2025 08:20:31 +0900 Subject: [PATCH] mruby-compiler: fix pattern matching === operand order bug When matching array/hash element patterns like `[Integer]` against values, the element register was being overwritten by codegen before the comparison. This caused `[1] in [Integer]|[String]` to incorrectly return false because the bytecode was effectively doing `1.===(Integer)` instead of `Integer.===(1)`. Fix by preserving the element value with push() before calling codegen_pattern, so the element stays at cursp()-1 while the pattern value is generated at cursp(). Co-authored-by: Claude --- mrbgems/mruby-compiler/core/codegen.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index dc9db6314..cd18ec344 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -4557,8 +4557,10 @@ codegen_pattern(codegen_scope *s, node *pattern, int target, uint32_t *fail_pos) gen_int(s, cursp(), i); push(); push(); pop(); pop(); pop(); genop_3(s, OP_SEND, cursp(), sym_idx(s, MRB_OPSYM_2(s->mrb, aref)), 1); + push(); /* Preserve element result for codegen_pattern */ /* Match element pattern */ - codegen_pattern(s, elem->car, cursp(), fail_pos); + codegen_pattern(s, elem->car, cursp() - 1, fail_pos); + pop(); /* Clean up element slot */ } /* Bind rest elements if rest is a variable */ @@ -4598,8 +4600,10 @@ codegen_pattern(codegen_scope *s, node *pattern, int target, uint32_t *fail_pos) gen_int(s, cursp(), i); push(); push(); pop(); pop(); pop(); genop_3(s, OP_SEND, cursp(), sym_idx(s, MRB_OPSYM_2(s->mrb, aref)), 1); + push(); /* Preserve element result for codegen_pattern */ /* Match element pattern */ - codegen_pattern(s, elem->car, cursp(), fail_pos); + codegen_pattern(s, elem->car, cursp() - 1, fail_pos); + pop(); /* Clean up element slot */ } pop(); /* Pop arr_reg */ @@ -4685,8 +4689,10 @@ codegen_pattern(codegen_scope *s, node *pattern, int target, uint32_t *fail_pos) } push(); push(); pop(); pop(); pop(); genop_3(s, OP_SEND, cursp(), sym_idx(s, MRB_OPSYM_2(s->mrb, aref)), 1); + push(); /* Preserve element result for codegen_pattern */ /* Match element pattern - on fail, try next index */ - codegen_pattern(s, elem->car, cursp(), &match_fail); + codegen_pattern(s, elem->car, cursp() - 1, &match_fail); + pop(); /* Clean up element slot */ } /* All elements matched - bind pre and post if named */ @@ -4825,9 +4831,11 @@ codegen_pattern(codegen_scope *s, node *pattern, int target, uint32_t *fail_pos) } push(); push(); pop(); pop(); pop(); genop_3(s, OP_SEND, cursp(), sym_idx(s, MRB_OPSYM_2(s->mrb, aref)), 1); + push(); /* Preserve value for codegen_pattern */ /* Match pattern against value */ - codegen_pattern(s, pat, cursp(), fail_pos); + codegen_pattern(s, pat, cursp() - 1, fail_pos); + pop(); /* Clean up value slot */ } /* Handle rest pattern */