typeprof 0.5.4 → 0.9.0

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 +308 -171
  6. data/lib/typeprof/arguments.rb +14 -6
  7. data/lib/typeprof/block.rb +6 -2
  8. data/lib/typeprof/builtin.rb +230 -67
  9. data/lib/typeprof/cli.rb +33 -34
  10. data/lib/typeprof/config.rb +6 -4
  11. data/lib/typeprof/container-type.rb +159 -104
  12. data/lib/typeprof/export.rb +28 -22
  13. data/lib/typeprof/import.rb +70 -53
  14. data/lib/typeprof/iseq.rb +23 -7
  15. data/lib/typeprof/method.rb +71 -138
  16. data/lib/typeprof/type.rb +73 -15
  17. data/lib/typeprof/version.rb +1 -1
  18. data/smoke/alias.rb +5 -4
  19. data/smoke/alias2.rb +4 -4
  20. data/smoke/any1.rb +2 -1
  21. data/smoke/any2.rb +3 -2
  22. data/smoke/arguments.rb +3 -2
  23. data/smoke/arguments2.rb +11 -10
  24. data/smoke/array-each.rb +2 -1
  25. data/smoke/array-each2.rb +2 -1
  26. data/smoke/array-each3.rb +2 -1
  27. data/smoke/array-ltlt.rb +2 -1
  28. data/smoke/array-ltlt2.rb +2 -1
  29. data/smoke/array-map.rb +2 -1
  30. data/smoke/array-map2.rb +2 -1
  31. data/smoke/array-map3.rb +4 -3
  32. data/smoke/array-mul.rb +3 -2
  33. data/smoke/array-plus1.rb +2 -1
  34. data/smoke/array-plus2.rb +2 -2
  35. data/smoke/array-pop.rb +2 -1
  36. data/smoke/array-range-aref.rb +71 -0
  37. data/smoke/array-replace.rb +2 -1
  38. data/smoke/array-s-aref.rb +2 -1
  39. data/smoke/array1.rb +6 -5
  40. data/smoke/array10.rb +2 -1
  41. data/smoke/array11.rb +2 -1
  42. data/smoke/array12.rb +4 -3
  43. data/smoke/array13.rb +5 -4
  44. data/smoke/array14.rb +2 -1
  45. data/smoke/array15.rb +16 -0
  46. data/smoke/array2.rb +4 -3
  47. data/smoke/array3.rb +4 -4
  48. data/smoke/array4.rb +2 -1
  49. data/smoke/array5.rb +2 -1
  50. data/smoke/array6.rb +3 -2
  51. data/smoke/array7.rb +2 -1
  52. data/smoke/array8.rb +1 -1
  53. data/smoke/array9.rb +2 -1
  54. data/smoke/attr-module.rb +26 -0
  55. data/smoke/attr.rb +5 -5
  56. data/smoke/autoload.rb +14 -0
  57. data/smoke/backtrace.rb +4 -3
  58. data/smoke/block-ambiguous.rb +9 -8
  59. data/smoke/block-args1-rest.rb +12 -11
  60. data/smoke/block-args1.rb +11 -10
  61. data/smoke/block-args2-rest.rb +12 -11
  62. data/smoke/block-args2.rb +11 -10
  63. data/smoke/block-args3-rest.rb +14 -13
  64. data/smoke/block-args3.rb +13 -12
  65. data/smoke/block-blockarg.rb +5 -4
  66. data/smoke/block-kwarg.rb +11 -10
  67. data/smoke/block1.rb +2 -1
  68. data/smoke/block10.rb +2 -1
  69. data/smoke/block11.rb +6 -5
  70. data/smoke/block12.rb +3 -2
  71. data/smoke/block14.rb +3 -2
  72. data/smoke/block2.rb +2 -1
  73. data/smoke/block3.rb +3 -3
  74. data/smoke/block4.rb +3 -2
  75. data/smoke/block5.rb +3 -2
  76. data/smoke/block6.rb +3 -2
  77. data/smoke/block7.rb +2 -1
  78. data/smoke/block8.rb +4 -3
  79. data/smoke/block9.rb +2 -1
  80. data/smoke/blown.rb +2 -1
  81. data/smoke/break1.rb +3 -2
  82. data/smoke/break2.rb +2 -1
  83. data/smoke/break3.rb +13 -0
  84. data/smoke/case.rb +2 -1
  85. data/smoke/case2.rb +2 -1
  86. data/smoke/case3.rb +17 -0
  87. data/smoke/class-hierarchy.rb +5 -5
  88. data/smoke/class-hierarchy2.rb +3 -3
  89. data/smoke/class-new.rb +15 -0
  90. data/smoke/class_instance_var.rb +1 -1
  91. data/smoke/class_method.rb +2 -2
  92. data/smoke/class_method2.rb +2 -2
  93. data/smoke/class_method3.rb +4 -2
  94. data/smoke/constant1.rb +6 -6
  95. data/smoke/constant2.rb +5 -4
  96. data/smoke/constant3.rb +2 -1
  97. data/smoke/constant4.rb +2 -1
  98. data/smoke/context-sensitive1.rb +2 -1
  99. data/smoke/cvar.rb +6 -5
  100. data/smoke/cvar2.rb +2 -2
  101. data/smoke/define_method.rb +16 -0
  102. data/smoke/define_method2.rb +18 -0
  103. data/smoke/define_method3.rb +13 -0
  104. data/smoke/define_method3.rbs +3 -0
  105. data/smoke/define_method4.rb +15 -0
  106. data/smoke/define_method4.rbs +3 -0
  107. data/smoke/define_method5.rb +12 -0
  108. data/smoke/demo.rb +7 -6
  109. data/smoke/demo1.rb +2 -1
  110. data/smoke/demo10.rb +3 -2
  111. data/smoke/demo11.rb +2 -1
  112. data/smoke/demo2.rb +2 -1
  113. data/smoke/demo3.rb +2 -1
  114. data/smoke/demo4.rb +3 -3
  115. data/smoke/demo5.rb +1 -1
  116. data/smoke/demo6.rb +3 -3
  117. data/smoke/demo7.rb +2 -1
  118. data/smoke/demo8.rb +3 -2
  119. data/smoke/demo9.rb +3 -2
  120. data/smoke/dummy-execution1.rb +3 -2
  121. data/smoke/dummy-execution2.rb +2 -2
  122. data/smoke/dummy_element.rb +14 -0
  123. data/smoke/ensure1.rb +3 -2
  124. data/smoke/enumerator.rb +3 -2
  125. data/smoke/expandarray1.rb +2 -1
  126. data/smoke/expandarray2.rb +2 -1
  127. data/smoke/fib.rb +2 -2
  128. data/smoke/flip-flop.rb +28 -0
  129. data/smoke/flow1.rb +2 -1
  130. data/smoke/flow2.rb +2 -1
  131. data/smoke/flow3.rb +2 -1
  132. data/smoke/flow5.rb +2 -1
  133. data/smoke/flow6.rb +2 -1
  134. data/smoke/flow7.rb +2 -1
  135. data/smoke/flow8.rb +2 -1
  136. data/smoke/flow9.rb +12 -0
  137. data/smoke/freeze.rb +2 -1
  138. data/smoke/function.rb +3 -2
  139. data/smoke/gvar.rb +3 -2
  140. data/smoke/gvar2.rb +3 -2
  141. data/smoke/hash-bot.rb +12 -0
  142. data/smoke/hash-fetch.rb +4 -3
  143. data/smoke/hash-merge-bang.rb +2 -1
  144. data/smoke/hash1.rb +3 -2
  145. data/smoke/hash2.rb +2 -1
  146. data/smoke/hash3.rb +2 -1
  147. data/smoke/hash4.rb +2 -1
  148. data/smoke/hash5.rb +1 -1
  149. data/smoke/inheritance.rb +4 -4
  150. data/smoke/inheritance2.rb +2 -2
  151. data/smoke/initialize.rb +6 -5
  152. data/smoke/instance_eval.rb +2 -2
  153. data/smoke/instance_eval2.rb +10 -0
  154. data/smoke/instance_eval3.rb +25 -0
  155. data/smoke/int_times.rb +2 -1
  156. data/smoke/integer.rb +2 -1
  157. data/smoke/ivar.rb +5 -4
  158. data/smoke/ivar2.rb +4 -4
  159. data/smoke/ivar3.rb +2 -2
  160. data/smoke/kernel-class.rb +2 -1
  161. data/smoke/keyword1.rb +2 -1
  162. data/smoke/keyword2.rb +2 -1
  163. data/smoke/keyword3.rb +2 -1
  164. data/smoke/keyword4.rb +2 -1
  165. data/smoke/keyword5.rb +2 -1
  166. data/smoke/kwrest.rb +12 -0
  167. data/smoke/kwrest.rbs +3 -0
  168. data/smoke/kwsplat1.rb +5 -4
  169. data/smoke/kwsplat2.rb +2 -1
  170. data/smoke/lit-complex.rb +10 -0
  171. data/smoke/lit-encoding.rb +10 -0
  172. data/smoke/manual-rbs.rb +4 -3
  173. data/smoke/manual-rbs2.rb +2 -1
  174. data/smoke/manual-rbs3.rb +2 -2
  175. data/smoke/masgn1.rb +2 -1
  176. data/smoke/masgn2.rb +3 -2
  177. data/smoke/masgn3.rb +2 -1
  178. data/smoke/method_in_branch.rb +3 -2
  179. data/smoke/method_missing.rb +28 -0
  180. data/smoke/module1.rb +2 -2
  181. data/smoke/module2.rb +1 -1
  182. data/smoke/module3.rb +2 -2
  183. data/smoke/module4.rb +2 -2
  184. data/smoke/module5.rb +17 -0
  185. data/smoke/module6.rb +40 -0
  186. data/smoke/module_function1.rb +3 -3
  187. data/smoke/module_function2.rb +3 -3
  188. data/smoke/multiple-include.rb +1 -1
  189. data/smoke/multiple-superclass.rb +1 -1
  190. data/smoke/next1.rb +3 -2
  191. data/smoke/next2.rb +2 -1
  192. data/smoke/object-send1.rb +4 -3
  193. data/smoke/object-send2.rb +10 -0
  194. data/smoke/object-send3.rb +18 -0
  195. data/smoke/once.rb +2 -1
  196. data/smoke/optional1.rb +2 -1
  197. data/smoke/optional2.rb +2 -1
  198. data/smoke/optional3.rb +2 -1
  199. data/smoke/parameterizedd-self.rb +3 -2
  200. data/smoke/parameterizedd-self2.rb +15 -0
  201. data/smoke/pathname1.rb +2 -1
  202. data/smoke/pathname2.rb +2 -1
  203. data/smoke/pattern-match1.rb +2 -1
  204. data/smoke/pattern-match2.rb +2 -1
  205. data/smoke/printf.rb +2 -2
  206. data/smoke/proc.rb +3 -2
  207. data/smoke/proc2.rb +2 -1
  208. data/smoke/proc3.rb +2 -1
  209. data/smoke/proc4.rb +2 -1
  210. data/smoke/proc5.rb +19 -0
  211. data/smoke/public.rb +34 -0
  212. data/smoke/range.rb +2 -1
  213. data/smoke/rbs-alias.rb +2 -1
  214. data/smoke/rbs-attr.rb +6 -5
  215. data/smoke/rbs-attr2.rb +11 -0
  216. data/smoke/rbs-attr2.rbs +3 -0
  217. data/smoke/rbs-extend.rb +2 -1
  218. data/smoke/rbs-interface.rb +5 -4
  219. data/smoke/rbs-module.rb +26 -0
  220. data/smoke/rbs-module.rbs +4 -0
  221. data/smoke/rbs-opt-and-rest.rb +10 -0
  222. data/smoke/rbs-opt-and-rest.rbs +3 -0
  223. data/smoke/rbs-proc1.rb +2 -1
  224. data/smoke/rbs-proc2.rb +3 -2
  225. data/smoke/rbs-proc3.rb +2 -1
  226. data/smoke/rbs-record.rb +3 -2
  227. data/smoke/rbs-tyvar.rb +3 -2
  228. data/smoke/rbs-tyvar2.rb +3 -2
  229. data/smoke/rbs-tyvar3.rb +3 -2
  230. data/smoke/rbs-tyvar4.rb +3 -3
  231. data/smoke/rbs-tyvar5.rb +2 -1
  232. data/smoke/rbs-tyvar6.rb +18 -0
  233. data/smoke/rbs-tyvar6.rbs +12 -0
  234. data/smoke/rbs-tyvar7.rb +12 -0
  235. data/smoke/rbs-tyvar7.rbs +7 -0
  236. data/smoke/rbs-vars.rb +7 -8
  237. data/smoke/redo1.rb +3 -2
  238. data/smoke/redo2.rb +3 -2
  239. data/smoke/req-keyword.rb +2 -1
  240. data/smoke/rescue1.rb +3 -2
  241. data/smoke/rescue2.rb +3 -2
  242. data/smoke/rescue3.rb +19 -0
  243. data/smoke/rescue4.rb +17 -0
  244. data/smoke/respond_to.rb +2 -1
  245. data/smoke/rest-farg.rb +2 -1
  246. data/smoke/rest1.rb +3 -2
  247. data/smoke/rest2.rb +2 -1
  248. data/smoke/rest3.rb +7 -6
  249. data/smoke/rest4.rb +3 -2
  250. data/smoke/rest5.rb +2 -1
  251. data/smoke/rest6.rb +2 -1
  252. data/smoke/retry1.rb +3 -2
  253. data/smoke/return.rb +2 -1
  254. data/smoke/singleton_method.rb +1 -1
  255. data/smoke/step.rb +4 -3
  256. data/smoke/string-split.rb +2 -1
  257. data/smoke/struct-keyword_init.rb +20 -0
  258. data/smoke/struct.rb +1 -1
  259. data/smoke/struct2.rb +5 -4
  260. data/smoke/struct3.rb +2 -2
  261. data/smoke/struct4.rb +7 -0
  262. data/smoke/struct5.rb +16 -0
  263. data/smoke/struct6.rb +15 -0
  264. data/smoke/struct7.rb +17 -0
  265. data/smoke/stub-keyword.rb +10 -0
  266. data/smoke/super1.rb +5 -4
  267. data/smoke/super2.rb +1 -1
  268. data/smoke/super3.rb +3 -3
  269. data/smoke/super4.rb +43 -0
  270. data/smoke/super5.rb +36 -0
  271. data/smoke/svar1.rb +2 -1
  272. data/smoke/symbol-proc-attr.rb +22 -0
  273. data/smoke/symbol-proc-attr2.rb +15 -0
  274. data/smoke/symbol-proc-bot.rb +13 -0
  275. data/smoke/symbol-proc.rb +4 -3
  276. data/smoke/tap1.rb +3 -2
  277. data/smoke/toplevel.rb +2 -1
  278. data/smoke/two-map.rb +3 -2
  279. data/smoke/type_var.rb +2 -1
  280. data/smoke/typed_method.rb +2 -1
  281. data/smoke/uninitialize-var.rb +2 -1
  282. data/smoke/union-recv.rb +2 -2
  283. data/smoke/user-demo.rb +3 -3
  284. data/smoke/wrong-extend.rb +2 -2
  285. data/smoke/wrong-include.rb +2 -2
  286. data/smoke/wrong-include2.rb +17 -0
  287. data/typeprof.gemspec +1 -1
  288. metadata +61 -6
  289. data/tools/stackprof-wrapper.rb +0 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d60066fe3965ec65f9885e311f856277d0e41330478489c026fdf6b387ba2ba
