rbs 4.0.3 → 4.1.0.pre.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/c-check.yml +3 -0
  3. data/.github/workflows/dependabot.yml +1 -1
  4. data/.github/workflows/jruby.yml +67 -0
  5. data/.github/workflows/milestone.yml +4 -1
  6. data/.github/workflows/ruby.yml +40 -0
  7. data/.github/workflows/rust.yml +3 -2
  8. data/.github/workflows/truffleruby.yml +54 -0
  9. data/.github/workflows/typecheck.yml +3 -0
  10. data/.github/workflows/wasm.yml +53 -0
  11. data/.github/workflows/windows.yml +3 -0
  12. data/.gitignore +7 -0
  13. data/CHANGELOG.md +0 -8
  14. data/README.md +3 -3
  15. data/Rakefile +118 -3
  16. data/Steepfile +7 -0
  17. data/config.yml +24 -0
  18. data/core/array.rbs +144 -144
  19. data/core/builtin.rbs +7 -6
  20. data/core/class.rbs +5 -3
  21. data/core/enumerable.rbs +109 -109
  22. data/core/enumerator/product.rbs +5 -5
  23. data/core/enumerator.rbs +28 -28
  24. data/core/file.rbs +24 -1018
  25. data/core/file_constants.rbs +463 -0
  26. data/core/file_stat.rbs +534 -0
  27. data/core/hash.rbs +117 -101
  28. data/core/integer.rbs +21 -58
  29. data/core/io.rbs +25 -7
  30. data/core/kernel.rbs +26 -11
  31. data/core/module.rbs +88 -74
  32. data/core/numeric.rbs +3 -0
  33. data/core/object_space/weak_key_map.rbs +7 -7
  34. data/core/range.rbs +23 -23
  35. data/core/rbs/ops.rbs +154 -0
  36. data/core/rbs/unnamed/argf.rbs +3 -3
  37. data/core/ruby_vm.rbs +40 -0
  38. data/core/set.rbs +3 -3
  39. data/core/struct.rbs +16 -16
  40. data/core/thread.rbs +6 -6
  41. data/docs/CONTRIBUTING.md +2 -1
  42. data/docs/inline.md +65 -7
  43. data/docs/rbs_by_example.md +20 -20
  44. data/docs/syntax.md +2 -2
  45. data/docs/wasm_serialization.md +80 -0
  46. data/ext/rbs_extension/ast_translation.c +1298 -956
  47. data/ext/rbs_extension/ast_translation.h +4 -0
  48. data/ext/rbs_extension/class_constants.c +2 -0
  49. data/ext/rbs_extension/class_constants.h +1 -0
  50. data/ext/rbs_extension/extconf.rb +1 -0
  51. data/ext/rbs_extension/main.c +139 -4
  52. data/include/rbs/ast.h +323 -298
  53. data/include/rbs/defines.h +13 -0
  54. data/include/rbs/lexer.h +1 -0
  55. data/include/rbs/serialize.h +39 -0
  56. data/lib/rbs/annotate/rdoc_annotator.rb +27 -31
  57. data/lib/rbs/ast/ruby/annotations.rb +42 -0
  58. data/lib/rbs/ast/ruby/comment_block.rb +6 -4
  59. data/lib/rbs/ast/ruby/declarations.rb +11 -1
  60. data/lib/rbs/ast/ruby/helpers/location_helper.rb +1 -1
  61. data/lib/rbs/ast/ruby/members.rb +40 -1
  62. data/lib/rbs/buffer.rb +48 -11
  63. data/lib/rbs/cli.rb +3 -5
  64. data/lib/rbs/collection/config/lockfile_generator.rb +14 -1
  65. data/lib/rbs/collection/sources/git.rb +6 -0
  66. data/lib/rbs/definition_builder/method_builder.rb +12 -6
  67. data/lib/rbs/environment.rb +10 -3
  68. data/lib/rbs/inline_parser.rb +54 -28
  69. data/lib/rbs/namespace.rb +47 -11
  70. data/lib/rbs/prototype/runtime.rb +2 -0
  71. data/lib/rbs/resolver/type_name_resolver.rb +12 -14
  72. data/lib/rbs/rewriter.rb +70 -0
  73. data/lib/rbs/test/type_check.rb +6 -1
  74. data/lib/rbs/type_name.rb +33 -13
  75. data/lib/rbs/unit_test/type_assertions.rb +9 -0
  76. data/lib/rbs/version.rb +1 -1
  77. data/lib/rbs/wasm/deserializer.rb +213 -0
  78. data/lib/rbs/wasm/location.rb +61 -0
  79. data/lib/rbs/wasm/parser.rb +137 -0
  80. data/lib/rbs/wasm/runtime.rb +217 -0
  81. data/lib/rbs/wasm/serialization_schema.rb +110 -0
  82. data/lib/rbs.rb +14 -2
  83. data/rbs.gemspec +19 -2
  84. data/sig/annotate/rdoc_annotater.rbs +12 -9
  85. data/sig/ast/ruby/annotations.rbs +49 -0
  86. data/sig/ast/ruby/members.rbs +21 -1
  87. data/sig/buffer.rbs +19 -1
  88. data/sig/collection/config/lockfile_generator.rbs +2 -0
  89. data/sig/inline_parser.rbs +2 -0
  90. data/sig/manifest.yaml +0 -1
  91. data/sig/namespace.rbs +20 -0
  92. data/sig/parser.rbs +10 -0
  93. data/sig/resolver/type_name_resolver.rbs +2 -4
  94. data/sig/rewriter.rbs +45 -0
  95. data/sig/typename.rbs +15 -0
  96. data/sig/unit_test/type_assertions.rbs +4 -0
  97. data/sig/wasm/deserializer.rbs +66 -0
  98. data/sig/wasm/serialization_schema.rbs +13 -0
  99. data/src/ast.c +186 -162
  100. data/src/lexer.c +137 -114
  101. data/src/lexer.re +1 -0
  102. data/src/lexstate.c +6 -1
  103. data/src/parser.c +55 -5
  104. data/src/serialize.c +958 -0
  105. data/src/util/rbs_allocator.c +1 -4
  106. data/stdlib/abbrev/0/array.rbs +1 -1
  107. data/stdlib/csv/0/csv.rbs +5 -5
  108. data/stdlib/digest/0/digest.rbs +1 -1
  109. data/stdlib/etc/0/etc.rbs +18 -4
  110. data/stdlib/fileutils/0/fileutils.rbs +21 -21
  111. data/stdlib/json/0/json.rbs +6 -6
  112. data/stdlib/openssl/0/openssl.rbs +7 -7
  113. data/stdlib/resolv/0/resolv.rbs +1 -1
  114. data/stdlib/shellwords/0/shellwords.rbs +1 -1
  115. data/stdlib/stringio/0/stringio.rbs +32 -10
  116. data/stdlib/strscan/0/string_scanner.rbs +74 -55
  117. data/stdlib/tsort/0/cyclic.rbs +1 -1
  118. data/stdlib/tsort/0/interfaces.rbs +8 -8
  119. data/stdlib/tsort/0/tsort.rbs +9 -9
  120. data/stdlib/zlib/0/gzip_reader.rbs +2 -2
  121. data/wasm/README.md +59 -0
  122. data/wasm/rbs_wasm.c +411 -0
  123. metadata +23 -5
  124. data/.vscode/extensions.json +0 -5
  125. data/.vscode/settings.json +0 -19
@@ -23,6 +23,7 @@ rbs_translation_context_t rbs_translation_context_create(rbs_constant_pool_t *co
23
23
  .constant_pool = constant_pool,
24
24
  .buffer = buffer,
25
25
  .encoding = ruby_encoding,
26
+ .reusable_kwargs_hash = rb_hash_new(),
26
27
  };
27
28
  }
28
29
 
@@ -176,6 +177,30 @@ VALUE rbs_type_param_variance_to_ruby(enum rbs_type_param_variance value) {
176
177
  rb_class_new_instance(argc, argv, receiver)
177
178
  #endif
178
179
 
180
+ // Route Namespace / TypeName construction through the Ruby-side
181
+ // flyweight cache (`RBS::Namespace.[]` / `RBS::TypeName.[]`) so that
182
+ // structurally equal values produced by the parser share canonical
183
+ // instances. An in-C trie walk was tried but did not beat
184
+ // `rb_funcallv` on Ruby 4.0+, where method dispatch is well optimized.
185
+ static ID id_intern_brackets;
186
+
187
+ static inline ID intern_brackets(void) {
188
+ if (!id_intern_brackets) id_intern_brackets = rb_intern("[]");
189
+ return id_intern_brackets;
190
+ }
191
+
192
+ static VALUE rbs_intern_namespace(rbs_translation_context_t ctx, rbs_namespace_t *node) {
193
+ VALUE args[2];
194
+ args[0] = rbs_node_list_to_ruby_array(ctx, node->path);
195
+ args[1] = node->absolute ? Qtrue : Qfalse;
196
+ return rb_funcallv(RBS_Namespace, intern_brackets(), 2, args);
197
+ }
198
+
199
+ static VALUE rbs_intern_type_name(VALUE namespace, VALUE name) {
200
+ VALUE args[2] = { namespace, name };
201
+ return rb_funcallv(RBS_TypeName, intern_brackets(), 2, args);
202
+ }
203
+
179
204
  VALUE rbs_struct_to_ruby_value(rbs_translation_context_t ctx, rbs_node_t *instance) {
180
205
  if (instance == NULL) return Qnil;
181
206
 
@@ -183,15 +208,17 @@ VALUE rbs_struct_to_ruby_value(rbs_translation_context_t ctx, rbs_node_t *instan
183
208
  case RBS_AST_ANNOTATION: {
184
209
  rbs_ast_annotation_t *node = (rbs_ast_annotation_t *) instance;
185
210
 
186
- VALUE h = rb_hash_new();
187
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
188
- rb_hash_aset(h, ID2SYM(rb_intern("string")), rbs_string_to_ruby_string(&node->string, ctx.encoding));
211
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
212
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
213
+ VALUE arg_string = rbs_string_to_ruby_string(&node->string, ctx.encoding);
189
214
 
190
- return CLASS_NEW_INSTANCE(
191
- RBS_AST_Annotation,
192
- 1,
193
- &h
194
- );
215
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
216
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
217
+ VALUE h = ctx.reusable_kwargs_hash;
218
+ rb_hash_clear(h);
219
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
220
+ rb_hash_aset(h, ID2SYM(rb_intern("string")), arg_string);
221
+ return CLASS_NEW_INSTANCE(RBS_AST_Annotation, 1, &h);
195
222
  }
196
223
  case RBS_AST_BOOL: {
197
224
  return ((rbs_ast_bool_t *) instance)->value ? Qtrue : Qfalse;
@@ -199,321 +226,395 @@ VALUE rbs_struct_to_ruby_value(rbs_translation_context_t ctx, rbs_node_t *instan
199
226
  case RBS_AST_COMMENT: {
200
227
  rbs_ast_comment_t *node = (rbs_ast_comment_t *) instance;
201
228
 
202
- VALUE h = rb_hash_new();
203
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
204
- rb_hash_aset(h, ID2SYM(rb_intern("string")), rbs_string_to_ruby_string(&node->string, ctx.encoding));
229
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
230
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
231
+ VALUE arg_string = rbs_string_to_ruby_string(&node->string, ctx.encoding);
205
232
 
206
- return CLASS_NEW_INSTANCE(
207
- RBS_AST_Comment,
208
- 1,
209
- &h
210
- );
233
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
234
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
235
+ VALUE h = ctx.reusable_kwargs_hash;
236
+ rb_hash_clear(h);
237
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
238
+ rb_hash_aset(h, ID2SYM(rb_intern("string")), arg_string);
239
+ return CLASS_NEW_INSTANCE(RBS_AST_Comment, 1, &h);
211
240
  }
212
241
  case RBS_AST_DECLARATIONS_CLASS: {
213
242
  rbs_ast_declarations_class_t *node = (rbs_ast_declarations_class_t *) instance;
214
243
 
215
- VALUE h = rb_hash_new();
216
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
217
- rbs_loc *loc = rbs_check_location(location);
218
- rbs_loc_legacy_alloc_children(loc, 5);
219
- rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
220
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
221
- rbs_loc_legacy_add_required_child(loc, rb_intern("end"), (rbs_loc_range) { .start = node->end_range.start_char, .end = node->end_range.end_char });
222
- rbs_loc_legacy_add_optional_child(loc, rb_intern("type_params"), (rbs_loc_range) { .start = node->type_params_range.start_char, .end = node->type_params_range.end_char });
223
- rbs_loc_legacy_add_optional_child(loc, rb_intern("lt"), (rbs_loc_range) { .start = node->lt_range.start_char, .end = node->lt_range.end_char });
224
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
225
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
226
- rb_hash_aset(h, ID2SYM(rb_intern("type_params")), rbs_node_list_to_ruby_array(ctx, node->type_params));
227
- rb_hash_aset(h, ID2SYM(rb_intern("super_class")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->super_class)); // rbs_ast_declarations_class_super
228
- rb_hash_aset(h, ID2SYM(rb_intern("members")), rbs_node_list_to_ruby_array(ctx, node->members));
229
- rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
230
- rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
244
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
245
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
246
+ rbs_loc *loc = rbs_check_location(arg_location);
247
+ {
248
+ rbs_loc_legacy_alloc_children(loc, 5);
249
+ rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
250
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
251
+ rbs_loc_legacy_add_required_child(loc, rb_intern("end"), (rbs_loc_range) { .start = node->end_range.start_char, .end = node->end_range.end_char });
252
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("type_params"), (rbs_loc_range) { .start = node->type_params_range.start_char, .end = node->type_params_range.end_char });
253
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("lt"), (rbs_loc_range) { .start = node->lt_range.start_char, .end = node->lt_range.end_char });
254
+ }
255
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_type_name
256
+ VALUE arg_type_params = rbs_node_list_to_ruby_array(ctx, node->type_params);
257
+ VALUE arg_super_class = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->super_class); // rbs_ast_declarations_class_super
258
+ VALUE arg_members = rbs_node_list_to_ruby_array(ctx, node->members);
259
+ VALUE arg_annotations = rbs_node_list_to_ruby_array(ctx, node->annotations);
260
+ VALUE arg_comment = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment); // rbs_ast_comment
231
261
 
232
262
  rb_funcall(
233
263
  RBS_AST_TypeParam,
234
264
  rb_intern("resolve_variables"),
235
265
  1,
236
- rb_hash_lookup(h, ID2SYM(rb_intern("type_params")))
237
- );
238
- return CLASS_NEW_INSTANCE(
239
- RBS_AST_Declarations_Class,
240
- 1,
241
- &h
242
- );
266
+ arg_type_params
267
+ );
268
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
269
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
270
+ VALUE h = ctx.reusable_kwargs_hash;
271
+ rb_hash_clear(h);
272
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
273
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
274
+ rb_hash_aset(h, ID2SYM(rb_intern("type_params")), arg_type_params);
275
+ rb_hash_aset(h, ID2SYM(rb_intern("super_class")), arg_super_class);
276
+ rb_hash_aset(h, ID2SYM(rb_intern("members")), arg_members);
277
+ rb_hash_aset(h, ID2SYM(rb_intern("annotations")), arg_annotations);
278
+ rb_hash_aset(h, ID2SYM(rb_intern("comment")), arg_comment);
279
+ return CLASS_NEW_INSTANCE(RBS_AST_Declarations_Class, 1, &h);
243
280
  }
244
281
  case RBS_AST_DECLARATIONS_CLASS_SUPER: {
245
282
  rbs_ast_declarations_class_super_t *node = (rbs_ast_declarations_class_super_t *) instance;
246
283
 
247
- VALUE h = rb_hash_new();
248
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
249
- rbs_loc *loc = rbs_check_location(location);
250
- rbs_loc_legacy_alloc_children(loc, 2);
251
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
252
- rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
253
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
254
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
255
- rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));
256
-
257
- return CLASS_NEW_INSTANCE(
258
- RBS_AST_Declarations_Class_Super,
259
- 1,
260
- &h
261
- );
284
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
285
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
286
+ rbs_loc *loc = rbs_check_location(arg_location);
287
+ {
288
+ rbs_loc_legacy_alloc_children(loc, 2);
289
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
290
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
291
+ }
292
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_type_name
293
+ VALUE arg_args = rbs_node_list_to_ruby_array(ctx, node->args);
294
+
295
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
296
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
297
+ VALUE h = ctx.reusable_kwargs_hash;
298
+ rb_hash_clear(h);
299
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
300
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
301
+ rb_hash_aset(h, ID2SYM(rb_intern("args")), arg_args);
302
+ return CLASS_NEW_INSTANCE(RBS_AST_Declarations_Class_Super, 1, &h);
262
303
  }
