typeprof 0.32.0 → 0.33.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 93757a88e1532a3e0d9faf5b3eb8690b7a61ced6027e28d49dfce43234557015
4
- data.tar.gz: 8e41f82794582ea68445e0972a6cab30982fcac483a50c5032811e3a2fcb9a60
3
+ metadata.gz: 8dc7b580d84d82c2a49d4a2d24ddf32ddcafc938d4f9511fc4b6d4543f0b8e19
4
+ data.tar.gz: eed64be210440c2ea2627a7b21c95c7eedee374b760e9e6aa479dfa4c27df54f
5
5
  SHA512:
6
- metadata.gz: f1020867309edd82548dd3bcfc84d22007324af9c6acd0e6c82bb002678dfef3bb7acc695f6cc19d243d24084871a3a7a0695b1d7f069122ab28a221fca06469
7
- data.tar.gz: 17cf614ed4edd5e75c772750fe844db59d65dcf7dc129b22269e4a840dbf4a45c1136f7ed74ac780d37d183f08de24e2ca447cd1804ea39bc39e7876f393ede8
6
+ metadata.gz: b314eccaecb06cac94df1af7ab96084b06d1d70710c9ece6934c98ca5379ca98e82ab93838322081357d13c0200681beb24d6108f699aac4a8904952333a7d83
7
+ data.tar.gz: 7ebcd55f8c8d91b1eac583c7d585723de31a83da5fa85c7485cda77e520e24d09f1652b1dde7657db62c8151166cbfdc71d3563647ccd60871bb31e74fc6055a
@@ -118,6 +118,19 @@ module TypeProf::Core
118
118
  raise "should override"
119
119
  end
120
120
 
121
+ # Counterpart of install/install0 for pattern position; reuses the install
122
+ # machinery so @changes is reconciled the same way during incremental analysis.
123
+ def install_pattern(genv, subject)
124
+ @ret = install_pattern0(genv, subject)
125
+ @changes.reinstall(genv)
126
+ @ret
127
+ end
128
+
129
+ # By default a pattern behaves as a plain expression, ignoring the matched value.
130
+ def install_pattern0(genv, subject)
131
+ install0(genv)
132
+ end
133
+
121
134
  def uninstall(genv)
122
135
  @changes.reinstall(genv)
123
136
  each_subnode do |subnode|
@@ -1,12 +1,12 @@
1
1
  module TypeProf::Core
2
2
  class AST
3
3
  class CallBaseNode < Node
4
- def initialize(raw_node, recv, mid, mid_code_range, raw_args, last_arg, raw_block, lenv, forwarding_arguments: false)
4
+ def initialize(raw_node, recv, mid, mid_code_range_loc, raw_args, last_arg, raw_block, lenv, forwarding_arguments: false)
5
5
  super(raw_node, lenv)
6
6
 
7
7
  @recv = recv
8
8
  @mid = mid
9
- @mid_code_range = mid_code_range
9
+ @mid_code_range_loc = mid_code_range_loc
10
10
 
11
11
  # args
12
12
  @positional_args = []
@@ -31,7 +31,7 @@ module TypeProf::Core
31
31
  args << raw_arg.expression
32
32
  @splat_flags << true
33
33
  when Prism::ForwardingArgumentsNode
34
- @forwarding_arguments = true
34
+ @forwarding_arguments = :rest
35
35
  else
36
36
  args << raw_arg
37
37
  @splat_flags << false
@@ -60,17 +60,24 @@ module TypeProf::Core
60
60
  @block_multi_targets = {}
61
61
  @block_f_args = case raw_block.parameters
62
62
  when Prism::BlockParametersNode
63
+ # `{ || ... }` (empty pipes) and `{ |; x| ... }`
64
+ # (block-local-only) yield BlockParametersNode
65
+ # whose inner `parameters` is nil.
63
66
  params = raw_block.parameters.parameters
64
- req = params.requireds.each_with_index.map do |n, i|
65
- if n.is_a?(Prism::MultiTargetNode)
66
- @block_multi_targets[i] = n
67
- nil
68
- else
69
- n.name
67
+ if params
68
+ req = params.requireds.each_with_index.map do |n, i|
69
+ if n.is_a?(Prism::MultiTargetNode)
70
+ @block_multi_targets[i] = n
71
+ nil
72
+ else
73
+ n.name
74
+ end
70
75
  end
