steep 0.27.0 → 0.31.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +38 -0
  3. data/bin/smoke_runner.rb +3 -4
  4. data/bin/steep-prof +1 -2
  5. data/lib/steep.rb +6 -4
  6. data/lib/steep/annotation_parser.rb +2 -4
  7. data/lib/steep/ast/builtin.rb +11 -21
  8. data/lib/steep/ast/types/factory.rb +234 -101
  9. data/lib/steep/ast/types/intersection.rb +12 -9
  10. data/lib/steep/ast/types/logic.rb +63 -0
  11. data/lib/steep/ast/types/name.rb +2 -58
  12. data/lib/steep/ast/types/union.rb +5 -6
  13. data/lib/steep/errors.rb +14 -0
  14. data/lib/steep/interface/interface.rb +5 -62
  15. data/lib/steep/interface/method_type.rb +346 -75
  16. data/lib/steep/interface/substitution.rb +16 -4
  17. data/lib/steep/module_helper.rb +25 -0
  18. data/lib/steep/project.rb +25 -0
  19. data/lib/steep/project/completion_provider.rb +57 -58
  20. data/lib/steep/project/file_loader.rb +7 -2
  21. data/lib/steep/project/hover_content.rb +92 -83
  22. data/lib/steep/project/signature_file.rb +33 -0
  23. data/lib/steep/project/{file.rb → source_file.rb} +24 -54
  24. data/lib/steep/project/target.rb +31 -12
  25. data/lib/steep/server/base_worker.rb +1 -0
  26. data/lib/steep/server/code_worker.rb +31 -45
  27. data/lib/steep/server/interaction_worker.rb +42 -38
  28. data/lib/steep/server/master.rb +23 -33
  29. data/lib/steep/server/utils.rb +46 -13
  30. data/lib/steep/server/worker_process.rb +4 -2
  31. data/lib/steep/signature/validator.rb +3 -3
  32. data/lib/steep/source.rb +60 -3
  33. data/lib/steep/subtyping/check.rb +34 -47
  34. data/lib/steep/subtyping/constraints.rb +8 -0
  35. data/lib/steep/type_construction.rb +366 -365
  36. data/lib/steep/type_inference/block_params.rb +5 -0
  37. data/lib/steep/type_inference/constant_env.rb +2 -5
  38. data/lib/steep/type_inference/logic_type_interpreter.rb +219 -0
  39. data/lib/steep/type_inference/type_env.rb +2 -2
  40. data/lib/steep/version.rb +1 -1
  41. data/smoke/alias/a.rb +1 -1
  42. data/smoke/case/a.rb +1 -1
  43. data/smoke/if/a.rb +1 -1
  44. data/smoke/module/a.rb +1 -1
  45. data/smoke/rescue/a.rb +4 -13
  46. data/smoke/toplevel/Steepfile +5 -0
  47. data/smoke/toplevel/a.rb +4 -0
  48. data/smoke/toplevel/a.rbs +3 -0
  49. data/smoke/type_case/a.rb +0 -7
  50. data/steep.gemspec +3 -3
  51. metadata +20 -16
  52. data/lib/steep/ast/method_type.rb +0 -126
  53. data/lib/steep/ast/namespace.rb +0 -80
  54. data/lib/steep/names.rb +0 -86
@@ -28,33 +28,36 @@ module Steep
28
28
  else
29
29
  type
30
30
  end
31
- end.compact.uniq.yield_self do |tys|
32
- if tys.size == 1
31
+ end.compact.yield_self do |tys|
32
+ dups = Set.new(tys)
33
+
34
+ case dups.size
35
+ when 0
36
+ AST::Types::Top.new(location: location)
37
+ when 1
33
38
  tys.first
34
39
  else
35
- new(types: tys.sort_by(&:hash), location: location)
40
+ new(types: dups.to_a, location: location)
36
41
  end
37
42
  end
38
43
  end
39
44
 
40
45
  def ==(other)
41
- other.is_a?(Intersection) &&
42
- other.types == types
46
+ other.is_a?(Intersection) && other.types == types
43
47
  end
44
48
 
45
49
  def hash
46
- self.class.hash ^ types.hash
50
+ @hash ||= self.class.hash ^ types.hash
47
51
  end
48
52
 
49
53
  alias eql? ==
50
54
 
51
55
  def subst(s)
52
- self.class.build(location: location,
53
- types: types.map {|ty| ty.subst(s) })
56
+ self.class.build(location: location, types: types.map {|ty| ty.subst(s) })
54
57
  end
55
58
 
56
59
  def to_s
57
- "(#{types.map(&:to_s).sort.join(" & ")})"
60
+ "(#{types.map(&:to_s).join(" & ")})"
58
61
  end
59
62
 
60
63
  def free_variables()