263
304
  case RBS_AST_DECLARATIONS_CLASS_ALIAS: {
264
305
  rbs_ast_declarations_class_alias_t *node = (rbs_ast_declarations_class_alias_t *) instance;
265
306
 
266
- VALUE h = rb_hash_new();
267
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
268
- rbs_loc *loc = rbs_check_location(location);
269
- rbs_loc_legacy_alloc_children(loc, 4);
270
- rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
271
- rbs_loc_legacy_add_required_child(loc, rb_intern("new_name"), (rbs_loc_range) { .start = node->new_name_range.start_char, .end = node->new_name_range.end_char });
272
- rbs_loc_legacy_add_required_child(loc, rb_intern("eq"), (rbs_loc_range) { .start = node->eq_range.start_char, .end = node->eq_range.end_char });
273
- rbs_loc_legacy_add_required_child(loc, rb_intern("old_name"), (rbs_loc_range) { .start = node->old_name_range.start_char, .end = node->old_name_range.end_char });
274
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
275
- rb_hash_aset(h, ID2SYM(rb_intern("new_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->new_name)); // rbs_type_name
276
- rb_hash_aset(h, ID2SYM(rb_intern("old_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->old_name)); // rbs_type_name
277
- rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
278
- rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
279
-
280
- return CLASS_NEW_INSTANCE(
281
- RBS_AST_Declarations_ClassAlias,
282
- 1,
283
- &h
284
- );
307
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
308
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
309
+ rbs_loc *loc = rbs_check_location(arg_location);
310
+ {
311
+ rbs_loc_legacy_alloc_children(loc, 4);
312
+ rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
313
+ rbs_loc_legacy_add_required_child(loc, rb_intern("new_name"), (rbs_loc_range) { .start = node->new_name_range.start_char, .end = node->new_name_range.end_char });
314
+ rbs_loc_legacy_add_required_child(loc, rb_intern("eq"), (rbs_loc_range) { .start = node->eq_range.start_char, .end = node->eq_range.end_char });
315
+ rbs_loc_legacy_add_required_child(loc, rb_intern("old_name"), (rbs_loc_range) { .start = node->old_name_range.start_char, .end = node->old_name_range.end_char });
316
+ }
317
+ VALUE arg_new_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->new_name); // rbs_type_name
318
+ VALUE arg_old_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->old_name); // rbs_type_name
319
+ VALUE arg_comment = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment); // rbs_ast_comment
320
+ VALUE arg_annotations = rbs_node_list_to_ruby_array(ctx, node->annotations);
321
+
322
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
323
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
324
+ VALUE h = ctx.reusable_kwargs_hash;
325
+ rb_hash_clear(h);
326
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
327
+ rb_hash_aset(h, ID2SYM(rb_intern("new_name")), arg_new_name);
328
+ rb_hash_aset(h, ID2SYM(rb_intern("old_name")), arg_old_name);
329
+ rb_hash_aset(h, ID2SYM(rb_intern("comment")), arg_comment);
330
+ rb_hash_aset(h, ID2SYM(rb_intern("annotations")), arg_annotations);
331
+ return CLASS_NEW_INSTANCE(RBS_AST_Declarations_ClassAlias, 1, &h);
285
332
  }
286
333
  case RBS_AST_DECLARATIONS_CONSTANT: {
287
334
  rbs_ast_declarations_constant_t *node = (rbs_ast_declarations_constant_t *) instance;
288
335
 
289
- VALUE h = rb_hash_new();
290
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
291
- rbs_loc *loc = rbs_check_location(location);
292
- rbs_loc_legacy_alloc_children(loc, 2);
293
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
294
- rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
295
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
296
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
297
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
298
- rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
299
- rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
300
-
301
- return CLASS_NEW_INSTANCE(
302
- RBS_AST_Declarations_Constant,
303
- 1,
304
- &h
305
- );
336
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
337
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
338
+ rbs_loc *loc = rbs_check_location(arg_location);
339
+ {
340
+ rbs_loc_legacy_alloc_children(loc, 2);
341
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
342
+ rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
343
+ }
344
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_type_name
345
+ VALUE arg_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type); // rbs_node
346
+ VALUE arg_comment = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment); // rbs_ast_comment
347
+ VALUE arg_annotations = rbs_node_list_to_ruby_array(ctx, node->annotations);
348
+
349
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
350
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
351
+ VALUE h = ctx.reusable_kwargs_hash;
352
+ rb_hash_clear(h);
353
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
354
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
355
+ rb_hash_aset(h, ID2SYM(rb_intern("type")), arg_type);
356
+ rb_hash_aset(h, ID2SYM(rb_intern("comment")), arg_comment);
357
+ rb_hash_aset(h, ID2SYM(rb_intern("annotations")), arg_annotations);
358
+ return CLASS_NEW_INSTANCE(RBS_AST_Declarations_Constant, 1, &h);
306
359
  }
307
360
  case RBS_AST_DECLARATIONS_GLOBAL: {
308
361
  rbs_ast_declarations_global_t *node = (rbs_ast_declarations_global_t *) instance;
309
362
 
310
- VALUE h = rb_hash_new();
311
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
312
- rbs_loc *loc = rbs_check_location(location);
313
- rbs_loc_legacy_alloc_children(loc, 2);
314
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
315
- rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
316
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
317
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol
318
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
319
- rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
320
- rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
321
-
322
- return CLASS_NEW_INSTANCE(
323
- RBS_AST_Declarations_Global,
324
- 1,
325
- &h
326
- );
363
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
364
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
365
+ rbs_loc *loc = rbs_check_location(arg_location);
366
+ {
367
+ rbs_loc_legacy_alloc_children(loc, 2);
368
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
369
+ rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
370
+ }
371
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_ast_symbol
372
+ VALUE arg_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type); // rbs_node
373
+ VALUE arg_comment = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment); // rbs_ast_comment
374
+ VALUE arg_annotations = rbs_node_list_to_ruby_array(ctx, node->annotations);
375
+
376
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
377
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
378
+ VALUE h = ctx.reusable_kwargs_hash;
379
+ rb_hash_clear(h);
380
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
381
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
382
+ rb_hash_aset(h, ID2SYM(rb_intern("type")), arg_type);
383
+ rb_hash_aset(h, ID2SYM(rb_intern("comment")), arg_comment);
384
+ rb_hash_aset(h, ID2SYM(rb_intern("annotations")), arg_annotations);
385
+ return CLASS_NEW_INSTANCE(RBS_AST_Declarations_Global, 1, &h);
327
386
  }
328
387
  case RBS_AST_DECLARATIONS_INTERFACE: {
329
388
  rbs_ast_declarations_interface_t *node = (rbs_ast_declarations_interface_t *) instance;
330
389
 
331
- VALUE h = rb_hash_new();
332
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
333
- rbs_loc *loc = rbs_check_location(location);
334
- rbs_loc_legacy_alloc_children(loc, 4);
335
- rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
336
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
337
- rbs_loc_legacy_add_required_child(loc, rb_intern("end"), (rbs_loc_range) { .start = node->end_range.start_char, .end = node->end_range.end_char });
338
- rbs_loc_legacy_add_optional_child(loc, rb_intern("type_params"), (rbs_loc_range) { .start = node->type_params_range.start_char, .end = node->type_params_range.end_char });
339
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
340
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
341
- rb_hash_aset(h, ID2SYM(rb_intern("type_params")), rbs_node_list_to_ruby_array(ctx, node->type_params));
342
- rb_hash_aset(h, ID2SYM(rb_intern("members")), rbs_node_list_to_ruby_array(ctx, node->members));
343
- rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
344
- rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
390
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
391
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
392
+ rbs_loc *loc = rbs_check_location(arg_location);
393
+ {
394
+ rbs_loc_legacy_alloc_children(loc, 4);
395
+ rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
396
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
397
+ rbs_loc_legacy_add_required_child(loc, rb_intern("end"), (rbs_loc_range) { .start = node->end_range.start_char, .end = node->end_range.end_char });
398
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("type_params"), (rbs_loc_range) { .start = node->type_params_range.start_char, .end = node->type_params_range.end_char });
399
+ }
400
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_type_name
401
+ VALUE arg_type_params = rbs_node_list_to_ruby_array(ctx, node->type_params);
402
+ VALUE arg_members = rbs_node_list_to_ruby_array(ctx, node->members);
403
+ VALUE arg_annotations = rbs_node_list_to_ruby_array(ctx, node->annotations);
404
+ VALUE arg_comment = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment); // rbs_ast_comment
345
405
 
346
406
  rb_funcall(
347
407
  RBS_AST_TypeParam,
348
408
  rb_intern("resolve_variables"),
349
409
  1,
350
- rb_hash_lookup(h, ID2SYM(rb_intern("type_params")))
351
- );
352
- return CLASS_NEW_INSTANCE(
353
- RBS_AST_Declarations_Interface,
354
- 1,
355
- &h
410
+ arg_type_params
356
411
  );
412
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
413
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
414
+ VALUE h = ctx.reusable_kwargs_hash;
415
+ rb_hash_clear(h);
416
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
417
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
418
+ rb_hash_aset(h, ID2SYM(rb_intern("type_params")), arg_type_params);
419
+ rb_hash_aset(h, ID2SYM(rb_intern("members")), arg_members);
420
+ rb_hash_aset(h, ID2SYM(rb_intern("annotations")), arg_annotations);
421
+ rb_hash_aset(h, ID2SYM(rb_intern("comment")), arg_comment);
422
+ return CLASS_NEW_INSTANCE(RBS_AST_Declarations_Interface, 1, &h);
357
423
  }
358
424
  case RBS_AST_DECLARATIONS_MODULE: {
359
425
  rbs_ast_declarations_module_t *node = (rbs_ast_declarations_module_t *) instance;
360
426
 
361
- VALUE h = rb_hash_new();
362
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
363
- rbs_loc *loc = rbs_check_location(location);
364
- rbs_loc_legacy_alloc_children(loc, 6);
365
- rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
366
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
367
- rbs_loc_legacy_add_required_child(loc, rb_intern("end"), (rbs_loc_range) { .start = node->end_range.start_char, .end = node->end_range.end_char });
368
- rbs_loc_legacy_add_optional_child(loc, rb_intern("type_params"), (rbs_loc_range) { .start = node->type_params_range.start_char, .end = node->type_params_range.end_char });
369
- rbs_loc_legacy_add_optional_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
370
- rbs_loc_legacy_add_optional_child(loc, rb_intern("self_types"), (rbs_loc_range) { .start = node->self_types_range.start_char, .end = node->self_types_range.end_char });
371
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
372
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
373
- rb_hash_aset(h, ID2SYM(rb_intern("type_params")), rbs_node_list_to_ruby_array(ctx, node->type_params));
374
- rb_hash_aset(h, ID2SYM(rb_intern("self_types")), rbs_node_list_to_ruby_array(ctx, node->self_types));
375
- rb_hash_aset(h, ID2SYM(rb_intern("members")), rbs_node_list_to_ruby_array(ctx, node->members));
376
- rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
377
- rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
427
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
428
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
429
+ rbs_loc *loc = rbs_check_location(arg_location);
430
+ {
431
+ rbs_loc_legacy_alloc_children(loc, 6);
432
+ rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
433
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
434
+ rbs_loc_legacy_add_required_child(loc, rb_intern("end"), (rbs_loc_range) { .start = node->end_range.start_char, .end = node->end_range.end_char });
435
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("type_params"), (rbs_loc_range) { .start = node->type_params_range.start_char, .end = node->type_params_range.end_char });
436
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
437
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("self_types"), (rbs_loc_range) { .start = node->self_types_range.start_char, .end = node->self_types_range.end_char });
438
+ }
439
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_type_name
440
+ VALUE arg_type_params = rbs_node_list_to_ruby_array(ctx, node->type_params);
441
+ VALUE arg_self_types = rbs_node_list_to_ruby_array(ctx, node->self_types);
442
+ VALUE arg_members = rbs_node_list_to_ruby_array(ctx, node->members);
443
+ VALUE arg_annotations = rbs_node_list_to_ruby_array(ctx, node->annotations);
444
+ VALUE arg_comment = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment); // rbs_ast_comment
378
445
 
379
446
  rb_funcall(
380
447
  RBS_AST_TypeParam,
381
448
  rb_intern("resolve_variables"),
382
449
  1,
383
- rb_hash_lookup(h, ID2SYM(rb_intern("type_params")))
384
- );
385
- return CLASS_NEW_INSTANCE(
386
- RBS_AST_Declarations_Module,
387
- 1,
388
- &h
389
- );
450
+ arg_type_params
451
+ );
452
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
453
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
454
+ VALUE h = ctx.reusable_kwargs_hash;
455
+ rb_hash_clear(h);
456
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
457
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
458
+ rb_hash_aset(h, ID2SYM(rb_intern("type_params")), arg_type_params);
459
+ rb_hash_aset(h, ID2SYM(rb_intern("self_types")), arg_self_types);
460
+ rb_hash_aset(h, ID2SYM(rb_intern("members")), arg_members);
461
+ rb_hash_aset(h, ID2SYM(rb_intern("annotations")), arg_annotations);
462
+ rb_hash_aset(h, ID2SYM(rb_intern("comment")), arg_comment);
463
+ return CLASS_NEW_INSTANCE(RBS_AST_Declarations_Module, 1, &h);
390
464
  }
391
465
  case RBS_AST_DECLARATIONS_MODULE_SELF: {
392
466
  rbs_ast_declarations_module_self_t *node = (rbs_ast_declarations_module_self_t *) instance;
393
467
 
394
- VALUE h = rb_hash_new();
395
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
396
- rbs_loc *loc = rbs_check_location(location);
397
- rbs_loc_legacy_alloc_children(loc, 2);
398
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
399
- rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
400
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
401
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
402
- rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));
403
-
404
- return CLASS_NEW_INSTANCE(
405
- RBS_AST_Declarations_Module_Self,
406
- 1,
407
- &h
408
- );
468
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
469
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
470
+ rbs_loc *loc = rbs_check_location(arg_location);
471
+ {
472
+ rbs_loc_legacy_alloc_children(loc, 2);
473
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
474
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
475
+ }
476
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_type_name
477
+ VALUE arg_args = rbs_node_list_to_ruby_array(ctx, node->args);
478
+
479
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
480
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
481
+ VALUE h = ctx.reusable_kwargs_hash;
482
+ rb_hash_clear(h);
483
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
484
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
485
+ rb_hash_aset(h, ID2SYM(rb_intern("args")), arg_args);
486
+ return CLASS_NEW_INSTANCE(RBS_AST_Declarations_Module_Self, 1, &h);
409
487
  }
410
488
  case RBS_AST_DECLARATIONS_MODULE_ALIAS: {
411
489
  rbs_ast_declarations_module_alias_t *node = (rbs_ast_declarations_module_alias_t *) instance;
412
490
 
413
- VALUE h = rb_hash_new();
414
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
415
- rbs_loc *loc = rbs_check_location(location);
416
- rbs_loc_legacy_alloc_children(loc, 4);
417
- rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
418
- rbs_loc_legacy_add_required_child(loc, rb_intern("new_name"), (rbs_loc_range) { .start = node->new_name_range.start_char, .end = node->new_name_range.end_char });
419
- rbs_loc_legacy_add_required_child(loc, rb_intern("eq"), (rbs_loc_range) { .start = node->eq_range.start_char, .end = node->eq_range.end_char });
420
- rbs_loc_legacy_add_required_child(loc, rb_intern("old_name"), (rbs_loc_range) { .start = node->old_name_range.start_char, .end = node->old_name_range.end_char });
421
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
422
- rb_hash_aset(h, ID2SYM(rb_intern("new_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->new_name)); // rbs_type_name
423
- rb_hash_aset(h, ID2SYM(rb_intern("old_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->old_name)); // rbs_type_name
424
- rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
425
- rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
426
-
427
- return CLASS_NEW_INSTANCE(
428
- RBS_AST_Declarations_ModuleAlias,
429
- 1,
430
- &h
431
- );
491
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
492
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
493
+ rbs_loc *loc = rbs_check_location(arg_location);
494
+ {
495
+ rbs_loc_legacy_alloc_children(loc, 4);
496
+ rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
497
+ rbs_loc_legacy_add_required_child(loc, rb_intern("new_name"), (rbs_loc_range) { .start = node->new_name_range.start_char, .end = node->new_name_range.end_char });
498
+ rbs_loc_legacy_add_required_child(loc, rb_intern("eq"), (rbs_loc_range) { .start = node->eq_range.start_char, .end = node->eq_range.end_char });
499
+ rbs_loc_legacy_add_required_child(loc, rb_intern("old_name"), (rbs_loc_range) { .start = node->old_name_range.start_char, .end = node->old_name_range.end_char });
500
+ }
501
+ VALUE arg_new_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->new_name); // rbs_type_name
502
+ VALUE arg_old_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->old_name); // rbs_type_name
503
+ VALUE arg_comment = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment); // rbs_ast_comment
504
+ VALUE arg_annotations = rbs_node_list_to_ruby_array(ctx, node->annotations);
505
+
506
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
507
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
508
+ VALUE h = ctx.reusable_kwargs_hash;
509
+ rb_hash_clear(h);
510
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
511
+ rb_hash_aset(h, ID2SYM(rb_intern("new_name")), arg_new_name);
512
+ rb_hash_aset(h, ID2SYM(rb_intern("old_name")), arg_old_name);
513
+ rb_hash_aset(h, ID2SYM(rb_intern("comment")), arg_comment);
514
+ rb_hash_aset(h, ID2SYM(rb_intern("annotations")), arg_annotations);
515
+ return CLASS_NEW_INSTANCE(RBS_AST_Declarations_ModuleAlias, 1, &h);
432
516
  }
433
517
  case RBS_AST_DECLARATIONS_TYPE_ALIAS: {
434
518
  rbs_ast_declarations_type_alias_t *node = (rbs_ast_declarations_type_alias_t *) instance;
435
519
 
436
- VALUE h = rb_hash_new();
437
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
438
- rbs_loc *loc = rbs_check_location(location);
439
- rbs_loc_legacy_alloc_children(loc, 4);
440
- rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
441
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
442
- rbs_loc_legacy_add_required_child(loc, rb_intern("eq"), (rbs_loc_range) { .start = node->eq_range.start_char, .end = node->eq_range.end_char });
443
- rbs_loc_legacy_add_optional_child(loc, rb_intern("type_params"), (rbs_loc_range) { .start = node->type_params_range.start_char, .end = node->type_params_range.end_char });
444
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
445
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
446
- rb_hash_aset(h, ID2SYM(rb_intern("type_params")), rbs_node_list_to_ruby_array(ctx, node->type_params));
447
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
448
- rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
449
- rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
520
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
521
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
522
+ rbs_loc *loc = rbs_check_location(arg_location);
523
+ {
524
+ rbs_loc_legacy_alloc_children(loc, 4);
525
+ rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
526
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
527
+ rbs_loc_legacy_add_required_child(loc, rb_intern("eq"), (rbs_loc_range) { .start = node->eq_range.start_char, .end = node->eq_range.end_char });
528
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("type_params"), (rbs_loc_range) { .start = node->type_params_range.start_char, .end = node->type_params_range.end_char });
529
+ }
530
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_type_name
531
+ VALUE arg_type_params = rbs_node_list_to_ruby_array(ctx, node->type_params);
532
+ VALUE arg_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type); // rbs_node
533
+ VALUE arg_annotations = rbs_node_list_to_ruby_array(ctx, node->annotations);
534
+ VALUE arg_comment = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment); // rbs_ast_comment
450
535
 
451
536
  rb_funcall(
452
537
  RBS_AST_TypeParam,
453
538
  rb_intern("resolve_variables"),
454
539
  1,
455
- rb_hash_lookup(h, ID2SYM(rb_intern("type_params")))
456
- );
457
- return CLASS_NEW_INSTANCE(
458
- RBS_AST_Declarations_TypeAlias,
459
- 1,
460
- &h
540
+ arg_type_params
461
541
  );
542
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
543
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
544
+ VALUE h = ctx.reusable_kwargs_hash;
545
+ rb_hash_clear(h);
546
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
547
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
548
+ rb_hash_aset(h, ID2SYM(rb_intern("type_params")), arg_type_params);
549
+ rb_hash_aset(h, ID2SYM(rb_intern("type")), arg_type);
550
+ rb_hash_aset(h, ID2SYM(rb_intern("annotations")), arg_annotations);
551
+ rb_hash_aset(h, ID2SYM(rb_intern("comment")), arg_comment);
552
+ return CLASS_NEW_INSTANCE(RBS_AST_Declarations_TypeAlias, 1, &h);
462
553
  }
