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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/bin/smoke_runner.rb +3 -4
- data/lib/steep.rb +1 -1
- data/lib/steep/ast/builtin.rb +2 -20
- data/lib/steep/ast/types/factory.rb +60 -51
- data/lib/steep/ast/types/intersection.rb +12 -9
- data/lib/steep/ast/types/name.rb +2 -58
- data/lib/steep/ast/types/union.rb +5 -6
- data/lib/steep/errors.rb +14 -0
- data/lib/steep/interface/interface.rb +5 -62
- data/lib/steep/interface/method_type.rb +335 -74
- data/lib/steep/interface/substitution.rb +16 -4
- data/lib/steep/project/completion_provider.rb +1 -1
- data/lib/steep/project/hover_content.rb +1 -1
- data/lib/steep/server/base_worker.rb +1 -0
- data/lib/steep/server/code_worker.rb +2 -0
- data/lib/steep/server/master.rb +10 -3
- data/lib/steep/source.rb +2 -2
- data/lib/steep/subtyping/check.rb +29 -40
- data/lib/steep/type_construction.rb +192 -188
- data/lib/steep/type_inference/block_params.rb +5 -0
- data/lib/steep/version.rb +1 -1
- data/smoke/alias/a.rb +1 -1
- data/smoke/case/a.rb +1 -1
- data/smoke/if/a.rb +1 -1
- data/smoke/module/a.rb +1 -1
- data/smoke/rescue/a.rb +4 -13
- data/steep.gemspec +1 -1
- metadata +5 -5
@@ -38,29 +38,28 @@ module Steep
|
|
38
38
|
when 1
|
39
39
|
tys.first
|
40
40
|
else
|
41
|
-
new(types: tys
|
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).
|
62
|
+
"(#{types.map(&:to_s).join(" | ")})"
|
64
63
|
end
|
65
64
|
|
66
65
|
def free_variables
|
data/lib/steep/errors.rb
CHANGED
@@ -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
|
5
|
-
attr_reader :
|
6
|
-
attr_reader :types
|
4
|
+
class Entry
|
5
|
+
attr_reader :method_types
|
7
6
|
|
8
|
-
def initialize(
|
9
|
-
@
|
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
|
-
|
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
|
-
|
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
|
24
|
-
optional: optional
|
25
|
-
rest: rest
|
26
|
-
required_keywords: required_keywords
|
27
|
-
optional_keywords: optional_keywords
|
28
|
-
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
|
-
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
334
|
+
(self.drop_first + other).with_first_param(RestPositional.new(a.type))
|
328
335
|
when a.nil? && b.is_a?(RequiredPositional)
|
329
|
-
(self
|
336
|
+
(self + other.drop_first).with_first_param(OptionalPositional.new(b.type))
|
330
337
|
when a.nil? && b.is_a?(OptionalPositional)
|
331
|
-
(self
|
338
|
+
(self + other.drop_first).with_first_param(OptionalPositional.new(b.type))
|
332
339
|
when a.nil? && b.is_a?(RestPositional)
|
333
|
-
(self
|
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)
|
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)
|
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)
|
438
|
+
(self.drop_first & other)&.with_first_param(RequiredPositional.new(type))
|
429
439
|
end
|
430
440
|
when a.is_a?(RequiredPositional) && b.nil?
|
431
|
-
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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(
|
604
|
-
|
605
|
-
|
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
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
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:
|
689
|
-
self.class.new(
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
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
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
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
|
-
|
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)
|
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
|