steep 0.33.0 → 0.38.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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +28 -0
  3. data/lib/steep.rb +9 -0
  4. data/lib/steep/annotation_parser.rb +1 -1
  5. data/lib/steep/ast/types/factory.rb +167 -102
  6. data/lib/steep/ast/types/logic.rb +20 -1
  7. data/lib/steep/ast/types/proc.rb +32 -20
  8. data/lib/steep/cli.rb +15 -2
  9. data/lib/steep/drivers/print_project.rb +11 -0
  10. data/lib/steep/drivers/stats.rb +85 -0
  11. data/lib/steep/drivers/vendor.rb +1 -20
  12. data/lib/steep/errors.rb +38 -15
  13. data/lib/steep/index/rbs_index.rb +334 -0
  14. data/lib/steep/index/signature_symbol_provider.rb +154 -0
  15. data/lib/steep/index/source_index.rb +100 -0
  16. data/lib/steep/interface/block.rb +79 -0
  17. data/lib/steep/interface/function.rb +770 -0
  18. data/lib/steep/interface/method_type.rb +41 -832
  19. data/lib/steep/method_name.rb +28 -0
  20. data/lib/steep/project/completion_provider.rb +24 -15
  21. data/lib/steep/project/dsl.rb +13 -17
  22. data/lib/steep/project/options.rb +4 -4
  23. data/lib/steep/project/source_file.rb +2 -1
  24. data/lib/steep/project/target.rb +19 -10
  25. data/lib/steep/server/interaction_worker.rb +1 -1
  26. data/lib/steep/server/master.rb +5 -1
  27. data/lib/steep/server/signature_worker.rb +63 -6
  28. data/lib/steep/subtyping/check.rb +70 -32
  29. data/lib/steep/subtyping/variable_occurrence.rb +4 -2
  30. data/lib/steep/subtyping/variable_variance.rb +2 -2
  31. data/lib/steep/type_construction.rb +780 -495
  32. data/lib/steep/type_inference/block_params.rb +1 -1
  33. data/lib/steep/type_inference/constant_env.rb +5 -1
  34. data/lib/steep/type_inference/context.rb +7 -3
  35. data/lib/steep/type_inference/local_variable_type_env.rb +10 -1
  36. data/lib/steep/type_inference/logic_type_interpreter.rb +3 -0
  37. data/lib/steep/type_inference/method_call.rb +116 -0
  38. data/lib/steep/typing.rb +46 -10
  39. data/lib/steep/version.rb +1 -1
  40. data/smoke/regression/range.rb +5 -0
  41. data/smoke/tsort/Steepfile +6 -0
  42. data/smoke/tsort/a.rb +15 -0
  43. data/steep.gemspec +1 -1
  44. metadata +17 -6
@@ -10,12 +10,12 @@ module Steep
10
10
  end
11
11
 
12
12
  def add_method_type(method_type)
13
- method_type.params.each_type do |type|
13
+ method_type.type.params.each_type do |type|
14
14
  each_var(type) do |var|
15
15
  params << var
16
16
  end
17
17
  end
18
- each_var(method_type.return_type) do |var|
18
+ each_var(method_type.type.return_type) do |var|
19
19
  returns << var
20
20
  end
21
21
 
@@ -29,6 +29,8 @@ module Steep
29
29
  returns << var
30
30
  end
31
31
  end
32
+
33
+ params.subtract(returns)
32
34
  end
33
35
 
34
36
  def each_var(type, &block)
@@ -25,8 +25,8 @@ module Steep
25
25
  covariants = Set.new
26
26
  contravariants = Set.new
27
27
 
28
- add_params(method_type.params, block: false, contravariants: contravariants, covariants: covariants)
29
- add_type(method_type.return_type, variance: :covariant, covariants: covariants, contravariants: contravariants)
28
+ add_params(method_type.type.params, block: false, contravariants: contravariants, covariants: covariants)
29
+ add_type(method_type.type.return_type, variance: :covariant, covariants: covariants, contravariants: contravariants)
30
30
 
31
31
  method_type.block&.type&.yield_self do |proc|
32
32
  add_params(proc.params, block: true, contravariants: contravariants, covariants: covariants)
@@ -131,7 +131,7 @@ module Steep
131
131
  definition_method_type = if definition
132
132
  definition.methods[method_name]&.yield_self do |method|
133
133
  method.method_types
134
- .map {|method_type| checker.factory.method_type(method_type, self_type: self_type) }
134
+ .map {|method_type| checker.factory.method_type(method_type, self_type: self_type, method_decls: Set[]) }
135
135
  .select {|method_type| method_type.is_a?(Interface::MethodType) }
136
136
  .inject {|t1, t2| t1 + t2}
137
137
  end
@@ -140,10 +140,10 @@ module Steep
140
140
 
141
141
  method_type = annotation_method_type || definition_method_type
142
142
 
143
- if annots&.return_type && method_type&.return_type
144
- check_relation(sub_type: annots.return_type, super_type: method_type.return_type).else do |result|
143
+ if annots&.return_type && method_type&.type&.return_type
144
+ check_relation(sub_type: annots.return_type, super_type: method_type.type.return_type).else do |result|
145
145
  typing.add_error Errors::MethodReturnTypeAnnotationMismatch.new(node: node,
146
- method_type: method_type.return_type,
146
+ method_type: method_type.type.return_type,
147
147
  annotation_type: annots.return_type,
148
148
  result: result)
149
149
  end
@@ -152,19 +152,18 @@ module Steep
152
152
  # constructor_method = method&.attributes&.include?(:constructor)
153
153
 
154
154
  if method_type
155
- var_types = TypeConstruction.parameter_types(args, method_type)
156
- unless TypeConstruction.valid_parameter_env?(var_types, args.reject {|arg| arg.type == :blockarg}, method_type.params)
155
+ var_types = TypeConstruction.parameter_types(args, method_type.type)
156
+ unless TypeConstruction.valid_parameter_env?(var_types, args.reject {|arg| arg.type == :blockarg}, method_type.type.params)
157
157
  typing.add_error Errors::MethodArityMismatch.new(node: node)
158
158
  end
159
159
  end
160
160
 
161
161
  if (block_arg = args.find {|arg| arg.type == :blockarg})
162
162
  if method_type&.block
163
- block_type = if method_type.block.optional?
164
- AST::Types::Union.build(types: [method_type.block.type, AST::Builtin.nil_type])
165
- else
166
- method_type.block.type
167
- end
163
+ block_type = AST::Types::Proc.new(type: method_type.block.type, block: nil)
164
+ if method_type.block.optional?
165
+ block_type = AST::Types::Union.build(types: [block_type, AST::Builtin.nil_type])
166
+ end
168
167
  var_types[block_arg.children[0]] = block_type
169
168
  end
170
169
  end
@@ -183,7 +182,7 @@ module Steep
183
182
  name: method_name,
184
183
  method: definition && definition.methods[method_name],
185
184
  method_type: method_type,
186
- return_type: annots.return_type || method_type&.return_type || AST::Builtin.any_type,
185
+ return_type: annots.return_type || method_type&.type&.return_type || AST::Builtin.any_type,
187
186
  constructor: false,
188
187
  super_method: super_method
189
188
  )
@@ -216,6 +215,21 @@ module Steep
216
215
 
217
216
  lvar_env = lvar_env.annotate(annots)
218
217
 
218
+ call_context = case self_type
219
+ when nil
220
+ TypeInference::MethodCall::UnknownContext.new()
221
+ when AST::Types::Name::Singleton
222
+ TypeInference::MethodCall::MethodContext.new(
223
+ method_name: SingletonMethodName.new(type_name: module_context.class_name, method_name: method_name)
224
+ )
225
+ when AST::Types::Name::Instance, AST::Types::Intersection
226
+ TypeInference::MethodCall::MethodContext.new(
227
+ method_name: InstanceMethodName.new(type_name: module_context.class_name, method_name: method_name)
228
+ )
229
+ else
230
+ raise "Unexpected self_type: #{self_type}"
231
+ end
232
+
219
233
  self.class.new(
220
234
  checker: checker,
221
235
  source: source,
@@ -227,7 +241,8 @@ module Steep
227
241
  break_context: nil,
228
242
  self_type: annots.self_type || self_type,
229
243
  type_env: type_env,
230
- lvar_env: lvar_env
244
+ lvar_env: lvar_env,
245
+ call_context: call_context
231
246
  ),
232
247
  typing: typing,
233
248
  )
@@ -355,7 +370,8 @@ module Steep
355
370
  module_context: module_context_,
356
371
  self_type: module_context_.module_type,
357
372
  type_env: module_type_env,
358
- lvar_env: lvar_env
373
+ lvar_env: lvar_env,
374
+ call_context: TypeInference::MethodCall::ModuleContext.new(type_name: module_context_.class_name)
359
375
  )
360
376
  )
361
377
  end
@@ -424,7 +440,8 @@ module Steep
424
440
  break_context: nil,
425
441
  self_type: module_context.module_type,
426
442
  type_env: class_type_env,
427
- lvar_env: lvar_env
443
+ lvar_env: lvar_env,
444
+ call_context: TypeInference::MethodCall::ModuleContext.new(type_name: module_context.class_name)
428
445
  )
429
446
 