76
+ opt = params.optionals.map {|n| n.name }
77
+ req + opt
78
+ else
79
+ []
71
80
  end
72
- opt = params.optionals.map {|n| n.name }
73
- req + opt
74
81
  when Prism::NumberedParametersNode
75
82
  1.upto(raw_block.parameters.maximum).map { |n| :"_#{n}" }
76
83
  when Prism::ItParametersNode
@@ -83,7 +90,7 @@ module TypeProf::Core
83
90
  ncref = CRef.new(lenv.cref.cpath, :instance, @mid, lenv.cref)
84
91
  nlenv = LocalEnv.new(@lenv.file_context, ncref, {}, @lenv.return_boxes)
85
92
  @block_opt_positional_defaults = []
86
- if raw_block.parameters.is_a?(Prism::BlockParametersNode)
93
+ if raw_block.parameters.is_a?(Prism::BlockParametersNode) && raw_block.parameters.parameters
87
94
  raw_block.parameters.parameters.optionals.each do |n|
88
95
  @block_opt_positional_defaults << AST.create_node(n.value, nlenv)
89
96
  end
@@ -95,7 +102,11 @@ module TypeProf::Core
95
102
  @yield = raw_node.type == :yield_node
96
103
  end
97
104
 
98
- attr_reader :recv, :mid, :mid_code_range, :yield
105
+ attr_reader :recv, :mid, :yield
106
+
107
+ def mid_code_range
108
+ @mid_code_range ||= @lenv.code_range_from_node(@mid_code_range_loc) if @mid_code_range_loc
109
+ end
99
110
  attr_reader :positional_args, :splat_flags, :keyword_args
100
111
  attr_reader :block_tbl, :block_f_args, :block_opt_positional_defaults, :block_body, :block_pass, :anonymous_block_forwarding
101
112
  attr_reader :block_multi_targets
@@ -113,10 +124,17 @@ module TypeProf::Core
113
124
  end
114
125
 
115
126
  if @forwarding_arguments
116
- forward_a_args = (@lenv.forward_args || raise).to_actual_arguments(genv, @changes, self)
117
- positional_args = forward_a_args.positionals
118
- splat_flags = forward_a_args.splat_flags
119
- keyword_args = forward_a_args.keywords
127
+ forward_a_args = (@lenv.forward_args || raise).to_actual_arguments(
128
+ genv,
129
+ @changes,
130
+ self,
131
+ include_leading_positionals: @forwarding_arguments != :rest,
132
+ activation_required: @forwarding_arguments == :rest,
133
+ )
134
+ # An anonymous rest cannot appear here: `bar(*, ...)` is a syntax error
135
+ leading_args = @positional_args.map {|arg| arg.install(genv) }
136
+ a_args = forward_a_args.prepend_positionals(leading_args, @splat_flags)
137
+ a_args = a_args.with_keywords(@keyword_args.install(genv)) if @keyword_args
120
138
  else
121
139
  positional_args = @positional_args.map do |arg|
122
140
  if arg.nil?
@@ -125,8 +143,7 @@ module TypeProf::Core
125
143
  arg.install(genv)
126
144
  end
127
145
  end
128
- splat_flags = @splat_flags
129
- keyword_args = @keyword_args ? @keyword_args.install(genv) : nil
146
+ a_args = ActualArguments.new(positional_args, @splat_flags, @keyword_args ? @keyword_args.install(genv) : nil, nil)
130
147
  end
131
148
 
132
149
  if @block_body
@@ -198,7 +215,11 @@ module TypeProf::Core
198
215
  blk_ty = forward_a_args.block
199
216
  end
200
217
 
201
- a_args = ActualArguments.new(positional_args, splat_flags, keyword_args, blk_ty)
218
+ if @forwarding_arguments
219
+ a_args = a_args.with_block(blk_ty, omittable: !@block_body && !@block_pass && !@anonymous_block_forwarding)
220
+ else
221
+ a_args = a_args.with_block(blk_ty)
222
+ end
202
223
  box = @changes.add_method_call_box(genv, recv, @mid, a_args, !@recv)
203
224
 
