typeprof 0.7.0 → 0.10.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 (296) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +8 -5
  3. data/lib/typeprof/analyzer.rb +211 -98
  4. data/lib/typeprof/arguments.rb +2 -0
  5. data/lib/typeprof/block.rb +40 -2
  6. data/lib/typeprof/builtin.rb +301 -99
  7. data/lib/typeprof/cli.rb +2 -0
  8. data/lib/typeprof/config.rb +14 -2
  9. data/lib/typeprof/container-type.rb +5 -4
  10. data/lib/typeprof/export.rb +116 -65
  11. data/lib/typeprof/import.rb +68 -41
  12. data/lib/typeprof/iseq.rb +46 -11
  13. data/lib/typeprof/method.rb +47 -23
  14. data/lib/typeprof/type.rb +96 -18
  15. data/lib/typeprof/version.rb +1 -1
  16. data/smoke/alias.rb +5 -4
  17. data/smoke/alias2.rb +6 -4
  18. data/smoke/any1.rb +2 -1
  19. data/smoke/any2.rb +3 -2
  20. data/smoke/arguments.rb +3 -2
  21. data/smoke/arguments2.rb +11 -10
  22. data/smoke/array-each.rb +2 -1
  23. data/smoke/array-each2.rb +2 -1
  24. data/smoke/array-each3.rb +2 -1
  25. data/smoke/array-ltlt.rb +2 -1
  26. data/smoke/array-ltlt2.rb +2 -1
  27. data/smoke/array-map.rb +2 -1
  28. data/smoke/array-map2.rb +2 -1
  29. data/smoke/array-map3.rb +4 -3
  30. data/smoke/array-mul.rb +3 -2
  31. data/smoke/array-plus1.rb +2 -1
  32. data/smoke/array-plus2.rb +3 -2
  33. data/smoke/array-pop.rb +2 -1
  34. data/smoke/array-range-aref.rb +12 -11
  35. data/smoke/array-replace.rb +2 -1
  36. data/smoke/array-s-aref.rb +2 -1
  37. data/smoke/array1.rb +6 -5
  38. data/smoke/array10.rb +2 -1
  39. data/smoke/array11.rb +2 -1
  40. data/smoke/array12.rb +4 -3
  41. data/smoke/array13.rb +5 -4
  42. data/smoke/array14.rb +2 -1
  43. data/smoke/array15.rb +16 -0
  44. data/smoke/array2.rb +4 -3
  45. data/smoke/array3.rb +5 -4
  46. data/smoke/array4.rb +2 -1
  47. data/smoke/array5.rb +2 -1
  48. data/smoke/array6.rb +4 -2
  49. data/smoke/array7.rb +2 -1
  50. data/smoke/array8.rb +1 -1
  51. data/smoke/array9.rb +2 -1
  52. data/smoke/attr-module.rb +27 -0
  53. data/smoke/attr-vis.rb +43 -0
  54. data/smoke/attr-vis.rbs +4 -0
  55. data/smoke/attr.rb +5 -5
  56. data/smoke/autoload.rb +2 -1
  57. data/smoke/backtrace.rb +4 -3
  58. data/smoke/block-ambiguous.rb +9 -8
  59. data/smoke/block-args1-rest.rb +13 -11
  60. data/smoke/block-args1.rb +11 -10
  61. data/smoke/block-args2-rest.rb +13 -11
  62. data/smoke/block-args2.rb +11 -10
  63. data/smoke/block-args3-rest.rb +15 -13
  64. data/smoke/block-args3.rb +13 -12
  65. data/smoke/block-blockarg.rb +5 -4
  66. data/smoke/block-kwarg.rb +11 -10
  67. data/smoke/block1.rb +2 -1
  68. data/smoke/block10.rb +2 -1
  69. data/smoke/block11.rb +6 -5
  70. data/smoke/block12.rb +3 -2
  71. data/smoke/block14.rb +3 -2
  72. data/smoke/block2.rb +2 -1
  73. data/smoke/block3.rb +3 -3
  74. data/smoke/block4.rb +3 -2
  75. data/smoke/block5.rb +4 -2
  76. data/smoke/block6.rb +3 -2
  77. data/smoke/block7.rb +2 -1
  78. data/smoke/block8.rb +4 -3
  79. data/smoke/block9.rb +2 -1
  80. data/smoke/block_given.rb +37 -0
  81. data/smoke/blown.rb +2 -1
  82. data/smoke/break1.rb +3 -2
  83. data/smoke/break2.rb +2 -1
  84. data/smoke/break3.rb +13 -0
  85. data/smoke/case.rb +2 -1
  86. data/smoke/case2.rb +2 -1
  87. data/smoke/case3.rb +17 -0
  88. data/smoke/class-hierarchy.rb +5 -5
  89. data/smoke/class-hierarchy2.rb +3 -3
  90. data/smoke/class-new.rb +15 -0
  91. data/smoke/class_instance_var.rb +1 -1
  92. data/smoke/class_method.rb +2 -2
  93. data/smoke/class_method2.rb +2 -2
  94. data/smoke/class_method3.rb +4 -2
  95. data/smoke/constant1.rb +6 -6
  96. data/smoke/constant2.rb +6 -4
  97. data/smoke/constant3.rb +2 -1
  98. data/smoke/constant4.rb +2 -1
  99. data/smoke/context-sensitive1.rb +2 -1
  100. data/smoke/cvar.rb +7 -5
  101. data/smoke/cvar2.rb +2 -2
  102. data/smoke/define_method.rb +2 -2
  103. data/smoke/define_method2.rb +2 -2
  104. data/smoke/define_method3.rb +14 -0
  105. data/smoke/define_method3.rbs +3 -0
  106. data/smoke/define_method4.rb +15 -0
  107. data/smoke/define_method4.rbs +3 -0
  108. data/smoke/define_method5.rb +12 -0
  109. data/smoke/define_method6.rb +19 -0
  110. data/smoke/demo.rb +7 -6
  111. data/smoke/demo1.rb +2 -1
  112. data/smoke/demo10.rb +3 -2
  113. data/smoke/demo11.rb +2 -1
  114. data/smoke/demo2.rb +2 -1
  115. data/smoke/demo3.rb +2 -1
  116. data/smoke/demo4.rb +3 -3
  117. data/smoke/demo5.rb +1 -1
  118. data/smoke/demo6.rb +4 -3
  119. data/smoke/demo7.rb +2 -1
  120. data/smoke/demo8.rb +3 -2
  121. data/smoke/demo9.rb +4 -2
  122. data/smoke/dummy-execution1.rb +3 -2
  123. data/smoke/dummy-execution2.rb +2 -2
  124. data/smoke/dummy_element.rb +14 -0
  125. data/smoke/ensure1.rb +3 -2
  126. data/smoke/enum_for.rb +15 -0
  127. data/smoke/enum_for2.rb +17 -0
  128. data/smoke/enumerator.rb +3 -2
  129. data/smoke/expandarray1.rb +2 -1
  130. data/smoke/expandarray2.rb +2 -1
  131. data/smoke/fib.rb +2 -2
  132. data/smoke/flip-flop.rb +28 -0
  133. data/smoke/flow1.rb +2 -1
  134. data/smoke/flow10.rb +17 -0
  135. data/smoke/flow2.rb +2 -1
  136. data/smoke/flow3.rb +2 -1
  137. data/smoke/flow5.rb +2 -1
  138. data/smoke/flow6.rb +2 -1
  139. data/smoke/flow7.rb +2 -1
  140. data/smoke/flow8.rb +2 -1
  141. data/smoke/flow9.rb +12 -0
  142. data/smoke/freeze.rb +2 -1
  143. data/smoke/function.rb +3 -2
  144. data/smoke/gvar.rb +3 -2
  145. data/smoke/gvar2.rb +4 -3
  146. data/smoke/hash-bot.rb +12 -0
  147. data/smoke/hash-fetch.rb +4 -3
  148. data/smoke/hash-merge-bang.rb +2 -1
  149. data/smoke/hash1.rb +3 -2
  150. data/smoke/hash2.rb +2 -1
  151. data/smoke/hash3.rb +2 -1
  152. data/smoke/hash4.rb +2 -1
  153. data/smoke/hash5.rb +1 -1
  154. data/smoke/inheritance.rb +4 -4
  155. data/smoke/inheritance2.rb +2 -2
  156. data/smoke/initialize.rb +7 -5
  157. data/smoke/instance_eval.rb +2 -2
  158. data/smoke/instance_eval2.rb +10 -0
  159. data/smoke/instance_eval3.rb +25 -0
  160. data/smoke/int_times.rb +2 -1
  161. data/smoke/integer.rb +2 -1
  162. data/smoke/ivar.rb +6 -4
  163. data/smoke/ivar2.rb +4 -4
  164. data/smoke/ivar3.rb +4 -3
  165. data/smoke/ivar4.rb +21 -0
  166. data/smoke/kernel-class.rb +2 -1
  167. data/smoke/keyword1.rb +2 -1
  168. data/smoke/keyword2.rb +2 -1
  169. data/smoke/keyword3.rb +2 -1
  170. data/smoke/keyword4.rb +2 -1
  171. data/smoke/keyword5.rb +2 -1
  172. data/smoke/kwrest.rb +3 -2
  173. data/smoke/kwsplat1.rb +5 -4
  174. data/smoke/kwsplat2.rb +2 -1
  175. data/smoke/lit-complex.rb +10 -0
  176. data/smoke/lit-encoding.rb +10 -0
  177. data/smoke/manual-rbs.rb +6 -4
  178. data/smoke/manual-rbs2.rb +2 -1
  179. data/smoke/manual-rbs3.rb +3 -2
  180. data/smoke/masgn1.rb +2 -1
  181. data/smoke/masgn2.rb +3 -2
  182. data/smoke/masgn3.rb +2 -1
  183. data/smoke/method_in_branch.rb +4 -3
  184. data/smoke/method_missing.rb +5 -4
  185. data/smoke/module1.rb +2 -2
  186. data/smoke/module2.rb +1 -1
  187. data/smoke/module3.rb +3 -3
  188. data/smoke/module4.rb +3 -2
  189. data/smoke/module5.rb +17 -0
  190. data/smoke/module6.rb +40 -0
  191. data/smoke/module_function1.rb +4 -3
  192. data/smoke/module_function2.rb +4 -3
  193. data/smoke/multiple-include.rb +2 -1
  194. data/smoke/multiple-superclass.rb +1 -1
  195. data/smoke/next1.rb +3 -2
  196. data/smoke/next2.rb +2 -1
  197. data/smoke/object-send1.rb +4 -3
  198. data/smoke/object-send2.rb +10 -0
  199. data/smoke/object-send3.rb +18 -0
  200. data/smoke/once.rb +2 -1
  201. data/smoke/optional1.rb +2 -1
  202. data/smoke/optional2.rb +2 -1
  203. data/smoke/optional3.rb +2 -1
  204. data/smoke/parameterizedd-self.rb +4 -2
  205. data/smoke/parameterizedd-self2.rb +1 -1
  206. data/smoke/pathname1.rb +2 -1
  207. data/smoke/pathname2.rb +2 -1
  208. data/smoke/pattern-match1.rb +2 -1
  209. data/smoke/pattern-match2.rb +2 -1
  210. data/smoke/prepend1.rb +33 -0
  211. data/smoke/prepend2.rb +10 -0
  212. data/smoke/prepend2.rbs +9 -0
  213. data/smoke/primitive_method.rb +19 -0
  214. data/smoke/printf.rb +2 -2
  215. data/smoke/proc.rb +3 -2
  216. data/smoke/proc2.rb +2 -1
  217. data/smoke/proc3.rb +2 -1
  218. data/smoke/proc4.rb +2 -1
  219. data/smoke/proc5.rb +19 -0
  220. data/smoke/public.rb +38 -0
  221. data/smoke/range.rb +2 -1
  222. data/smoke/rbs-alias.rb +2 -1
  223. data/smoke/rbs-attr.rb +6 -5
  224. data/smoke/rbs-attr2.rb +1 -1
  225. data/smoke/rbs-extend.rb +2 -1
  226. data/smoke/rbs-interface.rb +5 -4
  227. data/smoke/rbs-module.rb +26 -0
  228. data/smoke/rbs-module.rbs +4 -0
  229. data/smoke/rbs-opt-and-rest.rb +10 -0
  230. data/smoke/rbs-opt-and-rest.rbs +3 -0
  231. data/smoke/rbs-proc1.rb +2 -1
  232. data/smoke/rbs-proc2.rb +3 -2
  233. data/smoke/rbs-proc3.rb +2 -1
  234. data/smoke/rbs-record.rb +3 -2
  235. data/smoke/rbs-tyvar.rb +3 -2
  236. data/smoke/rbs-tyvar2.rb +3 -2
  237. data/smoke/rbs-tyvar3.rb +3 -2
  238. data/smoke/rbs-tyvar4.rb +4 -3
  239. data/smoke/rbs-tyvar5.rb +2 -1
  240. data/smoke/rbs-tyvar6.rb +4 -3
  241. data/smoke/rbs-tyvar7.rb +2 -1
  242. data/smoke/rbs-vars.rb +7 -6
  243. data/smoke/redo1.rb +3 -2
  244. data/smoke/redo2.rb +3 -2
  245. data/smoke/req-keyword.rb +2 -1
  246. data/smoke/rescue1.rb +3 -2
  247. data/smoke/rescue2.rb +3 -2
  248. data/smoke/rescue3.rb +20 -0
  249. data/smoke/rescue4.rb +17 -0
  250. data/smoke/respond_to.rb +2 -1
  251. data/smoke/rest-farg.rb +2 -1
  252. data/smoke/rest1.rb +3 -2
  253. data/smoke/rest2.rb +2 -1
  254. data/smoke/rest3.rb +7 -6
  255. data/smoke/rest4.rb +3 -2
  256. data/smoke/rest5.rb +2 -1
  257. data/smoke/rest6.rb +2 -1
  258. data/smoke/retry1.rb +3 -2
  259. data/smoke/return.rb +2 -1
  260. data/smoke/simple.rb +12 -0
  261. data/smoke/singleton_method.rb +1 -1
  262. data/smoke/step.rb +4 -3
  263. data/smoke/string-split.rb +2 -1
  264. data/smoke/struct-keyword_init.rb +10 -0
  265. data/smoke/struct.rb +1 -1
  266. data/smoke/struct2.rb +5 -4
  267. data/smoke/struct3.rb +2 -2
  268. data/smoke/struct4.rb +7 -0
  269. data/smoke/struct5.rb +16 -0
  270. data/smoke/struct6.rb +15 -0
  271. data/smoke/struct7.rb +17 -0
  272. data/smoke/stub-keyword.rb +10 -0
  273. data/smoke/super1.rb +5 -4
  274. data/smoke/super2.rb +1 -1
  275. data/smoke/super3.rb +4 -3
  276. data/smoke/super4.rb +7 -5
  277. data/smoke/super5.rb +6 -4
  278. data/smoke/svar1.rb +2 -1
  279. data/smoke/symbol-proc-attr.rb +22 -0
  280. data/smoke/symbol-proc-attr2.rb +15 -0
  281. data/smoke/symbol-proc-bot.rb +13 -0
  282. data/smoke/symbol-proc.rb +4 -3
  283. data/smoke/tap1.rb +3 -2
  284. data/smoke/toplevel.rb +2 -1
  285. data/smoke/two-map.rb +3 -2
  286. data/smoke/type_var.rb +4 -3
  287. data/smoke/typed_method.rb +2 -1
  288. data/smoke/uninitialize-var.rb +2 -1
  289. data/smoke/union-recv.rb +2 -2
  290. data/smoke/user-demo.rb +3 -3
  291. data/smoke/wrong-extend.rb +3 -2
  292. data/smoke/wrong-include.rb +3 -2
  293. data/smoke/wrong-include2.rb +17 -0
  294. data/typeprof.gemspec +1 -1
  295. metadata +57 -5
  296. data/tools/stackprof-wrapper.rb +0 -10
