steep 1.4.0.dev.2 → 1.4.0.dev.4

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 (81) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +1 -2
  3. data/Gemfile +1 -1
  4. data/Gemfile.lock +9 -11
  5. data/Gemfile.steep +1 -2
  6. data/Gemfile.steep.lock +11 -14
  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 +80 -6
  15. data/lib/steep/drivers/check.rb +4 -4
  16. data/lib/steep/interface/block.rb +10 -0
  17. data/lib/steep/interface/builder.rb +3 -3
  18. data/lib/steep/method_name.rb +8 -0
  19. data/lib/steep/module_helper.rb +13 -11
  20. data/lib/steep/path_helper.rb +4 -0
  21. data/lib/steep/server/interaction_worker.rb +197 -230
  22. data/lib/steep/server/lsp_formatter.rb +308 -154
  23. data/lib/steep/server/master.rb +4 -1
  24. data/lib/steep/services/completion_provider.rb +140 -103
  25. data/lib/steep/services/hover_provider/rbs.rb +37 -32
  26. data/lib/steep/services/signature_help_provider.rb +108 -0
  27. data/lib/steep/services/type_name_completion.rb +165 -0
  28. data/lib/steep/source.rb +1 -0
  29. data/lib/steep/type_construction.rb +460 -266
  30. data/lib/steep/type_inference/block_params.rb +13 -0
  31. data/lib/steep/type_inference/context.rb +3 -3
  32. data/lib/steep/type_inference/method_call.rb +1 -1
  33. data/lib/steep/type_inference/method_params.rb +42 -16
  34. data/lib/steep/type_inference/send_args.rb +80 -51
  35. data/lib/steep/type_inference/type_env.rb +12 -4
  36. data/lib/steep/version.rb +1 -1
  37. data/lib/steep.rb +2 -0
  38. data/rbs_collection.steep.lock.yaml +0 -28
  39. data/rbs_collection.steep.yaml +10 -9
  40. data/sample/Steepfile +2 -0
  41. data/sample/lib/conference.rb +12 -0
  42. data/sample/sig/conference.rbs +5 -0
  43. data/sig/shims/language-server_protocol.rbs +277 -0
  44. data/sig/shims/parser/nodes.rbs +37 -0
  45. data/sig/shims/parser.rbs +4 -0
  46. data/sig/shims/string.rbs +4 -0
  47. data/sig/steep/ast/types/factory.rbs +10 -8
  48. data/sig/steep/diagnostic/lsp_formatter.rbs +1 -1
  49. data/sig/steep/diagnostic/ruby.rbs +38 -2
  50. data/sig/steep/drivers/check.rbs +1 -1
  51. data/sig/steep/drivers/checkfile.rbs +1 -1
  52. data/sig/steep/drivers/diagnostic_printer.rbs +1 -1
  53. data/sig/steep/drivers/watch.rbs +1 -1
  54. data/sig/steep/index/signature_symbol_provider.rbs +1 -1
  55. data/sig/steep/interface/block.rbs +2 -0
  56. data/sig/steep/interface/builder.rbs +5 -3
  57. data/sig/steep/interface/method_type.rbs +5 -3
  58. data/sig/steep/method_name.rbs +5 -1
  59. data/sig/steep/module_helper.rbs +9 -0
  60. data/sig/steep/path_helper.rbs +3 -1
  61. data/sig/steep/server/base_worker.rbs +1 -1
  62. data/sig/steep/server/interaction_worker.rbs +52 -17
  63. data/sig/steep/server/lsp_formatter.rbs +43 -18
  64. data/sig/steep/server/master.rbs +1 -1
  65. data/sig/steep/server/type_check_worker.rbs +7 -5
  66. data/sig/steep/server/worker_process.rbs +6 -4
  67. data/sig/steep/services/completion_provider.rbs +106 -28
  68. data/sig/steep/services/hover_provider/rbs.rbs +13 -9
  69. data/sig/steep/services/signature_help_provider.rbs +39 -0
  70. data/sig/steep/services/type_name_completion.rbs +122 -0
  71. data/sig/steep/type_construction.rbs +99 -30
  72. data/sig/steep/type_inference/block_params.rbs +4 -0
  73. data/sig/steep/type_inference/context.rbs +70 -22
  74. data/sig/steep/type_inference/method_call.rbs +1 -1
  75. data/sig/steep/type_inference/method_params.rbs +43 -24
  76. data/sig/steep/type_inference/multiple_assignment.rbs +1 -1
  77. data/sig/steep/type_inference/send_args.rbs +19 -5
  78. data/sig/steep/typing.rbs +8 -3
  79. data/smoke/diagnostics/test_expectations.yml +1 -0
  80. data/steep.gemspec +0 -1
  81. metadata +12 -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,19 +1902,21 @@ 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
 
1914
+ # @type var tests: Array[Parser::AST::Node]
1915
+ # @type var body: Parser::AST::Node?
1897
1916
  *tests, body = when_clause.children
1898
1917
 
1899
1918
  tests.each do |test|
1900
- test_type, condition_constr = condition_constr.synthesize(test, condition: true).to_ary
1919
+ test_type, condition_constr = condition_constr.synthesize(test, condition: true)
1901
1920
  truthy_env, falsy_env = interpreter.eval(env: condition_constr.context.type_env, node: test)
1902
1921
 
1903
1922
  condition_constr = condition_constr.update_type_env { falsy_env }
@@ -1975,7 +1994,7 @@ module Steep
1975
1994
  end
1976
1995
 
1977
1996
  resbody_construction = body_constr.for_branch(resbody).update_type_env do |env|
1978
- assignments = {}
1997
+ assignments = {} #: Hash[Symbol, AST::Types::t]
1979
1998
 
1980
1999
  case
1981
2000
  when exn_classes && var_name && exn_types
@@ -2025,8 +2044,12 @@ module Steep
2025
2044
  klasses, asgn, body = node.children
2026
2045
  synthesize(klasses) if klasses
