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

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