@@ -49,10 +49,18 @@ module TypeProf
49
49
  insns[i, 0] = [[:_iseq_body_start]]
50
50
  end
51
51
 
52
+ # rescue/ensure clauses need to have a dedicated return addresses
53
+ # because they requires to be virtually called.
54
+ # So, this preprocess adds "nop" to make a new insn for their return addresses
55
+ special_labels = {}
56
+ catch_table.map do |type, iseq, first, last, cont, stack_depth|
57
+ special_labels[cont] = true if type == :rescue || type == :ensure
58
+ end
59
+
52
60
  @insns = []
53
61
  @linenos = []
54
62
 
55
- labels = setup_iseq(insns)
63
+ labels = setup_iseq(insns, special_labels)
56
64
 
57
65
  # checkmatch->branch
58
66
  # send->branch
@@ -60,7 +68,8 @@ module TypeProf
60
68
  @catch_table = []
61
69
  catch_table.map do |type, iseq, first, last, cont, stack_depth|
62
70
  iseq = iseq ? ISeq.new(iseq) : nil
63
- entry = [type, iseq, labels[cont], stack_depth]
71
+ target = labels[special_labels[cont] ? :"#{ cont }_special" : cont]
72
+ entry = [type, iseq, target, stack_depth]
64
73
  labels[first].upto(labels[last]) do |i|