@@ -0,0 +1,63 @@
1
+ module Steep
2
+ module AST
3
+ module Types
4
+ module Logic
5
+ class Base
6
+ attr_reader :location
7
+
8
+ def subst(s)
9
+ self
10
+ end
11
+
12
+ def free_variables
13
+ @fvs ||= Set[]
14
+ end
15
+
16
+ def hash
17
+ self.class.hash
18
+ end
19
+
20
+ def ==(other)
21
+ other.class ==self.class
22
+ end
23
+
24
+ alias eql? ==
25
+
26
+ def to_s
27
+ "<% #{self.class} %>"
28
+ end
29
+ end
30
+
31
+ class Not < Base
32
+ def initialize(location: nil)
33
+ @location = location
34
+ end
35
+ end
36
+
37
+ class ReceiverIsNil < Base
38
+ def initialize(location: nil)
39
+ @location = location
40
+ end
41
+ end
42
+
43
+ class ReceiverIsNotNil < Base
44
+ def initialize(location: nil)
45
+ @location = location
46
+ end
47
+ end
48
+
49
+ class ReceiverIsArg < Base
50
+ def initialize(location: nil)
51
+ @location = location
52
+ end
53
+ end
54
+
55
+ class ArgIsReceiver < Base
56
+ def initialize(location: nil)
57
+ @location = location
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -79,59 +79,7 @@ module Steep
79
79
  end
80
80
  end
81
81
 
82
- class Class < Base
83
- attr_reader :constructor
84
-
85
- def initialize(name:, constructor:, location: nil)
86
- raise "Name should be a module name: #{name.inspect}" unless name.is_a?(Names::Module)
87
- super(name: name, location: location)
88
- @constructor = constructor
89
- end
90
-
91
- def ==(other)
92
- other.class == self.class &&
93
- other.name == name &&
94
- other.constructor == constructor
95
- end
96
-
97
- alias eql? ==
98
-
99
- def hash
100
- self.class.hash ^ name.hash ^ constructor.hash
101
- end
102
-
103
- def to_s
104
- k = case constructor
105
- when true
106
- " constructor"
107
- when false
108
- " noconstructor"
109
- when nil
110
- ""
111
- end
112
- "singleton(#{name.to_s})"
113
- end
114
-
115
- def with_location(new_location)
116
- self.class.new(name: name, constructor: constructor, location: new_location)
117
- end
118
-
119
- def to_instance(*args)
120
- Instance.new(name: name, args: args)
121
- end
122
-
123
- NOTHING = ::Object.new
124
-
125
- def updated(constructor: NOTHING)
126
- if NOTHING == constructor
127
- constructor = self.constructor
128
- end
129
-
130
- self.class.new(name: name, constructor: constructor, location: location)
131
- end
132
- end
133
-
134
- class Module < Base
82
+ class Singleton < Base
135
83
  def ==(other)
136
84
  other.class == self.class &&
137
85
  other.name == name
@@ -153,12 +101,8 @@ module Steep
153
101
  end
154
102
 
155
103
  class Instance < Applying
156
- def to_class(constructor:)
157
- Class.new(name: name, location: location, constructor: constructor)
158
- end
159
-
160
104
  def to_module
161
- Module.new(name: name, location: location)
105
+ Singleton.new(name: name, location: location)
162
106
  end
163
107
  end
164
108
 
@@ -38,29 +38,28 @@ module Steep
38
38
  when 1
39
39
  tys.first
40
40
  else
41
- new(types: tys.sort_by(&:hash), location: location)
41
+ new(types: tys, location: location)
42
42
  end
43
43
  end
44
44
  end
45
45
 
46
46
  def ==(other)
47
47
  other.is_a?(Union) &&
48
- other.types == types
48
+ Set.new(other.types) == Set.new(types)
49
49
  end
50
50
 
51
51
  def hash
52
- self.class.hash ^ types.hash
52
+ @hash ||= self.class.hash ^ types.sort_by(&:to_s).hash
53
53
  end
54
54
 
55
55
  alias eql? ==
56
56
 
57
57
  def subst(s)
58
- self.class.build(location: location,
59
- types: types.map {|ty| ty.subst(s) })
58
+ self.class.build(location: location, types: types.map {|ty| ty.subst(s) })
60
59
  end
61
60
 
62
61
  def to_s
63
- "(#{types.map(&:to_s).sort.join(" | ")})"
62
+ "(#{types.map(&:to_s).join(" | ")})"
64
63
  end
65
64
 
66
65
  def free_variables
@@ -543,5 +543,19 @@ module Steep
543
543
  "#{location_to_str}: MissingKeyword: #{missing_keywords.to_a.join(", ")}"
544
544
  end
545
545
  end
546
+
547
+ class UnsupportedSyntax < Base
548
+ attr_reader :message
549
+
550
+ def initialize(node:, message: nil)
551
+ super(node: node)
552
+ @message = message
553
+ end
554
+
555
+ def to_s
556
+ msg = message || "#{node.type} is not supported"
557
+ "#{location_to_str}: UnsupportedSyntax: #{msg}"
558
+ end
559
+ end
546
560
  end
547
561
  end
@@ -1,72 +1,15 @@
1
1
  module Steep
2
2
  module Interface
3
3
  class Interface
4
- class Combination
5
- attr_reader :operator
6
- attr_reader :types
4
+ class Entry
5
+ attr_reader :method_types
7
6
 