463
554
  case RBS_AST_DIRECTIVES_USE: {
464
555
  rbs_ast_directives_use_t *node = (rbs_ast_directives_use_t *) instance;
465
556
 
466
- VALUE h = rb_hash_new();
467
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
468
- rbs_loc *loc = rbs_check_location(location);
469
- rbs_loc_legacy_alloc_children(loc, 1);
470
- rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
471
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
472
- rb_hash_aset(h, ID2SYM(rb_intern("clauses")), rbs_node_list_to_ruby_array(ctx, node->clauses));
473
-
474
- return CLASS_NEW_INSTANCE(
475
- RBS_AST_Directives_Use,
476
- 1,
477
- &h
478
- );
557
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
558
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
559
+ rbs_loc *loc = rbs_check_location(arg_location);
560
+ {
561
+ rbs_loc_legacy_alloc_children(loc, 1);
562
+ rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
563
+ }
564
+ VALUE arg_clauses = rbs_node_list_to_ruby_array(ctx, node->clauses);
565
+
566
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
567
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
568
+ VALUE h = ctx.reusable_kwargs_hash;
569
+ rb_hash_clear(h);
570
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
571
+ rb_hash_aset(h, ID2SYM(rb_intern("clauses")), arg_clauses);
572
+ return CLASS_NEW_INSTANCE(RBS_AST_Directives_Use, 1, &h);
479
573
  }
480
574
  case RBS_AST_DIRECTIVES_USE_SINGLE_CLAUSE: {
481
575
  rbs_ast_directives_use_single_clause_t *node = (rbs_ast_directives_use_single_clause_t *) instance;
482
576
 
483
- VALUE h = rb_hash_new();
484
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
485
- rbs_loc *loc = rbs_check_location(location);
486
- rbs_loc_legacy_alloc_children(loc, 3);
487
- rbs_loc_legacy_add_required_child(loc, rb_intern("type_name"), (rbs_loc_range) { .start = node->type_name_range.start_char, .end = node->type_name_range.end_char });
488
- rbs_loc_legacy_add_optional_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
489
- rbs_loc_legacy_add_optional_child(loc, rb_intern("new_name"), (rbs_loc_range) { .start = node->new_name_range.start_char, .end = node->new_name_range.end_char });
490
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
491
- rb_hash_aset(h, ID2SYM(rb_intern("type_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type_name)); // rbs_type_name
492
- rb_hash_aset(h, ID2SYM(rb_intern("new_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->new_name)); // rbs_ast_symbol
493
-
494
- return CLASS_NEW_INSTANCE(
495
- RBS_AST_Directives_Use_SingleClause,
496
- 1,
497
- &h
498
- );
577
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
578
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
579
+ rbs_loc *loc = rbs_check_location(arg_location);
580
+ {
581
+ rbs_loc_legacy_alloc_children(loc, 3);
582
+ rbs_loc_legacy_add_required_child(loc, rb_intern("type_name"), (rbs_loc_range) { .start = node->type_name_range.start_char, .end = node->type_name_range.end_char });
583
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
584
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("new_name"), (rbs_loc_range) { .start = node->new_name_range.start_char, .end = node->new_name_range.end_char });
585
+ }
586
+ VALUE arg_type_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type_name); // rbs_type_name
587
+ VALUE arg_new_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->new_name); // rbs_ast_symbol
588
+
589
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
590
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
591
+ VALUE h = ctx.reusable_kwargs_hash;
592
+ rb_hash_clear(h);
593
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
594
+ rb_hash_aset(h, ID2SYM(rb_intern("type_name")), arg_type_name);
595
+ rb_hash_aset(h, ID2SYM(rb_intern("new_name")), arg_new_name);
596
+ return CLASS_NEW_INSTANCE(RBS_AST_Directives_Use_SingleClause, 1, &h);
499
597
  }
500
598
  case RBS_AST_DIRECTIVES_USE_WILDCARD_CLAUSE: {
501
599
  rbs_ast_directives_use_wildcard_clause_t *node = (rbs_ast_directives_use_wildcard_clause_t *) instance;
502
600
 
503
- VALUE h = rb_hash_new();
504
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
505
- rbs_loc *loc = rbs_check_location(location);
506
- rbs_loc_legacy_alloc_children(loc, 2);
507
- rbs_loc_legacy_add_required_child(loc, rb_intern("namespace"), (rbs_loc_range) { .start = node->namespace_range.start_char, .end = node->namespace_range.end_char });
508
- rbs_loc_legacy_add_required_child(loc, rb_intern("star"), (rbs_loc_range) { .start = node->star_range.start_char, .end = node->star_range.end_char });
509
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
510
- rb_hash_aset(h, ID2SYM(rb_intern("namespace")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->rbs_namespace)); // rbs_namespace
511
-
512
- return CLASS_NEW_INSTANCE(
513
- RBS_AST_Directives_Use_WildcardClause,
514
- 1,
515
- &h
516
- );
601
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
602
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
603
+ rbs_loc *loc = rbs_check_location(arg_location);
604
+ {
605
+ rbs_loc_legacy_alloc_children(loc, 2);
606
+ rbs_loc_legacy_add_required_child(loc, rb_intern("namespace"), (rbs_loc_range) { .start = node->namespace_range.start_char, .end = node->namespace_range.end_char });
607
+ rbs_loc_legacy_add_required_child(loc, rb_intern("star"), (rbs_loc_range) { .start = node->star_range.start_char, .end = node->star_range.end_char });
608
+ }
609
+ VALUE arg_namespace = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->rbs_namespace); // rbs_namespace
610
+
611
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
612
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
613
+ VALUE h = ctx.reusable_kwargs_hash;
614
+ rb_hash_clear(h);
615
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
616
+ rb_hash_aset(h, ID2SYM(rb_intern("namespace")), arg_namespace);
617
+ return CLASS_NEW_INSTANCE(RBS_AST_Directives_Use_WildcardClause, 1, &h);
517
618
  }
518
619
  case RBS_AST_INTEGER: {
519
620
  rbs_ast_integer_t *integer_node = (rbs_ast_integer_t *) instance;
@@ -526,523 +627,707 @@ VALUE rbs_struct_to_ruby_value(rbs_translation_context_t ctx, rbs_node_t *instan
526
627
  case RBS_AST_MEMBERS_ALIAS: {
527
628
  rbs_ast_members_alias_t *node = (rbs_ast_members_alias_t *) instance;
528
629
 
529
- VALUE h = rb_hash_new();
530
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
531
- rbs_loc *loc = rbs_check_location(location);
532
- rbs_loc_legacy_alloc_children(loc, 5);
533
- rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
534
- rbs_loc_legacy_add_required_child(loc, rb_intern("new_name"), (rbs_loc_range) { .start = node->new_name_range.start_char, .end = node->new_name_range.end_char });
535
- rbs_loc_legacy_add_required_child(loc, rb_intern("old_name"), (rbs_loc_range) { .start = node->old_name_range.start_char, .end = node->old_name_range.end_char });
536
- rbs_loc_legacy_add_optional_child(loc, rb_intern("new_kind"), (rbs_loc_range) { .start = node->new_kind_range.start_char, .end = node->new_kind_range.end_char });
537
- rbs_loc_legacy_add_optional_child(loc, rb_intern("old_kind"), (rbs_loc_range) { .start = node->old_kind_range.start_char, .end = node->old_kind_range.end_char });
538
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
539
- rb_hash_aset(h, ID2SYM(rb_intern("new_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->new_name)); // rbs_ast_symbol
540
- rb_hash_aset(h, ID2SYM(rb_intern("old_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->old_name)); // rbs_ast_symbol
541
- rb_hash_aset(h, ID2SYM(rb_intern("kind")), rbs_alias_kind_to_ruby(node->kind)); // alias_kind
542
- rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
543
- rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
544
-
545
- return CLASS_NEW_INSTANCE(
546
- RBS_AST_Members_Alias,
547
- 1,
548
- &h
549
- );
630
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
631
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
632
+ rbs_loc *loc = rbs_check_location(arg_location);
633
+ {
634
+ rbs_loc_legacy_alloc_children(loc, 5);
635
+ rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
636
+ rbs_loc_legacy_add_required_child(loc, rb_intern("new_name"), (rbs_loc_range) { .start = node->new_name_range.start_char, .end = node->new_name_range.end_char });
637
+ rbs_loc_legacy_add_required_child(loc, rb_intern("old_name"), (rbs_loc_range) { .start = node->old_name_range.start_char, .end = node->old_name_range.end_char });
638
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("new_kind"), (rbs_loc_range) { .start = node->new_kind_range.start_char, .end = node->new_kind_range.end_char });
639
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("old_kind"), (rbs_loc_range) { .start = node->old_kind_range.start_char, .end = node->old_kind_range.end_char });
640
+ }
641
+ VALUE arg_new_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->new_name); // rbs_ast_symbol
642
+ VALUE arg_old_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->old_name); // rbs_ast_symbol
643
+ VALUE arg_kind = rbs_alias_kind_to_ruby(node->kind); // alias_kind
644
+ VALUE arg_annotations = rbs_node_list_to_ruby_array(ctx, node->annotations);
645
+ VALUE arg_comment = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment); // rbs_ast_comment
646
+
647
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
648
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
649
+ VALUE h = ctx.reusable_kwargs_hash;
650
+ rb_hash_clear(h);
651
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
652
+ rb_hash_aset(h, ID2SYM(rb_intern("new_name")), arg_new_name);
653
+ rb_hash_aset(h, ID2SYM(rb_intern("old_name")), arg_old_name);
654
+ rb_hash_aset(h, ID2SYM(rb_intern("kind")), arg_kind);
655
+ rb_hash_aset(h, ID2SYM(rb_intern("annotations")), arg_annotations);
656
+ rb_hash_aset(h, ID2SYM(rb_intern("comment")), arg_comment);
657
+ return CLASS_NEW_INSTANCE(RBS_AST_Members_Alias, 1, &h);
550
658
  }
551
659
  case RBS_AST_MEMBERS_ATTR_ACCESSOR: {
552
660
  rbs_ast_members_attr_accessor_t *node = (rbs_ast_members_attr_accessor_t *) instance;
553
661
 
554
- VALUE h = rb_hash_new();
555
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
556
- rbs_loc *loc = rbs_check_location(location);
557
- rbs_loc_legacy_alloc_children(loc, 7);
558
- rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
559
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
560
- rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
561
- rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
562
- rbs_loc_legacy_add_optional_child(loc, rb_intern("ivar"), (rbs_loc_range) { .start = node->ivar_range.start_char, .end = node->ivar_range.end_char });
563
- rbs_loc_legacy_add_optional_child(loc, rb_intern("ivar_name"), (rbs_loc_range) { .start = node->ivar_name_range.start_char, .end = node->ivar_name_range.end_char });
564
- rbs_loc_legacy_add_optional_child(loc, rb_intern("visibility"), (rbs_loc_range) { .start = node->visibility_range.start_char, .end = node->visibility_range.end_char });
565
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
566
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol
567
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
568
- rb_hash_aset(h, ID2SYM(rb_intern("ivar_name")), rbs_attr_ivar_name_to_ruby(ctx, node->ivar_name)); // rbs_attr_ivar_name_t
569
- rb_hash_aset(h, ID2SYM(rb_intern("kind")), rbs_attribute_kind_to_ruby(node->kind)); // attribute_kind
570
- rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
571
- rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
572
- rb_hash_aset(h, ID2SYM(rb_intern("visibility")), rbs_attribute_visibility_to_ruby(node->visibility)); // attribute_visibility
573
-
574
- return CLASS_NEW_INSTANCE(
575
- RBS_AST_Members_AttrAccessor,
576
- 1,
577
- &h
578
- );
662
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
663
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
664
+ rbs_loc *loc = rbs_check_location(arg_location);
665
+ {
666
+ rbs_loc_legacy_alloc_children(loc, 7);
667
+ rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
668
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
669
+ rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
670
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
671
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("ivar"), (rbs_loc_range) { .start = node->ivar_range.start_char, .end = node->ivar_range.end_char });
672
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("ivar_name"), (rbs_loc_range) { .start = node->ivar_name_range.start_char, .end = node->ivar_name_range.end_char });
673
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("visibility"), (rbs_loc_range) { .start = node->visibility_range.start_char, .end = node->visibility_range.end_char });
674
+ }
675
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_ast_symbol
676
+ VALUE arg_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type); // rbs_node
677
+ VALUE arg_ivar_name = rbs_attr_ivar_name_to_ruby(ctx, node->ivar_name); // rbs_attr_ivar_name_t
678
+ VALUE arg_kind = rbs_attribute_kind_to_ruby(node->kind); // attribute_kind
679
+ VALUE arg_annotations = rbs_node_list_to_ruby_array(ctx, node->annotations);
680
+ VALUE arg_comment = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment); // rbs_ast_comment
681
+ VALUE arg_visibility = rbs_attribute_visibility_to_ruby(node->visibility); // attribute_visibility
682
+
683
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
684
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
685
+ VALUE h = ctx.reusable_kwargs_hash;
686
+ rb_hash_clear(h);
687
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
688
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
689
+ rb_hash_aset(h, ID2SYM(rb_intern("type")), arg_type);
690
+ rb_hash_aset(h, ID2SYM(rb_intern("ivar_name")), arg_ivar_name);
691
+ rb_hash_aset(h, ID2SYM(rb_intern("kind")), arg_kind);
692
+ rb_hash_aset(h, ID2SYM(rb_intern("annotations")), arg_annotations);
693
+ rb_hash_aset(h, ID2SYM(rb_intern("comment")), arg_comment);
694
+ rb_hash_aset(h, ID2SYM(rb_intern("visibility")), arg_visibility);
695
+ return CLASS_NEW_INSTANCE(RBS_AST_Members_AttrAccessor, 1, &h);
579
696
  }
580
697
  case RBS_AST_MEMBERS_ATTR_READER: {
581
698
  rbs_ast_members_attr_reader_t *node = (rbs_ast_members_attr_reader_t *) instance;
582
699
 
583
- VALUE h = rb_hash_new();
584
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
585
- rbs_loc *loc = rbs_check_location(location);
586
- rbs_loc_legacy_alloc_children(loc, 7);
587
- rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
588
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
589
- rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
590
- rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
591
- rbs_loc_legacy_add_optional_child(loc, rb_intern("ivar"), (rbs_loc_range) { .start = node->ivar_range.start_char, .end = node->ivar_range.end_char });
592
- rbs_loc_legacy_add_optional_child(loc, rb_intern("ivar_name"), (rbs_loc_range) { .start = node->ivar_name_range.start_char, .end = node->ivar_name_range.end_char });
593
- rbs_loc_legacy_add_optional_child(loc, rb_intern("visibility"), (rbs_loc_range) { .start = node->visibility_range.start_char, .end = node->visibility_range.end_char });
594
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
595
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol
596
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
597
- rb_hash_aset(h, ID2SYM(rb_intern("ivar_name")), rbs_attr_ivar_name_to_ruby(ctx, node->ivar_name)); // rbs_attr_ivar_name_t
598
- rb_hash_aset(h, ID2SYM(rb_intern("kind")), rbs_attribute_kind_to_ruby(node->kind)); // attribute_kind
599
- rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
600
- rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
601
- rb_hash_aset(h, ID2SYM(rb_intern("visibility")), rbs_attribute_visibility_to_ruby(node->visibility)); // attribute_visibility
602
-
603
- return CLASS_NEW_INSTANCE(
604
- RBS_AST_Members_AttrReader,
605
- 1,
606
- &h
607
- );
700
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
701
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
702
+ rbs_loc *loc = rbs_check_location(arg_location);
703
+ {
704
+ rbs_loc_legacy_alloc_children(loc, 7);
705
+ rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
706
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
707
+ rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
708
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
709
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("ivar"), (rbs_loc_range) { .start = node->ivar_range.start_char, .end = node->ivar_range.end_char });
710
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("ivar_name"), (rbs_loc_range) { .start = node->ivar_name_range.start_char, .end = node->ivar_name_range.end_char });
711
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("visibility"), (rbs_loc_range) { .start = node->visibility_range.start_char, .end = node->visibility_range.end_char });
712
+ }
713
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_ast_symbol
714
+ VALUE arg_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type); // rbs_node
715
+ VALUE arg_ivar_name = rbs_attr_ivar_name_to_ruby(ctx, node->ivar_name); // rbs_attr_ivar_name_t
716
+ VALUE arg_kind = rbs_attribute_kind_to_ruby(node->kind); // attribute_kind
717
+ VALUE arg_annotations = rbs_node_list_to_ruby_array(ctx, node->annotations);
718
+ VALUE arg_comment = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment); // rbs_ast_comment
719
+ VALUE arg_visibility = rbs_attribute_visibility_to_ruby(node->visibility); // attribute_visibility
720
+
721
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
722
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
723
+ VALUE h = ctx.reusable_kwargs_hash;
724
+ rb_hash_clear(h);
725
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
726
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
727
+ rb_hash_aset(h, ID2SYM(rb_intern("type")), arg_type);
728
+ rb_hash_aset(h, ID2SYM(rb_intern("ivar_name")), arg_ivar_name);
729
+ rb_hash_aset(h, ID2SYM(rb_intern("kind")), arg_kind);
730
+ rb_hash_aset(h, ID2SYM(rb_intern("annotations")), arg_annotations);
731
+ rb_hash_aset(h, ID2SYM(rb_intern("comment")), arg_comment);
732
+ rb_hash_aset(h, ID2SYM(rb_intern("visibility")), arg_visibility);
733
+ return CLASS_NEW_INSTANCE(RBS_AST_Members_AttrReader, 1, &h);
608
734
  }
