rbs 3.8.0 → 3.9.0.dev.1

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 (98) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/comments.yml +3 -3
  3. data/.github/workflows/dependabot.yml +1 -1
  4. data/.github/workflows/ruby.yml +7 -7
  5. data/.github/workflows/typecheck.yml +2 -0
  6. data/.github/workflows/windows.yml +15 -0
  7. data/.rubocop.yml +20 -1
  8. data/CHANGELOG.md +14 -0
  9. data/Rakefile +5 -2
  10. data/config.yml +6 -0
  11. data/core/data.rbs +1 -1
  12. data/core/enumerator.rbs +14 -2
  13. data/core/exception.rbs +148 -39
  14. data/core/gc.rbs +2 -2
  15. data/core/io.rbs +7 -3
  16. data/core/kernel.rbs +58 -16
  17. data/core/method.rbs +2 -2
  18. data/core/module.rbs +3 -3
  19. data/core/proc.rbs +2 -2
  20. data/core/ractor.rbs +4 -1
  21. data/core/rbs/unnamed/argf.rbs +3 -3
  22. data/core/regexp.rbs +4 -2
  23. data/core/ruby_vm.rbs +8 -8
  24. data/core/rubygems/version.rbs +2 -2
  25. data/core/string.rbs +1 -1
  26. data/core/time.rbs +1 -1
  27. data/core/unbound_method.rbs +1 -1
  28. data/docs/syntax.md +10 -5
  29. data/ext/rbs_extension/extconf.rb +2 -1
  30. data/ext/rbs_extension/location.c +32 -10
  31. data/ext/rbs_extension/location.h +4 -3
  32. data/ext/rbs_extension/main.c +22 -1
  33. data/ext/rbs_extension/parser.c +144 -136
  34. data/ext/rbs_extension/parserstate.c +40 -9
  35. data/ext/rbs_extension/parserstate.h +6 -4
  36. data/include/rbs/ruby_objs.h +6 -6
  37. data/include/rbs/util/rbs_constant_pool.h +219 -0
  38. data/lib/rbs/ast/declarations.rb +9 -4
  39. data/lib/rbs/ast/directives.rb +10 -0
  40. data/lib/rbs/ast/members.rb +2 -0
  41. data/lib/rbs/ast/type_param.rb +2 -2
  42. data/lib/rbs/cli/validate.rb +1 -0
  43. data/lib/rbs/cli.rb +3 -3
  44. data/lib/rbs/collection/config/lockfile_generator.rb +28 -7
  45. data/lib/rbs/collection/sources/rubygems.rb +1 -1
  46. data/lib/rbs/definition.rb +46 -31
  47. data/lib/rbs/definition_builder/ancestor_builder.rb +2 -0
  48. data/lib/rbs/definition_builder.rb +86 -30
  49. data/lib/rbs/environment.rb +33 -18
  50. data/lib/rbs/errors.rb +23 -0
  51. data/lib/rbs/locator.rb +2 -0
  52. data/lib/rbs/method_type.rb +2 -0
  53. data/lib/rbs/parser_aux.rb +38 -1
  54. data/lib/rbs/subtractor.rb +3 -3
  55. data/lib/rbs/test/hook.rb +2 -2
  56. data/lib/rbs/test/type_check.rb +7 -5
  57. data/lib/rbs/types.rb +44 -5
  58. data/lib/rbs/unit_test/spy.rb +4 -2
  59. data/lib/rbs/unit_test/type_assertions.rb +17 -11
  60. data/lib/rbs/validator.rb +4 -0
  61. data/lib/rbs/version.rb +1 -1
  62. data/lib/rbs/writer.rb +10 -5
  63. data/lib/rbs.rb +1 -0
  64. data/rbs.gemspec +1 -1
  65. data/sig/collection/config/lockfile_generator.rbs +1 -1
  66. data/sig/declarations.rbs +10 -3
  67. data/sig/definition.rbs +67 -14
  68. data/sig/definition_builder.rbs +17 -3
  69. data/sig/directives.rbs +17 -1
  70. data/sig/environment.rbs +2 -0
  71. data/sig/errors.rbs +16 -0
  72. data/sig/parser.rbs +5 -1
  73. data/sig/subtractor.rbs +1 -1
  74. data/sig/test/type_check.rbs +2 -2
  75. data/sig/type_param.rbs +1 -1
  76. data/sig/types.rbs +3 -0
  77. data/sig/unit_test/spy.rbs +2 -0
  78. data/sig/unit_test/type_assertions.rbs +2 -0
  79. data/sig/validator.rbs +4 -0
  80. data/sig/writer.rbs +1 -1
  81. data/src/ruby_objs.c +12 -6
  82. data/src/util/rbs_constant_pool.c +342 -0
  83. data/stdlib/cgi/0/core.rbs +10 -0
  84. data/stdlib/json/0/json.rbs +52 -50
  85. data/stdlib/monitor/0/monitor.rbs +13 -4
  86. data/stdlib/net-http/0/net-http.rbs +2 -2
  87. data/stdlib/openssl/0/openssl.rbs +73 -73
  88. data/stdlib/resolv/0/resolv.rbs +8 -8
  89. data/stdlib/socket/0/addrinfo.rbs +1 -1
  90. data/stdlib/socket/0/unix_socket.rbs +4 -2
  91. data/stdlib/stringio/0/stringio.rbs +1 -1
  92. data/stdlib/uri/0/common.rbs +17 -0
  93. metadata +4 -7
  94. data/templates/include/rbs/constants.h.erb +0 -20
  95. data/templates/include/rbs/ruby_objs.h.erb +0 -10
  96. data/templates/src/constants.c.erb +0 -36
  97. data/templates/src/ruby_objs.c.erb +0 -27
  98. data/templates/template.rb +0 -122