204
225
  block_body = @block_body
@@ -230,7 +251,7 @@ module TypeProf::Core
230
251
  end
231
252
 
232
253
  def retrieve_at(pos, &blk)
233
- yield self if @mid_code_range && @mid_code_range.include?(pos)
254
+ yield self if mid_code_range&.include?(pos)
234
255
  each_subnode do |subnode|
235
256
  next unless subnode
236
257
  subnode.retrieve_at(pos, &blk)
@@ -257,10 +278,9 @@ module TypeProf::Core
257
278
  def initialize(raw_node, lenv)
258
279
  recv = raw_node.receiver ? AST.create_node(raw_node.receiver, lenv) : nil
259
280
  mid = raw_node.name
260
- mid_code_range = lenv.code_range_from_node(raw_node.message_loc) if raw_node.message_loc
261
281
  raw_args = raw_node.arguments
262
282
  raw_block = raw_node.block
263
- super(raw_node, recv, mid, mid_code_range, raw_args, nil, raw_block, lenv)
283
+ super(raw_node, recv, mid, raw_node.message_loc, raw_args, nil, raw_block, lenv)
264
284
  end
265
285
 
266
286
  def narrowings
@@ -317,7 +337,7 @@ module TypeProf::Core
317
337
  def initialize(raw_node, lenv)
318
338
  raw_args = nil
319
339
  raw_block = raw_node.block
320
- super(raw_node, nil, :"*super", nil, raw_args, nil, raw_block, lenv, forwarding_arguments: true)
340
+ super(raw_node, nil, :"*super", nil, raw_args, nil, raw_block, lenv, forwarding_arguments: :all)
321
341
  end
322
342
  end
323
343
 
@@ -331,9 +351,8 @@ module TypeProf::Core
331
351
  class OperatorNode < CallBaseNode
332
352
  def initialize(raw_node, recv, lenv)
333
353
  mid = raw_node.binary_operator
334
- mid_code_range = lenv.code_range_from_node(raw_node.binary_operator_loc)
335
354
  last_arg = AST.create_node(raw_node.value, lenv)
336
- super(raw_node, recv, mid, mid_code_range, nil, last_arg, nil, lenv)
355
+ super(raw_node, recv, mid, raw_node.binary_operator_loc, nil, last_arg, nil, lenv)
337
356
  end
338
357
  end
339
358
 
@@ -364,8 +383,7 @@ module TypeProf::Core
364
383
  def initialize(raw_node, lenv)
365
384
  recv = AST.create_node(raw_node.receiver, lenv)
366
385
  mid = raw_node.read_name
367
- mid_code_range = lenv.code_range_from_node(raw_node.message_loc)
368
- super(raw_node, recv, mid, mid_code_range, nil, nil, nil, lenv)
386
+ super(raw_node, recv, mid, raw_node.message_loc, nil, nil, nil, lenv)
369
387
  end
370
388
  end
371
389
 
@@ -373,9 +391,8 @@ module TypeProf::Core
373
391
  def initialize(raw_node, rhs, lenv)
374
392
  recv = AST.create_node(raw_node.receiver, lenv)
375
393
  mid = raw_node.is_a?(Prism::CallTargetNode) ? raw_node.name : raw_node.write_name
376
- mid_code_range = lenv.code_range_from_node(raw_node.message_loc)
377
394
  @rhs = rhs
378
- super(raw_node, recv, mid, mid_code_range, nil, rhs, nil, lenv)
395
+ super(raw_node, recv, mid, raw_node.message_loc, nil, rhs, nil, lenv)
379
396
  end
380
397
 
381
398
  attr_reader :rhs
@@ -8,7 +8,7 @@ module TypeProf::Core
8
8
  @cbase = nil
9
9
  @toplevel = false
10
10
  @cname = raw_node.name
11
- @cname_code_range = lenv.code_range_from_node(raw_node.location)
11
+ @cname_code_range_loc = raw_node.location
12
12
  when :constant_path_node, :constant_path_target_node
13
13
  if raw_node.parent
14
14
  @cbase = AST.create_node(raw_node.parent, lenv)
@@ -18,14 +18,18 @@ module TypeProf::Core
18
18
  @toplevel = true
19
19
  end
20
20
  @cname = raw_node.name
