typeprof 0.30.1 → 0.31.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 +4 -4
- data/README.md +23 -4
- data/lib/typeprof/cli/cli.rb +27 -7
- data/lib/typeprof/code_range.rb +9 -7
- data/lib/typeprof/core/ast/base.rb +27 -10
- data/lib/typeprof/core/ast/call.rb +85 -24
- data/lib/typeprof/core/ast/const.rb +7 -12
- data/lib/typeprof/core/ast/control.rb +345 -71
- data/lib/typeprof/core/ast/meta.rb +5 -5
- data/lib/typeprof/core/ast/method.rb +15 -5
- data/lib/typeprof/core/ast/misc.rb +21 -2
- data/lib/typeprof/core/ast/module.rb +10 -7
- data/lib/typeprof/core/ast/pattern.rb +9 -1
- data/lib/typeprof/core/ast/sig_decl.rb +163 -42
- data/lib/typeprof/core/ast/sig_type.rb +394 -24
- data/lib/typeprof/core/ast/value.rb +10 -2
- data/lib/typeprof/core/ast/variable.rb +32 -2
- data/lib/typeprof/core/ast.rb +15 -4
- data/lib/typeprof/core/builtin.rb +15 -9
- data/lib/typeprof/core/env/method.rb +21 -16
- data/lib/typeprof/core/env/method_entity.rb +11 -2
- data/lib/typeprof/core/env/module_entity.rb +57 -0
- data/lib/typeprof/core/env/narrowing.rb +131 -0
- data/lib/typeprof/core/env/static_read.rb +9 -8
- data/lib/typeprof/core/env.rb +37 -12
- data/lib/typeprof/core/graph/box.rb +207 -97
- data/lib/typeprof/core/graph/change_set.rb +44 -37
- data/lib/typeprof/core/graph/vertex.rb +4 -21
- data/lib/typeprof/core/service.rb +30 -1
- data/lib/typeprof/core/type.rb +48 -123
- data/lib/typeprof/core.rb +1 -0
- data/lib/typeprof/diagnostic.rb +5 -6
- data/lib/typeprof/lsp/messages.rb +21 -15
- data/lib/typeprof/lsp/server.rb +132 -39
- data/lib/typeprof/lsp/text.rb +1 -0
- data/lib/typeprof/version.rb +1 -1
- data/typeprof.conf.jsonc +22 -0
- data/typeprof.gemspec +1 -0
- metadata +19 -6
|
@@ -39,18 +39,12 @@ module TypeProf::Core
|
|
|
39
39
|
@changes.reinstall(genv)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
-
def
|
|
43
|
-
raise
|
|
44
|
-
@changes.diagnostics.each(&blk)
|
|
45
|
-
@changes.boxes.each_value do |box|
|
|
46
|
-
box.diagnostics(genv, &blk)
|
|
47
|
-
end
|
|
42
|
+
def run0(genv, changes)
|
|
43
|
+
raise NotImplementedError
|
|
48
44
|
end
|
|
49
45
|
|
|
50
|
-
#@@new_id = 0
|
|
51
|
-
|
|
52
46
|
def to_s
|
|
53
|
-
"#{ self.class.to_s.split("::").last
|
|
47
|
+
"#{ self.class.to_s.split("::").last }#{ @id ||= $new_id += 1 }"
|
|
54
48
|
end
|
|
55
49
|
|
|
56
50
|
alias inspect to_s
|
|
@@ -87,7 +81,20 @@ module TypeProf::Core
|
|
|
87
81
|
attr_reader :node, :rbs_type, :ret
|
|
88
82
|
|
|
89
83
|
def run0(genv, changes)
|
|
90
|
-
|
|
84
|
+
# Create substitution map for type parameters if we're in a SigInstanceVariableNode within a generic class
|
|
85
|
+
subst = {}
|
|
86
|
+
if @node.is_a?(AST::SigInstanceVariableNode) && @node.cpath
|
|
87
|
+
mod = genv.resolve_cpath(@node.cpath)
|
|
88
|
+
if mod.type_params && !mod.type_params.empty?
|
|
89
|
+
# Create a substitution map where each type parameter maps to a type variable vertex
|
|
90
|
+
subst = mod.type_params.to_h do |param|
|
|
91
|
+
type_var_vtx = Vertex.new(@node)
|
|
92
|
+
[param, type_var_vtx]
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
vtx = @rbs_type.covariant_vertex(genv, changes, subst)
|
|
91
98
|
changes.add_edge(genv, vtx, @ret)
|
|
92
99
|
end
|
|
93
100
|
end
|
|
@@ -142,13 +149,11 @@ module TypeProf::Core
|
|
|
142
149
|
end
|
|
143
150
|
|
|
144
151
|
method_type.req_positionals.each_with_index do |ty, i|
|
|
145
|
-
|
|
146
|
-
return false unless a_args.positionals[i].check_match(genv, changes, f_arg)
|
|
152
|
+
return false unless ty.typecheck(genv, changes, a_args.positionals[i], param_map)
|
|
147
153
|
end
|
|
148
154
|
method_type.post_positionals.each_with_index do |ty, i|
|
|
149
|
-
f_arg = ty.contravariant_vertex(genv, changes, param_map)
|
|
150
155
|
i -= method_type.post_positionals.size
|
|
151
|
-
return false unless a_args.positionals[i]
|
|
156
|
+
return false unless ty.typecheck(genv, changes, a_args.positionals[i], param_map)
|
|
152
157
|
end
|
|
153
158
|
|
|
154
159
|
start_rest = method_type.req_positionals.size
|
|
@@ -157,61 +162,100 @@ module TypeProf::Core
|
|
|
157
162
|
i = 0
|
|
158
163
|
while i < method_type.opt_positionals.size && start_rest < end_rest
|
|
159
164
|
break if a_args.splat_flags[start_rest]
|
|
160
|
-
|
|
161
|
-
return false unless a_args.positionals[start_rest].check_match(genv, changes, f_arg)
|
|
165
|
+
return false unless method_type.opt_positionals[i].typecheck(genv, changes, a_args.positionals[start_rest], param_map)
|
|
162
166
|
i += 1
|
|
163
167
|
start_rest += 1
|
|
164
168
|
end
|
|
165
169
|
|
|
166
170
|
if start_rest < end_rest
|
|
167
|
-
vtxs = a_args.get_rest_args(genv, start_rest, end_rest)
|
|
171
|
+
vtxs = a_args.get_rest_args(genv, changes, start_rest, end_rest)
|
|
168
172
|
while i < method_type.opt_positionals.size
|
|
169
|
-
|
|
170
|
-
return false if vtxs.any? {|vtx| !
|
|
173
|
+
ty = method_type.opt_positionals[i]
|
|
174
|
+
return false if vtxs.any? {|vtx| !ty.typecheck(genv, changes, vtx, param_map) }
|
|
171
175
|
i += 1
|
|
172
176
|
end
|
|
173
177
|
if method_type.rest_positionals
|
|
174
|
-
|
|
175
|
-
return false if vtxs.any? {|vtx| !vtx.check_match(genv, changes, f_arg) }
|
|
178
|
+
return false if vtxs.any? {|vtx| !method_type.rest_positionals.typecheck(genv, changes, vtx, param_map) }
|
|
176
179
|
end
|
|
177
180
|
end
|
|
178
181
|
|
|
179
182
|
return true
|
|
180
183
|
end
|
|
181
184
|
|
|
182
|
-
def
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
method_type.type_params.zip(yield(method_type)) do |var, vtx|
|
|
188
|
-
param_map0[var] = vtx
|
|
189
|
-
end
|
|
185
|
+
def resolve_overload(changes, genv, method_type, node, param_map, a_args, ret, force)
|
|
186
|
+
param_map0 = param_map.dup
|
|
187
|
+
if method_type.type_params
|
|
188
|
+
method_type.type_params.zip(yield(method_type)) do |var, vtx|
|
|
189
|
+
param_map0[var] = vtx
|
|
190
190
|
end
|
|
191
|
+
end
|
|
191
192
|
|
|
192
|
-
|
|
193
|
+
unless match_arguments?(genv, changes, param_map0, a_args, method_type)
|
|
194
|
+
if force
|
|
195
|
+
meth = node.mid_code_range ? :mid_code_range : :code_range
|
|
196
|
+
changes.add_diagnostic(meth, "wrong type of arguments") # XXX: more friendly and fine-grained error message
|
|
197
|
+
end
|
|
198
|
+
return false
|
|
199
|
+
end
|
|
193
200
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
201
|
+
rbs_blk = method_type.block
|
|
202
|
+
if method_type.block_required && !a_args.block
|
|
203
|
+
if force
|
|
204
|
+
meth = node.mid_code_range ? :mid_code_range : :code_range
|
|
205
|
+
changes.add_diagnostic(meth, "block is expected") # XXX: more friendly error message
|
|
206
|
+
end
|
|
207
|
+
return false
|
|
208
|
+
end
|
|
209
|
+
if !rbs_blk && a_args.block
|
|
210
|
+
if force
|
|
211
|
+
meth = node.mid_code_range ? :mid_code_range : :code_range
|
|
212
|
+
changes.add_diagnostic(meth, "block is not expected") # XXX: more friendly error message
|
|
213
|
+
end
|
|
214
|
+
return false
|
|
215
|
+
end
|
|
216
|
+
if rbs_blk && a_args.block
|
|
217
|
+
# rbs_blk_func.optional_keywords, ...
|
|
218
|
+
blk_a_args = rbs_blk.req_positionals.map do |blk_a_arg|
|
|
219
|
+
blk_a_arg.covariant_vertex(genv, changes, param_map0)
|
|
220
|
+
end
|
|
221
|
+
a_args.block.each_type do |ty|
|
|
222
|
+
case ty
|
|
223
|
+
when Type::Proc
|
|
224
|
+
ty.block.accept_args(genv, changes, blk_a_args)
|
|
225
|
+
|
|
226
|
+
if ty.block.is_a?(Block)
|
|
227
|
+
ty.block.next_boxes.each do |next_box|
|
|
228
|
+
unless rbs_blk.return_type.typecheck(genv, changes, next_box.a_ret, param_map0)
|
|
229
|
+
next_box.wrong_return_type(rbs_blk.return_type.show, changes)
|
|
230
|
+
end
|
|
205
231
|
end
|
|
206
|
-
|
|
207
|
-
ty.block.accept_args(genv, changes, blk_a_args, blk_f_ret, true)
|
|
208
232
|
end
|
|
209
233
|
end
|
|
210
234
|
end
|
|
211
|
-
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
force = true
|
|
238
|
+
return true
|
|
212
239
|
|
|
240
|
+
ensure
|
|
241
|
+
if force
|
|
242
|
+
ret_vtx = method_type.return_type.covariant_vertex(genv, changes, param_map0)
|
|
213
243
|
changes.add_edge(genv, ret_vtx, ret)
|
|
214
|
-
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def resolve_overloads(changes, genv, node, param_map, a_args, ret, &blk)
|
|
248
|
+
if @method_types.size == 1
|
|
249
|
+
method_type = @method_types.first
|
|
250
|
+
resolve_overload(changes, genv, method_type, node, param_map, a_args, ret, true, &blk)
|
|
251
|
+
return
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
match_any_overload = false
|
|
255
|
+
@method_types.each do |method_type|
|
|
256
|
+
if resolve_overload(changes, genv, method_type, node, param_map, a_args, ret, false, &blk)
|
|
257
|
+
match_any_overload = true
|
|
258
|
+
end
|
|
215
259
|
end
|
|
216
260
|
unless match_any_overload
|
|
217
261
|
meth = node.mid_code_range ? :mid_code_range : :code_range
|
|
@@ -252,53 +296,66 @@ module TypeProf::Core
|
|
|
252
296
|
end
|
|
253
297
|
|
|
254
298
|
class EscapeBox < Box
|
|
255
|
-
def initialize(node, genv, a_ret
|
|
299
|
+
def initialize(node, genv, a_ret)
|
|
256
300
|
super(node)
|
|
257
301
|
@a_ret = a_ret.new_vertex(genv, node)
|
|
258
|
-
@f_ret = f_ret
|
|
259
|
-
@f_ret.add_edge(genv, self)
|
|
260
302
|
end
|
|
261
303
|
|
|
262
|
-
attr_reader :a_ret
|
|
304
|
+
attr_reader :a_ret
|
|
263
305
|
|
|
264
306
|
def ret = @a_ret
|
|
265
307
|
|
|
266
308
|
def run0(genv, changes)
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
309
|
+
return
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
def wrong_return_type(f_ret_show, changes)
|
|
313
|
+
actual_ty = @a_ret.show
|
|
314
|
+
return if actual_ty == "untyped" # XXX: too ad-hoc?
|
|
315
|
+
msg = "expected: #{ f_ret_show }; actual: #{ actual_ty }"
|
|
316
|
+
case @node
|
|
317
|
+
when AST::ReturnNode
|
|
318
|
+
changes.add_diagnostic(:code_range, msg, @node)
|
|
319
|
+
when AST::DefNode
|
|
320
|
+
changes.add_diagnostic(:last_stmt_code_range, msg, @node)
|
|
321
|
+
when AST::NextNode
|
|
322
|
+
changes.add_diagnostic(:code_range, msg, @node)
|
|
323
|
+
when AST::CallNode
|
|
324
|
+
changes.add_diagnostic(:block_last_stmt_code_range, msg, @node)
|
|
325
|
+
when AST::AttrReaderMetaNode, AST::AttrAccessorMetaNode
|
|
326
|
+
changes.add_diagnostic(:code_range, msg, @node)
|
|
327
|
+
else
|
|
328
|
+
pp @node.class
|
|
283
329
|
end
|
|
284
330
|
end
|
|
285
331
|
end
|
|
286
332
|
|
|
287
333
|
class SplatBox < Box
|
|
288
|
-
def initialize(node, genv, ary)
|
|
334
|
+
def initialize(node, genv, ary, idx)
|
|
289
335
|
super(node)
|
|
290
336
|
@ary = ary
|
|
337
|
+
@idx = idx
|
|
291
338
|
@ary.add_edge(genv, self)
|
|
292
339
|
@ret = Vertex.new(node)
|
|
293
340
|
end
|
|
294
341
|
|
|
295
|
-
attr_reader :ary, :ret
|
|
342
|
+
attr_reader :ary, :idx, :ret
|
|
296
343
|
|
|
297
344
|
def run0(genv, changes)
|
|
298
345
|
@ary.each_type do |ty|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
346
|
+
case ty
|
|
347
|
+
when Type::Instance
|
|
348
|
+
if ty.mod == genv.mod_ary
|
|
349
|
+
changes.add_edge(genv, ty.args[0], @ret)
|
|
350
|
+
else
|
|
351
|
+
"???"
|
|
352
|
+
end
|
|
353
|
+
when Type::Array
|
|
354
|
+
if @idx && @idx < ty.elems.size
|
|
355
|
+
changes.add_edge(genv, ty.elems[@idx], @ret)
|
|
356
|
+
else
|
|
357
|
+
changes.add_edge(genv, ty.get_elem(genv, @idx), @ret)
|
|
358
|
+
end
|
|
302
359
|
else
|
|
303
360
|
"???"
|
|
304
361
|
end
|
|
@@ -323,8 +380,8 @@ module TypeProf::Core
|
|
|
323
380
|
@hsh.each_type do |ty|
|
|
324
381
|
ty = ty.base_type(genv)
|
|
325
382
|
if ty.mod == genv.mod_hash
|
|
326
|
-
changes.add_edge(genv, ty.args[0], @unified_key)
|
|
327
|
-
changes.add_edge(genv, ty.args[1], @unified_val)
|
|
383
|
+
changes.add_edge(genv, ty.args[0].new_vertex(genv, :__hash_splat), @unified_key)
|
|
384
|
+
changes.add_edge(genv, ty.args[1].new_vertex(genv, :__hash_splat), @unified_val)
|
|
328
385
|
else
|
|
329
386
|
"???"
|
|
330
387
|
end
|
|
@@ -355,11 +412,8 @@ module TypeProf::Core
|
|
|
355
412
|
end
|
|
356
413
|
me = genv.resolve_method(@cpath, @singleton, @mid)
|
|
357
414
|
me.add_def(self)
|
|
358
|
-
if me.decls.empty?
|
|
359
|
-
|
|
360
|
-
else
|
|
361
|
-
genv.add_run(self)
|
|
362
|
-
end
|
|
415
|
+
me.add_run_all_method_call_boxes(genv) if me.decls.empty?
|
|
416
|
+
genv.add_run(self)
|
|
363
417
|
end
|
|
364
418
|
|
|
365
419
|
attr_accessor :node
|
|
@@ -369,11 +423,8 @@ module TypeProf::Core
|
|
|
369
423
|
def destroy(genv)
|
|
370
424
|
me = genv.resolve_method(@cpath, @singleton, @mid)
|
|
371
425
|
me.remove_def(self)
|
|
372
|
-
if me.decls.empty?
|
|
373
|
-
|
|
374
|
-
else
|
|
375
|
-
genv.add_run(self)
|
|
376
|
-
end
|
|
426
|
+
me.add_run_all_method_call_boxes(genv) if me.decls.empty?
|
|
427
|
+
genv.add_run(self)
|
|
377
428
|
super(genv)
|
|
378
429
|
end
|
|
379
430
|
|
|
@@ -430,8 +481,11 @@ module TypeProf::Core
|
|
|
430
481
|
if pass_arguments(changes, genv, a_args)
|
|
431
482
|
# TODO: block
|
|
432
483
|
f_ret = method_type.return_type.contravariant_vertex(genv, changes, param_map0)
|
|
484
|
+
changes.add_edge(genv, f_ret, @ret)
|
|
433
485
|
@ret_boxes.each do |ret_box|
|
|
434
|
-
|
|
486
|
+
unless method_type.return_type.typecheck(genv, changes, ret_box.a_ret, param_map0)
|
|
487
|
+
ret_box.wrong_return_type(method_type.return_type.show, changes)
|
|
488
|
+
end
|
|
435
489
|
end
|
|
436
490
|
end
|
|
437
491
|
end
|
|
@@ -451,7 +505,7 @@ module TypeProf::Core
|
|
|
451
505
|
|
|
452
506
|
start_rest = [a_args.splat_flags.index(true), @f_args.req_positionals.size + @f_args.opt_positionals.size].min
|
|
453
507
|
end_rest = [a_args.splat_flags.rindex(true) + 1, a_args.positionals.size - @f_args.post_positionals.size].max
|
|
454
|
-
rest_vtxs = a_args.get_rest_args(genv, start_rest, end_rest)
|
|
508
|
+
rest_vtxs = a_args.get_rest_args(genv, changes, start_rest, end_rest)
|
|
455
509
|
|
|
456
510
|
@f_args.req_positionals.each_with_index do |f_vtx, i|
|
|
457
511
|
if i < start_rest
|
|
@@ -590,7 +644,7 @@ module TypeProf::Core
|
|
|
590
644
|
end
|
|
591
645
|
end
|
|
592
646
|
if @f_args.rest_keywords
|
|
593
|
-
args << "**#{ Type.strip_parens(@f_args.rest_keywords.show) }"
|
|
647
|
+
args << "**#{ Type.extract_hash_value_type(Type.strip_parens(@f_args.rest_keywords.show)) }"
|
|
594
648
|
end
|
|
595
649
|
|
|
596
650
|
if output_parameter_names && @node.is_a?(AST::DefNode)
|
|
@@ -610,7 +664,7 @@ module TypeProf::Core
|
|
|
610
664
|
args = args.join(", ")
|
|
611
665
|
s = args.empty? ? [] : ["(#{ args })"]
|
|
612
666
|
s << "#{ block_show.sort.join(" | ") }" unless block_show.empty?
|
|
613
|
-
s << "-> #{ @ret.show }"
|
|
667
|
+
s << "-> #{ @mid == :initialize ? "void" : @ret.show }"
|
|
614
668
|
s.join(" ")
|
|
615
669
|
end
|
|
616
670
|
end
|
|
@@ -626,11 +680,8 @@ module TypeProf::Core
|
|
|
626
680
|
|
|
627
681
|
me = genv.resolve_method(@cpath, @singleton, @new_mid)
|
|
628
682
|
me.add_alias(self, @old_mid)
|
|
629
|
-
if me.decls.empty?
|
|
630
|
-
|
|
631
|
-
else
|
|
632
|
-
genv.add_run(self)
|
|
633
|
-
end
|
|
683
|
+
me.add_run_all_method_call_boxes(genv) if me.decls.empty?
|
|
684
|
+
genv.add_run(self)
|
|
634
685
|
end
|
|
635
686
|
|
|
636
687
|
attr_accessor :node
|
|
@@ -640,11 +691,8 @@ module TypeProf::Core
|
|
|
640
691
|
def destroy(genv)
|
|
641
692
|
me = genv.resolve_method(@cpath, @singleton, @new_mid)
|
|
642
693
|
me.remove_alias(self)
|
|
643
|
-
if me.decls.empty?
|
|
644
|
-
|
|
645
|
-
else
|
|
646
|
-
genv.add_run(self)
|
|
647
|
-
end
|
|
694
|
+
me.add_run_all_method_call_boxes(genv) if me.decls.empty?
|
|
695
|
+
genv.add_run(self)
|
|
648
696
|
super(genv)
|
|
649
697
|
end
|
|
650
698
|
|
|
@@ -661,7 +709,6 @@ module TypeProf::Core
|
|
|
661
709
|
@recv.add_edge(genv, self)
|
|
662
710
|
@mid = mid
|
|
663
711
|
@a_args = a_args.new_vertexes(genv, node)
|
|
664
|
-
@a_args.positionals.each {|arg| arg.add_edge(genv, self) }
|
|
665
712
|
@a_args.keywords.add_edge(genv, self) if @a_args.keywords
|
|
666
713
|
@a_args.block.add_edge(genv, self) if @a_args.block
|
|
667
714
|
@ret = Vertex.new(node)
|
|
@@ -749,6 +796,16 @@ module TypeProf::Core
|
|
|
749
796
|
alias_limit = 0
|
|
750
797
|
while ty
|
|
751
798
|
unless skip
|
|
799
|
+
# First check prepended modules
|
|
800
|
+
if !ty.is_a?(Type::Singleton)
|
|
801
|
+
if resolve_prepended_modules(genv, changes, base_ty_env, ty, mid) do |me, ty, mid|
|
|
802
|
+
yield me, ty, mid, orig_ty
|
|
803
|
+
end
|
|
804
|
+
break
|
|
805
|
+
end
|
|
806
|
+
end
|
|
807
|
+
|
|
808
|
+
# Then check the class/module itself
|
|
752
809
|
me = ty.mod.get_method(ty.is_a?(Type::Singleton), mid)
|
|
753
810
|
changes.add_depended_method_entity(me) if changes
|
|
754
811
|
if !me.aliases.empty?
|
|
@@ -767,6 +824,7 @@ module TypeProf::Core
|
|
|
767
824
|
if ty.is_a?(Type::Singleton)
|
|
768
825
|
# TODO: extended modules
|
|
769
826
|
else
|
|
827
|
+
# Finally check included modules
|
|
770
828
|
break if resolve_included_modules(genv, changes, base_ty_env, ty, mid) do |me, ty, mid|
|
|
771
829
|
yield me, ty, mid, orig_ty
|
|
772
830
|
end
|
|
@@ -779,6 +837,38 @@ module TypeProf::Core
|
|
|
779
837
|
end
|
|
780
838
|
end
|
|
781
839
|
|
|
840
|
+
def resolve_prepended_modules(genv, changes, base_ty_env, ty, mid, &blk)
|
|
841
|
+
found = false
|
|
842
|
+
|
|
843
|
+
alias_limit = 0
|
|
844
|
+
# Process prepended modules in reverse order (last prepended = first in ancestor chain)
|
|
845
|
+
ty.mod.prepended_modules.reverse_each do |prep_decl, prep_mod|
|
|
846
|
+
if prep_decl.is_a?(AST::SigPrependNode) && prep_mod.type_params
|
|
847
|
+
prep_ty = genv.get_instance_type(prep_mod, prep_decl.args, changes, base_ty_env, ty)
|
|
848
|
+
else
|
|
849
|
+
type_params = prep_mod.type_params.map {|ty_param| Source.new() } # TODO: better support
|
|
850
|
+
prep_ty = Type::Instance.new(genv, prep_mod, type_params)
|
|
851
|
+
end
|
|
852
|
+
|
|
853
|
+
me = prep_ty.mod.get_method(false, mid)
|
|
854
|
+
changes.add_depended_method_entity(me) if changes
|
|
855
|
+
if !me.aliases.empty?
|
|
856
|
+
mid = me.aliases.values.first
|
|
857
|
+
alias_limit += 1
|
|
858
|
+
redo if alias_limit < 5
|
|
859
|
+
end
|
|
860
|
+
if me.exist?
|
|
861
|
+
found = true
|
|
862
|
+
yield me, prep_ty, mid
|
|
863
|
+
else
|
|
864
|
+
found = resolve_prepended_modules(genv, changes, base_ty_env, prep_ty, mid, &blk)
|
|
865
|
+
end
|
|
866
|
+
break if found
|
|
867
|
+
end
|
|
868
|
+
|
|
869
|
+
found
|
|
870
|
+
end
|
|
871
|
+
|
|
782
872
|
def resolve_included_modules(genv, changes, base_ty_env, ty, mid, &blk)
|
|
783
873
|
found = false
|
|
784
874
|
|
|
@@ -995,4 +1085,24 @@ module TypeProf::Core
|
|
|
995
1085
|
end
|
|
996
1086
|
end
|
|
997
1087
|
end
|
|
1088
|
+
|
|
1089
|
+
class InstanceTypeBox < Box
|
|
1090
|
+
def initialize(node, genv, singleton_ty_vtx)
|
|
1091
|
+
super(node)
|
|
1092
|
+
@singleton_ty_vtx = singleton_ty_vtx
|
|
1093
|
+
@ret = Vertex.new(node)
|
|
1094
|
+
genv.add_run(self)
|
|
1095
|
+
end
|
|
1096
|
+
|
|
1097
|
+
attr_reader :ret
|
|
1098
|
+
|
|
1099
|
+
def run0(genv, changes)
|
|
1100
|
+
instance_tys = []
|
|
1101
|
+
@singleton_ty_vtx.each_type do |ty|
|
|
1102
|
+
instance_tys << ty.get_instance_type(genv)
|
|
1103
|
+
end
|
|
1104
|
+
source_vtx = Source.new(*instance_tys)
|
|
1105
|
+
changes.add_edge(genv, source_vtx, @ret)
|
|
1106
|
+
end
|
|
1107
|
+
end
|
|
998
1108
|
end
|
|
@@ -3,6 +3,7 @@ module TypeProf::Core
|
|
|
3
3
|
def initialize(node, target)
|
|
4
4
|
@node = node
|
|
5
5
|
@target = target
|
|
6
|
+
@new_vertexes = {}
|
|
6
7
|
@covariant_types = {}
|
|
7
8
|
@contravariant_types = {}
|
|
8
9
|
@edges = []
|
|
@@ -21,30 +22,35 @@ module TypeProf::Core
|
|
|
21
22
|
@new_depended_superclasses = []
|
|
22
23
|
end
|
|
23
24
|
|
|
24
|
-
attr_reader :node, :covariant_types, :edges, :boxes, :diagnostics
|
|
25
|
+
attr_reader :node, :target, :covariant_types, :contravariant_types, :edges, :boxes, :diagnostics
|
|
25
26
|
|
|
26
27
|
def reuse(new_node)
|
|
27
28
|
@node = new_node
|
|
28
29
|
@boxes.each_value do |box|
|
|
29
30
|
box.reuse(new_node)
|
|
30
31
|
end
|
|
31
|
-
@diagnostics.each do |diag|
|
|
32
|
-
diag.reuse(new_node)
|
|
33
|
-
end
|
|
34
32
|
end
|
|
35
33
|
|
|
36
34
|
def copy_from(other)
|
|
37
35
|
@covariant_types = other.covariant_types.dup
|
|
36
|
+
@contravariant_types = other.contravariant_types.dup
|
|
38
37
|
@edges = other.edges.dup
|
|
39
38
|
@boxes = other.boxes.dup
|
|
40
39
|
@diagnostics = other.diagnostics.dup
|
|
41
40
|
|
|
42
41
|
other.covariant_types.clear
|
|
42
|
+
other.contravariant_types.clear
|
|
43
43
|
other.edges.clear
|
|
44
44
|
other.boxes.clear
|
|
45
45
|
other.diagnostics.clear
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
+
def new_vertex(genv, origin, base_vtx)
|
|
49
|
+
new_vtx = @new_vertexes[base_vtx] ||= Vertex.new(origin)
|
|
50
|
+
add_edge(genv, base_vtx, new_vtx)
|
|
51
|
+
new_vtx
|
|
52
|
+
end
|
|
53
|
+
|
|
48
54
|
def new_covariant_vertex(genv, sig_type_node)
|
|
49
55
|
# This is used to avoid duplicated vertex generation for the same sig node
|
|
50
56
|
@covariant_types[sig_type_node] ||= Vertex.new(sig_type_node)
|
|
@@ -56,8 +62,6 @@ module TypeProf::Core
|
|
|
56
62
|
end
|
|
57
63
|
|
|
58
64
|
def add_edge(genv, src, dst)
|
|
59
|
-
raise src.class.to_s unless src.is_a?(BasicVertex)
|
|
60
|
-
src.add_edge(genv, dst) if !@edges.include?([src, dst]) && !@new_edges.include?([src, dst])
|
|
61
65
|
@new_edges << [src, dst]
|
|
62
66
|
end
|
|
63
67
|
|
|
@@ -65,84 +69,76 @@ module TypeProf::Core
|
|
|
65
69
|
|
|
66
70
|
def add_method_call_box(genv, recv, mid, a_args, subclasses)
|
|
67
71
|
key = [:mcall, recv, mid, a_args, subclasses]
|
|
68
|
-
|
|
69
|
-
@new_boxes[key] = MethodCallBox.new(@node, genv, recv, mid, a_args, subclasses)
|
|
72
|
+
@new_boxes[key] ||= MethodCallBox.new(@node, genv, recv, mid, a_args, subclasses)
|
|
70
73
|
end
|
|
71
74
|
|
|
72
|
-
def add_escape_box(genv, a_ret
|
|
75
|
+
def add_escape_box(genv, a_ret)
|
|
73
76
|
key = [:return, a_ret]
|
|
74
|
-
|
|
75
|
-
@new_boxes[key] = EscapeBox.new(@node, genv, a_ret, f_ret)
|
|
77
|
+
@new_boxes[key] ||= EscapeBox.new(@node, genv, a_ret)
|
|
76
78
|
end
|
|
77
79
|
|
|
78
|
-
def add_splat_box(genv, arg)
|
|
79
|
-
key = [:splat, arg]
|
|
80
|
-
|
|
81
|
-
@new_boxes[key] = SplatBox.new(@node, genv, arg)
|
|
80
|
+
def add_splat_box(genv, arg, idx = nil)
|
|
81
|
+
key = [:splat, arg, idx]
|
|
82
|
+
@new_boxes[key] ||= SplatBox.new(@node, genv, arg, idx)
|
|
82
83
|
end
|
|
83
84
|
|
|
84
85
|
def add_hash_splat_box(genv, arg, unified_key, unified_val)
|
|
85
86
|
key = [:hash_splat, arg, unified_key, unified_val]
|
|
86
|
-
|
|
87
|
-
@new_boxes[key] = HashSplatBox.new(@node, genv, arg, unified_key, unified_val)
|
|
87
|
+
@new_boxes[key] ||= HashSplatBox.new(@node, genv, arg, unified_key, unified_val)
|
|
88
88
|
end
|
|
89
89
|
|
|
90
90
|
def add_masgn_box(genv, value, lefts, rest_elem, rights)
|
|
91
91
|
key = [:masgn, value, lefts, rest_elem, rights]
|
|
92
|
-
|
|
93
|
-
@new_boxes[key] = MAsgnBox.new(@node, genv, value, lefts, rest_elem, rights)
|
|
92
|
+
@new_boxes[key] ||= MAsgnBox.new(@node, genv, value, lefts, rest_elem, rights)
|
|
94
93
|
end
|
|
95
94
|
|
|
96
95
|
def add_method_def_box(genv, cpath, singleton, mid, f_args, ret_boxes)
|
|
97
96
|
key = [:mdef, cpath, singleton, mid, f_args, ret_boxes]
|
|
98
|
-
|
|
99
|
-
@new_boxes[key] = MethodDefBox.new(@node, genv, cpath, singleton, mid, f_args, ret_boxes)
|
|
97
|
+
@new_boxes[key] ||= MethodDefBox.new(@node, genv, cpath, singleton, mid, f_args, ret_boxes)
|
|
100
98
|
end
|
|
101
99
|
|
|
102
100
|
def add_method_decl_box(genv, cpath, singleton, mid, method_types, overloading)
|
|
103
101
|
key = [:mdecl, cpath, singleton, mid, method_types, overloading]
|
|
104
|
-
|
|
105
|
-
@new_boxes[key] = MethodDeclBox.new(@node, genv, cpath, singleton, mid, method_types, overloading)
|
|
102
|
+
@new_boxes[key] ||= MethodDeclBox.new(@node, genv, cpath, singleton, mid, method_types, overloading)
|
|
106
103
|
end
|
|
107
104
|
|
|
108
105
|
def add_method_alias_box(genv, cpath, singleton, new_mid, old_mid)
|
|
109
106
|
key = [:mdecl, cpath, singleton, new_mid, old_mid]
|
|
110
|
-
|
|
111
|
-
@new_boxes[key] = MethodAliasBox.new(@node, genv, cpath, singleton, new_mid, old_mid)
|
|
107
|
+
@new_boxes[key] ||= MethodAliasBox.new(@node, genv, cpath, singleton, new_mid, old_mid)
|
|
112
108
|
end
|
|
113
109
|
|
|
114
110
|
def add_const_read_box(genv, static_ret)
|
|
115
111
|
key = [:cread, static_ret]
|
|
116
|
-
|
|
117
|
-
@new_boxes[key] = ConstReadBox.new(@node, genv, static_ret)
|
|
112
|
+
@new_boxes[key] ||= ConstReadBox.new(@node, genv, static_ret)
|
|
118
113
|
end
|
|
119
114
|
|
|
120
115
|
def add_gvar_read_box(genv, var)
|
|
121
116
|
key = [:gvar_read, var]
|
|
122
|
-
|
|
123
|
-
@new_boxes[key] = GVarReadBox.new(@node, genv, var)
|
|
117
|
+
@new_boxes[key] ||= GVarReadBox.new(@node, genv, var)
|
|
124
118
|
end
|
|
125
119
|
|
|
126
120
|
def add_ivar_read_box(genv, cpath, singleton, name)
|
|
127
121
|
key = [:ivar_read, cpath, singleton, name]
|
|
128
|
-
|
|
129
|
-
@new_boxes[key] = IVarReadBox.new(@node, genv, cpath, singleton, name)
|
|
122
|
+
@new_boxes[key] ||= IVarReadBox.new(@node, genv, cpath, singleton, name)
|
|
130
123
|
end
|
|
131
124
|
|
|
132
125
|
def add_cvar_read_box(genv, cpath, name)
|
|
133
126
|
key = [:cvar_read, cpath, name]
|
|
134
|
-
|
|
135
|
-
@new_boxes[key] = CVarReadBox.new(@node, genv, cpath, name)
|
|
127
|
+
@new_boxes[key] ||= CVarReadBox.new(@node, genv, cpath, name)
|
|
136
128
|
end
|
|
137
129
|
|
|
138
130
|
def add_type_read_box(genv, type)
|
|
139
131
|
key = [:type_read, type]
|
|
140
|
-
|
|
141
|
-
|
|
132
|
+
@new_boxes[key] ||= TypeReadBox.new(@node, genv, type)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def add_instance_type_box(genv, singleton_ty_vtx)
|
|
136
|
+
key = [:instance_type, singleton_ty_vtx]
|
|
137
|
+
@new_boxes[key] ||= InstanceTypeBox.new(@node, genv, singleton_ty_vtx)
|
|
142
138
|
end
|
|
143
139
|
|
|
144
|
-
def add_diagnostic(meth, msg)
|
|
145
|
-
@new_diagnostics << TypeProf::Diagnostic.new(
|
|
140
|
+
def add_diagnostic(meth, msg, node = @node)
|
|
141
|
+
@new_diagnostics << TypeProf::Diagnostic.new(node, meth, msg)
|
|
146
142
|
end
|
|
147
143
|
|
|
148
144
|
def add_depended_value_entity(ve)
|
|
@@ -163,6 +159,9 @@ module TypeProf::Core
|
|
|
163
159
|
|
|
164
160
|
def reinstall(genv)
|
|
165
161
|
@new_edges.uniq!
|
|
162
|
+
@new_edges.each do |src, dst|
|
|
163
|
+
src.add_edge(genv, dst) unless @edges.include?([src, dst])
|
|
164
|
+
end
|
|
166
165
|
@edges.each do |src, dst|
|
|
167
166
|
src.remove_edge(genv, dst) unless @new_edges.include?([src, dst])
|
|
168
167
|
end
|
|
@@ -175,6 +174,14 @@ module TypeProf::Core
|
|
|
175
174
|
@boxes, @new_boxes = @new_boxes, @boxes
|
|
176
175
|
@new_boxes.clear
|
|
177
176
|
|
|
177
|
+
@diagnostics.each do |diag|
|
|
178
|
+
genv.add_diagnostic_path(diag.node.lenv.path)
|
|
179
|
+
diag.node.remove_diagnostic(diag)
|
|
180
|
+
end
|
|
181
|
+
@new_diagnostics.each do |diag|
|
|
182
|
+
genv.add_diagnostic_path(diag.node.lenv.path)
|
|
183
|
+
diag.node.add_diagnostic(diag)
|
|
184
|
+
end
|
|
178
185
|
@diagnostics, @new_diagnostics = @new_diagnostics, @diagnostics
|
|
179
186
|
@new_diagnostics.clear
|
|
180
187
|
|