typeprof 0.6.0 → 0.9.1

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 +214 -133
  6. data/lib/typeprof/arguments.rb +14 -6
  7. data/lib/typeprof/block.rb +6 -2
  8. data/lib/typeprof/builtin.rb +223 -71
  9. data/lib/typeprof/cli.rb +33 -34
  10. data/lib/typeprof/config.rb +6 -4
  11. data/lib/typeprof/container-type.rb +154 -99
  12. data/lib/typeprof/export.rb +23 -17
  13. data/lib/typeprof/import.rb +49 -42
  14. data/lib/typeprof/iseq.rb +23 -7
  15. data/lib/typeprof/method.rb +63 -147
  16. data/lib/typeprof/type.rb +63 -7
  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/ivar4.rb +20 -0
  161. data/smoke/kernel-class.rb +2 -1
  162. data/smoke/keyword1.rb +2 -1
  163. data/smoke/keyword2.rb +2 -1
  164. data/smoke/keyword3.rb +2 -1
  165. data/smoke/keyword4.rb +2 -1
  166. data/smoke/keyword5.rb +2 -1
  167. data/smoke/kwrest.rb +12 -0
  168. data/smoke/kwrest.rbs +3 -0
  169. data/smoke/kwsplat1.rb +5 -4
  170. data/smoke/kwsplat2.rb +2 -1
  171. data/smoke/lit-complex.rb +10 -0
  172. data/smoke/lit-encoding.rb +10 -0
  173. data/smoke/manual-rbs.rb +4 -3
  174. data/smoke/manual-rbs2.rb +2 -1
  175. data/smoke/manual-rbs3.rb +2 -2
  176. data/smoke/masgn1.rb +2 -1
  177. data/smoke/masgn2.rb +3 -2
  178. data/smoke/masgn3.rb +2 -1
  179. data/smoke/method_in_branch.rb +3 -2
  180. data/smoke/method_missing.rb +28 -0
  181. data/smoke/module1.rb +2 -2
  182. data/smoke/module2.rb +1 -1
  183. data/smoke/module3.rb +2 -2
  184. data/smoke/module4.rb +2 -2
  185. data/smoke/module5.rb +17 -0
  186. data/smoke/module6.rb +40 -0
  187. data/smoke/module_function1.rb +3 -3
  188. data/smoke/module_function2.rb +3 -3
  189. data/smoke/multiple-include.rb +1 -1
  190. data/smoke/multiple-superclass.rb +1 -1
  191. data/smoke/next1.rb +3 -2
  192. data/smoke/next2.rb +2 -1
  193. data/smoke/object-send1.rb +4 -3
  194. data/smoke/object-send2.rb +10 -0
  195. data/smoke/object-send3.rb +18 -0
  196. data/smoke/once.rb +2 -1
  197. data/smoke/optional1.rb +2 -1
  198. data/smoke/optional2.rb +2 -1
  199. data/smoke/optional3.rb +2 -1
  200. data/smoke/parameterizedd-self.rb +3 -2
  201. data/smoke/parameterizedd-self2.rb +1 -1
  202. data/smoke/pathname1.rb +2 -1
  203. data/smoke/pathname2.rb +2 -1
  204. data/smoke/pattern-match1.rb +2 -1
  205. data/smoke/pattern-match2.rb +2 -1
  206. data/smoke/printf.rb +2 -2
  207. data/smoke/proc.rb +3 -2
  208. data/smoke/proc2.rb +2 -1
  209. data/smoke/proc3.rb +2 -1
  210. data/smoke/proc4.rb +2 -1
  211. data/smoke/proc5.rb +19 -0
  212. data/smoke/public.rb +34 -0
  213. data/smoke/range.rb +2 -1
  214. data/smoke/rbs-alias.rb +2 -1
  215. data/smoke/rbs-attr.rb +6 -5
  216. data/smoke/rbs-attr2.rb +11 -0
  217. data/smoke/rbs-attr2.rbs +3 -0
  218. data/smoke/rbs-extend.rb +2 -1
  219. data/smoke/rbs-interface.rb +5 -4
  220. data/smoke/rbs-module.rb +26 -0
  221. data/smoke/rbs-module.rbs +4 -0
  222. data/smoke/rbs-opt-and-rest.rb +10 -0
  223. data/smoke/rbs-opt-and-rest.rbs +3 -0
  224. data/smoke/rbs-proc1.rb +2 -1
  225. data/smoke/rbs-proc2.rb +3 -2
  226. data/smoke/rbs-proc3.rb +2 -1
  227. data/smoke/rbs-record.rb +3 -2
  228. data/smoke/rbs-tyvar.rb +3 -2
  229. data/smoke/rbs-tyvar2.rb +3 -2
  230. data/smoke/rbs-tyvar3.rb +3 -2
  231. data/smoke/rbs-tyvar4.rb +3 -3
  232. data/smoke/rbs-tyvar5.rb +2 -1
  233. data/smoke/rbs-tyvar6.rb +4 -3
  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 +5 -5
  270. data/smoke/super5.rb +4 -4
  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 +56 -5
  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
