steep 1.4.0.dev.2 → 1.4.0.dev.3

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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +1 -2
  3. data/Gemfile +1 -1
  4. data/Gemfile.lock +7 -9
  5. data/Gemfile.steep +1 -2
  6. data/Gemfile.steep.lock +9 -10
  7. data/README.md +7 -1
  8. data/Steepfile +0 -3
  9. data/bin/rbs +0 -1
  10. data/guides/README.md +5 -0
  11. data/guides/src/gem-rbs-collection/gem-rbs-collection.md +143 -0
  12. data/guides/src/getting-started/getting-started.md +164 -0
  13. data/guides/src/nil-optional/nil-optional.md +195 -0
  14. data/lib/steep/diagnostic/ruby.rb +79 -4
  15. data/lib/steep/drivers/check.rb +4 -4
  16. data/lib/steep/interface/block.rb +10 -0
  17. data/lib/steep/module_helper.rb +13 -11
  18. data/lib/steep/path_helper.rb +4 -0
  19. data/lib/steep/server/interaction_worker.rb +105 -92
  20. data/lib/steep/services/type_name_completion.rb +157 -0
  21. data/lib/steep/source.rb +1 -0
  22. data/lib/steep/type_construction.rb +402 -229
  23. data/lib/steep/type_inference/block_params.rb +13 -0
  24. data/lib/steep/type_inference/context.rb +3 -3
  25. data/lib/steep/type_inference/method_params.rb +42 -16
  26. data/lib/steep/type_inference/send_args.rb +79 -50
  27. data/lib/steep/type_inference/type_env.rb +7 -1
  28. data/lib/steep/version.rb +1 -1
  29. data/lib/steep.rb +1 -0
  30. data/rbs_collection.steep.lock.yaml +0 -28
  31. data/rbs_collection.steep.yaml +10 -9
  32. data/sample/lib/conference.rb +12 -0
  33. data/sample/sig/conference.rbs +5 -0
  34. data/sig/shims/language-server_protocol.rbs +12 -0
  35. data/sig/shims/parser/nodes.rbs +37 -0
  36. data/sig/shims/parser.rbs +1 -0
  37. data/sig/shims/string.rbs +4 -0
  38. data/sig/steep/ast/types/factory.rbs +10 -8
  39. data/sig/steep/diagnostic/lsp_formatter.rbs +1 -1
  40. data/sig/steep/diagnostic/ruby.rbs +38 -2
  41. data/sig/steep/drivers/check.rbs +1 -1
  42. data/sig/steep/drivers/checkfile.rbs +1 -1
  43. data/sig/steep/drivers/diagnostic_printer.rbs +1 -1
  44. data/sig/steep/drivers/watch.rbs +1 -1
  45. data/sig/steep/index/signature_symbol_provider.rbs +1 -1
  46. data/sig/steep/interface/block.rbs +2 -0
  47. data/sig/steep/interface/builder.rbs +5 -3
  48. data/sig/steep/interface/method_type.rbs +5 -3
  49. data/sig/steep/module_helper.rbs +9 -0
  50. data/sig/steep/path_helper.rbs +3 -1
  51. data/sig/steep/server/base_worker.rbs +1 -1
  52. data/sig/steep/server/interaction_worker.rbs +46 -17
  53. data/sig/steep/server/master.rbs +1 -1
  54. data/sig/steep/server/type_check_worker.rbs +7 -5
  55. data/sig/steep/server/worker_process.rbs +6 -4
  56. data/sig/steep/services/completion_provider.rbs +2 -0
  57. data/sig/steep/services/type_name_completion.rbs +122 -0
  58. data/sig/steep/type_construction.rbs +99 -30
  59. data/sig/steep/type_inference/block_params.rbs +4 -0
  60. data/sig/steep/type_inference/context.rbs +70 -22
  61. data/sig/steep/type_inference/method_params.rbs +43 -24
  62. data/sig/steep/type_inference/multiple_assignment.rbs +1 -1
  63. data/sig/steep/type_inference/send_args.rbs +13 -3
  64. data/sig/steep/typing.rbs +7 -2
  65. data/smoke/diagnostics/test_expectations.yml +1 -0
  66. data/steep.gemspec +0 -1
  67. metadata +10 -16
@@ -52,10 +52,6 @@ module Steep
52
52
  context.module_context
53
53
  end
54
54
 
55
- def module_context!
56
- module_context or raise
57
- end
58
-
59
55
  def method_context
60
56
  context.method_context
61
57
  end
@@ -68,6 +64,10 @@ module Steep
68
64
  context.block_context
69
65
  end
70
66
 
67
+ def block_context!
68
+ block_context or raise
69
+ end
70
+
71
71
  def break_context
72
72
  context.break_context
73
73
  end
@@ -135,8 +135,8 @@ module Steep
135
135
  checker.check(
136
136
  relation,
137
137
  self_type: self_type,
138
- instance_type: module_context!.instance_type,
139
- class_type: module_context!.module_type,
138
+ instance_type: module_context.instance_type,
139
+ class_type: module_context.module_type,
140
140
  constraints: constraints
141
141
  )
142
142
  end
@@ -163,8 +163,8 @@ module Steep
163
163
 
164
164
  method_type = annotation_method_type || definition_method_type
165
165
 