65
74
  @catch_table[i] ||= []
66
75
  @catch_table[i] << entry
@@ -76,19 +85,26 @@ module TypeProf
76
85
  @id <=> other.id
77
86
  end
78
87
 
79
- def setup_iseq(insns)
88
+ def setup_iseq(insns, special_labels)
80
89
  i = 0
81
90
  labels = {}
91
+ ninsns = []
82
92
  insns.each do |e|
83
93
  if e.is_a?(Symbol) && e.to_s.start_with?("label")
94
+ if special_labels[e]
95
+ labels[:"#{ e }_special"] = i
96
+ ninsns << [:nop]
97
+ i += 1
98
+ end
84
99
  labels[e] = i
85
- elsif e.is_a?(Array)
86
- i += 1
100
+ else
101
+ i += 1 if e.is_a?(Array)
102
+ ninsns << e
87
103
  end
88
104
  end
89
105
 
90
106
  lineno = 0
91
- insns.each do |e|
107
+ ninsns.each do |e|
92
108
  case e
93
109
  when Integer # lineno
94
110
  lineno = e
@@ -191,7 +207,7 @@ module TypeProf
191
207
  end
192
208
 
193
209
  # find a pattern: getlocal, ..., send (is_a?, respond_to?), branch
194
- send_branch_list = []
210
+ getlocal_send_branch_list = []
195
211
  (@insns.size - 1).times do |i|
