typeprof 0.5.4 → 0.9.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 (289) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +7 -5
  3. data/doc/doc.ja.md +3 -4
  4. data/doc/doc.md +3 -4
  5. data/lib/typeprof/analyzer.rb +308 -171
  6. data/lib/typeprof/arguments.rb +14 -6
  7. data/lib/typeprof/block.rb +6 -2
  8. data/lib/typeprof/builtin.rb +230 -67
  9. data/lib/typeprof/cli.rb +33 -34
  10. data/lib/typeprof/config.rb +6 -4
  11. data/lib/typeprof/container-type.rb +159 -104
  12. data/lib/typeprof/export.rb +28 -22
  13. data/lib/typeprof/import.rb +70 -53
  14. data/lib/typeprof/iseq.rb +23 -7
  15. data/lib/typeprof/method.rb +71 -138
  16. data/lib/typeprof/type.rb +73 -15
  17. data/lib/typeprof/version.rb +1 -1
  18. data/smoke/alias.rb +5 -4
  19. data/smoke/alias2.rb +4 -4
  20. data/smoke/any1.rb +2 -1
  21. data/smoke/any2.rb +3 -2
  22. data/smoke/arguments.rb +3 -2
  23. data/smoke/arguments2.rb +11 -10
  24. data/smoke/array-each.rb +2 -1
  25. data/smoke/array-each2.rb +2 -1
  26. data/smoke/array-each3.rb +2 -1
  27. data/smoke/array-ltlt.rb +2 -1
  28. data/smoke/array-ltlt2.rb +2 -1
  29. data/smoke/array-map.rb +2 -1
  30. data/smoke/array-map2.rb +2 -1
  31. data/smoke/array-map3.rb +4 -3
  32. data/smoke/array-mul.rb +3 -2
  33. data/smoke/array-plus1.rb +2 -1
  34. data/smoke/array-plus2.rb +2 -2
  35. data/smoke/array-pop.rb +2 -1
  36. data/smoke/array-range-aref.rb +71 -0
  37. data/smoke/array-replace.rb +2 -1
  38. data/smoke/array-s-aref.rb +2 -1
  39. data/smoke/array1.rb +6 -5
  40. data/smoke/array10.rb +2 -1
  41. data/smoke/array11.rb +2 -1
  42. data/smoke/array12.rb +4 -3
  43. data/smoke/array13.rb +5 -4
  44. data/smoke/array14.rb +2 -1
  45. data/smoke/array15.rb +16 -0
  46. data/smoke/array2.rb +4 -3
  47. data/smoke/array3.rb +4 -4
  48. data/smoke/array4.rb +2 -1
  49. data/smoke/array5.rb +2 -1
  50. data/smoke/array6.rb +3 -2
  51. data/smoke/array7.rb +2 -1
  52. data/smoke/array8.rb +1 -1
  53. data/smoke/array9.rb +2 -1
  54. data/smoke/attr-module.rb +26 -0
  55. data/smoke/attr.rb +5 -5
  56. data/smoke/autoload.rb +14 -0
  57. data/smoke/backtrace.rb +4 -3
  58. data/smoke/block-ambiguous.rb +9 -8
  59. data/smoke/block-args1-rest.rb +12 -11
  60. data/smoke/block-args1.rb +11 -10
  61. data/smoke/block-args2-rest.rb +12 -11
  62. data/smoke/block-args2.rb +11 -10
  63. data/smoke/block-args3-rest.rb +14 -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 +3 -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/blown.rb +2 -1
  81. data/smoke/break1.rb +3 -2
  82. data/smoke/break2.rb +2 -1
  83. data/smoke/break3.rb +13 -0
  84. data/smoke/case.rb +2 -1
  85. data/smoke/case2.rb +2 -1
  86. data/smoke/case3.rb +17 -0
  87. data/smoke/class-hierarchy.rb +5 -5
  88. data/smoke/class-hierarchy2.rb +3 -3
  89. data/smoke/class-new.rb +15 -0
  90. data/smoke/class_instance_var.rb +1 -1
  91. data/smoke/class_method.rb +2 -2
  92. data/smoke/class_method2.rb +2 -2
  93. data/smoke/class_method3.rb +4 -2
  94. data/smoke/constant1.rb +6 -6
  95. data/smoke/constant2.rb +5 -4
  96. data/smoke/constant3.rb +2 -1
  97. data/smoke/constant4.rb +2 -1
  98. data/smoke/context-sensitive1.rb +2 -1
  99. data/smoke/cvar.rb +6 -5
  100. data/smoke/cvar2.rb +2 -2
  101. data/smoke/define_method.rb +16 -0
  102. data/smoke/define_method2.rb +18 -0
  103. data/smoke/define_method3.rb +13 -0
  104. data/smoke/define_method3.rbs +3 -0
  105. data/smoke/define_method4.rb +15 -0
  106. data/smoke/define_method4.rbs +3 -0
  107. data/smoke/define_method5.rb +12 -0
  108. data/smoke/demo.rb +7 -6
  109. data/smoke/demo1.rb +2 -1
  110. data/smoke/demo10.rb +3 -2
  111. data/smoke/demo11.rb +2 -1
  112. data/smoke/demo2.rb +2 -1
  113. data/smoke/demo3.rb +2 -1
  114. data/smoke/demo4.rb +3 -3
  115. data/smoke/demo5.rb +1 -1
  116. data/smoke/demo6.rb +3 -3
  117. data/smoke/demo7.rb +2 -1
  118. data/smoke/demo8.rb +3 -2
  119. data/smoke/demo9.rb +3 -2
  120. data/smoke/dummy-execution1.rb +3 -2
  121. data/smoke/dummy-execution2.rb +2 -2
  122. data/smoke/dummy_element.rb +14 -0
  123. data/smoke/ensure1.rb +3 -2
  124. data/smoke/enumerator.rb +3 -2
  125. data/smoke/expandarray1.rb +2 -1
  126. data/smoke/expandarray2.rb +2 -1
  127. data/smoke/fib.rb +2 -2
  128. data/smoke/flip-flop.rb +28 -0
  129. data/smoke/flow1.rb +2 -1
  130. data/smoke/flow2.rb +2 -1
  131. data/smoke/flow3.rb +2 -1
  132. data/smoke/flow5.rb +2 -1
  133. data/smoke/flow6.rb +2 -1
  134. data/smoke/flow7.rb +2 -1
  135. data/smoke/flow8.rb +2 -1
  136. data/smoke/flow9.rb +12 -0
  137. data/smoke/freeze.rb +2 -1
  138. data/smoke/function.rb +3 -2
  139. data/smoke/gvar.rb +3 -2
  140. data/smoke/gvar2.rb +3 -2
  141. data/smoke/hash-bot.rb +12 -0
  142. data/smoke/hash-fetch.rb +4 -3
  143. data/smoke/hash-merge-bang.rb +2 -1
  144. data/smoke/hash1.rb +3 -2
  145. data/smoke/hash2.rb +2 -1
  146. data/smoke/hash3.rb +2 -1
  147. data/smoke/hash4.rb +2 -1
  148. data/smoke/hash5.rb +1 -1
  149. data/smoke/inheritance.rb +4 -4
  150. data/smoke/inheritance2.rb +2 -2
  151. data/smoke/initialize.rb +6 -5
  152. data/smoke/instance_eval.rb +2 -2
  153. data/smoke/instance_eval2.rb +10 -0
  154. data/smoke/instance_eval3.rb +25 -0
  155. data/smoke/int_times.rb +2 -1
  156. data/smoke/integer.rb +2 -1
  157. data/smoke/ivar.rb +5 -4
  158. data/smoke/ivar2.rb +4 -4
  159. data/smoke/ivar3.rb +2 -2
  160. data/smoke/kernel-class.rb +2 -1
  161. data/smoke/keyword1.rb +2 -1
  162. data/smoke/keyword2.rb +2 -1
  163. data/smoke/keyword3.rb +2 -1
  164. data/smoke/keyword4.rb +2 -1
  165. data/smoke/keyword5.rb +2 -1
  166. data/smoke/kwrest.rb +12 -0
  167. data/smoke/kwrest.rbs +3 -0
  168. data/smoke/kwsplat1.rb +5 -4
  169. data/smoke/kwsplat2.rb +2 -1
  170. data/smoke/lit-complex.rb +10 -0
  171. data/smoke/lit-encoding.rb +10 -0
  172. data/smoke/manual-rbs.rb +4 -3
  173. data/smoke/manual-rbs2.rb +2 -1
  174. data/smoke/manual-rbs3.rb +2 -2
  175. data/smoke/masgn1.rb +2 -1
  176. data/smoke/masgn2.rb +3 -2
  177. data/smoke/masgn3.rb +2 -1
  178. data/smoke/method_in_branch.rb +3 -2
  179. data/smoke/method_missing.rb +28 -0
  180. data/smoke/module1.rb +2 -2
  181. data/smoke/module2.rb +1 -1
  182. data/smoke/module3.rb +2 -2
  183. data/smoke/module4.rb +2 -2
  184. data/smoke/module5.rb +17 -0
  185. data/smoke/module6.rb +40 -0
  186. data/smoke/module_function1.rb +3 -3
  187. data/smoke/module_function2.rb +3 -3
  188. data/smoke/multiple-include.rb +1 -1
  189. data/smoke/multiple-superclass.rb +1 -1
  190. data/smoke/next1.rb +3 -2
  191. data/smoke/next2.rb +2 -1
  192. data/smoke/object-send1.rb +4 -3
  193. data/smoke/object-send2.rb +10 -0
  194. data/smoke/object-send3.rb +18 -0
  195. data/smoke/once.rb +2 -1
  196. data/smoke/optional1.rb +2 -1
  197. data/smoke/optional2.rb +2 -1
  198. data/smoke/optional3.rb +2 -1
  199. data/smoke/parameterizedd-self.rb +3 -2
  200. data/smoke/parameterizedd-self2.rb +15 -0
  201. data/smoke/pathname1.rb +2 -1
  202. data/smoke/pathname2.rb +2 -1
  203. data/smoke/pattern-match1.rb +2 -1
  204. data/smoke/pattern-match2.rb +2 -1
  205. data/smoke/printf.rb +2 -2
  206. data/smoke/proc.rb +3 -2
  207. data/smoke/proc2.rb +2 -1
  208. data/smoke/proc3.rb +2 -1
  209. data/smoke/proc4.rb +2 -1
  210. data/smoke/proc5.rb +19 -0
  211. data/smoke/public.rb +34 -0
  212. data/smoke/range.rb +2 -1
  213. data/smoke/rbs-alias.rb +2 -1
  214. data/smoke/rbs-attr.rb +6 -5
  215. data/smoke/rbs-attr2.rb +11 -0
  216. data/smoke/rbs-attr2.rbs +3 -0
  217. data/smoke/rbs-extend.rb +2 -1
  218. data/smoke/rbs-interface.rb +5 -4
  219. data/smoke/rbs-module.rb +26 -0
  220. data/smoke/rbs-module.rbs +4 -0
  221. data/smoke/rbs-opt-and-rest.rb +10 -0
  222. data/smoke/rbs-opt-and-rest.rbs +3 -0
  223. data/smoke/rbs-proc1.rb +2 -1
  224. data/smoke/rbs-proc2.rb +3 -2
  225. data/smoke/rbs-proc3.rb +2 -1
  226. data/smoke/rbs-record.rb +3 -2
  227. data/smoke/rbs-tyvar.rb +3 -2
  228. data/smoke/rbs-tyvar2.rb +3 -2
  229. data/smoke/rbs-tyvar3.rb +3 -2
  230. data/smoke/rbs-tyvar4.rb +3 -3
  231. data/smoke/rbs-tyvar5.rb +2 -1
  232. data/smoke/rbs-tyvar6.rb +18 -0
  233. data/smoke/rbs-tyvar6.rbs +12 -0
  234. data/smoke/rbs-tyvar7.rb +12 -0
  235. data/smoke/rbs-tyvar7.rbs +7 -0
  236. data/smoke/rbs-vars.rb +7 -8
  237. data/smoke/redo1.rb +3 -2
  238. data/smoke/redo2.rb +3 -2
  239. data/smoke/req-keyword.rb +2 -1
  240. data/smoke/rescue1.rb +3 -2
  241. data/smoke/rescue2.rb +3 -2
  242. data/smoke/rescue3.rb +19 -0
  243. data/smoke/rescue4.rb +17 -0
  244. data/smoke/respond_to.rb +2 -1
  245. data/smoke/rest-farg.rb +2 -1
  246. data/smoke/rest1.rb +3 -2
  247. data/smoke/rest2.rb +2 -1
  248. data/smoke/rest3.rb +7 -6
  249. data/smoke/rest4.rb +3 -2
  250. data/smoke/rest5.rb +2 -1
  251. data/smoke/rest6.rb +2 -1
  252. data/smoke/retry1.rb +3 -2
  253. data/smoke/return.rb +2 -1
  254. data/smoke/singleton_method.rb +1 -1
  255. data/smoke/step.rb +4 -3
  256. data/smoke/string-split.rb +2 -1
  257. data/smoke/struct-keyword_init.rb +20 -0
  258. data/smoke/struct.rb +1 -1
  259. data/smoke/struct2.rb +5 -4
  260. data/smoke/struct3.rb +2 -2
  261. data/smoke/struct4.rb +7 -0
  262. data/smoke/struct5.rb +16 -0
  263. data/smoke/struct6.rb +15 -0
  264. data/smoke/struct7.rb +17 -0
  265. data/smoke/stub-keyword.rb +10 -0
  266. data/smoke/super1.rb +5 -4
  267. data/smoke/super2.rb +1 -1
  268. data/smoke/super3.rb +3 -3
  269. data/smoke/super4.rb +43 -0
  270. data/smoke/super5.rb +36 -0
  271. data/smoke/svar1.rb +2 -1
  272. data/smoke/symbol-proc-attr.rb +22 -0
  273. data/smoke/symbol-proc-attr2.rb +15 -0
  274. data/smoke/symbol-proc-bot.rb +13 -0
  275. data/smoke/symbol-proc.rb +4 -3
  276. data/smoke/tap1.rb +3 -2
  277. data/smoke/toplevel.rb +2 -1
  278. data/smoke/two-map.rb +3 -2
  279. data/smoke/type_var.rb +2 -1
  280. data/smoke/typed_method.rb +2 -1
  281. data/smoke/uninitialize-var.rb +2 -1
  282. data/smoke/union-recv.rb +2 -2
  283. data/smoke/user-demo.rb +3 -3
  284. data/smoke/wrong-extend.rb +2 -2
  285. data/smoke/wrong-include.rb +2 -2
  286. data/smoke/wrong-include2.rb +17 -0
  287. data/typeprof.gemspec +1 -1
  288. metadata +61 -6
  289. data/tools/stackprof-wrapper.rb +0 -10
