steep 0.34.0 → 0.39.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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/lib/steep.rb +6 -0
  4. data/lib/steep/ast/types/bot.rb +1 -1
  5. data/lib/steep/ast/types/factory.rb +122 -53
  6. data/lib/steep/ast/types/logic.rb +33 -1
  7. data/lib/steep/ast/types/proc.rb +32 -20
  8. data/lib/steep/ast/types/top.rb +1 -1
  9. data/lib/steep/cli.rb +2 -2
  10. data/lib/steep/drivers/print_project.rb +11 -0
  11. data/lib/steep/drivers/vendor.rb +1 -20
  12. data/lib/steep/errors.rb +67 -38
  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 +32 -812
  19. data/lib/steep/project/dsl.rb +13 -17
  20. data/lib/steep/project/options.rb +4 -4
  21. data/lib/steep/project/target.rb +21 -12
  22. data/lib/steep/server/master.rb +5 -1
  23. data/lib/steep/server/signature_worker.rb +63 -6
  24. data/lib/steep/signature/errors.rb +51 -5
  25. data/lib/steep/signature/validator.rb +28 -4
  26. data/lib/steep/subtyping/check.rb +72 -34
  27. data/lib/steep/subtyping/variable_occurrence.rb +2 -2
  28. data/lib/steep/subtyping/variable_variance.rb +2 -2
  29. data/lib/steep/type_construction.rb +308 -152
  30. data/lib/steep/type_inference/block_params.rb +1 -1
  31. data/lib/steep/type_inference/constant_env.rb +5 -1
  32. data/lib/steep/type_inference/logic_type_interpreter.rb +102 -26
  33. data/lib/steep/typing.rb +8 -2
  34. data/lib/steep/version.rb +1 -1
  35. data/smoke/tsort/Steepfile +6 -0
  36. data/smoke/tsort/a.rb +15 -0
  37. data/smoke/type_case/a.rb +1 -1
  38. data/steep.gemspec +1 -1
  39. metadata +12 -5
@@ -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
 
@@ -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)
@@ -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
  )
@@ -400,6 +399,9 @@ module Steep
400
399
 
401
400
  instance_type = AST::Types::Name::Instance.new(name: class_name, args: class_args)
402
401
  module_type = AST::Types::Name::Singleton.new(name: class_name)
402
+ else
403
+ instance_type = AST::Builtin::Object.instance_type
404
+ module_type = AST::Builtin::Object.module_type
403
405
  end
404
406
 
405
407
  if annots.instance_type
@@ -643,7 +645,7 @@ module Steep
643
645
  Pair.new(type: call.return_type, constr: self)
644
646
  end
645
647
 
646
- def synthesize(node, hint: nil)
648
+ def synthesize(node, hint: nil, condition: false)
647
649
  Steep.logger.tagged "synthesize:(#{node.location.expression.to_s.split(/:/, 2).last})" do
648
650
  Steep.logger.debug node.type
649
651
  case node.type
@@ -880,9 +882,7 @@ module Steep
880
882
  new.typing.add_context_for_node(node, context: new.context)
881
883
  new.typing.add_context_for_body(node, context: new.context)
882
884
 
883
- each_child_node(args_node) do |arg|
884
- _, new = new.synthesize(arg)
885
- end
885
+ new = new.synthesize_children(args_node)
886
886
 
887
887
  body_pair = if body_node
888
888
  return_type = expand_alias(new.method_context&.return_type)
@@ -937,14 +937,17 @@ module Steep
937
937
  checker.factory.definition_builder.build_singleton(name)
938
938
  end
939
939
 
940
+ args_node = node.children[2]
940
941
  new = for_new_method(node.children[1],
941
942
  node,
942
- args: node.children[2].children,
943
+ args: args_node.children,
943
944
  self_type: self_type,
944
945
  definition: definition)
945
946
  new.typing.add_context_for_node(node, context: new.context)
946
947
  new.typing.add_context_for_body(node, context: new.context)
947
948
 
949
+ new = new.synthesize_children(args_node)
950
+
948
951
  each_child_node(node.children[2]) do |arg|
949
952
  new.synthesize(arg)
950
953
  end
@@ -1013,22 +1016,30 @@ module Steep
1013
1016
  value = node.children[0]
1014
1017
 
1015
1018
  if break_context
1016
- case
1017
- when value && break_context.break_type
1018
- check(value, break_context.break_type) do |break_type, actual_type, result|
1019
- typing.add_error Errors::BreakTypeMismatch.new(node: node,
1020
- expected: break_type,
1021
- actual: actual_type,
1022
- result: result)
1019
+ if break_type = break_context.break_type
1020
+ if value
1021
+ check(value, break_type) do |break_type, actual_type, result|
1022
+ typing.add_error Errors::BreakTypeMismatch.new(node: node,
1023
+ expected: break_type,
1024
+ actual: actual_type,
1025
+ result: result)
1026
+ end
1027
+ else
1028
+ check_relation(sub_type: AST::Builtin.nil_type, super_type: break_type).else do |result|
1029
+ typing.add_error Errors::BreakTypeMismatch.new(node: node,
1030
+ expected: break_type,
1031
+ actual: AST::Builtin.nil_type,
1032
+ result: result)
1033
+ end
1023
1034
  end