21
- @cname_code_range = lenv.code_range_from_node(raw_node.name_loc)
21
+ @cname_code_range_loc = raw_node.name_loc
22
22
  else
23
23
  raise raw_node.type.to_s
24
24
  end
25
25
  @strict_const_scope = lenv.strict_const_scope
26
26
  end
27
27
 
28
- attr_reader :cname, :cbase, :toplevel, :cname_code_range, :strict_const_scope
28
+ attr_reader :cname, :cbase, :toplevel, :strict_const_scope
29
+
30
+ def cname_code_range
31
+ @cname_code_range ||= @lenv.code_range_from_node(@cname_code_range_loc) if @cname_code_range_loc
32
+ end
29
33
 
30
34
  def attrs = { cname:, toplevel:, strict_const_scope: }
31
35
  def subnodes = { cbase: }
@@ -57,24 +61,28 @@ module TypeProf::Core
57
61
  # C = expr
58
62
  @cpath = nil
59
63
  @static_cpath = lenv.cref.cpath + [raw_node.name]
60
- @cname_code_range = lenv.code_range_from_node(raw_node.respond_to?(:name_loc) ? raw_node.name_loc : raw_node)
64
+ @cname_code_range_loc = raw_node.respond_to?(:name_loc) ? raw_node.name_loc : raw_node.location
61
65
  when :constant_path_write_node, :constant_path_operator_write_node, :constant_path_or_write_node, :constant_path_and_write_node
62
66
  # expr::C = expr
63
67
  @cpath = AST.create_node(raw_node.target, lenv)
64
68
  @static_cpath = AST.parse_cpath(raw_node.target, lenv.cref)
65
- @cname_code_range = lenv.code_range_from_node(raw_node.target)
69
+ @cname_code_range_loc = raw_node.target.location
66
70
  when :constant_path_target_node
67
71
  # expr::C, * = ary
68
72
  @cpath = ConstantReadNode.new(raw_node, lenv)
69
73
  @static_cpath = AST.parse_cpath(raw_node, lenv.cref)
70
- @cname_code_range = lenv.code_range_from_node(raw_node)
74
+ @cname_code_range_loc = raw_node.location
71
75
  else
72
76
  raise
73
77
  end
74
78
  @rhs = rhs
75
79
  end
76
80
 
77
- attr_reader :cpath, :rhs, :static_cpath, :cname_code_range
81
+ attr_reader :cpath, :rhs, :static_cpath
82
+
83
+ def cname_code_range
84
+ @cname_code_range ||= @lenv.code_range_from_node(@cname_code_range_loc) if @cname_code_range_loc
85
+ end
78
86
 
79
87
  def subnodes = { cpath:, rhs: }
80
88
  def attrs = { static_cpath: }
@@ -414,9 +414,9 @@ module TypeProf::Core
414
414
 
415
415
  def install0(genv)
416
416
  ret = Vertex.new(self)
417
- @pivot&.install(genv)
417
+ subject = @pivot ? @pivot.install(genv) : Source.new(genv.nil_type)
418
418
  @patterns.zip(@clauses) do |pattern, clause|
419
- pattern.install(genv)
419
+ pattern.install_pattern(genv, subject)
420
420
  @changes.add_edge(genv, clause.install(genv), ret)
421
421
  end
422
422
  @changes.add_edge(genv, @else_clause.install(genv), ret) if @else_clause
@@ -46,9 +46,56 @@ module TypeProf::Core
46
46
  end
47
47
  end
48
48
 
