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.
@@ -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}