typeprof 0.30.0 → 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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +23 -4
  3. data/doc/doc.ja.md +1 -1
  4. data/lib/typeprof/cli/cli.rb +28 -10
  5. data/lib/typeprof/cli.rb +1 -0
  6. data/lib/typeprof/code_range.rb +9 -7
  7. data/lib/typeprof/core/ast/base.rb +27 -10
  8. data/lib/typeprof/core/ast/call.rb +90 -21
  9. data/lib/typeprof/core/ast/const.rb +7 -12
  10. data/lib/typeprof/core/ast/control.rb +349 -74
  11. data/lib/typeprof/core/ast/meta.rb +5 -5
  12. data/lib/typeprof/core/ast/method.rb +19 -5
  13. data/lib/typeprof/core/ast/misc.rb +21 -2
  14. data/lib/typeprof/core/ast/module.rb +10 -7
  15. data/lib/typeprof/core/ast/pattern.rb +9 -1
  16. data/lib/typeprof/core/ast/sig_decl.rb +163 -42
  17. data/lib/typeprof/core/ast/sig_type.rb +394 -24
  18. data/lib/typeprof/core/ast/value.rb +11 -3
  19. data/lib/typeprof/core/ast/variable.rb +32 -2
  20. data/lib/typeprof/core/ast.rb +15 -4
  21. data/lib/typeprof/core/builtin.rb +15 -9
  22. data/lib/typeprof/core/env/method.rb +21 -16
  23. data/lib/typeprof/core/env/method_entity.rb +11 -2
  24. data/lib/typeprof/core/env/module_entity.rb +57 -0
  25. data/lib/typeprof/core/env/narrowing.rb +131 -0
  26. data/lib/typeprof/core/env/static_read.rb +9 -8
  27. data/lib/typeprof/core/env.rb +43 -12
  28. data/lib/typeprof/core/graph/box.rb +218 -101
  29. data/lib/typeprof/core/graph/change_set.rb +44 -37
  30. data/lib/typeprof/core/graph/vertex.rb +7 -21
  31. data/lib/typeprof/core/service.rb +61 -40
  32. data/lib/typeprof/core/type.rb +52 -123
  33. data/lib/typeprof/core.rb +1 -1
  34. data/lib/typeprof/diagnostic.rb +5 -6
  35. data/lib/typeprof/lsp/messages.rb +27 -36
  36. data/lib/typeprof/lsp/server.rb +144 -25
  37. data/lib/typeprof/lsp/text.rb +1 -0
  38. data/lib/typeprof/lsp/util.rb +0 -10
  39. data/lib/typeprof/version.rb +1 -1
  40. data/typeprof.conf.jsonc +22 -0
  41. data/typeprof.gemspec +1 -0
  42. metadata +19 -5
  43. data/lib/typeprof/core/graph.rb +0 -3
@@ -39,18 +39,12 @@ module TypeProf::Core
39
39
  @changes.reinstall(genv)
40
40
  end
41
41
 
42
- def diagnostics(genv, &blk)
43
- raise self.to_s if !@changes
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[0] }#{ @id ||= $new_id += 1 }"
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
- vtx = @rbs_type.covariant_vertex(genv, changes, {})
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
- f_arg = ty.contravariant_vertex(genv, changes, param_map)
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].check_match(genv, changes, f_arg)
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
- f_arg = method_type.opt_positionals[i].contravariant_vertex(genv, changes, param_map)
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
- f_arg = method_type.opt_positionals[i].contravariant_vertex(genv, changes, param_map)
170
- return false if vtxs.any? {|vtx| !vtx.check_match(genv, changes, f_arg) }
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
- f_arg = method_type.rest_positionals.contravariant_vertex(genv, changes, param_map)
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 resolve_overloads(changes, genv, node, param_map, a_args, ret)
183
- match_any_overload = false
184
- @method_types.each do |method_type|
185
- param_map0 = param_map.dup
186
- if method_type.type_params
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
- next unless match_arguments?(genv, changes, param_map0, a_args, method_type)
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
- rbs_blk = method_type.block
195
- next if method_type.block_required && !a_args.block
196
- next if !rbs_blk && a_args.block
197
- if rbs_blk && a_args.block
198
- # rbs_blk_func.optional_keywords, ...
199
- a_args.block.each_type do |ty|
200
- case ty
201
- when Type::Proc
202
- blk_f_ret = rbs_blk.return_type.contravariant_vertex(genv, changes, param_map0)
203
- blk_a_args = rbs_blk.req_positionals.map do |blk_a_arg|
204
- blk_a_arg.covariant_vertex(genv, changes, param_map0)
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
- ret_vtx = method_type.return_type.covariant_vertex(genv, changes, param_map0)
235
+ end
212
236
 
237
+ force = true
238
+ return true
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
- match_any_overload = true
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, f_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, :f_ret
304
+ attr_reader :a_ret
263
305
 
264
306
  def ret = @a_ret
265
307
 
266
308
  def run0(genv, changes)
267
- unless @a_ret.check_match(genv, changes, @f_ret)
268
- msg = "expected: #{ @f_ret.show }; actual: #{ @a_ret.show }"
269
- case @node
270
- when AST::ReturnNode
271
- changes.add_diagnostic(:code_range, msg)
272
- when AST::DefNode
273
- changes.add_diagnostic(:last_stmt_code_range, msg)
274
- when AST::NextNode
275
- changes.add_diagnostic(:code_range, msg)
276
- when AST::CallNode
277
- changes.add_diagnostic(:block_last_stmt_code_range, msg)
278
- when AST::AttrReaderMetaNode, AST::AttrAccessorMetaNode
279
- changes.add_diagnostic(:code_range, msg)
280
- else
281
- pp @node.class
282
- end
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
- ty = ty.base_type(genv)
300
- if ty.mod == genv.mod_ary
301
- changes.add_edge(genv, ty.args[0], @ret)
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
- me.add_run_all_method_call_boxes(genv)
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
- me.add_run_all_method_call_boxes(genv)
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
- changes.add_edge(genv, f_ret, ret_box.f_ret)
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
@@ -485,7 +539,11 @@ module TypeProf::Core
485
539
 