1024
- when !value
1025
- # ok
1026
1035
  else
1027
- synthesize(value) if value
1028
- typing.add_error Errors::UnexpectedJumpValue.new(node: node)
1036
+ if value
1037
+ synthesize(value)
1038
+ typing.add_error Errors::UnexpectedJumpValue.new(node: node)
1039
+ end
1029
1040
  end
1030
1041
  else
1031
- synthesize(value)
1042
+ synthesize(value) if value
1032
1043
  typing.add_error Errors::UnexpectedJump.new(node: node)
1033
1044
  end
1034
1045
 
@@ -1038,22 +1049,32 @@ module Steep
1038
1049
  value = node.children[0]
1039
1050
 
1040
1051
  if break_context
1041
- case
1042
- when value && break_context.next_type
1043
- check(value, break_context.next_type) do |break_type, actual_type, result|
1044
- typing.add_error Errors::BreakTypeMismatch.new(node: node,
1045
- expected: break_type,
1046
- actual: actual_type,
1047
- result: result)
1052
+ if next_type = break_context.next_type
1053
+ next_type = deep_expand_alias(next_type)
1054
+
1055
+ if value
1056
+ _, constr = check(value, next_type) do |break_type, actual_type, result|
1057
+ typing.add_error Errors::BreakTypeMismatch.new(node: node,
1058
+ expected: break_type,
1059
+ actual: actual_type,
1060
+ result: result)
1061
+ end
1062
+ else
1063
+ check_relation(sub_type: AST::Builtin.nil_type, super_type: next_type).else do |result|
1064
+ typing.add_error Errors::BreakTypeMismatch.new(node: node,
1065
+ expected: next_type,
1066
+ actual: AST::Builtin.nil_type,
1067
+ result: result)
1068
+ end
1048
1069
  end
1049
- when !value
1050
- # ok
1051
1070
  else
1052
- synthesize(value) if value
1053
- typing.add_error Errors::UnexpectedJumpValue.new(node: node)
1071
+ if value
1072
+ synthesize(value)
1073
+ typing.add_error Errors::UnexpectedJumpValue.new(node: node)
1074
+ end
1054
1075
  end
1055
1076
  else
1056
- synthesize(value)
1077
+ synthesize(value) if value
1057
1078
  typing.add_error Errors::UnexpectedJump.new(node: node)
1058
1079
  end
1059
1080
 
@@ -1074,10 +1095,6 @@ module Steep
1074
1095
  add_typing(node, type: type)
1075
1096
  else
1076
1097
  type = AST::Builtin.any_type
1077
- if context&.method_context&.method_type
1078
- Steep.logger.error { "Unknown arg type: #{node}" }
1079
- end
1080
-
1081
1098
  lvasgn(node, type)
1082
1099
  end
1083
1100
  end
@@ -1251,13 +1268,32 @@ module Steep
1251
1268
  constr = self
1252
1269
 
1253
1270
  name, sup, _ = node.children
1254
- _, constr = constr.synthesize(name)
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
1255
1279
  _, constr = constr.synthesize(sup) if sup
1256
1280
 
1257
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
+
1258
1293
  constructor.typing.add_context_for_node(node, context: constructor.context)
1259
1294
  constructor.typing.add_context_for_body(node, context: constructor.context)
1260
1295
 
1296
+ constructor.synthesize(node.children[1]) if node.children[1]
1261
1297
  constructor.synthesize(node.children[2]) if node.children[2]
1262
1298
 
1263
1299
  if constructor.module_context&.implement_name && !namespace_module?(node)
@@ -1276,6 +1312,11 @@ module Steep
1276
1312
  _, constr = constr.synthesize(name)
1277
1313
 
1278
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
+
1279
1320
  constructor.typing.add_context_for_node(node, context: constructor.context)
1280
1321
  constructor.typing.add_context_for_body(node, context: constructor.context)
1281
1322
 
@@ -1336,6 +1377,10 @@ module Steep
1336
1377
  const_name = constr.module_name_from_node(node)
1337
1378
 
1338
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
+
1339
1384
  type = type_env.get(const: const_name) do
1340
1385
  constr.fallback_to_any(node)
1341
1386
  end
@@ -1353,6 +1398,10 @@ module Steep
1353
1398
  const_name = constr.module_name_from_node(node)
1354
1399
 
1355
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
+
1356
1405
  const_type = type_env.get(const: const_name) {}
