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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '080db9120b2b069f8a1385e3696851212a2271652f73b8627d5337d2d26d8f2b'
4
- data.tar.gz: 969e38b2a1b64ec3fbe90551b440418901c8af028c7126b1f56acaca3818d2b1
3
+ metadata.gz: 481ba91ab18504fff44772720b462a9fa302e4eecddb559c3a5942710e081fa9
4
+ data.tar.gz: 288ddfd1d6c9e198ea62e6564addf40ce851c91337801db44f2957c98b9f58f5
5
5
  SHA512:
6
- metadata.gz: 322bff1d2a49e9a2729012064e393138cb9e4b81472e1c75b14a2d55a4fe3616ef3efc5ecf5df3a156a418ff6ad0281c24c2c585c61a733db0c6e4d05ceb6595
7
- data.tar.gz: 78de3b56104b239c272938a9877bfdd49ccf20df8dbd360bf5fe7ef3c342e1d746c2adbf957fd511c03156258effe630c440941e600d58b7e7cd914ff11ca4d5
6
+ metadata.gz: 7f1eefdf5e92e2fa79a03979e36dd810ffcb337c426035acc384473e45fe6201487e8354608b4b87582515561b214e3ef339edd19e3980fab2873e6bc24cb9c5
7
+ data.tar.gz: cd74500c47328634ab7991911f795e7ea9b5cc47c15e3540c7796b39c2d1d83661cd50b45623e92cf1f33cbf1e83c4c8b5796a5e5332c8e1f475d3f1d26c043c
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- typeprof (0.6.0)
5
- rbs (>= 0.17.0)
4
+ typeprof (0.9.1)
5
+ rbs (>= 0.20.1)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
@@ -11,13 +11,15 @@ GEM
11
11
  docile (1.3.2)
12
12
  power_assert (1.2.0)
13
13
  rake (13.0.1)
14
- rbs (0.17.0)
15
- simplecov (0.19.1)
14
+ rbs (0.20.1)
15
+ simplecov (0.20.0)
16
16
  docile (~> 1.1)
17
17
  simplecov-html (~> 0.11)
18
+ simplecov_json_formatter (~> 0.1)
18
19
  simplecov-html (0.12.3)
20
+ simplecov_json_formatter (0.1.2)
19
21
  stackprof (0.2.16)
20
- test-unit (3.3.6)
22
+ test-unit (3.3.7)
21
23
  power_assert
22
24
 
23
25
  PLATFORMS
@@ -35,10 +35,9 @@ $ typeprof sig/app.rbs app.rb -o sig/app.gen.rbs
35
35
  * `--exclude-dir DIR`: `DIR`以下のファイルの解析結果を出力から省略する。後に指定されているほうが優先される(`--include-dir foo --exclude-dir foo/bar`の場合う、foo/bar/baz.rbの結果は出力されず、foo/baz.rbの結果は出力される)。
36
36
  * `--include-dir DIR`: `DIR`以下のファイルの解析結果を出力に含める。後に指定されているほうが優先される(`--exclude-dir foo --include-dir foo/bar`の場合、
37
37
  foo/bar/baz.rbの結果は出力されるが、foo/baz.rbの結果は出力されない)。
38
- * `-fshow-errors`: 実行中に見つけたバグの可能性を出力します(多くの場合、大量のfalse positiveが出ます)。
39
- * `-fpedantic-output`: デフォルトでは`A | untyped`と推定されたところを単に`A`と出力しますが、より生の出力、つまり`A | untyped`と出力します。
40
- * `-fshow-container-raw-elements`: (後で書く)
41
- * `-ftype-depth-limit=NUM`: (後で書く)
38
+ * `--show-errors`: 実行中に見つけたバグの可能性を出力します(多くの場合、大量のfalse positiveが出ます)。
39
+ * `--show-untyped`: デフォルトでは`A | untyped`と推定されたところを単に`A`と出力しますが、より生の出力、つまり`A | untyped`と出力します。
40
+ * `--type-depth-limit=NUM`: (後で書く)
42
41
 
43
42
  ## TypeProfとは
44
43
 
data/doc/doc.md CHANGED
@@ -34,10 +34,9 @@ Here is a list of currently avaiable options:
34
34
  * `-r GEMNAME`: Load the RBS files of `GEMNAME`
35
35
  * `--exclude-dir DIR`: Omit the result of files that are placed under the directory `DIR`. If there are some directory specifications, the latter one is stronger. (Assuming that `--include-dir foo --exclude-dir foo/bar` is specified, the analysis result of foo/bar/baz.rb is omitted, but foo/baz.rb is shown.)
36
36
  * `--include-dir DIR`: Show the result of files that are placed under the directory `DIR`. If there are some directory specifications, the latter one is stronger. (Assuming that `--exclude-dir foo --include-dir foo/bar` is specified, the analysis result of foo/bar/baz.rb is shown, but foo/baz.rb is omitted.)
37
- * `-fshow-errors`: Prints out possible bugs found during execution (often a lot of false positives).
38
- * `-fpedantic-output`: When TypeProf inferred a type `A | untyped`, it simply outputs `A` by default. But this option forces it to output `A | untyped`.
39
- * `-fshow-container-raw-elements`: (undocumented yet)
40
- * `-ftype-depth-limit=NUM`: (undocumented yet)
37
+ * `--show-errors`: Prints out possible bugs found during execution (often a lot of false positives).
38
+ * `--show-untyped`: When TypeProf infers a type `A | untyped`, it simply outputs `A` by default. But this option forces to output `A | untyped`.
39
+ * `--type-depth-limit=NUM`: (undocumented yet)
41
40
 
42
41
  ## What is a TypeProf?
43
42
 
