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