data/core/kernel.rbs CHANGED
@@ -936,16 +936,37 @@ module Kernel : BasicObject
936
936
  #
937
937
  # See [Messages](rdoc-ref:exceptions.md@Messages).
938
938
  #
939
- # Argument `backtrace` sets the stored backtrace in the new exception, which may
940
- # be retrieved by method Exception#backtrace; the backtrace must be an array of
941
- # strings or `nil`:
939
+ # Argument `backtrace` might be used to modify the backtrace of the new
940
+ # exception, as reported by Exception#backtrace and
941
+ # Exception#backtrace_locations; the backtrace must be an array of
942
+ # Thread::Backtrace::Location, an array of strings, a single string, or `nil`.
943
+ #
944
+ # Using the array of Thread::Backtrace::Location instances is the most
945
+ # consistent option and should be preferred when possible. The necessary value
946
+ # might be obtained from #caller_locations, or copied from
947
+ # Exception#backtrace_locations of another error:
942
948
  #
943
949
  # begin
944
- # raise(StandardError, 'Boom', %w[foo bar baz])
945
- # rescue => x
946
- # p x.backtrace
950
+ # do_some_work()
951
+ # rescue ZeroDivisionError => ex
952
+ # raise(LogicalError, "You have an error in your math", ex.backtrace_locations)
953
+ # end
954
+ #
955
+ # The ways, both Exception#backtrace and Exception#backtrace_locations of the
956
+ # raised error are set to the same backtrace.
957
+ #
958
+ # When the desired stack of locations is not available and should be constructed
959
+ # from scratch, an array of strings or a singular string can be used. In this
960
+ # case, only Exception#backtrace is set:
961
+ #
962
+ # begin
963
+ # raise(StandardError, 'Boom', %w[dsl.rb:3 framework.rb:1])
964
+ # rescue => ex
965
+ # p ex.backtrace
966
+ # # => ["dsl.rb:3", "framework.rb:1"]
967
+ # p ex.backtrace_locations
968
+ # # => nil
947
969
  # end
948
- # # => ["foo", "bar", "baz"]
949
970
  #
950
971
  # If argument `backtrace` is not given, the backtrace is set according to an
951
972
  # array of Thread::Backtrace::Location objects, as derived from the call stack.
@@ -1021,16 +1042,37 @@ module Kernel : BasicObject
1021
1042
  #
1022
1043
  # See [Messages](rdoc-ref:exceptions.md@Messages).
