steep 0.27.0 → 0.28.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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