@@ -72,7 +72,7 @@ module TypeProf
72
72
  gvars.dump.each do |gvar_name, entry|
73
73
  next if entry.type == Type.bot
74
74
  s = entry.rbs_declared ? "#" : ""
75
- output.puts s + "#{ gvar_name } : #{ entry.type.screen_name(scratch) }"
75
+ output.puts s + "#{ gvar_name }: #{ entry.type.screen_name(scratch) }"
76
76
  end
77
77
  output.puts
78
78
  end
@@ -91,9 +91,9 @@ module TypeProf
91
91
  def conv_class(namespace, class_def, inner_classes)
92
92
  @scratch.namespace = namespace
93
93
 
94
- if class_def.superclass
95
- omit = @class_defs[class_def.superclass].klass_obj == Type::Builtin[:obj] || class_def.klass_obj == Type::Builtin[:obj]
96
- superclass = omit ? nil : @scratch.get_class_name(@class_defs[class_def.superclass].klass_obj)
94
+ if class_def.klass_obj.superclass != :__root__ && class_def.klass_obj.superclass
95
+ omit = class_def.klass_obj.superclass == Type::Builtin[:obj] || class_def.klass_obj == Type::Builtin[:obj]
96
+ superclass = omit ? nil : @scratch.get_class_name(class_def.klass_obj.superclass)
97
97
  end
