steep 0.27.0 → 0.28.0

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.
@@ -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
@@ -617,8 +776,6 @@ module Steep
617
776
  attr_reader :return_type
618
777
  attr_reader :location
619
778
 
620
- NONE = Object.new
621
-
622
779
  def initialize(type_params:, params:, block:, return_type:, location:)
623
780
  @type_params = type_params
624
781
  @params = params
@@ -636,6 +793,12 @@ module Steep
636
793
  (!other.location || !location || other.location == location)
637
794
  end
638
795
 
796
+ alias eql? ==
797
+
798
+ def hash
799
+ type_params.hash ^ params.hash ^ block.hash ^ return_type.hash
800
+ end
801
+
639
802
  def free_variables
640
803
  @fvs ||= Set.new.tap do |set|
641
804
  set.merge(params.free_variables)
@@ -676,23 +839,19 @@ module Steep
676
839
  end
677
840
 
678
841
  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
- )
842
+ self.class.new(type_params: [],
843
+ params: params.subst(s),
844
+ block: block&.subst(s),
845
+ return_type: return_type.subst(s),
846
+ location: location)
686
847
  end
687
848
 
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
- )
849
+ def with(type_params: self.type_params, params: self.params, block: self.block, return_type: self.return_type, location: self.location)
850
+ self.class.new(type_params: type_params,
851
+ params: params,
852
+ block: block,
853
+ return_type: return_type,
854
+ location: location)
696
855
  end
697
856
 
698
857
  def to_s
@@ -704,16 +863,16 @@ module Steep
704
863
  end
705
864
 
706
865
  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
- )
866
+ self.class.new(type_params: type_params,
867
+ params: params.map_type(&block),
868
+ block: self.block&.yield_self {|blk| blk.map_type(&block) },
869
+ return_type: yield(return_type),
870
+ location: location)
714
871
  end
715
872
 
716
- def +(other)
873
+ # Returns a new method type which can be used for the method implementation type of both `self` and `other`.
874
+ #
875
+ def unify_overload(other)
717
876
  type_params = []
718
877
  s1 = Substitution.build(self.type_params)
719
878
  type_params.push(*s1.dictionary.values.map(&:name))
@@ -731,7 +890,7 @@ module Steep
731
890
 
732
891
  self.class.new(
733
892
  type_params: type_params,
734
- params: params.subst(s1) | other.params.subst(s2),
893
+ params: params.subst(s1) + other.params.subst(s2),
735
894
  block: block,
736
895
  return_type: AST::Types::Union.build(
737
896
  types: [return_type.subst(s1),other.return_type.subst(s2)]
@@ -739,6 +898,108 @@ module Steep
739
898
  location: nil
740
899
  )
741
900
  end
901
+
902
+ def +(other)
903
+ unify_overload(other)
904
+ end
905
+
906
+ # Returns a method type which is a super-type of both self and other.
907
+ # self <: (self | other) && other <: (self | other)
908
+ #
909
+ # Returns nil if self and other are incompatible.
910
+ #
911
+ def |(other)
912
+ self_type_params = Set.new(self.type_params)
913
+ other_type_params = Set.new(other.type_params)
914
+
915
+ unless (common_type_params = (self_type_params & other_type_params).to_a).empty?
916
+ fresh_types = common_type_params.map {|name| AST::Types::Var.fresh(name) }
917
+ fresh_names = fresh_types.map(&:name)
918
+ subst = Substitution.build(common_type_params, fresh_types)
919
+ other = other.instantiate(subst)
920
+ type_params = (self_type_params + (other_type_params - common_type_params + Set.new(fresh_names))).to_a
921
+ else
922
+ type_params = (self_type_params + other_type_params).to_a
923
+ end
924
+
925
+ params = self.params & other.params or return
926
+ block = case
927
+ when self.block && other.block
928
+ block_params = self.block.type.params | other.block.type.params
929
+ block_return_type = AST::Types::Intersection.build(types: [self.block.type.return_type, other.block.type.return_type])
930
+ block_type = AST::Types::Proc.new(params: block_params,
931
+ return_type: block_return_type,
932
+ location: nil)
933
+ Block.new(
934
+ type: block_type,
935
+ optional: self.block.optional && other.block.optional
936
+ )
937
+ when self.block && self.block.optional?
938
+ self.block
939
+ when other.block && other.block.optional?
940
+ other.block
941
+ when !self.block && !other.block
942
+ nil
943
+ else
944
+ return
945
+ end
946
+ return_type = AST::Types::Union.build(types: [self.return_type, other.return_type])
947
+
948
+ MethodType.new(
949
+ params: params,
950
+ block: block,
951
+ return_type: return_type,
952
+ type_params: type_params,
953
+ location: nil
954
+ )
955
+ end
956
+
957
+ # Returns a method type which is a sub-type of both self and other.
958
+ # (self & other) <: self && (self & other) <: other
959
+ #
960
+ # Returns nil if self and other are incompatible.
961
+ #
962
+ def &(other)
963
+ self_type_params = Set.new(self.type_params)
964
+ other_type_params = Set.new(other.type_params)
965
+
966
+ unless (common_type_params = (self_type_params & other_type_params).to_a).empty?
967
+ fresh_types = common_type_params.map {|name| AST::Types::Var.fresh(name) }
968
+ fresh_names = fresh_types.map(&:name)
969
+ subst = Substitution.build(common_type_params, fresh_types)
970
+ other = other.subst(subst)
971
+ type_params = (self_type_params + (other_type_params - common_type_params + Set.new(fresh_names))).to_a
972
+ else
973
+ type_params = (self_type_params + other_type_params).to_a
974
+ end
975
+
976
+ params = self.params | other.params
977
+ block = case
978
+ when self.block && other.block
979
+ block_params = self.block.type.params & other.block.type.params or return
980
+ block_return_type = AST::Types::Union.build(types: [self.block.type.return_type, other.block.type.return_type])
981
+ block_type = AST::Types::Proc.new(params: block_params,
982
+ return_type: block_return_type,
983
+ location: nil)
984
+ Block.new(
985
+ type: block_type,
986
+ optional: self.block.optional || other.block.optional
987
+ )
988
+
989
+ else
990
+ self.block || other.block
991
+ end
992
+
993
+ return_type = AST::Types::Intersection.build(types: [self.return_type, other.return_type])
994
+
995
+ MethodType.new(
996
+ params: params,
997
+ block: block,
998
+ return_type: return_type,
999
+ type_params: type_params,
1000
+ location: nil
1001
+ )
1002
+ end
742
1003
  end
743
1004
  end
744
1005
  end