typeprof 0.14.0 → 0.15.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- ty1 = container_to_union(ty1)
106
- ty2 = container_to_union(ty2)
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 ty1.is_a?(Union) && ty2.is_a?(Union)
109
- ty = ty1.types.sum(ty2.types)
110
- all_elems = ty1.elems.dup || {}
111
- ty2.elems&.each do |key, elems|
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.new(ty, all_elems).normalize
117
- else
118
- ty1, ty2 = ty2, ty1 if ty2.is_a?(Union)
119
- if ty1.is_a?(Union)
120
- Type::Union.new(ty1.types.add(ty2), ty1.elems).normalize
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
- ty
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.new(tys, elems).normalize
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.new(tys, nil).normalize
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.new(tys, elems).normalize
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 == :type ? :type_ : name } # XXX: workaround of RBS parser bug
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(", ") })"
@@ -1,3 +1,3 @@
1
1
  module TypeProf
2
- VERSION = "0.14.0"
2
+ VERSION = "0.15.2"
3
3
  end
data/smoke/alias2.rb CHANGED
@@ -17,5 +17,5 @@ class Foo
17
17
  @c: :z
18
18
 
19
19
  alias self.[] self.new
20
- def initialize: (:x a, :y b, :z c) -> [:x, :y, :z]
20
+ def initialize: (:x a, :y b, :z c) -> void
21
21
  end
data/smoke/array3.rb CHANGED
@@ -20,7 +20,7 @@ __END__
20
20
  class Foo
21
21
  @ary: [Integer, String?, :sym]
22
22
 
23
- def initialize: -> [Integer, String, :sym]
23
+ def initialize: -> void
24
24
  def foo: -> String?
25
25
  def bar: -> nil
26
26
  end
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: untyped
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
@@ -30,7 +30,7 @@ smoke/attr-vis.rb:20: [warning] inconsistent assignment to RBS-declared variable
30
30
 
31
31
  # Classes
32
32
  class Foo
33
- def initialize: -> Integer
33
+ def initialize: -> void
34
34
 
35
35
  private
36
36
  attr_accessor foo: Integer | String
data/smoke/attr.rb CHANGED
@@ -20,7 +20,7 @@ foo.c = :ccc
20
20
  __END__
21
21
  # Classes
22
22
  class Foo
23
- def initialize: (:aaa a) -> :aaa
23
+ def initialize: (:aaa a) -> void
24
24
  attr_reader a: :aaa
25
25
  attr_writer b: :bbb
26
26
  def get_b: -> :bbb
data/smoke/break2.rb CHANGED
@@ -12,5 +12,5 @@ __END__
12
12
  # Classes
13
13
  class Object
14
14
  private
15
- def foo: -> (Integer | String)
15
+ def foo: -> String
16
16
  end
data/smoke/gvar2.rb CHANGED
@@ -8,9 +8,6 @@ __END__
8
8
  # Errors
9
9
  smoke/gvar2.rb:1: [warning] inconsistent assignment to RBS-declared variable
10
10
 
11
- # Global variables
12
- #$foo: String
13
-
14
11
  # Classes
15
12
  class Object
16
13
  private
@@ -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
@@ -24,5 +24,5 @@ class A
24
24
  @str: String
25
25
  @val: (Integer | String)?
26
26
 
27
- def initialize: ((Integer | String)? x) -> ((Integer | String)?)
27
+ def initialize: ((Integer | String)? x) -> void
28
28
  end
data/smoke/ivar2.rb CHANGED
@@ -23,7 +23,7 @@ Foo.new.set
23
23
  __END__
24
24
  # Classes
25
25
  class Foo
26
- def initialize: -> Hash[bot, bot]
26
+ def initialize: -> void
27
27
  def set: -> :sym
28
28
  attr_reader array: Array[:sym | Integer | String]
29
29
  attr_reader hash: {a: Integer, b: String, c: :sym}