98
98
 
99
99
  @scratch.namespace = class_def.name
@@ -105,12 +105,12 @@ module TypeProf
105
105
  consts[name] = ty.screen_name(@scratch)
106
106
  end
107
107
 
108
- included_mods = class_def.modules[false].filter_map do |mod_def, absolute_paths|
108
+ included_mods = class_def.modules[false].filter_map do |mod_def, _type_args, absolute_paths|
109
109
  next if absolute_paths.all? {|path| !path || Config.check_dir_filter(path) == :exclude }
110
110
  Type::Instance.new(mod_def.klass_obj).screen_name(@scratch)
111
111
  end
112
112
 
113
- extended_mods = class_def.modules[true].filter_map do |mod_def, absolute_paths|
113
+ extended_mods = class_def.modules[true].filter_map do |mod_def, _type_args, absolute_paths|
114
114
  next if absolute_paths.all? {|path| !path || Config.check_dir_filter(path) == :exclude }
115
115
  Type::Instance.new(mod_def.klass_obj).screen_name(@scratch)
116
116
  end
@@ -135,11 +135,12 @@ module TypeProf
135
135
  method_name = ctx.mid
136
136
  method_name = "self.#{ method_name }" if singleton
137
137
 
138
- iseq_methods[method_name] ||= []
139
- iseq_methods[method_name] << @scratch.show_method_signature(ctx)
138
+ iseq_methods[method_name] ||= [true, []]
139
+ iseq_methods[method_name][0] &&= mdef.pub_meth
140
+ iseq_methods[method_name][1] << @scratch.show_method_signature(ctx)
140
141
  end
141
142
  when AttrMethodDef
142
- next if Config.check_dir_filter(mdef.absolute_path) == :exclude
143
+ next if !mdef.absolute_path || Config.check_dir_filter(mdef.absolute_path) == :exclude
143
144
  mid = mid.to_s[0..-2].to_sym if mid.to_s.end_with?("=")
144
145
  method_name = mid
145
146
  method_name = "self.#{ mid }" if singleton
@@ -168,12 +169,14 @@ module TypeProf
168
169
  next unless var.to_s.start_with?("@")
169
170
  var = "self.#{ var }" if singleton
170
171
  next if attr_methods[[singleton ? "self.#{ var.to_s[1..] }" : var.to_s[1..].to_sym, false]]
171
- [var, ty.screen_name(@scratch), entry.rbs_declared]
172
+ next if entry.rbs_declared
173
+ [var, ty.screen_name(@scratch)]
172
174
  end.compact
173
175
 
174
176
  cvars = cvars.map do |var, entry|
175
177
  next if entry.absolute_paths.all? {|path| Config.check_dir_filter(path) == :exclude }
176
- [var, entry.type.screen_name(@scratch), entry.rbs_declared]
178
+ next if entry.rbs_declared
179
+ [var, entry.type.screen_name(@scratch)]
177
180
  end.compact
178
181
 
179
182
  if !class_def.absolute_path || Config.check_dir_filter(class_def.absolute_path) == :exclude
