typeprof 0.3.0 → 0.4.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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/doc/demo.md +398 -0
  4. data/doc/doc.ja.md +4 -0
  5. data/doc/doc.md +4 -0
  6. data/lib/typeprof.rb +8 -0
  7. data/lib/typeprof/analyzer.rb +229 -245
  8. data/lib/typeprof/arguments.rb +397 -0
  9. data/lib/typeprof/block.rb +133 -0
  10. data/lib/typeprof/builtin.rb +14 -10
  11. data/lib/typeprof/container-type.rb +94 -17
  12. data/lib/typeprof/export.rb +185 -108
  13. data/lib/typeprof/import.rb +76 -54
  14. data/lib/typeprof/iseq.rb +27 -2
  15. data/lib/typeprof/method.rb +87 -73
  16. data/lib/typeprof/type.rb +125 -309
  17. data/lib/typeprof/version.rb +1 -1
  18. data/smoke/arguments2.rb +1 -1
  19. data/smoke/array-each3.rb +1 -4
  20. data/smoke/array12.rb +1 -1
  21. data/smoke/array6.rb +1 -0
  22. data/smoke/block-ambiguous.rb +36 -0
  23. data/smoke/block-args1-rest.rb +62 -0
  24. data/smoke/block-args1.rb +59 -0
  25. data/smoke/block-args2-rest.rb +62 -0
  26. data/smoke/block-args2.rb +59 -0
  27. data/smoke/block-args3-rest.rb +73 -0
  28. data/smoke/block-args3.rb +70 -0
  29. data/smoke/block-blockarg.rb +27 -0
  30. data/smoke/block-kwarg.rb +52 -0
  31. data/smoke/block11.rb +1 -1
  32. data/smoke/block14.rb +17 -0
  33. data/smoke/block4.rb +2 -2
  34. data/smoke/block5.rb +1 -0
  35. data/smoke/block6.rb +1 -1
  36. data/smoke/block7.rb +0 -2
  37. data/smoke/block8.rb +2 -2
  38. data/smoke/block9.rb +1 -1
  39. data/smoke/blown.rb +1 -1
  40. data/smoke/class-hierarchy.rb +54 -0
  41. data/smoke/class-hierarchy2.rb +27 -0
  42. data/smoke/constant1.rb +11 -6
  43. data/smoke/constant2.rb +2 -0
  44. data/smoke/cvar.rb +1 -0
  45. data/smoke/demo10.rb +1 -1
  46. data/smoke/demo8.rb +2 -2
  47. data/smoke/demo9.rb +1 -3
  48. data/smoke/flow7.rb +1 -7
  49. data/smoke/flow8.rb +13 -0
  50. data/smoke/instance_eval.rb +1 -1
  51. data/smoke/int_times.rb +1 -1
  52. data/smoke/multiple-superclass.rb +4 -0
  53. data/smoke/next2.rb +1 -1
  54. data/smoke/optional3.rb +10 -0
  55. data/smoke/proc4.rb +1 -1
  56. data/smoke/rbs-proc1.rb +9 -0
  57. data/smoke/rbs-proc1.rbs +3 -0
  58. data/smoke/rbs-proc2.rb +20 -0
  59. data/smoke/rbs-proc2.rbs +3 -0
  60. data/smoke/rbs-proc3.rb +13 -0
  61. data/smoke/rbs-proc3.rbs +4 -0
  62. data/smoke/rbs-record.rb +17 -0
  63. data/smoke/rbs-record.rbs +4 -0
  64. data/smoke/rbs-tyvar3.rb +25 -0
  65. data/smoke/rbs-tyvar3.rbs +4 -0
  66. data/smoke/rest2.rb +1 -1
  67. data/smoke/rest5.rb +1 -1
  68. data/smoke/return.rb +1 -1
  69. data/smoke/singleton_method.rb +3 -0
  70. data/smoke/struct.rb +4 -3
  71. data/smoke/struct3.rb +14 -0
  72. data/smoke/symbol-proc.rb +24 -0
  73. metadata +31 -3
  74. data/smoke/variadic1.rb.notyet +0 -5
@@ -264,35 +264,38 @@ module TypeProf
264
264
  end
