typeprof 0.8.0 → 0.11.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 (298) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +6 -5
  3. data/doc/demo.md +1 -1
  4. data/doc/todo.md +133 -0
  5. data/lib/typeprof/analyzer.rb +177 -76
  6. data/lib/typeprof/arguments.rb +2 -0
  7. data/lib/typeprof/block.rb +40 -2
  8. data/lib/typeprof/builtin.rb +279 -111
  9. data/lib/typeprof/cli.rb +5 -0
  10. data/lib/typeprof/config.rb +15 -1
  11. data/lib/typeprof/container-type.rb +5 -4
  12. data/lib/typeprof/export.rb +115 -70
  13. data/lib/typeprof/import.rb +71 -33
  14. data/lib/typeprof/iseq.rb +46 -11
  15. data/lib/typeprof/method.rb +42 -21
  16. data/lib/typeprof/type.rb +93 -15
  17. data/lib/typeprof/version.rb +1 -1
  18. data/smoke/alias.rb +4 -4
  19. data/smoke/alias2.rb +6 -4
  20. data/smoke/any1.rb +1 -1
  21. data/smoke/any2.rb +2 -2
  22. data/smoke/arguments.rb +2 -2
  23. data/smoke/arguments2.rb +10 -10
  24. data/smoke/array-each.rb +1 -1
  25. data/smoke/array-each2.rb +1 -1
  26. data/smoke/array-each3.rb +1 -1
  27. data/smoke/array-ltlt.rb +1 -1
  28. data/smoke/array-ltlt2.rb +1 -1
  29. data/smoke/array-map.rb +1 -1
  30. data/smoke/array-map2.rb +1 -1
  31. data/smoke/array-map3.rb +3 -3
  32. data/smoke/array-mul.rb +2 -2
  33. data/smoke/array-plus1.rb +1 -1
  34. data/smoke/array-plus2.rb +3 -2
  35. data/smoke/array-pop.rb +1 -1
  36. data/smoke/array-range-aref.rb +11 -11
  37. data/smoke/array-replace.rb +1 -1
  38. data/smoke/array-s-aref.rb +1 -1
  39. data/smoke/array1.rb +5 -5
  40. data/smoke/array10.rb +1 -1
  41. data/smoke/array11.rb +1 -1
  42. data/smoke/array12.rb +3 -3
  43. data/smoke/array13.rb +4 -4
  44. data/smoke/array14.rb +1 -1
  45. data/smoke/array15.rb +16 -0
  46. data/smoke/array2.rb +3 -3
  47. data/smoke/array3.rb +5 -4
  48. data/smoke/array4.rb +1 -1
  49. data/smoke/array5.rb +1 -1
  50. data/smoke/array6.rb +3 -2
  51. data/smoke/array7.rb +1 -1
  52. data/smoke/array8.rb +1 -1
  53. data/smoke/array9.rb +1 -1
  54. data/smoke/attr-module.rb +27 -0
  55. data/smoke/attr-vis.rb +43 -0
  56. data/smoke/attr-vis.rbs +4 -0
  57. data/smoke/attr.rb +5 -5
  58. data/smoke/autoload.rb +1 -1
  59. data/smoke/backtrace.rb +3 -3
  60. data/smoke/block-ambiguous.rb +8 -8
  61. data/smoke/block-args1-rest.rb +12 -11
  62. data/smoke/block-args1.rb +10 -10
  63. data/smoke/block-args2-rest.rb +12 -11
  64. data/smoke/block-args2.rb +10 -10
  65. data/smoke/block-args3-rest.rb +14 -13
  66. data/smoke/block-args3.rb +12 -12
  67. data/smoke/block-blockarg.rb +4 -4
  68. data/smoke/block-kwarg.rb +10 -10
  69. data/smoke/block1.rb +1 -1
  70. data/smoke/block10.rb +1 -1
  71. data/smoke/block11.rb +5 -5
  72. data/smoke/block12.rb +2 -2
  73. data/smoke/block14.rb +2 -2
  74. data/smoke/block2.rb +1 -1
  75. data/smoke/block3.rb +3 -3
  76. data/smoke/block4.rb +2 -2
  77. data/smoke/block5.rb +3 -2
  78. data/smoke/block6.rb +2 -2
  79. data/smoke/block7.rb +1 -1
  80. data/smoke/block8.rb +3 -3
  81. data/smoke/block9.rb +1 -1
  82. data/smoke/block_given.rb +37 -0
  83. data/smoke/blown.rb +1 -1
  84. data/smoke/break1.rb +2 -2
  85. data/smoke/break2.rb +1 -1
  86. data/smoke/break3.rb +13 -0
  87. data/smoke/case.rb +1 -1
  88. data/smoke/case2.rb +1 -1
  89. data/smoke/case3.rb +17 -0
  90. data/smoke/class-hierarchy.rb +5 -5
  91. data/smoke/class-hierarchy2.rb +3 -3
  92. data/smoke/class-new.rb +15 -0
  93. data/smoke/class_instance_var.rb +1 -1
  94. data/smoke/class_method.rb +2 -2
  95. data/smoke/class_method2.rb +2 -2
  96. data/smoke/class_method3.rb +2 -2
  97. data/smoke/constant1.rb +6 -6
  98. data/smoke/constant2.rb +5 -4
  99. data/smoke/constant3.rb +1 -1
  100. data/smoke/constant4.rb +1 -1
  101. data/smoke/context-sensitive1.rb +1 -1
  102. data/smoke/cvar.rb +6 -5
  103. data/smoke/cvar2.rb +2 -2
  104. data/smoke/define_method.rb +2 -2
  105. data/smoke/define_method2.rb +2 -2
  106. data/smoke/define_method3.rb +14 -0
  107. data/smoke/define_method3.rbs +3 -0
  108. data/smoke/define_method4.rb +15 -0
  109. data/smoke/define_method4.rbs +3 -0
  110. data/smoke/define_method5.rb +12 -0
  111. data/smoke/define_method6.rb +19 -0
  112. data/smoke/demo.rb +6 -6
  113. data/smoke/demo1.rb +1 -1
  114. data/smoke/demo10.rb +2 -2
  115. data/smoke/demo11.rb +1 -1
  116. data/smoke/demo2.rb +1 -1
  117. data/smoke/demo3.rb +1 -1
  118. data/smoke/demo4.rb +3 -3
  119. data/smoke/demo5.rb +1 -1
  120. data/smoke/demo6.rb +4 -3
  121. data/smoke/demo7.rb +1 -1
  122. data/smoke/demo8.rb +2 -2
  123. data/smoke/demo9.rb +3 -2
  124. data/smoke/dummy-execution1.rb +2 -2
  125. data/smoke/dummy-execution2.rb +2 -2
  126. data/smoke/dummy_element.rb +14 -0
  127. data/smoke/ensure1.rb +2 -2
  128. data/smoke/enum_for.rb +15 -0
  129. data/smoke/enum_for2.rb +17 -0
  130. data/smoke/enumerator.rb +2 -2
  131. data/smoke/expandarray1.rb +1 -1
  132. data/smoke/expandarray2.rb +1 -1
  133. data/smoke/fib.rb +2 -2
  134. data/smoke/flip-flop.rb +28 -0
  135. data/smoke/flow1.rb +1 -1
  136. data/smoke/flow10.rb +17 -0
  137. data/smoke/flow2.rb +1 -1
  138. data/smoke/flow3.rb +1 -1
  139. data/smoke/flow5.rb +1 -1
  140. data/smoke/flow6.rb +1 -1
  141. data/smoke/flow7.rb +1 -1
  142. data/smoke/flow8.rb +1 -1
  143. data/smoke/flow9.rb +12 -0
  144. data/smoke/freeze.rb +1 -1
  145. data/smoke/function.rb +2 -2
  146. data/smoke/gvar.rb +2 -2
  147. data/smoke/gvar2.rb +3 -3
  148. data/smoke/hash-bot.rb +12 -0
  149. data/smoke/hash-fetch.rb +3 -3
  150. data/smoke/hash-merge-bang.rb +1 -1
  151. data/smoke/hash1.rb +2 -2
  152. data/smoke/hash2.rb +1 -1
  153. data/smoke/hash3.rb +1 -1
  154. data/smoke/hash4.rb +1 -1
  155. data/smoke/hash5.rb +1 -1
  156. data/smoke/inheritance.rb +4 -4
  157. data/smoke/inheritance2.rb +2 -2
  158. data/smoke/initialize.rb +6 -5
  159. data/smoke/instance_eval.rb +2 -2
  160. data/smoke/instance_eval2.rb +10 -0
  161. data/smoke/instance_eval3.rb +25 -0
  162. data/smoke/int_times.rb +1 -1
  163. data/smoke/integer.rb +1 -1
  164. data/smoke/ivar.rb +5 -4
  165. data/smoke/ivar2.rb +4 -4
  166. data/smoke/ivar3.rb +4 -3
  167. data/smoke/ivar4.rb +21 -0
  168. data/smoke/kernel-class.rb +1 -1
  169. data/smoke/keyword1.rb +1 -1
  170. data/smoke/keyword2.rb +1 -1
  171. data/smoke/keyword3.rb +1 -1
  172. data/smoke/keyword4.rb +1 -1
  173. data/smoke/keyword5.rb +1 -1
  174. data/smoke/kwrest.rb +3 -2
  175. data/smoke/kwsplat1.rb +4 -4
  176. data/smoke/kwsplat2.rb +1 -1
  177. data/smoke/lit-complex.rb +10 -0
  178. data/smoke/lit-encoding.rb +10 -0
  179. data/smoke/manual-rbs.rb +5 -4
  180. data/smoke/manual-rbs2.rb +1 -1
  181. data/smoke/manual-rbs3.rb +3 -2
  182. data/smoke/masgn1.rb +1 -1
  183. data/smoke/masgn2.rb +2 -2
  184. data/smoke/masgn3.rb +1 -1
  185. data/smoke/method_in_branch.rb +3 -3
  186. data/smoke/method_missing.rb +5 -4
  187. data/smoke/module1.rb +2 -2
  188. data/smoke/module2.rb +1 -1
  189. data/smoke/module3.rb +3 -3
  190. data/smoke/module4.rb +3 -2
  191. data/smoke/module5.rb +17 -0
  192. data/smoke/module6.rb +40 -0
  193. data/smoke/module_function1.rb +4 -3
  194. data/smoke/module_function2.rb +4 -3
  195. data/smoke/multiple-include.rb +2 -1
  196. data/smoke/multiple-superclass.rb +1 -1
  197. data/smoke/next1.rb +2 -2
  198. data/smoke/next2.rb +1 -1
  199. data/smoke/object-send1.rb +3 -3
  200. data/smoke/object-send2.rb +10 -0
  201. data/smoke/object-send3.rb +18 -0
  202. data/smoke/once.rb +1 -1
  203. data/smoke/optional1.rb +1 -1
  204. data/smoke/optional2.rb +1 -1
  205. data/smoke/optional3.rb +1 -1
  206. data/smoke/parameterizedd-self.rb +3 -2
  207. data/smoke/parameterizedd-self2.rb +1 -1
  208. data/smoke/pathname1.rb +1 -1
  209. data/smoke/pathname2.rb +1 -1
  210. data/smoke/pattern-match1.rb +1 -1
  211. data/smoke/pattern-match2.rb +1 -1
  212. data/smoke/prepend1.rb +33 -0
  213. data/smoke/prepend2.rb +10 -0
  214. data/smoke/prepend2.rbs +9 -0
  215. data/smoke/primitive_method.rb +19 -0
  216. data/smoke/printf.rb +2 -2
  217. data/smoke/proc.rb +2 -2
  218. data/smoke/proc2.rb +1 -1
  219. data/smoke/proc3.rb +1 -1
  220. data/smoke/proc4.rb +1 -1
  221. data/smoke/proc5.rb +19 -0
  222. data/smoke/public.rb +38 -0
  223. data/smoke/range.rb +1 -1
  224. data/smoke/rbs-alias.rb +1 -1
  225. data/smoke/rbs-attr.rb +5 -5
  226. data/smoke/rbs-attr2.rb +1 -1
  227. data/smoke/rbs-extend.rb +1 -1
  228. data/smoke/rbs-interface.rb +4 -4
  229. data/smoke/rbs-module.rb +26 -0
  230. data/smoke/rbs-module.rbs +4 -0
  231. data/smoke/rbs-opt-and-rest.rb +10 -0
  232. data/smoke/rbs-opt-and-rest.rbs +3 -0
  233. data/smoke/rbs-proc1.rb +1 -1
  234. data/smoke/rbs-proc2.rb +2 -2
  235. data/smoke/rbs-proc3.rb +1 -1
  236. data/smoke/rbs-record.rb +2 -2
  237. data/smoke/rbs-tyvar.rb +2 -2
  238. data/smoke/rbs-tyvar2.rb +2 -2
  239. data/smoke/rbs-tyvar3.rb +2 -2
  240. data/smoke/rbs-tyvar4.rb +4 -3
  241. data/smoke/rbs-tyvar5.rb +1 -1
  242. data/smoke/rbs-tyvar6.rb +3 -3
  243. data/smoke/rbs-tyvar7.rb +1 -1
  244. data/smoke/rbs-vars.rb +6 -6
  245. data/smoke/redo1.rb +2 -2
  246. data/smoke/redo2.rb +2 -2
  247. data/smoke/req-keyword.rb +1 -1
  248. data/smoke/rescue1.rb +2 -2
  249. data/smoke/rescue2.rb +2 -2
  250. data/smoke/rescue3.rb +20 -0
  251. data/smoke/rescue4.rb +17 -0
  252. data/smoke/respond_to.rb +1 -1
  253. data/smoke/rest-farg.rb +1 -1
  254. data/smoke/rest1.rb +2 -2
  255. data/smoke/rest2.rb +1 -1
  256. data/smoke/rest3.rb +6 -6
  257. data/smoke/rest4.rb +2 -2
  258. data/smoke/rest5.rb +1 -1
  259. data/smoke/rest6.rb +1 -1
  260. data/smoke/retry1.rb +2 -2
  261. data/smoke/return.rb +1 -1
  262. data/smoke/simple.rb +12 -0
  263. data/smoke/singleton_method.rb +1 -1
  264. data/smoke/step.rb +3 -3
  265. data/smoke/string-split.rb +1 -1
  266. data/smoke/struct-keyword_init.rb +10 -0
  267. data/smoke/struct.rb +1 -1
  268. data/smoke/struct2.rb +4 -4
  269. data/smoke/struct3.rb +2 -2
  270. data/smoke/struct4.rb +7 -0
  271. data/smoke/struct5.rb +16 -0
  272. data/smoke/struct6.rb +15 -0
  273. data/smoke/struct7.rb +17 -0
  274. data/smoke/stub-keyword.rb +10 -0
  275. data/smoke/super1.rb +4 -4
  276. data/smoke/super2.rb +1 -1
  277. data/smoke/super3.rb +4 -3
  278. data/smoke/super4.rb +7 -5
  279. data/smoke/super5.rb +6 -4
  280. data/smoke/svar1.rb +1 -1
  281. data/smoke/symbol-proc-attr.rb +22 -0
  282. data/smoke/symbol-proc-attr2.rb +15 -0
  283. data/smoke/symbol-proc-bot.rb +13 -0
  284. data/smoke/symbol-proc.rb +3 -3
  285. data/smoke/tap1.rb +2 -2
  286. data/smoke/toplevel.rb +1 -1
  287. data/smoke/two-map.rb +2 -2
  288. data/smoke/type_var.rb +3 -3
  289. data/smoke/typed_method.rb +1 -1
  290. data/smoke/uninitialize-var.rb +1 -1
  291. data/smoke/union-recv.rb +2 -2
  292. data/smoke/user-demo.rb +3 -3
  293. data/smoke/wrong-extend.rb +3 -2
  294. data/smoke/wrong-include.rb +3 -2
  295. data/smoke/wrong-include2.rb +17 -0
  296. data/typeprof.gemspec +1 -1
  297. metadata +59 -6
  298. 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,5 +1,7 @@