609
735
  case RBS_AST_MEMBERS_ATTR_WRITER: {
610
736
  rbs_ast_members_attr_writer_t *node = (rbs_ast_members_attr_writer_t *) instance;
611
737
 
612
- VALUE h = rb_hash_new();
613
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
614
- rbs_loc *loc = rbs_check_location(location);
615
- rbs_loc_legacy_alloc_children(loc, 7);
616
- rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
617
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
618
- rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
619
- rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
620
- rbs_loc_legacy_add_optional_child(loc, rb_intern("ivar"), (rbs_loc_range) { .start = node->ivar_range.start_char, .end = node->ivar_range.end_char });
621
- rbs_loc_legacy_add_optional_child(loc, rb_intern("ivar_name"), (rbs_loc_range) { .start = node->ivar_name_range.start_char, .end = node->ivar_name_range.end_char });
622
- rbs_loc_legacy_add_optional_child(loc, rb_intern("visibility"), (rbs_loc_range) { .start = node->visibility_range.start_char, .end = node->visibility_range.end_char });
623
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
624
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol
625
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
626
- rb_hash_aset(h, ID2SYM(rb_intern("ivar_name")), rbs_attr_ivar_name_to_ruby(ctx, node->ivar_name)); // rbs_attr_ivar_name_t
627
- rb_hash_aset(h, ID2SYM(rb_intern("kind")), rbs_attribute_kind_to_ruby(node->kind)); // attribute_kind
628
- rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
629
- rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
630
- rb_hash_aset(h, ID2SYM(rb_intern("visibility")), rbs_attribute_visibility_to_ruby(node->visibility)); // attribute_visibility
631
-
632
- return CLASS_NEW_INSTANCE(
633
- RBS_AST_Members_AttrWriter,
634
- 1,
635
- &h
636
- );
738
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
739
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
740
+ rbs_loc *loc = rbs_check_location(arg_location);
741
+ {
742
+ rbs_loc_legacy_alloc_children(loc, 7);
743
+ rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
744
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
745
+ rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
746
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
747
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("ivar"), (rbs_loc_range) { .start = node->ivar_range.start_char, .end = node->ivar_range.end_char });
748
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("ivar_name"), (rbs_loc_range) { .start = node->ivar_name_range.start_char, .end = node->ivar_name_range.end_char });
749
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("visibility"), (rbs_loc_range) { .start = node->visibility_range.start_char, .end = node->visibility_range.end_char });
750
+ }
751
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_ast_symbol
752
+ VALUE arg_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type); // rbs_node
753
+ VALUE arg_ivar_name = rbs_attr_ivar_name_to_ruby(ctx, node->ivar_name); // rbs_attr_ivar_name_t
754
+ VALUE arg_kind = rbs_attribute_kind_to_ruby(node->kind); // attribute_kind
755
+ VALUE arg_annotations = rbs_node_list_to_ruby_array(ctx, node->annotations);
756
+ VALUE arg_comment = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment); // rbs_ast_comment
757
+ VALUE arg_visibility = rbs_attribute_visibility_to_ruby(node->visibility); // attribute_visibility
758
+
759
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
760
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
761
+ VALUE h = ctx.reusable_kwargs_hash;
762
+ rb_hash_clear(h);
763
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
764
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
765
+ rb_hash_aset(h, ID2SYM(rb_intern("type")), arg_type);
766
+ rb_hash_aset(h, ID2SYM(rb_intern("ivar_name")), arg_ivar_name);
767
+ rb_hash_aset(h, ID2SYM(rb_intern("kind")), arg_kind);
768
+ rb_hash_aset(h, ID2SYM(rb_intern("annotations")), arg_annotations);
769
+ rb_hash_aset(h, ID2SYM(rb_intern("comment")), arg_comment);
770
+ rb_hash_aset(h, ID2SYM(rb_intern("visibility")), arg_visibility);
771
+ return CLASS_NEW_INSTANCE(RBS_AST_Members_AttrWriter, 1, &h);
637
772
  }
638
773
  case RBS_AST_MEMBERS_CLASS_INSTANCE_VARIABLE: {
639
774
  rbs_ast_members_class_instance_variable_t *node = (rbs_ast_members_class_instance_variable_t *) instance;
640
775
 
641
- VALUE h = rb_hash_new();
642
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
643
- rbs_loc *loc = rbs_check_location(location);
644
- rbs_loc_legacy_alloc_children(loc, 3);
645
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
646
- rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
647
- rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
648
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
649
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol
650
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
651
- rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
652
-
653
- return CLASS_NEW_INSTANCE(
654
- RBS_AST_Members_ClassInstanceVariable,
655
- 1,
656
- &h
657
- );
776
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
777
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
778
+ rbs_loc *loc = rbs_check_location(arg_location);
779
+ {
780
+ rbs_loc_legacy_alloc_children(loc, 3);
781
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
782
+ rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
783
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
784
+ }
785
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_ast_symbol
786
+ VALUE arg_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type); // rbs_node
787
+ VALUE arg_comment = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment); // rbs_ast_comment
788
+
789
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
790
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
791
+ VALUE h = ctx.reusable_kwargs_hash;
792
+ rb_hash_clear(h);
793
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
794
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
795
+ rb_hash_aset(h, ID2SYM(rb_intern("type")), arg_type);
796
+ rb_hash_aset(h, ID2SYM(rb_intern("comment")), arg_comment);
797
+ return CLASS_NEW_INSTANCE(RBS_AST_Members_ClassInstanceVariable, 1, &h);
658
798
  }
659
799
  case RBS_AST_MEMBERS_CLASS_VARIABLE: {
660
800
  rbs_ast_members_class_variable_t *node = (rbs_ast_members_class_variable_t *) instance;
661
801
 
662
- VALUE h = rb_hash_new();
663
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
664
- rbs_loc *loc = rbs_check_location(location);
665
- rbs_loc_legacy_alloc_children(loc, 3);
666
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
667
- rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
668
- rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
669
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
670
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol
671
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
672
- rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
673
-
674
- return CLASS_NEW_INSTANCE(
675
- RBS_AST_Members_ClassVariable,
676
- 1,
677
- &h
678
- );
802
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
803
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
804
+ rbs_loc *loc = rbs_check_location(arg_location);
805
+ {
806
+ rbs_loc_legacy_alloc_children(loc, 3);
807
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
808
+ rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
809
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
810
+ }
811
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_ast_symbol
812
+ VALUE arg_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type); // rbs_node
813
+ VALUE arg_comment = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment); // rbs_ast_comment
814
+
815
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
816
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
817
+ VALUE h = ctx.reusable_kwargs_hash;
818
+ rb_hash_clear(h);
819
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
820
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
821
+ rb_hash_aset(h, ID2SYM(rb_intern("type")), arg_type);
822
+ rb_hash_aset(h, ID2SYM(rb_intern("comment")), arg_comment);
823
+ return CLASS_NEW_INSTANCE(RBS_AST_Members_ClassVariable, 1, &h);
679
824
  }
680
825
  case RBS_AST_MEMBERS_EXTEND: {
681
826
  rbs_ast_members_extend_t *node = (rbs_ast_members_extend_t *) instance;
682
827
 
683
- VALUE h = rb_hash_new();
684
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
685
- rbs_loc *loc = rbs_check_location(location);
686
- rbs_loc_legacy_alloc_children(loc, 3);
687
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
688
- rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
689
- rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
690
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
691
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
692
- rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));
693
- rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
694
- rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
695
-
696
- return CLASS_NEW_INSTANCE(
697
- RBS_AST_Members_Extend,
698
- 1,
699
- &h
700
- );
828
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
829
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
830
+ rbs_loc *loc = rbs_check_location(arg_location);
831
+ {
832
+ rbs_loc_legacy_alloc_children(loc, 3);
833
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
834
+ rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
835
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
836
+ }
837
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_type_name
838
+ VALUE arg_args = rbs_node_list_to_ruby_array(ctx, node->args);
839
+ VALUE arg_annotations = rbs_node_list_to_ruby_array(ctx, node->annotations);
840
+ VALUE arg_comment = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment); // rbs_ast_comment
841
+
842
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
843
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
844
+ VALUE h = ctx.reusable_kwargs_hash;
845
+ rb_hash_clear(h);
846
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
847
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
848
+ rb_hash_aset(h, ID2SYM(rb_intern("args")), arg_args);
849
+ rb_hash_aset(h, ID2SYM(rb_intern("annotations")), arg_annotations);
850
+ rb_hash_aset(h, ID2SYM(rb_intern("comment")), arg_comment);
851
+ return CLASS_NEW_INSTANCE(RBS_AST_Members_Extend, 1, &h);
701
852
  }
702
853
  case RBS_AST_MEMBERS_INCLUDE: {
703
854
  rbs_ast_members_include_t *node = (rbs_ast_members_include_t *) instance;
704
855
 
705
- VALUE h = rb_hash_new();
706
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
707
- rbs_loc *loc = rbs_check_location(location);
708
- rbs_loc_legacy_alloc_children(loc, 3);
709
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
710
- rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
711
- rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
712
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
713
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
714
- rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));
715
- rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
716
- rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
717
-
718
- return CLASS_NEW_INSTANCE(
719
- RBS_AST_Members_Include,
720
- 1,
721
- &h
722
- );
856
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
857
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
858
+ rbs_loc *loc = rbs_check_location(arg_location);
859
+ {
860
+ rbs_loc_legacy_alloc_children(loc, 3);
861
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
862
+ rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
863
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
864
+ }
865
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_type_name
866
+ VALUE arg_args = rbs_node_list_to_ruby_array(ctx, node->args);
867
+ VALUE arg_annotations = rbs_node_list_to_ruby_array(ctx, node->annotations);
868
+ VALUE arg_comment = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment); // rbs_ast_comment
869
+
870
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
871
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
872
+ VALUE h = ctx.reusable_kwargs_hash;
873
+ rb_hash_clear(h);
874
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
875
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
876
+ rb_hash_aset(h, ID2SYM(rb_intern("args")), arg_args);
877
+ rb_hash_aset(h, ID2SYM(rb_intern("annotations")), arg_annotations);
878
+ rb_hash_aset(h, ID2SYM(rb_intern("comment")), arg_comment);
879
+ return CLASS_NEW_INSTANCE(RBS_AST_Members_Include, 1, &h);
723
880
  }
724
881
  case RBS_AST_MEMBERS_INSTANCE_VARIABLE: {
725
882
  rbs_ast_members_instance_variable_t *node = (rbs_ast_members_instance_variable_t *) instance;
726
883
 
727
- VALUE h = rb_hash_new();
728
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
729
- rbs_loc *loc = rbs_check_location(location);
730
- rbs_loc_legacy_alloc_children(loc, 3);
731
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
732
- rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
733
- rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
734
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
735
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol
736
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
737
- rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
738
-
739
- return CLASS_NEW_INSTANCE(
740
- RBS_AST_Members_InstanceVariable,
741
- 1,
742
- &h
743
- );
884
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
885
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
886
+ rbs_loc *loc = rbs_check_location(arg_location);
887
+ {
888
+ rbs_loc_legacy_alloc_children(loc, 3);
889
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
890
+ rbs_loc_legacy_add_required_child(loc, rb_intern("colon"), (rbs_loc_range) { .start = node->colon_range.start_char, .end = node->colon_range.end_char });
891
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
892
+ }
893
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_ast_symbol
894
+ VALUE arg_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type); // rbs_node
895
+ VALUE arg_comment = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment); // rbs_ast_comment
896
+
897
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
898
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
899
+ VALUE h = ctx.reusable_kwargs_hash;
900
+ rb_hash_clear(h);
901
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
902
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
903
+ rb_hash_aset(h, ID2SYM(rb_intern("type")), arg_type);
904
+ rb_hash_aset(h, ID2SYM(rb_intern("comment")), arg_comment);
905
+ return CLASS_NEW_INSTANCE(RBS_AST_Members_InstanceVariable, 1, &h);
744
906
  }
745
907
  case RBS_AST_MEMBERS_METHOD_DEFINITION: {
746
908
  rbs_ast_members_method_definition_t *node = (rbs_ast_members_method_definition_t *) instance;
747
909
 
748
- VALUE h = rb_hash_new();
749
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
750
- rbs_loc *loc = rbs_check_location(location);
751
- rbs_loc_legacy_alloc_children(loc, 5);
752
- rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
753
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
754
- rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
755
- rbs_loc_legacy_add_optional_child(loc, rb_intern("overloading"), (rbs_loc_range) { .start = node->overloading_range.start_char, .end = node->overloading_range.end_char });
756
- rbs_loc_legacy_add_optional_child(loc, rb_intern("visibility"), (rbs_loc_range) { .start = node->visibility_range.start_char, .end = node->visibility_range.end_char });
757
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
758
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol
759
- rb_hash_aset(h, ID2SYM(rb_intern("kind")), rbs_method_definition_kind_to_ruby(node->kind)); // method_definition_kind
760
- rb_hash_aset(h, ID2SYM(rb_intern("overloads")), rbs_node_list_to_ruby_array(ctx, node->overloads));
761
- rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
762
- rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
763
- rb_hash_aset(h, ID2SYM(rb_intern("overloading")), node->overloading ? Qtrue : Qfalse);
764
- rb_hash_aset(h, ID2SYM(rb_intern("visibility")), rbs_method_definition_visibility_to_ruby(node->visibility)); // method_definition_visibility
765
-
766
- return CLASS_NEW_INSTANCE(
767
- RBS_AST_Members_MethodDefinition,
768
- 1,
769
- &h
770
- );
910
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
911
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
912
+ rbs_loc *loc = rbs_check_location(arg_location);
913
+ {
914
+ rbs_loc_legacy_alloc_children(loc, 5);
915
+ rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
916
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
917
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("kind"), (rbs_loc_range) { .start = node->kind_range.start_char, .end = node->kind_range.end_char });
918
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("overloading"), (rbs_loc_range) { .start = node->overloading_range.start_char, .end = node->overloading_range.end_char });
919
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("visibility"), (rbs_loc_range) { .start = node->visibility_range.start_char, .end = node->visibility_range.end_char });
920
+ }
921
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_ast_symbol
922
+ VALUE arg_kind = rbs_method_definition_kind_to_ruby(node->kind); // method_definition_kind
923
+ VALUE arg_overloads = rbs_node_list_to_ruby_array(ctx, node->overloads);
924
+ VALUE arg_annotations = rbs_node_list_to_ruby_array(ctx, node->annotations);
925
+ VALUE arg_comment = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment); // rbs_ast_comment
926
+ VALUE arg_overloading = node->overloading ? Qtrue : Qfalse;
927
+ VALUE arg_visibility = rbs_method_definition_visibility_to_ruby(node->visibility); // method_definition_visibility
928
+
929
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
930
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
931
+ VALUE h = ctx.reusable_kwargs_hash;
932
+ rb_hash_clear(h);
933
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
934
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
935
+ rb_hash_aset(h, ID2SYM(rb_intern("kind")), arg_kind);
936
+ rb_hash_aset(h, ID2SYM(rb_intern("overloads")), arg_overloads);
937
+ rb_hash_aset(h, ID2SYM(rb_intern("annotations")), arg_annotations);
938
+ rb_hash_aset(h, ID2SYM(rb_intern("comment")), arg_comment);
939
+ rb_hash_aset(h, ID2SYM(rb_intern("overloading")), arg_overloading);
940
+ rb_hash_aset(h, ID2SYM(rb_intern("visibility")), arg_visibility);
941
+ return CLASS_NEW_INSTANCE(RBS_AST_Members_MethodDefinition, 1, &h);
771
942
  }