265
265
 
266
266
  def conv_method_def(rbs_method_types)
267
- rbs_method_types.map do |type|
268
- blk = type.block ? conv_block(type.block) : nil
269
- type_params = type.type_params
270
-
271
- lead_tys = type.type.required_positionals.map {|type| conv_type(type.type) }
272
- opt_tys = type.type.optional_positionals.map {|type| conv_type(type.type) }
273
- rest_ty = type.type.rest_positionals
274
- rest_ty = conv_type(rest_ty.type) if rest_ty
275
- opt_kw_tys = type.type.optional_keywords.to_h {|key, type| [key, conv_type(type.type)] }
276
- req_kw_tys = type.type.required_keywords.to_h {|key, type| [key, conv_type(type.type)] }
277
- rest_kw_ty = type.type.rest_keywords
278
- raise NotImplementedError if rest_kw_ty # XXX
279
-
280
- ret_ty = conv_type(type.type.return_type)
281
-
282
- {
283
- type_params: type_params,
284
- lead_tys: lead_tys,
285
- opt_tys: opt_tys,
286
- rest_ty: rest_ty,
287
- req_kw_tys: req_kw_tys,
288
- opt_kw_tys: opt_kw_tys,
289
- rest_kw_ty: rest_kw_ty,
290
- blk: blk,
291
- ret_ty: ret_ty,
292
- }
267
+ rbs_method_types.map do |method_type|
268
+ conv_func(method_type.type_params, method_type.type, method_type.block)
293
269
  end
294
270
  end
295
271
 
272
+ def conv_func(type_params, func, block)
273
+ blk = block ? conv_block(block) : nil
274
+
275
+ lead_tys = func.required_positionals.map {|type| conv_type(type.type) }
276
+ opt_tys = func.optional_positionals.map {|type| conv_type(type.type) }
277
+ rest_ty = func.rest_positionals
278
+ rest_ty = conv_type(rest_ty.type) if rest_ty
279
+ opt_kw_tys = func.optional_keywords.to_h {|key, type| [key, conv_type(type.type)] }
280
+ req_kw_tys = func.required_keywords.to_h {|key, type| [key, conv_type(type.type)] }
281
+ rest_kw_ty = func.rest_keywords
282
+ raise NotImplementedError if rest_kw_ty # XXX
283
+
284
+ ret_ty = conv_type(func.return_type)
285
+
286
+ {
287
+ type_params: type_params,
288
+ lead_tys: lead_tys,
289
+ opt_tys: opt_tys,
290
+ rest_ty: rest_ty,
291
+ req_kw_tys: req_kw_tys,
292
+ opt_kw_tys: opt_kw_tys,
293
+ rest_kw_ty: rest_kw_ty,
294
+ blk: blk,
295
+ ret_ty: ret_ty,
296
+ }
297
+ end
298
+
296
299
  def attr_reader_def(ty)