8
- def initialize(operator:, types:)
9
- @types = types
10
- @operator = operator
11
- @incompatible = false
12
- end
13
-
14
- def overload?
15
- operator == :overload
16
- end
17
-
18
- def union?
19
- operator == :union
20
- end
21
-
22
- def intersection?
23
- operator == :intersection
24
- end
25
-
26
- def self.overload(types, incompatible:)
27
- new(operator: :overload, types: types).incompatible!(incompatible)
28
- end
29
-
30
- def incompatible?
31
- @incompatible
32
- end
33
-
34
- def incompatible!(value)
35
- @incompatible = value
36
- self
37
- end
38
-
39
- def self.union(types)
40
- case types.size
41
- when 0
42
- raise "Combination.union called with zero types"
43
- when 1
44
- types.first
45
- else
46
- new(operator: :union, types: types)
47
- end
48
- end
49
-
50
- def self.intersection(types)
51
- case types.size
52
- when 0
53
- raise "Combination.intersection called with zero types"
54
- when 1
55
- types.first
56
- else
57
- new(operator: :intersection, types: types)
58
- end
7
+ def initialize(method_types:)
8
+ @method_types = method_types
59
9
  end
60
10
 
61
11
  def to_s
62
- case operator
63
- when :overload
64
- "{ #{types.map(&:to_s).join(" | ")} }"
65
- when :union
66
- "[#{types.map(&:to_s).join(" | ")}]"
67
- when :intersection
68
- "[#{types.map(&:to_s).join(" & ")}]"
69
- end
12
+ "{ #{method_types.join(" || ")} }"
70
13
  end
71
14
  end
72
15
 
@@ -17,15 +17,14 @@ module Steep
17
17
  @rest_keywords = rest_keywords
18
18
  end
19
19
 
20
- NONE = Object.new
21
- def update(required: NONE, optional: NONE, rest: NONE, required_keywords: NONE, optional_keywords: NONE, rest_keywords: NONE)
20
+ def update(required: self.required, optional: self.optional, rest: self.rest, required_keywords: self.required_keywords, optional_keywords: self.optional_keywords, rest_keywords: self.rest_keywords)
22
21
  self.class.new(
23
- required: required.equal?(NONE) ? self.required : required,
24
- optional: optional.equal?(NONE) ? self.optional : optional,
25
- rest: rest.equal?(NONE) ? self.rest : rest,
26
- required_keywords: required_keywords.equal?(NONE) ? self.required_keywords : required_keywords,
27
- optional_keywords: optional_keywords.equal?(NONE) ? self.optional_keywords : optional_keywords,
28
- rest_keywords: rest_keywords.equal?(NONE) ? self.rest_keywords : rest_keywords
22
+ required: required,
23
+ optional: optional,
24
+ rest: rest,
25
+ required_keywords: required_keywords,
26
+ optional_keywords: optional_keywords,
27
+ rest_keywords: rest_keywords,
29
28
  )
30
29
  end
31
30
 
@@ -84,6 +83,12 @@ module Steep
84
83
  other.rest_keywords == rest_keywords
85
84
  end
86
85
 
86
+ alias eql? ==
87
+
88
+ def hash
89
+ required.hash ^ optional.hash ^ rest.hash ^ required_keywords.hash ^ optional_keywords.hash ^ rest_keywords.hash
90
+ end
91
+
87
92
  def flat_unnamed_params
88
93
  required.map {|p| [:required, p] } + optional.map {|p| [:optional, p] }
89
94
  end
@@ -278,59 +283,61 @@ module Steep
278
283
  !has_positional? && !has_keywords?
279
284
  end
280
285
 
281
- def |(other)
286
+ # self + params returns a new params for overloading.
287
+ #
288
+ def +(other)
282
289
  a = first_param
283
290
  b = other.first_param
284
291
 
285
292
  case
286
293
  when a.is_a?(RequiredPositional) && b.is_a?(RequiredPositional)
287
294
  AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
288
- (self.drop_first | other.drop_first).with_first_param(RequiredPositional.new(type))
295
+ (self.drop_first + other.drop_first).with_first_param(RequiredPositional.new(type))
289
296
  end
290
297
  when a.is_a?(RequiredPositional) && b.is_a?(OptionalPositional)
291
298
  AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
292
- (self.drop_first | other.drop_first).with_first_param(OptionalPositional.new(type))
299
+ (self.drop_first + other.drop_first).with_first_param(OptionalPositional.new(type))
293
300
  end
294
301
  when a.is_a?(RequiredPositional) && b.is_a?(RestPositional)
295
302
  AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
296
- (self.drop_first | other).with_first_param(OptionalPositional.new(type))
303
+ (self.drop_first + other).with_first_param(OptionalPositional.new(type))
297
304
  end
298
305
  when a.is_a?(RequiredPositional) && b.nil?
299
- (self.drop_first | other).with_first_param(OptionalPositional.new(a.type))
306
+ (self.drop_first + other).with_first_param(OptionalPositional.new(a.type))
300
307
  when a.is_a?(OptionalPositional) && b.is_a?(RequiredPositional)