4
- data.tar.gz: 963b66fe97d98207d72645011bcd012368937ded76278d92a4b677b961c92cdc
3
+ metadata.gz: 1c3bf54ec6fee3b06397893d2f10f1fae8e7af82b8f1640a4ddd305c33922ff7
4
+ data.tar.gz: 944d40a75789b4805e53ca70e169fe68fcd4dbca7f24bc4ccc779964085e980d
5
5
  SHA512:
6
- metadata.gz: a40e89e05c1680480eb66798863ab99a4b38b3faaacdc471a6cdd45dfc1f897efcc8f613800ef28e5bc722c3504dec510ca943435873b6cb765a27f1bb073425
7
- data.tar.gz: 94dddf2c3e465ee19093ce571d50440293118b07ab7c90203aa5ccb40c4f9eb9afe1059eff045c965006affa8f0d66d141be2064feddf9a2b1f8384f8cadae64
6
+ metadata.gz: 726cdbfcda694f189a96f3f35088cbcbd9a3064e79e3838f7758d7bc393bf8591c0559db1c17993f971f9ae2ee4ca3b4c09f5c0ef6d6675752b00b6948cdfe62
7
+ data.tar.gz: b2b7353855183df391d8bc78c247eb7de09c1b65b2753789eb1e1fb0208275d10fec6d2d95745f36771de30af5e32281476100a0654db6f7cf87c8e442b36a65
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- typeprof (0.5.4)
5
- rbs (>= 0.17.0)
4
+ typeprof (0.9.0)
5
+ rbs (>= 0.20.0)
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
 