297
300
  [{
298
301
  type_params: [],
@@ -401,8 +404,10 @@ module TypeProf
401
404
  [:instance, conv_type_name(ty.name)]
402
405
  end
403
406
  when RBS::Types::Bases::Instance then [:any] # XXX: not implemented yet
404
- when RBS::Types::Record then [:any] # XXX: not implemented yet
405
- when RBS::Types::Proc then [:any] # XXX: not implemented yet
407
+ when RBS::Types::Record
408
+ [:hash_record, [:Hash], ty.fields.map {|key, ty| [key, conv_type(ty)] }]
409
+ when RBS::Types::Proc
410
+ [:proc, conv_func(nil, ty.type, nil)]
406
411
  else
407
412
  warn "unknown RBS type: %p" % ty.class
408
413
  [:any]
@@ -463,6 +468,7 @@ module TypeProf
463
468
  when [:Symbol] then Type::Builtin[:sym] = klass
464
469
  when [:Array] then Type::Builtin[:ary] = klass
465
470
  when [:Hash] then Type::Builtin[:hash] = klass
471
+ when [:Proc] then Type::Builtin[:proc] = klass
466
472
  end
467
473
  end
468
474
 
@@ -505,7 +511,7 @@ module TypeProf
505
511
  @json[:constants].each do |classpath, value|
506
512
  base_klass = path_to_klass(classpath[0..-2])
507
513
  value = conv_type(value)
508
- @scratch.add_constant(base_klass, classpath[-1], value)
514
+ @scratch.add_constant(base_klass, classpath[-1], value, nil)
509
515
  end
510
516
 
511
517
  @json[:globals].each do |name, value|
@@ -517,34 +523,38 @@ module TypeProf
517
523
 
518
524
  def conv_method_def(method_name, mdef, rbs_source)
519
525
  sig_rets = mdef.flat_map do |sig_ret|
520
- #type_params = sig_ret[:type_params] # XXX
521
- lead_tys = sig_ret[:lead_tys]
522
- opt_tys = sig_ret[:opt_tys]
523
- rest_ty = sig_ret[:rest_ty]
524
- req_kw_tys = sig_ret[:req_kw_tys]
525
- opt_kw_tys = sig_ret[:opt_kw_tys]
526
- rest_kw_ty = sig_ret[:rest_kw_ty]
527
- blk = sig_ret[:blk]
528
- ret_ty = sig_ret[:ret_ty]
526
+ conv_func(sig_ret)
527
+ end
529
528
 
530
- lead_tys = lead_tys.map {|ty| conv_type(ty) }
531
- opt_tys = opt_tys.map {|ty| conv_type(ty) }
532
- rest_ty = conv_type(rest_ty) if rest_ty
533
- kw_tys = []
534
- req_kw_tys.each {|key, ty| kw_tys << [true, key, conv_type(ty)] }
535
- opt_kw_tys.each {|key, ty| kw_tys << [false, key, conv_type(ty)] }
536
- kw_rest_ty = conv_type(rest_kw_ty) if rest_kw_ty
529
+ TypedMethodDef.new(sig_rets, rbs_source)
530
+ end
537
531
 
538
- blks = conv_block(blk)
532
+ def conv_func(sig_ret)
533
+ #type_params = sig_ret[:type_params] # XXX
534
+ lead_tys = sig_ret[:lead_tys]
535
+ opt_tys = sig_ret[:opt_tys]
536
+ rest_ty = sig_ret[:rest_ty]
537
+ req_kw_tys = sig_ret[:req_kw_tys]
538
+ opt_kw_tys = sig_ret[:opt_kw_tys]
539
+ rest_kw_ty = sig_ret[:rest_kw_ty]
540
+ blk = sig_ret[:blk]
541
+ ret_ty = sig_ret[:ret_ty]
539
542
 
540
- ret_ty = conv_type(ret_ty)
543
+ lead_tys = lead_tys.map {|ty| conv_type(ty) }
544
+ opt_tys = opt_tys.map {|ty| conv_type(ty) }
545
+ rest_ty = conv_type(rest_ty) if rest_ty
546
+ kw_tys = []
547
+ req_kw_tys.each {|key, ty| kw_tys << [true, key, conv_type(ty)] }
548
+ opt_kw_tys.each {|key, ty| kw_tys << [false, key, conv_type(ty)] }
549
+ kw_rest_ty = conv_type(rest_kw_ty) if rest_kw_ty
541
550
 
542
- blks.map do |blk|
543
- [FormalArguments.new(lead_tys, opt_tys, rest_ty, [], kw_tys, kw_rest_ty, blk), ret_ty]
544
- end
545
- end
551
+ blks = conv_block(blk)
546
552
 
547
- TypedMethodDef.new(sig_rets, rbs_source)
553
+ ret_ty = conv_type(ret_ty)
554
+
555
+ blks.map do |blk|
556
+ [MethodSignature.new(lead_tys, opt_tys, rest_ty, [], kw_tys, kw_rest_ty, blk), ret_ty]
557
+ end
548
558
  end
549
559
 
550
560
  def conv_block(blk)
@@ -552,9 +562,9 @@ module TypeProf
552
562
  req, lead_tys, opt_tys, ret_ty = blk
553
563
  lead_tys = lead_tys.map {|ty| conv_type(ty) }
554
564
  opt_tys = opt_tys.map {|ty| conv_type(ty) }
555
- fargs = FormalArguments.new(lead_tys, opt_tys, nil, nil, nil, nil, nil)
565
+ msig = MethodSignature.new(lead_tys, opt_tys, nil, nil, nil, nil, nil)
556
566
  ret_ty = conv_type(ret_ty)
557
- ret = [Type::TypedProc.new(fargs, ret_ty, Type::Builtin[:proc])]
567
+ ret = [Type::Proc.new(TypedBlock.new(msig, ret_ty), Type::Builtin[:proc])]
558
568
  ret << Type.nil unless req
559
569
  ret
560
570
  end
@@ -587,11 +597,23 @@ module TypeProf
587
597
  v_ty = conv_type(v)
588
598
  h[k_ty] = v_ty
589
599
  end
600
+ when :hash_record
601
+ _, path, key_tys = ty
602
+ Type.gen_hash(Type::Instance.new(path_to_klass(path))) do |h|
603
+ key_tys.each do |key, ty|
604
+ k_ty = Type::Symbol.new(key, Type::Instance.new(Type::Builtin[:sym]))
605
+ v_ty = conv_type(ty)
606
+ h[k_ty] = v_ty
607
+ end
608
+ end
590
609
  when :union
591
610
  tys = ty[1]
592
611
  Type::Union.new(Utils::Set[*tys.map {|ty2| conv_type(ty2) }], nil) # XXX: Array and Hash support
593
612
  when :var
594
613
  Type::Var.new(ty[1])
614
+ when :proc
615
+ msig, ret_ty = conv_func(ty[1]).first # Currently, RBS Proc does not accept a block, so the size should be always one
616
+ Type::Proc.new(TypedBlock.new(msig, ret_ty), Type::Instance.new(Type::Builtin[:proc]))
595
617
  else
596
618
  pp ty
597
619
  raise NotImplementedError
@@ -32,7 +32,8 @@ module TypeProf
32
32
  @name, @path, @absolute_path, @start_lineno, @type,
33
33
  @locals, @fargs_format, catch_table, insns = *iseq
34
34
 
35
- if @type == :method
35
+ case @type
36
+ when :method, :block
36
37
  if @fargs_format[:opt]
37
38
  label = @fargs_format[:opt].last
38
39
  i = insns.index(label) + 1
@@ -45,7 +46,7 @@ module TypeProf
45
46
  label = insns[i + 1][1]
46
47
  i = insns.index(label) + 1
47
48
  end
48
- insns[i, 0] = [[:_method_body]]
49
+ insns[i, 0] = [[:_iseq_body_start]]
49
50
  end
50
51
 
51
52
  @insns = []
@@ -216,6 +217,30 @@ module TypeProf
216
217
  @insns[j + 1] = [:send_branch, [getlocal_operands, send_operands, branch_operands]]
217
218
  end
218
219
 
220
+ # find a pattern: getlocal, dup, branch
221
+ (@insns.size - 2).times do |i|
222
+ next if branch_targets[i + 1] || branch_targets[i + 2]
223
+ insn0, getlocal_operands = @insns[i]
224
+ insn1, dup_operands = @insns[i + 1]
225
+ insn2, branch_operands = @insns[i + 2]
226
+ if insn0 == :getlocal && insn1 == :dup && insn2 == :branch && getlocal_operands[1] == 0
227
+ @insns[i ] = [:nop]
228
+ @insns[i + 1] = [:nop]
229
+ @insns[i + 2] = [:getlocal_dup_branch, [getlocal_operands, dup_operands, branch_operands]]
230
+ end
231
+ end
232
+
233
+ # find a pattern: dup, branch
234
+ (@insns.size - 1).times do |i|
235
+ next if branch_targets[i + 1]
236
+ insn0, dup_operands = @insns[i]
237
+ insn1, branch_operands = @insns[i + 1]
238
+ if insn0 == :dup && insn1 == :branch
239
+ @insns[i ] = [:nop]
240
+ @insns[i + 1] = [:dup_branch, [dup_operands, branch_operands]]
241
+ end
242
+ end
243
+
219
244
  # find a pattern: getlocal, branch
220
245
  (@insns.size - 1).times do |i|
221
246
  next if branch_targets[i + 1]
@@ -14,21 +14,54 @@ module TypeProf
14
14
  recv = scratch.globalize_type(recv, caller_env, caller_ep)
15
15
  aargs = scratch.globalize_type(aargs, caller_env, caller_ep)
16
16
 
17
- aargs.each_formal_arguments(@iseq.fargs_format) do |fargs, start_pc|
18
- if fargs.is_a?(String)
19
- scratch.error(caller_ep, fargs)
20
- ctn[Type.any, caller_ep, caller_env]
21
- next
22
- end
17
+ locals = [Type.nil] * @iseq.locals.size
18
+
19
+ blk_ty, start_pcs = aargs.setup_formal_arguments(:method, locals, @iseq.fargs_format)
20
+ if blk_ty.is_a?(String)
21
+ scratch.error(caller_ep, blk_ty)
22
+ ctn[Type.any, caller_ep, caller_env]
23
+ return
24
+ end
23
25
 
24
- callee_ep = do_send_core(fargs, start_pc, recv, mid, scratch)
26
+ nctx = Context.new(@iseq, @cref, mid)
27
+ callee_ep = ExecutionPoint.new(nctx, 0, nil)
28
+ nenv = Env.new(StaticEnv.new(recv, blk_ty, false), locals, [], Utils::HashWrapper.new({}))
29
+ alloc_site = AllocationSite.new(callee_ep)
30
+ locals.each_with_index do |ty, i|
31
+ alloc_site2 = alloc_site.add_id(i)
32
+ # nenv is top-level, so it is okay to call Type#localize directly
33
+ nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
34
+ nenv = nenv.local_update(i, ty)
35
+ end
25
36
 
26
- scratch.add_iseq_method_call!(self, callee_ep.ctx)
27
- scratch.add_callsite!(callee_ep.ctx, caller_ep, caller_env, &ctn)
37
+ start_pcs.each do |start_pc|
38
+ scratch.merge_env(ExecutionPoint.new(nctx, start_pc, @outer_ep), nenv)
28
39
  end
40
+
41
+ scratch.add_iseq_method_call!(self, nctx)
42
+ scratch.add_callsite!(nctx, caller_ep, caller_env, &ctn)
29
43
  end
30
44
 
31
- def do_send_core(fargs, start_pc, recv, mid, scratch)
45
+ def do_check_send(msig, recv, mid, ep, scratch)
46
+ lead_num = @iseq.fargs_format[:lead_num] || 0
47
+ post_num = @iseq.fargs_format[:post_num] || 0
48
+ rest_start = @iseq.fargs_format[:rest_start]
49
+ opt = @iseq.fargs_format[:opt] || [0]
50
+
51
+ # TODO: check keywords
52
+ if rest_start
53
+ # almost ok
54
+ else
55
+ if msig.lead_tys.size + msig.post_tys.size < lead_num + post_num
56
+ scratch.error(ep, "RBS says that the arity may be %d, but the method definition requires at least %d arguments" % [msig.lead_tys.size + msig.post_tys.size, lead_num + post_num])
57
+ return
58
+ end
59
+ if msig.lead_tys.size + msig.opt_tys.size + msig.post_tys.size > lead_num + opt.size - 1 + post_num
60
+ scratch.error(ep, "RBS says that the arity may be %d, but the method definition requires at most %d arguments" % [msig.lead_tys.size + msig.opt_tys.size + msig.post_tys.size, lead_num + opt.size - 1 + post_num])
61
+ return
62
+ end
63
+ end
64
+
32
65
  lead_num = @iseq.fargs_format[:lead_num] || 0
33
66
  post_start = @iseq.fargs_format[:post_start]
34
67
  rest_start = @iseq.fargs_format[:rest_start]
@@ -37,81 +70,61 @@ module TypeProf
37
70
  kw_rest = @iseq.fargs_format[:kwrest]
38
71
  block_start = @iseq.fargs_format[:block_start]
39
72
 
40
- # XXX: need to check .rbs fargs and .rb fargs
73
+ # XXX: need to check .rbs msig and .rb fargs
41
74
 
42
75
  ctx = Context.new(@iseq, @cref, mid)
43
- callee_ep = ExecutionPoint.new(ctx, start_pc, nil)
76
+ callee_ep = ExecutionPoint.new(ctx, 0, nil)
44
77
 
45
78
  locals = [Type.nil] * @iseq.locals.size
46
- nenv = Env.new(StaticEnv.new(recv, fargs.blk_ty, false), locals, [], Utils::HashWrapper.new({}))
79
+ nenv = Env.new(StaticEnv.new(recv, msig.blk_ty, false), locals, [], Utils::HashWrapper.new({}))
47
80
  alloc_site = AllocationSite.new(callee_ep)
48
81
  idx = 0
49
- fargs.lead_tys.each_with_index do |ty, i|
82
+ msig.lead_tys.each_with_index do |ty, i|
50
83
  alloc_site2 = alloc_site.add_id(idx += 1)
51
84
  # nenv is top-level, so it is okay to call Type#localize directly
52
85
  nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
53
86
  nenv = nenv.local_update(i, ty)
54
87
  end
55
- if fargs.opt_tys
56
- fargs.opt_tys.each_with_index do |ty, i|
88
+ if msig.opt_tys
89
+ msig.opt_tys.each_with_index do |ty, i|
57
90
  alloc_site2 = alloc_site.add_id(idx += 1)
58
91
  nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
59
92
  nenv = nenv.local_update(lead_num + i, ty)
60
93
  end
61
94
  end
62
- if fargs.rest_ty
95
+ if msig.rest_ty
63
96
  alloc_site2 = alloc_site.add_id(idx += 1)
64
- ty = Type::Array.new(Type::Array::Elements.new([], fargs.rest_ty), Type::Instance.new(Type::Builtin[:ary]))
97
+ ty = Type::Array.new(Type::Array::Elements.new([], msig.rest_ty), Type::Instance.new(Type::Builtin[:ary]))
65
98
  nenv, rest_ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
66
99
  nenv = nenv.local_update(rest_start, rest_ty)
67
100
  end
68
- if fargs.post_tys
69
- fargs.post_tys.each_with_index do |ty, i|
101
+ if msig.post_tys
102
+ msig.post_tys.each_with_index do |ty, i|
70
103
  alloc_site2 = alloc_site.add_id(idx += 1)
71
104
  nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
72
105
  nenv = nenv.local_update(post_start + i, ty)
73
106
  end
74
107
  end
75
- if fargs.kw_tys
76
- fargs.kw_tys.each_with_index do |(_, key, ty), i|
108
+ if msig.kw_tys
109
+ msig.kw_tys.each_with_index do |(_, key, ty), i|
77
110
  alloc_site2 = alloc_site.add_id(key)
78
111
  nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
79
112
  nenv = nenv.local_update(kw_start + i, ty)
80
113
  end
81
114
  end
82
- if fargs.kw_rest_ty
83
- ty = fargs.kw_rest_ty
115
+ if msig.kw_rest_ty
116
+ ty = msig.kw_rest_ty
84
117
  alloc_site2 = alloc_site.add_id(:**)
85
118
  nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
86
119
  nenv = nenv.local_update(kw_rest, ty)
87
120
  end
88
- nenv = nenv.local_update(block_start, fargs.blk_ty) if block_start
89
-
90
- scratch.merge_env(callee_ep, nenv)
91
-
92
- callee_ep
93
- end
94
-
95
- def do_check_send_core(fargs, recv, mid, ep, scratch)
96
- lead_num = @iseq.fargs_format[:lead_num] || 0
97
- post_num = @iseq.fargs_format[:post_num] || 0
98
- rest_start = @iseq.fargs_format[:rest_start]
99
- opt = @iseq.fargs_format[:opt] || [0]
121
+ nenv = nenv.local_update(block_start, msig.blk_ty) if block_start
100
122
 
101
- # TODO: check keywords
102
- if rest_start
103
- # almost ok
104
- else
105
- if fargs.lead_tys.size + fargs.post_tys.size < lead_num + post_num
106
- scratch.error(ep, "RBS says that the arity may be %d, but the method definition requires at least %d arguments" % [fargs.lead_tys.size + fargs.post_tys.size, lead_num + post_num])
107
- return
108
- end
109
- if fargs.lead_tys.size + fargs.opt_tys.size + fargs.post_tys.size > lead_num + opt.size - 1 + post_num
110
- scratch.error(ep, "RBS says that the arity may be %d, but the method definition requires at most %d arguments" % [fargs.lead_tys.size + fargs.opt_tys.size + fargs.post_tys.size, lead_num + opt.size - 1 + post_num])
111
- return
112
- end
123
+ opt.each do |start_pc|
124
+ scratch.merge_env(ExecutionPoint.new(ctx, start_pc, nil), nenv)
113
125
  end
114
- do_send_core(fargs, 0, recv, mid, scratch)
126
+
127
+ ctx
115
128
  end
116
129
  end
117
130
 
@@ -147,8 +160,8 @@ module TypeProf
147
160
  end
148
161
 
149
162
  class TypedMethodDef < MethodDef
150
- def initialize(sigs, rbs_source) # sigs: Array<[FormalArguments, (return)Type]>
151
- @sigs = sigs
163
+ def initialize(sig_rets, rbs_source) # sig_rets: Array<[MethodSignature, (return)Type]>
164
+ @sig_rets = sig_rets
152
165
  @rbs_source = rbs_source
153
166
  end
154
167
 
@@ -158,12 +171,12 @@ module TypeProf
158
171
  recv = scratch.globalize_type(recv_orig, caller_env, caller_ep)
159
172
  found = false
160
173
  aargs = scratch.globalize_type(aargs, caller_env, caller_ep)
161
- @sigs.each do |fargs, ret_ty|
174
+ @sig_rets.each do |msig, ret_ty|
162
175
  ncaller_env = caller_env
163
- #pp [mid, aargs, fargs]
164
- # XXX: support self type in fargs
176
+ #pp [mid, aargs, msig]
177
+ # XXX: support self type in msig
165
178
  subst = { Type::Var.new(:self) => recv }
166
- next unless aargs.consistent_with_formal_arguments?(fargs, subst)
179
+ next unless aargs.consistent_with_method_signature?(msig, subst)
167
180
  case
168
181
  when recv.is_a?(Type::Cell) && recv_orig.is_a?(Type::LocalCell)
169
182
  tyvars = recv.base_type.klass.type_params.map {|name,| Type::Var.new(name) }
@@ -171,12 +184,12 @@ module TypeProf
171
184
  ty = subst[tyvar]
172
185
  if ty
173
186
  ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
174
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id) do |elems|
175
- Utils.array_update(elems, idx, elems[idx].union(ty))
187
+ ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
188
+ elems.update(idx, ty)
176
189
  end
177
190
  end
178
191
  end
179
- tyvars.zip(recv.elems) do |tyvar, elem|
192
+ tyvars.zip(recv.elems.elems) do |tyvar, elem|
180
193
  if subst[tyvar]
181
194
  subst[tyvar] = subst[tyvar].union(elem)
182
195
  else
@@ -188,11 +201,11 @@ module TypeProf
188
201
  if subst[tyvar_elem]
189
202
  ty = subst[tyvar_elem]
190
203
  ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
191
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id) do |elems|
204
+ ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
192
205
  elems.update(nil, ty)
