rbs 4.1.0.pre.1 → 4.1.0

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 (130) hide show
  1. checksums.yaml +4 -4
  2. data/.dockerignore +37 -0
  3. data/.github/workflows/bundle-update.yml +1 -1
  4. data/.github/workflows/c-check.yml +14 -6
  5. data/.github/workflows/comments.yml +2 -2
  6. data/.github/workflows/dependabot.yml +2 -2
  7. data/.github/workflows/jruby.yml +79 -0
  8. data/.github/workflows/milestone.yml +13 -2
  9. data/.github/workflows/ruby.yml +16 -4
  10. data/.github/workflows/rust.yml +13 -8
  11. data/.github/workflows/truffleruby.yml +54 -0
  12. data/.github/workflows/typecheck.yml +5 -2
  13. data/.github/workflows/wasm.yml +55 -0
  14. data/.github/workflows/windows.yml +8 -2
  15. data/.gitignore +8 -0
  16. data/CHANGELOG.md +88 -0
  17. data/Dockerfile.jruby +53 -0
  18. data/README.md +3 -3
  19. data/Rakefile +103 -1
  20. data/Steepfile +9 -0
  21. data/core/array.rbs +243 -180
  22. data/core/builtin.rbs +6 -6
  23. data/core/enumerable.rbs +109 -109
  24. data/core/enumerator/product.rbs +5 -5
  25. data/core/enumerator.rbs +28 -28
  26. data/core/file.rbs +24 -1018
  27. data/core/file_constants.rbs +463 -0
  28. data/core/file_stat.rbs +534 -0
  29. data/core/float.rbs +0 -24
  30. data/core/hash.rbs +117 -101
  31. data/core/integer.rbs +21 -58
  32. data/core/io.rbs +25 -7
  33. data/core/match_data.rbs +1 -1
  34. data/core/module.rbs +88 -74
  35. data/core/numeric.rbs +3 -0
  36. data/core/object_space/weak_key_map.rbs +7 -7
  37. data/core/pathname.rbs +0 -10
  38. data/core/ractor.rbs +0 -10
  39. data/core/range.rbs +23 -23
  40. data/core/rbs/ops.rbs +154 -0
  41. data/core/rbs/unnamed/argf.rbs +3 -3
  42. data/core/rubygems/errors.rbs +4 -1
  43. data/core/rubygems/requirement.rbs +0 -10
  44. data/core/rubygems/rubygems.rbs +4 -1
  45. data/core/rubygems/specification.rbs +8 -0
  46. data/core/rubygems/version.rbs +0 -160
  47. data/core/set.rbs +3 -3
  48. data/core/struct.rbs +16 -16
  49. data/core/thread.rbs +9 -14
  50. data/docs/CONTRIBUTING.md +2 -1
  51. data/docs/inline.md +36 -6
  52. data/docs/rbs_by_example.md +20 -20
  53. data/docs/release.md +69 -0
  54. data/docs/syntax.md +2 -2
  55. data/docs/wasm_serialization.md +80 -0
  56. data/ext/rbs_extension/ast_translation.c +1294 -973
  57. data/ext/rbs_extension/ast_translation.h +4 -0
  58. data/ext/rbs_extension/legacy_location.c +11 -6
  59. data/ext/rbs_extension/main.c +139 -4
  60. data/include/rbs/ast.h +9 -1
  61. data/include/rbs/serialize.h +39 -0
  62. data/lib/rbs/ast/ruby/comment_block.rb +6 -4
  63. data/lib/rbs/ast/ruby/helpers/location_helper.rb +1 -1
  64. data/lib/rbs/ast/ruby/members.rb +12 -1
  65. data/lib/rbs/buffer.rb +48 -11
  66. data/lib/rbs/collection/sources/git.rb +6 -0
  67. data/lib/rbs/definition_builder/method_builder.rb +12 -6
  68. data/lib/rbs/environment.rb +4 -3
  69. data/lib/rbs/inline_parser.rb +5 -3
  70. data/lib/rbs/namespace.rb +47 -11
  71. data/lib/rbs/parser_aux.rb +4 -2
  72. data/lib/rbs/prototype/rbi.rb +193 -25
  73. data/lib/rbs/prototype/runtime.rb +2 -0
  74. data/lib/rbs/resolver/type_name_resolver.rb +12 -14
  75. data/lib/rbs/type_name.rb +33 -13
  76. data/lib/rbs/unit_test/type_assertions.rb +9 -0
  77. data/lib/rbs/version.rb +1 -1
  78. data/lib/rbs/wasm/deserializer.rb +213 -0
  79. data/lib/rbs/wasm/location.rb +61 -0
  80. data/lib/rbs/wasm/parser.rb +137 -0
  81. data/lib/rbs/wasm/runtime.rb +196 -0
  82. data/lib/rbs/wasm/serialization_schema.rb +110 -0
  83. data/lib/rbs.rb +13 -2
  84. data/lib/rbs_jars.rb +39 -0
  85. data/lib/rdoc_plugin/parser.rb +5 -0
  86. data/rbs.gemspec +32 -2
  87. data/sig/ast/ruby/members.rbs +6 -1
  88. data/sig/buffer.rbs +19 -1
  89. data/sig/namespace.rbs +20 -0
  90. data/sig/parser.rbs +10 -0
  91. data/sig/prototype/rbi.rbs +33 -4
  92. data/sig/resolver/type_name_resolver.rbs +2 -4
  93. data/sig/typename.rbs +15 -0
  94. data/sig/unit_test/type_assertions.rbs +4 -0
  95. data/sig/wasm/deserializer.rbs +66 -0
  96. data/sig/wasm/serialization_schema.rbs +13 -0
  97. data/src/ast.c +78 -78
  98. data/src/lexer.c +97 -93
  99. data/src/lexer.re +1 -1
  100. data/src/lexstate.c +9 -1
  101. data/src/serialize.c +958 -0
  102. data/src/util/rbs_allocator.c +14 -8
  103. data/stdlib/abbrev/0/array.rbs +1 -1
  104. data/stdlib/csv/0/csv.rbs +5 -5
  105. data/stdlib/delegate/0/delegator.rbs +2 -1
  106. data/stdlib/digest/0/digest.rbs +11 -5
  107. data/stdlib/erb/0/erb.rbs +1 -1
  108. data/stdlib/etc/0/etc.rbs +18 -4
  109. data/stdlib/fileutils/0/fileutils.rbs +21 -21
  110. data/stdlib/ipaddr/0/ipaddr.rbs +0 -5
  111. data/stdlib/json/0/json.rbs +6 -6
  112. data/stdlib/monitor/0/monitor.rbs +2 -2
  113. data/stdlib/openssl/0/openssl.rbs +44 -38
  114. data/stdlib/resolv/0/resolv.rbs +1 -1
  115. data/stdlib/shellwords/0/shellwords.rbs +1 -1
  116. data/stdlib/stringio/0/stringio.rbs +32 -10
  117. data/stdlib/strscan/0/string_scanner.rbs +74 -55
  118. data/stdlib/tempfile/0/manifest.yaml +3 -0
  119. data/stdlib/timeout/0/timeout.rbs +0 -5
  120. data/stdlib/tsort/0/cyclic.rbs +1 -1
  121. data/stdlib/tsort/0/interfaces.rbs +8 -8
  122. data/stdlib/tsort/0/tsort.rbs +9 -9
  123. data/stdlib/uri/0/generic.rbs +0 -5
  124. data/stdlib/zlib/0/gzip_reader.rbs +2 -2
  125. data/stdlib/zlib/0/zstream.rbs +0 -1
  126. data/wasm/README.md +60 -0
  127. data/wasm/rbs_wasm.c +423 -0
  128. metadata +26 -5
  129. data/.vscode/extensions.json +0 -5
  130. 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 type_namespace, VALUE name) {
200
+ VALUE args[2] = { type_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,544 +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);
949
1172
  }