@@ -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
@@ -112,6 +119,7 @@ module TypeProf
112
119
  included_modules = []
113
120
  extended_modules = []
114
121
  methods = {}
122
+ attr_methods = {}
115
123
  ivars = {}
116
124
  cvars = {}
117
125
  rbs_sources = {}
@@ -147,15 +155,15 @@ module TypeProf
147
155
  end
148
156
  when RBS::AST::Members::AttrReader
149
157
  ty = conv_type(member.type)
150
- methods[[false, member.name]] = attr_reader_def(ty)
158
+ attr_methods[[false, member.name]] = attr_method_def(:reader, member.name, ty)
151
159
  when RBS::AST::Members::AttrWriter
152
160
  ty = conv_type(member.type)
153
- methods[[false, :"#{ member.name }="]] = attr_writer_def(ty)
161
+ attr_methods[[false, member.name]] = attr_method_def(:writer, member.name, ty)
154
162
  when RBS::AST::Members::AttrAccessor
155
163
  ty = conv_type(member.type)
156
- methods[[false, member.name]] = attr_reader_def(ty)
157
- methods[[false, :"#{ member.name }="]] = attr_writer_def(ty)
164
+ attr_methods[[false, member.name]] = attr_method_def(:accessor, member.name, ty)
158
165
  when RBS::AST::Members::Alias
166
+ # XXX: an alias to attr methods?
159
167
  if member.instance?
160
168
  method_def = methods[[false, member.old_name]]
161
169
  methods[[false, member.new_name]] = method_def if method_def
@@ -211,6 +219,7 @@ module TypeProf
211
219
  included_modules: included_modules,
212
220
  extended_modules: extended_modules,
213
221
  methods: methods,
222
+ attr_methods: attr_methods,
214
223
  ivars: ivars,
215
224
  cvars: cvars,
216
225
  rbs_sources: rbs_sources,
@@ -237,7 +246,7 @@ module TypeProf
237
246
  @all_env.class_decls[name].decls.each do |decl|
238
247
  decl = decl.decl
239
248
  next if decl.is_a?(RBS::AST::Declarations::Module)
240
- each_ancestor(decl) {|name| queue << [:visit, name] }
249
+ each_reference(decl) {|name| queue << [:visit, name] }
241
250
  end
242
251
  queue << [:visit, name.namespace.to_type_name] if !name.namespace.empty?
243
252
  end
@@ -252,13 +261,20 @@ module TypeProf
252
261
  end
253
262
  end
254
263
 
255
- def each_ancestor(decl, &blk)
264
+ def each_reference(decl, &blk)
256
265
  yield decl.name
257
- 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
258
271
  return if decl.name == RBS::BuiltinNames::BasicObject.name
259
- return if decl.name == super_class.name
260
- @all_env.class_decls[super_class.name].decls.each do |decl|
261
- 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
262
278
  end
263
279
  end
264
280
 
@@ -297,7 +313,7 @@ module TypeProf
297
313
  opt_kw_tys = func.optional_keywords.to_h {|key, type| [key, conv_type(type.type)] }
298
314
  req_kw_tys = func.required_keywords.to_h {|key, type| [key, conv_type(type.type)] }
299
315
  rest_kw_ty = func.rest_keywords
300
- raise NotImplementedError if rest_kw_ty # XXX
316
+ rest_kw_ty = conv_type(rest_kw_ty.type) if rest_kw_ty
301
317
 
302
318
  ret_ty = conv_type(func.return_type)
303
319
 
@@ -314,32 +330,12 @@ module TypeProf
314
330
  }
315
331
  end
316
332
 