430
447
  self.class.new(
@@ -509,7 +526,8 @@ module Steep
509
526
  break_context: nil,
510
527
  self_type: module_context.module_type,
511
528
  type_env: type_env,
512
- lvar_env: lvar_env
529
+ lvar_env: lvar_env,
530
+ call_context: TypeInference::MethodCall::ModuleContext.new(type_name: module_context.class_name)
513
531
  )
514
532
 
515
533
  self.class.new(
@@ -608,6 +626,22 @@ module Steep
608
626
  Pair.new(type: type, constr: constr)
609
627
  end
610
628
 
629
+ def add_call(call)
630
+ case call
631
+ when TypeInference::MethodCall::NoMethodError
632
+ typing.add_error(call.error)
633
+ when TypeInference::MethodCall::Error
634
+ call.errors.each do |error|
635
+ typing.add_error(error)
636
+ end
637
+ end
638
+
639
+ typing.add_typing(call.node, call.return_type, nil)
640
+ typing.add_call(call.node, call)
641
+
642
+ Pair.new(type: call.return_type, constr: self)
643
+ end
644
+
611
645
  def synthesize(node, hint: nil)
612
646
  Steep.logger.tagged "synthesize:(#{node.location.expression.to_s.split(/:/, 2).last})" do
613
647
  Steep.logger.debug node.type
@@ -786,28 +820,33 @@ module Steep
786
820
  when :super
787
821
  yield_self do
788
822
  if self_type && method_context&.method
789
- if method_context.super_method
823
+ if super_def = method_context.super_method
790
824
  each_child_node(node) do |child|
791
825
  synthesize(child)
792
826
  end
793
827
 
794
828
  super_method = Interface::Interface::Entry.new(
795
829
  method_types: method_context.super_method.method_types.map {|method_type|
796
- checker.factory.method_type(method_type, self_type: self_type)
830
+ decl = TypeInference::MethodCall::MethodDecl.new(
831
+ method_name: InstanceMethodName.new(type_name: super_def.implemented_in || super_def.defined_in,
832
+ method_name: method_context.name),
833
+ method_def: super_def
834
+ )
835
+ checker.factory.method_type(method_type, self_type: self_type, method_decls: Set[decl])
797
836
  }
798
837
  )
799
838
  args = TypeInference::SendArgs.from_nodes(node.children.dup)
800
839
 
801
- return_type, _ = type_method_call(node,
802
- receiver_type: self_type,
803
- method_name: method_context.name,
804
- method: super_method,
805
- args: args,
806
- block_params: nil,
807
- block_body: nil,
808
- topdown_hint: true)
840
+ call, constr = type_method_call(node,
841
+ receiver_type: self_type,
842
+ method_name: method_context.name,
843
+ method: super_method,
844
+ args: args,
845
+ block_params: nil,
846
+ block_body: nil,
847
+ topdown_hint: true)
809
848
 
810
- add_typing node, type: return_type
849
+ constr.add_call(call)
811
850
  else
812
851
  fallback_to_any node do
813
852
  Errors::UnexpectedSuper.new(node: node, method: method_context.name)
@@ -973,22 +1012,30 @@ module Steep
973
1012
  value = node.children[0]
974
1013
 
975
1014
  if break_context
976
- case
977
- when value && break_context.break_type
978
- check(value, break_context.break_type) do |break_type, actual_type, result|
979
- typing.add_error Errors::BreakTypeMismatch.new(node: node,
980
- expected: break_type,
981
- actual: actual_type,
982
- result: result)
1015
+ if break_type = break_context.break_type
1016
+ if value
1017
+ check(value, break_type) do |break_type, actual_type, result|
1018
+ typing.add_error Errors::BreakTypeMismatch.new(node: node,
1019
+ expected: break_type,
1020
+ actual: actual_type,
1021
+ result: result)
1022
+ end
1023
+ else
1024
+ check_relation(sub_type: AST::Builtin.nil_type, super_type: break_type).else do |result|
1025
+ typing.add_error Errors::BreakTypeMismatch.new(node: node,
1026
+ expected: break_type,
1027
+ actual: AST::Builtin.nil_type,
1028
+ result: result)
1029
+ end
983
1030
  end
984
- when !value
985
- # ok
986
1031
  else
987
- synthesize(value) if value
988
- typing.add_error Errors::UnexpectedJumpValue.new(node: node)
1032
+ if value
1033
+ synthesize(value)
1034
+ typing.add_error Errors::UnexpectedJumpValue.new(node: node)
1035
+ end
989
1036
  end
990
1037
  else
991
- synthesize(value)
1038
+ synthesize(value) if value
992
1039
  typing.add_error Errors::UnexpectedJump.new(node: node)
993
1040
  end
994
1041
 
@@ -998,22 +1045,32 @@ module Steep
998
1045
  value = node.children[0]
999
1046
 
1000
1047
  if break_context
1001
- case
1002
- when value && break_context.next_type
1003
- check(value, break_context.next_type) do |break_type, actual_type, result|
1004
- typing.add_error Errors::BreakTypeMismatch.new(node: node,
1005
- expected: break_type,
1006
- actual: actual_type,
1007
- result: result)
1048
+ if next_type = break_context.next_type
1049
+ next_type = deep_expand_alias(next_type)
1050
+
1051
+ if value
1052
+ _, constr = check(value, next_type) do |break_type, actual_type, result|
1053
+ typing.add_error Errors::BreakTypeMismatch.new(node: node,
1054
+ expected: break_type,
1055
+ actual: actual_type,
1056
+ result: result)
1057
+ end
1058
+ else
1059
+ check_relation(sub_type: AST::Builtin.nil_type, super_type: next_type).else do |result|
1060
+ typing.add_error Errors::BreakTypeMismatch.new(node: node,
1061
+ expected: next_type,
1062
+ actual: AST::Builtin.nil_type,
1063
+ result: result)
1064
+ end
1008
1065
  end
1009
- when !value
1010
- # ok
1011
1066
  else
1012
- synthesize(value) if value
1013
- typing.add_error Errors::UnexpectedJumpValue.new(node: node)
1067
+ if value
1068
+ synthesize(value)
1069
+ typing.add_error Errors::UnexpectedJumpValue.new(node: node)
1070
+ end
1014
1071
  end
1015
1072
  else
1016
- synthesize(value)
1073
+ synthesize(value) if value
1017
1074
  typing.add_error Errors::UnexpectedJump.new(node: node)
1018
1075
  end
1019
1076
 
@@ -1208,10 +1265,35 @@ module Steep
1208
1265
 
1209
1266
  when :class
1210
1267
  yield_self do
1211
- for_class(node).tap do |constructor|
1268
+ constr = self
1269
+
1270
+ name, sup, _ = node.children
1271
+ if name.type == :const
1272
+ # skip the last constant reference
1273
+ if const_parent = name.children[0]
1274
+ _, constr = constr.synthesize(const_parent)
1275
+ end
1276
+ else
1277
+ _, constr = constr.synthesize(name)
1278
+ end
1279
+ _, constr = constr.synthesize(sup) if sup
1280
+
1281
+ constr.for_class(node).tap do |constructor|
1282
+ if module_type = constructor.module_context&.module_type
1283
+ _, constructor = constructor.add_typing(name, type: module_type)
1284
+ else
1285
+ _, constructor = constructor.fallback_to_any(name)
1286
+ end
1287
+
1288
+ constructor.typing.source_index.add_definition(
1289
+ constant: constructor.module_context.class_name,
1290
+ definition: node
1291
+ )
1292
+
1212
1293
  constructor.typing.add_context_for_node(node, context: constructor.context)
1213
1294
  constructor.typing.add_context_for_body(node, context: constructor.context)
1214
1295
 
1296
+ constructor.synthesize(node.children[1]) if node.children[1]
1215
1297
  constructor.synthesize(node.children[2]) if node.children[2]
1216
1298
 
1217
1299
  if constructor.module_context&.implement_name && !namespace_module?(node)
@@ -1224,7 +1306,17 @@ module Steep
1224
1306
 
1225
1307
  when :module
1226
1308
  yield_self do
1309
+ constr = self
1310
+
1311
+ name, _ = node.children
1312
+ _, constr = constr.synthesize(name)
1313
+
1227
1314
  for_module(node).yield_self do |constructor|
1315
+ constructor.typing.source_index.add_definition(
1316
+ constant: constructor.module_context.class_name,
1317
+ definition: node
1318
+ )
1319
+
1228
1320
  constructor.typing.add_context_for_node(node, context: constructor.context)
1229
1321
  constructor.typing.add_context_for_body(node, context: constructor.context)
1230
1322
 
@@ -1271,24 +1363,47 @@ module Steep
1271
1363
  when :self
1272
1364
  add_typing node, type: AST::Types::Self.new
1273
1365
 
1366
+ when :cbase
1367
+ add_typing node, type: AST::Types::Void.new
1368
+
1274
1369
  when :const
1275
- const_name = module_name_from_node(node)
1370
+ parent = node.children[0]
1371
+ if parent
1372
+ _, constr = synthesize(parent)
1373
+ else
1374
+ constr = self
1375
+ end
1376
+
1377
+ const_name = constr.module_name_from_node(node)
1276
1378
 
1277
1379
  if const_name
1380
+ if constant = module_context.const_env.lookup_constant(const_name)
1381
+ typing.source_index.add_reference(constant: constant.name, ref: node)
1382
+ end
1383
+
1278
1384
  type = type_env.get(const: const_name) do
1279
- fallback_to_any node
1385
+ constr.fallback_to_any(node)
1280
1386
  end
1281
- add_typing node, type: type
1387
+ constr.add_typing(node, type: type)
1282
1388
  else
1283
- fallback_to_any node
1389
+ constr.fallback_to_any(node)
1284
1390
  end
1285
1391
 
1286
1392
  when :casgn
1287
1393
  yield_self do
1288
- const_name = module_name_from_node(node)
1394
+ constr = self
1395
+
1396
+ parent = node.children[0]
1397
+ _, constr = constr.synthesize(parent) if parent
1398
+ const_name = constr.module_name_from_node(node)
1399
+
1289
1400
  if const_name
1401
+ if constant = module_context.const_env.lookup_constant(const_name)
1402
+ typing.source_index.add_definition(constant: constant.name, definition: node)
1403
+ end
1404
+
1290
1405
  const_type = type_env.get(const: const_name) {}
1291
- value_type = synthesize(node.children.last, hint: const_type).type
1406
+ value_type, constr = constr.synthesize(node.children.last, hint: const_type)
1292
1407
  type = type_env.assign(const: const_name, type: value_type, self_type: self_type) do |error|
1293
1408
  case error
1294
1409
  when Subtyping::Result::Failure
@@ -1302,10 +1417,10 @@ module Steep
1302
1417
  end
1303
1418
  end
1304
1419
 
1305
- add_typing(node, type: type)
1420
+ constr.add_typing(node, type: type)
1306
1421
  else
1307
- synthesize(node.children.last).type
1308
- fallback_to_any(node)
1422
+ _, constr = constr.synthesize(node.children.last)
1423
+ constr.fallback_to_any(node)
1309
1424
  end
1310
1425
  end
1311
1426
 
@@ -1338,7 +1453,7 @@ module Steep
1338
1453
  if method_context&.method
1339
1454
  if method_context.super_method
1340
1455
  types = method_context.super_method.method_types.map {|method_type|
1341
- checker.factory.method_type(method_type, self_type: self_type).return_type
1456
+ checker.factory.method_type(method_type, self_type: self_type, method_decls: Set[]).type.return_type
1342
1457
  }
1343
1458
  add_typing(node, type: union_type(*types))
1344
1459
  else
@@ -1410,7 +1525,18 @@ module Steep
1410
1525
  .for_branch(right)
1411
1526
  .synthesize(right)
1412
1527
 
1413
- type = if left_type.is_a?(AST::Types::Boolean)
1528
+ truthy_env, _ = interpreter.eval(env: truthy_env, type: right_type, node: right)
1529
+
1530
+ env = if right_type.is_a?(AST::Types::Bot)
1531
+ falsey_env
1532
+ else
1533
+ context.lvar_env.join(falsey_env, constr.context.lvar_env)
1534
+ end
1535
+
1536
+ type = case
1537
+ when left_type.is_a?(AST::Types::Logic::Base) && right_type.is_a?(AST::Types::Logic::Base)
1538
+ AST::Types::Logic::Env.new(truthy: truthy_env, falsy: env)
1539
+ when check_relation(sub_type: left_type, super_type: AST::Types::Boolean.new).success?
1414
1540
  union_type(left_type, right_type)
1415
1541
  else
1416
1542
  union_type(right_type, AST::Builtin.nil_type)
@@ -1418,13 +1544,7 @@ module Steep
1418
1544
 
1419
1545
  add_typing(node,
1420
1546
  type: type,
1421
- constr: constr.update_lvar_env do
1422
- if right_type.is_a?(AST::Types::Bot)
1423
- falsey_env
1424
- else
1425
- context.lvar_env.join(falsey_env, constr.context.lvar_env)
1426
- end
1427
- end)
1547
+ constr: constr.update_lvar_env { env })
1428
1548
  end