@@ -281,11 +292,10 @@ module TypeProf
281
292
  attr_reader :class_defs
282
293
 
283
294
  class ClassDef # or ModuleDef
284
- def initialize(kind, name, superclass, absolute_path)
295
+ def initialize(kind, name, absolute_path)
285
296
  raise unless name.is_a?(Array)
286
297
  @kind = kind
287
- @superclass = superclass
288
- @modules = { true => {}, false => {} }
298
+ @modules = { true => [], false => [] }
289
299
  @name = name
290
300
  @consts = {}
291
301
  @methods = {}
@@ -295,14 +305,16 @@ module TypeProf
295
305
  @namespace = nil
296
306
  end
297
307
 
298
- attr_reader :kind, :superclass, :modules, :consts, :methods, :ivars, :cvars, :absolute_path
308
+ attr_reader :kind, :modules, :consts, :methods, :ivars, :cvars, :absolute_path
299
309
  attr_accessor :name, :klass_obj
300
310
 
301
- def include_module(mod, singleton, absolute_path)
302
- # XXX: need to check if mod is already included by the ancestors?
303
- absolute_paths = @modules[singleton][mod]
304
- unless absolute_paths
305
- @modules[singleton][mod] = absolute_paths = Utils::MutableSet.new
311
+ def include_module(mod, type_args, singleton, absolute_path)
312
+ mod_, module_type_args, absolute_paths = @modules[singleton].find {|m,| m == mod }
313
+ if mod_
314
+ raise "inconsistent include/extend type args in RBS?" if module_type_args != type_args && type_args != [] && type_args != nil
315
+ else
316
+ absolute_paths = Utils::MutableSet.new
317
+ @modules[singleton].unshift([mod, type_args, absolute_paths])
306
318
  end
307
319
  absolute_paths << absolute_path
308
320
  end
@@ -319,13 +331,29 @@ module TypeProf
319
331
  @consts[name] = [ty, absolute_path]
320
332
  end
321
333
 
322
- def get_method(mid, singleton)
323
- @methods[[singleton, mid]] || begin
324
- @modules[singleton].each_key do |mod|
325
- meth = mod.get_method(mid, false)
326
- return meth if meth
334
+ def adjust_substitution(singleton, mid, mthd, subst, direct, &blk)
335
+ mthds = @methods[[singleton, mid]]
336
+ yield subst, direct if mthds&.include?(mthd)
337
+ @modules[singleton].each do |mod_def, type_args,|
338
+ if mod_def.klass_obj.type_params && type_args
339
+ subst2 = {}
340
+ mod_def.klass_obj.type_params.zip(type_args) do |(tyvar, *), tyarg|
341
+ tyvar = Type::Var.new(tyvar)
342
+ subst2[tyvar] = tyarg.substitute(subst, Config.options[:type_depth_limit])
343
+ end
344
+ mod_def.adjust_substitution(false, mid, mthd, subst2, false, &blk)
327
345
  end
328
- nil
346
+ end
347
+ end
348
+
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
353
+ mthds = @methods[[singleton, mid]]
354
+ yield mthds, @klass_obj, singleton if mthds
355
+ @modules[singleton].each do |mod_def,|
356
+ mod_def.search_method(false, mid, visited, &blk)
329
357
  end
330
358
  end
331
359
 
@@ -344,12 +372,16 @@ module TypeProf
344
372
  end
345
373
 
346
374
  def set_method(mid, singleton, mdef)
347
- @methods[[singleton, mid]] = Utils::MutableSet.new
348
- @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
349
381
  end
350
382
  end
351
383
 
352
- def include_module(including_mod, included_mod, singleton, absolute_path)
384
+ def include_module(including_mod, included_mod, type_args, singleton, caller_ep)
353
385
  return if included_mod == Type.any