317
- def attr_reader_def(ty)
318
- [{
319
- type_params: [],
320
- lead_tys: [],
321
- opt_tys: [],
322
- rest_ty: nil,
323
- req_kw_tys: {},
324
- opt_kw_tys: {},
325
- rest_kw_ty: nil,
326
- blk: nil,
327
- ret_ty: ty,
328
- }]
329
- end
330
-
331
- def attr_writer_def(ty)
332
- [{
333
- type_params: [],
334
- lead_tys: [ty],
335
- opt_tys: [],
336
- rest_ty: nil,
337
- req_kw_tys: {},
338
- opt_kw_tys: {},
339
- rest_kw_ty: nil,
340
- blk: nil,
341
- ret_ty: ty,
342
- }]
333
+ def attr_method_def(kind, name, ty)
334
+ {
335
+ kind: kind,
336
+ ivar: name,
337
+ ty: ty,
338
+ }
343
339
  end
344
340
 
345
341
  def conv_block(rbs_block)
@@ -452,6 +448,8 @@ module TypeProf
452
448
  json = scratch.rbs_reader.load_library(feature)
453
449
  rescue RBS::EnvironmentLoader::UnknownLibraryError
454
450
  return nil
451
+ rescue RBS::DuplicatedDeclarationError
452
+ return true
455
453
  end
456
454
  # need cache?
457
455
  Import.new(scratch, json).import
@@ -483,8 +481,7 @@ module TypeProf
483
481
 
484
482
  klass = @scratch.get_constant(base_klass, name)
485
483
  if klass.is_a?(Type::Any)
486
- superclass_type_args = superclass_type_args&.map {|ty| conv_type(ty) }
487
- klass = @scratch.new_class(base_klass, name, type_params, superclass, superclass_type_args, nil)
484
+ klass = @scratch.new_class(base_klass, name, type_params, superclass, nil)
488
485
 
489
486
  # There builtin classes are needed to interpret RBS declarations
490
487
  case classpath
@@ -500,13 +497,15 @@ module TypeProf
500
497
  end
501
498
  end
502
499
 
503
- [klass, members]
500
+ [klass, superclass_type_args, members]
504
501
  end
505
502
 
506
- 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) })
507
505
  included_modules = members[:included_modules]
508
506
  extended_modules = members[:extended_modules]
509
507
  methods = members[:methods]
508
+ attr_methods = members[:attr_methods]
510
509
  ivars = members[:ivars]
511
510
  cvars = members[:cvars]
512
511
  rbs_sources = members[:rbs_sources]
@@ -527,6 +526,14 @@ module TypeProf
527
526
  @scratch.add_method(klass, method_name, singleton, mdef)
528
527
  end
529
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
+
530
537
  ivars.each do |ivar_name, ty|
531
538
  ty = conv_type(ty).remove_type_vars
532
539
  @scratch.add_ivar_write!(Type::Instance.new(klass), ivar_name, ty, nil)
@@ -593,7 +600,7 @@ module TypeProf
593
600
  req, lead_tys, opt_tys, ret_ty = blk
594
601
  lead_tys = lead_tys.map {|ty| conv_type(ty) }
595
602
  opt_tys = opt_tys.map {|ty| conv_type(ty) }
596
- msig = MethodSignature.new(lead_tys, opt_tys, nil, nil, nil, nil, nil)
603
+ msig = MethodSignature.new(lead_tys, opt_tys, nil, [], {}, nil, Type.nil)
597
604
  ret_ty = conv_type(ret_ty)
598
605
  ret = [Type::Proc.new(TypedBlock.new(msig, ret_ty), Type::Builtin[:proc])]
599
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]
@@ -171,30 +195,11 @@ module TypeProf
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)
173
197
 
174
- tmp_subst = {}
175
- case
176
- when recv.is_a?(Type::Cell) && recv_orig.is_a?(Type::LocalCell)
177
- tyvars = recv.base_type.klass.type_params.map {|name,| Type::Var.new(name) }
178
- tyvars.zip(recv.elems.elems) do |tyvar, elem|
179
- if tmp_subst[tyvar]
180
- tmp_subst[tyvar] = tmp_subst[tyvar].union(elem)
181
- else
182
- tmp_subst[tyvar] = elem
183
- end
184
- end
185
- when recv.is_a?(Type::Array) && recv_orig.is_a?(Type::LocalArray)
186
- tmp_subst = { Type::Var.new(:Elem) => recv.elems.squash }
187
- when recv.is_a?(Type::Hash) && recv_orig.is_a?(Type::LocalHash)
188
- tyvar_k = Type::Var.new(:K)
189
- tyvar_v = Type::Var.new(:V)
190
- k_ty0, v_ty0 = recv.elems.squash
191
- # XXX: need to heuristically replace ret type Hash[K, V] with self, instead of conversative type?
192
- tmp_subst = { tyvar_k => k_ty0, tyvar_v => v_ty0 }
193
- end
194
-
195
198
  klass, singleton = recv_orig.method_dispatch_info