49
+ class ExtendMetaNode < Node
50
+ def initialize(raw_node, lenv)
51
+ super(raw_node, lenv)
52
+ # TODO: error for splat
53
+ @args = raw_node.arguments.arguments.map do |raw_arg|
54
+ next if raw_arg.is_a?(Prism::SplatNode)
55
+ lenv.use_strict_const_scope do
56
+ AST.create_node(raw_arg, lenv)
57
+ end
58
+ end.compact
59
+ # TODO: error for non-LIT
60
+ # TODO: fine-grained hover
61
+ end
62
+
63
+ attr_reader :args
64
+
65
+ def subnodes = { args: }
66
+
67
+ def define0(genv)
68
+ mod = genv.resolve_cpath(@lenv.cref.cpath)
69
+ @args.each do |arg|
70
+ arg.define(genv)
71
+ if arg.static_ret
72
+ arg.static_ret.followers << mod
73
+ mod.add_extend_def(genv, arg)
74
+ end
75
+ end
76
+ end
77
+
78
+ def undefine0(genv)
79
+ mod = genv.resolve_cpath(@lenv.cref.cpath)
80
+ @args.each do |arg|
81
+ if arg.static_ret
82
+ mod.remove_extend_def(genv, arg)
83
+ end
84
+ arg.undefine(genv)
85
+ end
86
+ super(genv)
87
+ end
88
+
89
+ def install0(genv)
90
+ @args.each {|arg| arg.install(genv) }
91
+ Source.new
92
+ end
93
+ end
94
+
49
95
  class AttrReaderMetaNode < Node
50
96
  def initialize(raw_node, lenv)
51
97
  super(raw_node, lenv)
98
+ @singleton = lenv.cref.scope_level == :metaclass
52
99
  @args = []
53
100
  raw_node.arguments.arguments.each do |raw_arg|
54
101
  @args << raw_arg.value.to_sym if raw_arg.type == :symbol_node
@@ -57,9 +104,9 @@ module TypeProf::Core
57
104
  # TODO: fine-grained hover
58
105
  end
59
106
 
60
- attr_reader :args
107
+ attr_reader :singleton, :args
61
108
 
62
- def attrs = { args: }
109
+ def attrs = { singleton:, args: }
63
110
 
64
111
  def req_positionals = []
65
112
  def opt_positionals = []
@@ -68,6 +115,7 @@ module TypeProf::Core
68
115
  def req_keywords = []
69
116
  def opt_keywords = []
70
117
  def rest_keywords = nil
118
+ def no_keywords = false
71
119
 
72
120
  def mname_code_range(name)
73
121
  idx = @args.index(name.to_sym) # TODO: support string args
@@ -78,9 +126,9 @@ module TypeProf::Core
78
126
  def install0(genv)
79
127
  @args.each do |arg|
80
128
  ivar_name = :"@#{ arg }"
81
- ivar_box = @changes.add_ivar_read_box(genv, @lenv.cref.cpath, false, ivar_name)
129
+ ivar_box = @changes.add_ivar_read_box(genv, @lenv.cref.cpath, @singleton, ivar_name)
82
130
  ret_box = @changes.add_escape_box(genv, ivar_box.ret)
83
- @changes.add_method_def_box(genv, @lenv.cref.cpath, false, arg, FormalArguments::Empty, [ret_box])
131
+ @changes.add_method_def_box(genv, @lenv.cref.cpath, @singleton, arg, FormalArguments::Empty, [ret_box])
84
132
  end
85
133
  Source.new
86
134
  end
@@ -89,15 +137,22 @@ module TypeProf::Core
89
137
  class AttrWriterMetaNode < Node
90
138
  def initialize(raw_node, lenv)
91
139
  super(raw_node, lenv)
140
+ @singleton = lenv.cref.scope_level == :metaclass
92
141
  @args = []
93
142
  raw_node.arguments.arguments.each do |raw_arg|
94
143
  @args << raw_arg.value.to_sym if raw_arg.type == :symbol_node
95
144
  end
96
145
  end
97
146
 
98
- attr_reader :args
147
+ attr_reader :singleton, :args
99
148
 
100
- def attrs = { args: }
149
+ def attrs = { singleton:, args: }
150
+
151
+ # Interface expected by MethodDefBox
152
+ def req_keywords = []
153
+ def opt_keywords = []
154
+ def rest_keywords = nil
155
+ def no_keywords = false
101
156
 
102
157
  def mname_code_range(name)
103
158
  idx = @args.index(name.to_sym)
@@ -107,7 +162,7 @@ module TypeProf::Core
107
162
 
108
163
  def define0(genv)
109
164
  @args.map do |arg|
110
- mod = genv.resolve_ivar(lenv.cref.cpath, false, :"@#{ arg }")
165
+ mod = genv.resolve_ivar(lenv.cref.cpath, @singleton, :"@#{ arg }")
111
166
  mod.add_def(self)
112
167
  mod
113
168
  end