196
212
  insn, operands = @insns[i]
197
213
  if insn == :getlocal && operands[1] == 0
@@ -200,7 +216,7 @@ module TypeProf
200
216
  while @insns[j]
201
217
  sp = check_send_branch(sp, j)
202
218
  if sp == :match
203
- send_branch_list << [i, j]
219
+ getlocal_send_branch_list << [i, j]
204
220
  break
205
221
  end
206
222
  break if !sp
@@ -208,13 +224,32 @@ module TypeProf
208
224
  end
209
225
  end
210
226
  end
211
- send_branch_list.each do |i, j|
212
- next if (i + 1 .. j).any? {|i| branch_targets[i] }
227
+ getlocal_send_branch_list.each do |i, j|
228
+ next if (i + 1 .. j + 1).any? {|i| branch_targets[i] }
213
229
  _insn, getlocal_operands = @insns[i]
214
230
  _insn, send_operands = @insns[j]
215
231
  _insn, branch_operands = @insns[j + 1]
216
232
  @insns[j] = [:nop]
217
- @insns[j + 1] = [:send_branch, [getlocal_operands, send_operands, branch_operands]]
233
+ @insns[j + 1] = [:getlocal_send_branch, [getlocal_operands, send_operands, branch_operands]]
234
+ end
235
+
236
+ # find a pattern: send (block_given?), branch
237
+ send_branch_list = []
238
+ (@insns.size - 1).times do |i|
239
+ insn, _operands = @insns[i]
240
+ if insn == :send
241
+ insn, _operands = @insns[i + 1]
242
+ if insn == :branch
243
+ send_branch_list << i
244
+ end
245
+ end
246
+ end
247
+ send_branch_list.each do |i|
248
+ next if branch_targets[i + 1]
249
+ _insn, send_operands = @insns[i]
250
+ _insn, branch_operands = @insns[i + 1]
251
+ @insns[i] = [:nop]
252
+ @insns[i + 1] = [:send_branch, [send_operands, branch_operands]]
218
253
  end