354
386
 
355
387
  including_mod = @class_defs[including_mod.idx]
@@ -357,9 +389,9 @@ module TypeProf
357
389
  if included_mod.is_a?(Type::Class)
358
390
  included_mod = @class_defs[included_mod.idx]
359
391
  if included_mod && included_mod.kind == :module
360
- including_mod.include_module(included_mod, singleton, absolute_path)
392
+ including_mod.include_module(included_mod, type_args, singleton, caller_ep ? caller_ep.ctx.iseq.absolute_path : nil)
361
393
  else
362
- warn "including something that is not a module"
394
+ warn(caller_ep, "including something that is not a module")
363
395
  end
364
396
  end
365
397
  end
@@ -373,12 +405,7 @@ module TypeProf
373
405
  show_name = cbase_path(cbase) + [name]
374
406
  idx = @class_defs.size
375
407
  if superclass
376
- if superclass == :__root__
377
- superclass_idx = superclass = nil
378
- else
379
- superclass_idx = superclass.idx
380
- end
381
- @class_defs[idx] = ClassDef.new(:class, show_name, superclass_idx, absolute_path)
408
+ @class_defs[idx] = ClassDef.new(:class, show_name, absolute_path)
382
409
  klass = Type::Class.new(:class, idx, type_params, superclass, show_name)
383
410
  @class_defs[idx].klass_obj = klass
384
411
  cbase ||= klass # for bootstrap
@@ -386,7 +413,7 @@ module TypeProf
386
413
  return klass
387
414
  else
388
415
  # module
389
- @class_defs[idx] = ClassDef.new(:module, show_name, nil, absolute_path)
416
+ @class_defs[idx] = ClassDef.new(:module, show_name, absolute_path)
390
417
  mod = Type::Class.new(:module, idx, type_params, nil, show_name)
391
418
  @class_defs[idx].klass_obj = mod
392
419
  add_constant(cbase, name, mod, absolute_path)
@@ -394,14 +421,19 @@ module TypeProf
394
421
  end
395
422
  end
396
423
 
424
+ def add_superclass_type_args!(klass, tyargs)
425
+ klass.superclass_type_args = tyargs
426
+ end
427
+
397
428
  def new_struct(ep)
398
429
  return @struct_defs[ep] if @struct_defs[ep]
399
430
 
400
431
  idx = @class_defs.size
401
432
  superclass = Type::Builtin[:struct]
402
433
  name = "AnonymousStruct_generated_#{ @anonymous_struct_gen_id += 1 }"
403
- @class_defs[idx] = ClassDef.new(:class, [name], superclass.idx, ep.ctx.iseq.absolute_path)
434
+ @class_defs[idx] = ClassDef.new(:class, [name], ep.ctx.iseq.absolute_path)
404
435
  klass = Type::Class.new(:class, idx, [], superclass, name)
436
+ add_superclass_type_args!(klass, [Type.any])
405
437
  @class_defs[idx].klass_obj = klass
406
438
 
407
439
  @struct_defs[ep] = klass
@@ -431,28 +463,77 @@ module TypeProf
431
463
  end
432
464
  end
433
465
 
466
+ def adjust_substitution(klass, singleton, mid, mthd, subst, &blk)
467
+ direct = true
468
+ if klass.kind == :class
469
+ while klass != :__root__
470
+ class_def = @class_defs[klass.idx]
471
+ class_def.adjust_substitution(singleton, mid, mthd, subst, direct, &blk)
472
+ direct = false
473
+ if klass.superclass && klass.superclass_type_args
474
+ subst2 = {}
475
+ klass.superclass.type_params.zip(klass.superclass_type_args) do |(tyvar, *), tyarg|
476
+ tyvar = Type::Var.new(tyvar)
477
+ subst2[tyvar] = tyarg.substitute(subst, Config.options[:type_depth_limit])
478
+ end
479
+ subst = subst2
480
+ end
481
+ klass = klass.superclass
482
+ end
483
+ else
484
+ # module
485
+ class_def = @class_defs[klass.idx]
486
+ class_def.adjust_substitution(singleton, mid, mthd, subst, direct, &blk)
487
+ end
488
+ end
489
+
490
+ def search_method(klass, singleton, mid, &blk)
491
+ # XXX: support method alias correctly
492
+ klass_orig = klass
493
+ if klass.kind == :class
494
+ while klass != :__root__
495
+ class_def = @class_defs[klass.idx]
496
+ class_def.search_method(singleton, mid, {}, &blk)
497
+ klass = klass.superclass
498
+ end
499
+ else
500
+ # module
501
+ class_def = @class_defs[klass.idx]
502
+ class_def.search_method(singleton, mid, {}, &blk)
503
+ end
504
+ if singleton
505
+ search_method(Type::Builtin[klass_orig.kind], false, mid, &blk)
506
+ end
507
+ end
508
+
434
509
  def get_method(klass, singleton, mid)
435
- idx = klass.idx
436
- while idx
437
- class_def = @class_defs[idx]
438
- mthd = class_def.get_method(mid, singleton)
439
- # Need to be conservative to include all super candidates...?
440
- return mthd if mthd
441
- idx = class_def.superclass
510
+ search_method(klass, singleton, mid) {|mthds,| return mthds }
511
+ end
512
+
513
+ def get_all_super_methods(klass, singleton, current_klass, mid)
514
+ hit = false
515
+ search_method(klass, singleton, mid) do |mthds, klass0, singleton0|
516
+ yield mthds, klass0, singleton0 if hit
517
+ hit = klass0 == current_klass
442
518
  end
443
- return get_method(Type::Builtin[:class], false, mid) if singleton
444
- nil
445
519
  end
446
520
 
447
521
  def get_super_method(ctx, singleton)
448
- idx = ctx.cref.klass.idx
522
+ klass = ctx.cref.klass
449
523
  mid = ctx.mid
450
- idx = @class_defs[idx].superclass
451
- while idx
452
- class_def = @class_defs[idx]
524
+ if klass.kind == :class
525
+ klass = klass.superclass
526
+ while klass != :__root__
527
+ class_def = @class_defs[klass.idx]
528
+ mthd = class_def.get_method(mid, singleton)
529
+ return mthd if mthd
530
+ klass = klass.superclass
531
+ end
532
+ else
533
+ # module
534
+ class_def = @class_defs[klass.idx]
453
535
  mthd = class_def.get_method(mid, singleton)
454
536
  return mthd if mthd
455
- idx = class_def.superclass
456
537
  end
457
538
  nil
458
539
  end
@@ -478,9 +559,7 @@ module TypeProf
478
559
  end
479
560
 
480
561
  def add_constant(klass, name, value, user_defined)
481
- if klass == Type.any
482
- self
483
- else
562
+ if klass.is_a?(Type::Class)
484
563
  @class_defs[klass.idx].add_constant(name, value, user_defined)
485
564
  end
486
565
  end
@@ -508,12 +587,12 @@ module TypeProf
508
587
  end
509
588
  end
510
589
 