@@ -115,7 +170,7 @@ module TypeProf::Core
115
170
 
116
171
  def define_copy(genv)
117
172
  @args.map do |arg|
118
- mod = genv.resolve_ivar(lenv.cref.cpath, false, :"@#{ arg }")
173
+ mod = genv.resolve_ivar(lenv.cref.cpath, @singleton, :"@#{ arg }")
119
174
  mod.add_def(self)
120
175
  mod.remove_def(@prev_node)
121
176
  mod
@@ -125,7 +180,7 @@ module TypeProf::Core
125
180
 
126
181
  def undefine0(genv)
127
182
  @args.each do |arg|
128
- mod = genv.resolve_ivar(lenv.cref.cpath, false, :"@#{ arg }")
183
+ mod = genv.resolve_ivar(lenv.cref.cpath, @singleton, :"@#{ arg }")
129
184
  mod.remove_def(self)
130
185
  end
131
186
  end
@@ -136,7 +191,7 @@ module TypeProf::Core
136
191
  @changes.add_edge(genv, vtx, ive.vtx)
137
192
  ret_box = @changes.add_escape_box(genv, vtx)
138
193
  f_args = FormalArguments.new([vtx], [], nil, [], [], [], nil, nil)
139
- @changes.add_method_def_box(genv, @lenv.cref.cpath, false, :"#{ arg }=", f_args, [ret_box])
194
+ @changes.add_method_def_box(genv, @lenv.cref.cpath, @singleton, :"#{ arg }=", f_args, [ret_box])
140
195
  end
141
196
  Source.new
142
197
  end
@@ -145,6 +200,7 @@ module TypeProf::Core
145
200
  class AttrAccessorMetaNode < Node
146
201
  def initialize(raw_node, lenv)
147
202
  super(raw_node, lenv)
203
+ @singleton = lenv.cref.scope_level == :metaclass
148
204
  @args = []
149
205
  raw_node.arguments.arguments.each do |raw_arg|
150
206
  @args << raw_arg.value.to_sym if raw_arg.type == :symbol_node
@@ -153,9 +209,15 @@ module TypeProf::Core
153
209
  # TODO: fine-grained hover
154
210
  end
155
211
 
156
- attr_reader :args
212
+ attr_reader :singleton, :args
157
213
 
158
- def attrs = { args: }
214
+ def attrs = { singleton:, args: }
215
+
216
+ # Interface expected by MethodDefBox
217
+ def req_keywords = []
218
+ def opt_keywords = []
219
+ def rest_keywords = nil
220
+ def no_keywords = false
159
221
 
160
222
  def mname_code_range(name)
161
223
  idx = @args.index(name.to_sym) # TODO: support string args
@@ -165,7 +227,7 @@ module TypeProf::Core
165
227
 
166
228
  def define0(genv)
167
229
  @args.map do |arg|
168
- mod = genv.resolve_ivar(lenv.cref.cpath, false, :"@#{ arg }")
230
+ mod = genv.resolve_ivar(lenv.cref.cpath, @singleton, :"@#{ arg }")
169
231
  mod.add_def(self)
170
232
  mod
171
233
  end
@@ -173,7 +235,7 @@ module TypeProf::Core
173
235
 
174
236
  def define_copy(genv)
175
237
  @args.map do |arg|
176
- mod = genv.resolve_ivar(lenv.cref.cpath, false, :"@#{ arg }")
238
+ mod = genv.resolve_ivar(lenv.cref.cpath, @singleton, :"@#{ arg }")
177
239
  mod.add_def(self)
178
240
  mod.remove_def(@prev_node)
179
241
  mod
@@ -183,21 +245,21 @@ module TypeProf::Core
183
245
 
184
246
  def undefine0(genv)
185
247
  @args.each do |arg|
186
- mod = genv.resolve_ivar(lenv.cref.cpath, false, :"@#{ arg }")
248
+ mod = genv.resolve_ivar(lenv.cref.cpath, @singleton, :"@#{ arg }")
187
249
  mod.remove_def(self)
188
250
  end
189
251
  end
190
252
 
191
253
  def install0(genv)
192
254
  @args.zip(@static_ret) do |arg, ive|