193
206
  end
194
207
  end
195
- subst.merge!({ tyvar_elem => recv.elems.squash })
208
+ subst.merge!({ tyvar_elem => recv.elems.squash_or_any })
196
209
  when recv.is_a?(Type::Hash) && recv_orig.is_a?(Type::LocalHash)
197
210
  tyvar_k = Type::Var.new(:K)
198
211
  tyvar_v = Type::Var.new(:V)
@@ -203,18 +216,19 @@ module TypeProf
203
216
  end
204
217
  ret_ty = ret_ty.substitute(subst, Config.options[:type_depth_limit])
205
218
  found = true
206
- if aargs.blk_ty.is_a?(Type::ISeqProc)
219
+ if aargs.blk_ty.is_a?(Type::Proc)
220
+ #raise NotImplementedError unless aargs.blk_ty.block_body.is_a?(ISeqBlock) # XXX
207
221
  dummy_ctx = TypedContext.new(caller_ep, mid)
208
222
  dummy_ep = ExecutionPoint.new(dummy_ctx, -1, caller_ep)
209
- dummy_env = Env.new(StaticEnv.new(recv, fargs.blk_ty, false), [], [], Utils::HashWrapper.new({}))
210
- if fargs.blk_ty.is_a?(Type::TypedProc)
223
+ dummy_env = Env.new(StaticEnv.new(recv, msig.blk_ty, false), [], [], Utils::HashWrapper.new({}))
224
+ if msig.blk_ty.is_a?(Type::Proc)
211
225
  scratch.add_callsite!(dummy_ctx, caller_ep, ncaller_env, &ctn)
