steep 0.3.0 → 0.4.0

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