@@ -34,6 +34,14 @@ module TypeProf
34
34
  end
35
35
 
36
36
  attr_reader :iseq, :cref, :mid
37
+
38
+ def source_location(pc)
39
+ if @iseq
40
+ @iseq.source_location(pc)
41
+ else
42
+ "<builtin>"
43
+ end
44
+ end
37
45
  end
38
46
 
39
47
  class TypedContext
@@ -45,6 +53,14 @@ module TypeProf
45
53
  end
46
54
 
47
55
  attr_reader :caller_ep, :mid
56
+
57
+ def source_location(_pc)
58
+ if @caller_ep
59
+ @caller_ep.source_location
60
+ else
61
+ "<typed-context:#{ @mid }>"
62
+ end
63
+ end
48
64
  end
49
65
 
50
66
  class ExecutionPoint
@@ -71,36 +87,33 @@ module TypeProf
71
87
  end
72
88
 
73
89
  def source_location
74
- iseq = @ctx.iseq
75
- if iseq
76
- iseq.source_location(@pc)
77
- else
78
- "<builtin>"
79
- end
90
+ @ctx.source_location(@pc)
80
91
  end
81
92
  end
82
93
 
83
94
  class StaticEnv
84
95
  include Utils::StructuralEquality
85
96
 
86
- def initialize(recv_ty, blk_ty, mod_func)
97
+ def initialize(recv_ty, blk_ty, mod_func, pub_meth)
87
98
  @recv_ty = recv_ty
88
99
  @blk_ty = blk_ty
89
100
  @mod_func = mod_func
101
+ @pub_meth = pub_meth
90
102
 
91
103
  return if recv_ty == :top #OK
92
104
  recv_ty.each_child_global do |ty|
93
- raise ty.inspect if !ty.is_a?(Type::Instance) && !ty.is_a?(Type::Class) && ty != Type.any
105
+ raise ty.inspect if !ty.is_a?(Type::Instance) && !ty.is_a?(Type::Class) && !ty.is_a?(Type::Symbol) && ty != Type.any
94
106
  end
95
107
  end
96
108
 
97
- attr_reader :recv_ty, :blk_ty, :mod_func
109
+ attr_reader :recv_ty, :blk_ty, :mod_func, :pub_meth
98
110
 
99
111
  def merge(other)
100
112
  recv_ty = @recv_ty.union(other.recv_ty)
101
113
  blk_ty = @blk_ty.union(other.blk_ty)
102
114
  mod_func = @mod_func & other.mod_func # ??
103
- StaticEnv.new(recv_ty, blk_ty, mod_func)
115
+ pub_meth = @pub_meth & other.pub_meth # ??
116
+ StaticEnv.new(recv_ty, blk_ty, mod_func, pub_meth)
104
117
  end
105
118
  end
106
119
 
@@ -185,29 +198,27 @@ module TypeProf
185
198
  Env.new(@static_env, Utils.array_update(@locals, idx, ty), @stack, @type_params)
186
199
  end
187
200
 
188
- def deploy_type(klass, alloc_site, elems, base_ty)
189
- local_ty = klass.new(alloc_site, base_ty)
190
- type_params = Utils::HashWrapper.new(@type_params.internal_hash.merge({ alloc_site => elems }))
191
- nenv = Env.new(@static_env, @locals, @stack, type_params)
192
- return nenv, local_ty
193
- end
194
-
195
201
  def get_container_elem_types(id)
196
202
  @type_params.internal_hash[id]
197
203
  end
198
204
 
199
- def update_container_elem_types(id, elems)
205
+ def deploy_type(id, elems)
200
206
  type_params = Utils::HashWrapper.new(@type_params.internal_hash.merge({ id => elems }))
201
207
  Env.new(@static_env, @locals, @stack, type_params)
202
208
  end
203
209
 
204
210
  def enable_module_function
205
- senv = StaticEnv.new(@static_env.recv_ty, @static_env.blk_ty, true)
211
+ senv = StaticEnv.new(@static_env.recv_ty, @static_env.blk_ty, true, @static_env.pub_meth)
212
+ Env.new(senv, @locals, @stack, @type_params)
213
+ end
214
+
215
+ def method_public_set(flag)
216
+ senv = StaticEnv.new(@static_env.recv_ty, @static_env.blk_ty, @static_env.mod_func, flag)
206
217
  Env.new(senv, @locals, @stack, @type_params)
207
218
  end
208
219
 
209
220
  def replace_recv_ty(ty)
210
- senv = StaticEnv.new(ty, @static_env.blk_ty, @static_env.mod_func)
221
+ senv = StaticEnv.new(ty, @static_env.blk_ty, @static_env.mod_func, @static_env.pub_meth)
211
222
  Env.new(senv, @locals, @stack, @type_params)
212
223
  end
213
224
 
@@ -298,8 +309,8 @@ module TypeProf
298
309
  attr_accessor :name, :klass_obj
299
310
 
300
311
  def include_module(mod, type_args, singleton, absolute_path)
301
- module_type_args, _, absolute_paths = @modules[singleton].find {|m,| m == mod }
302
- if module_type_args
312
+ mod_, module_type_args, absolute_paths = @modules[singleton].find {|m,| m == mod }
313
+ if mod_
303
314
  raise "inconsistent include/extend type args in RBS?" if module_type_args != type_args && type_args != [] && type_args != nil
304
315
  else
305
316
  absolute_paths = Utils::MutableSet.new
@@ -320,9 +331,9 @@ module TypeProf
320
331
  @consts[name] = [ty, absolute_path]
321
332
  end
322
333
 
323
- def generate_substitution(singleton, mid, mthd, subst, &blk)
334
+ def adjust_substitution(singleton, mid, mthd, subst, direct, &blk)
324
335
  mthds = @methods[[singleton, mid]]