511
- def add_iseq_method(klass, mid, iseq, cref)
512
- 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))
513
592
  end
514
593
 
515
- def add_singleton_iseq_method(klass, mid, iseq, cref)
516
- 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))
517
596
  end
518
597
 
519
598
  def set_custom_method(klass, mid, impl)
@@ -546,6 +625,10 @@ module TypeProf
546
625
  @iseq_method_to_ctxs[iseq_mdef] << ctx
547
626
  end
548
627
 
628
+ def add_executed_iseq(iseq)
629
+ @executed_iseqs << iseq
630
+ end
631
+
549
632
  def add_callsite!(callee_ctx, caller_ep, caller_env, &ctn)
550
633
  @executed_iseqs << callee_ctx.iseq if callee_ctx.is_a?(Context)
551
634
 
@@ -605,7 +688,7 @@ module TypeProf
605
688
  def add_read!(site, ep, &ctn)
606
689
  entry = @tbl[site] ||= Entry.new(false, {}, Type.bot, Utils::MutableSet.new)
607
690
  entry.read_continuations[ep] = ctn
608
- entry.absolute_paths << ep.ctx.iseq.absolute_path
691
+ entry.absolute_paths << ep.ctx.iseq.absolute_path if ep.ctx.is_a?(Context)
609
692
  ctn[entry.type, ep]
610
693
  end
611
694
 
@@ -664,6 +747,7 @@ module TypeProf
664
747
 
665
748
  def add_cvar_read!(klass, var, ep, &ctn)
666
749
  klass.each_child do |klass|
750
+ next unless klass.is_a?(Type::Class)
667
751
  class_def = @class_defs[klass.idx]
668
752
  next unless class_def
669
753
  class_def.cvars.add_read!(var, ep, &ctn)
@@ -672,6 +756,7 @@ module TypeProf
672
756
 
673
757
  def add_cvar_write!(klass, var, ty, ep)
674
758
  klass.each_child do |klass|
759
+ next unless klass.is_a?(Type::Class)
675
760
  class_def = @class_defs[klass.idx]
676
761
  next unless class_def
677
762
  class_def.cvars.add_write!(var, ty, ep, self)
@@ -722,7 +807,7 @@ module TypeProf
722
807
  merge_return_env(tmp_ep) do |menv|
723
808
  elems = menv.get_container_elem_types(id)
724
809
  elems = yield elems
725
- menv = menv.update_container_elem_types(id, elems)
810
+ menv = menv.deploy_type(id, elems)
726
811
  gid = @alloc_site_to_global_id[id]
727
812
  if gid
728
813
  ty = globalize_type(elems.to_local_type(id, base_type), env, ep)
@@ -734,7 +819,7 @@ module TypeProf
734
819
  else
735
820
  elems = env.get_container_elem_types(id)
736
821
  elems = yield elems
737
- env = env.update_container_elem_types(id, elems)
822
+ env = env.deploy_type(id, elems)
738
823
  gid = @alloc_site_to_global_id[id]
739
824
  if gid
740
825
  ty = globalize_type(elems.to_local_type(id, base_type), env, ep)
@@ -775,11 +860,11 @@ module TypeProf
775
860
  ep = @worklist.deletemin
776
861
 
777
862
  iter_counter += 1
778
- if Config.verbose >= 1
863
+ if Config.options[:show_indicator]
779
864
  tick2 = Time.now
780
865
  if tick2 - tick >= 1
781
866
  tick = tick2
782
- $stderr << "\rType Profiling... (%d steps @ %s)\e[K" % [iter_counter, ep.source_location]
867
+ $stderr << "\rType Profiling... (%d instructions @ %s)\e[K" % [iter_counter, ep.source_location]
783
868
  $stderr.flush
784
869
  end
785
870
  end
@@ -795,9 +880,7 @@ module TypeProf
795
880
 
796
881
  break if @terminated
797
882
 
798
- # XXX: it would be good to provide no-dummy-execution mode.
799
- # It should work as a bit smarter "rbs prototype rb";
800
- # show all method definitions as "untyped" arguments and return values
883
+ break unless Config.options[:stub_execution]
801
884
 
802
885
  begin
803
886
  iseq, (kind, dummy_continuation) = @pending_execution.first
@@ -805,7 +888,7 @@ module TypeProf
805
888
  @pending_execution.delete(iseq)
806
889
  end while @executed_iseqs.include?(iseq)
807
890
 
808
- puts "DEBUG: trigger dummy execution (#{ iseq&.name || "(nil)" }): rest #{ @pending_execution.size }" if Config.verbose >= 2
891
+ puts "DEBUG: trigger stub execution (#{ iseq&.name || "(nil)" }): rest #{ @pending_execution.size }" if Config.verbose >= 2
809
892
 
810
893
  break if !iseq
811
894
  case kind
@@ -822,7 +905,7 @@ module TypeProf
822
905
  end
823
906
  end
824
907
  end
825
- $stderr.print "\r\e[K" if Config.verbose >= 1
908
+ $stderr.print "\r\e[K" if Config.options[:show_indicator]
826
909
 
827
910
  stat_eps
828
911
  end
@@ -863,9 +946,9 @@ module TypeProf
863
946
  end
864
947
  end
865
948
 
866
- def pend_method_execution(iseq, meth, recv, mid, cref)
949
+ def pend_method_execution(iseq, meth, recv, mid, cref, ep)
867
950
  ctx = Context.new(iseq, cref, mid)
868
- ep = ExecutionPoint.new(ctx, 0, nil)
951
+ ep = ExecutionPoint.new(ctx, 0, ep)
869
952
  locals = [Type.nil] * iseq.locals.size
870
953
 
871
954
  fargs_format = iseq.fargs_format
@@ -900,17 +983,23 @@ module TypeProf
900
983
  locals[kwrest_index] = Type.any if kwrest_index
901
984
  locals[block_index] = Type.nil if block_index
902
985
 
903
- env = Env.new(StaticEnv.new(recv, Type.nil, false), locals, [], Utils::HashWrapper.new({}))
986
+ env = Env.new(StaticEnv.new(recv, Type.nil, false, true), locals, [], Utils::HashWrapper.new({}))
904
987
 
905
- @pending_execution[iseq] ||= [:method, [meth, ep, env]]
988
+ if !@pending_execution[iseq] || @pending_execution[iseq][0] == :block
989
+ @pending_execution[iseq] = [:method, [meth, ep, env]]
990
+ end
906
991
  end
907
992
 
908
993
  def pend_block_dummy_execution(blk, iseq, nep, nenv)
909
994
  @pending_execution[iseq] ||= [:block, [blk, {}]]
910
- if @pending_execution[iseq][1][1][nep]
911
- @pending_execution[iseq][1][1][nep] = @pending_execution[iseq][1][1][nep].merge(nenv)
995
+ if @pending_execution[iseq][0] == :block
996
+ if @pending_execution[iseq][1][1][nep]
997
+ @pending_execution[iseq][1][1][nep] = @pending_execution[iseq][1][1][nep].merge(nenv)
998
+ else
999
+ @pending_execution[iseq][1][1][nep] = nenv
1000
+ end
912
1001
  else