486
540
  if @f_args.rest_positionals
487
541
  rest_vtxs.each do |vtx|
488
- changes.add_edge(genv, vtx, @f_args.rest_positionals)
542
+ @f_args.rest_positionals.each_type do |ty|
543
+ if ty.is_a?(Type::Instance) && ty.mod == genv.mod_ary && ty.args[0]
544
+ changes.add_edge(genv, vtx, ty.args[0])
545
+ end
546
+ end
489
547
  end
490
548
  end
491
549
  else
@@ -519,9 +577,12 @@ module TypeProf::Core
519
577
 
520
578
  if start_rest < end_rest
521
579
  if @f_args.rest_positionals
522
- f_arg = @f_args.rest_positionals
523
580
  (start_rest..end_rest-1).each do |i|
524
- changes.add_edge(genv, a_args.positionals[i], f_arg)
581
+ @f_args.rest_positionals.each_type do |ty|
582
+ if ty.is_a?(Type::Instance) && ty.mod == genv.mod_ary && ty.args[0]
583
+ changes.add_edge(genv, a_args.positionals[i], ty.args[0])
584
+ end
585
+ end
525
586
  end
526
587
  end
527
588
  end
@@ -569,7 +630,7 @@ module TypeProf::Core
569
630
  args << ("?" + Type.strip_parens(f_vtx.show))
570
631
  end
571
632
  if @f_args.rest_positionals
572
- args << ("*" + Type.strip_parens(@f_args.rest_positionals.show))
633
+ args << ("*" + Type.strip_array(Type.strip_parens(@f_args.rest_positionals.show)))
573
634
  end
574
635
  @f_args.post_positionals.each do |var|
575
636
  args << Type.strip_parens(var.show)
@@ -583,7 +644,7 @@ module TypeProf::Core
583
644
  end
584
645
  end
585
646
  if @f_args.rest_keywords
586
- args << "**#{ Type.strip_parens(@f_args.rest_keywords.show) }"
647
+ args << "**#{ Type.extract_hash_value_type(Type.strip_parens(@f_args.rest_keywords.show)) }"
587
648
  end
588
649
 
589
650
  if output_parameter_names && @node.is_a?(AST::DefNode)
@@ -603,7 +664,7 @@ module TypeProf::Core
603
664
  args = args.join(", ")
604
665
  s = args.empty? ? [] : ["(#{ args })"]
605
666
  s << "#{ block_show.sort.join(" | ") }" unless block_show.empty?
606
- s << "-> #{ @ret.show }"
667
+ s << "-> #{ @mid == :initialize ? "void" : @ret.show }"
607
668
  s.join(" ")
608
669
  end
609
670
  end
@@ -619,11 +680,8 @@ module TypeProf::Core
619
680
 
620
681
  me = genv.resolve_method(@cpath, @singleton, @new_mid)
621
682
  me.add_alias(self, @old_mid)
622
- if me.decls.empty?
623
- me.add_run_all_method_call_boxes(genv)
624
- else
625
- genv.add_run(self)
626
- end
683
+ me.add_run_all_method_call_boxes(genv) if me.decls.empty?
684
+ genv.add_run(self)
627
685
  end
628
686
 
629
687
  attr_accessor :node
@@ -633,11 +691,8 @@ module TypeProf::Core
633
691
  def destroy(genv)
634
692
  me = genv.resolve_method(@cpath, @singleton, @new_mid)
635
693
  me.remove_alias(self)
636
- if me.decls.empty?
637
- me.add_run_all_method_call_boxes(genv)
638
- else
639
- genv.add_run(self)
640
- end
694
+ me.add_run_all_method_call_boxes(genv) if me.decls.empty?
695
+ genv.add_run(self)
641
696
  super(genv)
642
697
  end
643
698
 
@@ -654,7 +709,6 @@ module TypeProf::Core
654
709
  @recv.add_edge(genv, self)
655
710
  @mid = mid
656
711
  @a_args = a_args.new_vertexes(genv, node)
657
- @a_args.positionals.each {|arg| arg.add_edge(genv, self) }
658
712
  @a_args.keywords.add_edge(genv, self) if @a_args.keywords
659
713
  @a_args.block.add_edge(genv, self) if @a_args.block
660
714
  @ret = Vertex.new(node)
@@ -742,6 +796,16 @@ module TypeProf::Core
742
796
  alias_limit = 0
743
797
  while ty
744
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
745
809
  me = ty.mod.get_method(ty.is_a?(Type::Singleton), mid)
746
810
  changes.add_depended_method_entity(me) if changes
747
811
  if !me.aliases.empty?
@@ -760,6 +824,7 @@ module TypeProf::Core
760
824
  if ty.is_a?(Type::Singleton)
761
825
  # TODO: extended modules
762
826
  else
827
+ # Finally check included modules
763
828
  break if resolve_included_modules(genv, changes, base_ty_env, ty, mid) do |me, ty, mid|
764
829
  yield me, ty, mid, orig_ty
765
830
  end
@@ -772,6 +837,38 @@ module TypeProf::Core
772
837
  end
773
838
  end
774
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
+
775
872
  def resolve_included_modules(genv, changes, base_ty_env, ty, mid, &blk)
776
873
  found = false
777
874
 
@@ -988,4 +1085,24 @@ module TypeProf::Core
988
1085
  end
989
1086
  end
990
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
991
1108
  end