aboutsummaryrefslogtreecommitdiffstats
path: root/variable.c
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2023-06-20 12:39:22 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2023-06-20 13:57:42 +0900
commit2dfbe91cad2ebc6aa1a925b1b77b7af07fec1403 (patch)
tree1a8b7dce7701857309ad6f95443a6b7cdf9d8d40 /variable.c
parent1edbaa850f6907c9b4bbaa083ef13a578f251da1 (diff)
downloadruby-2dfbe91cad2ebc6aa1a925b1b77b7af07fec1403.tar.gz
Stop `rb_ivar_foreach` when callback returned `ST_STOP`
Diffstat (limited to 'variable.c')
-rw-r--r--variable.c26
1 files changed, 19 insertions, 7 deletions
diff --git a/variable.c b/variable.c
index 0491562d22..ce6feda885 100644
--- a/variable.c
+++ b/variable.c
@@ -1633,14 +1633,19 @@ struct iv_itr_data {
rb_ivar_foreach_callback_func *func;
};
-static void
+/*
+ * Returns a flag to stop iterating depending on the result of +callback+.
+ */
+static bool
iterate_over_shapes_with_callback(rb_shape_t *shape, rb_ivar_foreach_callback_func *callback, struct iv_itr_data * itr_data)
{
switch ((enum shape_type)shape->type) {
case SHAPE_ROOT:
- return;
+ return false;
case SHAPE_IVAR:
- iterate_over_shapes_with_callback(rb_shape_get_parent(shape), callback, itr_data);
+ ASSUME(callback);
+ if (iterate_over_shapes_with_callback(rb_shape_get_parent(shape), callback, itr_data))
+ return true;
VALUE * iv_list;
switch (BUILTIN_TYPE(itr_data->obj)) {
case T_OBJECT:
@@ -1657,15 +1662,22 @@ iterate_over_shapes_with_callback(rb_shape_t *shape, rb_ivar_foreach_callback_fu
}
VALUE val = iv_list[shape->next_iv_index - 1];
if (!UNDEF_P(val)) {
- callback(shape->edge_name, val, itr_data->arg);
+ switch (callback(shape->edge_name, val, itr_data->arg)) {
+ case ST_CHECK:
+ case ST_CONTINUE:
+ break;
+ case ST_STOP:
+ return true;
+ default:
+ rb_bug("unreachable");
+ }
}
- return;
+ return false;
case SHAPE_INITIAL_CAPACITY:
case SHAPE_CAPACITY_CHANGE:
case SHAPE_FROZEN:
case SHAPE_T_OBJECT:
- iterate_over_shapes_with_callback(rb_shape_get_parent(shape), callback, itr_data);
- return;
+ return iterate_over_shapes_with_callback(rb_shape_get_parent(shape), callback, itr_data);
case SHAPE_OBJ_TOO_COMPLEX:
rb_bug("Unreachable");
}