950
1173
  case RBS_AST_RUBY_ANNOTATIONS_MODULE_SELF_ANNOTATION: {
951
1174
  rbs_ast_ruby_annotations_module_self_annotation_t *node = (rbs_ast_ruby_annotations_module_self_annotation_t *) instance;
952
1175
 
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("keyword_location")), rbs_location_range_to_ruby_location(ctx, node->keyword_location));
957
- rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), rbs_location_range_to_ruby_location(ctx, node->colon_location));
958
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
959
- rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));
960
- rb_hash_aset(h, ID2SYM(rb_intern("open_bracket_location")), rbs_location_range_to_ruby_location(ctx, node->open_bracket_location)); // optional
961
- rb_hash_aset(h, ID2SYM(rb_intern("close_bracket_location")), rbs_location_range_to_ruby_location(ctx, node->close_bracket_location)); // optional
962
- rb_hash_aset(h, ID2SYM(rb_intern("args_comma_locations")), rbs_location_range_list_to_ruby_array(ctx, node->args_comma_locations));
963
- rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional
964
-
965
- return CLASS_NEW_INSTANCE(
966
- RBS_AST_Ruby_Annotations_ModuleSelfAnnotation,
967
- 1,
968
- &h
969
- );
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);
970
1203
  }
971
1204
  case RBS_AST_RUBY_ANNOTATIONS_NODE_TYPE_ASSERTION: {
972
1205
  rbs_ast_ruby_annotations_node_type_assertion_t *node = (rbs_ast_ruby_annotations_node_type_assertion_t *) instance;
973
1206
 
974
- VALUE h = rb_hash_new();
975
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
976
- rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
977
- 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
978
1211
 
979
- return CLASS_NEW_INSTANCE(
980
- RBS_AST_Ruby_Annotations_NodeTypeAssertion,
981
- 1,
982
- &h
983
- );
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);
984
1220
  }