196
199
  cur_subst = {}
197
- scratch.generate_substitution(klass, singleton, mid, self, tmp_subst) do |subst|
200
+ direct_method = true
201
+ scratch.adjust_substitution(klass, singleton, mid, self, recv.generate_substitution) do |subst, direct|
202
+ direct_method &&= direct
198
203
  cur_subst = Type.merge_substitution(cur_subst, subst)
199
204
  end
200
205
 
@@ -206,45 +211,15 @@ module TypeProf
206
211
  # XXX: support self type in msig
207
212
  subst = aargs.consistent_with_method_signature?(msig)
208
213
  next unless subst
209
- case
210
- when recv.is_a?(Type::Cell) && recv_orig.is_a?(Type::LocalCell)
211
- tyvars = recv.base_type.klass.type_params.map {|name,| Type::Var.new(name) }
212
- # XXX: This should be skipped when the called methods belongs to superclass
213
- tyvars.each_with_index do |tyvar, idx|
214
- ty = subst[tyvar]
215
- if ty
216
- ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
217
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
218
- elems.update(idx, ty)
219
- end
220
- end
221
- end
222
- when recv.is_a?(Type::Array) && recv_orig.is_a?(Type::LocalArray)
223
- tyvar_elem = Type::Var.new(:Elem)
224
- if subst[tyvar_elem]
225
- ty = subst[tyvar_elem]
226
- ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
227
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
228
- elems.update(nil, ty)
229
- end
230
- end
231
- when recv.is_a?(Type::Hash) && recv_orig.is_a?(Type::LocalHash)
232
- tyvar_k = Type::Var.new(:K)
233
- tyvar_v = Type::Var.new(:V)
234
- if subst[tyvar_k] && subst[tyvar_v]
235
- k_ty = subst[tyvar_k]
236
- v_ty = subst[tyvar_v]
237
- alloc_site = AllocationSite.new(caller_ep)
238
- ncaller_env, k_ty = scratch.localize_type(k_ty, ncaller_env, caller_ep, alloc_site.add_id(:k))
239
- ncaller_env, v_ty = scratch.localize_type(v_ty, ncaller_env, caller_ep, alloc_site.add_id(:v))
240
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
241
- elems.update(k_ty, v_ty)
242
- end
243
- end
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)
244
217
  end
218
+
245
219
  subst = Type.merge_substitution(subst, cur_subst)
246
220
  # need to check self tyvar?
247
221
  subst[Type::Var.new(:self)] = recv
222
+
248
223
  found = true
249
224
  if aargs.blk_ty.is_a?(Type::Proc)
250
225
  #raise NotImplementedError unless aargs.blk_ty.block_body.is_a?(ISeqBlock) # XXX
@@ -252,91 +227,33 @@ module TypeProf
252
227
  dummy_ep = ExecutionPoint.new(dummy_ctx, -1, caller_ep)
253
228
  s_recv = recv
254
229
  s_recv = s_recv.base_type while s_recv.respond_to?(:base_type)
255
- 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({}))
256
231
  if msig.blk_ty.is_a?(Type::Proc)
257
232
  scratch.add_callsite!(dummy_ctx, caller_ep, ncaller_env, &ctn)
258
- nfargs = msig.blk_ty.block_body.msig
233
+ bsig = msig.blk_ty.block_body.msig
259
234
  alloc_site = AllocationSite.new(caller_ep).add_id(self)
260
- nlead_tys = (nfargs.lead_tys + nfargs.opt_tys).map.with_index do |ty, i|
261
- if recv.is_a?(Type::Array)
262
- tyvar_elem = Type::Var.new(:Elem)
263
- ty = ty.substitute(subst.merge({ tyvar_elem => recv.elems.squash_or_any }), Config.options[:type_depth_limit])
264
- else
265
- ty = ty.substitute(subst, Config.options[:type_depth_limit])
266
- end
267
- ty = ty.remove_type_vars
268
- alloc_site2 = alloc_site.add_id(i)
269
- 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))
270
238
  ty