@@ -266,7 +269,7 @@ module TypeProf
266
269
  output.puts indent + "#{ class_data.kind } #{ name }#{ superclass }"
267
270
  first = true
268
271
  class_data.consts.each do |name, ty|
269
- output.puts indent + " #{ name } : #{ ty }"
272
+ output.puts indent + " #{ name }: #{ ty }"
270
273
  first = false
271
274
  end
272
275
  class_data.included_mods.sort.each do |mod|
@@ -277,28 +280,31 @@ module TypeProf
277
280
  output.puts indent + " extend #{ mod }"
278
281
  first = false
279
282
  end
280
- class_data.ivars.each do |var, ty, rbs_declared|
281
- s = rbs_declared ? "# " : " "
282
- output.puts indent + s + "#{ var } : #{ ty }" unless var.start_with?("_")
283
+ class_data.ivars.each do |var, ty|
284
+ output.puts indent + " #{ var }: #{ ty }" unless var.start_with?("_")
283
285
  first = false
284
286
  end
285
- class_data.cvars.each do |var, ty, rbs_declared|
286
- s = rbs_declared ? "# " : " "
287
- output.puts indent + s + "#{ var } : #{ ty }"
287
+ class_data.cvars.each do |var, ty|
288
+ output.puts indent + " #{ var }: #{ ty }"
288
289
  first = false
289
290
  end
290
291
  class_data.attr_methods.each do |(method_name, hidden), (kind, ty)|
291
- output.puts indent + " attr_#{ kind } #{ method_name }#{ hidden ? "()" : "" } : #{ ty }"
292
+ output.puts indent + " attr_#{ kind } #{ method_name }#{ hidden ? "()" : "" }: #{ ty }"
292
293
  first = false
293
294
  end
294
295
  class_data.explicit_methods.each do |method_name, sigs|
295
296
  sigs = sigs.sort.join("\n" + indent + "#" + " " * (method_name.size + 6) + "| ")
296
- output.puts indent + "# def #{ method_name } : #{ sigs }"
297
+ output.puts indent + "# def #{ method_name }: #{ sigs }"
297
298
  first = false
298
299
  end
299
- class_data.iseq_methods.each do |method_name, sigs|
300
+ prev_pub_meth = true
301
+ class_data.iseq_methods.each do |method_name, (pub_meth, sigs)|
300
302
  sigs = sigs.sort.join("\n" + indent + " " * (method_name.size + 7) + "| ")
301
- output.puts indent + " def #{ method_name } : #{ sigs }"
303
+ if prev_pub_meth != pub_meth
304
+ output.puts indent + " #{ pub_meth ? "public" : "private" }"
305
+ prev_pub_meth = pub_meth
306
+ end
307
+ output.puts indent + " def #{ method_name }: #{ sigs }"
302
308
  first = false
303
309
  end
304
310
  show_class_hierarchy(depth + 1, class_data.inner_classes, output, first)
@@ -26,6 +26,13 @@ module TypeProf
26
26
  def load_library(lib)
27
27
  loader = RBS::EnvironmentLoader.new(core_root: nil)
28
28
  loader.add(library: lib)
29
+
30
+ case lib
31
+ when "yaml"
32
+ loader.add(library: "pstore")
33
+ loader.add(library: "dbm")
34
+ end
35
+
29
36
  new_decls = loader.load(env: @env).map {|decl,| decl }
30
37
  RBSReader.load_rbs(@env, new_decls)
31
38
  end
@@ -100,14 +107,19 @@ module TypeProf
100
107
  json = {}
101
108
 
102
109
  each_class_decl do |name, decls|
103
- super_class_name = get_super_class_name(name, decls)
104
110
  klass = conv_type_name(name)
105
- superclass = super_class_name ? conv_type_name(super_class_name) : nil
111
+ super_class_name, super_class_args = get_super_class(name, decls)
112
+ if super_class_name
113
+ name = conv_type_name(super_class_name)
114
+ type_args = super_class_args.map {|type| conv_type(type) }
115
+ superclass = [name, type_args]
116
+ end
106
117
 
107
118
  type_params = nil
108
119
  included_modules = []
109
120
  extended_modules = []
110
121
  methods = {}
122
+ attr_methods = {}
111
123
  ivars = {}
112
124
  cvars = {}
113
125
  rbs_sources = {}
@@ -143,15 +155,15 @@ module TypeProf
143
155
  end
144
156
  when RBS::AST::Members::AttrReader
145
157
  ty = conv_type(member.type)
146
- methods[[false, member.name]] = attr_reader_def(ty)
158
+ attr_methods[[false, member.name]] = attr_method_def(:reader, member.name, ty)
147
159
  when RBS::AST::Members::AttrWriter
148
160
  ty = conv_type(member.type)
149
- methods[[false, :"#{ member.name }="]] = attr_writer_def(ty)
161
+ attr_methods[[false, member.name]] = attr_method_def(:writer, member.name, ty)
150
162
  when RBS::AST::Members::AttrAccessor
151
163
  ty = conv_type(member.type)
152
- methods[[false, member.name]] = attr_reader_def(ty)
153
- methods[[false, :"#{ member.name }="]] = attr_writer_def(ty)
164
+ attr_methods[[false, member.name]] = attr_method_def(:accessor, member.name, ty)
154
165
  when RBS::AST::Members::Alias
166
+ # XXX: an alias to attr methods?
155
167
  if member.instance?
156
168
  method_def = methods[[false, member.old_name]]
157
169
  methods[[false, member.new_name]] = method_def if method_def
@@ -165,7 +177,8 @@ module TypeProf
165
177
  name = member.name
166
178
  if name.kind == :class
167
179
  mod = conv_type_name(name)
168
- included_modules << mod
180
+ type_args = member.args.map {|type| conv_type(type) }
181
+ included_modules << [mod, type_args]
169
182
  else
170
183
  # including an interface is not supported yet
171
184
  end
@@ -174,7 +187,8 @@ module TypeProf
174
187
  name = member.name
175
188
  if name.kind == :class
176
189
  mod = conv_type_name(name)
177
- extended_modules << mod
190
+ type_args = member.args.map {|type| conv_type(type) }
191
+ extended_modules << [mod, type_args]
178
192
  else
179
193
  # extending a module with an interface is not supported yet
180
194
  end
@@ -205,6 +219,7 @@ module TypeProf
205
219
  included_modules: included_modules,
206
220
  extended_modules: extended_modules,
207
221
  methods: methods,