985
1221
  case RBS_AST_RUBY_ANNOTATIONS_PARAM_TYPE_ANNOTATION: {
986
1222
  rbs_ast_ruby_annotations_param_type_annotation_t *node = (rbs_ast_ruby_annotations_param_type_annotation_t *) instance;
987
1223
 
988
- VALUE h = rb_hash_new();
989
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
990
- rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
991
- rb_hash_aset(h, ID2SYM(rb_intern("name_location")), rbs_location_range_to_ruby_location(ctx, node->name_location));
992
- rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), rbs_location_range_to_ruby_location(ctx, node->colon_location));
993
- rb_hash_aset(h, ID2SYM(rb_intern("param_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->param_type)); // rbs_node
994
- rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional
995
-
996
- return CLASS_NEW_INSTANCE(
997
- RBS_AST_Ruby_Annotations_ParamTypeAnnotation,
998
- 1,
999
- &h
1000
- );
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);
1001
1243
  }
1002
1244
  case RBS_AST_RUBY_ANNOTATIONS_RETURN_TYPE_ANNOTATION: {
1003
1245
  rbs_ast_ruby_annotations_return_type_annotation_t *node = (rbs_ast_ruby_annotations_return_type_annotation_t *) instance;
1004
1246
 
1005
- VALUE h = rb_hash_new();
1006
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1007
- rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
1008
- rb_hash_aset(h, ID2SYM(rb_intern("return_location")), rbs_location_range_to_ruby_location(ctx, node->return_location));
1009
- rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), rbs_location_range_to_ruby_location(ctx, node->colon_location));
1010
- rb_hash_aset(h, ID2SYM(rb_intern("return_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->return_type)); // rbs_node
1011
- rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional
1012
-
1013
- return CLASS_NEW_INSTANCE(
1014
- RBS_AST_Ruby_Annotations_ReturnTypeAnnotation,
1015
- 1,
1016
- &h
1017
- );
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);
1018
1266
  }
1019
1267
  case RBS_AST_RUBY_ANNOTATIONS_SKIP_ANNOTATION: {
1020
1268
  rbs_ast_ruby_annotations_skip_annotation_t *node = (rbs_ast_ruby_annotations_skip_annotation_t *) instance;
1021
1269
 
1022
- VALUE h = rb_hash_new();
1023
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1024
- rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
1025
- rb_hash_aset(h, ID2SYM(rb_intern("skip_location")), rbs_location_range_to_ruby_location(ctx, node->skip_location));
1026
- rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional
1027
-
1028
- return CLASS_NEW_INSTANCE(
1029
- RBS_AST_Ruby_Annotations_SkipAnnotation,
1030
- 1,
1031
- &h
1032
- );
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);
1033
1285
  }