212
- nfargs = fargs.blk_ty.fargs
226
+ nfargs = msig.blk_ty.block_body.msig
213
227
  alloc_site = AllocationSite.new(caller_ep).add_id(self)
214
228
  nlead_tys = (nfargs.lead_tys + nfargs.opt_tys).map.with_index do |ty, i|
215
229
  if recv.is_a?(Type::Array)
216
230
  tyvar_elem = Type::Var.new(:Elem)
217
- ty = ty.substitute(subst.merge({ tyvar_elem => recv.elems.squash }), Config.options[:type_depth_limit])
231
+ ty = ty.substitute(subst.merge({ tyvar_elem => recv.elems.squash_or_any }), Config.options[:type_depth_limit])
218
232
  else
219
233
  ty = ty.substitute(subst, Config.options[:type_depth_limit])
220
234
  end
@@ -225,13 +239,13 @@ module TypeProf
225
239
  end
226
240
  0.upto(nfargs.opt_tys.size) do |n|
227
241
  naargs = ActualArguments.new(nlead_tys[0, nfargs.lead_tys.size + n], nil, {}, Type.nil) # XXX: support block to block?
228
- scratch.do_invoke_block(false, aargs.blk_ty, naargs, dummy_ep, dummy_env) do |blk_ret_ty, _ep, _env|
242
+ scratch.do_invoke_block(aargs.blk_ty, naargs, dummy_ep, dummy_env) do |blk_ret_ty, _ep, _env|
229
243
  subst2 = {}