1
1
  module TypeProf
2
2
  class MethodDef
3
+ attr_accessor :pub_meth
4
+
3
5
  include Utils::StructuralEquality
4
6
  end
5
7
 
@@ -12,8 +14,6 @@ module TypeProf
12
14
  @pub_meth = pub_meth
13
15
  end
14
16
 
15
- attr_accessor :pub_meth
16
-
17
17
  def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
18
18
  recv = recv.base_type while recv.respond_to?(:base_type)
19
19
  recv = scratch.globalize_type(recv, caller_env, caller_ep)
@@ -87,7 +87,7 @@ module TypeProf
87
87
  # XXX: need to check .rbs msig and .rb fargs
88
88
 
89
89
  ctx = Context.new(@iseq, @cref, mid)
90
- callee_ep = ExecutionPoint.new(ctx, 0, nil)
90
+ callee_ep = ExecutionPoint.new(ctx, 0, @outer_ep)
91
91
 
92
92
  locals = [Type.nil] * @iseq.locals.size
93
93
  nenv = Env.new(StaticEnv.new(recv, msig.blk_ty, false, true), locals, [], Utils::HashWrapper.new({}))
@@ -95,16 +95,15 @@ module TypeProf
95
95
  idx = 0
96
96
  msig.lead_tys.each_with_index do |ty, i|