1034
1286
  case RBS_AST_RUBY_ANNOTATIONS_SPLAT_PARAM_TYPE_ANNOTATION: {
1035
1287
  rbs_ast_ruby_annotations_splat_param_type_annotation_t *node = (rbs_ast_ruby_annotations_splat_param_type_annotation_t *) instance;
1036
1288
 
1037
- VALUE h = rb_hash_new();
1038
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1039
- rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
1040
- rb_hash_aset(h, ID2SYM(rb_intern("star_location")), rbs_location_range_to_ruby_location(ctx, node->star_location));
1041
- rb_hash_aset(h, ID2SYM(rb_intern("name_location")), rbs_location_range_to_ruby_location(ctx, node->name_location)); // optional
1042
- rb_hash_aset(h, ID2SYM(rb_intern("colon_location")), rbs_location_range_to_ruby_location(ctx, node->colon_location));
1043
- rb_hash_aset(h, ID2SYM(rb_intern("param_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->param_type)); // rbs_node
1044
- rb_hash_aset(h, ID2SYM(rb_intern("comment_location")), rbs_location_range_to_ruby_location(ctx, node->comment_location)); // optional
1045
-
1046
- return CLASS_NEW_INSTANCE(
1047
- RBS_AST_Ruby_Annotations_SplatParamTypeAnnotation,
1048
- 1,
1049
- &h
1050
- );
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);
1051
1310
  }
1052
1311
  case RBS_AST_RUBY_ANNOTATIONS_TYPE_APPLICATION_ANNOTATION: {
1053
1312
  rbs_ast_ruby_annotations_type_application_annotation_t *node = (rbs_ast_ruby_annotations_type_application_annotation_t *) instance;
1054
1313
 
1055
- VALUE h = rb_hash_new();
1056
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1057
- rb_hash_aset(h, ID2SYM(rb_intern("prefix_location")), rbs_location_range_to_ruby_location(ctx, node->prefix_location));
1058
- rb_hash_aset(h, ID2SYM(rb_intern("type_args")), rbs_node_list_to_ruby_array(ctx, node->type_args));
1059
- rb_hash_aset(h, ID2SYM(rb_intern("close_bracket_location")), rbs_location_range_to_ruby_location(ctx, node->close_bracket_location));
1060
- rb_hash_aset(h, ID2SYM(rb_intern("comma_locations")), rbs_location_range_list_to_ruby_array(ctx, node->comma_locations));
1061
-
1062
- return CLASS_NEW_INSTANCE(
1063
- RBS_AST_Ruby_Annotations_TypeApplicationAnnotation,
1064
- 1,
1065
- &h
1066
- );
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);
1067
1331
  }
1068
1332
  case RBS_AST_STRING: {
1069
1333
  rbs_ast_string_t *string_node = (rbs_ast_string_t *) instance;
@@ -1074,68 +1338,71 @@ VALUE rbs_struct_to_ruby_value(rbs_translation_context_t ctx, rbs_node_t *instan
1074
1338
  case RBS_AST_TYPE_PARAM: {
1075
1339
  rbs_ast_type_param_t *node = (rbs_ast_type_param_t *) instance;
1076
1340
 
1077
- VALUE h = rb_hash_new();
1078
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1079
- rbs_loc *loc = rbs_check_location(location);
1080
- rbs_loc_legacy_alloc_children(loc, 6);
1081
- 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 });
1082
- 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 });
1083
- 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 });
1084
- 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 });
1085
- 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 });
1086
- 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 });
1087
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
1088
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol
1089
- rb_hash_aset(h, ID2SYM(rb_intern("variance")), rbs_type_param_variance_to_ruby(node->variance)); // type_param_variance
1090
- rb_hash_aset(h, ID2SYM(rb_intern("upper_bound")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->upper_bound)); // rbs_node
1091
- rb_hash_aset(h, ID2SYM(rb_intern("lower_bound")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->lower_bound)); // rbs_node
1092
- rb_hash_aset(h, ID2SYM(rb_intern("default_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->default_type)); // rbs_node
1093
- rb_hash_aset(h, ID2SYM(rb_intern("unchecked")), node->unchecked ? Qtrue : Qfalse);
1094
-
1095
- return CLASS_NEW_INSTANCE(
1096
- RBS_AST_TypeParam,
1097
- 1,
1098
- &h
1099
- );
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);
1100
1372
  }
1101
1373
  case RBS_METHOD_TYPE: {
1102
1374
  rbs_method_type_t *node = (rbs_method_type_t *) instance;
1103
1375
 
1104
- VALUE h = rb_hash_new();
1105
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1106
- rbs_loc *loc = rbs_check_location(location);
1107
- rbs_loc_legacy_alloc_children(loc, 2);
1108
- 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 });
1109
- 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 });
1110
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
1111
- rb_hash_aset(h, ID2SYM(rb_intern("type_params")), rbs_node_list_to_ruby_array(ctx, node->type_params));
1112
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
1113
- 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
1114
1387
 