219
254
 
220
255
  # find a pattern: getlocal, dup, branch
@@ -1,14 +1,17 @@
1
1
  module TypeProf
2
2
  class MethodDef
3
+ attr_accessor :pub_meth
4
+
3
5
  include Utils::StructuralEquality
4
6
  end
5
7
 
6
8
  class ISeqMethodDef < MethodDef
7
- def initialize(iseq, cref, outer_ep)
9
+ def initialize(iseq, cref, outer_ep, pub_meth)
8
10
  @iseq = iseq
9
11
  raise if iseq.nil?
10
12
  @cref = cref
11
13
  @outer_ep = outer_ep
14
+ @pub_meth = pub_meth
12
15
  end
13
16
 
14
17
  def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
@@ -27,7 +30,7 @@ module TypeProf
27
30
 
28
31
  nctx = Context.new(@iseq, @cref, mid)
29
32
  callee_ep = ExecutionPoint.new(nctx, 0, @outer_ep)
30
- nenv = Env.new(StaticEnv.new(recv, blk_ty, false), locals, [], Utils::HashWrapper.new({}))
33
+ nenv = Env.new(StaticEnv.new(recv, blk_ty, false, true), locals, [], Utils::HashWrapper.new({}))
31
34
  alloc_site = AllocationSite.new(callee_ep)
32
35
  locals.each_with_index do |ty, i|
33
36
  alloc_site2 = alloc_site.add_id(i)
@@ -84,24 +87,23 @@ module TypeProf
84
87
  # XXX: need to check .rbs msig and .rb fargs
85
88
 
86
89
  ctx = Context.new(@iseq, @cref, mid)
87
- callee_ep = ExecutionPoint.new(ctx, 0, nil)
90
+ callee_ep = ExecutionPoint.new(ctx, 0, @outer_ep)
88
91
 
89
92
  locals = [Type.nil] * @iseq.locals.size
90
- nenv = Env.new(StaticEnv.new(recv, msig.blk_ty, false), locals, [], Utils::HashWrapper.new({}))
93
+ nenv = Env.new(StaticEnv.new(recv, msig.blk_ty, false, true), locals, [], Utils::HashWrapper.new({}))
91
94
  alloc_site = AllocationSite.new(callee_ep)
92
95
  idx = 0
93
96
  msig.lead_tys.each_with_index do |ty, i|
94
97
  alloc_site2 = alloc_site.add_id(idx += 1)
95
- # nenv is top-level, so it is okay to call Type#localize directly
96
98
  ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
97
- nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
99
+ nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
98
100
  nenv = nenv.local_update(i, ty)
99
101
  end
100
102
  if msig.opt_tys
101
103
  msig.opt_tys.each_with_index do |ty, i|
102
104
  alloc_site2 = alloc_site.add_id(idx += 1)
103
105
  ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
104
- nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
106
+ nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
105
107
  nenv = nenv.local_update(lead_num + i, ty)
106
108
  end
107
109
  end
@@ -109,27 +111,27 @@ module TypeProf
109
111
  alloc_site2 = alloc_site.add_id(idx += 1)
110
112
  ty = Type::Array.new(Type::Array::Elements.new([], msig.rest_ty), Type::Instance.new(Type::Builtin[:ary]))
111
113
  ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
112
- nenv, rest_ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
114
+ nenv, rest_ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
113
115
  nenv = nenv.local_update(rest_start, rest_ty)
114
116
  end
115
117
  if msig.post_tys
116
118
  msig.post_tys.each_with_index do |ty, i|
117
119
  alloc_site2 = alloc_site.add_id(idx += 1)
118
120
  ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
119
- nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
121
+ nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
120
122
  nenv = nenv.local_update(post_start + i, ty)
121
123
  end
122
124
  end
123
- if msig.kw_tys
125
+ if msig.kw_tys && keyword # TODO: support the case where RBS writes kw_tys and RB method accepts **kwrest
124
126
  msig.kw_tys.each do |_, key, ty|
125
- i = keyword.index(key)
127
+ i = keyword.index {|callee_key,| callee_key == key }
126
128
  unless i
127
129
  # warn
128
130
  next