325
- yield subst if mthds&.include?(mthd)
336
+ yield subst, direct if mthds&.include?(mthd)
326
337
  @modules[singleton].each do |mod_def, type_args,|
327
338
  if mod_def.klass_obj.type_params && type_args
328
339
  subst2 = {}
@@ -330,16 +341,19 @@ module TypeProf
330
341
  tyvar = Type::Var.new(tyvar)
331
342
  subst2[tyvar] = tyarg.substitute(subst, Config.options[:type_depth_limit])
332
343
  end
333
- mod_def.generate_substitution(false, mid, mthd, subst2, &blk)
344
+ mod_def.adjust_substitution(false, mid, mthd, subst2, false, &blk)
334
345
  end
335
346
  end
336
347
  end
337
348
 
338
- def search_method(singleton, mid, &blk)
349
+ def search_method(singleton, mid, visited, &blk)
350
+ # Currently, circular inclusion of modules is allowed
351
+ return if visited[self]
352
+ visited[self] = true
339
353
  mthds = @methods[[singleton, mid]]
340
354
  yield mthds, @klass_obj, singleton if mthds
341
355
  @modules[singleton].each do |mod_def,|
342
- mod_def.search_method(false, mid, &blk)
356
+ mod_def.search_method(false, mid, visited, &blk)
343
357
  end
344
358
  end
345
359
 
@@ -358,12 +372,16 @@ module TypeProf
358
372
  end
359
373
 
360
374
  def set_method(mid, singleton, mdef)
361
- @methods[[singleton, mid]] = Utils::MutableSet.new
362
- @methods[[singleton, mid]] << mdef
375
+ if mdef
376
+ @methods[[singleton, mid]] = Utils::MutableSet.new
377
+ @methods[[singleton, mid]] << mdef
378
+ else
379
+ @methods.delete([singleton, mid])
380
+ end
363
381
  end
364
382
  end
365
383
 
366
- def include_module(including_mod, included_mod, type_args, singleton, absolute_path)
384
+ def include_module(including_mod, included_mod, type_args, singleton, caller_ep)
367
385
  return if included_mod == Type.any
368
386
 
369
387
  including_mod = @class_defs[including_mod.idx]
@@ -371,9 +389,9 @@ module TypeProf
371
389
  if included_mod.is_a?(Type::Class)
372
390
  included_mod = @class_defs[included_mod.idx]
373
391
  if included_mod && included_mod.kind == :module
374
- including_mod.include_module(included_mod, type_args, singleton, absolute_path)
392
+ including_mod.include_module(included_mod, type_args, singleton, caller_ep ? caller_ep.ctx.iseq.absolute_path : nil)
375
393
  else
376
- warn "including something that is not a module"
394
+ warn(caller_ep, "including something that is not a module")
377
395
  end
378
396
  end
379
397
  end
@@ -383,12 +401,12 @@ module TypeProf
383
401
  cbase && cbase.idx != 1 ? @class_defs[cbase.idx].name : []
384
402
  end
385
403
 
386
- def new_class(cbase, name, type_params, superclass, superclass_type_args, absolute_path)
404
+ def new_class(cbase, name, type_params, superclass, absolute_path)
387
405
  show_name = cbase_path(cbase) + [name]
388
406
  idx = @class_defs.size
389
407
  if superclass
390
408
  @class_defs[idx] = ClassDef.new(:class, show_name, absolute_path)
391
- klass = Type::Class.new(:class, idx, type_params, superclass, superclass_type_args, show_name)
409
+ klass = Type::Class.new(:class, idx, type_params, superclass, show_name)
392
410
  @class_defs[idx].klass_obj = klass
393
411
  cbase ||= klass # for bootstrap
394
412
  add_constant(cbase, name, klass, absolute_path)
@@ -396,13 +414,17 @@ module TypeProf
396
414
  else
397
415
  # module
398
416
  @class_defs[idx] = ClassDef.new(:module, show_name, absolute_path)
399
- mod = Type::Class.new(:module, idx, type_params, nil, nil, show_name)
417
+ mod = Type::Class.new(:module, idx, type_params, nil, show_name)
400
418
  @class_defs[idx].klass_obj = mod
401
419
  add_constant(cbase, name, mod, absolute_path)
402
420
  return mod
403
421
  end
404
422
  end
405
423
 
424
+ def add_superclass_type_args!(klass, tyargs)
425
+ klass.superclass_type_args = tyargs
426
+ end
427
+
406
428
  def new_struct(ep)
407
429
  return @struct_defs[ep] if @struct_defs[ep]
408
430
 
@@ -410,7 +432,8 @@ module TypeProf
410
432
  superclass = Type::Builtin[:struct]
411
433
  name = "AnonymousStruct_generated_#{ @anonymous_struct_gen_id += 1 }"
412
434
  @class_defs[idx] = ClassDef.new(:class, [name], ep.ctx.iseq.absolute_path)
413
- klass = Type::Class.new(:class, idx, [], superclass, [], name)
435
+ klass = Type::Class.new(:class, idx, [], superclass, name)
436
+ add_superclass_type_args!(klass, [Type.any])
414
437
  @class_defs[idx].klass_obj = klass
415
438
 
416
439
  @struct_defs[ep] = klass
@@ -440,11 +463,13 @@ module TypeProf
440
463
  end
441
464
  end
442
465
 
443
- def generate_substitution(klass, singleton, mid, mthd, subst, &blk)
466
+ def adjust_substitution(klass, singleton, mid, mthd, subst, &blk)
467
+ direct = true
444
468
  if klass.kind == :class
445
469
  while klass != :__root__
446
470
  class_def = @class_defs[klass.idx]