222
+ attr_methods: attr_methods,
208
223
  ivars: ivars,
209
224
  cvars: cvars,
210
225
  rbs_sources: rbs_sources,
@@ -231,7 +246,7 @@ module TypeProf
231
246
  @all_env.class_decls[name].decls.each do |decl|
232
247
  decl = decl.decl
233
248
  next if decl.is_a?(RBS::AST::Declarations::Module)
234
- each_ancestor(decl) {|name| queue << [:visit, name] }
249
+ each_reference(decl) {|name| queue << [:visit, name] }
235
250
  end
236
251
  queue << [:visit, name.namespace.to_type_name] if !name.namespace.empty?
237
252
  end
@@ -246,24 +261,32 @@ module TypeProf
246
261
  end
247
262
  end
248
263
 
249
- def each_ancestor(decl, &blk)
264
+ def each_reference(decl, &blk)
250
265
  yield decl.name
251
- super_class = decl.super_class || RBS::BuiltinNames::Object
266
+ if decl.super_class
267
+ name = decl.super_class.name
268
+ else
269
+ name = RBS::BuiltinNames::Object.name
270
+ end
252
271
  return if decl.name == RBS::BuiltinNames::BasicObject.name
253
- return if decl.name == super_class.name
254
- @all_env.class_decls[super_class.name].decls.each do |decl|
255
- each_ancestor(decl.decl, &blk)
272
+ return if decl.name == name
273
+ decls = @all_env.class_decls[name]
274
+ if decls
275
+ decls.decls.each do |decl|
276
+ each_reference(decl.decl, &blk)
277
+ end
256
278
  end
257
279
  end
258
280
 
259
- def get_super_class_name(name, decls)
281
+ def get_super_class(name, decls)
260
282
  return nil if name == RBS::BuiltinNames::BasicObject.name
261
283
 
262
284
  decls.each do |decl|
263
285
  decl = decl.decl
264
286
  case decl
265
287
  when RBS::AST::Declarations::Class
266
- return decl.super_class.name if decl.super_class
288
+ super_class = decl.super_class
289
+ return super_class.name, super_class.args if super_class
267
290
  when RBS::AST::Declarations::Module, RBS::AST::Declarations::Interface
268
291
  return nil
269
292
  else
@@ -271,7 +294,7 @@ module TypeProf
271
294
  end
272
295
  end
273
296
 
274
- return RBS::BuiltinNames::Object.name
297
+ return RBS::BuiltinNames::Object.name, []
275
298
  end
276
299
 
277
300
  def conv_method_def(rbs_method_types)
@@ -290,7 +313,7 @@ module TypeProf
290
313
  opt_kw_tys = func.optional_keywords.to_h {|key, type| [key, conv_type(type.type)] }
291
314
  req_kw_tys = func.required_keywords.to_h {|key, type| [key, conv_type(type.type)] }
292
315
  rest_kw_ty = func.rest_keywords
293
- raise NotImplementedError if rest_kw_ty # XXX
316
+ rest_kw_ty = conv_type(rest_kw_ty.type) if rest_kw_ty
294
317
 
295
318
  ret_ty = conv_type(func.return_type)
296
319
 
@@ -307,32 +330,12 @@ module TypeProf
307
330
  }
308
331
  end
309
332
 
310
- def attr_reader_def(ty)
311
- [{
312
- type_params: [],
313
- lead_tys: [],
314
- opt_tys: [],
315
- rest_ty: nil,
316
- req_kw_tys: {},
317
- opt_kw_tys: {},
318
- rest_kw_ty: nil,
319
- blk: nil,
320
- ret_ty: ty,
321
- }]
322
- end
323
-
324
- def attr_writer_def(ty)
325
- [{
326
- type_params: [],
327
- lead_tys: [ty],
328
- opt_tys: [],
329
- rest_ty: nil,
330
- req_kw_tys: {},
331
- opt_kw_tys: {},
332
- rest_kw_ty: nil,
333
- blk: nil,
334
- ret_ty: ty,
335
- }]
333
+ def attr_method_def(kind, name, ty)
334
+ {
335
+ kind: kind,
336
+ ivar: name,
337
+ ty: ty,
338
+ }
336
339
  end
337
340
 
338
341
  def conv_block(rbs_block)
@@ -445,6 +448,8 @@ module TypeProf
445
448
  json = scratch.rbs_reader.load_library(feature)
446
449
  rescue RBS::EnvironmentLoader::UnknownLibraryError
447
450
  return nil
451
+ rescue RBS::DuplicatedDeclarationError
452
+ return true
448
453
  end
449
454
  # need cache?
450
455
  Import.new(scratch, json).import
@@ -467,8 +472,8 @@ module TypeProf
467
472
  def import(explicit = false)
468
473
  classes = @json[:classes].map do |classpath, cdef|
469
474
  type_params = cdef[:type_params]
470
- superclass = cdef[:superclass]
471
- members = cdef[:members]
475
+ superclass, superclass_type_args = cdef[:superclass]
476
+ members = cdef[:members]
472
477
 
473
478
  name = classpath.last
474
479
  superclass = path_to_klass(superclass) if superclass
@@ -492,23 +497,27 @@ module TypeProf
492
497
  end
493
498
  end
494
499
 
495
- [klass, members]
500
+ [klass, superclass_type_args, members]
496
501
  end
497
502
 
498
- classes.each do |klass, members|
503
+ classes.each do |klass, superclass_type_args, members|
504
+ @scratch.add_superclass_type_args!(klass, superclass_type_args&.map {|ty| conv_type(ty) })
499
505
  included_modules = members[:included_modules]
500
506
  extended_modules = members[:extended_modules]
501
507
  methods = members[:methods]
508
+ attr_methods = members[:attr_methods]
502
509
  ivars = members[:ivars]
503
510
  cvars = members[:cvars]
504
511
  rbs_sources = members[:rbs_sources]
505
512
 
506
- included_modules.each do |mod|
507
- @scratch.include_module(klass, path_to_klass(mod), false, nil)
513
+ included_modules.each do |mod, type_args|
514
+ type_args = type_args&.map {|ty| conv_type(ty) }
515
+ @scratch.include_module(klass, path_to_klass(mod), type_args, false, nil)
508
516
  end
509
517
 
510
- extended_modules.each do |mod|
511
- @scratch.include_module(klass, path_to_klass(mod), true, nil)
518
+ extended_modules.each do |mod, type_args|
519
+ type_args = type_args&.map {|ty| conv_type(ty) }
520
+ @scratch.include_module(klass, path_to_klass(mod), type_args, true, nil)
512
521
  end