230
- if blk_ret_ty.consistent?(fargs.blk_ty.ret_ty, subst2)
244
+ if blk_ret_ty.consistent?(msig.blk_ty.block_body.ret_ty, subst2)
231
245
  if recv.is_a?(Type::Array) && recv_orig.is_a?(Type::LocalArray)
232
246
  tyvar_elem = Type::Var.new(:Elem)
233
247
  if subst2[tyvar_elem]
234
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id) do |elems|
248
+ ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
235
249
  elems.update(nil, subst2[tyvar_elem])
236
250
  end
237
251
  scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
@@ -247,10 +261,10 @@ module TypeProf
247
261
  end
248
262
  ret_ty = ret_ty.remove_type_vars
249
263
  # XXX: check the return type from the block
250
- # sig.blk_ty.ret_ty.eql?(_ret_ty) ???
251
- scratch.add_return_type!(dummy_ctx, ret_ty)
264
+ # sig.blk_ty.block_body.ret_ty.eql?(_ret_ty) ???
265
+ scratch.add_return_value!(dummy_ctx, ret_ty)
252
266
  end
253
- # scratch.add_return_type!(dummy_ctx, ret_ty) ?
267
+ # scratch.add_return_value!(dummy_ctx, ret_ty) ?
254
268
  # This makes `def foo; 1.times { return "str" }; end` return Integer|String
255
269
  end
256
270
  else
@@ -273,8 +287,8 @@ module TypeProf
273
287
 
274
288
  def do_match_iseq_mdef(iseq_mdef, recv, mid, env, ep, scratch)
275
289
  recv = scratch.globalize_type(recv, env, ep)
276
- @sigs.each do |fargs, _ret_ty|
277
- iseq_mdef.do_check_send_core(fargs, recv, mid, ep, scratch)
290
+ @sig_rets.each do |msig, _ret_ty|
291
+ iseq_mdef.do_check_send(msig, recv, mid, ep, scratch)
278
292
  end
279
293
  end
280
294
  end