1115
1388
  rb_funcall(
1116
1389
  RBS_AST_TypeParam,
1117
1390
  rb_intern("resolve_variables"),
1118
1391
  1,
1119
- rb_hash_lookup(h, ID2SYM(rb_intern("type_params")))
1120
- );
1121
- return CLASS_NEW_INSTANCE(
1122
- RBS_MethodType,
1123
- 1,
1124
- &h
1392
+ arg_type_params
1125
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);
1126
1403
  }
1127
1404
  case RBS_NAMESPACE: {
1128
- rbs_namespace_t *node = (rbs_namespace_t *) instance;
1129
-
1130
- VALUE h = rb_hash_new();
1131
- rb_hash_aset(h, ID2SYM(rb_intern("path")), rbs_node_list_to_ruby_array(ctx, node->path));
1132
- rb_hash_aset(h, ID2SYM(rb_intern("absolute")), node->absolute ? Qtrue : Qfalse);
1133
-
1134
- return CLASS_NEW_INSTANCE(
1135
- RBS_Namespace,
1136
- 1,
1137
- &h
1138
- );
1405
+ return rbs_intern_namespace(ctx, (rbs_namespace_t *) instance);
1139
1406
  }
1140
1407
  case RBS_SIGNATURE: {
1141
1408
  rbs_signature_t *signature = (rbs_signature_t *) instance;
@@ -1147,320 +1414,367 @@ VALUE rbs_struct_to_ruby_value(rbs_translation_context_t ctx, rbs_node_t *instan
1147
1414
  }
1148
1415
  case RBS_TYPE_NAME: {
1149
1416
  rbs_type_name_t *node = (rbs_type_name_t *) instance;
1150
-
1151
- VALUE h = rb_hash_new();
1152
- rb_hash_aset(h, ID2SYM(rb_intern("namespace")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->rbs_namespace)); // rbs_namespace
1153
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol
1154
-
1155
- return CLASS_NEW_INSTANCE(
1156
- RBS_TypeName,
1157
- 1,
1158
- &h
1159
- );
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);
1160
1420
  }
1161
1421
  case RBS_TYPES_ALIAS: {
1162
1422
  rbs_types_alias_t *node = (rbs_types_alias_t *) instance;
1163
1423
 
1164
- VALUE h = rb_hash_new();
1165
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1166
- rbs_loc *loc = rbs_check_location(location);
1167
- rbs_loc_legacy_alloc_children(loc, 2);
1168
- 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 });
1169
- 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 });
1170
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
1171
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
1172
- rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));
1173
-
1174
- return CLASS_NEW_INSTANCE(
1175
- RBS_Types_Alias,
1176
- 1,
1177
- &h
1178
- );
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);
1179
1443
  }
1180
1444
  case RBS_TYPES_BASES_ANY: {
1181
1445
  rbs_types_bases_any_t *node = (rbs_types_bases_any_t *) instance;
1182
1446
 
1183
- VALUE h = rb_hash_new();
1184
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1185
- 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;
1186
1450
 
1187
- return CLASS_NEW_INSTANCE(
1188
- RBS_Types_Bases_Any,
1189
- 1,
1190
- &h
1191
- );
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);
1192
1458
  }
1193
1459
  case RBS_TYPES_BASES_BOOL: {
1194
1460
  rbs_types_bases_bool_t *node = (rbs_types_bases_bool_t *) instance;
1195
1461
 
1196
- VALUE h = rb_hash_new();
1197
- 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);
1198
1464
 
1199
- return CLASS_NEW_INSTANCE(
1200
- RBS_Types_Bases_Bool,
1201
- 1,
1202
- &h
1203
- );
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);
1204
1471
  }
1205
1472
  case RBS_TYPES_BASES_BOTTOM: {
1206
1473
  rbs_types_bases_bottom_t *node = (rbs_types_bases_bottom_t *) instance;
1207
1474
 
1208
- VALUE h = rb_hash_new();
1209
- 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);
1210
1477
 
1211
- return CLASS_NEW_INSTANCE(
1212
- RBS_Types_Bases_Bottom,
1213
- 1,
1214
- &h
1215
- );
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);
1216
1484
  }
1217
1485
  case RBS_TYPES_BASES_CLASS: {
1218
1486
  rbs_types_bases_class_t *node = (rbs_types_bases_class_t *) instance;
1219
1487
 
1220
- VALUE h = rb_hash_new();
1221
- 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);
1222
1490
 