913
- @pending_execution[iseq][1][1][nep] = nenv
1002
+ # XXX: what to do?
914
1003
  end
915
1004
  end
916
1005
 
@@ -919,7 +1008,7 @@ module TypeProf
919
1008
  alloc_site = AllocationSite.new(ep)
920
1009
  nenv, ty = localize_type(ty, env, ep, alloc_site)
921
1010
  case ty
922
- when Type::LocalCell, Type::LocalArray, Type::LocalHash
1011
+ when Type::Local
923
1012
  @alloc_site_to_global_id[ty.id] = [recv, var] # need overwrite check??
924
1013
  end
925
1014
  yield ty, nenv
@@ -959,7 +1048,7 @@ module TypeProf
959
1048
  block_start = iseq.fargs_format[:block_start]
960
1049
 
961
1050
  lead_tys = env.locals[0, lead_num].map {|ty| globalize_type(ty, env, ep) }
962
- opt_tys = opt.size > 1 ? env.locals[lead_num, opt.size - 1].map {|ty| globalize_type(ty, env, ep) } : nil
1051
+ opt_tys = opt.size > 1 ? env.locals[lead_num, opt.size - 1].map {|ty| globalize_type(ty, env, ep) } : []
963
1052
  if rest_start # XXX:squash
964
1053
  ty = globalize_type(env.locals[lead_num + opt.size - 1], env, ep)
965
1054
  rest_ty = Type.bot
@@ -1085,31 +1174,7 @@ module TypeProf
1085
1174
 
1086
1175
  when :definemethod
1087
1176
  mid, iseq = operands
1088
- cref = ep.ctx.cref
1089
- recv = env.static_env.recv_ty
1090
- if cref.klass.is_a?(Type::Class)
1091
- typed_mdef = check_typed_method(cref.klass, mid, ep.ctx.cref.singleton)
1092
- recv = Type::Instance.new(recv) if recv.is_a?(Type::Class)
1093
- if typed_mdef
1094
- mdef = ISeqMethodDef.new(iseq, cref)
1095
- typed_mdef.each do |typed_mdef|
1096
- typed_mdef.do_match_iseq_mdef(mdef, recv, mid, env, ep, self)
1097
- end
1098
- else
1099
- if ep.ctx.cref.singleton
1100
- meth = add_singleton_iseq_method(cref.klass, mid, iseq, cref)
1101
- else
1102
- meth = add_iseq_method(cref.klass, mid, iseq, cref)
1103
- if env.static_env.mod_func
1104
- add_singleton_iseq_method(cref.klass, mid, iseq, cref)
1105
- end
1106
- end
1107
-
1108
- pend_method_execution(iseq, meth, recv, mid, ep.ctx.cref)
1109
- end
1110
- else
1111
- # XXX: what to do?
1112
- end
1177
+ do_define_iseq_method(ep, env, mid, iseq, nil)
1113
1178
 
1114
1179
  when :definesmethod
1115
1180
  mid, iseq = operands
@@ -1117,8 +1182,8 @@ module TypeProf
1117
1182
  cref = ep.ctx.cref
1118
1183
  recv.each_child do |recv|
1119
1184
  if recv.is_a?(Type::Class)
1120
- meth = add_singleton_iseq_method(recv, mid, iseq, cref)
1121
- pend_method_execution(iseq, meth, recv, mid, ep.ctx.cref)
1185
+ meth = add_singleton_iseq_method(recv, mid, iseq, cref, nil, env.static_env.pub_meth)
1186
+ pend_method_execution(iseq, meth, recv, mid, ep.ctx.cref, nil)
1122
1187
  else
1123
1188
  recv = Type.any # XXX: what to do?
1124
1189
  end
@@ -1154,10 +1219,11 @@ module TypeProf
1154
1219
  else # module
1155
1220
  superclass = nil
1156
1221
  end
1157
- if cbase == Type.any
1158
- klass = Type.any
1159
- else
1222
+ if cbase.is_a?(Type::Class)
1160
1223
  klass = new_class(cbase, id, [], superclass, ep.ctx.iseq.absolute_path)
1224
+ add_superclass_type_args!(klass, superclass.type_params.map { Type.any }) if superclass
1225
+ else
1226
+ klass = Type.any
1161
1227
  end
1162
1228
  end
1163
1229
  singleton = false
@@ -1179,7 +1245,7 @@ module TypeProf
1179
1245
  nctx = Context.new(iseq, ncref, nil)
1180
1246
  nep = ExecutionPoint.new(nctx, 0, nil)
1181
1247
  locals = [Type.nil] * iseq.locals.size
1182
- nenv = Env.new(StaticEnv.new(recv, blk, false), locals, [], Utils::HashWrapper.new({}))
1248
+ nenv = Env.new(StaticEnv.new(recv, blk, false, true), locals, [], Utils::HashWrapper.new({}))
1183
1249
  merge_env(nep, nenv)
1184
1250
  add_callsite!(nep.ctx, ep, env) do |ret_ty, ep, env|
1185
1251
  nenv, ret_ty = localize_type(ret_ty, env, ep)
@@ -1245,30 +1311,30 @@ module TypeProf
1245
1311
  end
1246
1312
  when :invokesuper
1247
1313
  env, recv, _, aargs = setup_actual_arguments(:method, operands, ep, env)
1248
-
1249
- env, recv = localize_type(env.static_env.recv_ty, env, ep)
1250
- mid = ep.ctx.mid
1251
- singleton = !recv.is_a?(Type::Instance) # TODO: any?
1252
- # XXX: need to support included module...
1253
- meths = get_super_method(ep.ctx, singleton) # TODO: multiple return values
1254
- if meths
1255
- meths.each do |meth|
1256
- # XXX: this decomposition is really needed??
1257
- # It calls `Object.new` with union receiver which causes an error, but
1258
- # it may be a fault of builtin Object.new implementation.
1259
- recv.each_child do |recv|
1260
- meth.do_send(recv, mid, aargs, ep, env, self) do |ret_ty, ep, env|
1261
- nenv, ret_ty, = localize_type(ret_ty, env, ep)
1262
- nenv = nenv.push(ret_ty)
1263
- merge_env(ep.next, nenv)
1314
+ mid = ep.ctx.mid
1315
+ found = false
1316
+ recv.each_child_global do |recv|
1317
+ klass, singleton = recv.method_dispatch_info
1318
+ next unless klass
1319
+ get_all_super_methods(klass, singleton, ep.ctx.cref.klass, ep.ctx.mid) do |meths, klass|
1320
+ found = true
1321
+ meths.each do |meth|
1322
+ # XXX: this decomposition is really needed??
1323
+ # It calls `Object.new` with union receiver which causes an error, but
1324
+ # it may be a fault of builtin Object.new implementation.
1325
+ recv.each_child do |recv|
1326
+ meth.do_send(recv, mid, aargs, ep, env, self) do |ret_ty, ep, env|
1327
+ nenv, ret_ty, = localize_type(ret_ty, env, ep)
1328
+ nenv = nenv.push(ret_ty)
1329
+ merge_env(ep.next, nenv)
1330
+ end
1264
1331
  end