1429
1549
 
1430
1550
  when :or
@@ -1436,24 +1556,31 @@ module Steep
1436
1556
  interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: typing)
1437
1557
  truthy_env, falsey_env = interpreter.eval(env: constr.context.lvar_env, type: left_type, node: left)
1438
1558
 
1439
- left_type_t, _ = checker.factory.unwrap_optional(left_type)
1559
+ left_type, _ = checker.factory.unwrap_optional(left_type)
1440
1560
  right_type, constr = constr
1441
1561
  .update_lvar_env { falsey_env }
1442
1562
  .tap {|constr| typing.add_context_for_node(right, context: constr.context) }
1443
1563
  .for_branch(right)
1444
- .synthesize(right, hint: left_type_t)
1564
+ .synthesize(right, hint: left_type)
1565
+
1566
+ _, falsey_env = interpreter.eval(env: falsey_env, type: right_type, node: right)
1567
+
1568
+ env = if right_type.is_a?(AST::Types::Bot)
1569
+ truthy_env
1570
+ else
1571
+ context.lvar_env.join(truthy_env, constr.context.lvar_env)
1572
+ end
1445
1573
 
1446
- type = union_type(left_type_t, right_type)
1574
+ type = case
1575
+ when left_type.is_a?(AST::Types::Logic::Base) && right_type.is_a?(AST::Types::Logic::Base)
1576
+ AST::Types::Logic::Env.new(truthy: env, falsy: falsey_env)
1577
+ else
1578
+ union_type(left_type, right_type)
1579
+ end
1447
1580
 
1448
1581
  add_typing(node,
1449
1582
  type: type,
1450
- constr: constr.update_lvar_env do
1451
- if right_type.is_a?(AST::Types::Bot)
1452
- truthy_env
1453
- else
1454
- context.lvar_env.join(truthy_env, constr.context.lvar_env)
1455
- end
1456
- end)
1583
+ constr: constr.update_lvar_env { env })
1457
1584
  end
1458
1585
 
1459
1586
  when :if
@@ -1518,6 +1645,18 @@ module Steep
1518
1645
 
1519
1646
  cond_type, constr = constr.synthesize(cond)
1520
1647
  _, cond_vars = interpreter.decompose_value(cond)
1648
+ unless cond_vars.empty?
1649
+ first_var = cond_vars.to_a[0]
1650
+ var_node = cond.updated(
1651
+ :lvar,
1652
+ [
1653
+ ASTUtils::Labeling::LabeledName.new(name: first_var, label: 0)
1654
+ ]
1655
+ )
1656
+ else
1657
+ first_var = nil
1658
+ var_node = cond
1659
+ end
1521
1660
 
1522
1661
  when_constr = constr
1523
1662
  whens.each do |clause|
@@ -1527,9 +1666,15 @@ module Steep
1527
1666
  test_envs = []
1528
1667
 
1529
1668
  tests.each do |test|
1530
- test_node = test.updated(:send, [test, :===, cond.dup])
1669
+ test_node = test.updated(:send, [test, :===, var_node])
1531
1670
  test_type, test_constr = test_constr.synthesize(test_node)
1532
1671
  truthy_env, falsy_env = interpreter.eval(type: test_type, node: test_node, env: test_constr.context.lvar_env)
1672
+ truthy_env = cond_vars.inject(truthy_env) do |env, var|
1673
+ env.assign!(var, node: test_node, type: env[first_var])
1674
+ end
1675
+ falsy_env = cond_vars.inject(falsy_env) do |env, var|
1676
+ env.assign!(var, node: test_node, type: env[first_var])
1677
+ end
1533
1678
  test_envs << truthy_env
1534
1679
  test_constr = test_constr.update_lvar_env { falsy_env }
1535
1680
  end
@@ -1559,10 +1704,6 @@ module Steep
1559
1704
  types = branch_pairs.map(&:type)
1560
1705
  constrs = branch_pairs.map(&:constr)
1561
1706
 
1562
- unless els
1563
- constrs << when_constr
1564
- end
1565
-
1566
1707
  if when_constr.context.lvar_env[cond_vars.first].is_a?(AST::Types::Bot)
1567
1708
  # Exhaustive
1568
1709
  if els
@@ -1570,6 +1711,7 @@ module Steep
1570
1711
  end
1571
1712
  else
1572
1713
  unless els
1714
+ constrs << when_constr
1573
1715
  types << AST::Builtin.nil_type
1574
1716
  end
1575
1717
  end
@@ -1929,17 +2071,25 @@ module Steep
1929
2071
  if hint.is_a?(AST::Types::Proc) && value.type == :sym
1930
2072
  if hint.one_arg?
1931
2073
  # Assumes Symbol#to_proc implementation
1932
- param_type = hint.params.required[0]
2074
+ param_type = hint.type.params.required[0]
1933
2075
  interface = checker.factory.interface(param_type, private: true)
1934
2076
  method = interface.methods[value.children[0]]
1935
2077
  if method
1936
2078
  return_types = method.method_types.select {|method_type|
1937
- method_type.params.each_type.count == 0
1938
- }.map(&:return_type)
2079
+ method_type.type.params.empty?
2080
+ }.map {|method_type|
2081
+ method_type.type.return_type
2082
+ }
1939
2083
 
1940
2084
  unless return_types.empty?
