typeprof 0.5.4 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +7 -5
- data/doc/doc.ja.md +3 -4
- data/doc/doc.md +3 -4
- data/lib/typeprof/analyzer.rb +308 -171
- data/lib/typeprof/arguments.rb +14 -6
- data/lib/typeprof/block.rb +6 -2
- data/lib/typeprof/builtin.rb +230 -67
- data/lib/typeprof/cli.rb +33 -34
- data/lib/typeprof/config.rb +6 -4
- data/lib/typeprof/container-type.rb +159 -104
- data/lib/typeprof/export.rb +28 -22
- data/lib/typeprof/import.rb +70 -53
- data/lib/typeprof/iseq.rb +23 -7
- data/lib/typeprof/method.rb +71 -138
- data/lib/typeprof/type.rb +73 -15
- data/lib/typeprof/version.rb +1 -1
- data/smoke/alias.rb +5 -4
- data/smoke/alias2.rb +4 -4
- data/smoke/any1.rb +2 -1
- data/smoke/any2.rb +3 -2
- data/smoke/arguments.rb +3 -2
- data/smoke/arguments2.rb +11 -10
- data/smoke/array-each.rb +2 -1
- data/smoke/array-each2.rb +2 -1
- data/smoke/array-each3.rb +2 -1
- data/smoke/array-ltlt.rb +2 -1
- data/smoke/array-ltlt2.rb +2 -1
- data/smoke/array-map.rb +2 -1
- data/smoke/array-map2.rb +2 -1
- data/smoke/array-map3.rb +4 -3
- data/smoke/array-mul.rb +3 -2
- data/smoke/array-plus1.rb +2 -1
- data/smoke/array-plus2.rb +2 -2
- data/smoke/array-pop.rb +2 -1
- data/smoke/array-range-aref.rb +71 -0
- data/smoke/array-replace.rb +2 -1
- data/smoke/array-s-aref.rb +2 -1
- data/smoke/array1.rb +6 -5
- data/smoke/array10.rb +2 -1
- data/smoke/array11.rb +2 -1
- data/smoke/array12.rb +4 -3
- data/smoke/array13.rb +5 -4
- data/smoke/array14.rb +2 -1
- data/smoke/array15.rb +16 -0
- data/smoke/array2.rb +4 -3
- data/smoke/array3.rb +4 -4
- data/smoke/array4.rb +2 -1
- data/smoke/array5.rb +2 -1
- data/smoke/array6.rb +3 -2
- data/smoke/array7.rb +2 -1
- data/smoke/array8.rb +1 -1
- data/smoke/array9.rb +2 -1
- data/smoke/attr-module.rb +26 -0
- data/smoke/attr.rb +5 -5
- data/smoke/autoload.rb +14 -0
- data/smoke/backtrace.rb +4 -3
- data/smoke/block-ambiguous.rb +9 -8
- data/smoke/block-args1-rest.rb +12 -11
- data/smoke/block-args1.rb +11 -10
- data/smoke/block-args2-rest.rb +12 -11
- data/smoke/block-args2.rb +11 -10
- data/smoke/block-args3-rest.rb +14 -13
- data/smoke/block-args3.rb +13 -12
- data/smoke/block-blockarg.rb +5 -4
- data/smoke/block-kwarg.rb +11 -10
- data/smoke/block1.rb +2 -1
- data/smoke/block10.rb +2 -1
- data/smoke/block11.rb +6 -5
- data/smoke/block12.rb +3 -2
- data/smoke/block14.rb +3 -2
- data/smoke/block2.rb +2 -1
- data/smoke/block3.rb +3 -3
- data/smoke/block4.rb +3 -2
- data/smoke/block5.rb +3 -2
- data/smoke/block6.rb +3 -2
- data/smoke/block7.rb +2 -1
- data/smoke/block8.rb +4 -3
- data/smoke/block9.rb +2 -1
- data/smoke/blown.rb +2 -1
- data/smoke/break1.rb +3 -2
- data/smoke/break2.rb +2 -1
- data/smoke/break3.rb +13 -0
- data/smoke/case.rb +2 -1
- data/smoke/case2.rb +2 -1
- data/smoke/case3.rb +17 -0
- data/smoke/class-hierarchy.rb +5 -5
- data/smoke/class-hierarchy2.rb +3 -3
- data/smoke/class-new.rb +15 -0
- data/smoke/class_instance_var.rb +1 -1
- data/smoke/class_method.rb +2 -2
- data/smoke/class_method2.rb +2 -2
- data/smoke/class_method3.rb +4 -2
- data/smoke/constant1.rb +6 -6
- data/smoke/constant2.rb +5 -4
- data/smoke/constant3.rb +2 -1
- data/smoke/constant4.rb +2 -1
- data/smoke/context-sensitive1.rb +2 -1
- data/smoke/cvar.rb +6 -5
- data/smoke/cvar2.rb +2 -2
- data/smoke/define_method.rb +16 -0
- data/smoke/define_method2.rb +18 -0
- data/smoke/define_method3.rb +13 -0
- data/smoke/define_method3.rbs +3 -0
- data/smoke/define_method4.rb +15 -0
- data/smoke/define_method4.rbs +3 -0
- data/smoke/define_method5.rb +12 -0
- data/smoke/demo.rb +7 -6
- data/smoke/demo1.rb +2 -1
- data/smoke/demo10.rb +3 -2
- data/smoke/demo11.rb +2 -1
- data/smoke/demo2.rb +2 -1
- data/smoke/demo3.rb +2 -1
- data/smoke/demo4.rb +3 -3
- data/smoke/demo5.rb +1 -1
- data/smoke/demo6.rb +3 -3
- data/smoke/demo7.rb +2 -1
- data/smoke/demo8.rb +3 -2
- data/smoke/demo9.rb +3 -2
- data/smoke/dummy-execution1.rb +3 -2
- data/smoke/dummy-execution2.rb +2 -2
- data/smoke/dummy_element.rb +14 -0
- data/smoke/ensure1.rb +3 -2
- data/smoke/enumerator.rb +3 -2
- data/smoke/expandarray1.rb +2 -1
- data/smoke/expandarray2.rb +2 -1
- data/smoke/fib.rb +2 -2
- data/smoke/flip-flop.rb +28 -0
- data/smoke/flow1.rb +2 -1
- data/smoke/flow2.rb +2 -1
- data/smoke/flow3.rb +2 -1
- data/smoke/flow5.rb +2 -1
- data/smoke/flow6.rb +2 -1
- data/smoke/flow7.rb +2 -1
- data/smoke/flow8.rb +2 -1
- data/smoke/flow9.rb +12 -0
- data/smoke/freeze.rb +2 -1
- data/smoke/function.rb +3 -2
- data/smoke/gvar.rb +3 -2
- data/smoke/gvar2.rb +3 -2
- data/smoke/hash-bot.rb +12 -0
- data/smoke/hash-fetch.rb +4 -3
- data/smoke/hash-merge-bang.rb +2 -1
- data/smoke/hash1.rb +3 -2
- data/smoke/hash2.rb +2 -1
- data/smoke/hash3.rb +2 -1
- data/smoke/hash4.rb +2 -1
- data/smoke/hash5.rb +1 -1
- data/smoke/inheritance.rb +4 -4
- data/smoke/inheritance2.rb +2 -2
- data/smoke/initialize.rb +6 -5
- data/smoke/instance_eval.rb +2 -2
- data/smoke/instance_eval2.rb +10 -0
- data/smoke/instance_eval3.rb +25 -0
- data/smoke/int_times.rb +2 -1
- data/smoke/integer.rb +2 -1
- data/smoke/ivar.rb +5 -4
- data/smoke/ivar2.rb +4 -4
- data/smoke/ivar3.rb +2 -2
- data/smoke/kernel-class.rb +2 -1
- data/smoke/keyword1.rb +2 -1
- data/smoke/keyword2.rb +2 -1
- data/smoke/keyword3.rb +2 -1
- data/smoke/keyword4.rb +2 -1
- data/smoke/keyword5.rb +2 -1
- data/smoke/kwrest.rb +12 -0
- data/smoke/kwrest.rbs +3 -0
- data/smoke/kwsplat1.rb +5 -4
- data/smoke/kwsplat2.rb +2 -1
- data/smoke/lit-complex.rb +10 -0
- data/smoke/lit-encoding.rb +10 -0
- data/smoke/manual-rbs.rb +4 -3
- data/smoke/manual-rbs2.rb +2 -1
- data/smoke/manual-rbs3.rb +2 -2
- data/smoke/masgn1.rb +2 -1
- data/smoke/masgn2.rb +3 -2
- data/smoke/masgn3.rb +2 -1
- data/smoke/method_in_branch.rb +3 -2
- data/smoke/method_missing.rb +28 -0
- data/smoke/module1.rb +2 -2
- data/smoke/module2.rb +1 -1
- data/smoke/module3.rb +2 -2
- data/smoke/module4.rb +2 -2
- data/smoke/module5.rb +17 -0
- data/smoke/module6.rb +40 -0
- data/smoke/module_function1.rb +3 -3
- data/smoke/module_function2.rb +3 -3
- data/smoke/multiple-include.rb +1 -1
- data/smoke/multiple-superclass.rb +1 -1
- data/smoke/next1.rb +3 -2
- data/smoke/next2.rb +2 -1
- data/smoke/object-send1.rb +4 -3
- data/smoke/object-send2.rb +10 -0
- data/smoke/object-send3.rb +18 -0
- data/smoke/once.rb +2 -1
- data/smoke/optional1.rb +2 -1
- data/smoke/optional2.rb +2 -1
- data/smoke/optional3.rb +2 -1
- data/smoke/parameterizedd-self.rb +3 -2
- data/smoke/parameterizedd-self2.rb +15 -0
- data/smoke/pathname1.rb +2 -1
- data/smoke/pathname2.rb +2 -1
- data/smoke/pattern-match1.rb +2 -1
- data/smoke/pattern-match2.rb +2 -1
- data/smoke/printf.rb +2 -2
- data/smoke/proc.rb +3 -2
- data/smoke/proc2.rb +2 -1
- data/smoke/proc3.rb +2 -1
- data/smoke/proc4.rb +2 -1
- data/smoke/proc5.rb +19 -0
- data/smoke/public.rb +34 -0
- data/smoke/range.rb +2 -1
- data/smoke/rbs-alias.rb +2 -1
- data/smoke/rbs-attr.rb +6 -5
- data/smoke/rbs-attr2.rb +11 -0
- data/smoke/rbs-attr2.rbs +3 -0
- data/smoke/rbs-extend.rb +2 -1
- data/smoke/rbs-interface.rb +5 -4
- data/smoke/rbs-module.rb +26 -0
- data/smoke/rbs-module.rbs +4 -0
- data/smoke/rbs-opt-and-rest.rb +10 -0
- data/smoke/rbs-opt-and-rest.rbs +3 -0
- data/smoke/rbs-proc1.rb +2 -1
- data/smoke/rbs-proc2.rb +3 -2
- data/smoke/rbs-proc3.rb +2 -1
- data/smoke/rbs-record.rb +3 -2
- data/smoke/rbs-tyvar.rb +3 -2
- data/smoke/rbs-tyvar2.rb +3 -2
- data/smoke/rbs-tyvar3.rb +3 -2
- data/smoke/rbs-tyvar4.rb +3 -3
- data/smoke/rbs-tyvar5.rb +2 -1
- data/smoke/rbs-tyvar6.rb +18 -0
- data/smoke/rbs-tyvar6.rbs +12 -0
- data/smoke/rbs-tyvar7.rb +12 -0
- data/smoke/rbs-tyvar7.rbs +7 -0
- data/smoke/rbs-vars.rb +7 -8
- data/smoke/redo1.rb +3 -2
- data/smoke/redo2.rb +3 -2
- data/smoke/req-keyword.rb +2 -1
- data/smoke/rescue1.rb +3 -2
- data/smoke/rescue2.rb +3 -2
- data/smoke/rescue3.rb +19 -0
- data/smoke/rescue4.rb +17 -0
- data/smoke/respond_to.rb +2 -1
- data/smoke/rest-farg.rb +2 -1
- data/smoke/rest1.rb +3 -2
- data/smoke/rest2.rb +2 -1
- data/smoke/rest3.rb +7 -6
- data/smoke/rest4.rb +3 -2
- data/smoke/rest5.rb +2 -1
- data/smoke/rest6.rb +2 -1
- data/smoke/retry1.rb +3 -2
- data/smoke/return.rb +2 -1
- data/smoke/singleton_method.rb +1 -1
- data/smoke/step.rb +4 -3
- data/smoke/string-split.rb +2 -1
- data/smoke/struct-keyword_init.rb +20 -0
- data/smoke/struct.rb +1 -1
- data/smoke/struct2.rb +5 -4
- data/smoke/struct3.rb +2 -2
- data/smoke/struct4.rb +7 -0
- data/smoke/struct5.rb +16 -0
- data/smoke/struct6.rb +15 -0
- data/smoke/struct7.rb +17 -0
- data/smoke/stub-keyword.rb +10 -0
- data/smoke/super1.rb +5 -4
- data/smoke/super2.rb +1 -1
- data/smoke/super3.rb +3 -3
- data/smoke/super4.rb +43 -0
- data/smoke/super5.rb +36 -0
- data/smoke/svar1.rb +2 -1
- data/smoke/symbol-proc-attr.rb +22 -0
- data/smoke/symbol-proc-attr2.rb +15 -0
- data/smoke/symbol-proc-bot.rb +13 -0
- data/smoke/symbol-proc.rb +4 -3
- data/smoke/tap1.rb +3 -2
- data/smoke/toplevel.rb +2 -1
- data/smoke/two-map.rb +3 -2
- data/smoke/type_var.rb +2 -1
- data/smoke/typed_method.rb +2 -1
- data/smoke/uninitialize-var.rb +2 -1
- data/smoke/union-recv.rb +2 -2
- data/smoke/user-demo.rb +3 -3
- data/smoke/wrong-extend.rb +2 -2
- data/smoke/wrong-include.rb +2 -2
- data/smoke/wrong-include2.rb +17 -0
- data/typeprof.gemspec +1 -1
- metadata +61 -6
- data/tools/stackprof-wrapper.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c3bf54ec6fee3b06397893d2f10f1fae8e7af82b8f1640a4ddd305c33922ff7
|
4
|
+
data.tar.gz: 944d40a75789b4805e53ca70e169fe68fcd4dbca7f24bc4ccc779964085e980d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 726cdbfcda694f189a96f3f35088cbcbd9a3064e79e3838f7758d7bc393bf8591c0559db1c17993f971f9ae2ee4ca3b4c09f5c0ef6d6675752b00b6948cdfe62
|
7
|
+
data.tar.gz: b2b7353855183df391d8bc78c247eb7de09c1b65b2753789eb1e1fb0208275d10fec6d2d95745f36771de30af5e32281476100a0654db6f7cf87c8e442b36a65
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
typeprof (0.
|
5
|
-
rbs (>= 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.
|
15
|
-
simplecov (0.
|
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.
|
22
|
+
test-unit (3.3.7)
|
21
23
|
power_assert
|
22
24
|
|
23
25
|
PLATFORMS
|
data/doc/doc.ja.md
CHANGED
@@ -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
|
-
*
|
39
|
-
*
|
40
|
-
*
|
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
|
-
*
|
38
|
-
*
|
39
|
-
*
|
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
|
|
data/lib/typeprof/analyzer.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
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,
|
295
|
+
def initialize(kind, name, absolute_path)
|
285
296
|
raise unless name.is_a?(Array)
|
286
297
|
@kind = kind
|
287
|
-
@
|
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, :
|
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
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
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
|
323
|
-
@methods[[singleton, mid]]
|
324
|
-
|
325
|
-
|
326
|
-
|
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
|
-
|
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
|
-
|
348
|
-
|
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,
|
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
|
-
|
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,
|
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],
|
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
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
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
|
-
|
522
|
+
klass = ctx.cref.klass
|
449
523
|
mid = ctx.mid
|
450
|
-
|
451
|
-
|
452
|
-
|
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
|
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.
|
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.
|
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.
|
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
|
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
|
-
|
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
|
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.
|
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,
|
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
|
-
|
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][
|
911
|
-
|
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
|
-
|
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::
|
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) } :
|
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
|
-
|
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
|
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
|
-
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
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
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
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::
|
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
|
-
|
1574
|
-
|
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
|
-
|
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::
|
1664
|
-
|
1665
|
-
|
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::
|
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::
|
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
|
-
|
1920
|
-
|
1921
|
-
|
1922
|
-
|
1923
|
-
|
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
|
-
|
1926
|
-
|
1927
|
-
|
1928
|
-
|
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
|
-
|
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.
|
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
|