1023
1044
  #
1024
- # Argument `backtrace` sets the stored backtrace in the new exception, which may
1025
- # be retrieved by method Exception#backtrace; the backtrace must be an array of
1026
- # strings or `nil`:
1045
+ # Argument `backtrace` might be used to modify the backtrace of the new
1046
+ # exception, as reported by Exception#backtrace and
1047
+ # Exception#backtrace_locations; the backtrace must be an array of
1048
+ # Thread::Backtrace::Location, an array of strings, a single string, or `nil`.
1049
+ #
1050
+ # Using the array of Thread::Backtrace::Location instances is the most
1051
+ # consistent option and should be preferred when possible. The necessary value
1052
+ # might be obtained from #caller_locations, or copied from
1053
+ # Exception#backtrace_locations of another error:
1027
1054
  #
1028
1055
  # begin
1029
- # raise(StandardError, 'Boom', %w[foo bar baz])
1030
- # rescue => x
1031
- # p x.backtrace
1056
+ # do_some_work()
1057
+ # rescue ZeroDivisionError => ex
1058
+ # raise(LogicalError, "You have an error in your math", ex.backtrace_locations)
1059
+ # end
1060
+ #
1061
+ # The ways, both Exception#backtrace and Exception#backtrace_locations of the
1062
+ # raised error are set to the same backtrace.
1063
+ #
1064
+ # When the desired stack of locations is not available and should be constructed
1065
+ # from scratch, an array of strings or a singular string can be used. In this
1066
+ # case, only Exception#backtrace is set:
1067
+ #
1068
+ # begin
1069
+ # raise(StandardError, 'Boom', %w[dsl.rb:3 framework.rb:1])
1070
+ # rescue => ex
1071
+ # p ex.backtrace
1072
+ # # => ["dsl.rb:3", "framework.rb:1"]
1073
+ # p ex.backtrace_locations
1074
+ # # => nil
1032
1075
  # end
1033
- # # => ["foo", "bar", "baz"]
1034
1076
  #
1035
1077
  # If argument `backtrace` is not given, the backtrace is set according to an
1036
1078
  # array of Thread::Backtrace::Location objects, as derived from the call stack.
@@ -1121,7 +1163,7 @@ module Kernel : BasicObject
1121
1163
  # The style of programming using `$_` as an implicit parameter is gradually
1122
1164
  # losing favor in the Ruby community.
1123
1165
  #
1124
- def self?.gets: (?String arg0, ?Integer arg1) -> String?
1166
+ def self?.gets: (?String sep, ?Integer limit, ?chomp: boolish) -> String?
1125
1167
 
1126
1168
  # <!--
1127
1169
  # rdoc-file=eval.c
@@ -1444,7 +1486,7 @@ module Kernel : BasicObject
1444
1486
  # Optional keyword argument `chomp` specifies whether line separators are to be
1445
1487
  # omitted.
1446
1488
  #
1447
- def self?.readline: (?String arg0, ?Integer arg1) -> String
1489
+ def self?.readline: (?String arg0, ?Integer arg1, ?chomp: boolish) -> String
1448
1490
 
1449
1491
  # <!--
1450
1492
  # rdoc-file=io.c
data/core/method.rbs CHANGED
@@ -54,7 +54,7 @@ class Method
54
54
  #
55
55
  def hash: () -> Integer
56
56
 
57
- def dup: () -> instance
57
+ def dup: () -> self
58
58
 
59
59
  # <!--
60
60
  # rdoc-file=proc.c
@@ -252,7 +252,7 @@ class Method
252
252
  # m.call # => "bar"
253
253
  # n = m.clone.call # => "bar"
254
254
  #
255
- def clone: () -> instance
255
+ def clone: () -> self
256
256
 
257
257
  # <!--
258
258
  # rdoc-file=proc.c
data/core/module.rbs CHANGED
@@ -731,8 +731,8 @@ class Module < Object
731
731
  # I'm Dino!
732
732
  # #<B:0x401b39e8>
733
733
  #