1357
1406
  value_type, constr = constr.synthesize(node.children.last, hint: const_type)
1358
1407
  type = type_env.assign(const: const_name, type: value_type, self_type: self_type) do |error|
@@ -1404,7 +1453,7 @@ module Steep
1404
1453
  if method_context&.method
1405
1454
  if method_context.super_method
1406
1455
  types = method_context.super_method.method_types.map {|method_type|
1407
- checker.factory.method_type(method_type, self_type: self_type, method_decls: Set[]).return_type
1456
+ checker.factory.method_type(method_type, self_type: self_type, method_decls: Set[]).type.return_type
1408
1457
  }
1409
1458
  add_typing(node, type: union_type(*types))
1410
1459
  else
@@ -1465,67 +1514,89 @@ module Steep
1465
1514
  yield_self do
1466
1515
  left, right = node.children
1467
1516
 
1468
- left_type, constr = synthesize(left)
1517
+ left_type, constr = synthesize(left, hint: hint, condition: true)
1469
1518
 
1470
1519
  interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: typing)
1471
1520
  truthy_env, falsey_env = interpreter.eval(env: constr.context.lvar_env, type: left_type, node: left)
1472
1521
 
1522
+ if left_type.is_a?(AST::Types::Logic::Env)
1523
+ left_type = left_type.type
1524
+ end
1525
+
1473
1526
  right_type, constr = constr
1474
1527
  .update_lvar_env { truthy_env }
1475
1528
  .tap {|constr| typing.add_context_for_node(right, context: constr.context) }
1476
1529
  .for_branch(right)
1477
- .synthesize(right)
1530
+ .synthesize(right, hint: hint, condition: true)
1478
1531
 
1479
- type = if left_type.is_a?(AST::Types::Boolean)
1532
+ truthy_env, _ = interpreter.eval(env: constr.context.lvar_env, type: right_type, node: right)
1533
+
1534
+ env = if right_type.is_a?(AST::Types::Bot)
1535
+ falsey_env
1536
+ else
1537
+ context.lvar_env.join(falsey_env, constr.context.lvar_env)
1538
+ end
1539
+
1540
+ type = case
1541
+ when check_relation(sub_type: left_type, super_type: AST::Types::Boolean.new).success?
1480
1542
  union_type(left_type, right_type)
1481
1543
  else
1482
1544
  union_type(right_type, AST::Builtin.nil_type)
1483
1545
  end
1484
1546
 
1547
+ type = AST::Types::Logic::Env.new(truthy: truthy_env, falsy: env, type: type) if condition
1548
+
1485
1549
  add_typing(node,
1486
1550
  type: type,
1487
- constr: constr.update_lvar_env do
1488
- if right_type.is_a?(AST::Types::Bot)
1489
- falsey_env
1490
- else
1491
- context.lvar_env.join(falsey_env, constr.context.lvar_env)
1492
- end
1493
- end)
1551
+ constr: constr.update_lvar_env { env })
1494
1552
  end
1495
1553
 
1496
1554
  when :or
1497
1555
  yield_self do
1498
1556
  left, right = node.children
1499
1557
 
1500
- left_type, constr = synthesize(left, hint: hint)
1558
+ left_type, constr = synthesize(left, hint: hint, condition: true)
1501
1559
 
1502
1560
  interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: typing)
1503
1561
  truthy_env, falsey_env = interpreter.eval(env: constr.context.lvar_env, type: left_type, node: left)
1504
1562
 
1505
- left_type_t, _ = checker.factory.unwrap_optional(left_type)
1563
+ if left_type.is_a?(AST::Types::Logic::Env)
1564
+ left_type = left_type.type
1565
+ end
1566
+ left_type, _ = checker.factory.unwrap_optional(left_type)
1567
+
1506
1568
  right_type, constr = constr
1507
1569
  .update_lvar_env { falsey_env }
1508
1570
  .tap {|constr| typing.add_context_for_node(right, context: constr.context) }
1509
1571
  .for_branch(right)
1510
- .synthesize(right, hint: left_type_t)
1572
+ .synthesize(right, hint: left_type, condition: true)
1511
1573
 
1512
- type = union_type(left_type_t, right_type)
1574
+ _, falsey_env = interpreter.eval(env: falsey_env, type: right_type, node: right)
1575
+
1576
+ env = if right_type.is_a?(AST::Types::Bot)
1577
+ truthy_env
1578
+ else
1579
+ context.lvar_env.join(truthy_env, constr.context.lvar_env)
1580
+ end
1581
+
1582
+ type = case
1583
+ when check_relation(sub_type: left_type, super_type: AST::Builtin.bool_type).success?
1584
+ AST::Builtin.bool_type
1585
+ else
1586
+ union_type(left_type, right_type)
1587
+ end
1513
1588
 