1941
- type = AST::Types::Proc.new(params: Interface::Params.empty.update(required: [param_type]),
1942
- return_type: AST::Types::Union.build(types: return_types))
2085
+ type = AST::Types::Proc.new(
2086
+ type: Interface::Function.new(
2087
+ params: Interface::Function::Params.empty.update(required: [param_type]),
2088
+ return_type: AST::Types::Union.build(types: return_types),
2089
+ location: nil
2090
+ ),
2091
+ block: nil
2092
+ )
1943
2093
  end
1944
2094
  end
1945
2095
  else
@@ -2029,7 +2179,7 @@ module Steep
2029
2179
  unless pair.is_a?(Pair) && !pair.type.is_a?(Pair)
2030
2180
  # Steep.logger.error { "result = #{pair.inspect}" }
2031
2181
  # Steep.logger.error { "node = #{node.type}" }
2032
- raise "#synthesize should return an instance of Pair: #{pair.class}"
2182
+ raise "#synthesize should return an instance of Pair: #{pair.class}, node=#{node.inspect}"
2033
2183
  end
2034
2184
  end
2035
2185
  end
@@ -2269,181 +2419,244 @@ module Steep
2269
2419
 
2270
2420
  case type_hint
2271
2421
  when AST::Types::Proc
2272
- params_hint = type_hint.params
2273
- return_hint = type_hint.return_type
2422
+ params_hint = type_hint.type.params
2423
+ return_hint = type_hint.type.return_type
2274
2424
  end
2275
2425
 
2276
- block_pair = type_block(node: node,
2277
- block_param_hint: params_hint,
2278
- block_type_hint: return_hint,
2279
- node_type_hint: nil,
2280
- block_params: params,
2281
- block_body: block_body,
2282
- block_annotations: block_annotations,
2283
- topdown_hint: true)
2426
+ block_constr = for_block(
2427
+ block_params: params,
2428
+ block_param_hint: params_hint,
2429
+ block_type_hint: return_hint,
2430
+ block_annotations: block_annotations,
2431
+ node_type_hint: nil
2432
+ )
2284
2433
 
2285
- add_typing node, type: block_pair.type
2286
- end
2434
+ block_constr.typing.add_context_for_body(node, context: block_constr.context)
2287
2435
 
2288
- def type_send(node, send_node:, block_params:, block_body:, unwrap: false)
2289
- receiver, method_name, *arguments = send_node.children
2290
- receiver_type, constr = receiver ? synthesize(receiver) : [AST::Types::Self.new, self]
2436
+ params.params.each do |param|
2437
+ _, block_constr = block_constr.synthesize(param.node, hint: param.type)
2438
+ end
2291
2439
 
2292
- if unwrap
2293
- receiver_type = unwrap(receiver_type)
2440
+ if block_body
2441
+ return_type = block_constr.synthesize_block(
2442
+ node: node,
2443
+ block_body: block_body,
2444
+ block_type_hint: return_hint
2445
+ )
2446
+
2447
+ if expected_block_type = block_constr.block_context.body_type
2448
+ check_relation(sub_type: return_type, super_type: expected_block_type).else do |result|
2449
+ block_constr.typing.add_error(
2450
+ Errors::BlockBodyTypeMismatch.new(
2451
+ node: block_body,
2452
+ expected: expected_block_type,
2453
+ actual: return_type,
2454
+ result: result
2455
+ )
2456
+ )
2457
+
2458
+ return_type = expected_block_type
2459
+ end
2460
+ end
2461
+ else
2462
+ return_type = AST::Builtin.any_type
2294
2463
  end
2295
2464
 
2296
- receiver_type = expand_alias(receiver_type)
2465
+ block_type = AST::Types::Proc.new(
2466
+ type: Interface::Function.new(
2467
+ params: params_hint || params.params_type,
2468
+ return_type: return_type,
2469
+ location: nil
2470
+ ),
2471
+ block: nil
2472
+ )
2297
2473
 
2298
- type, constr = case receiver_type
2299
- when AST::Types::Any
2300
- each_child_node(send_node) do |child|
2301
- unless child.equal?(receiver)
2302
- _, constr = constr.synthesize(child)
2303
- end
2304
- end
2474
+ add_typing node, type: block_type
2475
+ end
2305
2476
 
2306
- add_typing node, type: AST::Builtin.any_type
2477
+ def synthesize_children(node, skips: [])
2478
+ skips = Set.new.compare_by_identity.merge(skips)
2307
2479
 
2308
- when nil
2309
- fallback_to_any node
2480
+ constr = self
2310
2481
 
2311
- when AST::Types::Void, AST::Types::Bot, AST::Types::Top
2312
- fallback_to_any node do
2313
- Errors::NoMethod.new(node: node, method: method_name, type: receiver_type)
2314
- end
2482
+ each_child_node(node) do |child|
2483
+ unless skips.include?(child)
2484
+ _, constr = constr.synthesize(child)
2485
+ end
2486
+ end
2315
2487
 
2316
- else
2317
- case expanded_receiver_type = expand_self(receiver_type)
2318
- when AST::Types::Self
2319
- Steep.logger.debug { "`self` type cannot be resolved to concrete type" }
2320
- fallback_to_any node do
2321
- Errors::NoMethod.new(node: node, method: method_name, type: receiver_type)
2322
- end
2323
- else
2324
- begin
2325
- interface = checker.factory.interface(receiver_type,
2326
- private: !receiver,
2327
- self_type: expanded_receiver_type)
2328
-
2329
- method = interface.methods[method_name]
2330
-
2331
- if method
2332
- args = TypeInference::SendArgs.from_nodes(arguments)
2333
- return_type, constr, _ = constr.type_method_call(node,
2334
- method: method,
2335
- method_name: method_name,
2336
- args: args,
2337
- block_params: block_params,
2338
- block_body: block_body,
2339
- receiver_type: receiver_type,
2340
- topdown_hint: true)
2341
-
2342
- add_typing node, type: return_type, constr: constr
2343
- else
2344
- fallback_to_any node do
2345
- Errors::NoMethod.new(node: node, method: method_name, type: expanded_receiver_type)
2346
- end
2347
- end
2348
- rescue => exn
2349
- case exn
2350
- when RBS::NoTypeFoundError, RBS::NoMixinFoundError, RBS::NoSuperclassFoundError, RBS::InvalidTypeApplicationError
2351
- # ignore known RBS errors.
2352
- else
2353
- Steep.log_error(exn, message: "Unexpected error in #type_send: #{exn.message} (#{exn.class})")
2354
- end
2488
+ constr
2489
+ end
2355
2490
 
2356
- fallback_to_any node do
2357
- Errors::NoMethod.new(node: node, method: method_name, type: expanded_receiver_type)
2358
- end
2359
- end
2360
- end
2361
- end
2491
+ def type_send_interface(node, interface:, receiver:, receiver_type:, method_name:, arguments:, block_params:, block_body:)
2492
+ method = interface.methods[method_name]
2362
2493
 
2363
- case type
2364
- when nil, Errors::Base
2365
- arguments.each do |arg|
2366
- unless typing.has_type?(arg)
2367
- if arg.type == :splat
2368
- type, constr = constr.synthesize(arg.children[0])
2369
- add_typing(arg, type: AST::Builtin::Array.instance_type(type))
2370
- else
2371
- _, constr = constr.synthesize(arg)
2494
+ if method
2495
+ args = TypeInference::SendArgs.from_nodes(arguments)
2496
+ call, constr = type_method_call(node,
2497
+ method: method,
2498
+ method_name: method_name,
2499
+ args: args,
2500
+ block_params: block_params,
2501
+ block_body: block_body,
2502
+ receiver_type: receiver_type,
2503
+ topdown_hint: true)
2504
+
2505
+ if call && constr
2506
+ case method_name.to_s
2507
+ when "[]=", /\w=\Z/
2508
+ if typing.has_type?(arguments.last)
2509
+ call = call.with_return_type(typing.type_of(node: arguments.last))
2372
2510
  end
2373
2511
  end
2374
- end
2375
-
2376
- if block_body && block_params
2377
- unless typing.has_type?(block_body)
2378
- block_annotations = source.annotations(block: node, builder: checker.builder, current_module: current_namespace)
2379
- params = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
2380
- pairs = params.each.map {|param| [param, AST::Builtin.any_type]}
2512
+ else
2513
+ error = Errors::UnresolvedOverloading.new(
2514
+ node: node,
2515
+ receiver_type: receiver_type,
2516
+ method_name: method_name,
2517
+ method_types: method.method_types
2518
+ )
2519
+ call = TypeInference::MethodCall::Error.new(
2520
+ node: node,
2521
+ context: context.method_context,
2522
+ method_name: method_name,
2523
+ receiver_type: receiver_type,
2524
+ errors: [error]
2525
+ )
2381
2526
 
2382
- for_block, _ = constr.for_block(block_annotations: block_annotations,
2383
- param_pairs: pairs,
2384
- method_return_type: AST::Builtin.any_type,
2385
- typing: typing)
2527
+ skips = [receiver]
2528
+ skips << node.children[0] if node.type == :block
2386
2529
 
2387
- for_block.typing.add_context_for_body(node, context: for_block.context)
2530
+ constr = synthesize_children(node, skips: skips)
2531
+ if block_params
2532
+ block_annotations = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
2388
2533
 