129
131
  end
130
132
  alloc_site2 = alloc_site.add_id(key)
131
133
  ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
132
- nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
134
+ nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
133
135
  nenv = nenv.local_update(kw_start + i, ty)
134
136
  end
135
137
  end
@@ -137,34 +139,55 @@ module TypeProf
137
139
  ty = msig.kw_rest_ty
138
140
  alloc_site2 = alloc_site.add_id(:**)
139
141
  ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
140
- nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
142
+ nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
141
143
  nenv = nenv.local_update(kw_rest, ty)
142
144
  end
143
145
  nenv = nenv.local_update(block_start, msig.blk_ty) if block_start
144
146
 
145
147
  opt.each do |start_pc|
146
- scratch.merge_env(ExecutionPoint.new(ctx, start_pc, nil), nenv)
148
+ scratch.merge_env(callee_ep.jump(start_pc), nenv)
147
149
  end
150
+ scratch.add_executed_iseq(@iseq)
148
151
 
149
152
  ctx
150
153
  end
151
154
  end
152
155
 
156
+ class AliasMethodDef < MethodDef
157
+ def initialize(orig_mid, mdef, def_ep)
158
+ @orig_mid = orig_mid
159
+ @mdef = mdef
160
+ @pub_meth = mdef.pub_meth
161
+ @def_ep = def_ep
162
+ end
163
+
164
+ attr_reader :orig_mid, :mdef, :def_ep
165
+
166
+ def do_send(recv, _mid, aargs, caller_ep, caller_env, scratch, &ctn)
167
+ @mdef.do_send(recv, @orig_mid, aargs, caller_ep, caller_env, scratch, &ctn)
168
+ end
169
+
170
+ def do_check_send(msig, recv, mid, ep, scratch)
171
+ @mdef.do_check_send(msig, recv, mid, ep, scratch)
172
+ end
173
+ end
174
+
153
175
  class AttrMethodDef < MethodDef
154
- def initialize(ivar, kind, absolute_path)
176
+ def initialize(ivar, kind, pub_meth, def_ep)
155
177
  @ivar = ivar
156
178
  @kind = kind # :reader | :writer
157
- @absolute_path = absolute_path
179
+ @pub_meth = pub_meth
180
+ @def_ep = def_ep
158
181
  end
159
182
 
160
- attr_reader :ivar, :kind, :absolute_path
183
+ attr_reader :ivar, :kind, :def_ep
161
184
 
162
185
  def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
163
186
  case @kind
164
187
  when :reader
165
188
  if aargs.lead_tys.size == 0
166
- scratch.get_instance_variable(recv, @ivar, caller_ep, caller_env) do |ty, nenv|
167
- ctn[ty, caller_ep, nenv]
189
+ scratch.add_ivar_read!(recv, @ivar, caller_ep) do |ty, _ep|
190
+ ctn[ty, caller_ep, caller_env]
168
191
  end
169
192
  else
170
193
  ctn[Type.any, caller_ep, caller_env]
@@ -182,9 +205,10 @@ module TypeProf
182
205
  end
183
206
 
184
207
  class TypedMethodDef < MethodDef
185
- def initialize(sig_rets, rbs_source) # sig_rets: Array<[MethodSignature, (return)Type]>
208
+ def initialize(sig_rets, rbs_source, pub_meth) # sig_rets: Array<[MethodSignature, (return)Type]>
186
209
  @sig_rets = sig_rets
187
210
  @rbs_source = rbs_source
211
+ @pub_meth = pub_meth
188
212
  end
189
213
 
190
214
  attr_reader :rbs_source
@@ -224,7 +248,7 @@ module TypeProf
224
248
  dummy_ep = ExecutionPoint.new(dummy_ctx, -1, caller_ep)
225
249
  s_recv = recv
226
250
  s_recv = s_recv.base_type while s_recv.respond_to?(:base_type)
227
- dummy_env = Env.new(StaticEnv.new(s_recv, msig.blk_ty, false), [], [], Utils::HashWrapper.new({}))
251
+ dummy_env = Env.new(StaticEnv.new(s_recv, msig.blk_ty, false, true), [], [], Utils::HashWrapper.new({}))
228
252
  if msig.blk_ty.is_a?(Type::Proc)
229
253
  scratch.add_callsite!(dummy_ctx, caller_ep, ncaller_env, &ctn)
230
254
  bsig = msig.blk_ty.block_body.msig
@@ -283,12 +307,12 @@ module TypeProf
283
307
  end
284
308
 
285
309
  class CustomMethodDef < MethodDef
286
- def initialize(impl)
310
+ def initialize(impl, pub_meth)
287
311
  @impl = impl
312
+ @pub_meth = pub_meth
288
313
  end
289
314
 
290
315
  def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
291
- scratch.merge_return_env(caller_ep) {|env| env ? env.merge(caller_env) : caller_env } # for Kernel#lambda
292
316
  @impl[recv, mid, aargs, caller_ep, caller_env, scratch, &ctn]
293
317
  end
294
318
  end