1589
+ type = AST::Types::Logic::Env.new(truthy: env, falsy: falsey_env, type: type) if condition
1590
+
1514
1591
  add_typing(node,
1515
1592
  type: type,
1516
- constr: constr.update_lvar_env do
1517
- if right_type.is_a?(AST::Types::Bot)
1518
- truthy_env
1519
- else
1520
- context.lvar_env.join(truthy_env, constr.context.lvar_env)
1521
- end
1522
- end)
1593
+ constr: constr.update_lvar_env { env })
1523
1594
  end
1524
1595
 
1525
1596
  when :if
1526
1597
  cond, true_clause, false_clause = node.children
1527
1598
 
1528
- cond_type, constr = synthesize(cond)
1599
+ cond_type, constr = synthesize(cond, condition: true)
1529
1600
  interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: constr.typing)
1530
1601
  truthy_env, falsey_env = interpreter.eval(env: constr.context.lvar_env, type: cond_type, node: cond)
1531
1602
 
@@ -1584,6 +1655,18 @@ module Steep
1584
1655
 
1585
1656
  cond_type, constr = constr.synthesize(cond)
1586
1657
  _, cond_vars = interpreter.decompose_value(cond)
1658
+ unless cond_vars.empty?
1659
+ first_var = cond_vars.to_a[0]
1660
+ var_node = cond.updated(
1661
+ :lvar,
1662
+ [
1663
+ ASTUtils::Labeling::LabeledName.new(name: first_var, label: 0)
1664
+ ]
1665
+ )
1666
+ else
1667
+ first_var = nil
1668
+ var_node = cond
1669
+ end
1587
1670
 
1588
1671
  when_constr = constr
1589
1672
  whens.each do |clause|
@@ -1593,9 +1676,16 @@ module Steep
1593
1676
  test_envs = []
1594
1677
 
1595
1678
  tests.each do |test|
1596
- test_node = test.updated(:send, [test, :===, cond.dup])
1597
- test_type, test_constr = test_constr.synthesize(test_node)
1679
+ test_node = test.updated(:send, [test, :===, var_node])
1680
+ test_type, test_constr = test_constr.synthesize(test_node, condition: true)
1598
1681
  truthy_env, falsy_env = interpreter.eval(type: test_type, node: test_node, env: test_constr.context.lvar_env)
1682
+ truthy_env = cond_vars.inject(truthy_env) do |env, var|
1683
+ env.assign!(var, node: test_node, type: env[first_var])
1684
+ end
1685
+ falsy_env = cond_vars.inject(falsy_env) do |env, var|
1686
+ env.assign!(var, node: test_node, type: env[first_var])
1687
+ end
1688
+
1599
1689
  test_envs << truthy_env
1600
1690
  test_constr = test_constr.update_lvar_env { falsy_env }
1601
1691
  end
@@ -1625,10 +1715,6 @@ module Steep
1625
1715
  types = branch_pairs.map(&:type)
1626
1716
  constrs = branch_pairs.map(&:constr)
1627
1717
 
1628
- unless els
1629
- constrs << when_constr
1630
- end
1631
-
1632
1718
  if when_constr.context.lvar_env[cond_vars.first].is_a?(AST::Types::Bot)
1633
1719
  # Exhaustive
1634
1720
  if els
@@ -1636,6 +1722,7 @@ module Steep
1636
1722
  end
1637
1723
  else
1638
1724
  unless els
1725
+ constrs << when_constr
1639
1726
  types << AST::Builtin.nil_type
1640
1727
  end
1641
1728
  end
@@ -1643,21 +1730,20 @@ module Steep
1643
1730
  branch_pairs = []
1644
1731
 
1645
1732
  when_constr = constr
1733
+ clause_constr = constr
1646
1734
 
1647
1735
  whens.each do |clause|
1648
1736
  *tests, body = clause.children
1649
1737
 
1650
1738
  test_constr = when_constr
1651
- test_envs = []
1652
1739
 
1653
1740
  tests.each do |test|
1654
- test_type, test_constr = test_constr.synthesize(test)
1741
+ test_type, test_constr = test_constr.synthesize(test, condition: true)
1655
1742
  truthy_env, falsy_env = interpreter.eval(env: test_constr.context.lvar_env, type: test_type, node: test)
1656
- test_envs << truthy_env
1743
+ clause_constr = clause_constr.update_lvar_env { truthy_env }
1657
1744
  test_constr = test_constr.update_lvar_env { falsy_env }
1658
1745
  end
1659
1746
 
1660
- clause_constr = when_constr.update_lvar_env {|env| env.join(*test_envs) }
1661
1747
  when_constr = test_constr
1662
1748
 
1663
1749
  if body
@@ -1831,7 +1917,7 @@ module Steep
1831
1917
  when :while, :until
1832
1918
  yield_self do