447
- class_def.generate_substitution(singleton, mid, mthd, subst, &blk)
471
+ class_def.adjust_substitution(singleton, mid, mthd, subst, direct, &blk)
472
+ direct = false
448
473
  if klass.superclass && klass.superclass_type_args
449
474
  subst2 = {}
450
475
  klass.superclass.type_params.zip(klass.superclass_type_args) do |(tyvar, *), tyarg|
@@ -458,7 +483,7 @@ module TypeProf
458
483
  else
459
484
  # module
460
485
  class_def = @class_defs[klass.idx]
461
- class_def.generate_substitution(singleton, mid, mthd, subst, &blk)
486
+ class_def.adjust_substitution(singleton, mid, mthd, subst, direct, &blk)
462
487
  end
463
488
  end
464
489
 
@@ -468,13 +493,13 @@ module TypeProf
468
493
  if klass.kind == :class
469
494
  while klass != :__root__
470
495
  class_def = @class_defs[klass.idx]
471
- class_def.search_method(singleton, mid, &blk)
496
+ class_def.search_method(singleton, mid, {}, &blk)
472
497
  klass = klass.superclass
473
498
  end
474
499
  else
475
500
  # module
476
501
  class_def = @class_defs[klass.idx]
477
- class_def.search_method(singleton, mid, &blk)
502
+ class_def.search_method(singleton, mid, {}, &blk)
478
503
  end
479
504
  if singleton
480
505
  search_method(Type::Builtin[klass_orig.kind], false, mid, &blk)
@@ -534,9 +559,7 @@ module TypeProf
534
559
  end
535
560
 
536
561
  def add_constant(klass, name, value, user_defined)
537
- if klass == Type.any
538
- self
539
- else
562
+ if klass.is_a?(Type::Class)
540
563
  @class_defs[klass.idx].add_constant(name, value, user_defined)
541
564
  end
542
565
  end
@@ -564,12 +587,12 @@ module TypeProf
564
587
  end
565
588
  end
566
589
 
567
- def add_iseq_method(klass, mid, iseq, cref)
568
- add_method(klass, mid, false, ISeqMethodDef.new(iseq, cref))
590
+ def add_iseq_method(klass, mid, iseq, cref, outer_ep, pub_meth)
591
+ add_method(klass, mid, false, ISeqMethodDef.new(iseq, cref, outer_ep, pub_meth))
569
592
  end
570
593
 
571
- def add_singleton_iseq_method(klass, mid, iseq, cref)
572
- add_method(klass, mid, true, ISeqMethodDef.new(iseq, cref))
594
+ def add_singleton_iseq_method(klass, mid, iseq, cref, outer_ep, pub_meth)
595
+ add_method(klass, mid, true, ISeqMethodDef.new(iseq, cref, outer_ep, pub_meth))
573
596
  end
574
597
 
575
598
  def set_custom_method(klass, mid, impl)
@@ -602,6 +625,10 @@ module TypeProf
602
625
  @iseq_method_to_ctxs[iseq_mdef] << ctx
603
626
  end
604
627
 
628
+ def add_executed_iseq(iseq)
629
+ @executed_iseqs << iseq
630
+ end
631
+
605
632
  def add_callsite!(callee_ctx, caller_ep, caller_env, &ctn)
606
633
  @executed_iseqs << callee_ctx.iseq if callee_ctx.is_a?(Context)
607
634
 
@@ -661,8 +688,10 @@ module TypeProf
661
688
  def add_read!(site, ep, &ctn)
662
689
  entry = @tbl[site] ||= Entry.new(false, {}, Type.bot, Utils::MutableSet.new)
663
690
  entry.read_continuations[ep] = ctn
664
- entry.absolute_paths << ep.ctx.iseq.absolute_path
665
- ctn[entry.type, ep]
691
+ entry.absolute_paths << ep.ctx.iseq.absolute_path if ep.ctx.is_a?(Context)
692
+ ty = entry.type
693
+ ty = Type.nil if ty == Type.bot
694
+ ctn[ty, ep]
666
695
  end
667
696
 
668
697
  def add_write!(site, ty, ep, scratch)
@@ -720,6 +749,7 @@ module TypeProf
720
749
 
721
750
  def add_cvar_read!(klass, var, ep, &ctn)
722
751
  klass.each_child do |klass|
752
+ next unless klass.is_a?(Type::Class)
723
753
  class_def = @class_defs[klass.idx]
724
754
  next unless class_def
725
755
  class_def.cvars.add_read!(var, ep, &ctn)
@@ -728,6 +758,7 @@ module TypeProf
728
758
 
729
759
  def add_cvar_write!(klass, var, ty, ep)
730
760
  klass.each_child do |klass|
761
+ next unless klass.is_a?(Type::Class)
731
762
  class_def = @class_defs[klass.idx]
732
763
  next unless class_def
733
764
  class_def.cvars.add_write!(var, ty, ep, self)
@@ -778,7 +809,7 @@ module TypeProf
778
809
  merge_return_env(tmp_ep) do |menv|
779
810
  elems = menv.get_container_elem_types(id)
780
811
  elems = yield elems
781
- menv = menv.update_container_elem_types(id, elems)
812
+ menv = menv.deploy_type(id, elems)
782
813
  gid = @alloc_site_to_global_id[id]
783
814
  if gid
784
815
  ty = globalize_type(elems.to_local_type(id, base_type), env, ep)
@@ -790,7 +821,7 @@ module TypeProf
790
821
  else
791
822
  elems = env.get_container_elem_types(id)
792
823
  elems = yield elems
793
- env = env.update_container_elem_types(id, elems)
824
+ env = env.deploy_type(id, elems)
794
825
  gid = @alloc_site_to_global_id[id]