1223
- return CLASS_NEW_INSTANCE(
1224
- RBS_Types_Bases_Class,
1225
- 1,
1226
- &h
1227
- );
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);
1228
1497
  }
1229
1498
  case RBS_TYPES_BASES_INSTANCE: {
1230
1499
  rbs_types_bases_instance_t *node = (rbs_types_bases_instance_t *) instance;
1231
1500
 
1232
- VALUE h = rb_hash_new();
1233
- 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);
1234
1503
 
1235
- return CLASS_NEW_INSTANCE(
1236
- RBS_Types_Bases_Instance,
1237
- 1,
1238
- &h
1239
- );
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);
1240
1510
  }
1241
1511
  case RBS_TYPES_BASES_NIL: {
1242
1512
  rbs_types_bases_nil_t *node = (rbs_types_bases_nil_t *) instance;
1243
1513
 
1244
- VALUE h = rb_hash_new();
1245
- 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);
1246
1516
 
1247
- return CLASS_NEW_INSTANCE(
1248
- RBS_Types_Bases_Nil,
1249
- 1,
1250
- &h
1251
- );
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);
1252
1523
  }
1253
1524
  case RBS_TYPES_BASES_SELF: {
1254
1525
  rbs_types_bases_self_t *node = (rbs_types_bases_self_t *) instance;
1255
1526
 
1256
- VALUE h = rb_hash_new();
1257
- 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);
1258
1529
 
1259
- return CLASS_NEW_INSTANCE(
1260
- RBS_Types_Bases_Self,
1261
- 1,
1262
- &h
1263
- );
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);
1264
1536
  }
1265
1537
  case RBS_TYPES_BASES_TOP: {
1266
1538
  rbs_types_bases_top_t *node = (rbs_types_bases_top_t *) instance;
1267
1539
 
1268
- VALUE h = rb_hash_new();
1269
- 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);
1270
1542
 
1271
- return CLASS_NEW_INSTANCE(
1272
- RBS_Types_Bases_Top,
1273
- 1,
1274
- &h
1275
- );
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);
1276
1549
  }
1277
1550
  case RBS_TYPES_BASES_VOID: {
1278
1551
  rbs_types_bases_void_t *node = (rbs_types_bases_void_t *) instance;
1279
1552
 
1280
- VALUE h = rb_hash_new();
1281
- 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);
1282
1555
 
1283
- return CLASS_NEW_INSTANCE(
1284
- RBS_Types_Bases_Void,
1285
- 1,
1286
- &h
1287
- );
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);
1288
1562
  }
1289
1563
  case RBS_TYPES_BLOCK: {
1290
1564
  rbs_types_block_t *node = (rbs_types_block_t *) instance;
1291
1565
 
1292
- VALUE h = rb_hash_new();
1293
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1294
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
1295
- rb_hash_aset(h, ID2SYM(rb_intern("required")), node->required ? Qtrue : Qfalse);
1296
- rb_hash_aset(h, ID2SYM(rb_intern("self_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->self_type)); // rbs_node
1297
-
1298
- return CLASS_NEW_INSTANCE(
1299
- RBS_Types_Block,
1300
- 1,
1301
- &h
1302
- );
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);
1303
1581
  }
1304
1582
  case RBS_TYPES_CLASS_INSTANCE: {
1305
1583
  rbs_types_class_instance_t *node = (rbs_types_class_instance_t *) instance;
1306
1584
 
1307
- VALUE h = rb_hash_new();
1308
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1309
- rbs_loc *loc = rbs_check_location(location);
1310
- rbs_loc_legacy_alloc_children(loc, 2);
1311
- 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 });
1312
- 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 });
1313
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
1314
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
1315
- rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));
1316
-
1317
- return CLASS_NEW_INSTANCE(
1318
- RBS_Types_ClassInstance,
1319
- 1,
1320
- &h
1321
- );
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);
1322
1604
  }
1323
1605
  case RBS_TYPES_CLASS_SINGLETON: {
1324
1606
  rbs_types_class_singleton_t *node = (rbs_types_class_singleton_t *) instance;
1325
1607
 
1326
- VALUE h = rb_hash_new();
1327
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1328
- rbs_loc *loc = rbs_check_location(location);
1329
- rbs_loc_legacy_alloc_children(loc, 2);
1330
- 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 });
1331
- 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 });
1332
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
1333
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
1334
- rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));
1335
-
1336
- return CLASS_NEW_INSTANCE(
1337
- RBS_Types_ClassSingleton,
1338
- 1,
1339
- &h
1340
- );
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);
1341
1627
  }