1833
1919
  cond, body = node.children
1834
- cond_type, constr = synthesize(cond)
1920
+ cond_type, constr = synthesize(cond, condition: true)
1835
1921
 
1836
1922
  interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: typing)
1837
1923
  truthy_env, falsy_env = interpreter.eval(env: constr.context.lvar_env, node: cond, type: cond_type)
@@ -1995,17 +2081,25 @@ module Steep
1995
2081
  if hint.is_a?(AST::Types::Proc) && value.type == :sym
1996
2082
  if hint.one_arg?
1997
2083
  # Assumes Symbol#to_proc implementation
1998
- param_type = hint.params.required[0]
2084
+ param_type = hint.type.params.required[0]
1999
2085
  interface = checker.factory.interface(param_type, private: true)
2000
2086
  method = interface.methods[value.children[0]]
2001
2087
  if method
2002
2088
  return_types = method.method_types.select {|method_type|
2003
- method_type.params.each_type.count == 0
2004
- }.map(&:return_type)
2089
+ method_type.type.params.empty?
2090
+ }.map {|method_type|
2091
+ method_type.type.return_type
2092
+ }
2005
2093
 
2006
2094
  unless return_types.empty?
2007
- type = AST::Types::Proc.new(params: Interface::Params.empty.update(required: [param_type]),
2008
- return_type: AST::Types::Union.build(types: return_types))
2095
+ type = AST::Types::Proc.new(
2096
+ type: Interface::Function.new(
2097
+ params: Interface::Function::Params.empty.update(required: [param_type]),
2098
+ return_type: AST::Types::Union.build(types: return_types),
2099
+ location: nil
2100
+ ),
2101
+ block: nil
2102
+ )
2009
2103
  end
2010
2104
  end
2011
2105
  else
@@ -2070,7 +2164,12 @@ module Steep
2070
2164
 
2071
2165
  when :splat
2072
2166
  yield_self do
2073
- Steep.logger.warn { "Unsupported node #{node.type} (#{node.location.expression.source_buffer.name}:#{node.location.expression.line})" }
2167
+ typing.add_error(
2168
+ Errors::UnsupportedSyntax.new(
2169
+ node: node,
2170
+ message: "Unsupported splat node occurrence"
2171
+ )
2172
+ )
2074
2173
 
2075
2174
  each_child_node node do |child|
2076
2175
  synthesize(child)
@@ -2089,7 +2188,7 @@ module Steep
2089
2188
  add_typing node, type: AST::Builtin.any_type, constr: constr
2090
2189
 
2091
2190
  else
2092
- raise "Unexpected node: #{node.inspect}, #{node.location.expression}"
2191
+ typing.add_error(Errors::UnsupportedSyntax.new(node: node))
2093
2192
 
2094
2193
  end.tap do |pair|
2095
2194
  unless pair.is_a?(Pair) && !pair.type.is_a?(Pair)
@@ -2335,13 +2434,14 @@ module Steep
2335
2434
 
2336
2435
  case type_hint
2337
2436
  when AST::Types::Proc
2338
- params_hint = type_hint.params
2339
- return_hint = type_hint.return_type
2437
+ params_hint = type_hint.type.params
2438
+ return_hint = type_hint.type.return_type
2340
2439
  end
2341
2440
 
2342
2441
  block_constr = for_block(
2343
2442
  block_params: params,
2344
2443
  block_param_hint: params_hint,
2444
+ block_type_hint: return_hint,
2345
2445
  block_annotations: block_annotations,
2346
2446
  node_type_hint: nil
2347
2447
  )
@@ -2356,18 +2456,34 @@ module Steep
2356
2456
  return_type = block_constr.synthesize_block(
2357
2457
  node: node,
2358
2458
  block_body: block_body,
2359
- topdown_hint: true,
2360
2459
  block_type_hint: return_hint
2361
- ) do |error|
2362
- typing.add_error(error)
2460
+ )
2461
+
2462
+ if expected_block_type = block_constr.block_context.body_type
2463
+ check_relation(sub_type: return_type, super_type: expected_block_type).else do |result|
2464
+ block_constr.typing.add_error(
2465
+ Errors::BlockBodyTypeMismatch.new(
2466
+ node: block_body,
2467
+ expected: expected_block_type,
2468
+ actual: return_type,
2469
+ result: result
2470
+ )
2471
+ )
2472
+
2473
+ return_type = expected_block_type
2474
+ end
2363
2475
  end
2364
2476
  else
2365
2477
  return_type = AST::Builtin.any_type
2366
2478
  end
2367
2479
 
2368
2480
  block_type = AST::Types::Proc.new(
2369
- params: params_hint || params.params_type,
2370
- return_type: return_type
2481
+ type: Interface::Function.new(
2482
+ params: params_hint || params.params_type,
2483
+ return_type: return_type,
2484
+ location: nil
2485
+ ),
2486
+ block: nil
2371
2487
  )