795
826
  if gid
796
827
  ty = globalize_type(elems.to_local_type(id, base_type), env, ep)
@@ -831,11 +862,11 @@ module TypeProf
831
862
  ep = @worklist.deletemin
832
863
 
833
864
  iter_counter += 1
834
- if Config.verbose >= 1
865
+ if Config.options[:show_indicator]
835
866
  tick2 = Time.now
836
867
  if tick2 - tick >= 1
837
868
  tick = tick2
838
- $stderr << "\rType Profiling... (%d steps @ %s)\e[K" % [iter_counter, ep.source_location]
869
+ $stderr << "\rType Profiling... (%d instructions @ %s)\e[K" % [iter_counter, ep.source_location]
839
870
  $stderr.flush
840
871
  end
841
872
  end
@@ -851,9 +882,7 @@ module TypeProf
851
882
 
852
883
  break if @terminated
853
884
 
854
- # XXX: it would be good to provide no-dummy-execution mode.
855
- # It should work as a bit smarter "rbs prototype rb";
856
- # show all method definitions as "untyped" arguments and return values
885
+ break unless Config.options[:stub_execution]
857
886
 
858
887
  begin
859
888
  iseq, (kind, dummy_continuation) = @pending_execution.first
@@ -861,7 +890,7 @@ module TypeProf
861
890
  @pending_execution.delete(iseq)
862
891
  end while @executed_iseqs.include?(iseq)
863
892
 
864
- puts "DEBUG: trigger dummy execution (#{ iseq&.name || "(nil)" }): rest #{ @pending_execution.size }" if Config.verbose >= 2
893
+ puts "DEBUG: trigger stub execution (#{ iseq&.name || "(nil)" }): rest #{ @pending_execution.size }" if Config.verbose >= 2
865
894
 
866
895
  break if !iseq
867
896
  case kind
@@ -878,7 +907,7 @@ module TypeProf
878
907
  end
879
908
  end
880
909
  end
881
- $stderr.print "\r\e[K" if Config.verbose >= 1
910
+ $stderr.print "\r\e[K" if Config.options[:show_indicator]
882
911
 
883
912
  stat_eps
884
913
  end
@@ -919,9 +948,9 @@ module TypeProf
919
948
  end
920
949
  end
921
950
 
922
- def pend_method_execution(iseq, meth, recv, mid, cref)
951
+ def pend_method_execution(iseq, meth, recv, mid, cref, ep)
923
952
  ctx = Context.new(iseq, cref, mid)
924
- ep = ExecutionPoint.new(ctx, 0, nil)
953
+ ep = ExecutionPoint.new(ctx, 0, ep)
925
954
  locals = [Type.nil] * iseq.locals.size
926
955
 
927
956
  fargs_format = iseq.fargs_format
@@ -956,17 +985,23 @@ module TypeProf
956
985
  locals[kwrest_index] = Type.any if kwrest_index
957
986
  locals[block_index] = Type.nil if block_index
958
987
 
959
- env = Env.new(StaticEnv.new(recv, Type.nil, false), locals, [], Utils::HashWrapper.new({}))
988
+ env = Env.new(StaticEnv.new(recv, Type.nil, false, true), locals, [], Utils::HashWrapper.new({}))
960
989
 
961
- @pending_execution[iseq] ||= [:method, [meth, ep, env]]
990
+ if !@pending_execution[iseq] || @pending_execution[iseq][0] == :block
991
+ @pending_execution[iseq] = [:method, [meth, ep, env]]
992
+ end
962
993
  end
963
994
 
964
995
  def pend_block_dummy_execution(blk, iseq, nep, nenv)
965
996
  @pending_execution[iseq] ||= [:block, [blk, {}]]
966
- if @pending_execution[iseq][1][1][nep]
967
- @pending_execution[iseq][1][1][nep] = @pending_execution[iseq][1][1][nep].merge(nenv)
997
+ if @pending_execution[iseq][0] == :block
998
+ if @pending_execution[iseq][1][1][nep]
999
+ @pending_execution[iseq][1][1][nep] = @pending_execution[iseq][1][1][nep].merge(nenv)
1000
+ else
1001
+ @pending_execution[iseq][1][1][nep] = nenv
1002
+ end
968
1003
  else
969
- @pending_execution[iseq][1][1][nep] = nenv
1004
+ # XXX: what to do?
970
1005
  end
971
1006
  end
972
1007
 
@@ -975,7 +1010,7 @@ module TypeProf
975
1010
  alloc_site = AllocationSite.new(ep)
976
1011
  nenv, ty = localize_type(ty, env, ep, alloc_site)
977
1012
  case ty
978
- when Type::LocalCell, Type::LocalArray, Type::LocalHash
1013
+ when Type::Local
979
1014
  @alloc_site_to_global_id[ty.id] = [recv, var] # need overwrite check??
980
1015
  end
981
1016
  yield ty, nenv
@@ -1015,7 +1050,7 @@ module TypeProf
1015
1050
  block_start = iseq.fargs_format[:block_start]
1016
1051
 
1017
1052
  lead_tys = env.locals[0, lead_num].map {|ty| globalize_type(ty, env, ep) }
1018
- opt_tys = opt.size > 1 ? env.locals[lead_num, opt.size - 1].map {|ty| globalize_type(ty, env, ep) } : nil
1053
+ opt_tys = opt.size > 1 ? env.locals[lead_num, opt.size - 1].map {|ty| globalize_type(ty, env, ep) } : []
1019
1054
  if rest_start # XXX:squash
1020
1055
  ty = globalize_type(env.locals[lead_num + opt.size - 1], env, ep)
1021
1056
  rest_ty = Type.bot