734
- def define_method: (interned symbol, ^() [self: instance] -> untyped | Method | UnboundMethod method) -> Symbol
735
- | (interned symbol) { () [self: instance] -> untyped } -> Symbol
734
+ def define_method: (interned symbol, ^() [self: self] -> untyped | Method | UnboundMethod method) -> Symbol
735
+ | (interned symbol) { () [self: self] -> untyped } -> Symbol
736
736
 
737
737
  # <!--
738
738
  # rdoc-file=object.c
@@ -1164,7 +1164,7 @@ class Module < Object
1164
1164
  # -->
1165
1165
  # Returns the name of the module *mod*. Returns `nil` for anonymous modules.
1166
1166
  #
1167
- def name: () -> String?
1167
+ def name: %a{implicitly-returns-nil} () -> String
1168
1168
 
1169
1169
  # <!--
1170
1170
  # rdoc-file=eval.c
data/core/proc.rbs CHANGED
@@ -376,8 +376,8 @@ class Proc
376
376
  #
377
377
  def self.new: () { (?) -> untyped } -> instance
378
378
 
379
- def clone: () -> instance
380
- def dup: () -> instance
379
+ def clone: () -> self
380
+ def dup: () -> self
381
381
 
382
382
  # <!-- rdoc-file=proc.c -->
383
383
  # Invokes the block, setting the block's parameters to the values in *params*
data/core/ractor.rbs CHANGED
@@ -603,7 +603,7 @@ class Ractor
603
603
  # }
604
604
  # }.map(&:value).uniq.size #=> 1 and f() is called only once
605
605
  #
606
- def self.store_if_absent: (Symbol) { () -> untyped } -> untyped
606
+ def self.store_if_absent: [A] (Symbol) { (nil) -> A } -> A
607
607
 
608
608
  # <!--
609
609
  # rdoc-file=ractor.rb
@@ -1053,6 +1053,9 @@ class Ractor
1053
1053
  # end
1054
1054
  #
1055
1055
  class RemoteError < Ractor::Error
1056
+ # <!-- rdoc-file=ractor.rb -->
1057
+ # The Ractor an uncaught exception is raised in.
1058
+ #
1056
1059
  def ractor: () -> Ractor
1057
1060
  end
1058
1061
 
@@ -639,7 +639,7 @@ module RBS
639
639
  # See IO.readlines for details about getline_args.
640
640
  #