1342
1628
  case RBS_TYPES_FUNCTION: {
1343
1629
  rbs_types_function_t *node = (rbs_types_function_t *) instance;
1344
1630
 
1345
- VALUE h = rb_hash_new();
1346
- rb_hash_aset(h, ID2SYM(rb_intern("required_positionals")), rbs_node_list_to_ruby_array(ctx, node->required_positionals));
1347
- rb_hash_aset(h, ID2SYM(rb_intern("optional_positionals")), rbs_node_list_to_ruby_array(ctx, node->optional_positionals));
1348
- rb_hash_aset(h, ID2SYM(rb_intern("rest_positionals")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->rest_positionals)); // rbs_node
1349
- rb_hash_aset(h, ID2SYM(rb_intern("trailing_positionals")), rbs_node_list_to_ruby_array(ctx, node->trailing_positionals));
1350
- rb_hash_aset(h, ID2SYM(rb_intern("required_keywords")), rbs_hash_to_ruby_hash(ctx, node->required_keywords));
1351
- rb_hash_aset(h, ID2SYM(rb_intern("optional_keywords")), rbs_hash_to_ruby_hash(ctx, node->optional_keywords));
1352
- rb_hash_aset(h, ID2SYM(rb_intern("rest_keywords")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->rest_keywords)); // rbs_node
1353
- rb_hash_aset(h, ID2SYM(rb_intern("return_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->return_type)); // rbs_node
1354
-
1355
- return CLASS_NEW_INSTANCE(
1356
- RBS_Types_Function,
1357
- 1,
1358
- &h
1359
- );
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);
1360
1654
  }
1361
1655
  case RBS_TYPES_FUNCTION_PARAM: {
1362
1656
  rbs_types_function_param_t *node = (rbs_types_function_param_t *) instance;
1363
1657
 
1364
- VALUE h = rb_hash_new();
1365
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1366
- rbs_loc *loc = rbs_check_location(location);
1367
- rbs_loc_legacy_alloc_children(loc, 1);
1368
- 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 });
1369
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
1370
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
1371
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol
1372
-
1373
- return CLASS_NEW_INSTANCE(
1374
- RBS_Types_Function_Param,
1375
- 1,
1376
- &h
1377
- );
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);
1378
1676
  }
1379
1677
  case RBS_TYPES_INTERFACE: {
1380
1678
  rbs_types_interface_t *node = (rbs_types_interface_t *) instance;
1381
1679
 
1382
- VALUE h = rb_hash_new();
1383
- VALUE location = rbs_location_range_to_ruby_location(ctx, node->base.location);
1384
- rbs_loc *loc = rbs_check_location(location);
1385
- rbs_loc_legacy_alloc_children(loc, 2);
1386
- 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 });
1387
- 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 });
1388
- rb_hash_aset(h, ID2SYM(rb_intern("location")), location);
1389
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_type_name
1390
- rb_hash_aset(h, ID2SYM(rb_intern("args")), rbs_node_list_to_ruby_array(ctx, node->args));
1391
-
1392
- return CLASS_NEW_INSTANCE(
1393
- RBS_Types_Interface,
1394
- 1,
1395
- &h
1396
- );
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);
1397
1699
  }
1398
1700
  case RBS_TYPES_INTERSECTION: {
1399
1701
  rbs_types_intersection_t *node = (rbs_types_intersection_t *) instance;
1400
1702
 
1401
- VALUE h = rb_hash_new();
1402
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1403
- 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);
1404
1706
 
1405
- return CLASS_NEW_INSTANCE(
1406
- RBS_Types_Intersection,
1407
- 1,
1408
- &h
1409
- );
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);
1410
1714
  }
1411
1715
  case RBS_TYPES_LITERAL: {
1412
1716
  rbs_types_literal_t *node = (rbs_types_literal_t *) instance;
1413
1717
 
1414
- VALUE h = rb_hash_new();
1415
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1416
- 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
1417
1721
 
1418
- return CLASS_NEW_INSTANCE(
1419
- RBS_Types_Literal,
1420
- 1,
1421
- &h
1422
- );
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);
1423
1729
  }