301
308
  AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
302
- (self.drop_first | other.drop_first).with_first_param(OptionalPositional.new(type))
309
+ (self.drop_first + other.drop_first).with_first_param(OptionalPositional.new(type))
303
310
  end
304
311
  when a.is_a?(OptionalPositional) && b.is_a?(OptionalPositional)
305
312
  AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
306
- (self.drop_first | other.drop_first).with_first_param(OptionalPositional.new(type))
313
+ (self.drop_first + other.drop_first).with_first_param(OptionalPositional.new(type))
307
314
  end
308
315
  when a.is_a?(OptionalPositional) && b.is_a?(RestPositional)
309
316
  AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
310
- (self.drop_first | other).with_first_param(OptionalPositional.new(type))
317
+ (self.drop_first + other).with_first_param(OptionalPositional.new(type))
311
318
  end
312
319
  when a.is_a?(OptionalPositional) && b.nil?
313
- (self.drop_first | other).with_first_param(OptionalPositional.new(a.type))
320
+ (self.drop_first + other).with_first_param(OptionalPositional.new(a.type))
314
321
  when a.is_a?(RestPositional) && b.is_a?(RequiredPositional)
315
322
  AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
316
- (self | other.drop_first).with_first_param(OptionalPositional.new(type))
323
+ (self + other.drop_first).with_first_param(OptionalPositional.new(type))
317
324
  end
318
325
  when a.is_a?(RestPositional) && b.is_a?(OptionalPositional)
319
326
  AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
320
- (self | other.drop_first).with_first_param(OptionalPositional.new(type))
327
+ (self + other.drop_first).with_first_param(OptionalPositional.new(type))
321
328
  end
322
329
  when a.is_a?(RestPositional) && b.is_a?(RestPositional)
323
330
  AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
324
- (self.drop_first | other.drop_first).with_first_param(RestPositional.new(type))
331
+ (self.drop_first + other.drop_first).with_first_param(RestPositional.new(type))
325
332
  end
326
333
  when a.is_a?(RestPositional) && b.nil?
327
- (self.drop_first | other).with_first_param(RestPositional.new(a.type))
334
+ (self.drop_first + other).with_first_param(RestPositional.new(a.type))
328
335
  when a.nil? && b.is_a?(RequiredPositional)
329
- (self | other.drop_first).with_first_param(OptionalPositional.new(b.type))
336
+ (self + other.drop_first).with_first_param(OptionalPositional.new(b.type))
330
337
  when a.nil? && b.is_a?(OptionalPositional)
331
- (self | other.drop_first).with_first_param(OptionalPositional.new(b.type))
338
+ (self + other.drop_first).with_first_param(OptionalPositional.new(b.type))
332
339
  when a.nil? && b.is_a?(RestPositional)
333
- (self | other.drop_first).with_first_param(RestPositional.new(b.type))
340
+ (self + other.drop_first).with_first_param(RestPositional.new(b.type))
334
341
  when a.nil? && b.nil?
335
342
  required_keywords = {}
336
343
 
@@ -410,6 +417,9 @@ module Steep
410
417
  end
411
418
  end
412
419
 
420
+ # Returns the intersection between self and other.
421
+ # Returns nil if the intersection cannot be computed.
422
+ #
413
423
  def &(other)
414
424
  a = first_param
415
425
  b = other.first_param
@@ -417,48 +427,48 @@ module Steep
417
427
  case
418
428
  when a.is_a?(RequiredPositional) && b.is_a?(RequiredPositional)
419
429
  AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
420
- (self.drop_first & other.drop_first).with_first_param(RequiredPositional.new(type))
430
+ (self.drop_first & other.drop_first)&.with_first_param(RequiredPositional.new(type))
421
431
  end
422
432
  when a.is_a?(RequiredPositional) && b.is_a?(OptionalPositional)
423
433
  AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
424
- (self.drop_first & other.drop_first).with_first_param(RequiredPositional.new(type))
434
+ (self.drop_first & other.drop_first)&.with_first_param(RequiredPositional.new(type))
425
435
  end
426
436
  when a.is_a?(RequiredPositional) && b.is_a?(RestPositional)
427
437
  AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
428
- (self.drop_first & other).with_first_param(RequiredPositional.new(type))
438
+ (self.drop_first & other)&.with_first_param(RequiredPositional.new(type))
429
439
  end
430
440
  when a.is_a?(RequiredPositional) && b.nil?
431
- (self.drop_first & other).with_first_param(RequiredPositional.new(AST::Types::Bot.new))
441
+ nil
432
442
  when a.is_a?(OptionalPositional) && b.is_a?(RequiredPositional)
433
443
  AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
434
- (self.drop_first & other.drop_first).with_first_param(RequiredPositional.new(type))
444
+ (self.drop_first & other.drop_first)&.with_first_param(RequiredPositional.new(type))
435
445
  end
436
446
  when a.is_a?(OptionalPositional) && b.is_a?(OptionalPositional)