@@ -1141,31 +1176,7 @@ module TypeProf
1141
1176
 
1142
1177
  when :definemethod
1143
1178
  mid, iseq = operands
1144
- cref = ep.ctx.cref
1145
- recv = env.static_env.recv_ty
1146
- if cref.klass.is_a?(Type::Class)
1147
- typed_mdef = check_typed_method(cref.klass, mid, ep.ctx.cref.singleton)
1148
- recv = Type::Instance.new(recv) if recv.is_a?(Type::Class)
1149
- if typed_mdef
1150
- mdef = ISeqMethodDef.new(iseq, cref)
1151
- typed_mdef.each do |typed_mdef|
1152
- typed_mdef.do_match_iseq_mdef(mdef, recv, mid, env, ep, self)
1153
- end
1154
- else
1155
- if ep.ctx.cref.singleton
1156
- meth = add_singleton_iseq_method(cref.klass, mid, iseq, cref)
1157
- else
1158
- meth = add_iseq_method(cref.klass, mid, iseq, cref)
1159
- if env.static_env.mod_func
1160
- add_singleton_iseq_method(cref.klass, mid, iseq, cref)
1161
- end
1162
- end
1163
-
1164
- pend_method_execution(iseq, meth, recv, mid, ep.ctx.cref)
1165
- end
1166
- else
1167
- # XXX: what to do?
1168
- end
1179
+ do_define_iseq_method(ep, env, mid, iseq, nil)
1169
1180
 
1170
1181
  when :definesmethod
1171
1182
  mid, iseq = operands
@@ -1173,8 +1184,8 @@ module TypeProf
1173
1184
  cref = ep.ctx.cref
1174
1185
  recv.each_child do |recv|
1175
1186
  if recv.is_a?(Type::Class)
1176
- meth = add_singleton_iseq_method(recv, mid, iseq, cref)
1177
- pend_method_execution(iseq, meth, recv, mid, ep.ctx.cref)
1187
+ meth = add_singleton_iseq_method(recv, mid, iseq, cref, nil, env.static_env.pub_meth)
1188
+ pend_method_execution(iseq, meth, recv, mid, ep.ctx.cref, nil)
1178
1189
  else
1179
1190
  recv = Type.any # XXX: what to do?
1180
1191
  end
@@ -1210,11 +1221,11 @@ module TypeProf
1210
1221
  else # module
1211
1222
  superclass = nil
1212
1223
  end
1213
- if cbase == Type.any
1214
- klass = Type.any
1224
+ if cbase.is_a?(Type::Class)
1225
+ klass = new_class(cbase, id, [], superclass, ep.ctx.iseq.absolute_path)
1226
+ add_superclass_type_args!(klass, superclass.type_params.map { Type.any }) if superclass
1215
1227
  else
1216
- superclass_type_args = superclass.type_params.map { Type.any } if superclass
1217
- klass = new_class(cbase, id, [], superclass, superclass_type_args, ep.ctx.iseq.absolute_path)
1228
+ klass = Type.any
1218
1229
  end
1219
1230
  end
1220
1231
  singleton = false
@@ -1236,7 +1247,7 @@ module TypeProf
1236
1247
  nctx = Context.new(iseq, ncref, nil)
1237
1248
  nep = ExecutionPoint.new(nctx, 0, nil)
1238
1249
  locals = [Type.nil] * iseq.locals.size
1239
- nenv = Env.new(StaticEnv.new(recv, blk, false), locals, [], Utils::HashWrapper.new({}))
1250
+ nenv = Env.new(StaticEnv.new(recv, blk, false, true), locals, [], Utils::HashWrapper.new({}))
1240
1251
  merge_env(nep, nenv)
1241
1252
  add_callsite!(nep.ctx, ep, env) do |ret_ty, ep, env|
1242
1253
  nenv, ret_ty = localize_type(ret_ty, env, ep)
@@ -1352,11 +1363,24 @@ module TypeProf
1352
1363
  return
1353
1364
  when :break
1354
1365
  tmp_ep = ep
1355
- tmp_ep = tmp_ep.outer while tmp_ep.ctx.iseq.type != :block
1356
- tmp_ep = tmp_ep.outer
1357
- nenv = @return_envs[tmp_ep].push(ty)
1358
- merge_env(tmp_ep.next, nenv)
1359
- # TODO: jump to ensure?
1366
+ while true
1367
+ if tmp_ep.ctx.iseq.type == :block
1368
+ tmp_ep = tmp_ep.outer
1369
+ nenv = @return_envs[tmp_ep].push(ty)
1370
+ merge_env(tmp_ep.next, nenv)
1371
+ break
1372
+ end
1373
+ _type, _iseq, cont, stack_depth = tmp_ep.ctx.iseq.catch_table[tmp_ep.pc]&.find {|type,| type == :break }
1374
+ if cont
1375
+ nenv = @return_envs[tmp_ep]
1376
+ nenv, = nenv.pop(nenv.stack.size - stack_depth)
1377
+ nenv = nenv.push(ty)
1378
+ tmp_ep = tmp_ep.jump(cont)
1379
+ merge_env(tmp_ep, nenv)
1380
+ break
1381
+ end
1382
+ tmp_ep = tmp_ep.outer
1383
+ end
1360
1384
  when :next, :redo
1361
1385
  # begin; rescue; next; end
1362
1386
  tmp_ep = ep.outer
@@ -1549,9 +1573,7 @@ module TypeProf
1549
1573
  ret_ty.each_child do |ret_ty|
1550
1574
  flow_env = env.local_update(-var_idx+2, ret_ty)
1551
1575
  ret_ty = ret_ty.base_type if ret_ty.is_a?(Type::Symbol)