1265
1332
  end
1266
1333
  end
1267
- return
1268
- else
1269
- error(ep, "no superclass method: #{ env.static_env.recv_ty.screen_name(self) }##{ mid }")
1270
- env = env.push(Type.any)
1271
1334
  end
1335
+ return if found
1336
+ error(ep, "no superclass method: #{ env.static_env.recv_ty.screen_name(self) }##{ mid }")
1337
+ env = env.push(Type.any)
1272
1338
  when :invokebuiltin
1273
1339
  raise NotImplementedError
1274
1340
  when :leave
@@ -1295,11 +1361,24 @@ module TypeProf
1295
1361
  return
1296
1362
  when :break
1297
1363
  tmp_ep = ep
1298
- tmp_ep = tmp_ep.outer while tmp_ep.ctx.iseq.type != :block
1299
- tmp_ep = tmp_ep.outer
1300
- nenv = @return_envs[tmp_ep].push(ty)
1301
- merge_env(tmp_ep.next, nenv)
1302
- # TODO: jump to ensure?
1364
+ while true
1365
+ if tmp_ep.ctx.iseq.type == :block
1366
+ tmp_ep = tmp_ep.outer
1367
+ nenv = @return_envs[tmp_ep].push(ty)
1368
+ merge_env(tmp_ep.next, nenv)
1369
+ break
1370
+ end
1371
+ _type, _iseq, cont, stack_depth = tmp_ep.ctx.iseq.catch_table[tmp_ep.pc]&.find {|type,| type == :break }
1372
+ if cont
1373
+ nenv = @return_envs[tmp_ep]
1374
+ nenv, = nenv.pop(nenv.stack.size - stack_depth)
1375
+ nenv = nenv.push(ty)
1376
+ tmp_ep = tmp_ep.jump(cont)
1377
+ merge_env(tmp_ep, nenv)
1378
+ break
1379
+ end
1380
+ tmp_ep = tmp_ep.outer
1381
+ end
1303
1382
  when :next, :redo
1304
1383
  # begin; rescue; next; end
1305
1384
  tmp_ep = ep.outer
@@ -1492,9 +1571,7 @@ module TypeProf
1492
1571
  ret_ty.each_child do |ret_ty|
1493
1572
  flow_env = env.local_update(-var_idx+2, ret_ty)
1494
1573
  ret_ty = ret_ty.base_type if ret_ty.is_a?(Type::Symbol)
1495
- ret_ty = ret_ty.base_type if ret_ty.is_a?(Type::LocalCell)
1496
- ret_ty = ret_ty.base_type if ret_ty.is_a?(Type::LocalArray)
1497
- ret_ty = ret_ty.base_type if ret_ty.is_a?(Type::LocalHash)
1574
+ ret_ty = ret_ty.base_type if ret_ty.is_a?(Type::Local)
1498
1575
  if ret_ty.is_a?(Type::Instance)
1499
1576
  if ret_ty.klass == pattern_ty # XXX: inheritance
1500
1577
  merge_env(branchtype == :if ? ep_else : ep_then, flow_env)
@@ -1543,7 +1620,7 @@ module TypeProf
1543
1620
  warn(ep, "already initialized constant #{ Type::Instance.new(cbase).screen_name(self) }::#{ name }")
1544
1621
  end
1545
1622
  ty.each_child do |ty|
1546
- if ty.is_a?(Type::Class) && ty.superclass == Type::Builtin[:struct]
1623
+ if ty.is_a?(Type::Class) && cbase.is_a?(Type::Class) && ty.superclass == Type::Builtin[:struct]
1547
1624
  @class_defs[ty.idx].name = cbase_path(cbase) + [name]
1548
1625
  end
1549
1626
  end
@@ -1552,7 +1629,6 @@ module TypeProf
1552
1629
  when :getspecial
1553
1630
  key, type = operands
1554
1631
  if type == 0
1555
- raise NotImplementedError
1556
1632
  case key
1557
1633
  when 0 # VM_SVAR_LASTLINE
1558
1634
  env = env.push(Type.any) # or String | NilClass only?
@@ -1570,8 +1646,12 @@ module TypeProf
1570
1646
  return
1571
1647
  end
1572
1648
  when :setspecial
1573
- # flip-flop
1574
- raise NotImplementedError, "setspecial"
1649
+ key, = operands
1650
+ if key >= 2 # flip-flop
1651
+ env, = env.pop(1)
1652
+ else
1653
+ raise "unknown setspecial key: #{ key }"
1654
+ end
1575
1655
 
1576
1656
  when :dup
1577
1657
  env, (ty,) = env.pop(1)
@@ -1622,10 +1702,16 @@ module TypeProf
1622
1702
  env = env.push(Type.optional(sym_ty))
1623
1703
  when :checkmatch
1624
1704
  flag, = operands
1705
+
1706
+ # This flag means that the stack top is an array, and the check needs to be applied to find all elements
1707
+ # However, currently TypeProf uses very conservative interpretation (all check returns both true and false),
1708
+ # so we just ignore the flag now
1625
1709
  _array = flag & 4 != 0
1710
+
1626
1711
  case flag & 3
1627
- when 1
1628
- raise NotImplementedError
1712
+ when 1 # VM_CHECKMATCH_TYPE_WHEN
1713
+ env, = env.pop(2)
1714
+ env = env.push(Type.bool)
1629
1715
  when 2 # VM_CHECKMATCH_TYPE_CASE
1630
1716
  env, = env.pop(2)
1631
1717
  env = env.push(Type.bool)
@@ -1660,9 +1746,13 @@ module TypeProf
1660
1746
  from_head = flag & 2 == 0
1661
1747
  ary.each_child do |ary|
1662
1748
  case ary
1663
- when Type::LocalArray
1664
- elems = get_container_elem_types(env, ep, ary.id)
1665
- elems ||= Type::Array::Elements.new([], Type.any) # XXX
1749
+ when Type::Local
1750
+ if ary.kind == Type::Array
1751
+ elems = get_container_elem_types(env, ep, ary.id)
1752
+ elems ||= Type::Array::Elements.new([], Type.any) # XXX
1753
+ else
1754
+ elems = Type::Array::Elements.new([], Type.any) # XXX
1755
+ end
1666
1756
  do_expand_array(ep, env, elems, num, splat, from_head)
1667
1757
  when Type::Any
1668
1758
  nnum = num
@@ -1682,9 +1772,9 @@ module TypeProf
1682
1772
  return
1683
1773
  when :concatarray
1684
1774
  env, (ary1, ary2) = env.pop(2)
1685
- if ary1.is_a?(Type::LocalArray)
1775
+ if ary1.is_a?(Type::Local) && ary1.kind == Type::Array
1686
1776
  elems1 = get_container_elem_types(env, ep, ary1.id)