513
522
 
514
523
  methods.each do |(singleton, method_name), mdef|
@@ -517,6 +526,14 @@ module TypeProf
517
526
  @scratch.add_method(klass, method_name, singleton, mdef)
518
527
  end
519
528
 
529
+ attr_methods.each do |(singleton, method_name), mdef|
530
+ kind = mdef[:kind]
531
+ ivar = mdef[:ivar]
532
+ ty = conv_type(mdef[:ty]).remove_type_vars
533
+ @scratch.add_attr_method(klass, nil, ivar, :"@#{ ivar }", kind)
534
+ @scratch.add_ivar_write!(Type::Instance.new(klass), :"@#{ ivar }", ty, nil)
535
+ end
536
+
520
537
  ivars.each do |ivar_name, ty|
521
538
  ty = conv_type(ty).remove_type_vars
522
539
  @scratch.add_ivar_write!(Type::Instance.new(klass), ivar_name, ty, nil)
@@ -583,7 +600,7 @@ module TypeProf
583
600
  req, lead_tys, opt_tys, ret_ty = blk
584
601
  lead_tys = lead_tys.map {|ty| conv_type(ty) }
585
602
  opt_tys = opt_tys.map {|ty| conv_type(ty) }
586
- msig = MethodSignature.new(lead_tys, opt_tys, nil, nil, nil, nil, nil)
603
+ msig = MethodSignature.new(lead_tys, opt_tys, nil, [], {}, nil, Type.nil)
587
604
  ret_ty = conv_type(ret_ty)
588
605
  ret = [Type::Proc.new(TypedBlock.new(msig, ret_ty), Type::Builtin[:proc])]
589
606
  ret << Type.nil unless req
@@ -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
@@ -209,7 +225,7 @@ module TypeProf
209
225
  end
210
226
  end
211
227
  send_branch_list.each do |i, j|
212
- next if (i + 1 .. j).any? {|i| branch_targets[i] }
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]
@@ -4,12 +4,16 @@ module TypeProf
4
4
  end
5
5
 
6
6
  class ISeqMethodDef < MethodDef
7
- def initialize(iseq, cref)
7
+ def initialize(iseq, cref, outer_ep, pub_meth)
8
8
  @iseq = iseq
9
9
  raise if iseq.nil?
10
10
  @cref = cref
11
+ @outer_ep = outer_ep
12
+ @pub_meth = pub_meth
11
13
  end
12
14
 
15
+ attr_accessor :pub_meth
16
+
13
17
  def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
14
18
  recv = recv.base_type while recv.respond_to?(:base_type)
15
19
  recv = scratch.globalize_type(recv, caller_env, caller_ep)
@@ -25,8 +29,8 @@ module TypeProf
25
29
  end
26
30
 
27
31
  nctx = Context.new(@iseq, @cref, mid)
28
- callee_ep = ExecutionPoint.new(nctx, 0, nil)
29
- nenv = Env.new(StaticEnv.new(recv, blk_ty, false), locals, [], Utils::HashWrapper.new({}))
32
+ callee_ep = ExecutionPoint.new(nctx, 0, @outer_ep)
33
+ nenv = Env.new(StaticEnv.new(recv, blk_ty, false, true), locals, [], Utils::HashWrapper.new({}))
30
34
  alloc_site = AllocationSite.new(callee_ep)
31
35
  locals.each_with_index do |ty, i|
32
36
  alloc_site2 = alloc_site.add_id(i)
@@ -44,6 +48,14 @@ module TypeProf
44
48
  end
45
49
 
46
50
  def do_check_send(msig, recv, mid, ep, scratch)
51
+ klass, singleton = recv.method_dispatch_info
52
+ cur_subst = {}
53
+ direct_method = true
54
+ scratch.adjust_substitution(klass, singleton, mid, self, recv.generate_substitution) do |subst, direct|
55
+ direct_method &&= direct
56
+ cur_subst = Type.merge_substitution(cur_subst, subst)
57
+ end
58
+
47
59
  lead_num = @iseq.fargs_format[:lead_num] || 0
48
60
  post_num = @iseq.fargs_format[:post_num] || 0
49
61
  rest_start = @iseq.fargs_format[:rest_start]
@@ -67,63 +79,75 @@ module TypeProf
67
79
  post_start = @iseq.fargs_format[:post_start]
68
80
  rest_start = @iseq.fargs_format[:rest_start]
69
81
  kw_start = @iseq.fargs_format[:kwbits]
70
- kw_start -= @iseq.fargs_format[:keyword].size if kw_start
82
+ keyword = @iseq.fargs_format[:keyword]
83
+ kw_start -= keyword.size if kw_start
71
84
  kw_rest = @iseq.fargs_format[:kwrest]
72
85
  block_start = @iseq.fargs_format[:block_start]
73
86
 
74
87
  # XXX: need to check .rbs msig and .rb fargs
75
88
 
76
89
  ctx = Context.new(@iseq, @cref, mid)
77
- callee_ep = ExecutionPoint.new(ctx, 0, nil)
90
+ callee_ep = ExecutionPoint.new(ctx, 0, @outer_ep)
78
91
 
79
92
  locals = [Type.nil] * @iseq.locals.size
80
- 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({}))
81
94
  alloc_site = AllocationSite.new(callee_ep)
82
95
  idx = 0
83
96
  msig.lead_tys.each_with_index do |ty, i|
84
97
  alloc_site2 = alloc_site.add_id(idx += 1)
85
- # nenv is top-level, so it is okay to call Type#localize directly
86
- nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
98
+ ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
99
+ nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
87
100
  nenv = nenv.local_update(i, ty)
88
101
  end
89
102
  if msig.opt_tys
90
103
  msig.opt_tys.each_with_index do |ty, i|
91
104
  alloc_site2 = alloc_site.add_id(idx += 1)
92
- nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
105
+ ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
106
+ nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
93
107
  nenv = nenv.local_update(lead_num + i, ty)
94
108
  end
95
109
  end
96
110
  if msig.rest_ty
97
111
  alloc_site2 = alloc_site.add_id(idx += 1)
98
112
  ty = Type::Array.new(Type::Array::Elements.new([], msig.rest_ty), Type::Instance.new(Type::Builtin[:ary]))
99
- nenv, rest_ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
113
+ ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
114
+ nenv, rest_ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
100
115
  nenv = nenv.local_update(rest_start, rest_ty)