1552
- ret_ty = ret_ty.base_type if ret_ty.is_a?(Type::LocalCell)
1553
- ret_ty = ret_ty.base_type if ret_ty.is_a?(Type::LocalArray)
1554
- ret_ty = ret_ty.base_type if ret_ty.is_a?(Type::LocalHash)
1576
+ ret_ty = ret_ty.base_type if ret_ty.is_a?(Type::Local)
1555
1577
  if ret_ty.is_a?(Type::Instance)
1556
1578
  if ret_ty.klass == pattern_ty # XXX: inheritance
1557
1579
  merge_env(branchtype == :if ? ep_else : ep_then, flow_env)
@@ -1600,7 +1622,7 @@ module TypeProf
1600
1622
  warn(ep, "already initialized constant #{ Type::Instance.new(cbase).screen_name(self) }::#{ name }")
1601
1623
  end
1602
1624
  ty.each_child do |ty|
1603
- if ty.is_a?(Type::Class) && ty.superclass == Type::Builtin[:struct]
1625
+ if ty.is_a?(Type::Class) && cbase.is_a?(Type::Class) && ty.superclass == Type::Builtin[:struct]
1604
1626
  @class_defs[ty.idx].name = cbase_path(cbase) + [name]
1605
1627
  end
1606
1628
  end
@@ -1609,7 +1631,6 @@ module TypeProf
1609
1631
  when :getspecial
1610
1632
  key, type = operands
1611
1633
  if type == 0
1612
- raise NotImplementedError
1613
1634
  case key
1614
1635
  when 0 # VM_SVAR_LASTLINE
1615
1636
  env = env.push(Type.any) # or String | NilClass only?
@@ -1627,8 +1648,12 @@ module TypeProf
1627
1648
  return
1628
1649
  end
1629
1650
  when :setspecial
1630
- # flip-flop
1631
- raise NotImplementedError, "setspecial"
1651
+ key, = operands
1652
+ if key >= 2 # flip-flop
1653
+ env, = env.pop(1)
1654
+ else
1655
+ raise "unknown setspecial key: #{ key }"
1656
+ end
1632
1657
 
1633
1658
  when :dup
1634
1659
  env, (ty,) = env.pop(1)
@@ -1679,10 +1704,16 @@ module TypeProf
1679
1704
  env = env.push(Type.optional(sym_ty))
1680
1705
  when :checkmatch
1681
1706
  flag, = operands
1707
+
1708
+ # This flag means that the stack top is an array, and the check needs to be applied to find all elements
1709
+ # However, currently TypeProf uses very conservative interpretation (all check returns both true and false),
1710
+ # so we just ignore the flag now
1682
1711
  _array = flag & 4 != 0
1712
+
1683
1713
  case flag & 3
1684
- when 1
1685
- raise NotImplementedError
1714
+ when 1 # VM_CHECKMATCH_TYPE_WHEN
1715
+ env, = env.pop(2)
1716
+ env = env.push(Type.bool)
1686
1717
  when 2 # VM_CHECKMATCH_TYPE_CASE
1687
1718
  env, = env.pop(2)
1688
1719
  env = env.push(Type.bool)
@@ -1717,9 +1748,13 @@ module TypeProf
1717
1748
  from_head = flag & 2 == 0
1718
1749
  ary.each_child do |ary|
1719
1750
  case ary
1720
- when Type::LocalArray
1721
- elems = get_container_elem_types(env, ep, ary.id)
1722
- elems ||= Type::Array::Elements.new([], Type.any) # XXX
1751
+ when Type::Local
1752
+ if ary.kind == Type::Array
1753
+ elems = get_container_elem_types(env, ep, ary.id)
1754
+ elems ||= Type::Array::Elements.new([], Type.any) # XXX
1755
+ else
1756
+ elems = Type::Array::Elements.new([], Type.any) # XXX
1757
+ end
1723
1758
  do_expand_array(ep, env, elems, num, splat, from_head)
1724
1759
  when Type::Any
1725
1760
  nnum = num
@@ -1739,9 +1774,9 @@ module TypeProf
1739
1774
  return
1740
1775
  when :concatarray
1741
1776
  env, (ary1, ary2) = env.pop(2)
1742
- if ary1.is_a?(Type::LocalArray)
1777
+ if ary1.is_a?(Type::Local) && ary1.kind == Type::Array
1743
1778
  elems1 = get_container_elem_types(env, ep, ary1.id)
1744
- if ary2.is_a?(Type::LocalArray)
1779
+ if ary2.is_a?(Type::Local) && ary2.kind == Type::Array
1745
1780
  elems2 = get_container_elem_types(env, ep, ary2.id)
1746
1781
  elems = Type::Array::Elements.new([], elems1.squash.union(elems2.squash))
1747
1782
  env = update_container_elem_types(env, ep, ary1.id, ary1.base_type) { elems }
@@ -1888,6 +1923,10 @@ module TypeProf
1888
1923
  rest_ty = aargs.last
1889
1924
  aargs = aargs[0..-2]
1890
1925
  if flag_args_kw_splat
1926
+ # XXX: The types contained in ActualArguments are expected to be all local types.
1927
+ # This "globalize_type" breaks the invariant, and violates the assertion of Union#globalize that asserts @elems be nil.
1928
+ # To fix this issue fundamentally, ActualArguments should keep all arguments as-is (as like the VM does),
1929
+ # and globalize some types on the on-demand bases.
1891
1930
  ty = globalize_type(rest_ty, env, ep)
1892
1931
  if ty.is_a?(Type::Array)
1893
1932
  _, (ty,) = ty.elems.take_last(1)
@@ -1920,6 +1959,10 @@ module TypeProf
1920
1959
  aargs = ActualArguments.new(aargs, rest_ty, kw_tys, blk_ty)