166
- if annots&.return_type && method_type&.type&.return_type
167
- check_relation(sub_type: annots.return_type, super_type: method_type.type.return_type).else do |result|
166
+ if (annotation_return_type = annots&.return_type) && (method_type_return_type = method_type&.type&.return_type)
167
+ check_relation(sub_type: annotation_return_type, super_type: method_type_return_type).else do |result|
168
168
  typing.add_error(
169
169
  Diagnostic::Ruby::MethodReturnTypeAnnotationMismatch.new(
170
170
  node: node,
@@ -194,23 +194,23 @@ module Steep
194
194
  variable_context = self.variable_context
195
195
  end
196
196
 
197
+ method_params =
198
+ if method_type
199
+ TypeInference::MethodParams.build(node: node, method_type: method_type)
200
+ else
201
+ TypeInference::MethodParams.empty(node: node)
202
+ end
203
+
197
204
  method_context = TypeInference::Context::MethodContext.new(
198
205
  name: method_name,
199
206
  method: definition && definition.methods[method_name],
200
207
  method_type: method_type,
201
208
  return_type: annots.return_type || method_type&.type&.return_type || AST::Builtin.any_type,
202
- constructor: false,
203
- super_method: super_method
209
+ super_method: super_method,
210
+ forward_arg_type: method_params.forward_arg_type
204
211
  )
205
212
 
206
- method_params =
207
- if method_type
208
- TypeInference::MethodParams.build(node: node, method_type: method_type)
209
- else
210
- TypeInference::MethodParams.empty(node: node)
211
- end
212
-
213
- local_variable_types = method_params.each_param.with_object({}) do |param, hash|
213
+ local_variable_types = method_params.each_param.with_object({}) do |param, hash| #$ Hash[Symbol, AST::Types::t]
214
214
  if param.name
215
215
  unless SPECIAL_LVAR_NAMES.include?(param.name)
216
216
  hash[param.name] = param.var_type
@@ -221,14 +221,16 @@ module Steep
221
221
 
222
222
  type_env = TypeInference::TypeEnvBuilder.new(
223
223
  TypeInference::TypeEnvBuilder::Command::ImportLocalVariableAnnotations.new(annots).merge!.on_duplicate! do |name, original, annotated|
224
- param = method_params.each_param.find {|param| param.name == name }
225
- if result = no_subtyping?(sub_type: original, super_type: annotated)
226
- typing.add_error Diagnostic::Ruby::IncompatibleAnnotation.new(
227
- node: param.node,
228
- var_name: name,
229
- result: result,
230
- relation: result.relation
231
- )
224
+ if method_params.param?(name)
225
+ param = method_params[name]
226
+ if result = no_subtyping?(sub_type: original, super_type: annotated)
227
+ typing.add_error Diagnostic::Ruby::IncompatibleAnnotation.new(
228
+ node: param.node,
229
+ var_name: name,
230
+ result: result,
231
+ relation: result.relation
232
+ )
233
+ end
232
234
  end
233
235
  end,
234
236
  TypeInference::TypeEnvBuilder::Command::ImportInstanceVariableDefinition.new(definition, checker.factory),
@@ -308,7 +310,7 @@ module Steep
308
310
 
309
311
  def default_module_context(implement_module_name, nesting:)
310
312
  if implement_module_name
311
- module_name = checker.factory.absolute_type_name(implement_module_name.name, context: nesting)
313
+ module_name = checker.factory.absolute_type_name(implement_module_name.name, context: nesting) or raise
312
314
  module_args = implement_module_name.args.map {|name| AST::Types::Var.new(name: name) }
313
315
 
314
316
  instance_def = checker.factory.definition_builder.build_instance(module_name)
@@ -328,8 +330,8 @@ module Steep
328
330
  )
329
331
  else
330
332
  TypeInference::Context::ModuleContext.new(
331
- instance_type: nil,
332
- module_type: nil,
333
+ instance_type: AST::Builtin::Object.instance_type,
334
+ module_type: AST::Builtin::Object.module_type,
333
335
  implement_name: nil,
334
336
  nesting: nesting,
335
337
  class_name: self.module_context.class_name,
@@ -375,6 +377,8 @@ module Steep
375
377
  args: module_self.args,
376
378
  location: module_self.location
377
379
  )
380
+ else
381
+ raise
378
382
  end
379
383
  checker.factory.type(type)
380
384
  },
@@ -451,7 +455,7 @@ module Steep
451
455
  end
452
456
 
453
457
  def for_class(node, new_class_name, super_class_name)
454
- new_nesting = [nesting, new_class_name || false]
458
+ new_nesting = [nesting, new_class_name || false] #: RBS::Resolver::context
455
459
  annots = source.annotations(block: node, factory: checker.factory, context: new_nesting)
456
460
 
457
461
  class_const_env = TypeInference::ConstantEnv.new(
@@ -594,7 +598,7 @@ module Steep
594
598
 
595
599
  module_definition = case module_type
596
600
  when AST::Types::Name::Singleton
597
- type_name = instance_type.name
601
+ type_name = module_type.name
598
602
  checker.factory.definition_builder.build_singleton(type_name)
599
603
  else
600
604
  nil
@@ -728,7 +732,7 @@ module Steep
728
732
  else
729
733
  if enforced_type = context.type_env.enforced_type(name)
730
734
  case
731
- when hint == nil
735
+ when !hint
732
736
  hint = enforced_type
733
737
  when check_relation(sub_type: enforced_type, super_type: hint).success?
734
738
  # enforced_type is compatible with hint and more specific to hint.
@@ -862,27 +866,29 @@ module Steep
862
866
 
863
867
  when :super
864
868
  yield_self do
865
- if self_type && method_context&.method
866
- if super_def = method_context.super_method
869
+ if self_type && method_context!.method
870
+ if super_def = method_context!.super_method
867
871
  each_child_node(node) do |child|
868
872
  synthesize(child)
869
873
  end
870
874
 
871
875
  super_method = Interface::Shape::Entry.new(
872
- method_types: method_context.super_method.method_types.map {|method_type|
876
+ method_types: super_def.defs.map {|type_def|
873
877
  decl = TypeInference::MethodCall::MethodDecl.new(
874
- method_name: InstanceMethodName.new(type_name: super_def.implemented_in || super_def.defined_in,
875
- method_name: method_context.name),
876
- method_def: super_def
878
+ method_name: InstanceMethodName.new(
879
+ type_name: super_def.implemented_in || super_def.defined_in || raise,
880
+ method_name: method_context!.name || raise("method context must have a name")
881
+ ),
882
+ method_def: type_def
877
883
  )
878
- checker.factory.method_type(method_type, method_decls: Set[decl])
884
+ checker.factory.method_type(type_def.type, method_decls: Set[decl])
879
885
  }
880
886
  )
881
887
 
882
888
  call, constr = type_method_call(
883
889
  node,
884
890
  receiver_type: self_type,
885
- method_name: method_context.name,
891
+ method_name: method_context!.name || raise("method context must have a name"),
886
892
  method: super_method,
887
893
  arguments: node.children,
888
894
  block_params: nil,
@@ -896,13 +902,13 @@ module Steep
896
902
  error = Diagnostic::Ruby::UnresolvedOverloading.new(
897
903
  node: node,
898
904
  receiver_type: self_type,
899
- method_name: method_context.name,
905
+ method_name: method_context!.name,
900
906
  method_types: super_method.method_types
901
907
  )
902
908
  call = TypeInference::MethodCall::Error.new(
903
909
  node: node,
904
- context: context.method_context,
905
- method_name: method_context.name,
910
+ context: context.call_context,
911
+ method_name: method_context!.name || raise("method context must have a name"),
906
912
  receiver_type: self_type,
907
913
  errors: [error]
908
914
  )
@@ -913,7 +919,7 @@ module Steep
913
919
  end
914
920
  else
915
921
  fallback_to_any node do
916
- Diagnostic::Ruby::UnexpectedSuper.new(node: node, method: method_context.name)
922
+ Diagnostic::Ruby::UnexpectedSuper.new(node: node, method: method_context!.name)
917
923
  end
918
924
  end
919
925
  else
@@ -923,6 +929,8 @@ module Steep
923
929
 
924
930
  when :def
925
931
  yield_self do
932
+ # @type var node: Parser::AST::Node & Parser::AST::_DefNode
933
+
926
934
  name, args_node, body_node = node.children
927
935
 
928
936
  with_method_constr(
@@ -1021,16 +1029,16 @@ module Steep
1021
1029
  new.typing.add_context_for_node(node, context: new.context)
1022
1030
  new.typing.add_context_for_body(node, context: new.context)
1023
1031
 
1024
- new.method_context.tap do |method_context|
1032
+ new.method_context!.tap do |method_context|
1025
1033
  if method_context.method
1026
1034
  name_ = node.children[1]
1027
1035
 
1028
1036
  method_name =
1029
1037
  case self_type
1030
1038
  when AST::Types::Name::Instance
1031
- InstanceMethodName.new(type_name: method_context.method.implemented_in, method_name: name_)
1039
+ InstanceMethodName.new(type_name: method_context.method.implemented_in || raise, method_name: name_)
1032
1040
  when AST::Types::Name::Singleton
1033
- SingletonMethodName.new(type_name: method_context.method.implemented_in, method_name: name_)
1041
+ SingletonMethodName.new(type_name: method_context.method.implemented_in || raise, method_name: name_)
1034
1042
  end
1035
1043
 
1036
1044
  new.typing.source_index.add_definition(method: method_name, definition: node)
@@ -1044,8 +1052,8 @@ module Steep
1044
1052
  end
1045
1053
 
1046
1054
  if node.children[3]
1047
- return_type = expand_alias(new.method_context&.return_type)
1048
- if return_type && !return_type.is_a?(AST::Types::Void)
1055
+ return_type = expand_alias(new.method_context!.return_type)
1056
+ if !return_type.is_a?(AST::Types::Void)
1049
1057
  new.check(node.children[3], return_type) do |return_type, actual_type, result|
1050
1058
  typing.add_error(
1051
1059
  Diagnostic::Ruby::MethodBodyTypeMismatch.new(
@@ -1062,49 +1070,44 @@ module Steep
1062
1070
  end
1063
1071
  end
1064
1072
 
1065
- if module_context
1066
- if node.children[0].type == :self
1067
- module_context.defined_module_methods << node.children[1]
1068
- end
1073
+ if node.children[0].type == :self
1074
+ module_context.defined_module_methods << node.children[1]
1069
1075
  end
1070
1076
 
1071
1077
  add_typing(node, type: AST::Builtin::Symbol.instance_type)
1072
1078
 
1073
1079
  when :return
1074
1080
  yield_self do
1075
- method_return_type = expand_alias(method_context&.return_type)
1081
+ method_return_type =
1082
+ if method_context
1083
+ expand_alias(method_context.return_type)
1084
+ end
1076
1085
 
1077
- if node.children.size > 0
1086
+ case node.children.size
1087
+ when 0
1088
+ value_type = AST::Builtin.nil_type
1089
+ constr = self
1090
+ when 1
1091
+ return_value_node = node.children[0]
1092
+ value_type, constr = synthesize(return_value_node, hint: method_return_type)
1093
+ else
1094
+ constr = synthesize_children(node)
1078
1095
  return_types = node.children.map do |value|
1079
- synthesize(
1080
- value,
1081
- hint: if method_return_type.is_a?(AST::Types::Void)
1082
- nil
1083
- else
1084
- method_return_type
1085
- end
1086
- ).type
1096
+ constr.typing.type_of(node: value)
1087
1097
  end
1088
1098
 
1089
- value_type = if return_types.size == 1
1090
- return_types.first
1091
- else
1092
- AST::Builtin::Array.instance_type(union_type(*return_types))
1093
- end
1094
-
1095
- else
1096
- value_type = AST::Builtin.nil_type
1099
+ value_type = AST::Builtin::Array.instance_type(union_type(*return_types))
1097
1100
  end
1098
1101
 
1099
1102
  if method_return_type
1100
- unless method_return_type.is_a?(AST::Types::Void)
1101
- result = check_relation(sub_type: value_type, super_type: method_return_type)
1103
+ unless method_context.nil? || method_return_type.is_a?(AST::Types::Void)
1104
+ result = constr.check_relation(sub_type: value_type, super_type: method_return_type)
1102
1105
 
1103
1106
  if result.failure?
1104
1107
  typing.add_error(
1105
1108
  Diagnostic::Ruby::ReturnTypeMismatch.new(
1106
1109
  node: node,
1107
- expected: method_context&.return_type,
1110
+ expected: method_return_type,
1108
1111
  actual: value_type,
1109
1112
  result: result
1110
1113
  )
@@ -1113,14 +1116,14 @@ module Steep
1113
1116
  end
1114
1117
  end
1115
1118
 
1116
- add_typing(node, type: AST::Builtin.bottom_type)
1119
+ constr.add_typing(node, type: AST::Builtin.bottom_type)
1117
1120
  end
1118
1121
 
1119
1122
  when :break
1120
1123
  value = node.children[0]
1121
1124
 
1122
1125
  if break_context
1123
- break_type = (break_context || raise).break_type
1126
+ break_type = break_context.break_type
1124
1127
 
1125
1128
  if value
1126
1129
  check(value, break_type) do |break_type, actual_type, result|
@@ -1158,7 +1161,7 @@ module Steep
1158
1161
 
1159
1162
  if break_context
1160
1163
  if next_type = break_context.next_type
1161
- next_type = deep_expand_alias(next_type)
1164
+ next_type = deep_expand_alias(next_type) || next_type
1162
1165
 
1163
1166
  if value
1164
1167
  _, constr = check(value, next_type) do |break_type, actual_type, result|
@@ -1201,7 +1204,7 @@ module Steep
1201
1204
 
1202
1205
  when :procarg0
1203
1206
  yield_self do
1204
- constr = self
1207
+ constr = self #: TypeConstruction
1205
1208
 
1206
1209
  node.children.each do |arg|
1207
1210
  if arg.is_a?(Symbol)
@@ -1227,7 +1230,7 @@ module Steep
1227
1230
 
1228
1231
  when :mlhs
1229
1232
  yield_self do
1230
- constr = self
1233
+ constr = self #: TypeConstruction
1231
1234
 
1232
1235
  node.children.each do |arg|
1233
1236
  _, constr = constr.synthesize(arg)
@@ -1353,7 +1356,6 @@ module Steep
1353
1356
  ty = node.type == :true ? AST::Types::Literal.new(value: true) : AST::Types::Literal.new(value: false)
1354
1357
 
1355
1358
  if hint && check_relation(sub_type: ty, super_type: hint).success? && !hint.is_a?(AST::Types::Any) && !hint.is_a?(AST::Types::Top)
1356
-
1357
1359
  add_typing(node, type: hint)
1358
1360
  else
1359
1361
  add_typing(node, type: AST::Types::Boolean.new)
@@ -1393,8 +1395,11 @@ module Steep
1393
1395
  yield_self do
1394
1396
  constr = self
1395
1397
 
1398
+ # @type var name_node: Parser::AST::Node
1399
+ # @type var super_node: Parser::AST::Node?
1400
+
1396
1401
  name_node, super_node, _ = node.children
1397
- _, constr, class_name = synthesize_constant(name_node, name_node.children[0], name_node.children[1]) do
1402
+ _, constr, class_name = synthesize_constant_decl(name_node, name_node.children[0], name_node.children[1]) do
1398
1403
  typing.add_error(
1399
1404
  Diagnostic::Ruby::UnknownConstant.new(node: name_node, name: name_node.children[1]).class!
1400
1405
  )
@@ -1421,9 +1426,9 @@ module Steep
1421
1426
 
1422
1427
  with_class_constr(node, class_name, super_name) do |constructor|
1423
1428
  if module_type = constructor.module_context&.module_type
1424
- _, constructor = constructor.add_typing(name, type: module_type)
1429
+ _, constructor = constructor.add_typing(name_node, type: module_type)
1425
1430
  else
1426
- _, constructor = constructor.fallback_to_any(name)
1431
+ _, constructor = constructor.fallback_to_any(name_node)
1427
1432
  end
1428
1433
 
1429
1434
  constructor.typing.add_context_for_node(node, context: constructor.context)
@@ -1443,8 +1448,9 @@ module Steep
1443
1448
  yield_self do
1444
1449
  constr = self
1445
1450
 
1451
+ # @type var name_node: Parser::AST::Node
1446
1452
  name_node, _ = node.children
1447
- _, constr, module_name = synthesize_constant(name_node, name_node.children[0], name_node.children[1]) do
1453
+ _, constr, module_name = synthesize_constant_decl(name_node, name_node.children[0], name_node.children[1]) do
1448
1454
  typing.add_error Diagnostic::Ruby::UnknownConstant.new(node: name_node, name: name_node.children[1]).module!
1449
1455
  end
1450
1456
 
@@ -1454,9 +1460,9 @@ module Steep
1454
1460
 
1455
1461
  with_module_constr(node, module_name) do |constructor|
1456
1462
  if module_type = constructor.module_context&.module_type
1457
- _, constructor = constructor.add_typing(name, type: module_type)
1463
+ _, constructor = constructor.add_typing(name_node, type: module_type)
1458
1464
  else
1459
- _, constructor = constructor.fallback_to_any(name)
1465
+ _, constructor = constructor.fallback_to_any(name_node)
1460
1466
  end
1461
1467
 
1462
1468
  constructor.typing.add_context_for_node(node, context: constructor.context)
@@ -1492,9 +1498,9 @@ module Steep
1492
1498
 
1493
1499
  constructor.synthesize(node.children[1]) if node.children[1]
1494
1500
 
1495
- if constructor.module_context!.instance_definition && module_context!.module_definition
1496
- if constructor.module_context!.instance_definition.type_name == module_context!.module_definition.type_name
1497
- module_context!.defined_module_methods.merge(constructor.module_context!.defined_instance_methods)
1501
+ if constructor.module_context.instance_definition && module_context.module_definition
1502
+ if constructor.module_context.instance_definition.type_name == module_context.module_definition.type_name
1503
+ module_context.defined_module_methods.merge(constructor.module_context.defined_instance_methods)
1498
1504
  end
1499
1505
  end
1500
1506
  end
@@ -1521,7 +1527,7 @@ module Steep
1521
1527
 
1522
1528
  when :casgn
1523
1529
  yield_self do
1524
- constant_type, constr, constant_name = synthesize_constant(nil, node.children[0], node.children[1]) do
1530
+ constant_type, constr, constant_name = synthesize_constant_decl(nil, node.children[0], node.children[1]) do
1525
1531
  typing.add_error(
1526
1532
  Diagnostic::Ruby::UnknownConstant.new(
1527
1533
  node: node,
@@ -1570,6 +1576,7 @@ module Steep
1570
1576
  # @type var errors: Array[Diagnostic::Ruby::Base]
1571
1577
  errors = []
1572
1578
  constr = type_check_args(
1579
+ nil,
1573
1580
  args,
1574
1581
  Subtyping::Constraints.new(unknowns: []),
1575
1582
  errors
@@ -1590,7 +1597,7 @@ module Steep
1590
1597
 
1591
1598
  when :zsuper
1592
1599
  yield_self do
1593
- if method_context&.method
1600
+ if method_context && method_context.method
1594
1601
  if method_context.super_method
1595
1602
  types = method_context.super_method.method_types.map {|method_type|
1596
1603
  checker.factory.method_type(method_type, method_decls: Set[]).type.return_type
@@ -1623,22 +1630,28 @@ module Steep
1623
1630
  else
1624
1631
  node_range = node.loc.expression.yield_self {|l| l.begin_pos..l.end_pos }
1625
1632
 
1626
- if hint && !(tuples = select_flatten_types(hint) {|type| type.is_a?(AST::Types::Tuple) }).empty?
1627
- tuples.each do |tuple|
1628
- typing.new_child(node_range) do |child_typing|
1629
- if pair = with_new_typing(child_typing).try_tuple_type(node, tuple)
1630
- return pair.with(constr: pair.constr.save_typing)
1633
+ if hint
1634
+ tuples = select_flatten_types(hint) {|type| type.is_a?(AST::Types::Tuple) } #: Array[AST::Types::Tuple]
1635
+ unless tuples.empty?
1636
+ tuples.each do |tuple|
1637
+ typing.new_child(node_range) do |child_typing|
1638
+ if pair = with_new_typing(child_typing).try_tuple_type(node, tuple)
1639
+ return pair.with(constr: pair.constr.save_typing)
1640
+ end
1631
1641
  end
1632
1642
  end
1633
1643
  end
1634
1644
  end
1635
1645
 
1636
- if hint && !(arrays = select_flatten_types(hint) {|type| AST::Builtin::Array.instance_type?(type) }).empty?
1637
- arrays.each do |array|
1638
- typing.new_child(node_range) do |child_typing|
1639
- pair = with_new_typing(child_typing).try_array_type(node, array)
1640
- if pair.constr.check_relation(sub_type: pair.type, super_type: hint).success?
1641
- return pair.with(constr: pair.constr.save_typing)
1646
+ if hint
1647
+ arrays = select_flatten_types(hint) {|type| AST::Builtin::Array.instance_type?(type) } #: Array[AST::Types::Name::Instance]
1648
+ unless arrays.empty?
1649
+ arrays.each do |array|
1650
+ typing.new_child(node_range) do |child_typing|
1651
+ pair = with_new_typing(child_typing).try_array_type(node, array)
1652
+ if pair.constr.check_relation(sub_type: pair.type, super_type: hint).success?
1653
+ return pair.with(constr: pair.constr.save_typing)
1654
+ end
1642
1655
  end
1643
1656
  end
1644
1657
  end
@@ -1771,7 +1784,7 @@ module Steep
1771
1784
  end
1772
1785
 
1773
1786
  constr = constr.update_type_env do |env|
1774
- envs = []
1787
+ envs = [] #: Array[TypeInference::TypeEnv]
1775
1788
 
1776
1789
  if true_pair
1777
1790
  unless true_pair.type.is_a?(AST::Types::Bot)
@@ -1798,13 +1811,15 @@ module Steep
1798
1811
 
1799
1812
  when :case
1800
1813
  yield_self do
1814
+ # @type var node: Parser::AST::Node & Parser::AST::_CaseNode
1815
+
1801
1816
  cond, *whens, els = node.children
1802
1817
 
1803
- constr = self
1818
+ constr = self #: TypeConstruction
1804
1819
  interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: typing, config: builder_config)
1805
1820
 
1806
1821
  if cond
1807
- branch_results = []
1822
+ branch_results = [] #: Array[Pair]
1808
1823
 
1809
1824
  cond_type, constr = constr.synthesize(cond)
1810
1825
  _, cond_vars = interpreter.decompose_value(cond)
@@ -1858,6 +1873,8 @@ module Steep
1858
1873
  end
1859
1874
 
1860
1875
  if els
1876
+ node.loc.else or raise
1877
+
1861
1878
  begin_pos = node.loc.else.end_pos
1862
1879
  end_pos = node.loc.end.begin_pos
1863
1880
  typing.add_context(begin_pos..end_pos, context: when_constr.context)
@@ -1885,14 +1902,14 @@ module Steep
1885
1902
  end
1886
1903
  end
1887
1904
  else
1888
- branch_results = []
1905
+ branch_results = [] #: Array[Pair]
1889
1906
 
1890
1907
  condition_constr = constr
1891
1908
  clause_constr = constr
1892
1909
 
1893
1910
  whens.each do |when_clause|
1894
1911
  when_clause_constr = condition_constr
1895
- body_envs = []
1912
+ body_envs = [] #: Array[TypeInference::TypeEnv]
1896
1913
 
1897
1914
  *tests, body = when_clause.children
1898
1915
 
@@ -1975,7 +1992,7 @@ module Steep
1975
1992
  end
1976
1993
 
1977
1994
  resbody_construction = body_constr.for_branch(resbody).update_type_env do |env|
1978
- assignments = {}
1995
+ assignments = {} #: Hash[Symbol, AST::Types::t]
1979
1996
 
1980
1997
  case
1981
1998
  when exn_classes && var_name && exn_types
@@ -2025,8 +2042,12 @@ module Steep
2025
2042
  klasses, asgn, body = node.children
2026
2043
  synthesize(klasses) if klasses
2027
2044
  synthesize(asgn) if asgn
2028
- body_type = synthesize(body, hint: hint).type if body
2029
- add_typing(node, type: body_type)
2045
+ if body
2046
+ body_type = synthesize(body, hint: hint).type
2047
+ add_typing(node, type: body_type)
2048
+ else
2049
+ add_typing(node, type: AST::Builtin.nil_type)
2050
+ end
2030
2051
  end
2031
2052
 
2032
2053
  when :ensure
@@ -2034,7 +2055,11 @@ module Steep
2034
2055
  body, ensure_body = node.children
2035
2056
  body_type = synthesize(body).type if body
2036
2057
  synthesize(ensure_body) if ensure_body
2037
- add_typing(node, type: union_type(body_type))
2058
+ if body_type
2059
+ add_typing(node, type: body_type)
2060
+ else
2061
+ add_typing(node, type: AST::Builtin.nil_type)
2062
+ end
2038
2063
  end
2039
2064
 
2040
2065
  when :masgn
@@ -2054,13 +2079,13 @@ module Steep
2054
2079
  if method_type = (each.method_types || []).find {|type| type.block && type.block.type.params.first_param }
2055
2080
  if block = method_type.block
2056
2081
  if first_param = block.type.params.first_param
2057
- var_type = first_param.type
2082
+ var_type = first_param.type #: AST::Types::t
2058
2083
  end
2059
2084
  end
2060
2085
  end
2061
2086
  end
2062
2087
  end
2063
- var_name = asgn.children[0]
2088
+ var_name = asgn.children[0] #: Symbol
2064
2089
 
2065
2090
  if var_type
2066
2091
  if body
@@ -2106,8 +2131,14 @@ module Steep
2106
2131
  body_env, exit_env = truthy_env, falsy_env
2107
2132
  when :until
2108
2133
  exit_env, body_env = truthy_env, falsy_env
2134
+ else
2135
+ raise
2109
2136
  end
2110
2137
 
2138
+ body_env or raise
2139
+ exit_env or raise
2140
+
2141
+
2111
2142
  if body
2112
2143
  pins = body_env.pin_local_variables(nil)
2113
2144
  body_env = body_env.merge(local_variable_types: pins)
@@ -2131,7 +2162,7 @@ module Steep
2131
2162
  yield_self do
2132
2163
  cond, body = node.children
2133
2164
 
2134
- _, cond_constr, = synthesize(cond).to_ary
2165
+ _, cond_constr, = synthesize(cond)
2135
2166
 
2136
2167
  if body
2137
2168
  for_loop =
@@ -2146,7 +2177,7 @@ module Steep
2146
2177
 
2147
2178
  add_typing(node, type: AST::Builtin.nil_type, constr: constr)
2148
2179
  else
2149
- add_typing(node, type: AST::Builtin.nil_type, constr: cond_pair.constr)
2180
+ add_typing(node, type: AST::Builtin.nil_type, constr: cond_constr)
2150
2181
  end
2151
2182
  end
2152
2183
 
@@ -2155,12 +2186,12 @@ module Steep
2155
2186
 
2156
2187
  constr = self
2157
2188
  begin_type, constr = if begin_node
2158
- constr.synthesize(begin_node)
2189
+ constr.synthesize(begin_node).to_ary
2159
2190
  else
2160
2191
  [AST::Builtin.nil_type, constr]
2161
2192
  end
2162
2193
  end_type, constr = if end_node
2163
- constr.synthesize(end_node)
2194
+ constr.synthesize(end_node).to_ary
2164
2195
  else
2165
2196
  [AST::Builtin.nil_type, constr]
2166
2197
  end
@@ -2298,14 +2329,18 @@ module Steep
2298
2329
  Steep.logger.error "Passing multiple args through Symbol#to_proc is not supported yet"
2299
2330
  end
2300
2331
  when value == nil
2301
- type = AST::Types::Proc.new(
2302
- type: method_context.method_type.block.type,
2303
- location: nil,
2304
- block: nil,
2305
- self_type: method_context.method_type.block.self_type
2306
- )
2307
- if method_context.method_type.block.optional?
2308
- type = AST::Types::Union.build(types: [type, AST::Builtin.nil_type])
2332
+ if block_type = method_context!.block_type
2333
+ type = AST::Types::Proc.new(
2334
+ type: block_type.type,
2335
+ location: nil,
2336
+ block: nil,
2337
+ self_type: block_type.self_type
2338
+ )
2339
+ if block_type.optional?
2340
+ type = AST::Types::Union.build(types: [type, AST::Builtin.nil_type])
2341
+ end
2342
+ else
2343
+ type = AST::Builtin.nil_type
2309
2344
  end
2310
2345
  end
2311
2346
 
@@ -2328,9 +2363,12 @@ module Steep
2328
2363
 
2329
2364
  type, constr = synthesize(rhs, hint: hint)
2330
2365
 
2331
- var_type = if module_context&.class_variables
2332
- module_context.class_variables[name]&.yield_self {|ty| checker.factory.type(ty) }
2333
- end
2366
+ var_type =
2367
+ if class_vars = module_context.class_variables
2368
+ if ty = class_vars[name]
2369
+ checker.factory.type(ty)
2370
+ end
2371
+ end
2334
2372
 
2335
2373
  if var_type
2336
2374
  result = constr.check_relation(sub_type: type, super_type: var_type)
@@ -2352,10 +2390,13 @@ module Steep
2352
2390
  end
2353
2391
 
2354
2392
  when :cvar
2355
- name = node.children[0]
2356
- var_type = if module_context&.class_variables
2357
- module_context.class_variables[name]&.yield_self {|ty| checker.factory.type(ty) }
2358
- end
2393
+ name = node.children[0] #: Symbol
2394
+ var_type =
2395
+ if cvs = module_context.class_variables
2396
+ if ty = cvs[name]
2397
+ checker.factory.type(ty)
2398
+ end
2399
+ end
2359
2400
 
2360
2401
  if var_type
2361
2402
  add_typing node, type: var_type
@@ -2383,7 +2424,7 @@ module Steep
2383
2424
  end
2384
2425
 
2385
2426
  when :args
2386
- constr = self
2427
+ constr = self #: TypeConstruction
2387
2428
 
2388
2429
  each_child_node(node) do |child|
2389
2430
  _, constr = constr.synthesize(child)
@@ -2396,7 +2437,7 @@ module Steep
2396
2437
  # @type var as_type: AST::Node::TypeAssertion
2397
2438
  asserted_node, as_type = node.children
2398
2439
 
2399
- if type = as_type.type?(module_context!.nesting, checker.factory, [])
2440
+ if type = as_type.type?(module_context.nesting, checker.factory, [])
2400
2441
  actual_type, constr = synthesize(asserted_node, hint: type)
2401
2442
 
2402
2443
  if no_subtyping?(sub_type: type, super_type: actual_type) && no_subtyping?(sub_type: actual_type, super_type: type)
@@ -2426,6 +2467,9 @@ module Steep
2426
2467
  constr.add_typing(node, type: type)
2427
2468
  end
2428
2469
 
2470
+ when :forwarded_args, :forward_arg
2471
+ add_typing(node, type: AST::Builtin.any_type)
2472
+
2429
2473
  else
2430
2474
  typing.add_error(Diagnostic::Ruby::UnsupportedSyntax.new(node: node))
2431
2475
  add_typing(node, type: AST::Builtin.any_type)
@@ -2439,7 +2483,7 @@ module Steep
2439
2483
  end
2440
2484
  rescue RBS::BaseError => exn
2441
2485
  Steep.logger.warn { "Unexpected RBS error: #{exn.message}" }
2442
- exn.backtrace.each {|loc| Steep.logger.warn " #{loc}" }
2486
+ exn.backtrace&.each {|loc| Steep.logger.warn " #{loc}" }
2443
2487
  typing.add_error(Diagnostic::Ruby::UnexpectedError.new(node: node, error: exn))
2444
2488
  type_any_rec(node)
2445
2489
  rescue StandardError => exn
@@ -2466,7 +2510,7 @@ module Steep
2466
2510
  when :send
2467
2511
  yield_self do
2468
2512
  if self_class?(node)
2469
- module_type = expand_alias(module_context!.module_type)
2513
+ module_type = expand_alias(module_context.module_type)
2470
2514
  type = if module_type.is_a?(AST::Types::Name::Singleton)
2471
2515
  AST::Types::Name::Singleton.new(name: module_type.name)
2472
2516
  else
@@ -2482,7 +2526,7 @@ module Steep
2482
2526
  yield_self do
2483
2527
  send_type, constr =
2484
2528
  if self_class?(node)
2485
- module_type = expand_alias(module_context!.module_type)
2529
+ module_type = expand_alias(module_context.module_type)
2486
2530
  type = if module_type.is_a?(AST::Types::Name::Singleton)
2487
2531
  AST::Types::Name::Singleton.new(name: module_type.name)
2488
2532
  else
@@ -2501,6 +2545,7 @@ module Steep
2501
2545
  yield_self do
2502
2546
  send_node, params, body = node.children
2503
2547
  if send_node.type == :lambda
2548
+ # @type var node: Parser::AST::Node & Parser::AST::_BlockNode
2504
2549
  type_lambda(node, params_node: params, body_node: body, type_hint: hint)
2505
2550
  else
2506
2551
  type_send(node, send_node: send_node, block_params: params, block_body: body, unwrap: send_node.type == :csend, tapp: tapp)
@@ -2519,6 +2564,7 @@ module Steep
2519
2564
  params = Parser::AST::Node.new(:args, arg_nodes)
2520
2565
 
2521
2566
  if send_node.type == :lambda
2567
+ # @type var node: Parser::AST::Node & Parser::AST::_BlockNode
2522
2568
  type_lambda(node, params_node: params, body_node: body, type_hint: hint)
2523
2569
  else
2524
2570
  type_send(node, send_node: send_node, block_params: params, block_body: body, unwrap: send_node.type == :csend, tapp: tapp)
@@ -2632,7 +2678,7 @@ module Steep
2632
2678
  hint = masgn.hint_for_mlhs(lhs, context.type_env)
2633
2679
 
2634
2680
  rhs_type, lhs_constr = try_tuple_type!(rhs, hint: hint).to_ary
2635
- rhs_type = deep_expand_alias(rhs_type)
2681
+ rhs_type = deep_expand_alias(rhs_type) || rhs_type
2636
2682
 
2637
2683
  falsys, truthys = partition_flatten_types(rhs_type) do |type|
2638
2684
  type.is_a?(AST::Types::Nil) || (type.is_a?(AST::Types::Literal) && type.value == false)
@@ -2680,6 +2726,57 @@ module Steep
2680
2726
  constr.add_typing(node, type: truthy_rhs_type)
2681
2727
  end
2682
2728
 
2729
+ def synthesize_constant_decl(node, parent_node, constant_name, &block)
2730
+ const_name = module_name_from_node(parent_node, constant_name)
2731
+
2732
+ if const_name && type = context.type_env.annotated_constant(const_name)
2733
+ # const-type annotation wins
2734
+ if node
2735
+ constr = synthesize_children(node)
2736
+ type, constr = constr.add_typing(node, type: type)
2737
+ [type, constr, nil]
2738
+ else
2739
+ [type, self, nil]
2740
+ end
2741
+ else
2742
+ if parent_node
2743
+ synthesize_constant(node, parent_node, constant_name, &block)
2744
+ else
2745
+ if nesting
2746
+ if parent_nesting = nesting[1]
2747
+ if constant = context.type_env.constant_env.resolver.table.children(parent_nesting)&.fetch(constant_name, nil)
2748
+ return [checker.factory.type(constant.type), self, constant.name]
2749
+ end
2750
+ end
2751
+
2752
+ if block_given?
2753
+ yield
2754
+ else
2755
+ if node
2756
+ typing.add_error(
2757
+ Diagnostic::Ruby::UnknownConstant.new(node: node, name: constant_name)
2758
+ )
2759
+ end
2760
+ end
2761
+
2762
+ constr = self #: TypeConstruction
2763
+ if node
2764
+ _, constr = add_typing(node, type: AST::Builtin.any_type)
2765
+ end
2766
+
2767
+ [
2768
+ AST::Builtin.any_type,
2769
+ constr,
2770
+ nil
2771
+ ]
2772
+ else
2773
+ # No neesting
2774
+ synthesize_constant(node, nil, constant_name, &block)
2775
+ end
2776
+ end
2777
+ end
2778
+ end
2779
+
2683
2780
  def synthesize_constant(node, parent_node, constant_name)
2684
2781
  const_name = module_name_from_node(parent_node, constant_name)
2685
2782
 
@@ -2795,7 +2892,7 @@ module Steep
2795
2892
 
2796
2893
  block_constr.typing.add_context_for_body(node, context: block_constr.context)
2797
2894
 
2798
- params.params.each do |param|
2895
+ params.each_single_param do |param|
2799
2896
  _, block_constr = block_constr.synthesize(param.node, hint: param.type)
2800
2897
  end
2801
2898
 
@@ -2843,8 +2940,13 @@ module Steep
2843
2940
  Interface::Substitution.build([], [], self_type: block_constr.self_type)
2844
2941
  )
2845
2942
 
2846
- if expected_block_type = block_constr.block_context.body_type
2847
- type_vars = expected_block_type.free_variables
2943
+ if expected_block_type = block_constr.block_context!.body_type
2944
+ type_vars = expected_block_type.free_variables.filter_map do |var|
2945
+ case var
2946
+ when Symbol
2947
+ var
2948
+ end
2949
+ end
2848
2950
  subst = Interface::Substitution.build(type_vars, type_vars.map { AST::Builtin.any_type })
2849
2951
  expected_block_type = expected_block_type.subst(subst)
2850
2952
 
@@ -2879,7 +2981,7 @@ module Steep
2879
2981
  end
2880
2982
 
2881
2983
  def synthesize_children(node, skips: [])
2882
- skips = Set.new.compare_by_identity.merge(skips)
2984
+ skips = Set.new.compare_by_identity.merge(skips).delete(nil)
2883
2985
 
2884
2986
  # @type var constr: TypeConstruction
2885
2987
  constr = self
@@ -2902,8 +3004,11 @@ module Steep
2902
3004
  return false unless call.node.type == :send || call.node.type == :csend
2903
3005
  return false unless call.pure? || KNOWN_PURE_METHODS.superset?(Set.new(call.method_decls.map(&:method_name)))
2904
3006
 
2905
- [receiver, *arguments].all? do |node|
2906
- !node || value_node?(node) || context.type_env[node]
3007
+ argishes = [*arguments]
3008
+ argishes << receiver if receiver
3009
+
3010
+ argishes.all? do |node|
3011
+ value_node?(node) || context.type_env[node]
2907
3012
  end
2908
3013
  end
2909
3014
 
@@ -2944,7 +3049,11 @@ module Steep
2944
3049
  end
2945
3050
  else
2946
3051
  constr = constr.update_type_env do |env|
2947
- env.invalidate_pure_node(receiver)
3052
+ if receiver
3053
+ env.invalidate_pure_node(receiver)
3054
+ else
3055
+ env
3056
+ end
2948
3057
  end
2949
3058
  end
2950
3059
  end
@@ -2955,13 +3064,14 @@ module Steep
2955
3064
  call = call.with_return_type(optional_type)
2956
3065
  end
2957
3066
  else
2958
- errors = []
3067
+ errors = [] #: Array[Diagnostic::Ruby::Base]
2959
3068
 
2960
3069
  skips = [receiver]
2961
3070
  skips << node.children[0] if node.type == :block
2962
3071
 
2963
3072
  constr = synthesize_children(node, skips: skips)
2964
3073
  if block_params
3074
+ # @type var node: Parser::AST::Node & Parser::AST::_BlockNode
2965
3075
  block_annotations = source.annotations(block: node, factory: checker.factory, context: nesting)
2966
3076
 
2967
3077
  constr.type_block_without_hint(
@@ -2982,7 +3092,7 @@ module Steep
2982
3092
  )
2983
3093
  call = TypeInference::MethodCall::Error.new(
2984
3094
  node: node,
2985
- context: context.method_context,
3095
+ context: context.call_context,
2986
3096
  method_name: method_name,
2987
3097
  receiver_type: receiver_type,
2988
3098
  errors: errors
@@ -2991,7 +3101,7 @@ module Steep
2991
3101
 
2992
3102
  constr.add_call(call)
2993
3103
  else
2994
- skips = []
3104
+ skips = [] #: Array[Parser::AST::Node?]
2995
3105
  skips << receiver if receiver
2996
3106
  skips << node.children[0] if node.type == :block
2997
3107
  skips << block_params if block_params
@@ -2999,6 +3109,7 @@ module Steep
2999
3109
 
3000
3110
  constr = synthesize_children(node, skips: skips)
3001
3111
  if block_params
3112
+ # @type var node: Parser::AST::Node & Parser::AST::_BlockNode
3002
3113
  block_annotations = source.annotations(block: node, factory: checker.factory, context: nesting)
3003
3114
 
3004
3115
  constr.type_block_without_hint(
@@ -3023,7 +3134,7 @@ module Steep
3023
3134
  constr.add_call(
3024
3135
  TypeInference::MethodCall::NoMethodError.new(
3025
3136
  node: node,
3026
- context: context.method_context,
3137
+ context: context.call_context,
3027
3138
  method_name: method_name,
3028
3139
  receiver_type: receiver_type,
3029
3140
  error: Diagnostic::Ruby::NoMethod.new(node: node, method: method_name, type: interface&.type || receiver_type)
@@ -3079,7 +3190,7 @@ module Steep
3079
3190
  constr.add_call(
3080
3191
  TypeInference::MethodCall::Untyped.new(
3081
3192
  node: node,
3082
- context: context.method_context,
3193
+ context: context.call_context,
3083
3194
  method_name: method_name
3084
3195
  )
3085
3196
  )
@@ -3091,7 +3202,7 @@ module Steep
3091
3202
  interface: interface,
3092
3203
  receiver: receiver,
3093
3204
  receiver_type: receiver_type,
3094
- method_name: method_name,
3205
+ method_name: method_name,
3095
3206
  arguments: arguments,
3096
3207
  block_params: block_params,
3097
3208
  block_body: block_body,
@@ -3102,7 +3213,7 @@ module Steep
3102
3213
  constr.add_call(
3103
3214
  TypeInference::MethodCall::NoMethodError.new(
3104
3215
  node: node,
3105
- context: context.method_context,
3216
+ context: context.call_context,
3106
3217
  method_name: method_name,
3107
3218
  receiver_type: receiver_type,
3108
3219
  error: Diagnostic::Ruby::NoMethod.new(node: node, method: method_name, type: receiver_type)
@@ -3117,8 +3228,8 @@ module Steep
3117
3228
  def builder_config
3118
3229
  Interface::Builder::Config.new(
3119
3230
  self_type: self_type,
3120
- class_type: module_context!.module_type,
3121
- instance_type: module_context!.instance_type,
3231
+ class_type: module_context.module_type,
3232
+ instance_type: module_context.instance_type,
3122
3233
  variable_bounds: variable_context.upper_bounds
3123
3234
  )
3124
3235
  end
@@ -3173,7 +3284,7 @@ module Steep
3173
3284
  _, constr = add_typing(node, type: type)
3174
3285
  call = TypeInference::MethodCall::Special.new(
3175
3286
  node: node,
3176
- context: constr.context.method_context,
3287
+ context: constr.context.call_context,
3177
3288
  method_name: decl.method_name.method_name,
3178
3289
  receiver_type: receiver_type,
3179
3290
  actual_method_type: method_type.with(type: method_type.type.with(return_type: type)),
@@ -3197,7 +3308,7 @@ module Steep
3197
3308
  _, constr = add_typing(node, type: type)
3198
3309
  call = TypeInference::MethodCall::Special.new(
3199
3310
  node: node,
3200
- context: constr.context.method_context,
3311
+ context: constr.context.call_context,
3201
3312
  method_name: decl.method_name.method_name,
3202
3313
  receiver_type: receiver_type,
3203
3314
  actual_method_type: method_type.with(type: method_type.type.with(return_type: type)),
@@ -3214,7 +3325,7 @@ module Steep
3214
3325
  end
3215
3326
 
3216
3327
  def type_method_call(node, method_name:, receiver_type:, method:, arguments:, block_params:, block_body:, tapp:)
3217
- node_range = node.loc.expression.yield_self {|l| l.begin_pos..l.end_pos }
3328
+ node_range = node.loc.expression.to_range
3218
3329
 
3219
3330
  # @type var fails: Array[[TypeInference::MethodCall::t, TypeConstruction]]
3220
3331
  fails = []
@@ -3327,11 +3438,11 @@ module Steep
3327
3438
  end
3328
3439
  end
3329
3440
 
3330
- def type_check_args(args, constraints, errors)
3441
+ def type_check_args(method_name, args, constraints, errors)
3331
3442
  # @type var constr: TypeConstruction
3332
3443
  constr = self
3333
3444
 
3334
- es = args.each do |arg|
3445
+ forwarded_args, es = args.each do |arg|
3335
3446
  case arg
3336
3447
  when TypeInference::SendArgs::PositionalArgs::NodeParamPair
3337
3448
  _, constr = constr.type_check_argument(
@@ -3404,20 +3515,48 @@ module Steep
3404
3515
 
3405
3516
  when TypeInference::SendArgs::KeywordArgs::MissingKeyword
3406
3517
  # ignore
3518
+
3407
3519
  else
3408
- raise arg.inspect
3520
+ raise (_ = arg).inspect
3409
3521
  end
3410
3522
  end
3411
3523
 
3412
3524
  errors.push(*es)
3413
3525
 
3526
+ if forwarded_args
3527
+ method_name or raise "method_name cannot be nil if `forwarded_args` is given, because proc/block doesn't support `...` arg"
3528
+
3529
+ (params, block = context.method_context&.forward_arg_type) or raise
3530
+
3531
+ checker.with_context(self_type: self_type, instance_type: context.module_context.instance_type, class_type: context.module_context.module_type, constraints: constraints) do
3532
+ result = checker.check_method_params(
3533
+ :"... (argument forwarding)",
3534
+ Subtyping::Relation.new(
3535
+ sub_type: forwarded_args.params,
3536
+ super_type: params
3537
+ )
3538
+ )
3539
+
3540
+ if result.failure?
3541
+ errors.push(
3542
+ Diagnostic::Ruby::IncompatibleArgumentForwarding.new(
3543
+ method_name: method_name,
3544
+ node: forwarded_args.node,
3545
+ params_pair: [params, forwarded_args.params],
3546
+ result: result
3547
+ )
3548
+ )
3549
+ end
3550
+ end
3551
+ end
3552
+
3414
3553
  constr
3415
3554
  end
3416
3555
 
3417
3556
  def try_method_type(node, receiver_type:, method_name:, method_type:, arguments:, block_params:, block_body:, tapp:)
3418
3557
  constr = self
3419
3558
 
3420
- if tapp && type_args = tapp.types?(module_context!.nesting, checker.factory, [])
3559
+ if tapp && type_args = tapp.types?(module_context.nesting, checker.factory, [])
3421
3560
  type_arity = method_type.type_params.size
3422
3561
  type_param_names = method_type.type_params.map(&:name)
3423
3562
 
@@ -3477,7 +3616,7 @@ module Steep
3477
3616
  )
3478
3617
  end
3479
3618
 
3480
- type_params = []
3619
+ type_params = [] #: Array[Interface::TypeParam]
3481
3620
  type_param_names.clear
3482
3621
  else
3483
3622
  # Infer type application
@@ -3499,12 +3638,12 @@ module Steep
3499
3638
  constraints = Subtyping::Constraints.new(unknowns: type_params.map(&:name))
3500
3639
  ccontext = Subtyping::Constraints::Context.new(
3501
3640
  self_type: self_type,
3502
- instance_type: module_context!.instance_type,
3503
- class_type: module_context!.module_type,
3641
+ instance_type: module_context.instance_type,
3642
+ class_type: module_context.module_type,
3504
3643
  variance: variance
3505
3644
  )
3506
3645
 
3507
- upper_bounds = {}
3646
+ upper_bounds = {} #: Hash[Symbol, AST::Types::t]
3508
3647
 
3509
3648
  type_params.each do |param|
3510
3649
  if ub = param.upper_bound
@@ -3514,11 +3653,14 @@ module Steep
3514
3653
  end
3515
3654
 
3516
3655
  checker.push_variable_bounds(upper_bounds) do
3656
+ # @type block: [TypeInference::MethodCall::t, TypeConstruction]
3657
+
3517
3658
  # @type var errors: Array[Diagnostic::Ruby::Base]
3518
3659
  errors = []
3519
3660
 
3520
3661
  args = TypeInference::SendArgs.new(node: node, arguments: arguments, type: method_type)
3521
3662
  constr = constr.type_check_args(
3663
+ method_name,
3522
3664
  args,
3523
3665
  constraints,
3524
3666
  errors
@@ -3526,6 +3668,8 @@ module Steep
3526
3668
 
3527
3669
  if block_params
3528
3670
  # block is given
3671
+ # @type var node: Parser::AST::Node & Parser::AST::_BlockNode
3672
+
3529
3673
  block_annotations = source.annotations(block: node, factory: checker.factory, context: nesting)
3530
3674
  block_params_ = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
3531
3675
 
@@ -3596,12 +3740,14 @@ module Steep
3596
3740
  )
3597
3741
  }
3598
3742
 
3743
+ method_type.block or raise
3744
+
3599
3745
  if solved
3600
3746
  # Ready for type check the body of the block
3601
3747
  block_constr = block_constr.update_type_env {|env| env.subst(s) }
3602
3748
  block_constr = block_constr.update_context {|context|
3603
3749
  context.with(
3604
- self_type: method_type.block&.self_type || context.self_type,
3750
+ self_type: method_type.block.self_type || context.self_type,
3605
3751
  type_env: context.type_env.subst(s),
3606
3752
  block_context: context.block_context&.subst(s),
3607
3753
  break_context: context.break_context&.subst(s)
@@ -3708,6 +3854,21 @@ module Steep
3708
3854
  arg = args.block_pass_arg
3709
3855
 
3710
3856
  case
3857
+ when forwarded_args_node = args.forwarded_args_node
3858
+ (_, block = method_context!.forward_arg_type) or raise
3859
+
3860
+ method_block_type = method_type.block&.to_proc_type || AST::Builtin.nil_type
3861
+ forwarded_block_type = block&.to_proc_type || AST::Builtin.nil_type
3862
+
3863
+ if result = constr.no_subtyping?(sub_type: forwarded_block_type, super_type: method_block_type)
3864
+ errors << Diagnostic::Ruby::IncompatibleArgumentForwarding.new(
3865
+ method_name: method_name,
3866
+ node: forwarded_args_node,
3867
+ block_pair: [block, method_type.block],
3868
+ result: result
3869
+ )
3870
+ end
3871
+
3711
3872
  when arg.compatible?
3712
3873
  if arg.node
3713
3874
  # Block pass (&block) is given
@@ -3770,7 +3931,10 @@ module Steep
3770
3931
  )
3771
3932
 
3772
3933
  when arg.unexpected_block?
3773
- # Unexpected block is given
3934
+ # Unexpected block pass node is given
3935
+
3936
+ arg.node or raise
3937
+
3774
3938
  method_type, solved, _ = apply_solution(errors, node: node, method_type: method_type) {
3775
3939
  constraints.solution(checker, variables: method_type.free_variables, context: ccontext)
3776
3940
  }
@@ -3791,7 +3955,7 @@ module Steep
3791
3955
  call = if errors.empty?
3792
3956
  TypeInference::MethodCall::Typed.new(
3793
3957
  node: node,
3794
- context: context.method_context,
3958
+ context: context.call_context,
3795
3959
  receiver_type: receiver_type,
3796
3960
  method_name: method_name,
3797
3961
  actual_method_type: method_type,
@@ -3801,7 +3965,7 @@ module Steep
3801
3965
  else
3802
3966
  TypeInference::MethodCall::Error.new(
3803
3967
  node: node,
3804
- context: context.method_context,
3968
+ context: context.call_context,
3805
3969
  receiver_type: receiver_type,
3806
3970
  method_name: method_name,
3807
3971
  return_type: return_type || method_type.type.return_type,
@@ -3871,7 +4035,7 @@ module Steep
3871
4035
 
3872
4036
  block_type = block_constr.synthesize_block(node: node, block_type_hint: nil, block_body: block_body)
3873
4037
 
3874
- if expected_block_type = block_constr.block_context.body_type
4038
+ if expected_block_type = block_constr.block_context!.body_type
3875
4039
  block_constr.check_relation(sub_type: block_type, super_type: expected_block_type).else do |result|
3876
4040
  Diagnostic::Ruby::BlockBodyTypeMismatch.new(
3877
4041
  node: node,
@@ -3947,8 +4111,7 @@ module Steep
3947
4111
 
3948
4112
  param_types_hash.delete_if {|name, _| SPECIAL_LVAR_NAMES.include?(name) }
3949
4113
 
3950
- param_types = param_types_hash.each.with_object({}) do |pair, hash|
3951
- # @type var hash: Hash[Symbol, [AST::Types::t, AST::Types::t?]]
4114
+ param_types = param_types_hash.each.with_object({}) do |pair, hash| #$ Hash[Symbol, [AST::Types::t, AST::Types::t?]]
3952
4115
  name, type = pair
3953
4116
  hash[name] = [type, nil]
3954
4117
  end
@@ -4034,7 +4197,7 @@ module Steep
4034
4197
 
4035
4198
  def synthesize_block(node:, block_type_hint:, block_body:)
4036
4199
  if block_body
4037
- body_type, _, context = synthesize(block_body, hint: block_context.body_type || block_type_hint)
4200
+ body_type, _, context = synthesize(block_body, hint: block_context&.body_type || block_type_hint)
4038
4201
 
4039
4202
  range = block_body.loc.expression.end_pos..node.loc.end.begin_pos
4040
4203
  typing.add_context(range, context: context)
@@ -4055,7 +4218,7 @@ module Steep
4055
4218
 
4056
4219
  def union_type(*types)
4057
4220
  raise if types.empty?
4058
- AST::Types::Union.build(types: types)
4221
+ AST::Types::Union.build(types: types.compact)
4059
4222
  end
4060
4223
 
4061
4224
  def union_type_unify(*types)
@@ -4104,14 +4267,18 @@ module Steep
4104
4267
  return unless member_decl_count == 1
4105
4268
 
4106
4269
  expected_instance_method_names = (module_context.instance_definition&.methods || {}).each.with_object(Set[]) do |(name, method), set|
4107
- if method.implemented_in == module_context.instance_definition.type_name
4108
- set << name
4270
+ if method.implemented_in
4271
+ if method.implemented_in == module_context.instance_definition&.type_name
4272
+ set << name
4273
+ end
4109
4274
  end
4110
4275
  end
4111
4276
  expected_module_method_names = (module_context.module_definition&.methods || {}).each.with_object(Set[]) do |(name, method), set|
4112
4277
  if name != :new
4113
- if method.implemented_in == module_context.module_definition.type_name
4114
- set << name
4278
+ if method.implemented_in
4279
+ if method.implemented_in == module_context.module_definition&.type_name
4280
+ set << name
4281
+ end
4115
4282
  end
4116
4283
  end
4117
4284
  end
@@ -4188,18 +4355,20 @@ module Steep
4188
4355
  end
4189
4356
 
4190
4357
  def namespace_module?(node)
4191
- nodes = case node.type
4192
- when :class, :module
4193
- node.children.last&.yield_self {|child|
4194
- if child.type == :begin
4195
- child.children
4196
- else
4197
- [child]
4198
- end
4199
- } || []
4200
- else
4201
- return false
4202
- end
4358
+ # @type var nodes: Array[Parser::AST::Node]
4359
+ nodes =
4360
+ case node.type
4361
+ when :class, :module
4362
+ node.children.last&.yield_self {|child|
4363
+ if child.type == :begin
4364
+ child.children
4365
+ else
4366
+ [child]
4367
+ end
4368
+ } || []
4369
+ else
4370
+ return false
4371
+ end
4203
4372
 
4204
4373
  !nodes.empty? && nodes.all? {|child| child.type == :class || child.type == :module}
4205
4374
  end
@@ -4228,18 +4397,19 @@ module Steep
4228
4397
  end
4229
4398
 
4230
4399
  def select_flatten_types(type, &block)
4231
- types = flatten_union(deep_expand_alias(type))
4400
+ types = flatten_union(deep_expand_alias(type) || type)
4232
4401
  types.select(&block)
4233
4402
  end
4234
4403
 
4235
4404
  def partition_flatten_types(type, &block)
4236
- types = flatten_union(deep_expand_alias(type))
4405
+ types = flatten_union(deep_expand_alias(type) || type)
4237
4406
  types.partition(&block)
4238
4407
  end
4239
4408
 
4240
4409
  def flatten_array_elements(type)
4241
- flatten_union(deep_expand_alias(type)).flat_map do |type|
4410
+ flatten_union(deep_expand_alias(type) || type).flat_map do |type|
4242
4411
  if AST::Builtin::Array.instance_type?(type)
4412
+ # @type var type: AST::Types::Name::Instance
4243
4413
  type.args
4244
4414
  else
4245
4415
  [type]
@@ -4248,7 +4418,12 @@ module Steep
4248
4418
  end
4249
4419
 
4250
4420
  def expand_alias(type, &block)
4251
- checker.factory.expand_alias(type, &block)
4421
+ typ = checker.factory.expand_alias(type)
4422
+ if block
4423
+ yield(typ)
4424
+ else
4425
+ typ
4426
+ end
4252
4427
  end
4253
4428
 
4254
4429
  def test_literal_type(literal, hint)
@@ -4296,9 +4471,8 @@ module Steep
4296
4471
  def try_tuple_type(array_node, hint)
4297
4472
  raise unless array_node.type == :array
4298
4473
 
4299
- constr = self
4300
- # @type var element_types: Array[AST::Types::t]
4301
- element_types = []
4474
+ constr = self #: TypeConstruction
4475
+ element_types = [] #: Array[AST::Types::t]
4302
4476
 
4303
4477
  array_node.children.each_with_index do |child, index|
4304
4478
  return if child.type == :splat
@@ -4380,11 +4554,14 @@ module Steep
4380
4554
  instance_type: module_context.instance_type,
4381
4555
  class_type: module_context.module_type
4382
4556
  )
4383
- subst = constraints.solution(
4384
- checker,
4385
- variables: type.free_variables + [var.name],
4386
- context: context
4387
- )
4557
+
4558
+ variables = (type.free_variables + [var.name]).filter_map do |name|
4559
+ case name
4560
+ when Symbol
4561
+ name
4562
+ end
4563
+ end
4564
+ subst = constraints.solution(checker, variables: variables, context: context)
4388
4565
 
4389
4566
  type.subst(subst)
4390
4567
  end
@@ -4393,8 +4570,8 @@ module Steep
4393
4570
  def try_array_type(node, hint)
4394
4571
  element_hint = hint ? hint.args[0] : nil
4395
4572
 
4396
- constr = self
4397
- element_types = []
4573
+ constr = self #: TypeConstruction
4574
+ element_types = [] #: Array[AST::Types::t]
4398
4575
 
4399
4576
  each_child_node(node) do |child|
4400
4577
  case child.type
@@ -4425,24 +4602,24 @@ module Steep
4425
4602
  def type_hash_record(hash_node, record_type)
4426
4603
  raise unless hash_node.type == :hash || hash_node.type == :kwargs
4427
4604
 
4428
- constr = self
4605
+ constr = self #: TypeConstruction
4429
4606
 
4430
4607
  if record_type
4431
4608
  hints = record_type.elements.dup
4432
4609
  else
4433
- hints = {}
4610
+ hints = {} #: Hash[AST::Types::Record::key, AST::Types::t]
4434
4611
  end
4435
4612
 
4436
- elems = {}
4613
+ elems = {} #: Hash[AST::Types::Record::key, AST::Types::t]
4437
4614
 
4438
4615
  each_child_node(hash_node) do |child|
4439
4616
  if child.type == :pair
4440
4617
  case child.children[0].type
4441
4618
  when :sym, :str, :int
4442
- key_node = child.children[0]
4443
- value_node = child.children[1]
4619
+ key_node = child.children[0] #: Parser::AST::Node
4620
+ value_node = child.children[1] #: Parser::AST::Node
4444
4621
 
4445
- key = key_node.children[0]
4622
+ key = key_node.children[0] #: String | Symbol | Integer
4446
4623
 
4447
4624
  _, constr = constr.synthesize(key_node, hint: AST::Types::Literal.new(value: key))
4448
4625
 
@@ -4471,14 +4648,10 @@ module Steep
4471
4648
  constr.add_typing(hash_node, type: type)
4472
4649
  end
4473
4650
 
4474
- # Give hash_node a type based on hint.
4475
- #
4476
- # * When hint is Record type, it may have record type.
4477
- # * When hint is union type, it tries recursively with the union cases.
4478
- # * Otherwise, it tries to be a hash instance.
4479
- #
4480
4651
  def type_hash(hash_node, hint:)
4481
- hint = deep_expand_alias(hint)
4652
+ if hint
4653
+ hint = deep_expand_alias(hint)
4654
+ end
4482
4655
  range = hash_node.loc.expression.yield_self {|l| l.begin_pos..l.end_pos }
4483
4656
 
4484
4657
  case hint
@@ -4499,10 +4672,11 @@ module Steep
4499
4672
  end
4500
4673
  end
4501
4674
 
4502
- key_types = []
4503
- value_types = []
4675
+ key_types = [] #: Array[AST::Types::t]
4676
+ value_types = [] #: Array[AST::Types::t]
4504
4677
 
4505
- if AST::Builtin::Hash.instance_type?(hint)
4678
+ if hint && AST::Builtin::Hash.instance_type?(hint)
4679
+ # @type var hint: AST::Types::Name::Instance
4506
4680
  key_hint, value_hint = hint.args
4507
4681
  end
4508
4682
 
@@ -4511,7 +4685,7 @@ module Steep
4511
4685
  value_hint || AST::Builtin.any_type
4512
4686
  )
4513
4687
 
4514
- constr = self
4688
+ constr = self #: TypeConstruction
4515
4689
 
4516
4690
  if hash_node.children.empty?
4517
4691
  key_types << key_hint if key_hint
@@ -4528,14 +4702,13 @@ module Steep
4528
4702
  value_types << value_type
4529
4703
  when :kwsplat
4530
4704
  bypass_splat(elem) do |elem_|
4531
- pair = constr.synthesize(elem_, hint: hint_hash)
4532
-
4533
- if AST::Builtin::Hash.instance_type?(pair.type)
4534
- key_types << pair.type.args[0]
4535
- value_types << pair.type.args[1]
4705
+ constr.synthesize(elem_, hint: hint_hash).tap do |(type, _)|
4706
+ if AST::Builtin::Hash.instance_type?(type)
4707
+ # @type var type: AST::Types::Name::Instance
4708
+ key_types << type.args[0]
4709
+ value_types << type.args[1]
4710
+ end
4536
4711
  end
4537
-
4538
- pair
4539
4712
  end
4540
4713
  else
4541
4714
  raise
@@ -4573,7 +4746,7 @@ module Steep
4573
4746
 
4574
4747
  def save_typing
4575
4748
  typing.save!
4576
- with_new_typing(typing.parent)
4749
+ with_new_typing(typing.parent || raise)
4577
4750
  end
4578
4751
 
4579
4752
  def extract_outermost_call(node, var_name)