typeprof 0.6.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
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