437
447
  AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
438
- (self.drop_first & other.drop_first).with_first_param(OptionalPositional.new(type))
448
+ (self.drop_first & other.drop_first)&.with_first_param(OptionalPositional.new(type))
439
449
  end
440
450
  when a.is_a?(OptionalPositional) && b.is_a?(RestPositional)
441
451
  AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
442
- (self.drop_first & other).with_first_param(OptionalPositional.new(type))
452
+ (self.drop_first & other)&.with_first_param(OptionalPositional.new(type))
443
453
  end
444
454
  when a.is_a?(OptionalPositional) && b.nil?
445
455
  self.drop_first & other
446
456
  when a.is_a?(RestPositional) && b.is_a?(RequiredPositional)
447
457
  AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
448
- (self & other.drop_first).with_first_param(RequiredPositional.new(type))
458
+ (self & other.drop_first)&.with_first_param(RequiredPositional.new(type))
449
459
  end
450
460
  when a.is_a?(RestPositional) && b.is_a?(OptionalPositional)
451
461
  AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
452
- (self & other.drop_first).with_first_param(OptionalPositional.new(type))
462
+ (self & other.drop_first)&.with_first_param(OptionalPositional.new(type))
453
463
  end
454
464
  when a.is_a?(RestPositional) && b.is_a?(RestPositional)
455
465
  AST::Types::Intersection.build(types: [a.type, b.type]).yield_self do |type|
456
- (self.drop_first & other.drop_first).with_first_param(RestPositional.new(type))
466
+ (self.drop_first & other.drop_first)&.with_first_param(RestPositional.new(type))
457
467
  end
458
468
  when a.is_a?(RestPositional) && b.nil?
459
469
  self.drop_first & other
460
470
  when a.nil? && b.is_a?(RequiredPositional)
461
- (self & other.drop_first).with_first_param(RequiredPositional.new(AST::Types::Bot.new))
471
+ nil
462
472
  when a.nil? && b.is_a?(OptionalPositional)
463
473
  self & other.drop_first
464
474
  when a.nil? && b.is_a?(RestPositional)
@@ -467,7 +477,7 @@ module Steep
467
477
  optional_keywords = {}
468
478
 
469
479
  (Set.new(self.optional_keywords.keys) & Set.new(other.optional_keywords.keys)).each do |keyword|