641
641
  %a{annotate:rdoc:copy:ARGF#gets}
642
- def gets: (?String sep, ?Integer limit) -> String?
642
+ def gets: (?String sep, ?Integer limit, ?chomp: boolish) -> String?
643
643
 
644
644
  # <!--
645
645
  # rdoc-file=io.c
@@ -1024,7 +1024,7 @@ module RBS
1024
1024
  # An EOFError is raised at the end of the file.
1025
1025
  #
1026
1026
  %a{annotate:rdoc:copy:ARGF#readline}
1027
- def readline: (?String sep, ?Integer limit) -> String
1027
+ def readline: (?String sep, ?Integer limit, ?chomp: boolish) -> String
1028
1028
 
1029
1029
  # <!--
1030
1030
  # rdoc-file=io.c
@@ -1044,7 +1044,7 @@ module RBS
1044
1044
  # See `IO.readlines` for a full description of all options.
1045
1045
  #
1046
1046
  %a{annotate:rdoc:copy:ARGF#readlines}
1047
- def readlines: (?String sep, ?Integer limit) -> ::Array[String]
1047
+ def readlines: (?String sep, ?Integer limit, ?chomp: boolish) -> ::Array[String]
1048
1048
 
1049
1049
  # <!--
1050
1050
  # rdoc-file=io.c
data/core/regexp.rbs CHANGED
@@ -836,8 +836,10 @@
836
836
  # These are also commonly used:
837
837
  #
838
838
  # * `/\p{Emoji}/`: Unicode emoji.
839
- # * `/\p{Graph}/`: Non-blank character (excludes spaces, control characters,
840
- # and similar).
839
+ # * `/\p{Graph}/`: Characters excluding `/\p{Cntrl}/` and `/\p{Space}/`. Note
840
+ # that invisible characters under the Unicode
841
+ # ["Format"](https://www.compart.com/en/unicode/category/Cf) category are
842
+ # included.
841
843
  # * `/\p{Word}/`: A member in one of these Unicode character categories (see
842
844
  # below) or having one of these Unicode properties:
843
845
  #
data/core/ruby_vm.rbs CHANGED
@@ -688,14 +688,14 @@ module RubyVM::YJIT
688
688
  # Enable YJIT compilation. `stats` option decides whether to enable YJIT stats
689
689
  # or not. `compilation_log` decides
690
690
  # whether to enable YJIT compilation logging or not.
691
- # `stats`:
692
- # * `false`: Don't enable stats.
693
- # * `true`: Enable stats. Print stats at exit.
694
- # * `:quiet`: Enable stats. Do not print stats at exit.
695
- # `log`:
696
- # * `false`: Don't enable the log.
697
- # * `true`: Enable the log. Print log at exit.
698
- # * `:quiet`: Enable the log. Do not print log at exit.
691
+ # * `stats`:
692
+ # * `false`: Don't enable stats.
693
+ # * `true`: Enable stats. Print stats at exit.
694
+ # * `:quiet`: Enable stats. Do not print stats at exit.
695
+ # * `log`:
696
+ # * `false`: Don't enable the log.
697
+ # * `true`: Enable the log. Print log at exit.
698
+ # * `:quiet`: Enable the log. Do not print log at exit.
699
699
  #
700
700
  def self.enable: (?stats: false | true | :quiet) -> void
701
701
 
@@ -221,7 +221,7 @@ module Gem
221
221
  #
222
222
  # Pre-release (alpha) parts, e.g, 5.3.1.b.2 => 5.4, are ignored.
223
223
  #
224
- def bump: () -> instance
224
+ def bump: () -> self
225
225
 
226
226
  # <!--
227
227
  # rdoc-file=lib/rubygems/version.rb
@@ -274,7 +274,7 @@ module Gem
274
274
  # The release for this version (e.g. 1.2.0.a -> 1.2.0). Non-prerelease versions
275
275
  # return themselves.
276
276
  #
277
- def release: () -> instance
277
+ def release: () -> self
278
278
 
279
279
  # <!--
280
280
  # rdoc-file=lib/rubygems/version.rb
data/core/string.rbs CHANGED
@@ -1936,7 +1936,7 @@ class String
1936
1936
  ?crlf_newline: boolish,
1937
1937
  ?lf_newline: boolish,
1938
1938
  ?fallback: ^(String) -> string? | Method | _EncodeFallbackAref
1939
- ) -> instance
1939
+ ) -> self
1940
1940
 
1941
1941
  interface _EncodeFallbackAref
1942
1942
  def []: (String) -> string?
data/core/time.rbs CHANGED
@@ -1629,7 +1629,7 @@ class Time < Object
1629
1629
  #
1630
1630
  # You must require 'time' to use this method.
1631
1631
  #
1632
- def xmlschema: () -> String
1632
+ def xmlschema: (?Integer fraction_digits) -> String
1633
1633
 
1634
1634
  # <!--
1635
1635
  # rdoc-file=time.c
@@ -100,7 +100,7 @@ class UnboundMethod
100
100
  # m.call # => "bar"
101
101
  # n = m.clone.call # => "bar"
102
102
  #
103
- def clone: () -> instance
103
+ def clone: () -> self
104
104
 
105
105
  # <!--
106
106
  # rdoc-file=proc.c
data/docs/syntax.md CHANGED
@@ -289,7 +289,9 @@ The following `class`/`instance` types are allowed.
289
289
  class Foo
290
290
  attr_reader parent: class
291
291
 
292
- def foo: () -> instance
292
+ def foo: () -> instance # behaves like `self` in this context
293
+
294
+ def self?.bar: () -> instance # behaves like `class` for `def self.bar()` and `self` for `def bar()`
293
295
 
294
296
  @@foos: Array[instance]
295
297
 
@@ -405,9 +407,12 @@ _ivar-member_ ::= _ivar-name_ `:` _type_
405
407
  | `self` `.` _ivar-name_ `:` _type_
406
408
  | _cvar-name_ `:` _type_
407
409
 
408
- _method-member_ ::= _visibility_ `def` _method-name_ `:` _method-types_ # Instance method
409
- | _visibility_ `def self.` _method-name_ `:` _method-types_ # Singleton method
410
- | `def self?.` _method-name_ `:` _method-types_ # Singleton and instance method
410
+ _method-member_ ::= _method-class-member_
411
+ | _method-interface-member_
412
+ _method-class-member_ ::= _visibility_ `def` _method-name_ `:` _method-types_ # Instance method
413
+ | _visibility_ `def self.` _method-name_ `:` _method-types_ # Singleton method
414
+ | `def self?.` _method-name_ `:` _method-types_ # Singleton and instance method
415
+ _method-interface-member_ ::= `def` _method-name_ `:` _method-types_ # Instance method
411
416
 
412
417
  _method-types_ ::= _method-type-parameters_ _method-type_ # Single method type
413
418
  | _method-type-parameters_ _method-type_ `|` _method-types_ # Overloading types
@@ -624,7 +629,7 @@ _module-self-types_ ::= _class-name_ _type-arguments_ `,` _module-self-types_
624
629
 
625
630
  _interface-decl_ ::= `interface` _interface-name_ _module-type-parameters_ _interface-members_ `end`
626
631
 
627
- _interface-members_ ::= _method-member_ # Method
632
+ _interface-members_ ::= _method-interface-member_ # Method
628
633
  | _include-interface-member_ # Mixin (include)
629
634
  | _alias-member_ # Alias
630
635
 
@@ -4,10 +4,11 @@ $INCFLAGS << " -I$(top_srcdir)" if $extmk
4
4
  $INCFLAGS << " -I$(srcdir)/../../include"
5
5
 
6
6
  $VPATH << "$(srcdir)/../../src"
7
+ $VPATH << "$(srcdir)/../../src/util"
7
8
  $VPATH << "$(srcdir)/ext/rbs_extension"
8
9
 
9
10
  root_dir = File.expand_path('../../../', __FILE__)
10
- $srcs = Dir.glob("#{root_dir}/src/*.c") +
11
+ $srcs = Dir.glob("#{root_dir}/src/**/*.c") +
11
12
  Dir.glob("#{root_dir}/ext/rbs_extension/*.c")
12
13
 
13
14
  append_cflags ['-std=gnu99']
@@ -56,14 +56,14 @@ static void check_children_cap(rbs_loc *loc) {
56
56
  }
57
57
  }
