steep 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/lib/steep.rb +4 -0
- data/lib/steep/ast/types/any.rb +4 -0
- data/lib/steep/ast/types/boolean.rb +53 -0
- data/lib/steep/ast/types/bot.rb +4 -0
- data/lib/steep/ast/types/class.rb +4 -0
- data/lib/steep/ast/types/instance.rb +4 -0
- data/lib/steep/ast/types/intersection.rb +4 -0
- data/lib/steep/ast/types/literal.rb +59 -0
- data/lib/steep/ast/types/name.rb +4 -0
- data/lib/steep/ast/types/nil.rb +48 -0
- data/lib/steep/ast/types/self.rb +4 -0
- data/lib/steep/ast/types/top.rb +4 -0
- data/lib/steep/ast/types/tuple.rb +51 -0
- data/lib/steep/ast/types/union.rb +4 -0
- data/lib/steep/ast/types/var.rb +4 -0
- data/lib/steep/ast/types/void.rb +4 -0
- data/lib/steep/drivers/scaffold.rb +1 -1
- data/lib/steep/errors.rb +15 -0
- data/lib/steep/interface/builder.rb +5 -0
- data/lib/steep/interface/method.rb +10 -0
- data/lib/steep/parser.y +81 -39
- data/lib/steep/subtyping/check.rb +78 -0
- data/lib/steep/type_construction.rb +325 -195
- data/lib/steep/type_inference/type_env.rb +1 -1
- data/lib/steep/typing.rb +34 -19
- data/lib/steep/version.rb +1 -1
- data/smoke/and/a.rb +2 -2
- data/smoke/case/a.rb +1 -1
- data/smoke/literal/a.rb +2 -2
- data/stdlib/builtin.rbi +86 -84
- metadata +6 -2
data/lib/steep/parser.y
CHANGED
@@ -18,15 +18,13 @@ method_type:
|
|
18
18
|
return_type: val[4])
|
19
19
|
}
|
20
20
|
|
21
|
-
return_type:
|
22
|
-
| LPAREN union_seq RPAREN { result = AST::Types::Union.build(location: val[0].location + val[2].location,
|
23
|
-
types: val[1]) }
|
21
|
+
return_type: paren_type
|
24
22
|
|
25
23
|
params: { result = nil }
|
26
24
|
| LPAREN params0 RPAREN { result = LocatedValue.new(location: val[0].location + val[2].location,
|
27
25
|
value: val[1]) }
|
28
|
-
|
|
29
|
-
|
26
|
+
| simple_type { result = LocatedValue.new(location: val[0].location,
|
27
|
+
value: AST::MethodType::Params::Required.new(location: val[0].location, type: val[0])) }
|
30
28
|
|
31
29
|
params0: required_param { result = AST::MethodType::Params::Required.new(location: val[0].location, type: val[0]) }
|
32
30
|
| required_param COMMA params0 {
|
@@ -154,8 +152,28 @@ simple_type: type_name {
|
|
154
152
|
| INSTANCE { result = AST::Types::Instance.new(location: val[0].location) }
|
155
153
|
| SELF { result = AST::Types::Self.new(location: val[0].location) }
|
156
154
|
| VOID { result = AST::Types::Void.new(location: val[0].location) }
|
157
|
-
| NIL { result = AST::Types::
|
158
|
-
|
155
|
+
| NIL { result = AST::Types::Nil.new(location: val[0].location) }
|
156
|
+
| BOOL { result = AST::Types::Boolean.new(location: val[0].location) }
|
157
|
+
| simple_type QUESTION {
|
158
|
+
type = val[0]
|
159
|
+
nil_type = AST::Types::Nil.new(location: val[1].location)
|
160
|
+
result = AST::Types::Union.build(types: [type, nil_type], location: val[0].location + val[1].location)
|
161
|
+
}
|
162
|
+
| SELFQ {
|
163
|
+
type = AST::Types::Self.new(location: val[0].location)
|
164
|
+
nil_type = AST::Types::Nil.new(location: val[0].location)
|
165
|
+
result = AST::Types::Union.build(types: [type, nil_type], location: val[0].location)
|
166
|
+
}
|
167
|
+
| INT { result = AST::Types::Literal.new(value: val[0].value, location: val[0].location) }
|
168
|
+
| STRING { result = AST::Types::Literal.new(value: val[0].value, location: val[0].location) }
|
169
|
+
| SYMBOL { result = AST::Types::Literal.new(value: val[0].value, location: val[0].location) }
|
170
|
+
| LBRACKET type_seq RBRACKET {
|
171
|
+
loc = val[0].location + val[2].location
|
172
|
+
result = AST::Types::Tuple.new(types: val[1], location: loc)
|
173
|
+
}
|
174
|
+
|
175
|
+
paren_type: LPAREN type RPAREN { result = val[1].with_location(val[0].location + val[2].location) }
|
176
|
+
| simple_type
|
159
177
|
|
160
178
|
instance_type_name: module_name {
|
161
179
|
result = LocatedValue.new(value: TypeName::Instance.new(name: val[0].value),
|
@@ -182,7 +200,7 @@ constructor: { result = nil }
|
|
182
200
|
| CONSTRUCTOR
|
183
201
|
| NOCONSTRUCTOR
|
184
202
|
|
185
|
-
type:
|
203
|
+
type: paren_type
|
186
204
|
| union_seq {
|
187
205
|
loc = val[0].first.location + val[0].last.location
|
188
206
|
result = AST::Types::Union.build(types: val[0], location: loc)
|
@@ -406,40 +424,54 @@ interface_method: DEF method_name COLON method_type_union {
|
|
406
424
|
method_type_union: method_type { result = [val[0]] }
|
407
425
|
| method_type BAR method_type_union { result = [val[0]] + val[2] }
|
408
426
|
|
409
|
-
method_name:
|
410
|
-
| MODULE_NAME
|
411
|
-
| INTERFACE_NAME
|
412
|
-
| ANY | VOID
|
413
|
-
| INTERFACE
|
414
|
-
| END
|
415
|
-
| PLUS
|
416
|
-
| CLASS
|
417
|
-
| MODULE
|
418
|
-
| INSTANCE
|
419
|
-
| EXTEND
|
420
|
-
| INCLUDE
|
421
|
-
| OPERATOR
|
422
|
-
| METHOD_NAME
|
423
|
-
| BLOCK
|
424
|
-
| UIDENT
|
425
|
-
| BREAK
|
427
|
+
method_name: method_name0
|
426
428
|
| STAR | STAR2
|
427
429
|
| PERCENT | MINUS
|
428
430
|
| LT | GT
|
429
|
-
| METHOD
|
430
431
|
| BAR { result = LocatedValue.new(location: val[0].location, value: :|) }
|
431
|
-
|
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
432
|
+
| method_name0 EQ {
|
433
|
+
raise ParseError, "\nunexpected method name #{val[0].to_s} =" unless val[0].location.pred?(val[1].location)
|
434
|
+
result = LocatedValue.new(location: val[0].location + val[1].location,
|
435
|
+
value: :"#{val[0].value}=")
|
436
|
+
}
|
437
|
+
| method_name0 QUESTION {
|
438
|
+
raise ParseError, "\nunexpected method name #{val[0].to_s} ?" unless val[0].location.pred?(val[1].location)
|
439
|
+
result = LocatedValue.new(location: val[0].location + val[1].location,
|
440
|
+
value: :"#{val[0].value}?")
|
441
|
+
}
|
442
|
+
| method_name0 BANG {
|
443
|
+
raise ParseError, "\nunexpected method name #{val[0].to_s} !" unless val[0].location.pred?(val[1].location)
|
444
|
+
result = LocatedValue.new(location: val[0].location + val[1].location,
|
445
|
+
value: :"#{val[0].value}!")
|
436
446
|
}
|
437
447
|
| GT GT {
|
438
448
|
raise ParseError, "\nunexpected method name > >" unless val[0].location.pred?(val[1].location)
|
439
449
|
result = LocatedValue.new(location: val[0].location + val[1].location, value: :>>)
|
440
450
|
}
|
441
|
-
|
442
|
-
|
451
|
+
|
452
|
+
method_name0: IDENT
|
453
|
+
| UIDENT
|
454
|
+
| MODULE_NAME
|
455
|
+
| INTERFACE_NAME
|
456
|
+
| ANY | VOID
|
457
|
+
| INTERFACE
|
458
|
+
| END
|
459
|
+
| PLUS
|
460
|
+
| CLASS
|
461
|
+
| MODULE
|
462
|
+
| INSTANCE
|
463
|
+
| EXTEND
|
464
|
+
| INCLUDE
|
465
|
+
| OPERATOR
|
466
|
+
| BANG
|
467
|
+
| BLOCK
|
468
|
+
| BREAK
|
469
|
+
| METHOD
|
470
|
+
| BOOL
|
471
|
+
| CONSTRUCTOR { result = LocatedValue.new(location: val[0].location, value: :constructor) }
|
472
|
+
| NOCONSTRUCTOR { result = LocatedValue.new(location: val[0].location, value: :noconstructor) }
|
473
|
+
| ATTR_READER
|
474
|
+
| ATTR_ACCESSOR
|
443
475
|
|
444
476
|
annotation: AT_TYPE VAR subject COLON type {
|
445
477
|
loc = val.first.location + val.last.location
|
@@ -591,6 +623,8 @@ def next_token
|
|
591
623
|
new_token(:ARROW)
|
592
624
|
when input.scan(/\?/)
|
593
625
|
new_token(:QUESTION)
|
626
|
+
when input.scan(/!/)
|
627
|
+
new_token(:BANG)
|
594
628
|
when input.scan(/\(/)
|
595
629
|
new_token(:LPAREN, nil)
|
596
630
|
when input.scan(/\)/)
|
@@ -601,6 +635,8 @@ def next_token
|
|
601
635
|
new_token(:RBRACE, nil)
|
602
636
|
when input.scan(/,/)
|
603
637
|
new_token(:COMMA, nil)
|
638
|
+
when input.scan(/:\w+/)
|
639
|
+
new_token(:SYMBOL, input.matched[1..-1].to_sym)
|
604
640
|
when input.scan(/::/)
|
605
641
|
new_token(:COLON2)
|
606
642
|
when input.scan(/:/)
|
@@ -617,16 +653,24 @@ def next_token
|
|
617
653
|
new_token(:LTCOLON)
|
618
654
|
when input.scan(/(\[\]=)|(\[\])|===|==|\^|!=|<</)
|
619
655
|
new_token(:OPERATOR, input.matched.to_sym)
|
656
|
+
when input.scan(/\[/)
|
657
|
+
new_token(:LBRACKET, nil)
|
658
|
+
when input.scan(/\]/)
|
659
|
+
new_token(:RBRACKET, nil)
|
620
660
|
when input.scan(/<=/)
|
621
661
|
new_token(:OPERATOR, :<=)
|
622
662
|
when input.scan(/>=/)
|
623
663
|
new_token(:OPERATOR, :>=)
|
664
|
+
when input.scan(/=/)
|
665
|
+
new_token(:EQ, :"=")
|
624
666
|
when input.scan(/</)
|
625
667
|
new_token(:LT, :<)
|
626
668
|
when input.scan(/>/)
|
627
669
|
new_token(:GT, :>)
|
628
670
|
when input.scan(/nil\b/)
|
629
671
|
new_token(:NIL, :nil)
|
672
|
+
when input.scan(/bool\b/)
|
673
|
+
new_token(:BOOL, :bool)
|
630
674
|
when input.scan(/any\b/)
|
631
675
|
new_token(:ANY, :any)
|
632
676
|
when input.scan(/void\b/)
|
@@ -673,8 +717,6 @@ def next_token
|
|
673
717
|
new_token(:CLASS, :class)
|
674
718
|
when input.scan(/module\b/)
|
675
719
|
new_token(:MODULE, :module)
|
676
|
-
when input.scan(/include\?/)
|
677
|
-
new_token(:METHOD_NAME, :include?)
|
678
720
|
when input.scan(/include\b/)
|
679
721
|
new_token(:INCLUDE, :include)
|
680
722
|
when input.scan(/extend\b/)
|
@@ -693,16 +735,12 @@ def next_token
|
|
693
735
|
new_token(:OPERATOR, :~)
|
694
736
|
when input.scan(/\//)
|
695
737
|
new_token(:OPERATOR, :/)
|
696
|
-
when input.scan(/!/)
|
697
|
-
new_token(:OPERATOR, :!)
|
698
738
|
when input.scan(/extension\b/)
|
699
739
|
new_token(:EXTENSION, :extension)
|
700
740
|
when input.scan(/constructor\b/)
|
701
741
|
new_token(:CONSTRUCTOR, true)
|
702
742
|
when input.scan(/noconstructor\b/)
|
703
743
|
new_token(:NOCONSTRUCTOR, false)
|
704
|
-
when input.scan(/\w+(\!|\?|=)/)
|
705
|
-
new_token(:METHOD_NAME, input.matched.to_sym)
|
706
744
|
when input.scan(/\$\w+\b/)
|
707
745
|
new_token(:GVAR, input.matched.to_sym)
|
708
746
|
when input.scan(/[A-Z]\w*/)
|
@@ -711,6 +749,10 @@ def next_token
|
|
711
749
|
new_token(:INTERFACE_NAME, input.matched.to_sym)
|
712
750
|
when input.scan(/@\w+/)
|
713
751
|
new_token(:IVAR_NAME, input.matched.to_sym)
|
752
|
+
when input.scan(/\d+/)
|
753
|
+
new_token(:INT, input.matched.to_i)
|
754
|
+
when input.scan(/\"[^\"]*\"/)
|
755
|
+
new_token(:STRING, input.matched[1...-1])
|
714
756
|
when input.scan(/\w+/)
|
715
757
|
new_token(:IDENT, input.matched.to_sym)
|
716
758
|
end
|
@@ -83,6 +83,14 @@ module Steep
|
|
83
83
|
trace: trace)
|
84
84
|
end
|
85
85
|
|
86
|
+
when relation.sub_type.is_a?(AST::Types::Literal)
|
87
|
+
check0(
|
88
|
+
Relation.new(sub_type: relation.sub_type.back_type, super_type: relation.super_type),
|
89
|
+
assumption: assumption,
|
90
|
+
trace: trace,
|
91
|
+
constraints: constraints
|
92
|
+
)
|
93
|
+
|
86
94
|
when relation.sub_type.is_a?(AST::Types::Union)
|
87
95
|
results = relation.sub_type.types.map do |sub_type|
|
88
96
|
check0(Relation.new(sub_type: sub_type, super_type: relation.super_type),
|
@@ -156,6 +164,24 @@ module Steep
|
|
156
164
|
check_interface(sub_interface, super_interface, assumption: assumption, trace: trace, constraints: constraints)
|
157
165
|
end
|
158
166
|
|
167
|
+
when relation.sub_type.is_a?(AST::Types::Tuple) && relation.super_type.is_a?(AST::Types::Tuple)
|
168
|
+
if relation.sub_type.types[0, relation.super_type.types.size] == relation.super_type.types
|
169
|
+
success(constraints: constraints)
|
170
|
+
else
|
171
|
+
failure(error: Result::Failure::UnknownPairError.new(relation: relation),
|
172
|
+
trace: trace)
|
173
|
+
end
|
174
|
+
|
175
|
+
when relation.sub_type.is_a?(AST::Types::Tuple)
|
176
|
+
sub_interface = resolve(relation.sub_type, with_initialize: false)
|
177
|
+
super_interface = resolve(relation.super_type, with_initialize: false)
|
178
|
+
|
179
|
+
check_interface(sub_interface,
|
180
|
+
super_interface,
|
181
|
+
assumption: assumption,
|
182
|
+
trace: trace,
|
183
|
+
constraints: constraints)
|
184
|
+
|
159
185
|
else
|
160
186
|
failure(error: Result::Failure::UnknownPairError.new(relation: relation),
|
161
187
|
trace: trace)
|
@@ -528,6 +554,12 @@ module Steep
|
|
528
554
|
case type
|
529
555
|
when AST::Types::Any, AST::Types::Var, AST::Types::Class, AST::Types::Instance
|
530
556
|
raise CannotResolveError.new(type: type)
|
557
|
+
when AST::Types::Nil, AST::Types::Literal, AST::Types::Boolean
|
558
|
+
resolve(type.back_type,
|
559
|
+
self_type: self_type,
|
560
|
+
instance_type: instance_type,
|
561
|
+
module_type: module_type,
|
562
|
+
with_initialize: with_initialize)
|
531
563
|
when AST::Types::Name
|
532
564
|
builder.build(type.name, with_initialize: with_initialize).yield_self do |abstract|
|
533
565
|
case type.name
|
@@ -666,6 +698,52 @@ module Steep
|
|
666
698
|
Interface::Instantiated.new(type: type,
|
667
699
|
methods: {},
|
668
700
|
ivar_chains: {})
|
701
|
+
|
702
|
+
when AST::Types::Tuple
|
703
|
+
yield_self do
|
704
|
+
element_type = AST::Types::Union.build(types: type.types)
|
705
|
+
array_type = AST::Types::Name.new_instance(name: "::Array",
|
706
|
+
args: [element_type])
|
707
|
+
array_interface = resolve(array_type, self_type: self_type, with_initialize: with_initialize)
|
708
|
+
|
709
|
+
array_interface.methods[:[]] = array_interface.methods[:[]].yield_self do |aref|
|
710
|
+
types = type.types.map.with_index {|elem_type, index|
|
711
|
+
Interface::MethodType.new(
|
712
|
+
type_params: [],
|
713
|
+
params: Interface::Params.new(required: [AST::Types::Literal.new(value: index)],
|
714
|
+
optional: [],
|
715
|
+
rest: nil,
|
716
|
+
required_keywords: {},
|
717
|
+
optional_keywords: {},
|
718
|
+
rest_keywords: nil),
|
719
|
+
block: nil,
|
720
|
+
return_type: elem_type,
|
721
|
+
location: nil
|
722
|
+
)
|
723
|
+
} + aref.types
|
724
|
+
aref.with_types(types)
|
725
|
+
end
|
726
|
+
|
727
|
+
array_interface.methods[:[]=] = array_interface.methods[:[]=].yield_self do |aref|
|
728
|
+
types = type.types.map.with_index {|elem_type, index|
|
729
|
+
Interface::MethodType.new(
|
730
|
+
type_params: [],
|
731
|
+
params: Interface::Params.new(required: [AST::Types::Literal.new(value: index), elem_type],
|
732
|
+
optional: [],
|
733
|
+
rest: nil,
|
734
|
+
required_keywords: {},
|
735
|
+
optional_keywords: {},
|
736
|
+
rest_keywords: nil),
|
737
|
+
block: nil,
|
738
|
+
return_type: elem_type,
|
739
|
+
location: nil
|
740
|
+
)
|
741
|
+
} + aref.types
|
742
|
+
aref.with_types(types)
|
743
|
+
end
|
744
|
+
|
745
|
+
array_interface
|
746
|
+
end
|
669
747
|
end
|
670
748
|
end
|
671
749
|
end
|
@@ -12,7 +12,7 @@ module Steep
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def nil_instance
|
15
|
-
AST::Types::
|
15
|
+
AST::Types::Nil.new
|
16
16
|
end
|
17
17
|
|
18
18
|
def string_instance
|
@@ -32,7 +32,7 @@ module Steep
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def boolean?(type)
|
35
|
-
type
|
35
|
+
type.is_a?(AST::Types::Boolean)
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
@@ -432,14 +432,14 @@ module Steep
|
|
432
432
|
)
|
433
433
|
end
|
434
434
|
|
435
|
-
def synthesize(node)
|
435
|
+
def synthesize(node, hint: nil)
|
436
436
|
Steep.logger.tagged "synthesize:(#{node.location.expression.to_s.split(/:/, 2).last})" do
|
437
437
|
Steep.logger.debug node.type
|
438
438
|
case node.type
|
439
439
|
when :begin, :kwbegin
|
440
440
|
yield_self do
|
441
441
|
type = each_child_node(node).map do |child|
|
442
|
-
synthesize(child)
|
442
|
+
synthesize(child, hint: hint)
|
443
443
|
end.last
|
444
444
|
|
445
445
|
typing.add_typing(node, type)
|
@@ -829,23 +829,47 @@ module Steep
|
|
829
829
|
typing.add_typing(node, type)
|
830
830
|
end
|
831
831
|
|
832
|
-
when :int
|
833
|
-
typing.add_typing(node, AST::Types::Name.new_instance(name: "::Integer"))
|
834
|
-
|
835
832
|
when :float
|
836
833
|
typing.add_typing(node, AST::Types::Name.new_instance(name: "::Float"))
|
837
834
|
|
838
835
|
when :nil
|
839
836
|
typing.add_typing(node, Types.nil_instance)
|
840
837
|
|
838
|
+
when :int
|
839
|
+
yield_self do
|
840
|
+
literal_type = test_literal_type(node.children[0], hint)
|
841
|
+
|
842
|
+
if literal_type
|
843
|
+
typing.add_typing(node, literal_type)
|
844
|
+
else
|
845
|
+
typing.add_typing(node, AST::Types::Name.new_instance(name: "::Integer"))
|
846
|
+
end
|
847
|
+
end
|
848
|
+
|
841
849
|
when :sym
|
842
|
-
|
850
|
+
yield_self do
|
851
|
+
literal_type = test_literal_type(node.children[0], hint)
|
852
|
+
|
853
|
+
if literal_type
|
854
|
+
typing.add_typing(node, literal_type)
|
855
|
+
else
|
856
|
+
typing.add_typing(node, Types.symbol_instance)
|
857
|
+
end
|
858
|
+
end
|
843
859
|
|
844
860
|
when :str
|
845
|
-
|
861
|
+
yield_self do
|
862
|
+
literal_type = test_literal_type(node.children[0], hint)
|
863
|
+
|
864
|
+
if literal_type
|
865
|
+
typing.add_typing(node, literal_type)
|
866
|
+
else
|
867
|
+
typing.add_typing(node, Types.string_instance)
|
868
|
+
end
|
869
|
+
end
|
846
870
|
|
847
871
|
when :true, :false
|
848
|
-
typing.add_typing(node, AST::Types::
|
872
|
+
typing.add_typing(node, AST::Types::Boolean.new)
|
849
873
|
|
850
874
|
when :hash
|
851
875
|
yield_self do
|
@@ -1007,32 +1031,48 @@ module Steep
|
|
1007
1031
|
if node.children.empty?
|
1008
1032
|
typing.add_typing(node, Types.array_instance(Types.any))
|
1009
1033
|
else
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1034
|
+
is_tuple = hint.is_a?(AST::Types::Tuple)
|
1035
|
+
is_tuple &&= node.children.all? {|child| child.type != :splat }
|
1036
|
+
is_tuple &&= node.children.map.with_index do |child, index|
|
1037
|
+
synthesize(child, hint: absolute_type(hint.types[index]))
|
1038
|
+
end.yield_self do |types|
|
1039
|
+
tuple = AST::Types::Tuple.new(types: types)
|
1040
|
+
relation = Subtyping::Relation.new(sub_type: tuple, super_type: absolute_type(hint))
|
1041
|
+
result = checker.check(relation, constraints: Subtyping::Constraints.empty)
|
1042
|
+
result.success?
|
1043
|
+
end
|
1044
|
+
|
1045
|
+
if is_tuple
|
1046
|
+
array_type = hint
|
1047
|
+
else
|
1048
|
+
element_types = node.children.flat_map do |e|
|
1049
|
+
if e.type == :splat
|
1050
|
+
Steep.logger.info "Typing of splat in array is incompatible with Ruby; it does not use #to_a method"
|
1051
|
+
synthesize(e.children.first).yield_self do |type|
|
1052
|
+
case type
|
1053
|
+
when AST::Types::Union
|
1054
|
+
type.types
|
1055
|
+
else
|
1056
|
+
[type]
|
1057
|
+
end
|
1058
|
+
end.map do |type|
|
1059
|
+
case
|
1060
|
+
when type.is_a?(AST::Types::Name) && type.name.is_a?(TypeName::Instance) && type.name.name == ModuleName.new(name: "Array", absolute: true)
|
1061
|
+
type.args.first
|
1062
|
+
when type.is_a?(AST::Types::Name) && type.name.is_a?(TypeName::Instance) && type.name.name == ModuleName.new(name: "Range", absolute: true)
|
1063
|
+
type.args.first
|
1064
|
+
else
|
1065
|
+
type
|
1066
|
+
end
|
1028
1067
|
end
|
1068
|
+
else
|
1069
|
+
[synthesize(e)]
|
1029
1070
|
end
|
1030
|
-
else
|
1031
|
-
[synthesize(e)]
|
1032
1071
|
end
|
1072
|
+
array_type = Types.array_instance(AST::Types::Union.build(types: element_types))
|
1033
1073
|
end
|
1034
1074
|
|
1035
|
-
typing.add_typing(node,
|
1075
|
+
typing.add_typing(node, array_type)
|
1036
1076
|
end
|
1037
1077
|
end
|
1038
1078
|
|
@@ -1070,13 +1110,13 @@ module Steep
|
|
1070
1110
|
|
1071
1111
|
if true_clause
|
1072
1112
|
true_type, true_env = for_branch(true_clause, truthy_vars: truthy_vars).yield_self do |constructor|
|
1073
|
-
type = constructor.synthesize(true_clause)
|
1113
|
+
type = constructor.synthesize(true_clause, hint: hint)
|
1074
1114
|
[type, constructor.type_env]
|
1075
1115
|
end
|
1076
1116
|
end
|
1077
1117
|
if false_clause
|
1078
1118
|
false_type, false_env = for_branch(false_clause).yield_self do |constructor|
|
1079
|
-
type = constructor.synthesize(false_clause)
|
1119
|
+
type = constructor.synthesize(false_clause, hint: hint)
|
1080
1120
|
[type, constructor.type_env]
|
1081
1121
|
end
|
1082
1122
|
end
|
@@ -1099,7 +1139,7 @@ module Steep
|
|
1099
1139
|
pairs = whens.each.with_object([]) do |clause, pairs|
|
1100
1140
|
if clause&.type == :when
|
1101
1141
|
test_types = clause.children.take(clause.children.size - 1).map do |child|
|
1102
|
-
synthesize(child)
|
1142
|
+
synthesize(child, hint: hint)
|
1103
1143
|
end
|
1104
1144
|
|
1105
1145
|
if (body = clause.children.last)
|
@@ -1126,7 +1166,7 @@ module Steep
|
|
1126
1166
|
end
|
1127
1167
|
|
1128
1168
|
for_branch(body, type_case_override: type_case_override).yield_self do |body_construction|
|
1129
|
-
type = body_construction.synthesize(body)
|
1169
|
+
type = body_construction.synthesize(body, hint: hint)
|
1130
1170
|
pairs << [type, body_construction.type_env]
|
1131
1171
|
end
|
1132
1172
|
else
|
@@ -1149,7 +1189,7 @@ module Steep
|
|
1149
1189
|
end
|
1150
1190
|
|
1151
1191
|
for_branch(clause, type_case_override: type_case_override).yield_self do |body_construction|
|
1152
|
-
type = body_construction.synthesize(clause)
|
1192
|
+
type = body_construction.synthesize(clause, hint: hint)
|
1153
1193
|
pairs << [type, body_construction.type_env]
|
1154
1194
|
end
|
1155
1195
|
end
|
@@ -1352,7 +1392,7 @@ module Steep
|
|
1352
1392
|
end
|
1353
1393
|
|
1354
1394
|
def check(node, type)
|
1355
|
-
type_ = synthesize(node)
|
1395
|
+
type_ = synthesize(node, hint: type)
|
1356
1396
|
|
1357
1397
|
result = checker.check(
|
1358
1398
|
Subtyping::Relation.new(sub_type: type_,
|
@@ -1366,7 +1406,7 @@ module Steep
|
|
1366
1406
|
|
1367
1407
|
def type_assignment(var, rhs, node)
|
1368
1408
|
if rhs
|
1369
|
-
rhs_type = synthesize(rhs)
|
1409
|
+
rhs_type = synthesize(rhs, hint: type_env.lvar_types[var.name])
|
1370
1410
|
node_type = assign_type_to_variable(var, rhs_type, node)
|
1371
1411
|
typing.add_typing(node, node_type)
|
1372
1412
|
else
|
@@ -1374,13 +1414,9 @@ module Steep
|
|
1374
1414
|
lhs_type = variable_type(var)
|
1375
1415
|
|
1376
1416
|
if lhs_type
|
1377
|
-
typing.add_var_type(var, lhs_type)
|
1378
1417
|
typing.add_typing(node, lhs_type)
|
1379
|
-
var_types[var] = lhs_type
|
1380
1418
|
else
|
1381
|
-
typing.add_var_type(var, Types.any)
|
1382
1419
|
fallback_to_any node
|
1383
|
-
var_types[var] = Types.any
|
1384
1420
|
end
|
1385
1421
|
end
|
1386
1422
|
end
|
@@ -1431,6 +1467,34 @@ module Steep
|
|
1431
1467
|
|
1432
1468
|
typing.add_typing(node, rhs_type)
|
1433
1469
|
|
1470
|
+
when rhs_type.is_a?(AST::Types::Tuple) && lhs.children.all? {|a| a.type == :lvasgn || a.type == :ivasgn }
|
1471
|
+
lhs.children.each.with_index do |asgn, index|
|
1472
|
+
type = rhs_type.types[index]
|
1473
|
+
|
1474
|
+
case
|
1475
|
+
when asgn.type == :lvasgn && asgn.children[0].name != :_
|
1476
|
+
type ||= Types.nil_instance
|
1477
|
+
type_env.assign(lvar: asgn.children[0].name, type: type) do |result|
|
1478
|
+
var_type = type_env.get(lvar: asgn.children[0].name)
|
1479
|
+
typing.add_error(Errors::IncompatibleAssignment.new(node: node,
|
1480
|
+
lhs_type: var_type,
|
1481
|
+
rhs_type: type,
|
1482
|
+
result: result))
|
1483
|
+
end
|
1484
|
+
when asgn.type == :ivasgn
|
1485
|
+
type ||= Types.nil_instance
|
1486
|
+
type_env.assign(ivar: asgn.children[0], type: type) do |result|
|
1487
|
+
var_type = type_env.get(ivar: asgn.children[0])
|
1488
|
+
typing.add_error(Errors::IncompatibleAssignment.new(node: node,
|
1489
|
+
lhs_type: var_type,
|
1490
|
+
rhs_type: type,
|
1491
|
+
result: result))
|
1492
|
+
end
|
1493
|
+
end
|
1494
|
+
end
|
1495
|
+
|
1496
|
+
typing.add_typing(node, rhs_type)
|
1497
|
+
|
1434
1498
|
when rhs_type.is_a?(AST::Types::Any)
|
1435
1499
|
fallback_to_any(node)
|
1436
1500
|
|
@@ -1503,14 +1567,6 @@ module Steep
|
|
1503
1567
|
def type_send(node, send_node:, block_params:, block_body:, unwrap: false)
|
1504
1568
|
receiver, method_name, *arguments = send_node.children
|
1505
1569
|
receiver_type = receiver ? synthesize(receiver) : self_type
|
1506
|
-
arguments.each do |arg|
|
1507
|
-
if arg.type == :splat
|
1508
|
-
type = synthesize(arg.children[0])
|
1509
|
-
typing.add_typing(arg, Types.array_instance(type))
|
1510
|
-
else
|
1511
|
-
synthesize(arg)
|
1512
|
-
end
|
1513
|
-
end
|
1514
1570
|
|
1515
1571
|
if unwrap
|
1516
1572
|
receiver_type = TypeConstruction.unwrap(receiver_type)
|
@@ -1554,9 +1610,82 @@ module Steep
|
|
1554
1610
|
Errors::NoMethod.new(node: node, method: method_name, type: receiver_type)
|
1555
1611
|
end
|
1556
1612
|
end
|
1613
|
+
end.tap do
|
1614
|
+
arguments.each do |arg|
|
1615
|
+
unless typing.has_type?(arg)
|
1616
|
+
if arg.type == :splat
|
1617
|
+
type = synthesize(arg.children[0])
|
1618
|
+
typing.add_typing(arg, Types.array_instance(type))
|
1619
|
+
else
|
1620
|
+
synthesize(arg)
|
1621
|
+
end
|
1622
|
+
end
|
1623
|
+
end
|
1624
|
+
|
1625
|
+
if block_body && block_params
|
1626
|
+
unless typing.has_type?(block_body)
|
1627
|
+
block_annotations = source.annotations(block: node)
|
1628
|
+
params = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
|
1629
|
+
pairs = params.each.map {|param| [param, Types.any] }
|
1630
|
+
|
1631
|
+
for_block, _ = for_block(block_annotations: block_annotations,
|
1632
|
+
param_pairs: pairs,
|
1633
|
+
method_return_type: Types.any,
|
1634
|
+
typing: typing)
|
1635
|
+
|
1636
|
+
for_block.synthesize(block_body)
|
1637
|
+
end
|
1638
|
+
end
|
1557
1639
|
end
|
1558
1640
|
end
|
1559
1641
|
|
1642
|
+
def for_block(block_annotations:, param_pairs:, method_return_type:, typing:)
|
1643
|
+
block_type_env = type_env.dup.yield_self do |env|
|
1644
|
+
param_pairs.each do |param, type|
|
1645
|
+
if param.type
|
1646
|
+
env.set(lvar: param.var.name, type: absolute_type(param.type))
|
1647
|
+
else
|
1648
|
+
env.set(lvar: param.var.name, type: absolute_type(type))
|
1649
|
+
end
|
1650
|
+
end
|
1651
|
+
|
1652
|
+
env.with_annotations(
|
1653
|
+
lvar_types: block_annotations.var_types.transform_values {|annot| absolute_type(annot.type) },
|
1654
|
+
ivar_types: block_annotations.ivar_types.transform_values {|type| absolute_type(type) },
|
1655
|
+
const_types: block_annotations.const_types.transform_values {|type| absolute_type(type) }
|
1656
|
+
)
|
1657
|
+
end
|
1658
|
+
|
1659
|
+
return_type = if block_annotations.break_type
|
1660
|
+
union_type(method_return_type, absolute_type(block_annotations.break_type))
|
1661
|
+
else
|
1662
|
+
method_return_type
|
1663
|
+
end
|
1664
|
+
Steep.logger.debug("return_type = #{return_type}")
|
1665
|
+
|
1666
|
+
block_context = BlockContext.new(body_type: absolute_type(block_annotations.block_type))
|
1667
|
+
Steep.logger.debug("block_context { body_type: #{block_context.body_type} }")
|
1668
|
+
|
1669
|
+
break_context = BreakContext.new(
|
1670
|
+
break_type: absolute_type(block_annotations.break_type) || method_return_type,
|
1671
|
+
next_type: absolute_type(block_annotations.block_type)
|
1672
|
+
)
|
1673
|
+
Steep.logger.debug("break_context { type: #{absolute_type(break_context.break_type)} }")
|
1674
|
+
|
1675
|
+
[self.class.new(
|
1676
|
+
checker: checker,
|
1677
|
+
source: source,
|
1678
|
+
annotations: annotations + block_annotations,
|
1679
|
+
type_env: block_type_env,
|
1680
|
+
block_context: block_context,
|
1681
|
+
typing: typing,
|
1682
|
+
method_context: method_context,
|
1683
|
+
module_context: module_context,
|
1684
|
+
self_type: absolute_type(block_annotations.self_type) || self_type,
|
1685
|
+
break_context: break_context
|
1686
|
+
), return_type]
|
1687
|
+
end
|
1688
|
+
|
1560
1689
|
def type_method_call(node, receiver_type:, method:, args:, block_params:, block_body:)
|
1561
1690
|
results = method.types.map do |method_type|
|
1562
1691
|
Steep.logger.tagged method_type.location&.source do
|
@@ -1590,184 +1719,172 @@ module Steep
|
|
1590
1719
|
fresh_vars = Set.new(fresh_types.map(&:name))
|
1591
1720
|
instantiation = Interface::Substitution.build(method_type.type_params, fresh_types)
|
1592
1721
|
|
1593
|
-
|
1594
|
-
|
1595
|
-
|
1596
|
-
|
1722
|
+
typing.new_child do |child_typing|
|
1723
|
+
construction = self.class.new(
|
1724
|
+
checker: checker,
|
1725
|
+
source: source,
|
1726
|
+
annotations: annotations,
|
1727
|
+
type_env: type_env,
|
1728
|
+
typing: child_typing,
|
1729
|
+
self_type: self_type,
|
1730
|
+
method_context: method_context,
|
1731
|
+
block_context: block_context,
|
1732
|
+
module_context: module_context,
|
1733
|
+
break_context: break_context
|
1734
|
+
)
|
1597
1735
|
|
1598
|
-
|
1599
|
-
|
1600
|
-
|
1601
|
-
|
1602
|
-
|
1736
|
+
method_type.instantiate(instantiation).yield_self do |method_type|
|
1737
|
+
constraints = Subtyping::Constraints.new(unknowns: fresh_types.map(&:name))
|
1738
|
+
variance = Subtyping::VariableVariance.from_method_type(method_type)
|
1739
|
+
occurence = Subtyping::VariableOccurence.from_method_type(method_type)
|
1740
|
+
|
1741
|
+
arg_pairs.each do |(arg_node, param_type)|
|
1742
|
+
arg_type = if arg_node.type == :splat
|
1743
|
+
type = construction.synthesize(arg_node.children[0])
|
1744
|
+
child_typing.add_typing(arg_node, Types.array_instance(type))
|
1745
|
+
else
|
1746
|
+
construction.synthesize(arg_node, hint: param_type)
|
1747
|
+
end
|
1603
1748
|
|
1604
|
-
|
1605
|
-
|
1606
|
-
|
1607
|
-
receiver_type: receiver_type,
|
1608
|
-
expected: relation.super_type,
|
1609
|
-
actual: relation.sub_type
|
1749
|
+
relation = Subtyping::Relation.new(
|
1750
|
+
sub_type: arg_type,
|
1751
|
+
super_type: param_type.subst(instantiation)
|
1610
1752
|
)
|
1611
|
-
end
|
1612
|
-
end
|
1613
1753
|
|
1614
|
-
|
1615
|
-
|
1754
|
+
checker.check(relation, constraints: constraints).else do |result|
|
1755
|
+
return Errors::ArgumentTypeMismatch.new(
|
1756
|
+
node: arg_node,
|
1757
|
+
receiver_type: receiver_type,
|
1758
|
+
expected: relation.super_type,
|
1759
|
+
actual: relation.sub_type
|
1760
|
+
)
|
1761
|
+
end
|
1762
|
+
end
|
1616
1763
|
|
1617
|
-
|
1618
|
-
|
1764
|
+
if method_type.block && block_params
|
1765
|
+
block_annotations = source.annotations(block: node)
|
1619
1766
|
|
1620
|
-
|
1621
|
-
|
1622
|
-
node: node,
|
1623
|
-
method_type: method_type
|
1624
|
-
)
|
1625
|
-
end
|
1767
|
+
params = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
|
1768
|
+
block_param_pairs = params.zip(method_type.block.params)
|
1626
1769
|
|
1627
|
-
|
1628
|
-
|
1629
|
-
|
1630
|
-
|
1631
|
-
super_type: absolute_type(param.type)
|
1770
|
+
unless block_param_pairs
|
1771
|
+
return Errors::IncompatibleBlockParameters.new(
|
1772
|
+
node: node,
|
1773
|
+
method_type: method_type
|
1632
1774
|
)
|
1775
|
+
end
|
1633
1776
|
|
1634
|
-
|
1635
|
-
|
1636
|
-
|
1637
|
-
|
1638
|
-
|
1777
|
+
block_param_pairs.each do |param, type|
|
1778
|
+
if param.type
|
1779
|
+
relation = Subtyping::Relation.new(
|
1780
|
+
sub_type: type,
|
1781
|
+
super_type: absolute_type(param.type)
|
1639
1782
|
)
|
1783
|
+
|
1784
|
+
checker.check(relation, constraints: constraints).else do |result|
|
1785
|
+
return Errors::BlockParameterTypeMismatch.new(
|
1786
|
+
node: param.node,
|
1787
|
+
expected: type,
|
1788
|
+
actual: param.type
|
1789
|
+
)
|
1790
|
+
end
|
1640
1791
|
end
|
1641
1792
|
end
|
1642
|
-
end
|
1643
1793
|
|
1644
|
-
|
1645
|
-
|
1646
|
-
|
1647
|
-
|
1648
|
-
|
1794
|
+
if block_annotations.block_type
|
1795
|
+
relation = Subtyping::Relation.new(
|
1796
|
+
sub_type: absolute_type(block_annotations.block_type),
|
1797
|
+
super_type: method_type.block.return_type
|
1798
|
+
)
|
1649
1799
|
|
1650
|
-
|
1651
|
-
|
1652
|
-
|
1653
|
-
|
1654
|
-
|
1800
|
+
checker.check(relation, constraints: constraints).else do |result|
|
1801
|
+
typing.add_error Errors::BlockTypeMismatch.new(node: node,
|
1802
|
+
expected: method_type.block.return_type,
|
1803
|
+
actual: absolute_type(block_annotations.block_type),
|
1804
|
+
result: result)
|
1805
|
+
end
|
1655
1806
|
end
|
1656
1807
|
end
|
1657
|
-
end
|
1658
|
-
|
1659
|
-
case
|
1660
|
-
when method_type.block && block_params && block_body
|
1661
|
-
Steep.logger.debug "block is okay: method_type=#{method_type}"
|
1662
|
-
Steep.logger.debug "Constraints = #{constraints}"
|
1663
1808
|
|
1664
|
-
|
1665
|
-
|
1666
|
-
|
1809
|
+
case
|
1810
|
+
when method_type.block && block_params && block_body
|
1811
|
+
Steep.logger.debug "block is okay: method_type=#{method_type}"
|
1812
|
+
Steep.logger.debug "Constraints = #{constraints}"
|
1667
1813
|
|
1668
|
-
|
1669
|
-
|
1814
|
+
begin
|
1815
|
+
method_type.subst(constraints.solution(checker, variance: variance, variables: occurence.params)).yield_self do |method_type|
|
1816
|
+
block_annotations = source.annotations(block: node)
|
1670
1817
|
|
1671
|
-
|
1672
|
-
|
1673
|
-
if param.type
|
1674
|
-
env.set(lvar: param.var.name, type: absolute_type(param.type))
|
1675
|
-
else
|
1676
|
-
env.set(lvar: param.var.name, type: absolute_type(type))
|
1677
|
-
end
|
1818
|
+
block_param_pairs = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations).yield_self do |params|
|
1819
|
+
params.zip(method_type.block.params)
|
1678
1820
|
end
|
1679
1821
|
|
1680
|
-
|
1681
|
-
|
1682
|
-
|
1683
|
-
|
1684
|
-
)
|
1685
|
-
end
|
1686
|
-
|
1687
|
-
return_type = if block_annotations.break_type
|
1688
|
-
union_type(method_type.return_type, absolute_type(block_annotations.break_type))
|
1689
|
-
else
|
1690
|
-
method_type.return_type
|
1691
|
-
end
|
1692
|
-
Steep.logger.debug("return_type = #{return_type}")
|
1693
|
-
|
1694
|
-
block_context = BlockContext.new(body_type: absolute_type(block_annotations.block_type))
|
1695
|
-
Steep.logger.debug("block_context { body_type: #{block_context.body_type} }")
|
1822
|
+
for_block, return_type = for_block(block_annotations: block_annotations,
|
1823
|
+
param_pairs: block_param_pairs,
|
1824
|
+
method_return_type: method_type.return_type,
|
1825
|
+
typing: child_typing)
|
1696
1826
|
|
1697
|
-
|
1698
|
-
|
1699
|
-
|
1700
|
-
)
|
1701
|
-
Steep.logger.debug("break_context { type: #{absolute_type(break_context.break_type)} }")
|
1702
|
-
|
1703
|
-
for_block = self.class.new(
|
1704
|
-
checker: checker,
|
1705
|
-
source: source,
|
1706
|
-
annotations: annotations + block_annotations,
|
1707
|
-
type_env: block_type_env,
|
1708
|
-
block_context: block_context,
|
1709
|
-
typing: typing,
|
1710
|
-
method_context: method_context,
|
1711
|
-
module_context: module_context,
|
1712
|
-
self_type: absolute_type(block_annotations.self_type) || self_type,
|
1713
|
-
break_context: break_context
|
1714
|
-
)
|
1715
|
-
|
1716
|
-
each_child_node(block_params) do |p|
|
1717
|
-
for_block.synthesize(p)
|
1718
|
-
end
|
1827
|
+
each_child_node(block_params) do |p|
|
1828
|
+
for_block.synthesize(p)
|
1829
|
+
end
|
1719
1830
|
|
1720
|
-
|
1831
|
+
block_body_type = for_block.synthesize(block_body)
|
1721
1832
|
|
1722
|
-
|
1723
|
-
|
1724
|
-
|
1725
|
-
|
1726
|
-
|
1833
|
+
unless method_type.block.return_type.is_a?(AST::Types::Void)
|
1834
|
+
result = checker.check(Subtyping::Relation.new(
|
1835
|
+
sub_type: block_annotations.block_type || block_body_type,
|
1836
|
+
super_type: method_type.block.return_type
|
1837
|
+
), constraints: constraints)
|
1727
1838
|
|
1728
|
-
|
1729
|
-
|
1839
|
+
if result.success?
|
1840
|
+
return_type.subst(constraints.solution(checker, variance: variance, variables: fresh_vars)).tap do
|
1841
|
+
child_typing.save!
|
1842
|
+
end
|
1843
|
+
else
|
1844
|
+
typing.add_error Errors::BlockTypeMismatch.new(node: node,
|
1845
|
+
expected: method_type.block.return_type,
|
1846
|
+
actual: block_annotations.block_type || block_body_type,
|
1847
|
+
result: result)
|
1848
|
+
return_type
|
1849
|
+
end
|
1730
1850
|
else
|
1731
|
-
|
1732
|
-
expected: method_type.block.return_type,
|
1733
|
-
actual: block_annotations.block_type || block_body_type,
|
1734
|
-
result: result)
|
1851
|
+
child_typing.save!
|
1735
1852
|
return_type
|
1736
1853
|
end
|
1737
|
-
else
|
1738
|
-
return_type
|
1739
1854
|
end
|
1740
|
-
end
|
1741
1855
|
|
1742
|
-
|
1743
|
-
|
1744
|
-
|
1745
|
-
|
1746
|
-
|
1747
|
-
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1751
|
-
|
1856
|
+
rescue Subtyping::Constraints::UnsatisfiableConstraint => exn
|
1857
|
+
typing.add_error Errors::UnsatisfiableConstraint.new(node: node,
|
1858
|
+
method_type: method_type,
|
1859
|
+
var: exn.var,
|
1860
|
+
sub_type: exn.sub_type,
|
1861
|
+
super_type: exn.super_type,
|
1862
|
+
result: exn.result
|
1863
|
+
)
|
1864
|
+
fallback_any_rec node
|
1865
|
+
end
|
1752
1866
|
|
1753
|
-
|
1754
|
-
|
1755
|
-
|
1867
|
+
when !method_type.block && !block_params && !block_body
|
1868
|
+
# OK, without block
|
1869
|
+
method_type.subst(constraints.solution(checker, variance: variance, variables: fresh_vars)).return_type.tap do
|
1870
|
+
child_typing.save!
|
1871
|
+
end
|
1756
1872
|
|
1757
|
-
|
1758
|
-
|
1759
|
-
|
1760
|
-
|
1761
|
-
|
1873
|
+
when !method_type.block && block_params && block_body
|
1874
|
+
Errors::UnexpectedBlockGiven.new(
|
1875
|
+
node: node,
|
1876
|
+
method_type: method_type
|
1877
|
+
)
|
1762
1878
|
|
1763
|
-
|
1764
|
-
|
1765
|
-
|
1766
|
-
|
1767
|
-
|
1879
|
+
when method_type.block && !block_params && !block_body
|
1880
|
+
Errors::RequiredBlockMissing.new(
|
1881
|
+
node: node,
|
1882
|
+
method_type: method_type
|
1883
|
+
)
|
1768
1884
|
|
1769
|
-
|
1770
|
-
|
1885
|
+
else
|
1886
|
+
raise "Unexpected case condition"
|
1887
|
+
end
|
1771
1888
|
end
|
1772
1889
|
end
|
1773
1890
|
end
|
@@ -2120,7 +2237,7 @@ module Steep
|
|
2120
2237
|
def self.unwrap(type)
|
2121
2238
|
case
|
2122
2239
|
when type.is_a?(AST::Types::Union)
|
2123
|
-
types = type.types.reject {|type| type.is_a?(AST::Types::
|
2240
|
+
types = type.types.reject {|type| type.is_a?(AST::Types::Nil) }
|
2124
2241
|
AST::Types::Union.build(types: types)
|
2125
2242
|
else
|
2126
2243
|
type
|
@@ -2154,5 +2271,18 @@ module Steep
|
|
2154
2271
|
Set.new
|
2155
2272
|
end
|
2156
2273
|
end
|
2274
|
+
|
2275
|
+
def test_literal_type(literal, hint)
|
2276
|
+
case hint
|
2277
|
+
when AST::Types::Literal
|
2278
|
+
if hint.value == literal
|
2279
|
+
hint
|
2280
|
+
end
|
2281
|
+
when AST::Types::Union
|
2282
|
+
if hint.types.any? {|ty| ty.is_a?(AST::Types::Literal) && ty.value == literal }
|
2283
|
+
hint
|
2284
|
+
end
|
2285
|
+
end
|
2286
|
+
end
|
2157
2287
|
end
|
2158
2288
|
end
|