193
- ivar_box = @changes.add_ivar_read_box(genv, @lenv.cref.cpath, false, :"@#{ arg }")
255
+ ivar_box = @changes.add_ivar_read_box(genv, @lenv.cref.cpath, @singleton, :"@#{ arg }")
194
256
  ret_box = @changes.add_escape_box(genv, ivar_box.ret)
195
- @changes.add_method_def_box(genv, @lenv.cref.cpath, false, arg, FormalArguments::Empty, [ret_box])
257
+ @changes.add_method_def_box(genv, @lenv.cref.cpath, @singleton, arg, FormalArguments::Empty, [ret_box])
196
258
 
197
259
  vtx = Vertex.new(self)
198
260
  @changes.add_edge(genv, vtx, ive.vtx)
199
261
  f_args = FormalArguments.new([vtx], [], nil, [], [], [], nil, nil)
200
- @changes.add_method_def_box(genv, @lenv.cref.cpath, false, :"#{ arg }=", f_args, [ret_box])
262
+ @changes.add_method_def_box(genv, @lenv.cref.cpath, @singleton, :"#{ arg }=", f_args, [ret_box])
201
263
  end
202
264
  Source.new
203
265
  end
@@ -234,6 +296,11 @@ module TypeProf::Core
234
296
 
235
297
  attr_reader :static_cpath, :members, :kind, :block_body
236
298
 
299
+ # Not a valid constant name, so no Ruby code can refer to it
300
+ BASE_CNAME = :"<struct base>"
301
+
302
+ def struct_base_cpath = @static_cpath + [BASE_CNAME]
303
+
237
304
  def subnodes = { block_body: }
238
305
  def attrs = { static_cpath:, members:, kind: }
239
306
 
@@ -251,8 +318,9 @@ module TypeProf::Core
251
318
  mod = genv.resolve_cpath(@static_cpath)
252
319
  # add_module_def internally calls get_const(name).add_def(self)
253
320
  cdef = mod.add_module_def(genv, self)
321
+ genv.resolve_cpath(struct_base_cpath).add_module_def(genv, self)
254
322
  @members.each do |member|
255
- ive = genv.resolve_ivar(@static_cpath, false, member)
323
+ ive = genv.resolve_ivar(struct_base_cpath, false, member)
256
324
  ive.add_def(self)
257
325
  end
258
326
  @block_body.define(genv) if @block_body
@@ -263,8 +331,11 @@ module TypeProf::Core
263
331
  mod = genv.resolve_cpath(@static_cpath)
264
332
  mod.add_module_def(genv, self)
265
333
  mod.remove_module_def(genv, @prev_node)
334
+ base = genv.resolve_cpath(struct_base_cpath)
335
+ base.add_module_def(genv, self)
336
+ base.remove_module_def(genv, @prev_node)
266
337
  @members.each do |member|
267
- ive = genv.resolve_ivar(@static_cpath, false, member)
338
+ ive = genv.resolve_ivar(struct_base_cpath, false, member)
268
339
  ive.add_def(self)
269
340
  ive.remove_def(@prev_node)
270
341
  end
@@ -274,8 +345,9 @@ module TypeProf::Core
274
345
  def undefine0(genv)
275
346
  mod = genv.resolve_cpath(@static_cpath)
276
347
  mod.remove_module_def(genv, self)
348
+ genv.resolve_cpath(struct_base_cpath).remove_module_def(genv, self)
277
349
  @members.each do |member|
278
- ive = genv.resolve_ivar(@static_cpath, false, member)
350
+ ive = genv.resolve_ivar(struct_base_cpath, false, member)
279
351
  ive.remove_def(self)
280
352
  end
281
353
  @block_body.undefine(genv) if @block_body
@@ -288,7 +360,7 @@ module TypeProf::Core
288
360
  @changes.add_edge(genv, mod_val, @static_ret.vtx)
289
361
  end
290
362
 
291
- cpath = @static_cpath
363
+ cpath = struct_base_cpath
292
364
  @members.each do |member|
293
365
  # Use bare `:member` (not `:@member`) so the slot can't collide with a
294
366
  # user-written @member ivar — Struct/Data fields are not real ivars.
@@ -325,7 +397,8 @@ module TypeProf::Core
325
397
 
326
398
  # Struct.[] is an alias for Struct.new
327
399
  if @kind == :struct