58
58
 
59
- void rbs_loc_add_required_child(rbs_loc *loc, ID name, range r) {
59
+ void rbs_loc_add_required_child(rbs_loc *loc, rbs_constant_id_t name, range r) {
60
60
  rbs_loc_add_optional_child(loc, name, r);
61
61
 
62
62
  unsigned short last_index = loc->children->len - 1;
63
63
  loc->children->required_p |= 1 << last_index;
64
64
  }
65
65
 
66
- void rbs_loc_add_optional_child(rbs_loc *loc, ID name, range r) {
66
+ void rbs_loc_add_optional_child(rbs_loc *loc, rbs_constant_id_t name, range r) {
67
67
  check_children_cap(loc);
68
68
 
69
69
  unsigned short i = loc->children->len++;
@@ -168,6 +168,15 @@ static VALUE location_end_pos(VALUE self) {
168
168
  return INT2FIX(loc->rg.end);
169
169
  }
170
170
 
171
+ static rbs_constant_id_t rbs_constant_pool_insert_ruby_symbol(VALUE symbol) {
172
+ VALUE name = rb_sym2str(symbol);
173
+
174
+ // Constants inserted here will never be freed, but that's acceptable because:
175
+ // 1. Most symbols passed into here will be the ones already inserted into the constant pool by `parser.c`.
176
+ // 2. Methods like `add_required_child` and `add_optional_child` will usually only get called with a few different symbols.
177
+ return rbs_constant_pool_insert_constant(RBS_GLOBAL_CONSTANT_POOL, (const uint8_t *) RSTRING_PTR(name), RSTRING_LEN(name));
178
+ }
179
+
171
180
  static VALUE location_add_required_child(VALUE self, VALUE name, VALUE start, VALUE end) {
172
181
  rbs_loc *loc = rbs_check_location(self);
173
182
 
@@ -175,7 +184,7 @@ static VALUE location_add_required_child(VALUE self, VALUE name, VALUE start, VA
175
184
  rg.start = rbs_loc_position(FIX2INT(start));
176
185
  rg.end = rbs_loc_position(FIX2INT(end));
177
186
 
178
- rbs_loc_add_required_child(loc, SYM2ID(name), rg);
187
+ rbs_loc_add_required_child(loc, rbs_constant_pool_insert_ruby_symbol(name), rg);
179
188
 
180
189
  return Qnil;
181
190
  }
@@ -187,7 +196,7 @@ static VALUE location_add_optional_child(VALUE self, VALUE name, VALUE start, VA
187
196
  rg.start = rbs_loc_position(FIX2INT(start));
188
197
  rg.end = rbs_loc_position(FIX2INT(end));
189
198
 
190
- rbs_loc_add_optional_child(loc, SYM2ID(name), rg);
199
+ rbs_loc_add_optional_child(loc, rbs_constant_pool_insert_ruby_symbol(name), rg);
191
200
 
192
201
  return Qnil;
193
202
  }
@@ -195,7 +204,7 @@ static VALUE location_add_optional_child(VALUE self, VALUE name, VALUE start, VA
195
204
  static VALUE location_add_optional_no_child(VALUE self, VALUE name) {
196
205
  rbs_loc *loc = rbs_check_location(self);
197
206
 
198
- rbs_loc_add_optional_child(loc, SYM2ID(name), NULL_RANGE);
207
+ rbs_loc_add_optional_child(loc, rbs_constant_pool_insert_ruby_symbol(name), NULL_RANGE);
199
208
 
200
209
  return Qnil;
201
210
  }
@@ -218,12 +227,18 @@ static VALUE rbs_new_location_from_loc_range(VALUE buffer, rbs_loc_range rg) {
218
227
  return obj;
219
228
  }
220
229
 
230
+ static rbs_constant_id_t rbs_constant_pool_find_ruby_symbol(VALUE symbol) {
231
+ VALUE name = rb_sym2str(symbol);
232
+
233
+ return rbs_constant_pool_find(RBS_GLOBAL_CONSTANT_POOL, (const uint8_t *) RSTRING_PTR(name), RSTRING_LEN(name));
234
+ }
235
+
221
236
  static VALUE location_aref(VALUE self, VALUE name) {
222
237
  rbs_loc *loc = rbs_check_location(self);
223
238
 
224
- ID id = SYM2ID(name);
239
+ rbs_constant_id_t id = rbs_constant_pool_find_ruby_symbol(name);
225
240
 
226
- if (loc->children != NULL) {
241
+ if (loc->children != NULL && id != RBS_CONSTANT_ID_UNSET) {
227
242
  for (unsigned short i = 0; i < loc->children->len; i++) {
228
243
  if (loc->children->entries[i].name == id) {
229
244
  rbs_loc_range result = loc->children->entries[i].rg;
@@ -241,6 +256,10 @@ static VALUE location_aref(VALUE self, VALUE name) {
241
256
  rb_raise(rb_eRuntimeError, "Unknown child name given: %s", RSTRING_PTR(string));
242
257
  }
243
258
 
259
+ static VALUE rbs_constant_to_ruby_symbol(rbs_constant_t *constant) {
260
+ return ID2SYM(rb_intern2((const char *) constant->start, constant->length));
261
+ }
262
+
244
263
  static VALUE location_optional_keys(VALUE self) {
245
264
  VALUE keys = rb_ary_new();
246
265
 
@@ -252,8 +271,9 @@ static VALUE location_optional_keys(VALUE self) {
252
271
 
253
272
  for (unsigned short i = 0; i < children->len; i++) {
254
273
  if (RBS_LOC_OPTIONAL_P(loc, i)) {
255
- rb_ary_push(keys, ID2SYM(children->entries[i].name));
256
-
274
+ rbs_constant_t *key_id = rbs_constant_pool_id_to_constant(RBS_GLOBAL_CONSTANT_POOL, children->entries[i].name);
275
+ VALUE key_sym = rbs_constant_to_ruby_symbol(key_id);
276
+ rb_ary_push(keys, key_sym);
257
277
  }
258
278
  }
259
279
 
@@ -271,7 +291,9 @@ static VALUE location_required_keys(VALUE self) {
271
291
 
272
292
  for (unsigned short i = 0; i < children->len; i++) {
273
293
  if (RBS_LOC_REQUIRED_P(loc, i)) {
274
- rb_ary_push(keys, ID2SYM(children->entries[i].name));
294
+ rbs_constant_t *key_id = rbs_constant_pool_id_to_constant(RBS_GLOBAL_CONSTANT_POOL, children->entries[i].name);
295
+ VALUE key_sym = rbs_constant_to_ruby_symbol(key_id);
296
+ rb_ary_push(keys, key_sym);
275
297
  }
276
298
  }
277
299
 
@@ -3,6 +3,7 @@
3
3
 
4
4
  #include "ruby.h"
5
5
  #include "lexer.h"
6
+ #include "rbs/util/rbs_constant_pool.h"
6
7
 
7
8
  /**
8
9
  * RBS::Location class
@@ -15,7 +16,7 @@ typedef struct {
15
16
  } rbs_loc_range;
16
17
 
17
18
  typedef struct {
18
- ID name;
19
+ rbs_constant_id_t name;
19
20
  rbs_loc_range rg;
20
21
  } rbs_loc_entry;
21
22
 
@@ -58,14 +59,14 @@ void rbs_loc_alloc_children(rbs_loc *loc, unsigned short cap);
58
59
  *
59
60
  * Allocate memory for children with rbs_loc_alloc_children before calling this function.
60
61
  * */
61
- void rbs_loc_add_required_child(rbs_loc *loc, ID name, range r);
62
+ void rbs_loc_add_required_child(rbs_loc *loc, rbs_constant_id_t name, range r);
62
63
 
63
64
  /**
64
65
  * Add an optional child range with given name.
65
66
  *
66
67
  * Allocate memory for children with rbs_loc_alloc_children before calling this function.
67
68
  * */
68
- void rbs_loc_add_optional_child(rbs_loc *loc, ID name, range r);
69
+ void rbs_loc_add_optional_child(rbs_loc *loc, rbs_constant_id_t name, range r);
69
70
 
70
71
  /**
71
72
  * Returns RBS::Location object with start/end positions.
@@ -1,12 +1,33 @@
1
1
  #include "rbs_extension.h"
2
+ #include "rbs/util/rbs_constant_pool.h"
3
+
4
+ #include "ruby/vm.h"
5
+
6
+ static
7
+ void Deinit_rbs_extension(ruby_vm_t *_) {
8
+ rbs_constant_pool_free(RBS_GLOBAL_CONSTANT_POOL);
9
+ }
2
10
 
3
11
  void
4
12
  Init_rbs_extension(void)
5
13
  {
6
14
  #ifdef HAVE_RB_EXT_RACTOR_SAFE
7
15
  rb_ext_ractor_safe(true);
8
- #endif
16
+ #endif
9
17
  rbs__init_constants();
10
18
  rbs__init_location();
11
19
  rbs__init_parser();
20
+
21
+ // Calculated based on the number of unique strings used with the `INTERN` macro in `parser.c`.
22
+ //
23
+ // ```bash
24
+ // grep -o 'INTERN("\([^"]*\)")' ext/rbs_extension/parser.c \
25
+ // | sed 's/INTERN("\(.*\)")/\1/' \
26
+ // | sort -u \
27
+ // | wc -l
28
+ // ```
29
+ const size_t num_uniquely_interned_strings = 26;
30
+ rbs_constant_pool_init(RBS_GLOBAL_CONSTANT_POOL, num_uniquely_interned_strings);
31
+
32
+ ruby_vm_at_exit(Deinit_rbs_extension);
12
33
  }