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
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