328
- self_ret = @changes.add_escape_box(genv, Source.new(Type::Instance.new(genv, genv.resolve_cpath(cpath), [])))
400
+ # Struct.[] builds the struct class itself, not the base class
401
+ self_ret = @changes.add_escape_box(genv, Source.new(Type::Instance.new(genv, genv.resolve_cpath(@static_cpath), [])))
329
402
  @changes.add_method_def_box(genv, cpath, true, :[], init_f_args, [self_ret])
330
403
  end
331
404
 
@@ -135,7 +135,7 @@ module TypeProf::Core
135
135
  # TODO: warn "def self.foo" in a metaclass
136
136
  singleton = !!raw_node.receiver || lenv.cref.scope_level == :metaclass
137
137
  mid = raw_node.name
138
- mid_code_range = lenv.code_range_from_node(raw_node.name_loc)
138
+ mid_code_range_loc = raw_node.name_loc
139
139
  @tbl = raw_node.locals
140
140
  raw_args = raw_node.parameters
141
141
  raw_body = raw_node.body
@@ -144,7 +144,7 @@ module TypeProf::Core
144
144
 
145
145
  @singleton = singleton
146
146
  @mid = mid
147
- @mid_code_range = mid_code_range
147
+ @mid_code_range_loc = mid_code_range_loc
148
148
 
149
149
  ncref = CRef.new(lenv.cref.cpath, @singleton ? :class : :instance, @mid, lenv.cref)
150
150
  nlenv = LocalEnv.new(@lenv.file_context, ncref, {}, [])
@@ -177,7 +177,11 @@ module TypeProf::Core
177
177
  @reusable = !use_result
178
178
  end
179
179
 
180
- attr_reader :singleton, :mid, :mid_code_range
180
+ attr_reader :singleton, :mid
181
+
182
+ def mid_code_range
183
+ @mid_code_range ||= @lenv.code_range_from_node(@mid_code_range_loc) if @mid_code_range_loc
184
+ end
181
185
  attr_reader :tbl
182
186
  attr_reader :req_positionals
183
187
  attr_reader :opt_positionals
@@ -203,7 +207,6 @@ module TypeProf::Core
203
207
  def attrs = {
204
208
  singleton:,
205
209
  mid:,
206
- mid_code_range:,
207
210
  tbl:,
208
211
  req_positionals:,
209
212
  opt_positionals:,
@@ -217,7 +220,7 @@ module TypeProf::Core
217
220
  reusable:,
218
221
  }
219
222
 
220
- def mname_code_range(_name) = @mid_code_range
223
+ def mname_code_range(_name) = mid_code_range
221
224
 
222
225
  def define(genv) # NOT define0
223
226
  return define_copy(genv) if @prev_node && @reusable
@@ -271,21 +274,22 @@ module TypeProf::Core
271
274
  block = @body.lenv.new_var(:"*given_block", self)
272
275
  end
273
276
 
274
- forward_opt_positionals = @opt_positionals.map do
275
- elem_vtx = Vertex.new(self)
276
- [Source.new(genv.gen_ary_type(elem_vtx)), elem_vtx]
277
- end
277
+ forward_opt_positionals = @opt_positionals.map { Vertex.new(self) }
278
+ forward_rest_positionals = @rest_positionals ? Vertex.new(self) : nil
278
279
  forward_opt_keywords = @opt_keywords.map {|_name| Vertex.new(self) }
280
+ forward_rest_keywords = @rest_keywords ? Vertex.new(self) : nil
281
+ forward_block = Vertex.new(self)
282
+ forward_activation = Vertex.new(self)
279
283
  @body.lenv.forward_args = ForwardingArguments.new(
280
284
  req_positionals,
281
- forward_opt_positionals.map(&:first),
282
- forward_opt_positionals.map(&:last),
283
- rest_positionals,
285
+ forward_opt_positionals,
286
+ forward_rest_positionals,
284
287
  post_positionals,
285
288
  @req_keywords.zip(req_keywords),
286
289
  @opt_keywords.zip(forward_opt_keywords),
287
- rest_keywords,
288
- block,
290
+ forward_rest_keywords,
291
+ forward_block,
292
+ forward_activation,
289
293
  )
290
294
 
291
295
  if @body