772
943
  case RBS_AST_MEMBERS_METHOD_DEFINITION_OVERLOAD: {
773
944
  rbs_ast_members_method_definition_overload_t *node = (rbs_ast_members_method_definition_overload_t *) instance;
774
945
 
775
- VALUE h = rb_hash_new();
776
- rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
777
- rb_hash_aset(h, ID2SYM(rb_intern("method_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->method_type)); // rbs_node
946
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
947
+ VALUE arg_annotations = rbs_node_list_to_ruby_array(ctx, node->annotations);
948
+ VALUE arg_method_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->method_type); // rbs_node
778
949
 
779
- return CLASS_NEW_INSTANCE(
780
- RBS_AST_Members_MethodDefinition_Overload,
781
- 1,
782
- &h
783
- );
950
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
951
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
952
+ VALUE h = ctx.reusable_kwargs_hash;
953
+ rb_hash_clear(h);
954
+ rb_hash_aset(h, ID2SYM(rb_intern("annotations")), arg_annotations);
955
+ rb_hash_aset(h, ID2SYM(rb_intern("method_type")), arg_method_type);
956
+ return CLASS_NEW_INSTANCE(RBS_AST_Members_MethodDefinition_Overload, 1, &h);
784
957
  }
785
958
  case RBS_AST_MEMBERS_PREPEND: {
786
959
  rbs_ast_members_prepend_t *node = (rbs_ast_members_prepend_t *) instance;
787
960
 
788
- VALUE h = rb_hash_new();
789
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
790
- rbs_loc *loc = rbs_check_location(location);
791
- rbs_loc_legacy_alloc_children(loc, 3);
792
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
793
- rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
794
- rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
795
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
796
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
797
- rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));
798
- rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
799
- rb_hash_aset(h, ID2SYM(rb_intern("comment")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment)); // rbs_ast_comment
800
-
801
- return CLASS_NEW_INSTANCE(
802
- RBS_AST_Members_Prepend,
803
- 1,
804
- &h
805
- );
961
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
962
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
963
+ rbs_loc *loc = rbs_check_location(arg_location);
964
+ {
965
+ rbs_loc_legacy_alloc_children(loc, 3);
966
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
967
+ rbs_loc_legacy_add_required_child(loc, rb_intern("keyword"), (rbs_loc_range) { .start = node->keyword_range.start_char, .end = node->keyword_range.end_char });
968
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
969
+ }
970
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_type_name
971
+ VALUE arg_args = rbs_node_list_to_ruby_array(ctx, node->args);
972
+ VALUE arg_annotations = rbs_node_list_to_ruby_array(ctx, node->annotations);
973
+ VALUE arg_comment = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->comment); // rbs_ast_comment
974
+
975
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
976
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
977
+ VALUE h = ctx.reusable_kwargs_hash;
978
+ rb_hash_clear(h);
979
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
980
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
981
+ rb_hash_aset(h, ID2SYM(rb_intern("args")), arg_args);
982
+ rb_hash_aset(h, ID2SYM(rb_intern("annotations")), arg_annotations);
983
+ rb_hash_aset(h, ID2SYM(rb_intern("comment")), arg_comment);
984
+ return CLASS_NEW_INSTANCE(RBS_AST_Members_Prepend, 1, &h);
806
985
  }
807
986
  case RBS_AST_MEMBERS_PRIVATE: {
808
987
  rbs_ast_members_private_t *node = (rbs_ast_members_private_t *) instance;
809
988
 
810
- VALUE h = rb_hash_new();
811
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
989
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
990
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
812
991
 
813
- return CLASS_NEW_INSTANCE(
814
- RBS_AST_Members_Private,
815
- 1,
816
- &h
817
- );
992
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
993
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
994
+ VALUE h = ctx.reusable_kwargs_hash;
995
+ rb_hash_clear(h);
996
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
997
+ return CLASS_NEW_INSTANCE(RBS_AST_Members_Private, 1, &h);
818
998
  }
819
999
  case RBS_AST_MEMBERS_PUBLIC: {
820
1000
  rbs_ast_members_public_t *node = (rbs_ast_members_public_t *) instance;
821
1001
 
822
- VALUE h = rb_hash_new();
823
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1002
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1003
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
824
1004
 
825
- return CLASS_NEW_INSTANCE(
826
- RBS_AST_Members_Public,
827
- 1,
828
- &h
829
- );
1005
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1006
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1007
+ VALUE h = ctx.reusable_kwargs_hash;
1008
+ rb_hash_clear(h);
1009
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1010
+ return CLASS_NEW_INSTANCE(RBS_AST_Members_Public, 1, &h);
830
1011
  }
831
1012
  case RBS_AST_RUBY_ANNOTATIONS_BLOCK_PARAM_TYPE_ANNOTATION: {
832
1013
  rbs_ast_ruby_annotations_block_param_type_annotation_t *node = (rbs_ast_ruby_annotations_block_param_type_annotation_t *) instance;
833
1014
 
834
- VALUE h = rb_hash_new();
835
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
836
- rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
837
- rb_hash_aset(h, ID2SYM(rb_intern("ampersand_location")), rbs_location_range_to_ruby_location(ctx, node->ampersand_location));
838
- rb_hash_aset(h, ID2SYM(rb_intern("name_location")), rbs_location_range_to_ruby_location(ctx, node->name_location)); // optional
839
- rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), rbs_location_range_to_ruby_location(ctx, node->colon_location));
840
- rb_hash_aset(h, ID2SYM(rb_intern("question_location")), rbs_location_range_to_ruby_location(ctx, node->question_location)); // optional
841
- rb_hash_aset(h, ID2SYM(rb_intern("type_location")), rbs_location_range_to_ruby_location(ctx, node->type_location));
842
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type_)); // rbs_node
843
- rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional
844
-
845
- return CLASS_NEW_INSTANCE(
846
- RBS_AST_Ruby_Annotations_BlockParamTypeAnnotation,
847
- 1,
848
- &h
849
- );
1015
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1016
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1017
+ VALUE arg_prefix_location = rbs_location_range_to_ruby_location(ctx, node->prefix_location);
1018
+ VALUE arg_ampersand_location = rbs_location_range_to_ruby_location(ctx, node->ampersand_location);
1019
+ VALUE arg_name_location = rbs_location_range_to_ruby_location(ctx, node->name_location); // optional
1020
+ VALUE arg_colon_location = rbs_location_range_to_ruby_location(ctx, node->colon_location);
1021
+ VALUE arg_question_location = rbs_location_range_to_ruby_location(ctx, node->question_location); // optional
1022
+ VALUE arg_type_location = rbs_location_range_to_ruby_location(ctx, node->type_location);
1023
+ VALUE arg_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type_); // rbs_node
1024
+ VALUE arg_comment_location = rbs_location_range_to_ruby_location(ctx, node->comment_location); // optional
1025
+
1026
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1027
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1028
+ VALUE h = ctx.reusable_kwargs_hash;
1029
+ rb_hash_clear(h);
1030
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1031
+ rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), arg_prefix_location);
1032
+ rb_hash_aset(h, ID2SYM(rb_intern("ampersand_location")), arg_ampersand_location);
1033
+ rb_hash_aset(h, ID2SYM(rb_intern("name_location")), arg_name_location);
1034
+ rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), arg_colon_location);
1035
+ rb_hash_aset(h, ID2SYM(rb_intern("question_location")), arg_question_location);
1036
+ rb_hash_aset(h, ID2SYM(rb_intern("type_location")), arg_type_location);
1037
+ rb_hash_aset(h, ID2SYM(rb_intern("type")), arg_type);
1038
+ rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), arg_comment_location);
1039
+ return CLASS_NEW_INSTANCE(RBS_AST_Ruby_Annotations_BlockParamTypeAnnotation, 1, &h);
850
1040
  }
851
1041
  case RBS_AST_RUBY_ANNOTATIONS_CLASS_ALIAS_ANNOTATION: {
852
1042
  rbs_ast_ruby_annotations_class_alias_annotation_t *node = (rbs_ast_ruby_annotations_class_alias_annotation_t *) instance;
853
1043
 
854
- VALUE h = rb_hash_new();
855
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
856
- rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
857
- rb_hash_aset(h, ID2SYM(rb_intern("keyword_location")), rbs_location_range_to_ruby_location(ctx, node->keyword_location));
858
- rb_hash_aset(h, ID2SYM(rb_intern("type_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type_name)); // rbs_type_name
859
- rb_hash_aset(h, ID2SYM(rb_intern("type_name_location")), rbs_location_range_to_ruby_location(ctx, node->type_name_location)); // optional
860
-
861
- return CLASS_NEW_INSTANCE(
862
- RBS_AST_Ruby_Annotations_ClassAliasAnnotation,
863
- 1,
864
- &h
865
- );
1044
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1045
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1046
+ VALUE arg_prefix_location = rbs_location_range_to_ruby_location(ctx, node->prefix_location);
1047
+ VALUE arg_keyword_location = rbs_location_range_to_ruby_location(ctx, node->keyword_location);
1048
+ VALUE arg_type_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type_name); // rbs_type_name
1049
+ VALUE arg_type_name_location = rbs_location_range_to_ruby_location(ctx, node->type_name_location); // optional
1050
+
1051
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1052
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1053
+ VALUE h = ctx.reusable_kwargs_hash;
1054
+ rb_hash_clear(h);
1055
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1056
+ rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), arg_prefix_location);
1057
+ rb_hash_aset(h, ID2SYM(rb_intern("keyword_location")), arg_keyword_location);
1058
+ rb_hash_aset(h, ID2SYM(rb_intern("type_name")), arg_type_name);
1059
+ rb_hash_aset(h, ID2SYM(rb_intern("type_name_location")), arg_type_name_location);
1060
+ return CLASS_NEW_INSTANCE(RBS_AST_Ruby_Annotations_ClassAliasAnnotation, 1, &h);
866
1061
  }
867
1062
  case RBS_AST_RUBY_ANNOTATIONS_COLON_METHOD_TYPE_ANNOTATION: {
868
1063
  rbs_ast_ruby_annotations_colon_method_type_annotation_t *node = (rbs_ast_ruby_annotations_colon_method_type_annotation_t *) instance;
869
1064
 
870
- VALUE h = rb_hash_new();
871
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
872
- rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
873
- rb_hash_aset(h, ID2SYM(rb_intern("annotations")), rbs_node_list_to_ruby_array(ctx, node->annotations));
874
- rb_hash_aset(h, ID2SYM(rb_intern("method_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->method_type)); // rbs_node
875
-
876
- return CLASS_NEW_INSTANCE(
877
- RBS_AST_Ruby_Annotations_ColonMethodTypeAnnotation,
878
- 1,
879
- &h
880
- );
1065
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1066
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1067
+ VALUE arg_prefix_location = rbs_location_range_to_ruby_location(ctx, node->prefix_location);
1068
+ VALUE arg_annotations = rbs_node_list_to_ruby_array(ctx, node->annotations);
1069
+ VALUE arg_method_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->method_type); // rbs_node
1070
+
1071
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1072
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1073
+ VALUE h = ctx.reusable_kwargs_hash;
1074
+ rb_hash_clear(h);
1075
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1076
+ rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), arg_prefix_location);
1077
+ rb_hash_aset(h, ID2SYM(rb_intern("annotations")), arg_annotations);
1078
+ rb_hash_aset(h, ID2SYM(rb_intern("method_type")), arg_method_type);
1079
+ return CLASS_NEW_INSTANCE(RBS_AST_Ruby_Annotations_ColonMethodTypeAnnotation, 1, &h);
881
1080
  }
882
1081
  case RBS_AST_RUBY_ANNOTATIONS_DOUBLE_SPLAT_PARAM_TYPE_ANNOTATION: {
883
1082
  rbs_ast_ruby_annotations_double_splat_param_type_annotation_t *node = (rbs_ast_ruby_annotations_double_splat_param_type_annotation_t *) instance;
884
1083
 
885
- VALUE h = rb_hash_new();
886
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
887
- rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
888
- rb_hash_aset(h, ID2SYM(rb_intern("star2_location")), rbs_location_range_to_ruby_location(ctx, node->star2_location));
889
- rb_hash_aset(h, ID2SYM(rb_intern("name_location")), rbs_location_range_to_ruby_location(ctx, node->name_location)); // optional
890
- rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), rbs_location_range_to_ruby_location(ctx, node->colon_location));
891
- rb_hash_aset(h, ID2SYM(rb_intern("param_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->param_type)); // rbs_node
892
- rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional
893
-
894
- return CLASS_NEW_INSTANCE(
895
- RBS_AST_Ruby_Annotations_DoubleSplatParamTypeAnnotation,
896
- 1,
897
- &h
898
- );
1084
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1085
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1086
+ VALUE arg_prefix_location = rbs_location_range_to_ruby_location(ctx, node->prefix_location);
1087
+ VALUE arg_star2_location = rbs_location_range_to_ruby_location(ctx, node->star2_location);
1088
+ VALUE arg_name_location = rbs_location_range_to_ruby_location(ctx, node->name_location); // optional
1089
+ VALUE arg_colon_location = rbs_location_range_to_ruby_location(ctx, node->colon_location);
1090
+ VALUE arg_param_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->param_type); // rbs_node
1091
+ VALUE arg_comment_location = rbs_location_range_to_ruby_location(ctx, node->comment_location); // optional
1092
+
1093
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1094
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1095
+ VALUE h = ctx.reusable_kwargs_hash;
1096
+ rb_hash_clear(h);
1097
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1098
+ rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), arg_prefix_location);
1099
+ rb_hash_aset(h, ID2SYM(rb_intern("star2_location")), arg_star2_location);
1100
+ rb_hash_aset(h, ID2SYM(rb_intern("name_location")), arg_name_location);
1101
+ rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), arg_colon_location);
1102
+ rb_hash_aset(h, ID2SYM(rb_intern("param_type")), arg_param_type);
1103
+ rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), arg_comment_location);
1104
+ return CLASS_NEW_INSTANCE(RBS_AST_Ruby_Annotations_DoubleSplatParamTypeAnnotation, 1, &h);
899
1105
  }
900
1106
  case RBS_AST_RUBY_ANNOTATIONS_INSTANCE_VARIABLE_ANNOTATION: {
901
1107
  rbs_ast_ruby_annotations_instance_variable_annotation_t *node = (rbs_ast_ruby_annotations_instance_variable_annotation_t *) instance;
902
1108
 
903
- VALUE h = rb_hash_new();
904
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
905
- rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
906
- rb_hash_aset(h, ID2SYM(rb_intern("ivar_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->ivar_name)); // rbs_ast_symbol
907
- rb_hash_aset(h, ID2SYM(rb_intern("ivar_name_location")), rbs_location_range_to_ruby_location(ctx, node->ivar_name_location));
908
- rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), rbs_location_range_to_ruby_location(ctx, node->colon_location));
909
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
910
- rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional
911
-
912
- return CLASS_NEW_INSTANCE(
913
- RBS_AST_Ruby_Annotations_InstanceVariableAnnotation,
914
- 1,
915
- &h
916
- );
1109
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1110
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1111
+ VALUE arg_prefix_location = rbs_location_range_to_ruby_location(ctx, node->prefix_location);
1112
+ VALUE arg_ivar_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->ivar_name); // rbs_ast_symbol
1113
+ VALUE arg_ivar_name_location = rbs_location_range_to_ruby_location(ctx, node->ivar_name_location);
1114
+ VALUE arg_colon_location = rbs_location_range_to_ruby_location(ctx, node->colon_location);
1115
+ VALUE arg_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type); // rbs_node
1116
+ VALUE arg_comment_location = rbs_location_range_to_ruby_location(ctx, node->comment_location); // optional
1117
+
1118
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1119
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1120
+ VALUE h = ctx.reusable_kwargs_hash;
1121
+ rb_hash_clear(h);
1122
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1123
+ rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), arg_prefix_location);
1124
+ rb_hash_aset(h, ID2SYM(rb_intern("ivar_name")), arg_ivar_name);
1125
+ rb_hash_aset(h, ID2SYM(rb_intern("ivar_name_location")), arg_ivar_name_location);
1126
+ rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), arg_colon_location);
1127
+ rb_hash_aset(h, ID2SYM(rb_intern("type")), arg_type);
1128
+ rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), arg_comment_location);
1129
+ return CLASS_NEW_INSTANCE(RBS_AST_Ruby_Annotations_InstanceVariableAnnotation, 1, &h);
917
1130
  }
918
1131
  case RBS_AST_RUBY_ANNOTATIONS_METHOD_TYPES_ANNOTATION: {
919
1132
  rbs_ast_ruby_annotations_method_types_annotation_t *node = (rbs_ast_ruby_annotations_method_types_annotation_t *) instance;
920
1133
 
921
- VALUE h = rb_hash_new();
922
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
923
- rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
924
- rb_hash_aset(h, ID2SYM(rb_intern("overloads")), rbs_node_list_to_ruby_array(ctx, node->overloads));
925
- rb_hash_aset(h, ID2SYM(rb_intern("vertical_bar_locations")), rbs_location_range_list_to_ruby_array(ctx, node->vertical_bar_locations));
926
- rb_hash_aset(h, ID2SYM(rb_intern("dot3_location")), rbs_location_range_to_ruby_location(ctx, node->dot3_location)); // optional
927
-
928
- return CLASS_NEW_INSTANCE(
929
- RBS_AST_Ruby_Annotations_MethodTypesAnnotation,
930
- 1,
931
- &h
932
- );
1134
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1135
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1136
+ VALUE arg_prefix_location = rbs_location_range_to_ruby_location(ctx, node->prefix_location);
1137
+ VALUE arg_overloads = rbs_node_list_to_ruby_array(ctx, node->overloads);
1138
+ VALUE arg_vertical_bar_locations = rbs_location_range_list_to_ruby_array(ctx, node->vertical_bar_locations);
1139
+ VALUE arg_dot3_location = rbs_location_range_to_ruby_location(ctx, node->dot3_location); // optional
1140
+
1141
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1142
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1143
+ VALUE h = ctx.reusable_kwargs_hash;
1144
+ rb_hash_clear(h);
1145
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1146
+ rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), arg_prefix_location);
1147
+ rb_hash_aset(h, ID2SYM(rb_intern("overloads")), arg_overloads);
1148
+ rb_hash_aset(h, ID2SYM(rb_intern("vertical_bar_locations")), arg_vertical_bar_locations);
1149
+ rb_hash_aset(h, ID2SYM(rb_intern("dot3_location")), arg_dot3_location);
1150
+ return CLASS_NEW_INSTANCE(RBS_AST_Ruby_Annotations_MethodTypesAnnotation, 1, &h);
933
1151
  }
