summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJemma Issroff <jemmaissroff@gmail.com>2023-11-28 16:12:19 -0500
committerJemma Issroff <jemmaissroff@gmail.com>2023-11-28 17:01:34 -0500
commita9c07cbd2128ae8fcb11862265d5fa24feaf3d4f (patch)
treee7fbf35d338316cd66f22659eb7b700d7eff62e9
parent04cbcd37b1c18c4db4b9df8d80abb4efec11755c (diff)
[PRISM] Don't calculate params size based on locals
Prior to this commit, we were conflating the size of the locals list with the number of parameters. This commit distinguishes the two, and fixes a related bug which would occur if we set a local that was not a parameter
-rw-r--r--prism_compile.c21
-rw-r--r--test/ruby/test_compile_prism.rb1
2 files changed, 19 insertions, 3 deletions
diff --git a/prism_compile.c b/prism_compile.c
index 05c75ead50..1f16bfe044 100644
--- a/prism_compile.c
+++ b/prism_compile.c
@@ -710,13 +710,13 @@ pm_lookup_local_index(rb_iseq_t *iseq, pm_scope_node_t *scope_node, pm_constant_
{
st_data_t local_index;
- int num_params = ISEQ_BODY(iseq)->param.size;
+ int locals_size = (int) scope_node->locals.size;
if (!st_lookup(scope_node->index_lookup_table, constant_id, &local_index)) {
rb_bug("This local does not exist");
}
- return num_params - (int)local_index;
+ return locals_size - (int)local_index;
}
static int
@@ -3592,7 +3592,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
VALUE idtmp = 0;
rb_ast_id_table_t *tbl = ALLOCV(idtmp, sizeof(rb_ast_id_table_t) + locals_size * sizeof(ID));
tbl->size = (int) locals_size;
- body->param.size = (int) locals_size;
for (size_t i = 0; i < locals_size; i++) {
pm_constant_id_t constant_id = locals->ids[i];
@@ -3740,6 +3739,22 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
}
}
+ iseq_calc_param_size(iseq);
+
+ // Calculating the parameter size above does not account for numbered parameters
+ // We can _only_ have numbered parameters if we don't have non numbered parameters
+ // We verify this through asserts, and add the numbered_parameters size accordingly
+ if (PM_NODE_TYPE_P(scope_node->ast_node, PM_BLOCK_NODE)) {
+ uint32_t numbered_parameters = ((pm_block_node_t *)(scope_node->ast_node))->numbered_parameters;
+ RUBY_ASSERT(!body->param.size || !numbered_parameters);
+ body->param.size += numbered_parameters;
+ }
+ else if (PM_NODE_TYPE_P(scope_node->ast_node, PM_LAMBDA_NODE)) {
+ uint32_t numbered_parameters = ((pm_lambda_node_t *)(scope_node->ast_node))->numbered_parameters;
+ RUBY_ASSERT(!body->param.size || !numbered_parameters);
+ body->param.size += numbered_parameters;
+ }
+
iseq_set_local_table(iseq, tbl);
switch (body->type) {
diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb
index b7dc6a6e0f..8a078c01cc 100644
--- a/test/ruby/test_compile_prism.rb
+++ b/test/ruby/test_compile_prism.rb
@@ -756,6 +756,7 @@ module Prism
assert_prism_eval("def self.prism_test_def_node() 1 end; prism_test_def_node()")
assert_prism_eval("def self.prism_test_def_node(a,b) [a, b] end; prism_test_def_node(1,2)")
assert_prism_eval("def self.prism_test_def_node(a,x=7,y=1) x end; prism_test_def_node(7,1)")
+ assert_prism_eval("def self.prism_test_def_node(a = 1); x = 2; end; prism_test_def_node")
# rest argument
assert_prism_eval("def self.prism_test_def_node(*a) a end; prism_test_def_node().inspect")