470
- self.optional_keywords[keyword] = AST::Types::Intersection.build(
480
+ optional_keywords[keyword] = AST::Types::Intersection.build(
471
481
  types: [
472
482
  self.optional_keywords[keyword],
473
483
  other.optional_keywords[keyword]
@@ -482,9 +492,7 @@ module Steep
482
492
  when other.required_keywords.key?(keyword)
483
493
  required_keywords[keyword] = AST::Types::Intersection.build(types: [t, other.required_keywords[keyword]])
484
494
  when other.rest_keywords
485
- required_keywords[keyword] = AST::Types::Intersection.build(types: [t, other.rest_keywords])
486
- else
487
- required_keywords[keyword] = t
495
+ optional_keywords[keyword] = AST::Types::Intersection.build(types: [t, other.rest_keywords])
488
496
  end
489
497
  end
490
498
  end
@@ -494,9 +502,7 @@ module Steep
494
502
  when self.required_keywords.key?(keyword)
495
503
  required_keywords[keyword] = AST::Types::Intersection.build(types: [t, self.required_keywords[keyword]])
496
504
  when self.rest_keywords
497
- required_keywords[keyword] = AST::Types::Intersection.build(types: [t, self.rest_keywords])
498
- else
499
- required_keywords[keyword] = t
505
+ optional_keywords[keyword] = AST::Types::Intersection.build(types: [t, self.rest_keywords])
500
506
  end
501
507
  end
502
508
  end
@@ -508,7 +514,7 @@ module Steep
508
514
  when other.rest_keywords
509
515
  required_keywords[keyword] = AST::Types::Intersection.build(types: [t, other.rest_keywords])
510
516
  else
511
- required_keywords[keyword] = t
517
+ return
512
518
  end
513
519
  end
514
520
  end
@@ -520,7 +526,7 @@ module Steep
520
526
  when self.rest_keywords
521
527
  required_keywords[keyword] = AST::Types::Intersection.build(types: [t, self.rest_keywords])
522
528
  else
523
- required_keywords[keyword] = t
529
+ return
524
530
  end
525
531
  end
526
532
  end
@@ -529,7 +535,153 @@ module Steep
529
535
  when self.rest_keywords && other.rest_keywords
530
536
  AST::Types::Intersection.build(types: [self.rest_keywords, other.rest_keywords])
531
537
  else
532
- self.rest_keywords || other.rest_keywords
538
+ nil
539
+ end
540
+
541
+ Params.new(
542
+ required: [],
543
+ optional: [],
544
+ rest: nil,
545
+ required_keywords: required_keywords,
546
+ optional_keywords: optional_keywords,
547
+ rest_keywords: rest)
548
+ end
549
+ end
550
+
551
+ # Returns the union between self and other.
552
+ #
553
+ def |(other)
554
+ a = first_param
555
+ b = other.first_param
556
+
557
+ case
558
+ when a.is_a?(RequiredPositional) && b.is_a?(RequiredPositional)
559
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
560
+ (self.drop_first | other.drop_first)&.with_first_param(RequiredPositional.new(type))
561
+ end
562
+ when a.is_a?(RequiredPositional) && b.is_a?(OptionalPositional)
563
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
564
+ (self.drop_first | other.drop_first)&.with_first_param(OptionalPositional.new(type))
565
+ end
566
+ when a.is_a?(RequiredPositional) && b.is_a?(RestPositional)
567
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
568
+ (self.drop_first | other.drop_first)&.with_first_param(OptionalPositional.new(type))
569
+ end
570
+ when a.is_a?(RequiredPositional) && b.nil?
571
+ self.drop_first&.with_first_param(OptionalPositional.new(a.type))
572
+ when a.is_a?(OptionalPositional) && b.is_a?(RequiredPositional)
573
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
574
+ (self.drop_first | other.drop_first)&.with_first_param(OptionalPositional.new(type))
575
+ end
576
+ when a.is_a?(OptionalPositional) && b.is_a?(OptionalPositional)
577
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
578
+ (self.drop_first | other.drop_first)&.with_first_param(OptionalPositional.new(type))
579
+ end
580
+ when a.is_a?(OptionalPositional) && b.is_a?(RestPositional)
581
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
582
+ (self.drop_first | other.drop_first)&.with_first_param(OptionalPositional.new(type))
583
+ end
584
+ when a.is_a?(OptionalPositional) && b.nil?
585
+ (self.drop_first | other)&.with_first_param(a)
586
+ when a.is_a?(RestPositional) && b.is_a?(RequiredPositional)
587
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
588
+ (self.drop_first | other.drop_first)&.with_first_param(OptionalPositional.new(type))
589
+ end
590
+ when a.is_a?(RestPositional) && b.is_a?(OptionalPositional)
591
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
592
+ (self | other.drop_first)&.with_first_param(OptionalPositional.new(type))
593
+ end
594
+ when a.is_a?(RestPositional) && b.is_a?(RestPositional)
595
+ AST::Types::Union.build(types: [a.type, b.type]).yield_self do |type|
596
+ (self.drop_first | other.drop_first)&.with_first_param(RestPositional.new(type))
597
+ end
598
+ when a.is_a?(RestPositional) && b.nil?
599
+ (self.drop_first | other)&.with_first_param(a)
600
+ when a.nil? && b.is_a?(RequiredPositional)
601
+ other.drop_first&.with_first_param(OptionalPositional.new(b.type))
602
+ when a.nil? && b.is_a?(OptionalPositional)
603
+ (self | other.drop_first)&.with_first_param(b)
604
+ when a.nil? && b.is_a?(RestPositional)
605
+ (self | other.drop_first)&.with_first_param(b)
606
+ when a.nil? && b.nil?
607
+ required_keywords = {}
608
+ optional_keywords = {}
609
+
610
+ (Set.new(self.required_keywords.keys) & Set.new(other.required_keywords.keys)).each do |keyword|
611
+ required_keywords[keyword] = AST::Types::Union.build(
612
+ types: [
613
+ self.required_keywords[keyword],
614
+ other.required_keywords[keyword]
615
+ ]
616
+ )
617
+ end
618
+
619
+ self.optional_keywords.each do |keyword, t|
620
+ unless optional_keywords.key?(keyword) || required_keywords.key?(keyword)
621
+ case
622
+ when s = other.required_keywords[keyword]
623
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, s])
624
+ when s = other.optional_keywords[keyword]
625
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, s])
626
+ when r = other.rest_keywords
627
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, r])
628
+ else
629
+ optional_keywords[keyword] = t
630
+ end
631
+ end
632
+ end
633
+ other.optional_keywords.each do |keyword, t|
634
+ unless optional_keywords.key?(keyword) || required_keywords.key?(keyword)
635
+ case
636
+ when s = self.required_keywords[keyword]
637
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, s])
638
+ when s = self.optional_keywords[keyword]
639
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, s])
640
+ when r = self.rest_keywords
641
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, r])
642
+ else
643
+ optional_keywords[keyword] = t
644
+ end
645
+ end
646
+ end
647
+ self.required_keywords.each do |keyword, t|
648
+ unless optional_keywords.key?(keyword) || required_keywords.key?(keyword)
649
+ case
650
+ when s = other.optional_keywords[keyword]
651
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, s])
652
+ when r = other.rest_keywords
653
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, r])
654
+ else
655
+ optional_keywords[keyword] = t
656
+ end
657
+ end
658
+ end
659
+ other.required_keywords.each do |keyword, t|
660
+ unless optional_keywords.key?(keyword) || required_keywords.key?(keyword)
661
+ case
662
+ when s = self.optional_keywords[keyword]
663
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, s])
664
+ when r = self.rest_keywords
665
+ optional_keywords[keyword] = AST::Types::Union.build(types: [t, r])
666
+ else
667
+ optional_keywords[keyword] = t
668
+ end
669
+ end
670
+ end
671
+
672
+ rest = case
673
+ when self.rest_keywords && other.rest_keywords
674
+ AST::Types::Union.build(types: [self.rest_keywords, other.rest_keywords])
675
+ when self.rest_keywords
676
+ if required_keywords.empty? && optional_keywords.empty?
677
+ self.rest_keywords
678
+ end
679
+ when other.rest_keywords
680
+ if required_keywords.empty? && optional_keywords.empty?
681
+ other.rest_keywords
682
+ end
683
+ else
684
+ nil
533
685
  end