934
1152
  case RBS_AST_RUBY_ANNOTATIONS_MODULE_ALIAS_ANNOTATION: {
935
1153
  rbs_ast_ruby_annotations_module_alias_annotation_t *node = (rbs_ast_ruby_annotations_module_alias_annotation_t *) instance;
936
1154
 
937
- VALUE h = rb_hash_new();
938
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
939
- rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
940
- rb_hash_aset(h, ID2SYM(rb_intern("keyword_location")), rbs_location_range_to_ruby_location(ctx, node->keyword_location));
941
- rb_hash_aset(h, ID2SYM(rb_intern("type_name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type_name)); // rbs_type_name
942
- rb_hash_aset(h, ID2SYM(rb_intern("type_name_location")), rbs_location_range_to_ruby_location(ctx, node->type_name_location)); // optional
943
-
944
- return CLASS_NEW_INSTANCE(
945
- RBS_AST_Ruby_Annotations_ModuleAliasAnnotation,
946
- 1,
947
- &h
948
- );
1155
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1156
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1157
+ VALUE arg_prefix_location = rbs_location_range_to_ruby_location(ctx, node->prefix_location);
1158
+ VALUE arg_keyword_location = rbs_location_range_to_ruby_location(ctx, node->keyword_location);
1159
+ VALUE arg_type_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type_name); // rbs_type_name
1160
+ VALUE arg_type_name_location = rbs_location_range_to_ruby_location(ctx, node->type_name_location); // optional
1161
+
1162
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1163
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1164
+ VALUE h = ctx.reusable_kwargs_hash;
1165
+ rb_hash_clear(h);
1166
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1167
+ rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), arg_prefix_location);
1168
+ rb_hash_aset(h, ID2SYM(rb_intern("keyword_location")), arg_keyword_location);
1169
+ rb_hash_aset(h, ID2SYM(rb_intern("type_name")), arg_type_name);
1170
+ rb_hash_aset(h, ID2SYM(rb_intern("type_name_location")), arg_type_name_location);
1171
+ return CLASS_NEW_INSTANCE(RBS_AST_Ruby_Annotations_ModuleAliasAnnotation, 1, &h);
1172
+ }
1173
+ case RBS_AST_RUBY_ANNOTATIONS_MODULE_SELF_ANNOTATION: {
1174
+ rbs_ast_ruby_annotations_module_self_annotation_t *node = (rbs_ast_ruby_annotations_module_self_annotation_t *) instance;
1175
+
1176
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1177
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1178
+ VALUE arg_prefix_location = rbs_location_range_to_ruby_location(ctx, node->prefix_location);
1179
+ VALUE arg_keyword_location = rbs_location_range_to_ruby_location(ctx, node->keyword_location);
1180
+ VALUE arg_colon_location = rbs_location_range_to_ruby_location(ctx, node->colon_location);
1181
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_type_name
1182
+ VALUE arg_args = rbs_node_list_to_ruby_array(ctx, node->args);
1183
+ VALUE arg_open_bracket_location = rbs_location_range_to_ruby_location(ctx, node->open_bracket_location); // optional
1184
+ VALUE arg_close_bracket_location = rbs_location_range_to_ruby_location(ctx, node->close_bracket_location); // optional
1185
+ VALUE arg_args_comma_locations = rbs_location_range_list_to_ruby_array(ctx, node->args_comma_locations);
1186
+ VALUE arg_comment_location = rbs_location_range_to_ruby_location(ctx, node->comment_location); // optional
1187
+
1188
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1189
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1190
+ VALUE h = ctx.reusable_kwargs_hash;
1191
+ rb_hash_clear(h);
1192
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1193
+ rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), arg_prefix_location);
1194
+ rb_hash_aset(h, ID2SYM(rb_intern("keyword_location")), arg_keyword_location);
1195
+ rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), arg_colon_location);
1196
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
1197
+ rb_hash_aset(h, ID2SYM(rb_intern("args")), arg_args);
1198
+ rb_hash_aset(h, ID2SYM(rb_intern("open_bracket_location")), arg_open_bracket_location);
1199
+ rb_hash_aset(h, ID2SYM(rb_intern("close_bracket_location")), arg_close_bracket_location);
1200
+ rb_hash_aset(h, ID2SYM(rb_intern("args_comma_locations")), arg_args_comma_locations);
1201
+ rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), arg_comment_location);
1202
+ return CLASS_NEW_INSTANCE(RBS_AST_Ruby_Annotations_ModuleSelfAnnotation, 1, &h);
949
1203
  }
950
1204
  case RBS_AST_RUBY_ANNOTATIONS_NODE_TYPE_ASSERTION: {
951
1205
  rbs_ast_ruby_annotations_node_type_assertion_t *node = (rbs_ast_ruby_annotations_node_type_assertion_t *) instance;
952
1206
 
953
- VALUE h = rb_hash_new();
954
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
955
- rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
956
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
1207
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1208
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1209
+ VALUE arg_prefix_location = rbs_location_range_to_ruby_location(ctx, node->prefix_location);
1210
+ VALUE arg_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type); // rbs_node
957
1211
 
958
- return CLASS_NEW_INSTANCE(
959
- RBS_AST_Ruby_Annotations_NodeTypeAssertion,
960
- 1,
961
- &h
962
- );
1212
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1213
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1214
+ VALUE h = ctx.reusable_kwargs_hash;
1215
+ rb_hash_clear(h);
1216
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1217
+ rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), arg_prefix_location);
1218
+ rb_hash_aset(h, ID2SYM(rb_intern("type")), arg_type);
1219
+ return CLASS_NEW_INSTANCE(RBS_AST_Ruby_Annotations_NodeTypeAssertion, 1, &h);
963
1220
  }
964
1221
  case RBS_AST_RUBY_ANNOTATIONS_PARAM_TYPE_ANNOTATION: {
965
1222
  rbs_ast_ruby_annotations_param_type_annotation_t *node = (rbs_ast_ruby_annotations_param_type_annotation_t *) instance;
966
1223
 
967
- VALUE h = rb_hash_new();
968
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
969
- rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
970
- rb_hash_aset(h, ID2SYM(rb_intern("name_location")), rbs_location_range_to_ruby_location(ctx, node->name_location));
971
- rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), rbs_location_range_to_ruby_location(ctx, node->colon_location));
972
- rb_hash_aset(h, ID2SYM(rb_intern("param_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->param_type)); // rbs_node
973
- rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional
974
-
975
- return CLASS_NEW_INSTANCE(
976
- RBS_AST_Ruby_Annotations_ParamTypeAnnotation,
977
- 1,
978
- &h
979
- );
1224
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1225
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1226
+ VALUE arg_prefix_location = rbs_location_range_to_ruby_location(ctx, node->prefix_location);
1227
+ VALUE arg_name_location = rbs_location_range_to_ruby_location(ctx, node->name_location);
1228
+ VALUE arg_colon_location = rbs_location_range_to_ruby_location(ctx, node->colon_location);
1229
+ VALUE arg_param_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->param_type); // rbs_node
1230
+ VALUE arg_comment_location = rbs_location_range_to_ruby_location(ctx, node->comment_location); // optional
1231
+
1232
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1233
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1234
+ VALUE h = ctx.reusable_kwargs_hash;
1235
+ rb_hash_clear(h);
1236
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1237
+ rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), arg_prefix_location);
1238
+ rb_hash_aset(h, ID2SYM(rb_intern("name_location")), arg_name_location);
1239
+ rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), arg_colon_location);
1240
+ rb_hash_aset(h, ID2SYM(rb_intern("param_type")), arg_param_type);
1241
+ rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), arg_comment_location);
1242
+ return CLASS_NEW_INSTANCE(RBS_AST_Ruby_Annotations_ParamTypeAnnotation, 1, &h);
980
1243
  }
981
1244
  case RBS_AST_RUBY_ANNOTATIONS_RETURN_TYPE_ANNOTATION: {
982
1245
  rbs_ast_ruby_annotations_return_type_annotation_t *node = (rbs_ast_ruby_annotations_return_type_annotation_t *) instance;
983
1246
 
984
- VALUE h = rb_hash_new();
985
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
986
- rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
987
- rb_hash_aset(h, ID2SYM(rb_intern("return_location")), rbs_location_range_to_ruby_location(ctx, node->return_location));
988
- rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), rbs_location_range_to_ruby_location(ctx, node->colon_location));
989
- rb_hash_aset(h, ID2SYM(rb_intern("return_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->return_type)); // rbs_node
990
- rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional
991
-
992
- return CLASS_NEW_INSTANCE(
993
- RBS_AST_Ruby_Annotations_ReturnTypeAnnotation,
994
- 1,
995
- &h
996
- );
1247
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1248
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1249
+ VALUE arg_prefix_location = rbs_location_range_to_ruby_location(ctx, node->prefix_location);
1250
+ VALUE arg_return_location = rbs_location_range_to_ruby_location(ctx, node->return_location);
1251
+ VALUE arg_colon_location = rbs_location_range_to_ruby_location(ctx, node->colon_location);
1252
+ VALUE arg_return_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->return_type); // rbs_node
1253
+ VALUE arg_comment_location = rbs_location_range_to_ruby_location(ctx, node->comment_location); // optional
1254
+
1255
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1256
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1257
+ VALUE h = ctx.reusable_kwargs_hash;
1258
+ rb_hash_clear(h);
1259
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1260
+ rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), arg_prefix_location);
1261
+ rb_hash_aset(h, ID2SYM(rb_intern("return_location")), arg_return_location);
1262
+ rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), arg_colon_location);
1263
+ rb_hash_aset(h, ID2SYM(rb_intern("return_type")), arg_return_type);
1264
+ rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), arg_comment_location);
1265
+ return CLASS_NEW_INSTANCE(RBS_AST_Ruby_Annotations_ReturnTypeAnnotation, 1, &h);
997
1266
  }
998
1267
  case RBS_AST_RUBY_ANNOTATIONS_SKIP_ANNOTATION: {
999
1268
  rbs_ast_ruby_annotations_skip_annotation_t *node = (rbs_ast_ruby_annotations_skip_annotation_t *) instance;
1000
1269
 
1001
- VALUE h = rb_hash_new();
1002
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1003
- rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
1004
- rb_hash_aset(h, ID2SYM(rb_intern("skip_location")), rbs_location_range_to_ruby_location(ctx, node->skip_location));
1005
- rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional
1006
-
1007
- return CLASS_NEW_INSTANCE(
1008
- RBS_AST_Ruby_Annotations_SkipAnnotation,
1009
- 1,
1010
- &h
1011
- );
1270
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1271
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1272
+ VALUE arg_prefix_location = rbs_location_range_to_ruby_location(ctx, node->prefix_location);
1273
+ VALUE arg_skip_location = rbs_location_range_to_ruby_location(ctx, node->skip_location);
1274
+ VALUE arg_comment_location = rbs_location_range_to_ruby_location(ctx, node->comment_location); // optional
1275
+
1276
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1277
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1278
+ VALUE h = ctx.reusable_kwargs_hash;
1279
+ rb_hash_clear(h);
1280
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1281
+ rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), arg_prefix_location);
1282
+ rb_hash_aset(h, ID2SYM(rb_intern("skip_location")), arg_skip_location);
1283
+ rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), arg_comment_location);
1284
+ return CLASS_NEW_INSTANCE(RBS_AST_Ruby_Annotations_SkipAnnotation, 1, &h);
1012
1285
  }
1013
1286
  case RBS_AST_RUBY_ANNOTATIONS_SPLAT_PARAM_TYPE_ANNOTATION: {
1014
1287
  rbs_ast_ruby_annotations_splat_param_type_annotation_t *node = (rbs_ast_ruby_annotations_splat_param_type_annotation_t *) instance;
1015
1288
 
1016
- VALUE h = rb_hash_new();
1017
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1018
- rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
1019
- rb_hash_aset(h, ID2SYM(rb_intern("star_location")), rbs_location_range_to_ruby_location(ctx, node->star_location));
1020
- rb_hash_aset(h, ID2SYM(rb_intern("name_location")), rbs_location_range_to_ruby_location(ctx, node->name_location)); // optional
1021
- rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), rbs_location_range_to_ruby_location(ctx, node->colon_location));
1022
- rb_hash_aset(h, ID2SYM(rb_intern("param_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->param_type)); // rbs_node
1023
- rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional
1024
-
1025
- return CLASS_NEW_INSTANCE(
1026
- RBS_AST_Ruby_Annotations_SplatParamTypeAnnotation,
1027
- 1,
1028
- &h
1029
- );
1289
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1290
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1291
+ VALUE arg_prefix_location = rbs_location_range_to_ruby_location(ctx, node->prefix_location);
1292
+ VALUE arg_star_location = rbs_location_range_to_ruby_location(ctx, node->star_location);
1293
+ VALUE arg_name_location = rbs_location_range_to_ruby_location(ctx, node->name_location); // optional
1294
+ VALUE arg_colon_location = rbs_location_range_to_ruby_location(ctx, node->colon_location);
1295
+ VALUE arg_param_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->param_type); // rbs_node
1296
+ VALUE arg_comment_location = rbs_location_range_to_ruby_location(ctx, node->comment_location); // optional
1297
+
1298
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1299
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1300
+ VALUE h = ctx.reusable_kwargs_hash;
1301
+ rb_hash_clear(h);
1302
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1303
+ rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), arg_prefix_location);
1304
+ rb_hash_aset(h, ID2SYM(rb_intern("star_location")), arg_star_location);
1305
+ rb_hash_aset(h, ID2SYM(rb_intern("name_location")), arg_name_location);
1306
+ rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), arg_colon_location);
1307
+ rb_hash_aset(h, ID2SYM(rb_intern("param_type")), arg_param_type);
1308
+ rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), arg_comment_location);
1309
+ return CLASS_NEW_INSTANCE(RBS_AST_Ruby_Annotations_SplatParamTypeAnnotation, 1, &h);
1030
1310
  }
1031
1311
  case RBS_AST_RUBY_ANNOTATIONS_TYPE_APPLICATION_ANNOTATION: {
1032
1312
  rbs_ast_ruby_annotations_type_application_annotation_t *node = (rbs_ast_ruby_annotations_type_application_annotation_t *) instance;
1033
1313
 
1034
- VALUE h = rb_hash_new();
1035
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1036
- rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
1037
- rb_hash_aset(h, ID2SYM(rb_intern("type_args")), rbs_node_list_to_ruby_array(ctx, node->type_args));
1038
- rb_hash_aset(h, ID2SYM(rb_intern("close_bracket_location")), rbs_location_range_to_ruby_location(ctx, node->close_bracket_location));
1039
- rb_hash_aset(h, ID2SYM(rb_intern("comma_locations")), rbs_location_range_list_to_ruby_array(ctx, node->comma_locations));
1040
-
1041
- return CLASS_NEW_INSTANCE(
1042
- RBS_AST_Ruby_Annotations_TypeApplicationAnnotation,
1043
- 1,
1044
- &h
1045
- );
1314
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1315
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1316
+ VALUE arg_prefix_location = rbs_location_range_to_ruby_location(ctx, node->prefix_location);
1317
+ VALUE arg_type_args = rbs_node_list_to_ruby_array(ctx, node->type_args);
1318
+ VALUE arg_close_bracket_location = rbs_location_range_to_ruby_location(ctx, node->close_bracket_location);
1319
+ VALUE arg_comma_locations = rbs_location_range_list_to_ruby_array(ctx, node->comma_locations);
1320
+
1321
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1322
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1323
+ VALUE h = ctx.reusable_kwargs_hash;
1324
+ rb_hash_clear(h);
1325
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1326
+ rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), arg_prefix_location);
1327
+ rb_hash_aset(h, ID2SYM(rb_intern("type_args")), arg_type_args);
1328
+ rb_hash_aset(h, ID2SYM(rb_intern("close_bracket_location")), arg_close_bracket_location);
1329
+ rb_hash_aset(h, ID2SYM(rb_intern("comma_locations")), arg_comma_locations);
1330
+ return CLASS_NEW_INSTANCE(RBS_AST_Ruby_Annotations_TypeApplicationAnnotation, 1, &h);
1046
1331
  }