1921
1960
  elsif flag_args_kw_splat
1922
1961
  last = aargs.last
1962
+ # XXX: The types contained in ActualArguments are expected to be all local types.
1963
+ # This "globalize_type" breaks the invariant, and violates the assertion of Union#globalize that asserts @elems be nil.
1964
+ # To fix this issue fundamentally, ActualArguments should keep all arguments as-is (as like the VM does),
1965
+ # and globalize some types on the on-demand bases.
1923
1966
  ty = globalize_type(last, env, ep)
1924
1967
  case ty
1925
1968
  when Type::Hash
@@ -1963,7 +2006,7 @@ module TypeProf
1963
2006
  nctx = Context.new(blk_iseq, ep.ctx.cref, ep.ctx.mid)
1964
2007
  nep = ExecutionPoint.new(nctx, 0, ep)
1965
2008
  nlocals = [Type.any] * blk_iseq.locals.size
1966
- nsenv = StaticEnv.new(env.static_env.recv_ty, Type.any, env.static_env.mod_func)
2009
+ nsenv = StaticEnv.new(env.static_env.recv_ty, Type.any, env.static_env.mod_func, env.static_env.pub_meth)
1967
2010
  nenv = Env.new(nsenv, nlocals, [], nil)
1968
2011
  pend_block_dummy_execution(blk_ty, blk_iseq, nep, nenv)
1969
2012
  merge_return_env(ep) {|tenv| tenv ? tenv.merge(env) : env }
@@ -1973,21 +2016,31 @@ module TypeProf
1973
2016
  end
1974
2017
 
1975
2018
  def do_send(recv, mid, aargs, ep, env, &ctn)
1976
- klass, singleton = recv.method_dispatch_info
1977
- meths = get_method(klass, singleton, mid) if klass
1978
- if meths
1979
- meths.each do |meth|
1980
- meth.do_send(recv, mid, aargs, ep, env, self, &ctn)
1981
- end
2019
+ case recv
2020
+ when Type::Void
2021
+ error(ep, "void's method is called: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
2022
+ ctn[Type.any, ep, env]
2023
+ when Type::Any
2024
+ ctn[Type.any, ep, env]
1982
2025
  else
1983
- case recv
1984
- when Type::Void
1985
- error(ep, "void's method is called: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
1986
- when Type::Any
2026
+ klass, singleton = recv.method_dispatch_info
2027
+ meths = get_method(klass, singleton, mid) if klass
2028
+ if meths
2029
+ meths.each do |meth|
2030
+ meth.do_send(recv, mid, aargs, ep, env, self, &ctn)
2031
+ end
1987
2032
  else
1988
- error(ep, "undefined method: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
2033
+ meths = get_method(klass, singleton, :method_missing) if klass
2034
+ if meths
2035
+ aargs = aargs.for_method_missing(Type::Symbol.new(mid, Type::Instance.new(Type::Builtin[:sym])))
2036
+ meths.each do |meth|
2037
+ meth.do_send(recv, :method_missing, aargs, ep, env, self, &ctn)
2038
+ end
2039
+ else
2040
+ error(ep, "undefined method: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
2041
+ ctn[Type.any, ep, env]
2042
+ end
1989
2043
  end
1990
- ctn[Type.any, ep, env]
1991
2044
  end
1992
2045
  end
1993
2046
 
@@ -2002,6 +2055,34 @@ module TypeProf
2002
2055
  end
2003
2056
  end
2004
2057
 
2058
+ def do_define_iseq_method(ep, env, mid, iseq, outer_ep)
2059
+ cref = ep.ctx.cref
2060
+ if cref.klass.is_a?(Type::Class)
2061
+ typed_mdef = check_typed_method(cref.klass, mid, ep.ctx.cref.singleton)
2062
+ recv = cref.klass
2063
+ recv = Type::Instance.new(recv) unless ep.ctx.cref.singleton
2064
+ if typed_mdef
2065
+ mdef = ISeqMethodDef.new(iseq, cref, outer_ep, env.static_env.pub_meth)
2066
+ typed_mdef.each do |typed_mdef|
2067
+ typed_mdef.do_match_iseq_mdef(mdef, recv, mid, env, ep, self)
2068
+ end
2069
+ else
2070
+ if ep.ctx.cref.singleton
2071
+ meth = add_singleton_iseq_method(cref.klass, mid, iseq, cref, outer_ep, true)
2072
+ else
2073
+ meth = add_iseq_method(cref.klass, mid, iseq, cref, outer_ep, env.static_env.pub_meth)
2074
+ if env.static_env.mod_func
2075
+ add_singleton_iseq_method(cref.klass, mid, iseq, cref, outer_ep, true)
2076
+ end
2077
+ end
2078
+ end
2079
+
2080
+ pend_method_execution(iseq, meth, recv, mid, ep.ctx.cref, outer_ep)
2081
+ else
2082
+ # XXX: what to do?
2083
+ end
2084
+ end
2085
+
2005
2086
  def show_block_signature(blks)
2006
2087
  bsig = nil
2007
2088
  ret_ty = Type.bot
@@ -2042,7 +2123,7 @@ module TypeProf
2042
2123
  next unless @block_to_ctx[blk.block_body] # this occurs when screen_name is called before type-profiling finished (e.g., error message)
2043
2124
  @block_to_ctx[blk.block_body].each do |blk_ctx|
2044
2125
  if farg_tys
2045
- farg_tys = farg_tys.merge(@method_signatures[blk_ctx])
2126
+ farg_tys = farg_tys.merge_as_block_arguments(@method_signatures[blk_ctx])
2046
2127
  else
2047
2128
  farg_tys = @method_signatures[blk_ctx]
2048
2129
  end