97
97
  alloc_site2 = alloc_site.add_id(idx += 1)
98
- # nenv is top-level, so it is okay to call Type#localize directly
99
98
  ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
100
- nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
99
+ nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
101
100
  nenv = nenv.local_update(i, ty)
102
101
  end
103
102
  if msig.opt_tys
104
103
  msig.opt_tys.each_with_index do |ty, i|
105
104
  alloc_site2 = alloc_site.add_id(idx += 1)
106
105
  ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
107
- nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
106
+ nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
108
107
  nenv = nenv.local_update(lead_num + i, ty)
109
108
  end
110
109
  end
@@ -112,27 +111,27 @@ module TypeProf
112
111
  alloc_site2 = alloc_site.add_id(idx += 1)
113
112
  ty = Type::Array.new(Type::Array::Elements.new([], msig.rest_ty), Type::Instance.new(Type::Builtin[:ary]))
114
113
  ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
115
- 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)
116
115
  nenv = nenv.local_update(rest_start, rest_ty)
117
116
  end
118
117
  if msig.post_tys
119
118
  msig.post_tys.each_with_index do |ty, i|
120
119
  alloc_site2 = alloc_site.add_id(idx += 1)
121
120
  ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
122
- nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
121
+ nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
123
122
  nenv = nenv.local_update(post_start + i, ty)
