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.
@@ -18,15 +18,13 @@ method_type:
18
18
  return_type: val[4])
19
19
  }
20
20
 
21
- return_type: simple_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
- | type { result = LocatedValue.new(location: val[0].location,
29
- value: AST::MethodType::Params::Required.new(location: val[0].location, type: val[0])) }
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::Name.new_instance(name: ModuleName.new(name: "NilClass", absolute: true),
158
- location: val[0].location) }
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: simple_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: IDENT
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
- | CONSTRUCTOR { result = LocatedValue.new(location: val[0].location, value: :constructor) }
432
- | NOCONSTRUCTOR { result = LocatedValue.new(location: val[0].location, value: :noconstructor) }
433
- | ANY QUESTION {
434
- raise ParseError, "\nunexpected method name any ?" unless val[0].location.pred?(val[1].location)
435
- result = LocatedValue.new(location: val[0].location + val[1].location, value: :any?)
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
- | ATTR_READER
442
- | ATTR_ACCESSOR
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::Name.new_instance(name: "::NilClass")
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 == AST::Types::Name.new_interface(name: :_Boolean)
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
- typing.add_typing(node, Types.symbol_instance)
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
- typing.add_typing(node, Types.string_instance)
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::Name.new_interface(name: :_Boolean))
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
- types = node.children.flat_map do |e|
1011
- if e.type == :splat
1012
- Steep.logger.info "Typing of splat in array is incompatible with Ruby; it does not use #to_a method"
1013
- synthesize(e.children.first).yield_self do |type|
1014
- case type
1015
- when AST::Types::Union
1016
- type.types
1017
- else
1018
- [type]
1019
- end
1020
- end.map do |type|
1021
- case
1022
- when type.is_a?(AST::Types::Name) && type.name.is_a?(TypeName::Instance) && type.name.name == ModuleName.new(name: "Array", absolute: true)
1023
- type.args.first
1024
- when type.is_a?(AST::Types::Name) && type.name.is_a?(TypeName::Instance) && type.name.name == ModuleName.new(name: "Range", absolute: true)
1025
- type.args.first
1026
- else
1027
- type
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, Types.array_instance(AST::Types::Union.build(types: types)))
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
- method_type.instantiate(instantiation).yield_self do |method_type|
1594
- constraints = Subtyping::Constraints.new(unknowns: fresh_types.map(&:name))
1595
- variance = Subtyping::VariableVariance.from_method_type(method_type)
1596
- occurence = Subtyping::VariableOccurence.from_method_type(method_type)
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
- arg_pairs.each do |(arg_node, param_type)|
1599
- relation = Subtyping::Relation.new(
1600
- sub_type: typing.type_of(node: arg_node),
1601
- super_type: param_type.subst(instantiation)
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
- checker.check(relation, constraints: constraints).else do |result|
1605
- return Errors::ArgumentTypeMismatch.new(
1606
- node: arg_node,
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
- if method_type.block && block_params
1615
- block_annotations = source.annotations(block: node)
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
- params = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
1618
- block_param_pairs = params.zip(method_type.block.params)
1764
+ if method_type.block && block_params
1765
+ block_annotations = source.annotations(block: node)
1619
1766
 
1620
- unless block_param_pairs
1621
- return Errors::IncompatibleBlockParameters.new(
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
- block_param_pairs.each do |param, type|
1628
- if param.type
1629
- relation = Subtyping::Relation.new(
1630
- sub_type: type,
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
- checker.check(relation, constraints: constraints).else do |result|
1635
- return Errors::BlockParameterTypeMismatch.new(
1636
- node: param.node,
1637
- expected: type,
1638
- actual: param.type
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
- if block_annotations.block_type
1645
- relation = Subtyping::Relation.new(
1646
- sub_type: absolute_type(block_annotations.block_type),
1647
- super_type: method_type.block.return_type
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
- checker.check(relation, constraints: constraints).else do |result|
1651
- typing.add_error Errors::BlockTypeMismatch.new(node: node,
1652
- expected: method_type.block.return_type,
1653
- actual: absolute_type(block_annotations.block_type),
1654
- result: result)
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
- begin
1665
- method_type.subst(constraints.solution(checker, variance: variance, variables: occurence.params)).yield_self do |method_type|
1666
- block_annotations = source.annotations(block: node)
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
- params = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
1669
- block_param_pairs = params.zip(method_type.block.params)
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
- block_type_env = type_env.dup.yield_self do |env|
1672
- block_param_pairs.each do |param, type|
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
- env.with_annotations(
1681
- lvar_types: block_annotations.var_types.transform_values {|annot| absolute_type(annot.type) },
1682
- ivar_types: block_annotations.ivar_types.transform_values {|type| absolute_type(type) },
1683
- const_types: block_annotations.const_types.transform_values {|type| absolute_type(type) }
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
- break_context = BreakContext.new(
1698
- break_type: absolute_type(block_annotations.break_type) || method_type.return_type,
1699
- next_type: absolute_type(block_annotations.block_type)
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
- block_body_type = for_block.synthesize(block_body)
1831
+ block_body_type = for_block.synthesize(block_body)
1721
1832
 
1722
- unless method_type.block.return_type.is_a?(AST::Types::Void)
1723
- result = checker.check(Subtyping::Relation.new(
1724
- sub_type: block_annotations.block_type || block_body_type,
1725
- super_type: method_type.block.return_type
1726
- ), constraints: constraints)
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
- if result.success?
1729
- return_type.subst(constraints.solution(checker, variance: variance, variables: fresh_vars))
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
- typing.add_error Errors::BlockTypeMismatch.new(node: node,
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
- rescue Subtyping::Constraints::UnsatisfiableConstraint => exn
1743
- typing.add_error Errors::UnsatisfiableConstraint.new(node: node,
1744
- method_type: method_type,
1745
- var: exn.var,
1746
- sub_type: exn.sub_type,
1747
- super_type: exn.super_type,
1748
- result: exn.result
1749
- )
1750
- fallback_any_rec node
1751
- end
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
- when !method_type.block && !block_params && !block_body
1754
- # OK, without block
1755
- method_type.subst(constraints.solution(checker, variance: variance, variables: fresh_vars)).return_type
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
- when !method_type.block && block_params && block_body
1758
- Errors::UnexpectedBlockGiven.new(
1759
- node: node,
1760
- method_type: method_type
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
- when method_type.block && !block_params && !block_body
1764
- Errors::RequiredBlockMissing.new(
1765
- node: node,
1766
- method_type: method_type
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
- else
1770
- raise "Unexpected case condition"
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::Name) && type.name == TypeName::Instance.new(name: ModuleName.parse("::NilClass")) }
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