steep 0.3.0 → 0.4.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 +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
|