1424
1730
  case RBS_TYPES_OPTIONAL: {
1425
1731
  rbs_types_optional_t *node = (rbs_types_optional_t *) instance;
1426
1732
 
1427
- VALUE h = rb_hash_new();
1428
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1429
- 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
1430
1736
 
1431
- return CLASS_NEW_INSTANCE(
1432
- RBS_Types_Optional,
1433
- 1,
1434
- &h
1435
- );
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);
1436
1744
  }
1437
1745
  case RBS_TYPES_PROC: {
1438
1746
  rbs_types_proc_t *node = (rbs_types_proc_t *) instance;
1439
1747
 
1440
- VALUE h = rb_hash_new();
1441
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1442
- rb_hash_aset(h, ID2SYM(rb_intern("type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->type)); // rbs_node
1443
- rb_hash_aset(h, ID2SYM(rb_intern("block")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->block)); // rbs_types_block
1444
- rb_hash_aset(h, ID2SYM(rb_intern("self_type")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->self_type)); // rbs_node
1445
-
1446
- return CLASS_NEW_INSTANCE(
1447
- RBS_Types_Proc,
1448
- 1,
1449
- &h
1450
- );
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);
1451
1763
  }
1452
1764
  case RBS_TYPES_RECORD: {
1453
1765
  rbs_types_record_t *node = (rbs_types_record_t *) instance;
1454
1766
 
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("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);
1458
1770
 
1459
- return CLASS_NEW_INSTANCE(
1460
- RBS_Types_Record,
1461
- 1,
1462
- &h
1463
- );
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);
1464
1778
  }
1465
1779
  case RBS_TYPES_RECORD_FIELD_TYPE: {
1466
1780
  rbs_types_record_field_type_t *record_fieldtype = (rbs_types_record_field_type_t *) instance;
@@ -1473,53 +1787,60 @@ VALUE rbs_struct_to_ruby_value(rbs_translation_context_t ctx, rbs_node_t *instan
1473
1787
  case RBS_TYPES_TUPLE: {
1474
1788
  rbs_types_tuple_t *node = (rbs_types_tuple_t *) instance;
1475
1789
 
1476
- VALUE h = rb_hash_new();
1477
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1478
- 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);
1479
1793
 
1480
- return CLASS_NEW_INSTANCE(
1481
- RBS_Types_Tuple,
1482
- 1,
1483
- &h
1484
- );
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);
1485
1801
  }
1486
1802
  case RBS_TYPES_UNION: {
1487
1803
  rbs_types_union_t *node = (rbs_types_union_t *) instance;
1488
1804
 
1489
- VALUE h = rb_hash_new();
1490
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1491
- 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);
1492
1808
 
1493
- return CLASS_NEW_INSTANCE(
1494
- RBS_Types_Union,
1495
- 1,
1496
- &h
1497
- );
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);
1498
1816
  }
1499
1817
  case RBS_TYPES_UNTYPED_FUNCTION: {
1500
1818
  rbs_types_untyped_function_t *node = (rbs_types_untyped_function_t *) instance;
1501
1819
 
1502
- VALUE h = rb_hash_new();
1503
- 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
1504
1822
 
1505
- return CLASS_NEW_INSTANCE(
1506
- RBS_Types_UntypedFunction,
1507
- 1,
1508
- &h
1509
- );
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);
1510
1829
  }
1511
1830
  case RBS_TYPES_VARIABLE: {
1512
1831
  rbs_types_variable_t *node = (rbs_types_variable_t *) instance;
1513
1832
 
1514
- VALUE h = rb_hash_new();
1515
- rb_hash_aset(h, ID2SYM(rb_intern("location")), rbs_location_range_to_ruby_location(ctx, node->base.location));
1516
- rb_hash_aset(h, ID2SYM(rb_intern("name")), rbs_struct_to_ruby_value(ctx, (rbs_node_t *) node->name)); // rbs_ast_symbol
1517
-
1518
- return CLASS_NEW_INSTANCE(
1519
- RBS_Types_Variable,
1520
- 1,
1521
- &h
1522
- );
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);
1523
1844
  }
1524
1845
  case RBS_AST_SYMBOL: {
1525
1846
  rbs_constant_t *constant = rbs_constant_pool_id_to_constant(ctx.constant_pool, ((rbs_ast_symbol_t *) instance)->constant_id);