2389
- for_block.synthesize(block_body)
2534
+ constr.type_block_without_hint(
2535
+ node: node,
2536
+ block_params: TypeInference::BlockParams.from_node(block_params, annotations: block_annotations),
2537
+ block_annotations: block_annotations,
2538
+ block_body: block_body
2539
+ )
2390
2540
  end
2391
2541
  end
2542
+
2543
+ constr.add_call(call)
2392
2544
  else
2393
- Pair.new(type: type, constr: constr)
2545
+ add_call(
2546
+ TypeInference::MethodCall::NoMethodError.new(
2547
+ node: node,
2548
+ context: context.method_context,
2549
+ method_name: method_name,
2550
+ receiver_type: receiver_type,
2551
+ error: Errors::NoMethod.new(node: node, method: method_name, type: receiver_type)
2552
+ )
2553
+ )
2394
2554
  end
2395
2555
  end
2396
2556
 
2397
- def for_block(block_annotations:, param_pairs:, method_return_type:, typing:)
2398
- block_type_env = type_env.dup.yield_self do |env|
2399
- param_pairs.each do |param, type|
2400
- if param.type
2401
- env.set(lvar: param.var.name, type: param.type)
2402
- else
2403
- env.set(lvar: param.var.name, type: type)
2404
- end
2405
- end
2557
+ def type_send(node, send_node:, block_params:, block_body:, unwrap: false)
2558
+ receiver, method_name, *arguments = send_node.children
2559
+ recv_type, constr = receiver ? synthesize(receiver) : [AST::Types::Self.new, self]
2406
2560
 
2407
- env.with_annotations(
2408
- lvar_types: block_annotations.lvar_types,
2409
- ivar_types: block_annotations.ivar_types,
2410
- const_types: block_annotations.const_types,
2411
- )
2561
+ if unwrap
2562
+ recv_type = unwrap(recv_type)
2412
2563
  end
2413
2564
 
2414
- lvar_env = context.lvar_env.pin_assignments.annotate(block_annotations)
2565
+ receiver_type = checker.factory.deep_expand_alias(recv_type)
2415
2566
 
2416
- return_type = if block_annotations.break_type
2417
- union_type(method_return_type, block_annotations.break_type)
2418
- else
2419
- method_return_type
2420
- end
2421
- Steep.logger.debug("return_type = #{return_type}")
2567
+ type, constr = case receiver_type
2568
+ when nil
2569
+ raise
2422
2570
 
2423
- block_context = TypeInference::Context::BlockContext.new(body_type: block_annotations.block_type)
2424
- Steep.logger.debug("block_context { body_type: #{block_context.body_type} }")
2571
+ when AST::Types::Any
2572
+ constr = constr.synthesize_children(node, skips: [receiver])
2573
+ constr.add_call(
2574
+ TypeInference::MethodCall::Untyped.new(
2575
+ node: node,
2576
+ context: context.method_context,
2577
+ method_name: method_name
2578
+ )
2579
+ )
2425
2580
 
2426
- break_context = TypeInference::Context::BreakContext.new(
2427
- break_type: block_annotations.break_type || method_return_type,
2428
- next_type: block_annotations.block_type
2429
- )
2430
- Steep.logger.debug("break_context { type: #{break_context.break_type} }")
2581
+ when AST::Types::Void, AST::Types::Bot, AST::Types::Top, AST::Types::Var
2582
+ constr = constr.synthesize_children(node, skips: [receiver])
2583
+ constr.add_call(
2584
+ TypeInference::MethodCall::NoMethodError.new(
2585
+ node: node,
2586
+ context: context.method_context,
2587
+ method_name: method_name,
2588
+ receiver_type: receiver_type,
2589
+ error: Errors::NoMethod.new(node: node, method: method_name, type: receiver_type)
2590
+ )
2591
+ )
2431
2592
 