2372
2488
 
2373
2489
  add_typing node, type: block_type
@@ -2423,7 +2539,10 @@ module Steep
2423
2539
  errors: [error]
2424
2540
  )
2425
2541
 
2426
- constr = synthesize_children(node, skips: [receiver])
2542
+ skips = [receiver]
2543
+ skips << node.children[0] if node.type == :block
2544
+
2545
+ constr = synthesize_children(node, skips: skips)
2427
2546
  if block_params
2428
2547
  block_annotations = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
2429
2548
 
@@ -2432,15 +2551,31 @@ module Steep
2432
2551
  block_params: TypeInference::BlockParams.from_node(block_params, annotations: block_annotations),
2433
2552
  block_annotations: block_annotations,
2434
2553
  block_body: block_body
2435
- ) do |error|
2436
- errors << error
2437
- end
2554
+ )
2438
2555
  end
2439
2556
  end
2440
2557
 
2441
2558
  constr.add_call(call)
2442
2559
  else
2443
- add_call(
2560
+ skips = []
2561
+ skips << receiver if receiver
2562
+ skips << node.children[0] if node.type == :block
2563
+ skips << block_params if block_params
2564
+ skips << block_body if block_body
2565
+
2566
+ constr = synthesize_children(node, skips: skips)
2567
+ if block_params
2568
+ block_annotations = source.annotations(block: node, factory: checker.factory, current_module: current_namespace)
2569
+
2570
+ constr.type_block_without_hint(
2571
+ node: node,
2572
+ block_params: TypeInference::BlockParams.from_node(block_params, annotations: block_annotations),
2573
+ block_annotations: block_annotations,
2574
+ block_body: block_body
2575
+ )
2576
+ end
2577
+
2578
+ constr.add_call(
2444
2579
  TypeInference::MethodCall::NoMethodError.new(
2445
2580
  node: node,
2446
2581
  context: context.method_context,
@@ -2570,7 +2705,7 @@ module Steep
2570
2705
 
2571
2706
  results = method.method_types.flat_map do |method_type|
2572
2707
  Steep.logger.tagged method_type.to_s do
2573
- zips = args.zips(method_type.params, method_type.block&.type)
2708
+ zips = args.zips(method_type.type.params, method_type.block&.type)
2574
2709
 
2575
2710
  zips.map do |arg_pairs|
2576
2711
  typing.new_child(node_range) do |child_typing|
@@ -2602,7 +2737,7 @@ module Steep
2602
2737
  context: context.method_context,
2603
2738
  method_name: method_name,
2604
2739
  receiver_type: receiver_type,
2605
- return_type: method_type.return_type,
2740
+ return_type: method_type.type.return_type,
2606
2741
  errors: [error],
2607
2742
  method_decls: all_decls
2608
2743
  )
@@ -2625,7 +2760,7 @@ module Steep
2625
2760
  end
2626
2761
 
2627
2762
  def check_keyword_arg(receiver_type:, node:, method_type:, constraints:)
2628
- params = method_type.params
2763
+ params = method_type.type.params
2629
2764
 
2630
2765
  case node.type
2631
2766
  when :hash
@@ -2727,7 +2862,7 @@ module Steep
2727
2862
  )
2728
2863
  else
2729
2864
  hash_elements = params.required_keywords.merge(
2730
- method_type.params.optional_keywords.transform_values do |type|
2865
+ params.optional_keywords.transform_values do |type|
2731
2866
  AST::Types::Union.build(types: [type, AST::Builtin.nil_type])
2732
2867
  end
2733
2868
  )
@@ -2809,8 +2944,9 @@ module Steep
2809
2944
  block_constr = constr.for_block(
2810
2945
  block_params: block_params_,
2811
2946
  block_param_hint: method_type.block.type.params,
2947
+ block_type_hint: method_type.block.type.return_type,
2812
2948
  block_annotations: block_annotations,
2813
- node_type_hint: method_type.return_type
2949
+ node_type_hint: method_type.type.return_type
2814
2950
  )
2815
2951
  block_constr = block_constr.with_new_typing(
2816
2952
  block_constr.typing.new_child(
@@ -2840,19 +2976,16 @@ module Steep
2840
2976
  checker,
2841
2977
  self_type: self_type,
2842
2978
  variance: variance,
2843
- variables: method_type.params.free_variables + method_type.block.type.params.free_variables
2979
+ variables: method_type.type.params.free_variables + method_type.block.type.params.free_variables
2844
2980
  )
2845
2981
  method_type = method_type.subst(s)
2846
2982
  block_constr = block_constr.update_lvar_env {|env| env.subst(s) }
2847
2983
  if block_body
2848
2984
  block_body_type = block_constr.synthesize_block(
2849
2985
  node: node,
2850
- block_type_hint: method_type.block.type.return_type,
2851
2986
  block_body: block_body,
2852
- topdown_hint: topdown_hint
2853
- ) do |error|
2854
- errors << error
2855
- end
2987
+ block_type_hint: method_type.block.type.return_type
2988
+ )
2856
2989
  else
2857
2990
  block_body_type = AST::Builtin.nil_type
2858
2991
  end
@@ -2866,25 +2999,40 @@ module Steep
2866
2999
  s = constraints.solution(checker, self_type: self_type, variance: variance, variables: fresh_vars)
2867
3000
  method_type = method_type.subst(s)
2868
3001
 
2869
- return_type = method_type.return_type
3002
+ return_type = method_type.type.return_type
2870
3003
  if break_type = block_annotations.break_type
2871
3004
  return_type = union_type(break_type, return_type)
2872
3005
  end
2873
3006
 
2874
3007
  when Subtyping::Result::Failure
2875
- block_type = AST::Types::Proc.new(
2876
- params: method_type.block.type.params || block_params.params_type,
2877
- return_type: block_body_type
3008
+ given_block_type = AST::Types::Proc.new(
3009
+ type: Interface::Function.new(
3010
+ params: method_type.block.type.params || block_params.params_type,
3011
+ return_type: block_body_type,
3012
+ location: nil
3013
+ ),
3014
+ block: nil
3015
+ )
3016
+
3017
+ method_block_type = AST::Types::Proc.new(
3018
+ type: Interface::Function.new(
3019
+ params: method_type.block.type.params,
3020
+ return_type: method_type.block.type.return_type,
3021
+ location: nil
3022
+ ),
3023
+ block: nil
2878
3024
  )
3025
+
2879
3026
  errors << Errors::BlockTypeMismatch.new(node: node,
2880
- expected: method_type.block.type,
2881
- actual: block_type,
3027
+ expected: method_block_type,
3028
+ actual: given_block_type,
2882
3029
  result: result)
2883
3030
 
2884
- return_type = method_type.return_type
3031
+ return_type = method_type.type.return_type
2885
3032
  end
2886
3033
 
2887
3034
  block_constr.typing.save!
3035
+
2888
3036
  rescue Subtyping::Constraints::UnsatisfiableConstraint => exn
2889
3037
  errors << Errors::UnsatisfiableConstraint.new(
2890
3038
  node: node,
@@ -2955,23 +3103,24 @@ module Steep
2955
3103
  else
2956
3104
  begin
2957
3105
  method_type = method_type.subst(constraints.solution(checker, self_type: self_type, variance: variance, variables: occurence.params))
2958
- block_type, constr = constr.synthesize(args.block_pass_arg, hint: topdown_hint ? method_type.block.type : nil)
2959
- result = check_relation(
2960
- sub_type: block_type,
2961
- super_type: method_type.block.yield_self {|expected_block|
2962
- if expected_block.optional?
2963
- AST::Builtin.optional(expected_block.type)
2964
- else
2965
- expected_block.type
2966
- end
2967
- },
2968
- constraints: constraints
2969
- )
3106
+ hint_type = if topdown_hint
3107
+ AST::Types::Proc.new(type: method_type.block.type, block: nil)
3108
+ end
3109
+ given_block_type, constr = constr.synthesize(args.block_pass_arg, hint: hint_type)
3110
+ method_block_type = method_type.block.yield_self {|expected_block|
3111
+ proc_type = AST::Types::Proc.new(type: expected_block.type, block: nil)
3112
+ if expected_block.optional?
3113
+ AST::Builtin.optional(proc_type)
3114
+ else
3115
+ proc_type
3116
+ end
3117
+ }
2970
3118
 
3119
+ result = check_relation(sub_type: given_block_type, super_type: method_block_type, constraints: constraints)
2971
3120
  result.else do |result|
2972
3121
  errors << Errors::BlockTypeMismatch.new(node: node,
2973
- expected: method_type.block.type,
2974
- actual: block_type,
3122
+ expected: method_block_type,
3123
+ actual: given_block_type,
2975
3124
  result: result)
2976
3125
  end
2977
3126
 
@@ -2988,7 +3137,7 @@ module Steep
2988
3137
  receiver_type: receiver_type,
2989
3138
  method_name: method_name,
2990
3139
  actual_method_type: method_type,
2991
- return_type: return_type || method_type.return_type,
3140
+ return_type: return_type || method_type.type.return_type,
2992
3141
  method_decls: method_type.method_decls
2993
3142
  )
2994
3143
  else
@@ -2997,7 +3146,7 @@ module Steep
2997
3146
  context: context.method_context,
2998
3147
  receiver_type: receiver_type,
2999
3148
  method_name: method_name,
3000
- return_type: return_type || method_type.return_type,
3149
+ return_type: return_type || method_type.type.return_type,
3001
3150
  method_decls: method_type.method_decls,
3002
3151
  errors: errors
3003
3152
  )
@@ -3013,8 +3162,9 @@ module Steep
3013
3162
  block_constr = for_block(
3014
3163
  block_params: block_params,
3015
3164
  block_param_hint: nil,
3165
+ block_type_hint: AST::Builtin.any_type,
3016
3166
  block_annotations: block_annotations,
3017
- node_type_hint: nil
3167
+ node_type_hint: AST::Builtin.any_type
3018
3168
  )
3019
3169
 
3020
3170
  block_constr.typing.add_context_for_body(node, context: block_constr.context)
@@ -3023,10 +3173,23 @@ module Steep
3023
3173
  _, block_constr = block_constr.synthesize(param.node, hint: param.type)
3024
3174
  end
3025
3175
 
3026
- block_constr.synthesize_block(node: node, block_type_hint: nil, block_body: block_body, topdown_hint: false, &block)
3176
+ block_type = block_constr.synthesize_block(node: node, block_type_hint: nil, block_body: block_body)
3177
+
3178
+ if expected_block_type = block_constr.block_context.body_type
3179
+ block_constr.check_relation(sub_type: block_type, super_type: expected_block_type).else do |result|
3180
+ block_constr.typing.add_error(
3181
+ Errors::BlockBodyTypeMismatch.new(
3182
+ node: node,
3183
+ expected: expected_block_type,
3184
+ actual: block_type,
3185
+ result: result
3186
+ )
3187
+ )
3188
+ end
3189
+ end
3027
3190
  end
3028
3191
 
3029
- def for_block(block_params:, block_param_hint:, block_annotations:, node_type_hint:)
3192
+ def for_block(block_params:, block_param_hint:, block_type_hint:, block_annotations:, node_type_hint:)
3030
3193
  block_param_pairs = block_param_hint && block_params.zip(block_param_hint)
3031
3194
 
3032
3195
  param_types_hash = {}
@@ -3058,7 +3221,7 @@ module Steep
3058
3221
  end
3059
3222
 
3060
3223
  block_context = TypeInference::Context::BlockContext.new(
3061
- body_type: block_annotations.block_type
3224
+ body_type: block_annotations.block_type || block_type_hint || AST::Builtin.any_type
3062
3225
  )
3063
3226
  break_context = TypeInference::Context::BreakContext.new(
3064
3227
  break_type: break_type,
@@ -3083,20 +3246,9 @@ module Steep
3083
3246
  )
3084
3247
  end
3085
3248
 
3086
- def synthesize_block(node:, block_type_hint:, block_body:, topdown_hint:)
3249
+ def synthesize_block(node:, block_type_hint:, block_body:)
3087
3250
  if block_body
3088
- body_type, _, context =
3089
- if (body_type = block_context.body_type)
3090
- check(block_body, body_type) do |expected, actual, result|
3091
- error = Errors::BlockTypeMismatch.new(node: block_body,
3092
- expected: expected,
3093
- actual: actual,
3094
- result: result)
3095
- yield(error) if block_given?
3096
- end
3097
- else
3098
- synthesize(block_body, hint: topdown_hint ? block_type_hint : nil)
3099
- end
3251
+ body_type, _, context = synthesize(block_body, hint: block_context.body_type || block_type_hint)
3100
3252
 
3101
3253
  range = block_body.loc.expression.end_pos..node.loc.end.begin_pos
3102
3254
  typing.add_context(range, context: context)
@@ -3189,7 +3341,7 @@ module Steep
3189
3341
  if module_name.namespace.relative?
3190
3342
  (current_namespace + module_name.namespace).append(module_name.name)
3191
3343
  else
3192
- module_name
3344
+ module_name.to_namespace
3193
3345
  end
3194
3346
  end
3195
3347
 
@@ -3224,8 +3376,10 @@ module Steep
3224
3376
  end
3225
3377
  end
3226
3378
  expected_module_method_names = (module_context.module_definition&.methods || {}).each.with_object(Set[]) do |(name, method), set|
3227
- if method.implemented_in == module_context.module_definition.type_name
3228
- set << name
3379
+ if name != :new
3380
+ if method.implemented_in == module_context.module_definition.type_name
3381
+ set << name
3382
+ end
3229
3383
  end
3230
3384
  end
3231
3385
 
@@ -3486,6 +3640,8 @@ module Steep
3486
3640
  end
3487
3641
 
3488
3642
  def try_hash_type(node, hint)
3643
+ hint = expand_alias(hint)
3644
+
3489
3645
  case hint
3490
3646
  when AST::Types::Record
3491
3647
  typing.new_child(node.loc.expression.yield_self {|l| l.begin_pos..l.end_pos }) do |child_typing|