1687
- if ary2.is_a?(Type::LocalArray)
1777
+ if ary2.is_a?(Type::Local) && ary2.kind == Type::Array
1688
1778
  elems2 = get_container_elem_types(env, ep, ary2.id)
1689
1779
  elems = Type::Array::Elements.new([], elems1.squash.union(elems2.squash))
1690
1780
  env = update_container_elem_types(env, ep, ary1.id, ary1.base_type) { elems }
@@ -1831,6 +1921,10 @@ module TypeProf
1831
1921
  rest_ty = aargs.last
1832
1922
  aargs = aargs[0..-2]
1833
1923
  if flag_args_kw_splat
1924
+ # XXX: The types contained in ActualArguments are expected to be all local types.
1925
+ # This "globalize_type" breaks the invariant, and violates the assertion of Union#globalize that asserts @elems be nil.
1926
+ # To fix this issue fundamentally, ActualArguments should keep all arguments as-is (as like the VM does),
1927
+ # and globalize some types on the on-demand bases.
1834
1928
  ty = globalize_type(rest_ty, env, ep)
1835
1929
  if ty.is_a?(Type::Array)
1836
1930
  _, (ty,) = ty.elems.take_last(1)
@@ -1863,6 +1957,10 @@ module TypeProf
1863
1957
  aargs = ActualArguments.new(aargs, rest_ty, kw_tys, blk_ty)
1864
1958
  elsif flag_args_kw_splat
1865
1959
  last = aargs.last
1960
+ # XXX: The types contained in ActualArguments are expected to be all local types.
1961
+ # This "globalize_type" breaks the invariant, and violates the assertion of Union#globalize that asserts @elems be nil.
1962
+ # To fix this issue fundamentally, ActualArguments should keep all arguments as-is (as like the VM does),
1963
+ # and globalize some types on the on-demand bases.
1866
1964
  ty = globalize_type(last, env, ep)
1867
1965
  case ty
1868
1966
  when Type::Hash
@@ -1906,7 +2004,7 @@ module TypeProf
1906
2004
  nctx = Context.new(blk_iseq, ep.ctx.cref, ep.ctx.mid)
1907
2005
  nep = ExecutionPoint.new(nctx, 0, ep)
1908
2006
  nlocals = [Type.any] * blk_iseq.locals.size
1909
- nsenv = StaticEnv.new(env.static_env.recv_ty, Type.any, env.static_env.mod_func)
2007
+ nsenv = StaticEnv.new(env.static_env.recv_ty, Type.any, env.static_env.mod_func, env.static_env.pub_meth)
1910
2008
  nenv = Env.new(nsenv, nlocals, [], nil)
1911
2009
  pend_block_dummy_execution(blk_ty, blk_iseq, nep, nenv)
1912
2010
  merge_return_env(ep) {|tenv| tenv ? tenv.merge(env) : env }
@@ -1916,20 +2014,31 @@ module TypeProf
1916
2014
  end
1917
2015
 
1918
2016
  def do_send(recv, mid, aargs, ep, env, &ctn)
1919
- meths = recv.get_method(mid, self)
1920
- if meths
1921
- meths.each do |meth|
1922
- meth.do_send(recv, mid, aargs, ep, env, self, &ctn)
1923
- end
2017
+ case recv
2018
+ when Type::Void
2019
+ error(ep, "void's method is called: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
2020
+ ctn[Type.any, ep, env]
2021
+ when Type::Any
2022
+ ctn[Type.any, ep, env]
1924
2023
  else
1925
- case recv
1926
- when Type::Void
1927
- error(ep, "void's method is called: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
1928
- when Type::Any
2024
+ klass, singleton = recv.method_dispatch_info
2025
+ meths = get_method(klass, singleton, mid) if klass
2026
+ if meths
2027
+ meths.each do |meth|
2028
+ meth.do_send(recv, mid, aargs, ep, env, self, &ctn)
2029
+ end
1929
2030
  else
1930
- error(ep, "undefined method: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
2031
+ meths = get_method(klass, singleton, :method_missing) if klass
2032
+ if meths
2033
+ aargs = aargs.for_method_missing(Type::Symbol.new(mid, Type::Instance.new(Type::Builtin[:sym])))
2034
+ meths.each do |meth|
2035
+ meth.do_send(recv, :method_missing, aargs, ep, env, self, &ctn)
2036
+ end
2037
+ else
2038
+ error(ep, "undefined method: #{ globalize_type(recv, env, ep).screen_name(self) }##{ mid }")
2039
+ ctn[Type.any, ep, env]
2040
+ end
1931
2041
  end
1932
- ctn[Type.any, ep, env]
1933
2042
  end
1934
2043
  end
1935
2044
 
@@ -1944,6 +2053,34 @@ module TypeProf
1944
2053
  end
1945
2054
  end
1946
2055
 
2056
+ def do_define_iseq_method(ep, env, mid, iseq, outer_ep)
2057
+ cref = ep.ctx.cref
2058
+ if cref.klass.is_a?(Type::Class)
2059
+ typed_mdef = check_typed_method(cref.klass, mid, ep.ctx.cref.singleton)
2060
+ recv = cref.klass
2061
+ recv = Type::Instance.new(recv) unless ep.ctx.cref.singleton
2062
+ if typed_mdef
2063
+ mdef = ISeqMethodDef.new(iseq, cref, outer_ep, env.static_env.pub_meth)
2064
+ typed_mdef.each do |typed_mdef|
2065
+ typed_mdef.do_match_iseq_mdef(mdef, recv, mid, env, ep, self)
2066
+ end
2067
+ else
2068
+ if ep.ctx.cref.singleton
2069
+ meth = add_singleton_iseq_method(cref.klass, mid, iseq, cref, outer_ep, true)
2070
+ else
2071
+ meth = add_iseq_method(cref.klass, mid, iseq, cref, outer_ep, env.static_env.pub_meth)
2072
+ if env.static_env.mod_func
2073
+ add_singleton_iseq_method(cref.klass, mid, iseq, cref, outer_ep, true)
2074
+ end
2075
+ end
2076
+ end
2077
+
2078
+ pend_method_execution(iseq, meth, recv, mid, ep.ctx.cref, outer_ep)
2079
+ else
2080
+ # XXX: what to do?
2081
+ end
2082
+ end
2083
+
1947
2084
  def show_block_signature(blks)
1948
2085
  bsig = nil
1949
2086
  ret_ty = Type.bot
@@ -1984,7 +2121,7 @@ module TypeProf
1984
2121
  next unless @block_to_ctx[blk.block_body] # this occurs when screen_name is called before type-profiling finished (e.g., error message)
1985
2122
  @block_to_ctx[blk.block_body].each do |blk_ctx|
1986
2123
  if farg_tys
1987
- farg_tys = farg_tys.merge(@method_signatures[blk_ctx])
2124
+ farg_tys = farg_tys.merge_as_block_arguments(@method_signatures[blk_ctx])
1988
2125
  else
1989
2126
  farg_tys = @method_signatures[blk_ctx]
1990
2127
  end