2027
2046
  synthesize(asgn) if asgn
2028
- body_type = synthesize(body, hint: hint).type if body
2029
- add_typing(node, type: body_type)
2047
+ if body
2048
+ body_type = synthesize(body, hint: hint).type
2049
+ add_typing(node, type: body_type)
2050
+ else
2051
+ add_typing(node, type: AST::Builtin.nil_type)
2052
+ end
2030
2053
  end
2031
2054
 
2032
2055
  when :ensure
@@ -2034,7 +2057,11 @@ module Steep
2034
2057
  body, ensure_body = node.children
2035
2058
  body_type = synthesize(body).type if body
2036
2059
  synthesize(ensure_body) if ensure_body
2037
- add_typing(node, type: union_type(body_type))
2060
+ if body_type
2061
+ add_typing(node, type: body_type)
2062
+ else
2063
+ add_typing(node, type: AST::Builtin.nil_type)
2064
+ end
2038
2065
  end
2039
2066
 
2040
2067
  when :masgn
@@ -2054,13 +2081,13 @@ module Steep
2054
2081
  if method_type = (each.method_types || []).find {|type| type.block && type.block.type.params.first_param }
2055
2082
  if block = method_type.block
2056
2083
  if first_param = block.type.params.first_param
2057
- var_type = first_param.type
2084
+ var_type = first_param.type #: AST::Types::t
2058
2085
  end
2059
2086
  end
2060
2087
  end
2061
2088
  end
2062
2089
  end
2063
- var_name = asgn.children[0]
2090
+ var_name = asgn.children[0] #: Symbol
2064
2091
 
2065
2092
  if var_type
2066
2093
  if body
@@ -2106,8 +2133,14 @@ module Steep
2106
2133
  body_env, exit_env = truthy_env, falsy_env
2107
2134
  when :until
2108
2135
  exit_env, body_env = truthy_env, falsy_env
2136
+ else
2137
+ raise
2109
2138
  end
2110
2139
 
2140
+ body_env or raise
2141
+ exit_env or raise
2142
+
2143
+
2111
2144
  if body
2112
2145
  pins = body_env.pin_local_variables(nil)
2113
2146
  body_env = body_env.merge(local_variable_types: pins)
@@ -2131,7 +2164,7 @@ module Steep
2131
2164
  yield_self do
2132
2165
  cond, body = node.children
2133
2166
 
2134
- _, cond_constr, = synthesize(cond).to_ary
2167
+ _, cond_constr, = synthesize(cond)
2135
2168
 
2136
2169
  if body
2137
2170
  for_loop =
@@ -2146,7 +2179,7 @@ module Steep
2146
2179
 
2147
2180
  add_typing(node, type: AST::Builtin.nil_type, constr: constr)
2148
2181
  else
2149
- add_typing(node, type: AST::Builtin.nil_type, constr: cond_pair.constr)
2182
+ add_typing(node, type: AST::Builtin.nil_type, constr: cond_constr)
2150
2183
  end
2151
2184
  end
2152
2185
 
@@ -2155,12 +2188,12 @@ module Steep
2155
2188
 
2156
2189
  constr = self
2157
2190
  begin_type, constr = if begin_node
2158
- constr.synthesize(begin_node)
2191
+ constr.synthesize(begin_node).to_ary
2159
2192
  else
2160
2193
  [AST::Builtin.nil_type, constr]
2161
2194
  end
2162
2195
  end_type, constr = if end_node
2163
- constr.synthesize(end_node)
2196
+ constr.synthesize(end_node).to_ary
2164
2197
  else
2165
2198
  [AST::Builtin.nil_type, constr]
2166
2199
  end
@@ -2298,14 +2331,18 @@ module Steep
2298
2331
  Steep.logger.error "Passing multiple args through Symbol#to_proc is not supported yet"
2299
2332
  end
2300
2333
  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])
2334
+ if block_type = method_context!.block_type
2335
+ type = AST::Types::Proc.new(
2336
+ type: block_type.type,
2337
+ location: nil,
2338
+ block: nil,
2339
+ self_type: block_type.self_type
2340
+ )
2341
+ if block_type.optional?
2342
+ type = AST::Types::Union.build(types: [type, AST::Builtin.nil_type])
2343
+ end
2344
+ else
2345
+ type = AST::Builtin.nil_type
2309
2346
  end
2310
2347
  end
2311
2348
 
@@ -2328,9 +2365,12 @@ module Steep
2328
2365
 
2329
2366
  type, constr = synthesize(rhs, hint: hint)
2330
2367
 
2331
- var_type = if module_context&.class_variables
2332
- module_context.class_variables[name]&.yield_self {|ty| checker.factory.type(ty) }
2333
- end
2368
+ var_type =
2369
+ if class_vars = module_context.class_variables
2370
+ if ty = class_vars[name]
2371
+ checker.factory.type(ty)
2372
+ end
2373
+ end
2334
2374
 
2335
2375
  if var_type
2336
2376
  result = constr.check_relation(sub_type: type, super_type: var_type)
@@ -2352,10 +2392,13 @@ module Steep
2352
2392
  end
2353
2393
 
2354
2394
  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
2395
+ name = node.children[0] #: Symbol
2396
+ var_type =
2397
+ if cvs = module_context.class_variables
2398
+ if ty = cvs[name]
2399
+ checker.factory.type(ty)
2400
+ end
2401
+ end
2359
2402
 
2360
2403
  if var_type
2361
2404
  add_typing node, type: var_type
@@ -2383,7 +2426,7 @@ module Steep
2383
2426
  end
2384
2427
 
2385
2428
  when :args
2386
- constr = self
2429
+ constr = self #: TypeConstruction
2387
2430
 
2388
2431
  each_child_node(node) do |child|
2389
2432
  _, constr = constr.synthesize(child)
@@ -2396,7 +2439,7 @@ module Steep
2396
2439
  # @type var as_type: AST::Node::TypeAssertion