1047
1332
  case RBS_AST_STRING: {
1048
1333
  rbs_ast_string_t *string_node = (rbs_ast_string_t *) instance;
@@ -1053,68 +1338,71 @@ VALUE rbs_struct_to_ruby_value(rbs_translation_context_t ctx, rbs_node_t *instan
1053
1338
  case RBS_AST_TYPE_PARAM: {
1054
1339
  rbs_ast_type_param_t *node = (rbs_ast_type_param_t *) instance;
1055
1340
 
1056
- VALUE h = rb_hash_new();
1057
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1058
- rbs_loc *loc = rbs_check_location(location);
1059
- rbs_loc_legacy_alloc_children(loc, 6);
1060
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
1061
- rbs_loc_legacy_add_optional_child(loc, rb_intern("variance"), (rbs_loc_range) { .start = node->variance_range.start_char, .end = node->variance_range.end_char });
1062
- rbs_loc_legacy_add_optional_child(loc, rb_intern("unchecked"), (rbs_loc_range) { .start = node->unchecked_range.start_char, .end = node->unchecked_range.end_char });
1063
- rbs_loc_legacy_add_optional_child(loc, rb_intern("upper_bound"), (rbs_loc_range) { .start = node->upper_bound_range.start_char, .end = node->upper_bound_range.end_char });
1064
- rbs_loc_legacy_add_optional_child(loc, rb_intern("lower_bound"), (rbs_loc_range) { .start = node->lower_bound_range.start_char, .end = node->lower_bound_range.end_char });
1065
- rbs_loc_legacy_add_optional_child(loc, rb_intern("default"), (rbs_loc_range) { .start = node->default_range.start_char, .end = node->default_range.end_char });
1066
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
1067
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol
1068
- rb_hash_aset(h, ID2SYM(rb_intern("variance")), rbs_type_param_variance_to_ruby(node->variance)); // type_param_variance
1069
- rb_hash_aset(h, ID2SYM(rb_intern("upper_bound")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->upper_bound)); // rbs_node
1070
- rb_hash_aset(h, ID2SYM(rb_intern("lower_bound")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->lower_bound)); // rbs_node
1071
- rb_hash_aset(h, ID2SYM(rb_intern("default_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->default_type)); // rbs_node
1072
- rb_hash_aset(h, ID2SYM(rb_intern("unchecked")), node->unchecked ? Qtrue : Qfalse);
1073
-
1074
- return CLASS_NEW_INSTANCE(
1075
- RBS_AST_TypeParam,
1076
- 1,
1077
- &h
1078
- );
1341
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1342
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1343
+ rbs_loc *loc = rbs_check_location(arg_location);
1344
+ {
1345
+ rbs_loc_legacy_alloc_children(loc, 6);
1346
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
1347
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("variance"), (rbs_loc_range) { .start = node->variance_range.start_char, .end = node->variance_range.end_char });
1348
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("unchecked"), (rbs_loc_range) { .start = node->unchecked_range.start_char, .end = node->unchecked_range.end_char });
1349
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("upper_bound"), (rbs_loc_range) { .start = node->upper_bound_range.start_char, .end = node->upper_bound_range.end_char });
1350
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("lower_bound"), (rbs_loc_range) { .start = node->lower_bound_range.start_char, .end = node->lower_bound_range.end_char });
1351
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("default"), (rbs_loc_range) { .start = node->default_range.start_char, .end = node->default_range.end_char });
1352
+ }
1353
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_ast_symbol
1354
+ VALUE arg_variance = rbs_type_param_variance_to_ruby(node->variance); // type_param_variance
1355
+ VALUE arg_upper_bound = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->upper_bound); // rbs_node
1356
+ VALUE arg_lower_bound = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->lower_bound); // rbs_node
1357
+ VALUE arg_default_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->default_type); // rbs_node
1358
+ VALUE arg_unchecked = node->unchecked ? Qtrue : Qfalse;
1359
+
1360
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1361
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1362
+ VALUE h = ctx.reusable_kwargs_hash;
1363
+ rb_hash_clear(h);
1364
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1365
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
1366
+ rb_hash_aset(h, ID2SYM(rb_intern("variance")), arg_variance);
1367
+ rb_hash_aset(h, ID2SYM(rb_intern("upper_bound")), arg_upper_bound);
1368
+ rb_hash_aset(h, ID2SYM(rb_intern("lower_bound")), arg_lower_bound);
1369
+ rb_hash_aset(h, ID2SYM(rb_intern("default_type")), arg_default_type);
1370
+ rb_hash_aset(h, ID2SYM(rb_intern("unchecked")), arg_unchecked);
1371
+ return CLASS_NEW_INSTANCE(RBS_AST_TypeParam, 1, &h);
1079
1372
  }
1080
1373
  case RBS_METHOD_TYPE: {
1081
1374
  rbs_method_type_t *node = (rbs_method_type_t *) instance;
1082
1375
 
1083
- VALUE h = rb_hash_new();
1084
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1085
- rbs_loc *loc = rbs_check_location(location);
1086
- rbs_loc_legacy_alloc_children(loc, 2);
1087
- rbs_loc_legacy_add_required_child(loc, rb_intern("type"), (rbs_loc_range) { .start = node->type_range.start_char, .end = node->type_range.end_char });
1088
- rbs_loc_legacy_add_optional_child(loc, rb_intern("type_params"), (rbs_loc_range) { .start = node->type_params_range.start_char, .end = node->type_params_range.end_char });
1089
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
1090
- rb_hash_aset(h, ID2SYM(rb_intern("type_params")), rbs_node_list_to_ruby_array(ctx, node->type_params));
1091
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
1092
- rb_hash_aset(h, ID2SYM(rb_intern("block")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->block)); // rbs_types_block
1376
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1377
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1378
+ rbs_loc *loc = rbs_check_location(arg_location);
1379
+ {
1380
+ rbs_loc_legacy_alloc_children(loc, 2);
1381
+ rbs_loc_legacy_add_required_child(loc, rb_intern("type"), (rbs_loc_range) { .start = node->type_range.start_char, .end = node->type_range.end_char });
1382
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("type_params"), (rbs_loc_range) { .start = node->type_params_range.start_char, .end = node->type_params_range.end_char });
1383
+ }
1384
+ VALUE arg_type_params = rbs_node_list_to_ruby_array(ctx, node->type_params);
1385
+ VALUE arg_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type); // rbs_node
1386
+ VALUE arg_block = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->block); // rbs_types_block
1093
1387
 
1094
1388
  rb_funcall(
1095
1389
  RBS_AST_TypeParam,
1096
1390
  rb_intern("resolve_variables"),
1097
1391
  1,
1098
- rb_hash_lookup(h, ID2SYM(rb_intern("type_params")))
1099
- );
1100
- return CLASS_NEW_INSTANCE(
1101
- RBS_MethodType,
1102
- 1,
1103
- &h
1392
+ arg_type_params
1104
1393
  );
1394
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1395
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1396
+ VALUE h = ctx.reusable_kwargs_hash;
1397
+ rb_hash_clear(h);
1398
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1399
+ rb_hash_aset(h, ID2SYM(rb_intern("type_params")), arg_type_params);
1400
+ rb_hash_aset(h, ID2SYM(rb_intern("type")), arg_type);
1401
+ rb_hash_aset(h, ID2SYM(rb_intern("block")), arg_block);
1402
+ return CLASS_NEW_INSTANCE(RBS_MethodType, 1, &h);
1105
1403
  }
1106
1404
  case RBS_NAMESPACE: {
1107
- rbs_namespace_t *node = (rbs_namespace_t *) instance;
1108
-
1109
- VALUE h = rb_hash_new();
1110
- rb_hash_aset(h, ID2SYM(rb_intern("path")), rbs_node_list_to_ruby_array(ctx, node->path));
1111
- rb_hash_aset(h, ID2SYM(rb_intern("absolute")), node->absolute ? Qtrue : Qfalse);
1112
-
1113
- return CLASS_NEW_INSTANCE(
1114
- RBS_Namespace,
1115
- 1,
1116
- &h
1117
- );
1405
+ return rbs_intern_namespace(ctx, (rbs_namespace_t *) instance);
1118
1406
  }
1119
1407
  case RBS_SIGNATURE: {
1120
1408
  rbs_signature_t *signature = (rbs_signature_t *) instance;
@@ -1126,320 +1414,367 @@ VALUE rbs_struct_to_ruby_value(rbs_translation_context_t ctx, rbs_node_t *instan
1126
1414
  }
1127
1415
  case RBS_TYPE_NAME: {
1128
1416
  rbs_type_name_t *node = (rbs_type_name_t *) instance;
1129
-
1130
- VALUE h = rb_hash_new();
1131
- rb_hash_aset(h, ID2SYM(rb_intern("namespace")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->rbs_namespace)); // rbs_namespace
1132
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol
1133
-
1134
- return CLASS_NEW_INSTANCE(
1135
- RBS_TypeName,
1136
- 1,
1137
- &h
1138
- );
1417
+ VALUE ns = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->rbs_namespace);
1418
+ VALUE name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name);
1419
+ return rbs_intern_type_name(ns, name);
1139
1420
  }
1140
1421
  case RBS_TYPES_ALIAS: {
1141
1422
  rbs_types_alias_t *node = (rbs_types_alias_t *) instance;
1142
1423
 
1143
- VALUE h = rb_hash_new();
1144
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1145
- rbs_loc *loc = rbs_check_location(location);
1146
- rbs_loc_legacy_alloc_children(loc, 2);
1147
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
1148
- rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
1149
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
1150
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
1151
- rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));
1152
-
1153
- return CLASS_NEW_INSTANCE(
1154
- RBS_Types_Alias,
1155
- 1,
1156
- &h
1157
- );
1424
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1425
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1426
+ rbs_loc *loc = rbs_check_location(arg_location);
1427
+ {
1428
+ rbs_loc_legacy_alloc_children(loc, 2);
1429
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
1430
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
1431
+ }
1432
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_type_name
1433
+ VALUE arg_args = rbs_node_list_to_ruby_array(ctx, node->args);
1434
+
1435
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1436
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1437
+ VALUE h = ctx.reusable_kwargs_hash;
1438
+ rb_hash_clear(h);
1439
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1440
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
1441
+ rb_hash_aset(h, ID2SYM(rb_intern("args")), arg_args);
1442
+ return CLASS_NEW_INSTANCE(RBS_Types_Alias, 1, &h);
1158
1443
  }
1159
1444
  case RBS_TYPES_BASES_ANY: {
1160
1445
  rbs_types_bases_any_t *node = (rbs_types_bases_any_t *) instance;
1161
1446
 
1162
- VALUE h = rb_hash_new();
1163
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1164
- rb_hash_aset(h, ID2SYM(rb_intern("todo")), node->todo ? Qtrue : Qfalse);
1447
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1448
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1449
+ VALUE arg_todo = node->todo ? Qtrue : Qfalse;
1165
1450
 
1166
- return CLASS_NEW_INSTANCE(
1167
- RBS_Types_Bases_Any,
1168
- 1,
1169
- &h
1170
- );
1451
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1452
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1453
+ VALUE h = ctx.reusable_kwargs_hash;
1454
+ rb_hash_clear(h);
1455
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1456
+ rb_hash_aset(h, ID2SYM(rb_intern("todo")), arg_todo);
1457
+ return CLASS_NEW_INSTANCE(RBS_Types_Bases_Any, 1, &h);
1171
1458
  }
1172
1459
  case RBS_TYPES_BASES_BOOL: {
1173
1460
  rbs_types_bases_bool_t *node = (rbs_types_bases_bool_t *) instance;
1174
1461
 
1175
- VALUE h = rb_hash_new();
1176
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1462
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1463
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1177
1464
 
1178
- return CLASS_NEW_INSTANCE(
1179
- RBS_Types_Bases_Bool,
1180
- 1,
1181
- &h
1182
- );
1465
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1466
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1467
+ VALUE h = ctx.reusable_kwargs_hash;
1468
+ rb_hash_clear(h);
1469
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1470
+ return CLASS_NEW_INSTANCE(RBS_Types_Bases_Bool, 1, &h);
1183
1471
  }
1184
1472
  case RBS_TYPES_BASES_BOTTOM: {
1185
1473
  rbs_types_bases_bottom_t *node = (rbs_types_bases_bottom_t *) instance;
1186
1474
 
1187
- VALUE h = rb_hash_new();
1188
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1475
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1476
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1189
1477
 
1190
- return CLASS_NEW_INSTANCE(
1191
- RBS_Types_Bases_Bottom,
1192
- 1,
1193
- &h
1194
- );
1478
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1479
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1480
+ VALUE h = ctx.reusable_kwargs_hash;
1481
+ rb_hash_clear(h);
1482
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1483
+ return CLASS_NEW_INSTANCE(RBS_Types_Bases_Bottom, 1, &h);
1195
1484
  }
1196
1485
  case RBS_TYPES_BASES_CLASS: {
1197
1486
  rbs_types_bases_class_t *node = (rbs_types_bases_class_t *) instance;
1198
1487
 
1199
- VALUE h = rb_hash_new();
1200
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1488
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1489
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1201
1490
 
1202
- return CLASS_NEW_INSTANCE(
1203
- RBS_Types_Bases_Class,
1204
- 1,
1205
- &h
1206
- );
1491
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1492
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1493
+ VALUE h = ctx.reusable_kwargs_hash;
1494
+ rb_hash_clear(h);
1495
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1496
+ return CLASS_NEW_INSTANCE(RBS_Types_Bases_Class, 1, &h);
1207
1497
  }
1208
1498
  case RBS_TYPES_BASES_INSTANCE: {
1209
1499
  rbs_types_bases_instance_t *node = (rbs_types_bases_instance_t *) instance;
1210
1500
 
1211
- VALUE h = rb_hash_new();
1212
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1501
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1502
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1213
1503
 
1214
- return CLASS_NEW_INSTANCE(
1215
- RBS_Types_Bases_Instance,
1216
- 1,
1217
- &h
1218
- );
1504
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1505
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1506
+ VALUE h = ctx.reusable_kwargs_hash;
1507
+ rb_hash_clear(h);
1508
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1509
+ return CLASS_NEW_INSTANCE(RBS_Types_Bases_Instance, 1, &h);
1219
1510
  }
1220
1511
  case RBS_TYPES_BASES_NIL: {
1221
1512
  rbs_types_bases_nil_t *node = (rbs_types_bases_nil_t *) instance;
1222
1513
 
1223
- VALUE h = rb_hash_new();
1224
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1514
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1515
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1225
1516
 
1226
- return CLASS_NEW_INSTANCE(
1227
- RBS_Types_Bases_Nil,
1228
- 1,
1229
- &h
1230
- );
1517
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1518
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1519
+ VALUE h = ctx.reusable_kwargs_hash;
1520
+ rb_hash_clear(h);
1521
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1522
+ return CLASS_NEW_INSTANCE(RBS_Types_Bases_Nil, 1, &h);
1231
1523
  }
1232
1524
  case RBS_TYPES_BASES_SELF: {
1233
1525
  rbs_types_bases_self_t *node = (rbs_types_bases_self_t *) instance;
1234
1526
 
1235
- VALUE h = rb_hash_new();
1236
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1527
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1528
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1237
1529
 
1238
- return CLASS_NEW_INSTANCE(
1239
- RBS_Types_Bases_Self,
1240
- 1,
1241
- &h
1242
- );
1530
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1531
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1532
+ VALUE h = ctx.reusable_kwargs_hash;
1533
+ rb_hash_clear(h);
1534
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1535
+ return CLASS_NEW_INSTANCE(RBS_Types_Bases_Self, 1, &h);
1243
1536
  }
1244
1537
  case RBS_TYPES_BASES_TOP: {
1245
1538
  rbs_types_bases_top_t *node = (rbs_types_bases_top_t *) instance;
1246
1539
 
1247
- VALUE h = rb_hash_new();
1248
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1540
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1541
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1249
1542
 
1250
- return CLASS_NEW_INSTANCE(
1251
- RBS_Types_Bases_Top,
1252
- 1,
1253
- &h
1254
- );
1543
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1544
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1545
+ VALUE h = ctx.reusable_kwargs_hash;
1546
+ rb_hash_clear(h);
1547
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1548
+ return CLASS_NEW_INSTANCE(RBS_Types_Bases_Top, 1, &h);
1255
1549
  }
1256
1550
  case RBS_TYPES_BASES_VOID: {
1257
1551
  rbs_types_bases_void_t *node = (rbs_types_bases_void_t *) instance;
1258
1552
 
1259
- VALUE h = rb_hash_new();
1260
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1553
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1554
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1261
1555
 
1262
- return CLASS_NEW_INSTANCE(
1263
- RBS_Types_Bases_Void,
1264
- 1,
1265
- &h
1266
- );
1556
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1557
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1558
+ VALUE h = ctx.reusable_kwargs_hash;
1559
+ rb_hash_clear(h);
1560
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1561
+ return CLASS_NEW_INSTANCE(RBS_Types_Bases_Void, 1, &h);
1267
1562
  }
1268
1563
  case RBS_TYPES_BLOCK: {
1269
1564
  rbs_types_block_t *node = (rbs_types_block_t *) instance;
1270
1565
 
1271
- VALUE h = rb_hash_new();
1272
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1273
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
1274
- rb_hash_aset(h, ID2SYM(rb_intern("required")), node->required ? Qtrue : Qfalse);
1275
- rb_hash_aset(h, ID2SYM(rb_intern("self_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->self_type)); // rbs_node
1276
-
1277
- return CLASS_NEW_INSTANCE(
1278
- RBS_Types_Block,
1279
- 1,
1280
- &h
1281
- );
1566
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1567
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1568
+ VALUE arg_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type); // rbs_node
1569
+ VALUE arg_required = node->required ? Qtrue : Qfalse;
1570
+ VALUE arg_self_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->self_type); // rbs_node
1571
+
1572
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1573
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1574
+ VALUE h = ctx.reusable_kwargs_hash;
1575
+ rb_hash_clear(h);
1576
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1577
+ rb_hash_aset(h, ID2SYM(rb_intern("type")), arg_type);
1578
+ rb_hash_aset(h, ID2SYM(rb_intern("required")), arg_required);
1579
+ rb_hash_aset(h, ID2SYM(rb_intern("self_type")), arg_self_type);
1580
+ return CLASS_NEW_INSTANCE(RBS_Types_Block, 1, &h);
1282
1581
  }
1283
1582
  case RBS_TYPES_CLASS_INSTANCE: {
1284
1583
  rbs_types_class_instance_t *node = (rbs_types_class_instance_t *) instance;
1285
1584
 
1286
- VALUE h = rb_hash_new();
1287
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1288
- rbs_loc *loc = rbs_check_location(location);
1289
- rbs_loc_legacy_alloc_children(loc, 2);
1290
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
1291
- rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
1292
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
1293
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
1294
- rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));
1295
-
1296
- return CLASS_NEW_INSTANCE(
1297
- RBS_Types_ClassInstance,
1298
- 1,
1299
- &h
1300
- );
1585
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1586
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1587
+ rbs_loc *loc = rbs_check_location(arg_location);
1588
+ {
1589
+ rbs_loc_legacy_alloc_children(loc, 2);
1590
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
1591
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
1592
+ }
1593
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_type_name
1594
+ VALUE arg_args = rbs_node_list_to_ruby_array(ctx, node->args);
1595
+
1596
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1597
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1598
+ VALUE h = ctx.reusable_kwargs_hash;
1599
+ rb_hash_clear(h);
1600
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1601
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
1602
+ rb_hash_aset(h, ID2SYM(rb_intern("args")), arg_args);
1603
+ return CLASS_NEW_INSTANCE(RBS_Types_ClassInstance, 1, &h);
1301
1604
  }
