steep 0.27.0 → 0.31.1

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