2397
2440
  asserted_node, as_type = node.children
2398
2441
 
2399
- if type = as_type.type?(module_context!.nesting, checker.factory, [])
2442
+ if type = as_type.type?(module_context.nesting, checker.factory, [])
2400
2443
  actual_type, constr = synthesize(asserted_node, hint: type)
2401
2444
 
2402
2445
  if no_subtyping?(sub_type: type, super_type: actual_type) && no_subtyping?(sub_type: actual_type, super_type: type)
@@ -2426,6 +2469,9 @@ module Steep
2426
2469
  constr.add_typing(node, type: type)
2427
2470
  end
2428
2471
 
2472
+ when :forwarded_args, :forward_arg
2473
+ add_typing(node, type: AST::Builtin.any_type)
2474
+
2429
2475
  else
2430
2476
  typing.add_error(Diagnostic::Ruby::UnsupportedSyntax.new(node: node))
2431
2477
  add_typing(node, type: AST::Builtin.any_type)
@@ -2439,7 +2485,7 @@ module Steep
2439
2485
  end
2440
2486
  rescue RBS::BaseError => exn
2441
2487
  Steep.logger.warn { "Unexpected RBS error: #{exn.message}" }
2442
- exn.backtrace.each {|loc| Steep.logger.warn " #{loc}" }
2488
+ exn.backtrace&.each {|loc| Steep.logger.warn " #{loc}" }
2443
2489
  typing.add_error(Diagnostic::Ruby::UnexpectedError.new(node: node, error: exn))
2444
2490
  type_any_rec(node)
2445
2491
  rescue StandardError => exn
@@ -2466,7 +2512,7 @@ module Steep
2466
2512
  when :send
2467
2513
  yield_self do
2468
2514
  if self_class?(node)
2469
- module_type = expand_alias(module_context!.module_type)
2515
+ module_type = expand_alias(module_context.module_type)
2470
2516
  type = if module_type.is_a?(AST::Types::Name::Singleton)
2471
2517
  AST::Types::Name::Singleton.new(name: module_type.name)
2472
2518
  else
@@ -2482,7 +2528,7 @@ module Steep
2482
2528
  yield_self do
2483
2529
  send_type, constr =
2484
2530
  if self_class?(node)
2485
- module_type = expand_alias(module_context!.module_type)
2531
+ module_type = expand_alias(module_context.module_type)
2486
2532
  type = if module_type.is_a?(AST::Types::Name::Singleton)
2487
2533
  AST::Types::Name::Singleton.new(name: module_type.name)
2488
2534
  else
@@ -2501,6 +2547,7 @@ module Steep
2501
2547
  yield_self do
2502
2548
  send_node, params, body = node.children
2503
2549
  if send_node.type == :lambda
2550
+ # @type var node: Parser::AST::Node & Parser::AST::_BlockNode
2504
2551
  type_lambda(node, params_node: params, body_node: body, type_hint: hint)
2505
2552
  else
2506
2553
  type_send(node, send_node: send_node, block_params: params, block_body: body, unwrap: send_node.type == :csend, tapp: tapp)
@@ -2519,6 +2566,7 @@ module Steep
2519
2566
  params = Parser::AST::Node.new(:args, arg_nodes)
2520
2567
 
2521
2568
  if send_node.type == :lambda
2569
+ # @type var node: Parser::AST::Node & Parser::AST::_BlockNode
2522
2570
  type_lambda(node, params_node: params, body_node: body, type_hint: hint)
2523
2571
  else
2524
2572
  type_send(node, send_node: send_node, block_params: params, block_body: body, unwrap: send_node.type == :csend, tapp: tapp)
@@ -2632,7 +2680,7 @@ module Steep
2632
2680
  hint = masgn.hint_for_mlhs(lhs, context.type_env)
2633
2681
 
2634
2682
  rhs_type, lhs_constr = try_tuple_type!(rhs, hint: hint).to_ary
2635
- rhs_type = deep_expand_alias(rhs_type)
2683
+ rhs_type = deep_expand_alias(rhs_type) || rhs_type
2636
2684
 
2637
2685
  falsys, truthys = partition_flatten_types(rhs_type) do |type|
2638
2686
  type.is_a?(AST::Types::Nil) || (type.is_a?(AST::Types::Literal) && type.value == false)
@@ -2680,6 +2728,57 @@ module Steep
2680
2728
  constr.add_typing(node, type: truthy_rhs_type)
2681
2729
  end
2682
2730
 
2731
+ def synthesize_constant_decl(node, parent_node, constant_name, &block)
2732
+ const_name = module_name_from_node(parent_node, constant_name)
2733
+
2734
+ if const_name && type = context.type_env.annotated_constant(const_name)
2735
+ # const-type annotation wins
2736
+ if node
2737
+ constr = synthesize_children(node)
2738
+ type, constr = constr.add_typing(node, type: type)
2739
+ [type, constr, nil]
2740
+ else
2741
+ [type, self, nil]
2742
+ end
2743
+ else
2744
+ if parent_node
2745
+ synthesize_constant(node, parent_node, constant_name, &block)
2746
+ else
2747
+ if nesting
2748
+ if parent_nesting = nesting[1]
2749
+ if constant = context.type_env.constant_env.resolver.table.children(parent_nesting)&.fetch(constant_name, nil)
2750
+ return [checker.factory.type(constant.type), self, constant.name]
2751
+ end
2752
+ end
2753
+
2754
+ if block_given?
2755
+ yield
2756
+ else
2757
+ if node
2758
+ typing.add_error(
2759
+ Diagnostic::Ruby::UnknownConstant.new(node: node, name: constant_name)
2760
+ )
2761
+ end
2762
+ end
2763
+
2764
+ constr = self #: TypeConstruction
2765
+ if node
2766
+ _, constr = add_typing(node, type: AST::Builtin.any_type)
2767
+ end
2768
+
2769
+ [
2770
+ AST::Builtin.any_type,
2771
+ constr,
2772
+ nil
2773
+ ]
2774
+ else
2775
+ # No neesting
2776
+ synthesize_constant(node, nil, constant_name, &block)
2777
+ end
2778
+ end
2779
+ end
2780
+ end
2781
+
2683
2782
  def synthesize_constant(node, parent_node, constant_name)