1302
1605
  case RBS_TYPES_CLASS_SINGLETON: {
1303
1606
  rbs_types_class_singleton_t *node = (rbs_types_class_singleton_t *) instance;
1304
1607
 
1305
- VALUE h = rb_hash_new();
1306
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1307
- rbs_loc *loc = rbs_check_location(location);
1308
- rbs_loc_legacy_alloc_children(loc, 2);
1309
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
1310
- rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
1311
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
1312
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
1313
- rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));
1314
-
1315
- return CLASS_NEW_INSTANCE(
1316
- RBS_Types_ClassSingleton,
1317
- 1,
1318
- &h
1319
- );
1608
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1609
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1610
+ rbs_loc *loc = rbs_check_location(arg_location);
1611
+ {
1612
+ rbs_loc_legacy_alloc_children(loc, 2);
1613
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
1614
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
1615
+ }
1616
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_type_name
1617
+ VALUE arg_args = rbs_node_list_to_ruby_array(ctx, node->args);
1618
+
1619
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1620
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1621
+ VALUE h = ctx.reusable_kwargs_hash;
1622
+ rb_hash_clear(h);
1623
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1624
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
1625
+ rb_hash_aset(h, ID2SYM(rb_intern("args")), arg_args);
1626
+ return CLASS_NEW_INSTANCE(RBS_Types_ClassSingleton, 1, &h);
1320
1627
  }
1321
1628
  case RBS_TYPES_FUNCTION: {
1322
1629
  rbs_types_function_t *node = (rbs_types_function_t *) instance;
1323
1630
 
1324
- VALUE h = rb_hash_new();
1325
- rb_hash_aset(h, ID2SYM(rb_intern("required_positionals")), rbs_node_list_to_ruby_array(ctx, node->required_positionals));
1326
- rb_hash_aset(h, ID2SYM(rb_intern("optional_positionals")), rbs_node_list_to_ruby_array(ctx, node->optional_positionals));
1327
- rb_hash_aset(h, ID2SYM(rb_intern("rest_positionals")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->rest_positionals)); // rbs_node
1328
- rb_hash_aset(h, ID2SYM(rb_intern("trailing_positionals")), rbs_node_list_to_ruby_array(ctx, node->trailing_positionals));
1329
- rb_hash_aset(h, ID2SYM(rb_intern("required_keywords")), rbs_hash_to_ruby_hash(ctx, node->required_keywords));
1330
- rb_hash_aset(h, ID2SYM(rb_intern("optional_keywords")), rbs_hash_to_ruby_hash(ctx, node->optional_keywords));
1331
- rb_hash_aset(h, ID2SYM(rb_intern("rest_keywords")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->rest_keywords)); // rbs_node
1332
- rb_hash_aset(h, ID2SYM(rb_intern("return_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->return_type)); // rbs_node
1333
-
1334
- return CLASS_NEW_INSTANCE(
1335
- RBS_Types_Function,
1336
- 1,
1337
- &h
1338
- );
1631
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1632
+ VALUE arg_required_positionals = rbs_node_list_to_ruby_array(ctx, node->required_positionals);
1633
+ VALUE arg_optional_positionals = rbs_node_list_to_ruby_array(ctx, node->optional_positionals);
1634
+ VALUE arg_rest_positionals = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->rest_positionals); // rbs_node
1635
+ VALUE arg_trailing_positionals = rbs_node_list_to_ruby_array(ctx, node->trailing_positionals);
1636
+ VALUE arg_required_keywords = rbs_hash_to_ruby_hash(ctx, node->required_keywords);
1637
+ VALUE arg_optional_keywords = rbs_hash_to_ruby_hash(ctx, node->optional_keywords);
1638
+ VALUE arg_rest_keywords = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->rest_keywords); // rbs_node
1639
+ VALUE arg_return_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->return_type); // rbs_node
1640
+
1641
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1642
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1643
+ VALUE h = ctx.reusable_kwargs_hash;
1644
+ rb_hash_clear(h);
1645
+ rb_hash_aset(h, ID2SYM(rb_intern("required_positionals")), arg_required_positionals);
1646
+ rb_hash_aset(h, ID2SYM(rb_intern("optional_positionals")), arg_optional_positionals);
1647
+ rb_hash_aset(h, ID2SYM(rb_intern("rest_positionals")), arg_rest_positionals);
1648
+ rb_hash_aset(h, ID2SYM(rb_intern("trailing_positionals")), arg_trailing_positionals);
1649
+ rb_hash_aset(h, ID2SYM(rb_intern("required_keywords")), arg_required_keywords);
1650
+ rb_hash_aset(h, ID2SYM(rb_intern("optional_keywords")), arg_optional_keywords);
1651
+ rb_hash_aset(h, ID2SYM(rb_intern("rest_keywords")), arg_rest_keywords);
1652
+ rb_hash_aset(h, ID2SYM(rb_intern("return_type")), arg_return_type);
1653
+ return CLASS_NEW_INSTANCE(RBS_Types_Function, 1, &h);
1339
1654
  }
1340
1655
  case RBS_TYPES_FUNCTION_PARAM: {
1341
1656
  rbs_types_function_param_t *node = (rbs_types_function_param_t *) instance;
1342
1657
 
1343
- VALUE h = rb_hash_new();
1344
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1345
- rbs_loc *loc = rbs_check_location(location);
1346
- rbs_loc_legacy_alloc_children(loc, 1);
1347
- rbs_loc_legacy_add_optional_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
1348
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
1349
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
1350
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol
1351
-
1352
- return CLASS_NEW_INSTANCE(
1353
- RBS_Types_Function_Param,
1354
- 1,
1355
- &h
1356
- );
1658
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1659
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1660
+ rbs_loc *loc = rbs_check_location(arg_location);
1661
+ {
1662
+ rbs_loc_legacy_alloc_children(loc, 1);
1663
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
1664
+ }
1665
+ VALUE arg_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type); // rbs_node
1666
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_ast_symbol
1667
+
1668
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1669
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1670
+ VALUE h = ctx.reusable_kwargs_hash;
1671
+ rb_hash_clear(h);
1672
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1673
+ rb_hash_aset(h, ID2SYM(rb_intern("type")), arg_type);
1674
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
1675
+ return CLASS_NEW_INSTANCE(RBS_Types_Function_Param, 1, &h);
1357
1676
  }
1358
1677
  case RBS_TYPES_INTERFACE: {
1359
1678
  rbs_types_interface_t *node = (rbs_types_interface_t *) instance;
1360
1679
 
1361
- VALUE h = rb_hash_new();
1362
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1363
- rbs_loc *loc = rbs_check_location(location);
1364
- rbs_loc_legacy_alloc_children(loc, 2);
1365
- rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
1366
- rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
1367
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
1368
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
1369
- rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));
1370
-
1371
- return CLASS_NEW_INSTANCE(
1372
- RBS_Types_Interface,
1373
- 1,
1374
- &h
1375
- );
1680
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1681
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1682
+ rbs_loc *loc = rbs_check_location(arg_location);
1683
+ {
1684
+ rbs_loc_legacy_alloc_children(loc, 2);
1685
+ rbs_loc_legacy_add_required_child(loc, rb_intern("name"), (rbs_loc_range) { .start = node->name_range.start_char, .end = node->name_range.end_char });
1686
+ rbs_loc_legacy_add_optional_child(loc, rb_intern("args"), (rbs_loc_range) { .start = node->args_range.start_char, .end = node->args_range.end_char });
1687
+ }
1688
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_type_name
1689
+ VALUE arg_args = rbs_node_list_to_ruby_array(ctx, node->args);
1690
+
1691
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1692
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1693
+ VALUE h = ctx.reusable_kwargs_hash;
1694
+ rb_hash_clear(h);
1695
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1696
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
1697
+ rb_hash_aset(h, ID2SYM(rb_intern("args")), arg_args);
1698
+ return CLASS_NEW_INSTANCE(RBS_Types_Interface, 1, &h);
1376
1699
  }
1377
1700
  case RBS_TYPES_INTERSECTION: {
1378
1701
  rbs_types_intersection_t *node = (rbs_types_intersection_t *) instance;
1379
1702
 
1380
- VALUE h = rb_hash_new();
1381
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1382
- rb_hash_aset(h, ID2SYM(rb_intern("types")), rbs_node_list_to_ruby_array(ctx, node->types));
1703
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1704
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1705
+ VALUE arg_types = rbs_node_list_to_ruby_array(ctx, node->types);
1383
1706
 
1384
- return CLASS_NEW_INSTANCE(
1385
- RBS_Types_Intersection,
1386
- 1,
1387
- &h
1388
- );
1707
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1708
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1709
+ VALUE h = ctx.reusable_kwargs_hash;
1710
+ rb_hash_clear(h);
1711
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1712
+ rb_hash_aset(h, ID2SYM(rb_intern("types")), arg_types);
1713
+ return CLASS_NEW_INSTANCE(RBS_Types_Intersection, 1, &h);
1389
1714
  }
1390
1715
  case RBS_TYPES_LITERAL: {
1391
1716
  rbs_types_literal_t *node = (rbs_types_literal_t *) instance;
1392
1717
 
1393
- VALUE h = rb_hash_new();
1394
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1395
- rb_hash_aset(h, ID2SYM(rb_intern("literal")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->literal)); // rbs_node
1718
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1719
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1720
+ VALUE arg_literal = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->literal); // rbs_node
1396
1721
 
1397
- return CLASS_NEW_INSTANCE(
1398
- RBS_Types_Literal,
1399
- 1,
1400
- &h
1401
- );
1722
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1723
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1724
+ VALUE h = ctx.reusable_kwargs_hash;
1725
+ rb_hash_clear(h);
1726
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1727
+ rb_hash_aset(h, ID2SYM(rb_intern("literal")), arg_literal);
1728
+ return CLASS_NEW_INSTANCE(RBS_Types_Literal, 1, &h);
1402
1729
  }
1403
1730
  case RBS_TYPES_OPTIONAL: {
1404
1731
  rbs_types_optional_t *node = (rbs_types_optional_t *) instance;
1405
1732
 
1406
- VALUE h = rb_hash_new();
1407
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1408
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
1733
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1734
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1735
+ VALUE arg_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type); // rbs_node
1409
1736
 
1410
- return CLASS_NEW_INSTANCE(
1411
- RBS_Types_Optional,
1412
- 1,
1413
- &h
1414
- );
1737
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1738
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1739
+ VALUE h = ctx.reusable_kwargs_hash;
1740
+ rb_hash_clear(h);
1741
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1742
+ rb_hash_aset(h, ID2SYM(rb_intern("type")), arg_type);
1743
+ return CLASS_NEW_INSTANCE(RBS_Types_Optional, 1, &h);
1415
1744
  }
1416
1745
  case RBS_TYPES_PROC: {
1417
1746
  rbs_types_proc_t *node = (rbs_types_proc_t *) instance;
1418
1747
 
1419
- VALUE h = rb_hash_new();
1420
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1421
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
1422
- rb_hash_aset(h, ID2SYM(rb_intern("block")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->block)); // rbs_types_block
1423
- rb_hash_aset(h, ID2SYM(rb_intern("self_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->self_type)); // rbs_node
1424
-
1425
- return CLASS_NEW_INSTANCE(
1426
- RBS_Types_Proc,
1427
- 1,
1428
- &h
1429
- );
1748
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1749
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1750
+ VALUE arg_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type); // rbs_node
1751
+ VALUE arg_block = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->block); // rbs_types_block
1752
+ VALUE arg_self_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->self_type); // rbs_node
1753
+
1754
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1755
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1756
+ VALUE h = ctx.reusable_kwargs_hash;
1757
+ rb_hash_clear(h);
1758
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1759
+ rb_hash_aset(h, ID2SYM(rb_intern("type")), arg_type);
1760
+ rb_hash_aset(h, ID2SYM(rb_intern("block")), arg_block);
1761
+ rb_hash_aset(h, ID2SYM(rb_intern("self_type")), arg_self_type);
1762
+ return CLASS_NEW_INSTANCE(RBS_Types_Proc, 1, &h);
1430
1763
  }
1431
1764
  case RBS_TYPES_RECORD: {
1432
1765
  rbs_types_record_t *node = (rbs_types_record_t *) instance;
1433
1766
 
1434
- VALUE h = rb_hash_new();
1435
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1436
- rb_hash_aset(h, ID2SYM(rb_intern("all_fields")), rbs_hash_to_ruby_hash(ctx, node->all_fields));
1767
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1768
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1769
+ VALUE arg_all_fields = rbs_hash_to_ruby_hash(ctx, node->all_fields);
1437
1770
 
1438
- return CLASS_NEW_INSTANCE(
1439
- RBS_Types_Record,
1440
- 1,
1441
- &h
1442
- );
1771
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1772
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1773
+ VALUE h = ctx.reusable_kwargs_hash;
1774
+ rb_hash_clear(h);
1775
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1776
+ rb_hash_aset(h, ID2SYM(rb_intern("all_fields")), arg_all_fields);
1777
+ return CLASS_NEW_INSTANCE(RBS_Types_Record, 1, &h);
1443
1778
  }
1444
1779
  case RBS_TYPES_RECORD_FIELD_TYPE: {
1445
1780
  rbs_types_record_field_type_t *record_fieldtype = (rbs_types_record_field_type_t *) instance;
@@ -1452,53 +1787,60 @@ VALUE rbs_struct_to_ruby_value(rbs_translation_context_t ctx, rbs_node_t *instan
1452
1787
  case RBS_TYPES_TUPLE: {
1453
1788
  rbs_types_tuple_t *node = (rbs_types_tuple_t *) instance;
1454
1789
 
1455
- VALUE h = rb_hash_new();
1456
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1457
- rb_hash_aset(h, ID2SYM(rb_intern("types")), rbs_node_list_to_ruby_array(ctx, node->types));
1790
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1791
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1792
+ VALUE arg_types = rbs_node_list_to_ruby_array(ctx, node->types);
1458
1793
 
1459
- return CLASS_NEW_INSTANCE(
1460
- RBS_Types_Tuple,
1461
- 1,
1462
- &h
1463
- );
1794
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1795
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1796
+ VALUE h = ctx.reusable_kwargs_hash;
1797
+ rb_hash_clear(h);
1798
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1799
+ rb_hash_aset(h, ID2SYM(rb_intern("types")), arg_types);
1800
+ return CLASS_NEW_INSTANCE(RBS_Types_Tuple, 1, &h);
1464
1801
  }
1465
1802
  case RBS_TYPES_UNION: {
1466
1803
  rbs_types_union_t *node = (rbs_types_union_t *) instance;
1467
1804
 
1468
- VALUE h = rb_hash_new();
1469
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1470
- rb_hash_aset(h, ID2SYM(rb_intern("types")), rbs_node_list_to_ruby_array(ctx, node->types));
1805
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1806
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1807
+ VALUE arg_types = rbs_node_list_to_ruby_array(ctx, node->types);
1471
1808
 
1472
- return CLASS_NEW_INSTANCE(
1473
- RBS_Types_Union,
1474
- 1,
1475
- &h
1476
- );
1809
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1810
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1811
+ VALUE h = ctx.reusable_kwargs_hash;
1812
+ rb_hash_clear(h);
1813
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1814
+ rb_hash_aset(h, ID2SYM(rb_intern("types")), arg_types);
1815
+ return CLASS_NEW_INSTANCE(RBS_Types_Union, 1, &h);
1477
1816
  }
1478
1817
  case RBS_TYPES_UNTYPED_FUNCTION: {
1479
1818
  rbs_types_untyped_function_t *node = (rbs_types_untyped_function_t *) instance;
1480
1819
 
1481
- VALUE h = rb_hash_new();
1482
- rb_hash_aset(h, ID2SYM(rb_intern("return_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->return_type)); // rbs_node
1820
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1821
+ VALUE arg_return_type = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->return_type); // rbs_node
1483
1822
 
1484
- return CLASS_NEW_INSTANCE(
1485
- RBS_Types_UntypedFunction,
1486
- 1,
1487
- &h
1488
- );
1823
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1824
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1825
+ VALUE h = ctx.reusable_kwargs_hash;
1826
+ rb_hash_clear(h);
1827
+ rb_hash_aset(h, ID2SYM(rb_intern("return_type")), arg_return_type);
1828
+ return CLASS_NEW_INSTANCE(RBS_Types_UntypedFunction, 1, &h);
1489
1829
  }
1490
1830
  case RBS_TYPES_VARIABLE: {
1491
1831
  rbs_types_variable_t *node = (rbs_types_variable_t *) instance;
1492
1832
 
1493
- VALUE h = rb_hash_new();
1494
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1495
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol
1496
-
1497
- return CLASS_NEW_INSTANCE(
1498
- RBS_Types_Variable,
1499
- 1,
1500
- &h
1501
- );
1833
+ // Compute child VALUEs into locals variables first, before any recursion into `rbs_struct_to_ruby_value()`.
1834
+ VALUE arg_location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1835
+ VALUE arg_name = rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name); // rbs_ast_symbol
1836
+
1837
+ // Claim the shared kwargs hash, clear it, fill it, and hand it to `.new`.
1838
+ // Must not recurse between `rb_hash_clear()` and `CLASS_NEW_INSTANCE()`.
1839
+ VALUE h = ctx.reusable_kwargs_hash;
1840
+ rb_hash_clear(h);
1841
+ rb_hash_aset(h, ID2SYM(rb_intern("location")), arg_location);
1842
+ rb_hash_aset(h, ID2SYM(rb_intern("name")), arg_name);
1843
+ return CLASS_NEW_INSTANCE(RBS_Types_Variable, 1, &h);
1502
1844
  }
1503
1845
  case RBS_AST_SYMBOL: {
1504
1846
  rbs_constant_t *constant = rbs_constant_pool_id_to_constant(ctx.constant_pool, ((rbs_ast_symbol_t *) instance)->constant_id);