@@ -315,9 +315,14 @@ module TypeProf
315
315
  def globalize(env, visited, depth)
316
316
  return Type.any if depth <= 0
317
317
  tys = Utils::Set[]
318
- raise if @elems
318
+ if @elems
319
+ # XXX: If @elems is non nil, the Union type should global, so calling globalize against such a type should not occur.
320
+ # However, currently, ActualArguments may contain global types for flag_args_kw_splat case.
321
+ # This should be fixed in future in ActualArguments side. See Scratch#setup_actual_arguments.
322
+ #raise
323
+ end
319
324
 
320
- elems = {}
325
+ elems = @elems ? @elems.dup : {}
321
326
  @types.each do |ty|
322
327
  ty = ty.globalize(env, visited, depth - 1)
323
328
  case ty
@@ -435,17 +440,17 @@ module TypeProf
435
440
  end
436
441
 
437
442
  class Class < Type # or Module
438
- def initialize(kind, idx, type_params, superclass, superclass_type_args, name)
443
+ def initialize(kind, idx, type_params, superclass, name)
439
444
  @kind = kind # :class | :module
440
445
  @idx = idx
441
446
  @type_params = type_params
442
447
  @superclass = superclass
443
448
  raise if @kind == :class && !@superclass
444
- @superclass_type_args = superclass_type_args
445
449
  @_name = name
446
450
  end
447
451
 
448
- attr_reader :kind, :idx, :type_params, :superclass, :superclass_type_args
452
+ attr_reader :kind, :idx, :type_params, :superclass
453
+ attr_accessor :superclass_type_args
449
454
 
450
455
  def inspect
451
456
  if @_name
@@ -492,6 +497,8 @@ module TypeProf
492
497
  def initialize(klass)
493
498
  raise unless klass
494
499
  raise if klass == Type.any
500
+ raise if klass.is_a?(Type::Instance)
501
+ raise if klass.is_a?(Type::Union)
495
502
  @klass = klass
496
503
  end
497
504
 
@@ -682,6 +689,8 @@ module TypeProf
682
689
  Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:int]))
683
690
  when ::Rational
684
691
  Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:rational]))
692
+ when ::Complex
693
+ Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:complex]))
685
694
  when ::Float
686
695
  Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:float]))
687
696
  when ::Class
@@ -718,6 +727,8 @@ module TypeProf
718
727
  Type.nil
719
728
  when ::Range
720
729
  Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:range]))
730
+ when ::Encoding
731
+ Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:encoding]))
721
732
  else
722
733
  raise "unknown object: #{ obj.inspect }"
723
734
  end
@@ -770,31 +781,56 @@ module TypeProf
770
781
  class Signature
771
782
  include Utils::StructuralEquality
772
783
 
773
- def screen_name(scratch)
774
- str = @lead_tys.map {|ty| ty.screen_name(scratch) }
784
+ def screen_name(iseq, scratch)
785
+ fargs = @lead_tys.map {|ty| ty.screen_name(scratch) }
786
+ farg_names = []
787
+ farg_names += iseq.locals[0, @lead_tys.size] if iseq
775
788
  if @opt_tys
776
- str += @opt_tys.map {|ty| "?" + ty.screen_name(scratch) }
789
+ fargs += @opt_tys.map {|ty| "?" + ty.screen_name(scratch) }
790
+ farg_names += iseq.locals[@lead_tys.size, @opt_tys.size] if iseq
777
791
  end
778
792
  if @rest_ty
779
- str << ("*" + @rest_ty.screen_name(scratch))
793
+ fargs << ("*" + @rest_ty.screen_name(scratch))
794
+ if iseq
795
+ rest_index = iseq.fargs_format[:rest_start]
796
+ farg_names << (rest_index ? iseq.locals[rest_index] : nil)
797
+ end
780
798
  end
781
799
  if @post_tys
782
- str += @post_tys.map {|ty| ty.screen_name(scratch) }
800
+ fargs += @post_tys.map {|ty| ty.screen_name(scratch) }
801
+ if iseq
802
+ post_start = iseq.fargs_format[:post_start]
803
+ farg_names += (post_start ? iseq.locals[post_start, @post_tys.size] : [nil] * @post_tys.size)
804
+ end
783
805
  end
784
806
  if @kw_tys
785
807
  @kw_tys.each do |req, sym, ty|
786
808
  opt = req ? "" : "?"
787
- str << "#{ opt }#{ sym }: #{ ty.screen_name(scratch) }"
809
+ fargs << "#{ opt }#{ sym }: #{ ty.screen_name(scratch) }"
788
810
  end
789
811
  end
790
812
  if @kw_rest_ty
791
- str << ("**" + @kw_rest_ty.screen_name(scratch))
813
+ all_val_ty = Type.bot
814
+ @kw_rest_ty.each_child_global do |ty|
815
+ if ty == Type.any
816
+ val_ty = ty
817
+ else
818
+ # ty is a Type::Hash
819
+ _key_ty, val_ty = ty.elems.squash
820
+ end
821
+ all_val_ty = all_val_ty.union(val_ty)
822
+ end
823
+ fargs << ("**" + all_val_ty.screen_name(scratch))
792
824
  end