101
116
  end
102
117
  if msig.post_tys
103
118
  msig.post_tys.each_with_index do |ty, i|
104
119
  alloc_site2 = alloc_site.add_id(idx += 1)
105
- nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
120
+ ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
121
+ nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
106
122
  nenv = nenv.local_update(post_start + i, ty)
107
123
  end
108
124
  end
109
- if msig.kw_tys
110
- msig.kw_tys.each_with_index do |(_, key, ty), i|
125
+ if msig.kw_tys && keyword # TODO: support the case where RBS writes kw_tys and RB method accepts **kwrest
126
+ msig.kw_tys.each do |_, key, ty|
127
+ i = keyword.index {|callee_key,| callee_key == key }
128
+ unless i
129
+ # warn
130
+ next
131
+ end
111
132
  alloc_site2 = alloc_site.add_id(key)
112
- nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
133
+ ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
134
+ nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
113
135
  nenv = nenv.local_update(kw_start + i, ty)
114
136
  end
115
137
  end
116
138
  if msig.kw_rest_ty
117
139
  ty = msig.kw_rest_ty
118
140
  alloc_site2 = alloc_site.add_id(:**)
119
- nenv, ty = ty.localize(nenv, alloc_site2, Config.options[:type_depth_limit])
141
+ ty = ty.substitute(cur_subst, Config.options[:type_depth_limit]).remove_type_vars
142
+ nenv, ty = scratch.localize_type(ty, nenv, callee_ep, alloc_site2)
120
143
  nenv = nenv.local_update(kw_rest, ty)
121
144
  end
122
145
  nenv = nenv.local_update(block_start, msig.blk_ty) if block_start
123
146
 
124
147
  opt.each do |start_pc|
125
- scratch.merge_env(ExecutionPoint.new(ctx, start_pc, nil), nenv)
148
+ scratch.merge_env(callee_ep.jump(start_pc), nenv)
126
149
  end
150
+ scratch.add_executed_iseq(@iseq)
127
151
 
128
152
  ctx
129
153
  end
@@ -142,8 +166,8 @@ module TypeProf
142
166
  case @kind
143
167
  when :reader
144
168
  if aargs.lead_tys.size == 0
145
- scratch.get_instance_variable(recv, @ivar, caller_ep, caller_env) do |ty, nenv|
146
- ctn[ty, caller_ep, nenv]
169
+ scratch.add_ivar_read!(recv, @ivar, caller_ep) do |ty, _ep|
170
+ ctn[ty, caller_ep, caller_env]
147
171
  end
148
172
  else
149
173
  ctn[Type.any, caller_ep, caller_env]
@@ -170,6 +194,15 @@ module TypeProf
170
194
 
171
195
  def do_send(recv_orig, mid, aargs, caller_ep, caller_env, scratch, &ctn)
172
196
  recv = scratch.globalize_type(recv_orig, caller_env, caller_ep)
197
+
198
+ klass, singleton = recv_orig.method_dispatch_info
199
+ cur_subst = {}
200
+ direct_method = true
201
+ scratch.adjust_substitution(klass, singleton, mid, self, recv.generate_substitution) do |subst, direct|
202
+ direct_method &&= direct
203
+ cur_subst = Type.merge_substitution(cur_subst, subst)
204
+ end
205
+
173
206
  found = false
174
207
  aargs = scratch.globalize_type(aargs, caller_env, caller_ep)
175
208
  @sig_rets.each do |msig, ret_ty|
@@ -178,56 +211,15 @@ module TypeProf
178
211
  # XXX: support self type in msig
179
212
  subst = aargs.consistent_with_method_signature?(msig)
180
213
  next unless subst
214
+
215
+ if direct_method && recv_orig.is_a?(Type::Local)
216
+ ncaller_env = recv_orig.update_container_elem_type(subst, ncaller_env, caller_ep, scratch)
217
+ end
218
+
219
+ subst = Type.merge_substitution(subst, cur_subst)
181
220
  # need to check self tyvar?
182
221
  subst[Type::Var.new(:self)] = recv
183
- case
184
- when recv.is_a?(Type::Cell) && recv_orig.is_a?(Type::LocalCell)
185
- tyvars = recv.base_type.klass.type_params.map {|name,| Type::Var.new(name) }
186
- tyvars.each_with_index do |tyvar, idx|
187
- ty = subst[tyvar]
188
- if ty
189
- ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
190
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
191
- elems.update(idx, ty)
192
- end
193
- end
194
- end
195
- tyvars.zip(recv.elems.elems) do |tyvar, elem|
196
- if subst[tyvar]
197
- subst[tyvar] = subst[tyvar].union(elem)
198
- else
199
- subst[tyvar] = elem
200
- end
201
- end
202
- when recv.is_a?(Type::Array) && recv_orig.is_a?(Type::LocalArray)
203
- tyvar_elem = Type::Var.new(:Elem)
204
- if subst[tyvar_elem]
205
- ty = subst[tyvar_elem]
206
- ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
207
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
208
- elems.update(nil, ty)
209
- end
210
- end
211
- subst.merge!({ tyvar_elem => recv.elems.squash })
212
- when recv.is_a?(Type::Hash) && recv_orig.is_a?(Type::LocalHash)
213
- tyvar_k = Type::Var.new(:K)
214
- tyvar_v = Type::Var.new(:V)
215
- k_ty0, v_ty0 = recv.elems.squash
216
- if subst[tyvar_k] && subst[tyvar_v]
217
- k_ty = subst[tyvar_k]
218
- v_ty = subst[tyvar_v]
219
- k_ty0 = k_ty0.union(k_ty)
220
- v_ty0 = v_ty0.union(v_ty)
221
- alloc_site = AllocationSite.new(caller_ep)
222
- ncaller_env, k_ty = scratch.localize_type(k_ty, ncaller_env, caller_ep, alloc_site.add_id(:k))
223
- ncaller_env, v_ty = scratch.localize_type(v_ty, ncaller_env, caller_ep, alloc_site.add_id(:v))
224
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
225
- elems.update(k_ty, v_ty)
226
- end
227
- end
228
- # XXX: need to heuristically replace ret type Hash[K, V] with self, instead of conversative type?
229
- subst.merge!({ tyvar_k => k_ty0, tyvar_v => v_ty0 })
230
- end
222
+
231
223
  found = true
232
224
  if aargs.blk_ty.is_a?(Type::Proc)
233
225
  #raise NotImplementedError unless aargs.blk_ty.block_body.is_a?(ISeqBlock) # XXX