124
123
  end
125
124
  end
126
- if msig.kw_tys
125
+ if msig.kw_tys && keyword # TODO: support the case where RBS writes kw_tys and RB method accepts **kwrest
127
126
  msig.kw_tys.each do |_, key, ty|
128
- i = keyword.index(key)
127
+ i = keyword.index {|callee_key,| callee_key == key }
129
128
  unless i
130
129
  # warn
131
130
  next
132
131
  end
133
132
  alloc_site2 = alloc_site.add_id(key)
134
133
  ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
135
- nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
134
+ nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
136
135
  nenv = nenv.local_update(kw_start + i, ty)
137
136
  end
138
137
  end
@@ -140,34 +139,55 @@ module TypeProf
140
139
  ty = msig.kw_rest_ty
141
140
  alloc_site2 = alloc_site.add_id(:**)
142
141
  ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
143
- nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
142
+ nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
144
143
  nenv = nenv.local_update(kw_rest, ty)
145
144
  end
146
145
  nenv = nenv.local_update(block_start, msig.blk_ty) if block_start
147
146
 
148
147
  opt.each do |start_pc|
149
- scratch.merge_env(ExecutionPoint.new(ctx, start_pc, nil), nenv)
148
+ scratch.merge_env(callee_ep.jump(start_pc), nenv)
150
149
  end