2432
- [self.class.new(
2433
- checker: checker,
2434
- source: source,
2435
- annotations: annotations.merge_block_annotations(block_annotations),
2436
- typing: typing,
2437
- context: TypeInference::Context.new(
2438
- block_context: block_context,
2439
- method_context: method_context,
2440
- module_context: module_context,
2441
- break_context: break_context,
2442
- self_type: block_annotations.self_type || self_type,
2443
- type_env: block_type_env,
2444
- lvar_env: lvar_env
2593
+ when AST::Types::Self
2594
+ expanded_self = expand_self(receiver_type)
2595
+
2596
+ if expanded_self.is_a?(AST::Types::Self)
2597
+ Steep.logger.debug { "`self` type cannot be resolved to concrete type" }
2598
+
2599
+ constr = constr.synthesize_children(node, skips: [receiver])
2600
+ constr.add_call(
2601
+ TypeInference::MethodCall::NoMethodError.new(
2602
+ node: node,
2603
+ context: context.method_context,
2604
+ method_name: method_name,
2605
+ receiver_type: receiver_type,
2606
+ error: Errors::NoMethod.new(node: node, method: method_name, type: receiver_type)
2607
+ )
2608
+ )
2609
+ else
2610
+ interface = checker.factory.interface(expanded_self,
2611
+ private: !receiver,
2612
+ self_type: AST::Types::Self.new)
2613
+
2614
+ constr.type_send_interface(node,
2615
+ interface: interface,
2616
+ receiver: receiver,
2617
+ receiver_type: expanded_self,
2618
+ method_name: method_name,
2619
+ arguments: arguments,
2620
+ block_params: block_params,
2621
+ block_body: block_body)
2622
+ end
2623
+ else
2624
+ interface = checker.factory.interface(receiver_type,
2625
+ private: !receiver,
2626
+ self_type: receiver_type)
2627
+
2628
+ constr.type_send_interface(node,
2629
+ interface: interface,
2630
+ receiver: receiver,
2631
+ receiver_type: receiver_type,
2632
+ method_name: method_name,
2633
+ arguments: arguments,
2634
+ block_params: block_params,
2635
+ block_body: block_body)
2636
+ end
2637
+
2638
+ Pair.new(type: type, constr: constr)
2639
+ rescue => exn
2640
+ case exn
2641
+ when RBS::NoTypeFoundError, RBS::NoMixinFoundError, RBS::NoSuperclassFoundError, RBS::InvalidTypeApplicationError
2642
+ # ignore known RBS errors.
2643
+ else
2644
+ Steep.log_error(exn, message: "Unexpected error in #type_send: #{exn.message} (#{exn.class})")
2645
+ end
2646
+
2647
+ error = Errors::UnexpectedError.new(node: node, error: exn)
2648
+
2649
+ type_any_rec(node)
2650
+
2651
+ add_call(
2652
+ TypeInference::MethodCall::Error.new(
2653
+ node: node,
2654
+ context: context.method_context,
2655
+ method_name: method_name,
2656
+ receiver_type: receiver_type,
2657
+ errors: [error]
2445
2658
  )
2446
- ), return_type]
2659
+ )
2447
2660
  end
2448
2661
 
2449
2662
  def expand_self(type)
@@ -2459,71 +2672,62 @@ module Steep
2459
2672
 
2460
2673
  results = method.method_types.flat_map do |method_type|
2461
2674
  Steep.logger.tagged method_type.to_s do
2462
- zips = args.zips(method_type.params, method_type.block&.type)
2675
+ zips = args.zips(method_type.type.params, method_type.block&.type)
2463
2676
 
2464
2677
  zips.map do |arg_pairs|
2465
2678
  typing.new_child(node_range) do |child_typing|
2466
- ret = self.with_new_typing(child_typing).try_method_type(
2679
+ self.with_new_typing(child_typing).try_method_type(
2467
2680
  node,
2468
2681
  receiver_type: receiver_type,
2682
+ method_name: method_name,
2469
2683
  method_type: method_type,
2470
2684
  args: args,
2471
2685
  arg_pairs: arg_pairs,
2472
2686
  block_params: block_params,
2473
2687
  block_body: block_body,
2474
- child_typing: child_typing,
2475
2688
  topdown_hint: topdown_hint
2476
2689
  )
2477
-
2478
- raise unless ret.is_a?(Array) && ret[1].is_a?(TypeConstruction)
2479
-
2480
- result, constr = ret
2481
-
2482
- [result, constr, method_type]
2483
2690
  end
2484
2691
  end
2485
2692
  end
2486
2693
  end
2487
2694
 
2488
- unless results.empty?
2489
- result, constr, method_type = results.find {|result, _, _| !result.is_a?(Errors::Base) } || results.last
2490
- else
2695
+ case
2696
+ when results.empty?
2491
2697
  method_type = method.method_types.last
2698
+ all_decls = method.method_types.each.with_object(Set[]) do |method_type, set|
2699
+ set.merge(method_type.method_decls)
2700
+ end
2701
+ error = Errors::IncompatibleArguments.new(node: node, receiver_type: receiver_type, method_type: method_type)
2702
+ call = TypeInference::MethodCall::Error.new(
2703
+ node: node,
2704
+ context: context.method_context,
2705
+ method_name: method_name,
2706
+ receiver_type: receiver_type,
2707
+ return_type: method_type.type.return_type,
2708
+ errors: [error],
2709
+ method_decls: all_decls
2710
+ )
2492
2711
  constr = self.with_new_typing(typing.new_child(node_range))
2493
- result = Errors::IncompatibleArguments.new(node: node, receiver_type: receiver_type, method_type: method_type)
2494
- end
2495
- constr.typing.save!
2496
-
2497
- case result
2498
- when Errors::Base
2499
- if method.method_types.size == 1
2500
- typing.add_error result
2501
- type = case method_type.return_type
2502
- when AST::Types::Var
2503
- AST::Builtin.any_type
2504
- else
2505
- method_type.return_type
2506
- end
2712
+ when (call, constr = results.find {|call, _| call.is_a?(TypeInference::MethodCall::Typed) })
2713
+ # Nop
2714
+ else
2715
+ if results.one?
2716
+ call, constr = results[0]
2507
2717
  else
2508
- typing.add_error Errors::UnresolvedOverloading.new(node: node,
2509
- receiver_type: expand_self(receiver_type),
2510
- method_name: method_name,
2511
- method_types: method.method_types)
2512
- type = AST::Builtin.any_type
2718
+ return
2513
2719
  end
2514
-
2515
- [type,
2516
- update_lvar_env { constr.context.lvar_env },
2517
- result]
2518
- else # Type
2519
- [result,
2520
- update_lvar_env { constr.context.lvar_env },
2521
- nil]
2522
2720
  end
2721
+ constr.typing.save!
2722
+
2723
+ [
2724
+ call,
2725
+ update_lvar_env { constr.context.lvar_env }
2726
+ ]
2523
2727
  end
2524
2728
 
2525
2729
  def check_keyword_arg(receiver_type:, node:, method_type:, constraints:)
2526
- params = method_type.params
2730
+ params = method_type.type.params
2527
2731
 
2528
2732
  case node.type
2529
2733
  when :hash
@@ -2621,14 +2825,12 @@ module Steep
2621
2825
 
2622
2826
  hash_type = AST::Builtin::Hash.instance_type(
2623
2827
  AST::Builtin::Symbol.instance_type,
2624
- AST::Types::Union.build(types: value_types,
2625
- location: method_type.location)
2828
+ AST::Types::Union.build(types: value_types)
2626
2829
  )
2627
2830
  else
2628
2831
  hash_elements = params.required_keywords.merge(
2629
- method_type.params.optional_keywords.transform_values do |type|
2630
- AST::Types::Union.build(types: [type, AST::Builtin.nil_type],
2631
- location: method_type.location)
2832
+ params.optional_keywords.transform_values do |type|
2833
+ AST::Types::Union.build(types: [type, AST::Builtin.nil_type])
2632
2834
  end
2633
2835
  )
2634
2836
 
@@ -2650,226 +2852,311 @@ module Steep
2650
2852
  nil
2651
2853
  end
2652
2854
 
2653
- def try_method_type(node, receiver_type:, method_type:, args:, arg_pairs:, block_params:, block_body:, child_typing:, topdown_hint:)
2855
+ def try_method_type(node, receiver_type:, method_name:, method_type:, args:, arg_pairs:, block_params:, block_body:, topdown_hint:)
2654
2856
  fresh_types = method_type.type_params.map {|x| AST::Types::Var.fresh(x)}
2655
2857
  fresh_vars = Set.new(fresh_types.map(&:name))
2656
2858
  instantiation = Interface::Substitution.build(method_type.type_params, fresh_types)
2657
2859
 
2658
- construction = self.class.new(
2659
- checker: checker,
2660
- source: source,
2661
- annotations: annotations,
2662
- typing: child_typing,
2663
- context: context
2664
- )
2860
+ constr = self
2665
2861
 
2666
- constr = construction
2862
+ method_type = method_type.instantiate(instantiation)
2667
2863
 
2668
- method_type.instantiate(instantiation).yield_self do |method_type|
2669
- constraints = Subtyping::Constraints.new(unknowns: fresh_types.map(&:name))
2670
- variance = Subtyping::VariableVariance.from_method_type(method_type)
2671
- occurence = Subtyping::VariableOccurence.from_method_type(method_type)
2864
+ constraints = Subtyping::Constraints.new(unknowns: fresh_types.map(&:name))
2865
+ variance = Subtyping::VariableVariance.from_method_type(method_type)
2866
+ occurence = Subtyping::VariableOccurence.from_method_type(method_type)
2672
2867
 
2673
- arg_pairs.each do |pair|
2674
- case pair
2675
- when Array
2676
- (arg_node, param_type) = pair
2677
- param_type = param_type.subst(instantiation)
2868
+ errors = []
2678
2869
 
2679
- arg_type, constr = if arg_node.type == :splat
2680
- constr.synthesize(arg_node.children[0])
2681
- else
2682
- constr.synthesize(arg_node, hint: topdown_hint ? param_type : nil)
2683
- end
2870
+ arg_pairs.each do |pair|
2871
+ case pair
2872
+ when Array
2873
+ arg_node, param_type = pair
2874
+ param_type = param_type.subst(instantiation)
2684
2875
 
2685
- check_relation(sub_type: arg_type, super_type: param_type, constraints: constraints).else do |result|
2686
- return [Errors::ArgumentTypeMismatch.new(node: arg_node,
2876
+ arg_type, constr = if arg_node.type == :splat
2877
+ constr.synthesize(arg_node.children[0])
2878
+ else
2879
+ constr.synthesize(arg_node, hint: topdown_hint ? param_type : nil)
2880
+ end
2881
+
2882
+ check_relation(sub_type: arg_type, super_type: param_type, constraints: constraints).else do
2883
+ errors << Errors::ArgumentTypeMismatch.new(node: arg_node,
2687
2884
  receiver_type: receiver_type,
2688
2885
  expected: param_type,
2689
- actual: arg_type),
2690
- constr]
2691
- end
2692
- else
2693
- # keyword
2694
- result = check_keyword_arg(receiver_type: receiver_type,
2695
- node: pair,
2696
- method_type: method_type,
2697
- constraints: constraints)
2886
+ actual: arg_type)
2887
+ end
2888
+ else
2889
+ # keyword
2890
+ result = constr.check_keyword_arg(receiver_type: receiver_type,
2891
+ node: pair,
2892
+ method_type: method_type,
2893
+ constraints: constraints)
2698
2894
 
2699
- if result.is_a?(Errors::Base)
2700
- return [result, constr]
2701
- end
2895
+ if result.is_a?(Errors::Base)
2896
+ errors << result
2702
2897
  end
2703
2898
  end
2899
+ end
2704
2900
 
2705
- if block_params && method_type.block
2706
- block_annotations = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
2707
- block_params_ = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
2708
-
2709
- unless block_params_
2710
- return [
2711
- Errors::UnsupportedSyntax.new(
2712
- node: block_params,
2713
- message: "Unsupported block params pattern, probably masgn?"
2714
- ),
2715
- constr
2716
- ]
2717
- end
2718
-
2719
- pairs = block_params_.zip(method_type.block.type.params)
2720
-
2721
- unless pairs
2722
- return [
2723
- Errors::IncompatibleBlockParameters.new(node: node, method_type: method_type),
2724
- constr
2725
- ]
2726
- end
2727
-
2728
- pairs.each do |param, type|
2729
- if param.type
2730
- check_relation(sub_type: type, super_type: param.type, constraints: constraints).else do |result|
2731
- return [
2732
- Errors::IncompatibleAssignment.new(
2733
- node: param.node,
2734
- lhs_type: param.type,
2735
- rhs_type: type,
2736
- result: result
2737
- ),
2738
- constr
2739
- ]
2901
+ if block_params
2902
+ # block is given
2903
+ block_annotations = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
2904
+ block_params_ = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
2905
+
2906
+ if method_type.block
2907
+ pairs = method_type.block && block_params_&.zip(method_type.block.type.params)
2908
+
2909
+ if pairs
2910
+ begin
2911
+ block_constr = constr.for_block(
2912
+ block_params: block_params_,
2913
+ block_param_hint: method_type.block.type.params,
2914
+ block_type_hint: method_type.block.type.return_type,
2915
+ block_annotations: block_annotations,
2916
+ node_type_hint: method_type.type.return_type
2917
+ )
2918
+ block_constr = block_constr.with_new_typing(
2919
+ block_constr.typing.new_child(
2920
+ range: block_constr.typing.block_range(node)
2921
+ )
2922
+ )
2923
+
2924
+ block_constr.typing.add_context_for_body(node, context: block_constr.context)
2925
+
2926
+ pairs.each do |param, type|
2927
+ _, block_constr = block_constr.synthesize(param.node, hint: param.type || type)
2928
+
2929
+ if param.type
2930
+ check_relation(sub_type: type, super_type: param.type, constraints: constraints).else do |result|
2931
+ error = Errors::IncompatibleAssignment.new(
2932
+ node: param.node,
2933
+ lhs_type: param.type,
2934
+ rhs_type: type,
2935
+ result: result
2936
+ )
2937
+ errors << error
2938
+ end
2939
+ end
2740
2940
  end
2741
- end
2742
- end
2743
- end
2744
2941
 
2745
- case
2746
- when method_type.block && block_params
2747
- Steep.logger.debug "block is okay: method_type=#{method_type}"
2748
- Steep.logger.debug "Constraints = #{constraints}"
2749
-
2750
- begin
2751
- method_type.subst(constraints.solution(checker, self_type: self_type, variance: variance, variables: occurence.params)).yield_self do |method_type|
2752
- type, _ = constr.type_block(node: node,
2753
- block_param_hint: method_type.block.type.params,
2754
- block_type_hint: method_type.block.type.return_type,
2755
- node_type_hint: method_type.return_type,
2756
- block_params: block_params_,
2757
- block_body: block_body,
2758
- block_annotations: block_annotations,
2759
- topdown_hint: topdown_hint)
2760
-
2761
- result = check_relation(sub_type: type.return_type,
2942
+ s = constraints.solution(
2943
+ checker,
2944
+ self_type: self_type,
2945
+ variance: variance,
2946
+ variables: method_type.type.params.free_variables + method_type.block.type.params.free_variables
2947
+ )
2948
+ method_type = method_type.subst(s)
2949
+ block_constr = block_constr.update_lvar_env {|env| env.subst(s) }
2950
+ if block_body
2951
+ block_body_type = block_constr.synthesize_block(
2952
+ node: node,
2953
+ block_body: block_body,
2954
+ block_type_hint: method_type.block.type.return_type
2955
+ )
2956
+ else
2957
+ block_body_type = AST::Builtin.nil_type
2958
+ end
2959
+
2960
+ result = check_relation(sub_type: block_body_type,
2762
2961
  super_type: method_type.block.type.return_type,
2763
2962
  constraints: constraints)
2764
2963
 
2765
2964
  case result
2766
2965
  when Subtyping::Result::Success
2767
- method_type.return_type.subst(constraints.solution(checker, self_type: self_type, variance: variance, variables: fresh_vars)).yield_self do |ret_type|
2768
- ty = if block_annotations.break_type
2769
- AST::Types::Union.new(types: [block_annotations.break_type, ret_type])
2770
- else
2771
- ret_type
2772
- end
2773
- [ty, constr]
2966
+ s = constraints.solution(checker, self_type: self_type, variance: variance, variables: fresh_vars)
2967
+ method_type = method_type.subst(s)
2968
+
2969
+ return_type = method_type.type.return_type
2970
+ if break_type = block_annotations.break_type
2971
+ return_type = union_type(break_type, return_type)
2774
2972
  end
2775
2973
 
2776
2974
  when Subtyping::Result::Failure
2777
- [Errors::BlockTypeMismatch.new(node: node,
2778
- expected: method_type.block.type,
2779
- actual: type,
2780
- result: result),
2781
- constr]
2975
+ given_block_type = AST::Types::Proc.new(
2976
+ type: Interface::Function.new(
2977
+ params: method_type.block.type.params || block_params.params_type,
2978
+ return_type: block_body_type,
2979
+ location: nil
2980
+ ),
2981
+ block: nil
2982
+ )
2983
+
2984
+ method_block_type = AST::Types::Proc.new(
2985
+ type: Interface::Function.new(
2986
+ params: method_type.block.type.params,
2987
+ return_type: method_type.block.type.return_type,
2988
+ location: nil
2989
+ ),
2990
+ block: nil
2991
+ )
2992
+
2993
+ errors << Errors::BlockTypeMismatch.new(node: node,
2994
+ expected: method_block_type,
2995
+ actual: given_block_type,
2996
+ result: result)
2997
+
2998
+ return_type = method_type.type.return_type
2782
2999
  end
2783
- end
2784
3000
 
2785
- rescue Subtyping::Constraints::UnsatisfiableConstraint => exn
2786
- [Errors::UnsatisfiableConstraint.new(node: node,
2787
- method_type: method_type,
2788
- var: exn.var,
2789
- sub_type: exn.sub_type,
2790
- super_type: exn.super_type,
2791
- result: exn.result),
2792
- constr]
2793
- end
2794
-
2795
- when method_type.block && args.block_pass_arg
2796
- begin
2797
- method_type.subst(constraints.solution(checker, self_type: self_type, variance: variance, variables: occurence.params)).yield_self do |method_type|
2798
- block_type, constr = constr.synthesize(args.block_pass_arg, hint: topdown_hint ? method_type.block.type : nil)
2799
- result = check_relation(
2800
- sub_type: block_type,
2801
- super_type: method_type.block.yield_self {|expected_block|
2802
- if expected_block.optional?
2803
- AST::Builtin.optional(expected_block.type)
2804
- else
2805
- expected_block.type
2806
- end
2807
- },
2808
- constraints: constraints
2809
- )
3001
+ block_constr.typing.save!
2810
3002
 
2811
- case result
2812
- when Subtyping::Result::Success
2813
- [
2814
- method_type.return_type.subst(constraints.solution(checker, self_type: self_type, variance: variance, variables: fresh_vars)),
2815
- constr
2816
- ]
3003
+ rescue Subtyping::Constraints::UnsatisfiableConstraint => exn
3004
+ errors << Errors::UnsatisfiableConstraint.new(
3005
+ node: node,
3006
+ method_type: method_type,
3007
+ var: exn.var,
3008
+ sub_type: exn.sub_type,
3009
+ super_type: exn.super_type,
3010
+ result: exn.result
3011
+ )
2817
3012
 
2818
- when Subtyping::Result::Failure
2819
- [
2820
- Errors::BlockTypeMismatch.new(node: node,
2821
- expected: method_type.block.type,
2822
- actual: block_type,
2823
- result: result),
2824
- constr
2825
- ]
3013
+ constr.type_block_without_hint(node: node, block_annotations: block_annotations, block_params: block_params_, block_body: block_body) do |error|
3014
+ errors << error
2826
3015
  end
3016
+
3017
+ s = Interface::Substitution.build(method_type.free_variables,
3018
+ Array.new(method_type.free_variables.size, AST::Builtin.any_type))
3019
+ method_type = method_type.subst(s)
2827
3020
  end
3021
+ else
3022
+ errors << Errors::UnsupportedSyntax.new(
3023
+ node: block_params,
3024
+ message: "Unsupported block params pattern, probably masgn?"
3025
+ )
2828
3026
 
2829
- rescue Subtyping::Constraints::UnsatisfiableConstraint => exn
2830
- [
2831
- Errors::UnsatisfiableConstraint.new(node: node,
2832
- method_type: method_type,
2833
- var: exn.var,
2834
- sub_type: exn.sub_type,
2835
- super_type: exn.super_type,
2836
- result: exn.result),
2837
- constr
2838
- ]
2839
- end
2840
-
2841
- when (!method_type.block || method_type.block.optional?) && !block_params && !block_body && !args.block_pass_arg
2842
- # OK, without block
2843
- [
2844
- method_type.subst(constraints.solution(checker, variance: variance, variables: fresh_vars, self_type: self_type)).return_type,
2845
- constr
2846
- ]
2847
-
2848
- when !method_type.block && (block_params || args.block_pass_arg)
2849
- [
2850
- Errors::UnexpectedBlockGiven.new(
3027
+ s = constraints.solution(checker, variance: variance, variables: fresh_vars, self_type: self_type)
3028
+ method_type = method_type.subst(s)
3029
+ end
3030
+ else
3031
+ # Block is given but method doesn't accept
3032
+ #
3033
+ constr.type_block_without_hint(node: node, block_annotations: block_annotations, block_params: block_params_, block_body: block_body) do |error|
3034
+ errors << error
3035
+ end
3036
+
3037
+ errors << Errors::UnexpectedBlockGiven.new(
3038
+ node: node,
3039
+ method_type: method_type
3040
+ )
3041
+ end
3042
+ else
3043
+ # block is not given
3044
+ if (!method_type.block || method_type.block.optional?)
3045
+ # Method call without block is allowed
3046
+ unless args.block_pass_arg
3047
+ # OK, without block
3048
+ s = constraints.solution(checker, variance: variance, variables: fresh_vars, self_type: self_type)
3049
+ method_type = method_type.subst(s)
3050
+ else
3051
+ # &block arg is given
3052
+ s = constraints.solution(checker, variance: variance, variables: fresh_vars, self_type: self_type)
3053
+ method_type = method_type.subst(s)
3054
+
3055
+ errors << Errors::UnexpectedBlockGiven.new(
2851
3056
  node: node,
2852
3057
  method_type: method_type
2853
- ),
2854
- constr
2855
- ]
2856
-
2857
- when method_type.block && !method_type.block.optional? && !block_params && !block_body && !args.block_pass_arg
2858
- [
2859
- Errors::RequiredBlockMissing.new(
3058
+ )
3059
+ end
3060
+ else
3061
+ unless args.block_pass_arg
3062
+ # Required block is missing
3063
+ errors << Errors::RequiredBlockMissing.new(
2860
3064
  node: node,
2861
3065
  method_type: method_type
2862
- ),
2863
- constr
2864
- ]
3066
+ )
2865
3067
 
2866
- else
2867
- raise "Unexpected case condition"
3068
+ s = constraints.solution(checker, variance: variance, variables: fresh_vars, self_type: self_type)
3069
+ method_type = method_type.subst(s)
3070
+ else
3071
+ begin
3072
+ method_type = method_type.subst(constraints.solution(checker, self_type: self_type, variance: variance, variables: occurence.params))
3073
+ hint_type = if topdown_hint
3074
+ AST::Types::Proc.new(type: method_type.block.type, block: nil)
3075
+ end
3076
+ given_block_type, constr = constr.synthesize(args.block_pass_arg, hint: hint_type)
3077
+ method_block_type = method_type.block.yield_self {|expected_block|
3078
+ proc_type = AST::Types::Proc.new(type: expected_block.type, block: nil)
3079
+ if expected_block.optional?
3080
+ AST::Builtin.optional(proc_type)
3081
+ else
3082
+ proc_type
3083
+ end
3084
+ }
3085
+
3086
+ result = check_relation(sub_type: given_block_type, super_type: method_block_type, constraints: constraints)
3087
+ result.else do |result|
3088
+ errors << Errors::BlockTypeMismatch.new(node: node,
3089
+ expected: method_block_type,
3090
+ actual: given_block_type,
3091
+ result: result)
3092
+ end
3093
+
3094
+ method_type = method_type.subst(constraints.solution(checker, self_type: self_type, variance: variance, variables: method_type.free_variables))
3095
+ end
3096
+ end
3097
+ end
3098
+ end
3099
+
3100
+ call = if errors.empty?
3101
+ TypeInference::MethodCall::Typed.new(
3102
+ node: node,
3103
+ context: context.method_context,
3104
+ receiver_type: receiver_type,
3105
+ method_name: method_name,
3106
+ actual_method_type: method_type,
3107
+ return_type: return_type || method_type.type.return_type,
3108
+ method_decls: method_type.method_decls
3109
+ )
3110
+ else
3111
+ TypeInference::MethodCall::Error.new(
3112
+ node: node,
3113
+ context: context.method_context,
3114
+ receiver_type: receiver_type,
3115
+ method_name: method_name,
3116
+ return_type: return_type || method_type.type.return_type,
3117
+ method_decls: method_type.method_decls,
3118
+ errors: errors
3119
+ )
3120
+ end
3121
+
3122
+ [
3123
+ call,
3124
+ constr
3125
+ ]
3126
+ end
3127
+
3128
+ def type_block_without_hint(node:, block_annotations:, block_params:, block_body:, &block)
3129
+ block_constr = for_block(
3130
+ block_params: block_params,
3131
+ block_param_hint: nil,
3132
+ block_type_hint: nil,
3133
+ block_annotations: block_annotations,
3134
+ node_type_hint: nil
3135
+ )
3136
+
3137
+ block_constr.typing.add_context_for_body(node, context: block_constr.context)
3138
+
3139
+ block_params.params.each do |param|
3140
+ _, block_constr = block_constr.synthesize(param.node, hint: param.type)
3141
+ end
3142
+
3143
+ block_type = block_constr.synthesize_block(node: node, block_type_hint: nil, block_body: block_body)
3144
+
3145
+ if expected_block_type = block_constr.block_context.body_type
3146
+ block_constr.check_relation(sub_type: block_type, super_type: expected_block_type).else do |result|
3147
+ block_constr.typing.add_error(
3148
+ Errors::BlockBodyTypeMismatch.new(
3149
+ node: node,
3150
+ expected: expected_block_type,
3151
+ actual: block_type,
3152
+ result: result
3153
+ )
3154
+ )
2868
3155
  end
2869
3156
  end
2870
3157
  end
2871
3158
 
2872
- def type_block(node:, block_param_hint:, block_type_hint:, node_type_hint:, block_params:, block_body:, block_annotations:, topdown_hint:)
3159
+ def for_block(block_params:, block_param_hint:, block_type_hint:, block_annotations:, node_type_hint:)
2873
3160
  block_param_pairs = block_param_hint && block_params.zip(block_param_hint)
2874
3161
 
2875
3162
  param_types_hash = {}
@@ -2885,30 +3172,30 @@ module Steep
2885
3172
  end
2886
3173
  end
2887
3174
 
2888
- lvar_env = context.lvar_env.pin_assignments.yield_self do |env|
2889
- decls = param_types_hash.each.with_object({}) do |(name, type), hash|
2890
- hash[name] = TypeInference::LocalVariableTypeEnv::Entry.new(type: type)
2891
- end
2892
- env.except(decls.keys).update(assigned_types: decls)
2893
- end.annotate(block_annotations)
3175
+ decls = param_types_hash.each.with_object({}) do |(name, type), hash|
3176
+ hash[name] = TypeInference::LocalVariableTypeEnv::Entry.new(type: type)
3177
+ end
3178
+ lvar_env = context.lvar_env
3179
+ .pin_assignments
3180
+ .except(decls.keys)
3181
+ .update(assigned_types: decls)
3182
+ .annotate(block_annotations)
2894
3183
 
2895
3184
  break_type = if block_annotations.break_type
2896
3185
  union_type(node_type_hint, block_annotations.break_type)
2897
3186
  else
2898
3187
  node_type_hint
2899
3188
  end
2900
- Steep.logger.debug("return_type = #{break_type}")
2901
-
2902
- block_context = TypeInference::Context::BlockContext.new(body_type: block_annotations.block_type)
2903
- Steep.logger.debug("block_context { body_type: #{block_context.body_type} }")
2904
3189
 
3190
+ block_context = TypeInference::Context::BlockContext.new(
3191
+ body_type: block_annotations.block_type || block_type_hint || AST::Builtin.any_type
3192
+ )
2905
3193
  break_context = TypeInference::Context::BreakContext.new(
2906
3194
  break_type: break_type,
2907
3195
  next_type: block_context.body_type
2908
3196
  )
2909
- Steep.logger.debug("break_context { type: #{break_context.break_type} }")
2910
3197
 
2911
- for_block_body = self.class.new(
3198
+ self.class.new(
2912
3199
  checker: checker,
2913
3200
  source: source,
2914
3201
  annotations: annotations.merge_block_annotations(block_annotations),
@@ -2920,37 +3207,23 @@ module Steep
2920
3207
  break_context: break_context,
2921
3208
  self_type: block_annotations.self_type || self_type,
2922
3209
  type_env: type_env.dup,
2923
- lvar_env: lvar_env
3210
+ lvar_env: lvar_env,
3211
+ call_context: self.context.call_context
2924
3212
  )
2925
3213
  )
3214
+ end
2926
3215
 
2927
- for_block_body.typing.add_context_for_body(node, context: for_block_body.context)
2928
-
3216
+ def synthesize_block(node:, block_type_hint:, block_body:)
2929
3217
  if block_body
2930
- body_pair = if (body_type = block_context.body_type)
2931
- for_block_body.check(block_body, body_type) do |expected, actual, result|
2932
- typing.add_error Errors::BlockTypeMismatch.new(node: block_body,
2933
- expected: expected,
2934
- actual: actual,
2935
- result: result)
2936
-
2937
- end
2938
- else
2939
- for_block_body.synthesize(block_body, hint: topdown_hint ? block_type_hint : nil)
2940
- end
3218
+ body_type, _, context = synthesize(block_body, hint: block_context.body_type || block_type_hint)
2941
3219
 
2942
3220
  range = block_body.loc.expression.end_pos..node.loc.end.begin_pos
2943
- typing.add_context(range, context: body_pair.context)
3221
+ typing.add_context(range, context: context)
3222
+
3223
+ body_type
2944
3224
  else
2945
- body_pair = Pair.new(type: AST::Builtin.nil_type, constr: for_block_body)
3225
+ AST::Builtin.nil_type
2946
3226
  end
2947
-
2948
- body_pair.with(
2949
- type: AST::Types::Proc.new(
2950
- params: block_param_hint || block_params.params_type,
2951
- return_type: body_pair.type
2952
- )
2953
- )
2954
3227
  end
2955
3228
 
2956
3229
  def each_child_node(node)
@@ -3035,7 +3308,7 @@ module Steep
3035
3308
  if module_name.namespace.relative?
3036
3309
  (current_namespace + module_name.namespace).append(module_name.name)
3037
3310
  else
3038
- module_name
3311
+ module_name.to_namespace
3039
3312
  end
3040
3313
  end
3041
3314
 
@@ -3070,8 +3343,10 @@ module Steep
3070
3343
  end
3071
3344
  end
3072
3345
  expected_module_method_names = (module_context.module_definition&.methods || {}).each.with_object(Set[]) do |(name, method), set|
3073
- if method.implemented_in == module_context.module_definition.type_name
3074
- set << name
3346
+ if name != :new
3347
+ if method.implemented_in == module_context.module_definition.type_name
3348
+ set << name
3349
+ end
3075
3350
  end
3076
3351
  end
3077
3352
 
@@ -3172,6 +3447,14 @@ module Steep
3172
3447
  !nodes.empty? && nodes.all? {|child| child.type == :class || child.type == :module}
3173
3448
  end
3174
3449
 
3450
+ def type_any_rec(node)
3451
+ add_typing node, type: AST::Builtin.any_type
3452
+
3453
+ each_child_node(node) do |child|
3454
+ type_any_rec(child)
3455
+ end
3456
+ end
3457
+
3175
3458
  def fallback_any_rec(node)
3176
3459
  fallback_to_any(node) unless typing.has_type?(node)
3177
3460
 
@@ -3324,6 +3607,8 @@ module Steep
3324
3607
  end
3325
3608
 
3326
3609
  def try_hash_type(node, hint)
3610
+ hint = expand_alias(hint)
3611
+
3327
3612
  case hint
3328
3613
  when AST::Types::Record
3329
3614
  typing.new_child(node.loc.expression.yield_self {|l| l.begin_pos..l.end_pos }) do |child_typing|