271
239
  end
272
- 0.upto(nfargs.opt_tys.size) do |n|
273
- 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?
274
242
  scratch.do_invoke_block(aargs.blk_ty, naargs, dummy_ep, dummy_env) do |blk_ret_ty, _ep, _env|
275
243
  subst2 = Type.match?(blk_ret_ty, msig.blk_ty.block_body.ret_ty)
276
244
  if subst2
277
245
  subst2 = Type.merge_substitution(subst, subst2)
278
- case
279
- when recv.is_a?(Type::Cell) && recv_orig.is_a?(Type::LocalCell)
280
- tyvars = recv.base_type.klass.type_params.map {|name,| Type::Var.new(name) }
281
- tyvars.each_with_index do |tyvar, idx|
282
- ty = subst2[tyvar]
283
- if ty
284
- ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
285
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
286
- elems.update(idx, ty)
287
- end
288
- scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
289
- end
290
- end
291
- tyvars.zip(recv.elems.elems) do |tyvar, elem|
292
- if subst2[tyvar]
293
- subst2[tyvar] = subst2[tyvar].union(elem)
294
- else
295
- subst2[tyvar] = elem
296
- end
297
- end
298
- ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
299
- when recv.is_a?(Type::Array) && recv_orig.is_a?(Type::LocalArray)
300
- tyvar_elem = Type::Var.new(:Elem)
301
- if subst2[tyvar_elem]
302
- ty = subst2[tyvar_elem]
303
- ncaller_env, ty = scratch.localize_type(ty, ncaller_env, caller_ep)
304
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
305
- elems.update(nil, ty)
306
- end
307
- scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
308
- end
309
- ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
310
- when recv.is_a?(Type::Hash) && recv_orig.is_a?(Type::LocalHash)
311
- tyvar_k = Type::Var.new(:K)
312
- tyvar_v = Type::Var.new(:V)
313
- k_ty0, v_ty0 = recv.elems.squash
314
- if subst2[tyvar_k] && subst2[tyvar_v]
315
- k_ty = subst2[tyvar_k]
316
- v_ty = subst2[tyvar_v]
317
- k_ty0 = k_ty0.union(k_ty)
318
- v_ty0 = v_ty0.union(v_ty)
319
- alloc_site = AllocationSite.new(caller_ep)
320
- ncaller_env, k_ty = scratch.localize_type(k_ty, ncaller_env, caller_ep, alloc_site.add_id(:k))
321
- ncaller_env, v_ty = scratch.localize_type(v_ty, ncaller_env, caller_ep, alloc_site.add_id(:v))
322
- ncaller_env = scratch.update_container_elem_types(ncaller_env, caller_ep, recv_orig.id, recv_orig.base_type) do |elems|
323
- elems.update(k_ty, v_ty)
324
- end
325
- scratch.merge_return_env(caller_ep) {|env| env ? env.merge(ncaller_env) : ncaller_env }
326
- end
327
- ret_ty = ret_ty.substitute(subst2, Config.options[:type_depth_limit])
328
- else
329
- 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 }
330
249
  end
250
+ ret_ty2 = ret_ty.substitute(subst2, Config.options[:type_depth_limit]).remove_type_vars
331
251
  else
332
- # raise "???"
333
- # XXX: need warning
334
- ret_ty = Type.any
252
+ ret_ty2 = Type.any
335
253
  end
336
- ret_ty = ret_ty.remove_type_vars
337
254
  # XXX: check the return type from the block
338
255
  # sig.blk_ty.block_body.ret_ty.eql?(_ret_ty) ???
339
- scratch.add_return_value!(dummy_ctx, ret_ty)
256
+ scratch.add_return_value!(dummy_ctx, ret_ty2)
340
257
  end
341
258
  # scratch.add_return_value!(dummy_ctx, ret_ty) ?
342
259
  # This makes `def foo; 1.times { return "str" }; end` return Integer|String
@@ -374,7 +291,6 @@ module TypeProf
374
291
  end
375
292
 
376
293
  def do_send(recv, mid, aargs, caller_ep, caller_env, scratch, &ctn)
377
- scratch.merge_return_env(caller_ep) {|env| env ? env.merge(caller_env) : caller_env } # for Kernel#lambda
378
294
  @impl[recv, mid, aargs, caller_ep, caller_env, scratch, &ctn]
379
295
  end
380
296
  end