793
- str = str.empty? ? "" : "(#{ str.join(", ") })"
825
+ if Config.options[:show_parameter_names]
826
+ farg_names = farg_names.map {|name| name == :type ? :type_ : name } # XXX: workaround of RBS parser bug
827
+ fargs = fargs.zip(farg_names).map {|farg, name| name ? "#{ farg } #{ name }" : farg }
828
+ end
829
+ fargs = fargs.empty? ? "" : "(#{ fargs.join(", ") })"
794
830
 
795
831
  # Dirty Hack: Stop the iteration at most once!
796
832
  # I'll remove this hack if RBS removes the limitation of nesting blocks
797
- return str if caller_locations.any? {|frame| frame.label == "show_block_signature" }
833
+ return fargs if caller_locations.any? {|frame| frame.label == "show_block_signature" }
798
834
 
799
835
  optional = false
800
836
  blks = []
@@ -807,12 +843,12 @@ module TypeProf
807
843
  end
808
844
  end
809
845
  if blks != []
810
- str << " " if str != ""
811
- str << "?" if optional
812
- str << scratch.show_block_signature(blks)
846
+ fargs << " " if fargs != ""
847
+ fargs << "?" if optional
848
+ fargs << scratch.show_block_signature(blks)
813
849
  end
814
850
 
815
- str
851
+ fargs
816
852
  end
817
853
  end
818
854
 
@@ -820,12 +856,16 @@ module TypeProf
820
856
  def initialize(lead_tys, opt_tys, rest_ty, post_tys, kw_tys, kw_rest_ty, blk_ty)
821
857
  @lead_tys = lead_tys
822
858
  @opt_tys = opt_tys
859
+ raise unless opt_tys.is_a?(Array)
823
860
  @rest_ty = rest_ty
824
861
  @post_tys = post_tys
825
862
  raise unless post_tys
826
863
  @kw_tys = kw_tys
827
864
  kw_tys.each {|a| raise if a.size != 3 } if kw_tys
828
865
  @kw_rest_ty = kw_rest_ty
866
+ kw_rest_ty&.each_child_global do |ty|
867
+ raise ty.inspect if ty != Type.any && !ty.is_a?(Type::Hash)
868
+ end
829
869
  @blk_ty = blk_ty
830
870
  end
831
871
 
@@ -842,6 +882,44 @@ module TypeProf
842
882
  MethodSignature.new(lead_tys, opt_tys, rest_ty, post_tys, kw_tys, kw_rest_ty, blk_ty)
843
883
  end
844
884
 
885
+ def merge_as_block_arguments(other)
886
+ lead_tys1, opt_tys1, rest_ty1, post_tys1 = @lead_tys, @opt_tys, @rest_ty, @post_tys
887
+ lead_tys2, opt_tys2, rest_ty2, post_tys2 = other.lead_tys, other.opt_tys, other.rest_ty, other.post_tys
888
+
889
+ case
890
+ when lead_tys1.size > lead_tys2.size
891
+ n = lead_tys2.size
892
+ lead_tys1, opt_tys1 = lead_tys1[0, n], lead_tys1[n..] + opt_tys1
893
+ when lead_tys1.size < lead_tys2.size
894
+ n = lead_tys1.size
895
+ lead_tys2, opt_tys2 = lead_tys2[0, n], lead_tys2[n..] + opt_tys2
896
+ end
897
+ case
898
+ when post_tys1.size > post_tys2.size
899
+ i = post_tys1.size - post_tys2.size
900
+ if rest_ty1
901
+ rest_ty1 = post_tys[0, i].inject(rest_ty1) {|ty1, ty2| ty1.union(ty2) }
902
+ post_tys1 = post_tys1[i..]
903
+ else
904
+ opt_tys1, post_tys1 = opt_tys1 + post_tys1[0, i], post_tys1[i..]
905
+ end
906
+ when post_tys1.size < post_tys2.size
907
+ i = post_tys2.size - post_tys1.size
908
+ if rest_ty2
909
+ rest_ty2 = post_tys[0, i].inject(rest_ty2) {|ty1, ty2| ty1.union(ty2) }
910
+ post_tys2 = post_tys2[i..]
911
+ else
912
+ opt_tys2, post_tys2 = opt_tys2 + post_tys2[0, i], post_tys2[i..]
913
+ end
914
+ end
915
+
916
+ # XXX: tweak keywords too
917
+
918
+ msig1 = MethodSignature.new(lead_tys1, opt_tys1, rest_ty1, post_tys1, @kw_tys, @kw_rest_ty, @blk_ty)
919
+ msig2 = MethodSignature.new(lead_tys2, opt_tys2, rest_ty2, post_tys2, other.kw_tys, other.kw_rest_ty, other.blk_ty)
920
+ msig1.merge(msig2)
921
+ end
922
+
845
923
  def merge(other)
846
924
  raise if @lead_tys.size != other.lead_tys.size
847
925
  raise if @post_tys.size != other.post_tys.size