534
686
 
535
687
  Params.new(
@@ -567,6 +719,12 @@ module Steep
567
719
  other.is_a?(self.class) && other.type == type && other.optional == optional
568
720
  end
569
721
 
722
+ alias eql? ==
723
+
724
+ def hash
725
+ type.hash ^ optional.hash
726
+ end
727
+
570
728
  def closed?
571
729
  type.closed?
572
730
  end
@@ -600,9 +758,10 @@ module Steep
600
758
 
601
759
  def +(other)
602
760
  optional = self.optional? || other.optional?
603
- type = AST::Types::Proc.new(params: self.type.params | other.type.params,
604
- return_type: AST::Types::Union.build(types: [self.type.return_type,
605
- other.type.return_type]))
761
+ type = AST::Types::Proc.new(
762
+ params: self.type.params + other.type.params,
763
+ return_type: AST::Types::Union.build(types: [self.type.return_type, other.type.return_type])
764
+ )
606
765
  self.class.new(
607
766
  type: type,
608
767
  optional: optional
@@ -616,15 +775,15 @@ module Steep
616
775
  attr_reader :block
617
776
  attr_reader :return_type
618
777
  attr_reader :location
778
+ attr_reader :method_def
619
779
 
620
- NONE = Object.new
621
-
622
- def initialize(type_params:, params:, block:, return_type:, location:)
780
+ def initialize(type_params:, params:, block:, return_type:, location:, method_def:)
623
781
  @type_params = type_params
624
782
  @params = params
625
783
  @block = block
626
784
  @return_type = return_type
627
785
  @location = location
786
+ @method_def = method_def
628
787
  end
629
788
 
630
789
  def ==(other)
@@ -633,9 +792,16 @@ module Steep
633
792
  other.params == params &&
634
793
  other.block == block &&
635
794
  other.return_type == return_type &&
795
+ (!other.method_def || !method_def || other.method_def == method_def) &&
636
796
  (!other.location || !location || other.location == location)
637
797
  end
638
798
 
799
+ alias eql? ==
800
+
801
+ def hash
802
+ type_params.hash ^ params.hash ^ block.hash ^ return_type.hash
803
+ end
804
+
639
805
  def free_variables
640
806
  @fvs ||= Set.new.tap do |set|
641
807
  set.merge(params.free_variables)
@@ -658,6 +824,7 @@ module Steep
658
824
  params: params.subst(s_),
659
825
  block: block&.subst(s_),
660
826
  return_type: return_type.subst(s_),
827
+ method_def: method_def,
661
828
  location: location
662
829
  )
663
830
  end
@@ -676,23 +843,21 @@ module Steep
676
843
  end
677
844
 
678
845
  def instantiate(s)
679
- self.class.new(
680
- type_params: [],
681
- params: params.subst(s),
682
- block: block&.subst(s),
683
- return_type: return_type.subst(s),
684
- location: location,
685
- )
846
+ self.class.new(type_params: [],
847
+ params: params.subst(s),
848
+ block: block&.subst(s),
849
+ return_type: return_type.subst(s),
850
+ location: location,
851
+ method_def: method_def)
686
852
  end
687
853
 
688
- def with(type_params: NONE, params: NONE, block: NONE, return_type: NONE, location: NONE)
689
- self.class.new(
690
- type_params: type_params.equal?(NONE) ? self.type_params : type_params,
691
- params: params.equal?(NONE) ? self.params : params,
692
- block: block.equal?(NONE) ? self.block : block,
693
- return_type: return_type.equal?(NONE) ? self.return_type : return_type,
694
- location: location.equal?(NONE) ? self.location : location
695
- )
854
+ def with(type_params: self.type_params, params: self.params, block: self.block, return_type: self.return_type, location: self.location, method_def: self.method_def)
855
+ self.class.new(type_params: type_params,
856
+ params: params,
857
+ block: block,
858
+ return_type: return_type,
859
+ method_def: method_def,
860
+ location: location)
696
861
  end
697
862
 
698
863
  def to_s
@@ -704,16 +869,17 @@ module Steep
704
869
  end
705
870
 
706
871
  def map_type(&block)
707
- self.class.new(
708
- type_params: type_params,
709
- params: params.map_type(&block),
710
- block: self.block&.yield_self {|blk| blk.map_type(&block) },
711
- return_type: yield(return_type),
712
- location: location
713
- )
872
+ self.class.new(type_params: type_params,
873
+ params: params.map_type(&block),
874
+ block: self.block&.yield_self {|blk| blk.map_type(&block) },
875
+ return_type: yield(return_type),
876
+ location: location,
877
+ method_def: method_def)
714
878
  end
715
879
 
716
- def +(other)
880
+ # Returns a new method type which can be used for the method implementation type of both `self` and `other`.
881
+ #
882
+ def unify_overload(other)
717
883
  type_params = []
718
884
  s1 = Substitution.build(self.type_params)
719
885
  type_params.push(*s1.dictionary.values.map(&:name))
@@ -731,11 +897,116 @@ module Steep
731
897
 
732
898
  self.class.new(
733
899
  type_params: type_params,
734
- params: params.subst(s1) | other.params.subst(s2),
900
+ params: params.subst(s1) + other.params.subst(s2),
735
901
  block: block,
736
902
  return_type: AST::Types::Union.build(
737
903
  types: [return_type.subst(s1),other.return_type.subst(s2)]
738
904
  ),
905
+ method_def: method_def,
906
+ location: nil
907
+ )
908
+ end
909
+
910
+ def +(other)
911
+ unify_overload(other)
912
+ end
913
+
914
+ # Returns a method type which is a super-type of both self and other.
915
+ # self <: (self | other) && other <: (self | other)
916
+ #
917
+ # Returns nil if self and other are incompatible.
918
+ #
919
+ def |(other)
920
+ self_type_params = Set.new(self.type_params)
921
+ other_type_params = Set.new(other.type_params)
922
+
923
+ unless (common_type_params = (self_type_params & other_type_params).to_a).empty?
924
+ fresh_types = common_type_params.map {|name| AST::Types::Var.fresh(name) }
925
+ fresh_names = fresh_types.map(&:name)
926
+ subst = Substitution.build(common_type_params, fresh_types)
927
+ other = other.instantiate(subst)
928
+ type_params = (self_type_params + (other_type_params - common_type_params + Set.new(fresh_names))).to_a
929
+ else
930
+ type_params = (self_type_params + other_type_params).to_a
931
+ end
932
+
933
+ params = self.params & other.params or return
934
+ block = case
935
+ when self.block && other.block
936
+ block_params = self.block.type.params | other.block.type.params
937
+ block_return_type = AST::Types::Intersection.build(types: [self.block.type.return_type, other.block.type.return_type])
938
+ block_type = AST::Types::Proc.new(params: block_params,
939
+ return_type: block_return_type,
940
+ location: nil)
941
+ Block.new(
942
+ type: block_type,
943
+ optional: self.block.optional && other.block.optional
944
+ )
945
+ when self.block && self.block.optional?
946
+ self.block
947
+ when other.block && other.block.optional?
948
+ other.block
949
+ when !self.block && !other.block
950
+ nil
951
+ else
952
+ return
953
+ end
954
+ return_type = AST::Types::Union.build(types: [self.return_type, other.return_type])
955
+
956
+ MethodType.new(
957
+ params: params,
958
+ block: block,
959
+ return_type: return_type,
960
+ type_params: type_params,
961
+ method_def: nil,
962
+ location: nil
963
+ )
964
+ end
965
+
966
+ # Returns a method type which is a sub-type of both self and other.
967
+ # (self & other) <: self && (self & other) <: other
968
+ #
969
+ # Returns nil if self and other are incompatible.
970
+ #
971
+ def &(other)
972
+ self_type_params = Set.new(self.type_params)
973
+ other_type_params = Set.new(other.type_params)
974
+
975
+ unless (common_type_params = (self_type_params & other_type_params).to_a).empty?
976
+ fresh_types = common_type_params.map {|name| AST::Types::Var.fresh(name) }
977
+ fresh_names = fresh_types.map(&:name)
978
+ subst = Substitution.build(common_type_params, fresh_types)
979
+ other = other.subst(subst)
980
+ type_params = (self_type_params + (other_type_params - common_type_params + Set.new(fresh_names))).to_a
981
+ else
982
+ type_params = (self_type_params + other_type_params).to_a
983
+ end
984
+
985
+ params = self.params | other.params
986
+ block = case
987
+ when self.block && other.block
988
+ block_params = self.block.type.params & other.block.type.params or return
989
+ block_return_type = AST::Types::Union.build(types: [self.block.type.return_type, other.block.type.return_type])
990
+ block_type = AST::Types::Proc.new(params: block_params,
991
+ return_type: block_return_type,
992
+ location: nil)
993
+ Block.new(
994
+ type: block_type,
995
+ optional: self.block.optional || other.block.optional
996
+ )
997
+
998
+ else
999
+ self.block || other.block
1000
+ end
1001
+
1002
+ return_type = AST::Types::Intersection.build(types: [self.return_type, other.return_type])
1003
+
1004
+ MethodType.new(
1005
+ params: params,
1006
+ block: block,
1007
+ return_type: return_type,
1008
+ type_params: type_params,
1009
+ method_def: nil,
739
1010
  location: nil
740
1011
  )
741
1012
  end