2684
2783
  const_name = module_name_from_node(parent_node, constant_name)
2685
2784
 
@@ -2795,7 +2894,7 @@ module Steep
2795
2894
 
2796
2895
  block_constr.typing.add_context_for_body(node, context: block_constr.context)
2797
2896
 
2798
- params.params.each do |param|
2897
+ params.each_single_param do |param|
2799
2898
  _, block_constr = block_constr.synthesize(param.node, hint: param.type)
2800
2899
  end
2801
2900
 
@@ -2843,8 +2942,13 @@ module Steep
2843
2942
  Interface::Substitution.build([], [], self_type: block_constr.self_type)
2844
2943
  )
2845
2944
 
2846
- if expected_block_type = block_constr.block_context.body_type
2847
- type_vars = expected_block_type.free_variables
2945
+ if expected_block_type = block_constr.block_context!.body_type
2946
+ type_vars = expected_block_type.free_variables.filter_map do |var|
2947
+ case var
2948
+ when Symbol
2949
+ var
2950
+ end
2951
+ end
2848
2952
  subst = Interface::Substitution.build(type_vars, type_vars.map { AST::Builtin.any_type })
2849
2953
  expected_block_type = expected_block_type.subst(subst)
2850
2954
 
@@ -2879,7 +2983,7 @@ module Steep
2879
2983
  end
2880
2984
 
2881
2985
  def synthesize_children(node, skips: [])
2882
- skips = Set.new.compare_by_identity.merge(skips)
2986
+ skips = Set.new.compare_by_identity.merge(skips).delete(nil)
2883
2987
 
2884
2988
  # @type var constr: TypeConstruction
2885
2989
  constr = self
@@ -2902,8 +3006,11 @@ module Steep
2902
3006
  return false unless call.node.type == :send || call.node.type == :csend
2903
3007
  return false unless call.pure? || KNOWN_PURE_METHODS.superset?(Set.new(call.method_decls.map(&:method_name)))
2904
3008
 
2905
- [receiver, *arguments].all? do |node|
2906
- !node || value_node?(node) || context.type_env[node]
3009
+ argishes = [*arguments]
3010
+ argishes << receiver if receiver
3011
+
3012
+ argishes.all? do |node|
3013
+ value_node?(node) || context.type_env[node]
2907
3014
  end
2908
3015
  end
2909
3016
 
@@ -2944,7 +3051,11 @@ module Steep
2944
3051
  end
2945
3052
  else
2946
3053
  constr = constr.update_type_env do |env|
2947
- env.invalidate_pure_node(receiver)
3054
+ if receiver
3055
+ env.invalidate_pure_node(receiver)
3056
+ else
3057
+ env
3058
+ end
2948
3059
  end
2949
3060
  end
2950
3061
  end
@@ -2955,13 +3066,14 @@ module Steep
2955
3066
  call = call.with_return_type(optional_type)
2956
3067
  end
2957
3068
  else
2958
- errors = []
3069
+ errors = [] #: Array[Diagnostic::Ruby::Base]
2959
3070
 
2960
3071
  skips = [receiver]
2961
3072
  skips << node.children[0] if node.type == :block
2962
3073
 
2963
3074
  constr = synthesize_children(node, skips: skips)
2964
3075
  if block_params
3076
+ # @type var node: Parser::AST::Node & Parser::AST::_BlockNode
2965
3077
  block_annotations = source.annotations(block: node, factory: checker.factory, context: nesting)
2966
3078
 
2967
3079
  constr.type_block_without_hint(
@@ -2982,7 +3094,7 @@ module Steep
2982
3094
  )
