typeprof 0.14.0 → 0.15.2
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 +10 -10
- data/lib/typeprof/analyzer.rb +154 -85
- data/lib/typeprof/builtin.rb +22 -12
- data/lib/typeprof/cli.rb +1 -0
- data/lib/typeprof/config.rb +2 -1
- data/lib/typeprof/export.rb +9 -5
- data/lib/typeprof/import.rb +55 -21
- data/lib/typeprof/iseq.rb +307 -202
- data/lib/typeprof/method.rb +2 -2
- data/lib/typeprof/type.rb +97 -47
- data/lib/typeprof/version.rb +1 -1
- data/smoke/alias2.rb +1 -1
- data/smoke/array3.rb +1 -1
- data/smoke/attr-module.rb +1 -4
- data/smoke/attr-vis.rb +1 -1
- data/smoke/attr.rb +1 -1
- data/smoke/break2.rb +1 -1
- data/smoke/gvar2.rb +0 -3
- data/smoke/huge_union.rb +86 -0
- data/smoke/identifier_keywords.rb +17 -0
- data/smoke/initialize.rb +1 -1
- data/smoke/ivar2.rb +1 -1
- data/smoke/ivar3.rb +1 -1
- data/smoke/kwrest.rb +2 -2
- data/smoke/kwrest.rbs +1 -1
- data/smoke/method_missing.rb +1 -1
- data/smoke/next2.rb +1 -1
- data/smoke/noname.rb +9 -0
- data/smoke/or_raise.rb +18 -0
- data/smoke/pattern-match1.rb +1 -6
- data/smoke/proc6.rb +13 -0
- data/smoke/proc7.rb +32 -0
- data/smoke/rbs-tyvar4.rb +1 -1
- data/smoke/rbs-vars.rb +0 -3
- data/smoke/require1.rb +13 -0
- data/smoke/require2.rb +13 -0
- data/smoke/struct5.rb +1 -1
- data/smoke/struct6.rb +1 -1
- data/smoke/struct7.rb +1 -1
- data/smoke/super3.rb +1 -1
- data/smoke/symbol-proc-attr.rb +1 -1
- data/smoke/symbol-proc-attr2.rb +1 -1
- data/testbed/ao.rb +1 -1
- data/typeprof.gemspec +1 -1
- metadata +12 -4
data/lib/typeprof/method.rb
CHANGED
@@ -283,12 +283,12 @@ module TypeProf
|
|
283
283
|
# XXX: a block is passed to a method that does not accept block.
|
284
284
|
# Should we call the passed block with any arguments?
|
285
285
|
ret_ty = ret_ty.remove_type_vars
|
286
|
-
ctn[ret_ty, caller_ep, ncaller_env]
|
286
|
+
ctn[ret_ty, caller_ep, ncaller_env] if ret_ty != Type.bot
|
287
287
|
end
|
288
288
|
else
|
289
289
|
ret_ty = ret_ty.substitute(subst, Config.options[:type_depth_limit])
|
290
290
|
ret_ty = ret_ty.remove_type_vars
|
291
|
-
ctn[ret_ty, caller_ep, ncaller_env]
|
291
|
+
ctn[ret_ty, caller_ep, ncaller_env] if ret_ty != Type.bot
|
292
292
|
end
|
293
293
|
end
|
294
294
|
|
data/lib/typeprof/type.rb
CHANGED
@@ -102,34 +102,43 @@ module TypeProf
|
|
102
102
|
|
103
103
|
ty1, ty2 = self, other
|
104
104
|
|
105
|
-
|
106
|
-
|
105
|
+
case
|
106
|
+
when ty1.is_a?(Union)
|
107
|
+
ty1_types = ty1.types
|
108
|
+
ty1_elems = ty1.elems
|
109
|
+
when ty1.is_a?(Array) || ty1.is_a?(Hash)
|
110
|
+
ty1_types = Utils::Set[]
|
111
|
+
ty1_elems = {[ty1.class, ty1.base_type] => ty1.elems}
|
112
|
+
else
|
113
|
+
ty1_types = ty1_elems = nil
|
114
|
+
end
|
115
|
+
|
116
|
+
case
|
117
|
+
when ty2.is_a?(Union)
|
118
|
+
ty2_types = ty2.types
|
119
|
+
ty2_elems = ty2.elems
|
120
|
+
when ty2.is_a?(Array) || ty2.is_a?(Hash)
|
121
|
+
ty2_types = Utils::Set[]
|
122
|
+
ty2_elems = {[ty2.class, ty2.base_type] => ty2.elems}
|
123
|
+
else
|
124
|
+
ty2_types = ty2_elems = nil
|
125
|
+
end
|
107
126
|
|
108
|
-
if
|
109
|
-
ty =
|
110
|
-
all_elems =
|
111
|
-
|
127
|
+
if ty1_types && ty2_types
|
128
|
+
ty = ty1_types.sum(ty2_types)
|
129
|
+
all_elems = ty1_elems.dup || {}
|
130
|
+
ty2_elems&.each do |key, elems|
|
112
131
|
all_elems[key] = union_elems(all_elems[key], elems)
|
113
132
|
end
|
114
133
|
all_elems = nil if all_elems.empty?
|
115
134
|
|
116
|
-
Type::Union.
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
else
|
122
|
-
Type::Union.new(Utils::Set[ty1, ty2], nil).normalize
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
private def container_to_union(ty)
|
128
|
-
case ty
|
129
|
-
when Type::Array, Type::Hash
|
130
|
-
Type::Union.new(Utils::Set[], { [ty.class, ty.base_type] => ty.elems })
|
135
|
+
Type::Union.create(ty, all_elems)
|
136
|
+
elsif ty1_types
|
137
|
+
Type::Union.create(ty1_types.add(ty2), ty1_elems)
|
138
|
+
elsif ty2_types
|
139
|
+
Type::Union.create(ty2_types.add(ty1), ty2_elems)
|
131
140
|
else
|
132
|
-
|
141
|
+
Type::Union.create(Utils::Set[ty1, ty2], nil)
|
133
142
|
end
|
134
143
|
end
|
135
144
|
|
@@ -207,6 +216,37 @@ module TypeProf
|
|
207
216
|
|
208
217
|
|
209
218
|
class Union < Type
|
219
|
+
def self.create(tys, elems)
|
220
|
+
if tys.size == 1 && !elems
|
221
|
+
tys.each {|ty| return ty }
|
222
|
+
elsif tys.size == 0
|
223
|
+
if elems && elems.size == 1
|
224
|
+
(container_kind, base_type), nelems = elems.first
|
225
|
+
# container_kind = Type::Array or Type::Hash
|
226
|
+
container_kind.new(nelems, base_type)
|
227
|
+
else
|
228
|
+
new(tys, elems)
|
229
|
+
end
|
230
|
+
else
|
231
|
+
class_instances = []
|
232
|
+
non_class_instances = []
|
233
|
+
degenerated = false
|
234
|
+
tys.each do |ty|
|
235
|
+
if ty != Type::Instance.new(Type::Builtin[:nil]) && ty.is_a?(Type::Instance) && ty.klass.kind == :class
|
236
|
+
class_instances << ty
|
237
|
+
degenerated = true if ty.include_subclasses
|
238
|
+
else
|
239
|
+
non_class_instances << ty
|
240
|
+
end
|
241
|
+
end
|
242
|
+
if (Config.options[:union_width_limit] >= 2 && class_instances.size >= Config.options[:union_width_limit]) || (degenerated && class_instances.size >= 2)
|
243
|
+
create(Utils::Set[Instance.new_degenerate(class_instances), *non_class_instances], elems)
|
244
|
+
else
|
245
|
+
new(tys, elems)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
210
250
|
def initialize(tys, elems)
|
211
251
|
raise unless tys.is_a?(Utils::Set)
|
212
252
|
@types = tys # Set
|
@@ -243,22 +283,6 @@ module TypeProf
|
|
243
283
|
|
244
284
|
attr_reader :types, :elems
|
245
285
|
|
246
|
-
def normalize
|
247
|
-
if @types.size == 1 && !@elems
|
248
|
-
@types.each {|ty| return ty }
|
249
|
-
elsif @types.size == 0
|
250
|
-
if @elems && @elems.size == 1
|
251
|
-
(container_kind, base_type), elems = @elems.first
|
252
|
-
# container_kind = Type::Array or Type::Hash
|
253
|
-
container_kind.new(elems, base_type)
|
254
|
-
else
|
255
|
-
self
|
256
|
-
end
|
257
|
-
else
|
258
|
-
self
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
286
|
def each_child(&blk) # local
|
263
287
|
@types.each(&blk)
|
264
288
|
raise if @elems
|
@@ -343,7 +367,7 @@ module TypeProf
|
|
343
367
|
end
|
344
368
|
elems = nil if elems.empty?
|
345
369
|
|
346
|
-
Type::Union.
|
370
|
+
Type::Union.create(tys, elems)
|
347
371
|
end
|
348
372
|
|
349
373
|
def localize(env, alloc_site, depth)
|
@@ -357,7 +381,7 @@ module TypeProf
|
|
357
381
|
env, ty = ty.localize(env, alloc_site, depth - 1)
|
358
382
|
tys = tys.add(ty)
|
359
383
|
end
|
360
|
-
ty = Union.
|
384
|
+
ty = Union.create(tys, nil)
|
361
385
|
return env, ty
|
362
386
|
end
|
363
387
|
|
@@ -381,7 +405,7 @@ module TypeProf
|
|
381
405
|
elems = @elems&.to_h do |(container_kind, base_type), elems|
|
382
406
|
[[container_kind, base_type], elems.substitute(subst, depth - 1)]
|
383
407
|
end
|
384
|
-
ty = Union.
|
408
|
+
ty = Union.create(tys, elems)
|
385
409
|
unions.each do |ty0|
|
386
410
|
ty = ty.union(ty0)
|
387
411
|
end
|
@@ -484,7 +508,7 @@ module TypeProf
|
|
484
508
|
end
|
485
509
|
|
486
510
|
def method_dispatch_info
|
487
|
-
[self, true]
|
511
|
+
[self, true, false]
|
488
512
|
end
|
489
513
|
|
490
514
|
def consistent?(other)
|
@@ -513,15 +537,40 @@ module TypeProf
|
|
513
537
|
end
|
514
538
|
|
515
539
|
class Instance < Type
|
516
|
-
def initialize(klass)
|
540
|
+
def initialize(klass, include_subclasses=false)
|
517
541
|
raise unless klass
|
518
542
|
raise if klass == Type.any
|
519
543
|
raise if klass.is_a?(Type::Instance)
|
520
544
|
raise if klass.is_a?(Type::Union)
|
521
545
|
@klass = klass
|
546
|
+
@include_subclasses = include_subclasses
|
547
|
+
end
|
548
|
+
|
549
|
+
def self.new_degenerate(instances)
|
550
|
+
klass = instances.first.klass
|
551
|
+
ancestors = []
|
552
|
+
ancestor_idxs = {}
|
553
|
+
while klass != :__root__
|
554
|
+
ancestor_idxs[klass] = ancestors.size
|
555
|
+
ancestors << klass
|
556
|
+
klass = klass.superclass
|
557
|
+
end
|
558
|
+
common_superclass = nil
|
559
|
+
instances[1..].each do |instance|
|
560
|
+
klass = instance.klass
|
561
|
+
while !ancestor_idxs[klass]
|
562
|
+
klass = klass.superclass
|
563
|
+
end
|
564
|
+
common_superclass = klass
|
565
|
+
ancestor_idxs[klass].times do |i|
|
566
|
+
ancestor_idxs.delete(ancestors[i])
|
567
|
+
ancestors[i] = nil
|
568
|
+
end
|
569
|
+
end
|
570
|
+
new(common_superclass, true)
|
522
571
|
end
|
523
572
|
|
524
|
-
attr_reader :klass
|
573
|
+
attr_reader :klass, :include_subclasses
|
525
574
|
|
526
575
|
def inspect
|
527
576
|
"I[#{ @klass.inspect }]"
|
@@ -533,12 +582,12 @@ module TypeProf
|
|
533
582
|
when Type::Builtin[:true] then "true"
|
534
583
|
when Type::Builtin[:false] then "false"
|
535
584
|
else
|
536
|
-
scratch.get_class_name(@klass)
|
585
|
+
scratch.get_class_name(@klass) + (@include_subclasses ? "" : "")
|
537
586
|
end
|
538
587
|
end
|
539
588
|
|
540
589
|
def method_dispatch_info
|
541
|
-
[@klass, false]
|
590
|
+
[@klass, false, @include_subclasses]
|
542
591
|
end
|
543
592
|
|
544
593
|
def consistent?(other)
|
@@ -846,7 +895,8 @@ module TypeProf
|
|
846
895
|
fargs << ("**" + all_val_ty.screen_name(scratch))
|
847
896
|
end
|
848
897
|
if Config.options[:show_parameter_names]
|
849
|
-
farg_names = farg_names.map {|name| name
|
898
|
+
farg_names = farg_names.map {|name| RBS::Parser::KEYWORDS.key?(name.to_s) ? "`#{name}`" : name }
|
899
|
+
farg_names = farg_names.map {|name| name.is_a?(Integer) ? "noname_#{ name }" : name }
|
850
900
|
fargs = fargs.zip(farg_names).map {|farg, name| name ? "#{ farg } #{ name }" : farg }
|
851
901
|
end
|
852
902
|
fargs = fargs.empty? ? "" : "(#{ fargs.join(", ") })"
|
data/lib/typeprof/version.rb
CHANGED
data/smoke/alias2.rb
CHANGED
data/smoke/array3.rb
CHANGED
data/smoke/attr-module.rb
CHANGED
@@ -10,18 +10,15 @@ end
|
|
10
10
|
Foo.foo = 42
|
11
11
|
Bar.new.foo = "str"
|
12
12
|
|
13
|
-
# XXX: the output may be improved
|
14
|
-
|
15
13
|
__END__
|
16
14
|
# Classes
|
17
15
|
module Foo
|
18
16
|
self.@foo: Integer
|
19
17
|
|
20
|
-
attr_accessor foo:
|
18
|
+
attr_accessor foo: String
|
21
19
|
attr_accessor self.foo: Integer
|
22
20
|
end
|
23
21
|
|
24
22
|
class Bar
|
25
23
|
include Foo
|
26
|
-
@foo: String
|
27
24
|
end
|
data/smoke/attr-vis.rb
CHANGED
data/smoke/attr.rb
CHANGED
data/smoke/break2.rb
CHANGED
data/smoke/gvar2.rb
CHANGED
data/smoke/huge_union.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
class C0; end
|
2
|
+
class C1 < C0; def foo(n); end; end
|
3
|
+
class C2 < C0; def foo(n); end; end
|
4
|
+
class C3 < C0; def foo(n); end; end
|
5
|
+
class C4 < C0; def foo(n); end; end
|
6
|
+
class C5 < C0; def foo(n); end; end
|
7
|
+
class C6 < C0; def foo(n); end; end
|
8
|
+
class C7 < C0; def foo(n); end; end
|
9
|
+
class C8 < C0; def foo(n); end; end
|
10
|
+
class C9 < C0; def foo(n); end; end
|
11
|
+
class C10 < C0; def foo(n); end; end
|
12
|
+
class C11 < C0; def foo(n); end; end
|
13
|
+
class C12 < C0; def foo(n); end; end
|
14
|
+
|
15
|
+
def dispatch_foo(n)
|
16
|
+
n.foo("str")
|
17
|
+
end
|
18
|
+
|
19
|
+
dispatch_foo(C1.new)
|
20
|
+
dispatch_foo(C2.new)
|
21
|
+
dispatch_foo(C3.new)
|
22
|
+
dispatch_foo(C4.new)
|
23
|
+
dispatch_foo(C5.new)
|
24
|
+
dispatch_foo(C6.new)
|
25
|
+
dispatch_foo(C7.new)
|
26
|
+
dispatch_foo(C8.new)
|
27
|
+
dispatch_foo(C9.new)
|
28
|
+
dispatch_foo(C10.new)
|
29
|
+
|
30
|
+
__END__
|
31
|
+
# Classes
|
32
|
+
class Object
|
33
|
+
private
|
34
|
+
def dispatch_foo: (C0 n) -> nil
|
35
|
+
end
|
36
|
+
|
37
|
+
class C0
|
38
|
+
end
|
39
|
+
|
40
|
+
class C1 < C0
|
41
|
+
def foo: (String n) -> nil
|
42
|
+
end
|
43
|
+
|
44
|
+
class C2 < C0
|
45
|
+
def foo: (String n) -> nil
|
46
|
+
end
|
47
|
+
|
48
|
+
class C3 < C0
|
49
|
+
def foo: (String n) -> nil
|
50
|
+
end
|
51
|
+
|
52
|
+
class C4 < C0
|
53
|
+
def foo: (String n) -> nil
|
54
|
+
end
|
55
|
+
|
56
|
+
class C5 < C0
|
57
|
+
def foo: (String n) -> nil
|
58
|
+
end
|
59
|
+
|
60
|
+
class C6 < C0
|
61
|
+
def foo: (String n) -> nil
|
62
|
+
end
|
63
|
+
|
64
|
+
class C7 < C0
|
65
|
+
def foo: (String n) -> nil
|
66
|
+
end
|
67
|
+
|
68
|
+
class C8 < C0
|
69
|
+
def foo: (String n) -> nil
|
70
|
+
end
|
71
|
+
|
72
|
+
class C9 < C0
|
73
|
+
def foo: (String n) -> nil
|
74
|
+
end
|
75
|
+
|
76
|
+
class C10 < C0
|
77
|
+
def foo: (String n) -> nil
|
78
|
+
end
|
79
|
+
|
80
|
+
class C11 < C0
|
81
|
+
def foo: (String n) -> nil
|
82
|
+
end
|
83
|
+
|
84
|
+
class C12 < C0
|
85
|
+
def foo: (String n) -> nil
|
86
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
def type(type)
|
2
|
+
end
|
3
|
+
|
4
|
+
def out(*out)
|
5
|
+
end
|
6
|
+
|
7
|
+
def untyped(untyped:)
|
8
|
+
end
|
9
|
+
|
10
|
+
__END__
|
11
|
+
# Classes
|
12
|
+
class Object
|
13
|
+
private
|
14
|
+
def type: (untyped `type`) -> nil
|
15
|
+
def out: (*untyped `out`) -> nil
|
16
|
+
def untyped: (untyped: untyped) -> nil
|
17
|
+
end
|
data/smoke/initialize.rb
CHANGED
data/smoke/ivar2.rb
CHANGED