150
+ scratch.add_executed_iseq(@iseq)
151
151
 
152
152
  ctx
153
153
  end
154
154
  end
155
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
+
156
175
  class AttrMethodDef < MethodDef
157
- def initialize(ivar, kind, absolute_path)
176
+ def initialize(ivar, kind, pub_meth, def_ep)
158
177
  @ivar = ivar
159
178
  @kind = kind # :reader | :writer
160
- @absolute_path = absolute_path
179
+ @pub_meth = pub_meth
180
+ @def_ep = def_ep
161
181
  end
162
182
 
163
- attr_reader :ivar, :kind, :absolute_path
183
+ attr_reader :ivar, :kind, :def_ep
164
184
 
165
185
  def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
166
186
  case @kind
167
187
  when :reader
168
188
  if aargs.lead_tys.size == 0
169
- scratch.get_instance_variable(recv, @ivar, caller_ep, caller_env) do |ty, nenv|
170
- ctn[ty, caller_ep, nenv]
189
+ scratch.add_ivar_read!(recv, @ivar, caller_ep) do |ty, _ep|
190
+ ctn[ty, caller_ep, caller_env]
171
191
  end
172
192
  else
173
193
  ctn[Type.any, caller_ep, caller_env]
@@ -185,9 +205,10 @@ module TypeProf
185
205
  end
186
206
 
187
207
  class TypedMethodDef < MethodDef
188
- 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]>
189
209
  @sig_rets = sig_rets
190
210
  @rbs_source = rbs_source
211
+ @pub_meth = pub_meth
191
212
  end
192
213
 
193
214
  attr_reader :rbs_source
@@ -286,12 +307,12 @@ module TypeProf
286
307
  end
287
308
 
288
309
  class CustomMethodDef < MethodDef
289
- def initialize(impl)
310
+ def initialize(impl, pub_meth)
290
311
  @impl = impl
312
+ @pub_meth = pub_meth
291
313
  end
292
314
 
293
315
  def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
294
- scratch.merge_return_env(caller_ep) {|env| env ? env.merge(caller_env) : caller_env } # for Kernel#lambda
295
316
  @impl[recv, mid, aargs, caller_ep, caller_env, scratch, &ctn]
296
317
  end
297
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
@@ -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