2983
3095
  call = TypeInference::MethodCall::Error.new(
2984
3096
  node: node,
2985
- context: context.method_context,
3097
+ context: context.call_context,
2986
3098
  method_name: method_name,
2987
3099
  receiver_type: receiver_type,
2988
3100
  errors: errors
@@ -2991,7 +3103,7 @@ module Steep
2991
3103
 
2992
3104
  constr.add_call(call)
2993
3105
  else
2994
- skips = []
3106
+ skips = [] #: Array[Parser::AST::Node?]
2995
3107
  skips << receiver if receiver
2996
3108
  skips << node.children[0] if node.type == :block
2997
3109
  skips << block_params if block_params
@@ -2999,6 +3111,7 @@ module Steep
2999
3111
 
3000
3112
  constr = synthesize_children(node, skips: skips)
3001
3113
  if block_params
3114
+ # @type var node: Parser::AST::Node & Parser::AST::_BlockNode
3002
3115
  block_annotations = source.annotations(block: node, factory: checker.factory, context: nesting)
3003
3116
 
3004
3117
  constr.type_block_without_hint(
@@ -3023,7 +3136,7 @@ module Steep
3023
3136
  constr.add_call(
3024
3137
  TypeInference::MethodCall::NoMethodError.new(
3025
3138
  node: node,
3026
- context: context.method_context,
3139
+ context: context.call_context,
3027
3140
  method_name: method_name,
3028
3141
  receiver_type: receiver_type,
3029
3142
  error: Diagnostic::Ruby::NoMethod.new(node: node, method: method_name, type: interface&.type || receiver_type)
@@ -3070,46 +3183,65 @@ module Steep
3070
3183
  receiver_type = checker.factory.deep_expand_alias(recv_type)
3071
3184
  private = receiver.nil? || receiver.type == :self
3072
3185
 
3073
- type, constr = case receiver_type
3074
- when nil
3075
- raise
3076
-
3077
- when AST::Types::Any
3078
- constr = constr.synthesize_children(node, skips: [receiver])
3079
- constr.add_call(
3080
- TypeInference::MethodCall::Untyped.new(
3081
- node: node,
3082
- context: context.method_context,
3083
- method_name: method_name
3084
- )
3085
- )
3186
+ type, constr =
3187
+ case receiver_type
3188
+ when nil
3189
+ raise
3086
3190
 
3087
- else
3088
- if interface = calculate_interface(receiver_type, private: private)
3089
- constr.type_send_interface(
3090
- node,
3091
- interface: interface,
3092
- receiver: receiver,
3093
- receiver_type: receiver_type,
3094
- method_name: method_name,
3095
- arguments: arguments,
3096
- block_params: block_params,
3097
- block_body: block_body,
3098
- tapp: tapp
3099
- )
3100
- else
3101
- constr = constr.synthesize_children(node, skips: [receiver])
3102
- constr.add_call(
3103
- TypeInference::MethodCall::NoMethodError.new(
3104
- node: node,
3105
- context: context.method_context,
3106
- method_name: method_name,
3107
- receiver_type: receiver_type,
3108
- error: Diagnostic::Ruby::NoMethod.new(node: node, method: method_name, type: receiver_type)
3109
- )
3110
- )
3111
- end
3112
- end
3191
+ when AST::Types::Any
3192
+ case node.type
3193
+ when :block, :numblock
3194
+ # @type var node: Parser::AST::Node & Parser::AST::_BlockNode
3195
+ block_annotations = source.annotations(block: node, factory: checker.factory, context: nesting)
3196
+ block_params or raise
3197
+
3198
+ constr = constr.synthesize_children(node.children[0])
3199
+
3200
+ constr.type_block_without_hint(
3201
+ node: node,
3202
+ block_params: TypeInference::BlockParams.from_node(block_params, annotations: block_annotations),
3203
+ block_annotations: block_annotations,
3204
+ block_body: block_body
3205
+ ) do |error|
3206
+ constr.typing.errors << error
3207
+ end
3208
+ else
3209
+ constr = constr.synthesize_children(node, skips: [receiver])
3210
+ end
3211
+
3212
+ constr.add_call(
3213
+ TypeInference::MethodCall::Untyped.new(
3214
+ node: node,
3215
+ context: context.call_context,
3216
+ method_name: method_name
3217
+ )
3218
+ )
3219
+ else
3220
+ if interface = calculate_interface(receiver_type, private: private)
3221
+ constr.type_send_interface(
3222
+ node,
3223
+ interface: interface,
3224
+ receiver: receiver,
3225
+ receiver_type: receiver_type,
3226
+ method_name: method_name,
3227
+ arguments: arguments,
3228
+ block_params: block_params,
3229
+ block_body: block_body,
3230
+ tapp: tapp
3231
+ )
3232
+ else
3233
+ constr = constr.synthesize_children(node, skips: [receiver])
3234
+ constr.add_call(
3235
+ TypeInference::MethodCall::NoMethodError.new(
3236
+ node: node,
3237
+ context: context.call_context,
3238
+ method_name: method_name,
3239
+ receiver_type: receiver_type,
3240
+ error: Diagnostic::Ruby::NoMethod.new(node: node, method: method_name, type: receiver_type)
3241
+ )
3242
+ )
3243
+ end
3244
+ end
3113
3245
 
3114
3246
  Pair.new(type: type, constr: constr)
3115
3247
  end
@@ -3117,8 +3249,8 @@ module Steep
3117
3249
  def builder_config
3118
3250
  Interface::Builder::Config.new(
3119
3251
  self_type: self_type,
3120
- class_type: module_context!.module_type,
3121
- instance_type: module_context!.instance_type,
3252
+ class_type: module_context.module_type,
3253
+ instance_type: module_context.instance_type,
3122
3254
  variable_bounds: variable_context.upper_bounds
3123
3255
  )
3124
3256
  end
@@ -3173,7 +3305,7 @@ module Steep
3173
3305
  _, constr = add_typing(node, type: type)
3174
3306
  call = TypeInference::MethodCall::Special.new(
3175
3307
  node: node,
3176
- context: constr.context.method_context,
3308
+ context: constr.context.call_context,
3177
3309
  method_name: decl.method_name.method_name,
3178
3310
  receiver_type: receiver_type,
3179
3311
  actual_method_type: method_type.with(type: method_type.type.with(return_type: type)),
@@ -3197,7 +3329,7 @@ module Steep
3197
3329
  _, constr = add_typing(node, type: type)
3198
3330
  call = TypeInference::MethodCall::Special.new(
3199
3331
  node: node,
3200
- context: constr.context.method_context,
3332
+ context: constr.context.call_context,
3201
3333
  method_name: decl.method_name.method_name,
3202
3334
  receiver_type: receiver_type,
3203
3335
  actual_method_type: method_type.with(type: method_type.type.with(return_type: type)),
@@ -3214,7 +3346,7 @@ module Steep
3214
3346
  end
3215
3347
 
3216
3348
  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 }
3349
+ node_range = node.loc.expression.to_range
3218
3350
 
3219
3351
  # @type var fails: Array[[TypeInference::MethodCall::t, TypeConstruction]]
3220
3352
  fails = []
@@ -3327,11 +3459,11 @@ module Steep
3327
3459
  end
3328
3460
  end
3329
3461
 
3330
- def type_check_args(args, constraints, errors)
3462
+ def type_check_args(method_name, args, constraints, errors)
3331
3463
  # @type var constr: TypeConstruction
3332
3464
  constr = self
3333
3465
 
3334
- es = args.each do |arg|
3466
+ forwarded_args, es = args.each do |arg|
3335
3467
  case arg
3336
3468
  when TypeInference::SendArgs::PositionalArgs::NodeParamPair
3337
3469
  _, constr = constr.type_check_argument(
@@ -3404,20 +3536,48 @@ module Steep
3404
3536
 
3405
3537
  when TypeInference::SendArgs::KeywordArgs::MissingKeyword
3406
3538
  # ignore
3539
+
3407
3540
  else
3408
- raise arg.inspect
3541
+ raise (_ = arg).inspect
3409
3542
  end
3410
3543
  end
3411
3544
 
3412
3545
  errors.push(*es)
3413
3546
 
3547
+ if forwarded_args
3548
+ method_name or raise "method_name cannot be nil if `forwarded_args` is given, because proc/block doesn't support `...` arg"
3549
+
3550
+ (params, block = context.method_context&.forward_arg_type) or raise
3551
+
3552
+ checker.with_context(self_type: self_type, instance_type: context.module_context.instance_type, class_type: context.module_context.module_type, constraints: constraints) do
3553
+ result = checker.check_method_params(
3554
+ :"... (argument forwarding)",
3555
+ Subtyping::Relation.new(
3556
+ sub_type: forwarded_args.params,
3557
+ super_type: params
3558
+ )
3559
+ )
3560
+
3561
+ if result.failure?
3562
+ errors.push(
3563
+ Diagnostic::Ruby::IncompatibleArgumentForwarding.new(
3564
+ method_name: method_name,
3565
+ node: forwarded_args.node,
3566
+ params_pair: [params, forwarded_args.params],
3567
+ result: result
3568
+ )
3569
+ )
3570
+ end
3571
+ end
3572
+ end
3573
+
3414
3574
  constr
3415
3575
  end
3416
3576
 
3417
3577
  def try_method_type(node, receiver_type:, method_name:, method_type:, arguments:, block_params:, block_body:, tapp:)
3418
3578
  constr = self
3419
3579
 
3420
- if tapp && type_args = tapp.types?(module_context!.nesting, checker.factory, [])
3580
+ if tapp && type_args = tapp.types?(module_context.nesting, checker.factory, [])
3421
3581
  type_arity = method_type.type_params.size
3422
3582
  type_param_names = method_type.type_params.map(&:name)
3423
3583
 
@@ -3477,7 +3637,7 @@ module Steep
3477
3637
  )
3478
3638
  end
3479
3639
 
3480
- type_params = []
3640
+ type_params = [] #: Array[Interface::TypeParam]
3481
3641
  type_param_names.clear
3482
3642
  else
3483
3643
  # Infer type application
@@ -3499,12 +3659,12 @@ module Steep
3499
3659
  constraints = Subtyping::Constraints.new(unknowns: type_params.map(&:name))
3500
3660
  ccontext = Subtyping::Constraints::Context.new(
3501
3661
  self_type: self_type,
3502
- instance_type: module_context!.instance_type,
3503
- class_type: module_context!.module_type,
3662
+ instance_type: module_context.instance_type,
3663
+ class_type: module_context.module_type,
3504
3664
  variance: variance
3505
3665
  )
3506
3666
 
3507
- upper_bounds = {}
3667
+ upper_bounds = {} #: Hash[Symbol, AST::Types::t]
3508
3668
 
3509
3669
  type_params.each do |param|
3510
3670
  if ub = param.upper_bound
@@ -3514,11 +3674,14 @@ module Steep
3514
3674
  end
3515
3675
 
3516
3676
  checker.push_variable_bounds(upper_bounds) do
3677
+ # @type block: [TypeInference::MethodCall::t, TypeConstruction]
3678
+
3517
3679
  # @type var errors: Array[Diagnostic::Ruby::Base]
3518
3680
  errors = []
3519
3681
 
3520
3682
  args = TypeInference::SendArgs.new(node: node, arguments: arguments, type: method_type)
3521
3683
  constr = constr.type_check_args(
3684
+ method_name,
3522
3685
  args,
3523
3686
  constraints,
3524
3687
  errors
@@ -3526,6 +3689,8 @@ module Steep
3526
3689
 
3527
3690
  if block_params
3528
3691
  # block is given
3692
+ # @type var node: Parser::AST::Node & Parser::AST::_BlockNode
3693
+
3529
3694
  block_annotations = source.annotations(block: node, factory: checker.factory, context: nesting)
3530
3695
  block_params_ = TypeInference::BlockParams.from_node(block_params, annotations: block_annotations)
3531
3696
 
@@ -3596,12 +3761,14 @@ module Steep
3596
3761
  )
3597
3762
  }
3598
3763
 
3764
+ method_type.block or raise
3765
+
3599
3766
  if solved
3600
3767
  # Ready for type check the body of the block
3601
3768
  block_constr = block_constr.update_type_env {|env| env.subst(s) }
3602
3769
  block_constr = block_constr.update_context {|context|
3603
3770
  context.with(
3604
- self_type: method_type.block&.self_type || context.self_type,
3771
+ self_type: method_type.block.self_type || context.self_type,
3605
3772
  type_env: context.type_env.subst(s),
3606
3773
  block_context: context.block_context&.subst(s),
3607
3774
  break_context: context.break_context&.subst(s)
@@ -3708,6 +3875,21 @@ module Steep
3708
3875
  arg = args.block_pass_arg
3709
3876
 
3710
3877
  case
3878
+ when forwarded_args_node = args.forwarded_args_node
3879
+ (_, block = method_context!.forward_arg_type) or raise
3880
+
3881
+ method_block_type = method_type.block&.to_proc_type || AST::Builtin.nil_type
3882
+ forwarded_block_type = block&.to_proc_type || AST::Builtin.nil_type
3883
+
3884
+ if result = constr.no_subtyping?(sub_type: forwarded_block_type, super_type: method_block_type)
3885
+ errors << Diagnostic::Ruby::IncompatibleArgumentForwarding.new(
3886
+ method_name: method_name,
3887
+ node: forwarded_args_node,
3888
+ block_pair: [block, method_type.block],
3889
+ result: result
3890
+ )
3891
+ end
3892
+
3711
3893
  when arg.compatible?
3712
3894
  if arg.node
3713
3895
  # Block pass (&block) is given
@@ -3770,7 +3952,10 @@ module Steep
3770
3952
  )
3771
3953
 
3772
3954
  when arg.unexpected_block?
3773
- # Unexpected block is given
3955
+ # Unexpected block pass node is given
3956
+
3957
+ arg.node or raise
3958
+
3774
3959
  method_type, solved, _ = apply_solution(errors, node: node, method_type: method_type) {
3775
3960
  constraints.solution(checker, variables: method_type.free_variables, context: ccontext)
3776
3961
  }
@@ -3791,7 +3976,7 @@ module Steep
3791
3976
  call = if errors.empty?
3792
3977
  TypeInference::MethodCall::Typed.new(
3793
3978
  node: node,
3794
- context: context.method_context,
3979
+ context: context.call_context,
3795
3980
  receiver_type: receiver_type,
3796
3981
  method_name: method_name,
3797
3982
  actual_method_type: method_type,
@@ -3801,7 +3986,7 @@ module Steep
3801
3986
  else
3802
3987
  TypeInference::MethodCall::Error.new(
3803
3988
  node: node,
3804
- context: context.method_context,
3989
+ context: context.call_context,
3805
3990
  receiver_type: receiver_type,
3806
3991
  method_name: method_name,
3807
3992
  return_type: return_type || method_type.type.return_type,
@@ -3871,7 +4056,7 @@ module Steep
3871
4056
 
3872
4057
  block_type = block_constr.synthesize_block(node: node, block_type_hint: nil, block_body: block_body)
3873
4058
 
3874
- if expected_block_type = block_constr.block_context.body_type
4059
+ if expected_block_type = block_constr.block_context!.body_type
3875
4060
  block_constr.check_relation(sub_type: block_type, super_type: expected_block_type).else do |result|
3876
4061
  Diagnostic::Ruby::BlockBodyTypeMismatch.new(
3877
4062
  node: node,
@@ -3947,8 +4132,7 @@ module Steep
3947
4132
 
3948
4133
  param_types_hash.delete_if {|name, _| SPECIAL_LVAR_NAMES.include?(name) }
3949
4134
 
3950
- param_types = param_types_hash.each.with_object({}) do |pair, hash|
3951
- # @type var hash: Hash[Symbol, [AST::Types::t, AST::Types::t?]]
4135
+ param_types = param_types_hash.each.with_object({}) do |pair, hash| #$ Hash[Symbol, [AST::Types::t, AST::Types::t?]]
3952
4136
  name, type = pair
3953
4137
  hash[name] = [type, nil]
3954
4138
  end
@@ -4034,7 +4218,7 @@ module Steep
4034
4218
 
4035
4219
  def synthesize_block(node:, block_type_hint:, block_body:)
4036
4220
  if block_body
4037
- body_type, _, context = synthesize(block_body, hint: block_context.body_type || block_type_hint)
4221
+ body_type, _, context = synthesize(block_body, hint: block_context&.body_type || block_type_hint)
4038
4222
 
4039
4223
  range = block_body.loc.expression.end_pos..node.loc.end.begin_pos
4040
4224
  typing.add_context(range, context: context)
@@ -4055,7 +4239,7 @@ module Steep
4055
4239
 
4056
4240
  def union_type(*types)
4057
4241
  raise if types.empty?
4058
- AST::Types::Union.build(types: types)
4242
+ AST::Types::Union.build(types: types.compact)
4059
4243
  end
4060
4244
 
4061
4245
  def union_type_unify(*types)
@@ -4104,14 +4288,18 @@ module Steep
4104
4288
  return unless member_decl_count == 1
4105
4289
 
4106
4290
  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
4291
+ if method.implemented_in
4292
+ if method.implemented_in == module_context.instance_definition&.type_name
4293
+ set << name
4294
+ end
4109
4295
  end
4110
4296
  end
4111
4297
  expected_module_method_names = (module_context.module_definition&.methods || {}).each.with_object(Set[]) do |(name, method), set|
4112
4298
  if name != :new
4113
- if method.implemented_in == module_context.module_definition.type_name
4114
- set << name
4299
+ if method.implemented_in
4300
+ if method.implemented_in == module_context.module_definition&.type_name
4301
+ set << name
4302
+ end
4115
4303
  end
4116
4304
  end
4117
4305
  end
@@ -4188,18 +4376,20 @@ module Steep
4188
4376
  end
4189
4377
 
4190
4378
  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
4379
+ # @type var nodes: Array[Parser::AST::Node]
4380
+ nodes =
4381
+ case node.type
4382
+ when :class, :module
4383
+ node.children.last&.yield_self {|child|
4384
+ if child.type == :begin
4385
+ child.children
4386
+ else
4387
+ [child]
4388
+ end
4389
+ } || []
4390
+ else
4391
+ return false
4392
+ end
4203
4393
 
4204
4394
  !nodes.empty? && nodes.all? {|child| child.type == :class || child.type == :module}
4205
4395
  end
@@ -4228,18 +4418,19 @@ module Steep
4228
4418
  end
4229
4419
 
4230
4420
  def select_flatten_types(type, &block)
4231
- types = flatten_union(deep_expand_alias(type))
4421
+ types = flatten_union(deep_expand_alias(type) || type)
4232
4422
  types.select(&block)
4233
4423
  end
4234
4424
 
4235
4425
  def partition_flatten_types(type, &block)
4236
- types = flatten_union(deep_expand_alias(type))
4426
+ types = flatten_union(deep_expand_alias(type) || type)
4237
4427
  types.partition(&block)
4238
4428
  end
4239
4429
 
4240
4430
  def flatten_array_elements(type)
4241
- flatten_union(deep_expand_alias(type)).flat_map do |type|
4431
+ flatten_union(deep_expand_alias(type) || type).flat_map do |type|
4242
4432
  if AST::Builtin::Array.instance_type?(type)
4433
+ # @type var type: AST::Types::Name::Instance
4243
4434
  type.args
4244
4435
  else
4245
4436
  [type]
@@ -4248,7 +4439,12 @@ module Steep
4248
4439
  end
4249
4440
 
4250
4441
  def expand_alias(type, &block)
4251
- checker.factory.expand_alias(type, &block)
4442
+ typ = checker.factory.expand_alias(type)
4443
+ if block
4444
+ yield(typ)
4445
+ else
4446
+ typ
4447
+ end
4252
4448
  end
4253
4449
 
4254
4450
  def test_literal_type(literal, hint)
@@ -4296,9 +4492,8 @@ module Steep
4296
4492
  def try_tuple_type(array_node, hint)
4297
4493
  raise unless array_node.type == :array
4298
4494
 
4299
- constr = self
4300
- # @type var element_types: Array[AST::Types::t]
4301
- element_types = []
4495
+ constr = self #: TypeConstruction
4496
+ element_types = [] #: Array[AST::Types::t]
4302
4497
 
4303
4498
  array_node.children.each_with_index do |child, index|
4304
4499
  return if child.type == :splat
@@ -4380,11 +4575,14 @@ module Steep
4380
4575
  instance_type: module_context.instance_type,
4381
4576
  class_type: module_context.module_type
4382
4577
  )
4383
- subst = constraints.solution(
4384
- checker,
4385
- variables: type.free_variables + [var.name],
4386
- context: context
4387
- )
4578
+
4579
+ variables = (type.free_variables + [var.name]).filter_map do |name|
4580
+ case name
4581
+ when Symbol
4582
+ name
4583
+ end
4584
+ end
4585
+ subst = constraints.solution(checker, variables: variables, context: context)
4388
4586
 
4389
4587
  type.subst(subst)
4390
4588
  end
@@ -4393,8 +4591,8 @@ module Steep
4393
4591
  def try_array_type(node, hint)
4394
4592
  element_hint = hint ? hint.args[0] : nil
4395
4593
 
4396
- constr = self
4397
- element_types = []
4594
+ constr = self #: TypeConstruction
4595
+ element_types = [] #: Array[AST::Types::t]
4398
4596
 
4399
4597
  each_child_node(node) do |child|
4400
4598
  case child.type
@@ -4425,24 +4623,24 @@ module Steep
4425
4623
  def type_hash_record(hash_node, record_type)
4426
4624
  raise unless hash_node.type == :hash || hash_node.type == :kwargs
4427
4625
 
4428
- constr = self
4626
+ constr = self #: TypeConstruction
4429
4627
 
4430
4628
  if record_type
4431
4629
  hints = record_type.elements.dup
4432
4630
  else
4433
- hints = {}
4631
+ hints = {} #: Hash[AST::Types::Record::key, AST::Types::t]
4434
4632
  end
4435
4633
 
4436
- elems = {}
4634
+ elems = {} #: Hash[AST::Types::Record::key, AST::Types::t]
4437
4635
 
4438
4636
  each_child_node(hash_node) do |child|
4439
4637
  if child.type == :pair
4440
4638
  case child.children[0].type
4441
4639
  when :sym, :str, :int
4442
- key_node = child.children[0]
4443
- value_node = child.children[1]
4640
+ key_node = child.children[0] #: Parser::AST::Node
4641
+ value_node = child.children[1] #: Parser::AST::Node
4444
4642
 
4445
- key = key_node.children[0]
4643
+ key = key_node.children[0] #: String | Symbol | Integer
4446
4644
 
4447
4645
  _, constr = constr.synthesize(key_node, hint: AST::Types::Literal.new(value: key))
4448
4646
 
@@ -4471,14 +4669,10 @@ module Steep
4471
4669
  constr.add_typing(hash_node, type: type)
4472
4670
  end
4473
4671
 
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
4672
  def type_hash(hash_node, hint:)
4481
- hint = deep_expand_alias(hint)
4673
+ if hint
4674
+ hint = deep_expand_alias(hint)
4675
+ end
4482
4676
  range = hash_node.loc.expression.yield_self {|l| l.begin_pos..l.end_pos }
4483
4677
 
4484
4678
  case hint
@@ -4499,10 +4693,11 @@ module Steep
4499
4693
  end
4500
4694
  end
4501
4695
 
4502
- key_types = []
4503
- value_types = []
4696
+ key_types = [] #: Array[AST::Types::t]
4697
+ value_types = [] #: Array[AST::Types::t]
4504
4698
 
4505
- if AST::Builtin::Hash.instance_type?(hint)
4699
+ if hint && AST::Builtin::Hash.instance_type?(hint)
4700
+ # @type var hint: AST::Types::Name::Instance
4506
4701
  key_hint, value_hint = hint.args
4507
4702
  end
4508
4703
 
@@ -4511,7 +4706,7 @@ module Steep
4511
4706
  value_hint || AST::Builtin.any_type
4512
4707
  )
4513
4708
 
4514
- constr = self
4709
+ constr = self #: TypeConstruction
4515
4710
 
4516
4711
  if hash_node.children.empty?
4517
4712
  key_types << key_hint if key_hint
@@ -4528,14 +4723,13 @@ module Steep
4528
4723
  value_types << value_type
4529
4724
  when :kwsplat
4530
4725
  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]
4726
+ constr.synthesize(elem_, hint: hint_hash).tap do |(type, _)|
4727
+ if AST::Builtin::Hash.instance_type?(type)
4728
+ # @type var type: AST::Types::Name::Instance
4729
+ key_types << type.args[0]
4730
+ value_types << type.args[1]
4731
+ end
4536
4732
  end
4537
-
4538
- pair
4539
4733
  end
4540
4734
  else
4541
4735
  raise
@@ -4573,7 +4767,7 @@ module Steep
4573
4767
 
4574
4768
  def save_typing
4575
4769
  typing.save!
4576
- with_new_typing(typing.parent)
4770
+ with_new_typing(typing.parent || raise)
4577
4771
  end
4578
4772
 
4579
4773
  def extract_outermost_call(node, var_name)