@@ -235,91 +227,33 @@ module TypeProf
235
227
  dummy_ep = ExecutionPoint.new(dummy_ctx, -1, caller_ep)
236
228
  s_recv = recv
237
229
  s_recv = s_recv.base_type while s_recv.respond_to?(:base_type)
238
- dummy_env = Env.new(StaticEnv.new(s_recv, msig.blk_ty, false), [], [], Utils::HashWrapper.new({}))
230
+ dummy_env = Env.new(StaticEnv.new(s_recv, msig.blk_ty, false, true), [], [], Utils::HashWrapper.new({}))
239
231
  if msig.blk_ty.is_a?(Type::Proc)
240
232
  scratch.add_callsite!(dummy_ctx, caller_ep, ncaller_env, &ctn)
241
- nfargs = msig.blk_ty.block_body.msig
233
+ bsig = msig.blk_ty.block_body.msig
242
234
  alloc_site = AllocationSite.new(caller_ep).add_id(self)
243
- nlead_tys = (nfargs.lead_tys + nfargs.opt_tys).map.with_index do |ty, i|
244
- if recv.is_a?(Type::Array)
245
- tyvar_elem = Type::Var.new(:Elem)
246
- ty = ty.substitute(subst.merge({ tyvar_elem => recv.elems.squash_or_any }), Config.options[:type_depth_limit])
247
- else
248
- ty = ty.substitute(subst, Config.options[:type_depth_limit])
249
- end
250
- ty = ty.remove_type_vars
251
- alloc_site2 = alloc_site.add_id(i)
252
- dummy_env, ty = scratch.localize_type(ty, dummy_env, dummy_ep, alloc_site2)
235
+ nlead_tys = (bsig.lead_tys + bsig.opt_tys).map.with_index do |ty, i|
236
+ ty = ty.substitute(subst, Config.options[:type_depth_limit]).remove_type_vars
237
+ dummy_env, ty = scratch.localize_type(ty, dummy_env, dummy_ep, alloc_site.add_id(i))
253
238
  ty
254
239
  end
255
- 0.upto(nfargs.opt_tys.size) do |n|
256
- naargs = ActualArguments.new(nlead_tys[0, nfargs.lead_tys.size + n], nil, {}, Type.nil) # XXX: support block to block?
240
+ 0.upto(bsig.opt_tys.size) do |n|
241
+ naargs = ActualArguments.new(nlead_tys[0, bsig.lead_tys.size + n], nil, {}, Type.nil) # XXX: support block to block?
257
242
  scratch.do_invoke_block(aargs.blk_ty, naargs, dummy_ep, dummy_env) do |blk_ret_ty, _ep, _env|
258
243
  subst2 = Type.match?(blk_ret_ty, msig.blk_ty.block_body.ret_ty)
259
244
  if subst2
260
245
  subst2 = Type.merge_substitution(subst, subst2)
261
- case
262
- when recv.is_a?(Type::Cell) && recv_orig.is_a?(Type::LocalCell)
263
- tyvars = recv.base_type.klass.type_params.map {|name,| Type::Var.new(name) }
264
- tyvars.each_with_index do |tyvar, idx|
265
- ty = subst2[tyvar]
266
- if ty
267
- ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
268
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
269
- elems.update(idx, ty)
270
- end
271
- scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
272
- end
273
- end
274
- tyvars.zip(recv.elems.elems) do |tyvar, elem|
275
- if subst2[tyvar]
276
- subst2[tyvar] = subst2[tyvar].union(elem)
277
- else
278
- subst2[tyvar] = elem
279
- end
280
- end
281
- ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
282
- when recv.is_a?(Type::Array) && recv_orig.is_a?(Type::LocalArray)
283
- tyvar_elem = Type::Var.new(:Elem)
284
- if subst2[tyvar_elem]
285
- ty = subst2[tyvar_elem]
286
- ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
287
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
288
- elems.update(nil, ty)
289
- end
290
- scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
291
- end
292
- ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
293
- when recv.is_a?(Type::Hash) && recv_orig.is_a?(Type::LocalHash)
294
- tyvar_k = Type::Var.new(:K)
295
- tyvar_v = Type::Var.new(:V)
296
- k_ty0, v_ty0 = recv.elems.squash
297
- if subst2[tyvar_k] && subst2[tyvar_v]
298
- k_ty = subst2[tyvar_k]
299
- v_ty = subst2[tyvar_v]
300
- k_ty0 = k_ty0.union(k_ty)
301
- v_ty0 = v_ty0.union(v_ty)
302
- alloc_site = AllocationSite.new(caller_ep)
303
- ncaller_env, k_ty = scratch.localize_type(k_ty, ncaller_env, caller_ep, alloc_site.add_id(:k))
304
- ncaller_env, v_ty = scratch.localize_type(v_ty, ncaller_env, caller_ep, alloc_site.add_id(:v))
305
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
306
- elems.update(k_ty, v_ty)
307
- end
308
- scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
309
- end
310
- ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
311
- else
312
- ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
246
+ if direct_method && recv_orig.is_a?(Type::Local)
247
+ ncaller_env = recv_orig.update_container_elem_type(subst2, ncaller_env, caller_ep, scratch)
248
+ scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
313
249
  end
250
+ ret_ty2 = ret_ty.substitute(subst2, Config.options[:type_depth_limit]).remove_type_vars
314
251
  else
315
- # raise "???"
316
- # XXX: need warning
317
- ret_ty = Type.any
252
+ ret_ty2 = Type.any
318
253
  end
319
- ret_ty = ret_ty.remove_type_vars
320
254
  # XXX: check the return type from the block
321
255
  # sig.blk_ty.block_body.ret_ty.eql?(_ret_ty) ???
322
- scratch.add_return_value!(dummy_ctx, ret_ty)
256
+ scratch.add_return_value!(dummy_ctx, ret_ty2)
323
257
  end
324
258
  # scratch.add_return_value!(dummy_ctx, ret_ty) ?
325
259
  # This makes `def foo; 1.times { return "str" }; end` return Integer|String
@@ -357,7 +291,6 @@ module TypeProf
357
291
  end
358
292
 
359
293
  def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
360
- scratch.merge_return_env(caller_ep) {|env| env ? env.merge(caller_env) : caller_env } # for Kernel#lambda
361
294
  @impl[recv, mid, aargs, caller_ep, caller_env, scratch, &ctn]
362
295
  end
363
296
  end